2 // ScreenshotEditorViewController.swift
5 // Created by Hori,Masaki on 2016/12/29.
6 // Copyright © 2016年 Hori,Masaki. All rights reserved.
11 private struct EditedImage {
13 var editedImage: NSImage
16 init(image: NSImage, url: URL) {
23 final class TrimRectInformation: NSObject {
25 @objc private(set) var name: String
26 private(set) var rect: NSRect
28 fileprivate init(name: String, rect: NSRect) {
35 final class ScreenshotEditorViewController: BridgeViewController {
37 @objc let trimInfo = [
38 TrimRectInformation(name: "Status", rect: NSRect(x: 328, y: 13, width: 470, height: 365)),
39 TrimRectInformation(name: "List", rect: NSRect(x: 362, y: 15, width: 438, height: 368)),
40 TrimRectInformation(name: "AirplaneBase", rect: NSRect(x: 575, y: 13, width: 225, height: 358))
43 override init(nibName: NSNib.Name?, bundle: Bundle?) {
45 currentTrimInfo = trimInfo[0]
47 super.init(nibName: ScreenshotEditorViewController.nibName, bundle: nil)
50 required init?(coder: NSCoder) {
52 fatalError("init(coder:) has not been implemented")
56 @IBOutlet weak var tiledImageView: TiledImageView!
57 @IBOutlet weak var doneButton: NSButton!
59 @objc var columnCount: Int {
61 get { return tiledImageView.columnCount }
63 tiledImageView.columnCount = newValue
64 UserDefaults.standard[.screenshotEditorColumnCount] = newValue
70 return tiledImageView.image
73 @objc dynamic var currentTrimInfoIndex: Int {
75 get { return realiesCurrentTrimInforIndex }
77 guard case 0..<trimInfo.count = newValue else { return }
79 realiesCurrentTrimInforIndex = newValue
80 currentTrimInfo = trimInfo[newValue]
84 private var editedImage: NSImage?
85 private var currentSelection: [ScreenshotInformation] = []
86 private var editedImages: [EditedImage] = []
87 private var realiesCurrentTrimInforIndex = UserDefaults.standard[.scrennshotEditorType]
88 private var currentTrimInfo: TrimRectInformation {
95 if $0.name != currentTrimInfo.name { return false }
96 return $0.rect == currentTrimInfo.rect
98 .map { UserDefaults.standard[.scrennshotEditorType] = $0 }
102 private var selectionObservation: NSKeyValueObservation?
104 var completeHandler: ((NSImage?) -> Void)?
106 override func viewDidLoad() {
110 selectionObservation = arrayController.observe(\NSArrayController.selectionIndexes) { [weak self] (_, _) in
112 self?.updateSelections()
115 currentTrimInfoIndex = UserDefaults.standard[.scrennshotEditorType]
119 override func viewWillAppear() {
121 doneButton.action = #selector(ScreenshotEditorViewController.done(_:))
124 private func updateSelections() {
126 guard let selection = arrayController.selectedObjects as? [ScreenshotInformation] else { return }
128 if selection == currentSelection { return }
130 let removed: [ScreenshotInformation] = currentSelection.flatMap {
132 selection.contains($0) ? nil : $0
135 let appended: [ScreenshotInformation] = selection.flatMap {
137 currentSelection.contains($0) ? nil : $0
142 removeEditedImage(url: $0.url)
147 appendEditedImage(url: $0.url)
150 currentSelection = selection
154 private func removeEditedImage(url: URL) {
157 .index { $0.url == url }
158 .map { editedImages.remove(at: $0) }
161 private func appendEditedImage(url: URL) {
163 NSImage(contentsOf: url)
164 .flatMap { EditedImage(image: $0, url: url) }
165 .map { editedImages.append($0) }
168 private func makeEditedImage() {
170 guard !editedImages.isEmpty else {
172 tiledImageView.images = []
176 DispatchQueue(label: "makeTrimedImage queue").async {
178 let images: [NSImage] = self.editedImages.flatMap {
180 guard let originalImage = NSImage(contentsOf: $0.url) else { return nil }
182 let trimedImage = NSImage(size: self.currentTrimInfo.rect.size)
184 trimedImage.lockFocus()
185 originalImage.draw(at: .zero,
186 from: self.currentTrimInfo.rect,
189 trimedImage.unlockFocus()
194 DispatchQueue.main.async {
196 self.tiledImageView.images = images
201 @IBAction func done(_ sender: AnyObject?) {
203 completeHandler?(self.image)
207 extension ScreenshotEditorViewController: NibLoadable {}