2 // ScreenshotEditorViewController.swift
5 // Created by Hori,Masaki on 2016/12/29.
6 // Copyright © 2016年 Hori,Masaki. All rights reserved.
11 private struct URLImage {
16 init(image: NSImage, url: URL) {
24 final class TrimRectInformation: NSObject {
26 @objc private(set) var name: String
27 private(set) var rect: NSRect
29 fileprivate init(name: String, rect: NSRect) {
36 final class ScreenshotEditorViewController: BridgeViewController {
38 @objc let trimInfo = [
39 TrimRectInformation(name: "Status", rect: NSRect(x: 328, y: 13, width: 470, height: 365)),
40 TrimRectInformation(name: "List", rect: NSRect(x: 362, y: 15, width: 438, height: 368)),
41 TrimRectInformation(name: "AirplaneBase", rect: NSRect(x: 575, y: 13, width: 225, height: 358))
44 override init(nibName: NSNib.Name?, bundle: Bundle?) {
46 currentTrimInfo = trimInfo[0]
48 super.init(nibName: ScreenshotEditorViewController.nibName, bundle: nil)
51 required init?(coder: NSCoder) {
53 fatalError("init(coder:) has not been implemented")
57 @IBOutlet private weak var tiledImageView: TiledImageView!
58 @IBOutlet private weak var doneButton: NSButton!
60 @objc var columnCount: Int {
62 get { return tiledImageView.columnCount }
65 tiledImageView.columnCount = newValue
66 UserDefaults.standard[.screenshotEditorColumnCount] = newValue
72 return tiledImageView.image
75 @objc dynamic var currentTrimInfoIndex: Int {
77 get { return realiesCurrentTrimInforIndex }
80 guard case 0..<trimInfo.count = newValue else {
85 realiesCurrentTrimInforIndex = newValue
86 currentTrimInfo = trimInfo[newValue]
90 private var editedImage: NSImage?
91 private var currentSelection: [ScreenshotInformation] = []
92 private var originalImages: [URLImage] = []
93 private var realiesCurrentTrimInforIndex = UserDefaults.standard[.scrennshotEditorType]
94 private var currentTrimInfo: TrimRectInformation {
102 if $0.name != currentTrimInfo.name {
107 return $0.rect == currentTrimInfo.rect
109 .map { UserDefaults.standard[.scrennshotEditorType] = $0 }
113 private var selectionObservation: NSKeyValueObservation?
115 var completeHandler: ((NSImage?) -> Void)?
117 override func viewDidLoad() {
121 selectionObservation = arrayController.observe(\NSArrayController.selectionIndexes) { [weak self] (_, _) in
123 self?.updateSelections()
126 currentTrimInfoIndex = UserDefaults.standard[.scrennshotEditorType]
130 override func viewWillAppear() {
132 doneButton.action = #selector(ScreenshotEditorViewController.done(_:))
135 private func updateSelections() {
137 guard let selection = arrayController.selectedObjects as? [ScreenshotInformation] else {
142 if selection == currentSelection {
147 let removed: [ScreenshotInformation] = currentSelection.compactMap {
149 selection.contains($0) ? nil : $0
152 let appended: [ScreenshotInformation] = selection.compactMap {
154 currentSelection.contains($0) ? nil : $0
159 removeOriginalImage(url: $0.url)
164 appendOriginalImage(url: $0.url)
167 currentSelection = selection
171 private func removeOriginalImage(url: URL) {
174 .index { $0.url == url }
175 .map { originalImages.remove(at: $0) }
178 private func appendOriginalImage(url: URL) {
180 NSImage(contentsOf: url)
181 .flatMap { URLImage(image: $0, url: url) }
182 .map { originalImages.append($0) }
185 private func makeTrimedImage() {
187 guard !originalImages.isEmpty else {
189 tiledImageView.images = []
194 DispatchQueue(label: "makeTrimedImage queue").async {
196 let images: [NSImage] = self.originalImages.compactMap {
198 let trimedImage = NSImage(size: self.currentTrimInfo.rect.size)
200 trimedImage.lockFocus()
201 $0.image.draw(at: .zero,
202 from: self.currentTrimInfo.rect,
205 trimedImage.unlockFocus()
210 DispatchQueue.main.async {
212 self.tiledImageView.images = images
217 @IBAction func done(_ sender: AnyObject?) {
219 completeHandler?(self.image)
223 extension ScreenshotEditorViewController: NibLoadable {}