Skip to content

Commit

Permalink
Add 'Save Image As...' menu item
Browse files Browse the repository at this point in the history
  • Loading branch information
NSAntoine committed Aug 11, 2024
1 parent 66946db commit 6d4d987
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 11 deletions.
8 changes: 4 additions & 4 deletions Samra.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1.3;
CURRENT_PROJECT_VERSION = 1.4;
DEVELOPMENT_TEAM = L9735M962H;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Samra/Info.plist;
Expand All @@ -521,7 +521,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 10.15.1;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.serena.Samra;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -545,7 +545,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1.3;
CURRENT_PROJECT_VERSION = 1.4;
DEVELOPMENT_TEAM = L9735M962H;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Samra/Info.plist;
Expand All @@ -556,7 +556,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MACOSX_DEPLOYMENT_TARGET = 10.15.1;
MARKETING_VERSION = 1;
PRODUCT_BUNDLE_IDENTIFIER = com.serena.Samra;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
14 changes: 8 additions & 6 deletions Samra/Backend/DetailItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,13 @@ struct DetailItemSection: Hashable {
static func from(rendition: Rendition) -> [DetailItemSection] {
let cuiRend = rendition.cuiRend
let namedLookup = rendition.namedLookup
let diskSize = cuiRend.srcData.count.formatted(.byteCount(style:.memory,
spellsOutZero: true,
includesActualByteCount: true))

let formatter = ByteCountFormatter()
formatter.countStyle = .memory
formatter.includesActualByteCount = true

let diskSize = formatter.string(fromByteCount: Int64(cuiRend.srcData.count))

let sizeOnDisk = DetailItem(primaryText: "Size On Disk", secondaryText: diskSize)
var items: [DetailItemSection] = []

Expand All @@ -76,9 +80,7 @@ struct DetailItemSection: Hashable {
]))
var details : [DetailItem] = []
if let data = cuiRend.data() {
let size = data.count.formatted(.byteCount(style:.memory,
spellsOutZero: true,
includesActualByteCount: true))
let size = formatter.string(fromByteCount: Int64(data.count))
details.append(DetailItem(primaryText: "Data Length", secondaryText:size))

}
Expand Down
45 changes: 44 additions & 1 deletion Samra/UI/Rendition/RenditionListViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,32 @@ extension RenditionListViewController {
}

extension RenditionListViewController: MenuProvider {

static private func _promptToSaveImage(cgImage: CGImage, formatType: NSBitmapImageRep.FileType, defaultFileName: String, displayFormat: String) {
let savePanel = NSSavePanel()
savePanel.nameFieldStringValue = defaultFileName
guard savePanel.runModal() == .OK, let urlToSaveTo = savePanel.url else { return }

guard let data = NSBitmapImageRep(cgImage: cgImage).representation(using: formatType, properties: [.compressionFactor: 1]) else {
NSAlert(title: "Failed to save Image as \(displayFormat)", message: "NSBitmapImageRep representation returned nil.").runModal()
return
}

do {
try data.write(to: urlToSaveTo)
} catch {
NSAlert(title: "Failed to save Image as \(displayFormat)", message: error.localizedDescription).runModal()
}
}

func collectionView(_ collectionView: NSCollectionView, menuForItemAt indexPath: IndexPath) -> NSMenu? {
guard let item = dataSource.itemIdentifier(for: indexPath) else { return nil }
let copyName = ClosureMenuItem(title: "Copy Name") {
NSPasteboard.general.declareTypes([.string], owner: nil)
NSPasteboard.general.setString(item.name, forType: .string)
}

var items = [copyName]
var items: [NSMenuItem] = [copyName]

switch item.representation {
case .image(let cgImage):
Expand All @@ -224,6 +242,31 @@ extension RenditionListViewController: MenuProvider {
NSPasteboard.general.setData(NSImage(cgImage: cgImage, size: cgImage.size).tiffRepresentation, forType: .tiff)
}
items.append(copyImage)

var saveImageAsItems = [
ClosureMenuItem(title: "PNG") {
Self._promptToSaveImage(cgImage: cgImage, formatType: .png, defaultFileName: "image.png", displayFormat: "PNG")
},

ClosureMenuItem(title: "JPEG") {
Self._promptToSaveImage(cgImage: cgImage, formatType: .jpeg, defaultFileName: "image.jpeg", displayFormat: "JPEG")
}
]

if item.type == .svg, let svgDoc = item.cuiRend.svgDocument() {
let asSVG = ClosureMenuItem(title: "SVG") {
let savePanel = NSSavePanel()
savePanel.nameFieldStringValue = "image.svg"
guard savePanel.runModal() == .OK, let urlToSaveTo = savePanel.url else { return }
CGSVGDocumentWriteToURL(svgDoc, urlToSaveTo as CFURL, nil)
}

saveImageAsItems.insert(asSVG, at: 0)
}

let saveImageAs = NSMenuItem(submenuTitle: "Save Image As...", items: saveImageAsItems)
items.insert(saveImageAs, at: 0)
items.insert(.separator(), at: 1)
default:
break
}
Expand Down

0 comments on commit 6d4d987

Please sign in to comment.