OSDN Git Service

Equatableを自動実装させるようにした
[kcd/KCD.git] / KCD / ScreenshotEditorViewController.swift
index dc3f356..52600c9 100644 (file)
 
 import Cocoa
 
-fileprivate struct EditedImage {
-    var editedImage: NSImage
+private struct URLImage {
+    
+    var image: NSImage
     var url: URL
     
     init(image: NSImage, url: URL) {
-        editedImage = image
+        
+        self.image = image
         self.url = url
     }
 }
 
-class TrimRectInformation: NSObject {
-    fileprivate(set) var name: String
-    fileprivate(set) var rect: NSRect
+/// 切り取りサイズ、位置と名前
+final class TrimRectInformation: NSObject {
+    
+    @objc private(set) var name: String
+    private(set) var rect: NSRect
     
     fileprivate init(name: String, rect: NSRect) {
+        
         self.name = name
         self.rect = rect
     }
 }
 
-fileprivate extension Selector {
-    static let done = #selector(ScreenshotEditorViewController.done(_:))
-    static let changeToDetail = #selector(ScreenshotListWindowController.changeToDetail(_:))
-    static let registerImage = #selector(ScreenshotListViewController.registerImage(_:))
-}
-
-class ScreenshotEditorViewController: BridgeViewController {
-    let trimInfo: [TrimRectInformation]
-    
-    override init?(nibName: String?, bundle: Bundle?) {
-        trimInfo = [
-            TrimRectInformation(name: "Status", rect: NSMakeRect(328, 13, 470, 365)),
-            TrimRectInformation(name: "List", rect: NSMakeRect(362, 15, 438, 368)),
-            TrimRectInformation(name: "AirplaneBase", rect: NSMakeRect(575, 13, 225, 358))
-        ]
+final class ScreenshotEditorViewController: BridgeViewController {
+    
+    @objc let trimInfo = [
+        TrimRectInformation(name: "Status", rect: NSRect(x: 328, y: 13, width: 470, height: 365)),
+        TrimRectInformation(name: "List", rect: NSRect(x: 362, y: 15, width: 438, height: 368)),
+        TrimRectInformation(name: "AirplaneBase", rect: NSRect(x: 575, y: 13, width: 225, height: 358))
+    ]
+    
+    override init(nibName: NSNib.Name?, bundle: Bundle?) {
+        
         currentTrimInfo = trimInfo[0]
-        super.init(nibName: "ScreenshotEditorViewController", bundle: nil)
+        
+        super.init(nibName: ScreenshotEditorViewController.nibName, bundle: nil)
     }
+    
     required init?(coder: NSCoder) {
+        
         fatalError("init(coder:) has not been implemented")
     }
-    deinit {
-        arrayController.removeObserver(self, forKeyPath: NSSelectionIndexesBinding)
-    }
     
-    @IBOutlet weak var tiledImageView: TiledImageView!
-    @IBOutlet weak var doneButton: NSButton!
     
-    var columnCount: Int {
-        get {
-            return tiledImageView.columnCount
-        }
+    @IBOutlet private weak var tiledImageView: TiledImageView!
+    @IBOutlet private weak var doneButton: NSButton!
+    
+    @objc var columnCount: Int {
+        
+        get { return tiledImageView.columnCount }
         set {
+            
             tiledImageView.columnCount = newValue
-            UserDefaults.standard.screenshotEditorColumnCount = newValue
+            UserDefaults.standard[.screenshotEditorColumnCount] = newValue
         }
     }
+    
     var image: NSImage? {
+        
         return tiledImageView.image
     }
-    dynamic var currentTrimInfoIndex: Int {
+    
+    @objc dynamic var currentTrimInfoIndex: Int {
+        
         get { return realiesCurrentTrimInforIndex }
         set {
-            guard 0..<trimInfo.count ~= newValue
-                else { return }
+            
+            guard case 0..<trimInfo.count = newValue else {
+                
+                return
+            }
+            
             realiesCurrentTrimInforIndex = newValue
             currentTrimInfo = trimInfo[newValue]
         }
     }
+    
     private var editedImage: NSImage?
     private var currentSelection: [ScreenshotInformation] = []
-    private var editedImages: [EditedImage] = []
-    private var realiesCurrentTrimInforIndex = UserDefaults.standard.scrennshotEditorType
+    private var originalImages: [URLImage] = []
+    private var realiesCurrentTrimInforIndex = UserDefaults.standard[.scrennshotEditorType]
     private var currentTrimInfo: TrimRectInformation {
+        
         didSet {
-            makeEditedImage()
+            
+            makeTrimedImage()
             trimInfo
-                .index(where: {
-                    if $0.name != currentTrimInfo.name { return false }
+                .index {
+                    
+                    if $0.name != currentTrimInfo.name {
+                        
+                        return false
+                    }
+                    
                     return $0.rect == currentTrimInfo.rect
-                })
-                .map { UserDefaults.standard.scrennshotEditorType = $0 }
+                }
+                .map { UserDefaults.standard[.scrennshotEditorType] = $0 }
         }
     }
     
+    private var selectionObservation: NSKeyValueObservation?
+    
+    var completeHandler: ((NSImage?) -> Void)?
+    
     override func viewDidLoad() {
+        
         super.viewDidLoad()
         
-        arrayController.addObserver(self, forKeyPath: NSSelectionIndexesBinding, context: nil)
-        currentTrimInfoIndex = UserDefaults.standard.scrennshotEditorType
+        selectionObservation = arrayController.observe(\NSArrayController.selectionIndexes) { [weak self] (_, _) in
+            
+            self?.updateSelections()
+        }
+        
+        currentTrimInfoIndex = UserDefaults.standard[.scrennshotEditorType]
         updateSelections()
     }
+    
     override func viewWillAppear() {
-        doneButton.action = .done
+        
+        doneButton.action = #selector(ScreenshotEditorViewController.done(_:))
     }
     
-    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
-        if keyPath == NSSelectionIndexesBinding {
-            updateSelections()
+    private func updateSelections() {
+        
+        guard let selection = arrayController.selectedObjects as? [ScreenshotInformation] else {
+            
             return
         }
-        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
-    }
-    
-    private func updateSelections() {
-        guard let selection = arrayController.selectedObjects as? [ScreenshotInformation] else { return }
-        if selection == currentSelection { return }
-        let removed: [ScreenshotInformation] = currentSelection.flatMap {
-            if selection.contains($0) { return nil }
-            return $0
+        
+        if selection == currentSelection {
+            
+            return
+        }
+        
+        let removed: [ScreenshotInformation] = currentSelection.compactMap {
+            
+            selection.contains($0) ? nil : $0
         }
-        let appended: [ScreenshotInformation] = selection.flatMap {
-            if currentSelection.contains($0) { return nil }
-            return $0
+        
+        let appended: [ScreenshotInformation] = selection.compactMap {
+            
+            currentSelection.contains($0) ? nil : $0
         }
+        
         removed.forEach {
-            removeEditedImage(url: $0.url)
+            
+            removeOriginalImage(url: $0.url)
         }
+        
         appended.forEach {
-            appendEditedImage(url: $0.url)
+            
+            appendOriginalImage(url: $0.url)
         }
         
         currentSelection = selection
-        makeEditedImage()
+        makeTrimedImage()
     }
     
-    private func removeEditedImage(url: URL) {
-        let _ = editedImages
-            .index(where: { $0.url == url })
-            .map { editedImages.remove(at: $0) }
+    private func removeOriginalImage(url: URL) {
+        
+        _ = originalImages
+            .index { $0.url == url }
+            .map { originalImages.remove(at: $0) }
     }
     
-    private func appendEditedImage(url: URL) {
+    private func appendOriginalImage(url: URL) {
+        
         NSImage(contentsOf: url)
-            .flatMap { EditedImage(image: $0, url: url) }
-            .map { editedImages.append($0) }
+            .flatMap { URLImage(image: $0, url: url) }
+            .map { originalImages.append($0) }
     }
     
-    private func makeEditedImage() {
-        guard !editedImages.isEmpty else {
+    private func makeTrimedImage() {
+        
+        guard !originalImages.isEmpty else {
+            
             tiledImageView.images = []
+            
             return
         }
         
-        DispatchQueue(label: "makeTrimedImage queue")
-            .async {
-                let images: [NSImage] = self.editedImages.flatMap {
-                    guard let originalImage = NSImage(contentsOf: $0.url) else { return nil }
-                    let trimedImage = NSImage(size: self.currentTrimInfo.rect.size)
-                    trimedImage.lockFocus()
-                    originalImage.draw(at: .zero, from: self.currentTrimInfo.rect, operation: NSCompositeCopy, fraction: 1.0)
-                    trimedImage.unlockFocus()
-                    
-                    return trimedImage
-                }
+        DispatchQueue(label: "makeTrimedImage queue").async {
+            
+            let images: [NSImage] = self.originalImages.compactMap {
                 
-                DispatchQueue.main.async {
-                    self.tiledImageView.images = images
-                }
+                let trimedImage = NSImage(size: self.currentTrimInfo.rect.size)
+                
+                trimedImage.lockFocus()
+                $0.image.draw(at: .zero,
+                                   from: self.currentTrimInfo.rect,
+                                   operation: .copy,
+                                   fraction: 1.0)
+                trimedImage.unlockFocus()
+                
+                return trimedImage
+            }
+            
+            DispatchQueue.main.async {
+                
+                self.tiledImageView.images = images
+            }
         }
     }
     
-    // TODO: 外部から End Handlerを登録できるようにして依存をなくす
     @IBAction func done(_ sender: AnyObject?) {
-        NSApplication.shared().sendAction(.registerImage, to: nil, from: self)
-        NSApplication.shared().sendAction(.changeToDetail, to: nil, from: sender)
+        
+        completeHandler?(self.image)
     }
 }
+
+extension ScreenshotEditorViewController: NibLoadable {}