OSDN Git Service

shared instanceを持つようにした
[kcd/KCD.git] / KCD / ExternalBrowserWindowController.swift
index 04d16a1..a8701a8 100644 (file)
 import Cocoa
 import WebKit
 
-fileprivate extension Selector {
-    static let addBookmark = #selector(ExternalBrowserWindowController.addBookmark(_:))
-    static let showBookmark = #selector(ExternalBrowserWindowController.showBookmark(_:))
-    static let selectBookmark = #selector(ExternalBrowserWindowController.selectBookmark(_:))
-    static let reloadContent = #selector(ExternalBrowserWindowController.reloadContent(_:))
-    static let updateContentVisibleRect = #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:))
-}
-
-class ExternalBrowserWindowController: NSWindowController {
-    let managedObjectContext = BookmarkManager.shared().manageObjectContext
-    
-    deinit {
-        webView.removeObserver(self, forKeyPath: "canGoBack")
-        webView.removeObserver(self, forKeyPath: "canGoForward")
-    }
+final class ExternalBrowserWindowController: NSWindowController {
+        
+    @IBOutlet private var webView: WebView!
+    @IBOutlet private var goSegment: NSSegmentedControl!
+    @IBOutlet private var bookmarkListView: NSView!
     
-    @IBOutlet var webView: WebView!
-    @IBOutlet var goSegment: NSSegmentedControl!
-    @IBOutlet var bookmarkListView: NSView!
+    private var canGoBackObservation: NSKeyValueObservation?
+    private var canGoForwardObservation: NSKeyValueObservation?
     
-    override var windowNibName: String! {
-        return "ExternalBrowserWindowController"
+    override var windowNibName: NSNib.Name {
+        
+        return .nibName(instanceOf: self)
     }
-    dynamic var canResize: Bool = true {
+    
+    @objc dynamic var canResize: Bool = true {
+        
         willSet {
-            guard let window = window else { return }
-            if canResize == newValue { return }
-            var style = window.styleMask.rawValue
+            
+            if canResize == newValue {
+                
+                return
+            }
+            
             if newValue {
-                style |= NSResizableWindowMask.rawValue
+                
+                window?.styleMask.insert(.resizable)
+                
             } else {
-                style &= ~NSResizableWindowMask.rawValue
+                
+                window?.styleMask.remove(.resizable)
             }
-            window.styleMask = NSWindowStyleMask(rawValue: style)
         }
     }
-    dynamic var canScroll: Bool = true {
+    
+    @objc dynamic var canScroll: Bool = true {
+        
         willSet {
-            guard let webView = webView else { return }
-            if canScroll == newValue { return }
-            if newValue {
-                webView.mainFrame.frameView.allowsScrolling = true
-            } else {
-                webView.mainFrame.frameView.allowsScrolling = false
+            
+            if canScroll == newValue {
+                
+                return
             }
+            
+            webView?.mainFrame.frameView.allowsScrolling = newValue
         }
     }
-    dynamic var canMovePage: Bool = true
+    @objc dynamic var canMovePage: Bool = true
     
     var urlString: String? {
+        
         return webView.mainFrameURL
     }
+    
     var windowContentSize: NSSize {
+        
         get {
-            guard let window = window else { return .zero }
+            
+            guard let window = window else {
+                
+                return .zero
+            }
+            
             return window.contentRect(forFrameRect: window.frame).size
         }
         set {
-            guard let window = window else { return }
+            
+            guard let window = window else {
+                
+                return
+            }
+            
             var contentRect: NSRect = .zero
             contentRect.size = newValue
             var newFrame = window.frameRect(forContentRect: contentRect)
             let frame = window.frame
-            newFrame.origin.x = NSMinX(frame)
-            newFrame.origin.y = NSMaxY(frame) - NSHeight(newFrame)
+            newFrame.origin.x = frame.minX
+            newFrame.origin.y = frame.maxY - newFrame.height
             window.setFrame(newFrame, display: true)
         }
     }
+    
     var contentVisibleRect: NSRect {
-        get {
-            return webView.mainFrame.frameView.documentView.visibleRect
-        }
-        set {
-            webView.mainFrame.frameView.documentView.scrollToVisible(newValue)
-        }
+        
+        get { return webView.mainFrame.frameView.documentView.visibleRect }
+        set { webView.mainFrame.frameView.documentView.scrollToVisible(newValue) }
     }
     
-    fileprivate var bookmarkShowing: Bool = false
-    fileprivate var waitingBookmarkItem: Bookmark?
+    private var bookmarkShowing: Bool = false
+    private var waitingBookmarkItem: Bookmark?
     
-    private lazy var bookmarkListViwController: BookmarkListViewController? = {
-        [weak self] in
-        guard let `self` = self else { return nil }
+    private lazy var bookmarkListViwController: BookmarkListViewController? = { [weak self] in
+        
+        guard let `self` = self else {
+            
+            return nil
+        }
+        
         let controller = BookmarkListViewController()
         self.bookmarkListView = controller.view
         controller.delegate = self
@@ -106,57 +120,51 @@ class ExternalBrowserWindowController: NSWindowController {
     }()
     
     override func windowDidLoad() {
+        
         super.windowDidLoad()
         
-        webView.addObserver(self, forKeyPath: "canGoBack", context: nil)
-        webView.addObserver(self, forKeyPath: "canGoForward", context: nil)
-        webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
-        webView.frameLoadDelegate = self
-    }
-    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
-        if keyPath == "canGoBack" {
-            goSegment.setEnabled(webView.canGoBack, forSegment: 0)
-            return
-        }
-        if keyPath == "canGoForward" {
-            goSegment.setEnabled(webView.canGoForward, forSegment: 1)
-            return
+        canGoBackObservation = webView.observe(\WebView.canGoBack) { [weak self] _, _ in
+            
+            guard let `self` = self else {
+                
+                return
+            }
+            
+            self.goSegment.setEnabled(self.webView.canGoBack, forSegment: 0)
         }
-        
-        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
-    }
-    override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
-        guard let action = menuItem.action else { return false }
-        switch action {
-        case Selector.addBookmark:
-            return webView.mainFrameURL != nil
-        case Selector.showBookmark:
-            if showsBookmarkList() {
-                menuItem.title = NSLocalizedString("Hide Bookmark", comment: "Menu item title, Hide Bookmark")
-            } else {
-                menuItem.title = NSLocalizedString("Show Bookmark", comment: "Menu item title, Show Bookmark")
+        canGoForwardObservation = webView.observe(\WebView.canGoForward) { [weak self] _, _ in
+            
+            guard let `self` = self else {
+                
+                return
             }
-            return true
-        case Selector.selectBookmark:
-            return true
-        case Selector.reloadContent:
-            return true
-        default:
-            return false
+            
+            self.goSegment.setEnabled(self.webView.canGoForward, forSegment: 1)
         }
+        
+        webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
+        webView.frameLoadDelegate = self
     }
+    
     override func swipe(with event: NSEvent) {
+        
         if event.deltaX > 0 && showsBookmarkList() {
+            
             showBookmark(nil)
         }
+        
         if event.deltaX < 0 && !showsBookmarkList() {
+            
             showBookmark(nil)
         }
     }
     
-    fileprivate func move(bookmark: Bookmark) {
+    private func move(bookmark: Bookmark) {
+        
         if !canMovePage {
+            
             AppDelegate.shared.createNewBrowser().move(bookmark: bookmark)
+            
             return
         }
         
@@ -166,52 +174,142 @@ class ExternalBrowserWindowController: NSWindowController {
         canScroll = bookmark.canScroll
         waitingBookmarkItem = bookmark
     }
-    fileprivate func showsBookmarkList() -> Bool {
+    
+    private func showsBookmarkList() -> Bool {
+        
         return webView.frame.origin.x > 0
     }
+}
+
+extension ExternalBrowserWindowController: NSWindowDelegate {
+    
+    func windowWillClose(_ notification: Notification) {
+        
+        webView.policyDelegate = nil
+        webView.uiDelegate = nil
+        webView.downloadDelegate = nil
+        webView.frameLoadDelegate = nil
+    }
+}
+
+// MARK: - IBAction
+extension ExternalBrowserWindowController {
+    
+    override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+        
+        guard let action = menuItem.action else {
+            
+            return false
+        }
+        
+        switch action {
+            
+        case #selector(ExternalBrowserWindowController.addBookmark(_:)):
+            
+            return webView.mainFrameURL != nil
+            
+        case #selector(ExternalBrowserWindowController.showBookmark(_:)):
+            
+            if showsBookmarkList() {
+                
+                menuItem.title = LocalizedStrings.hideBookmark.string
+                
+            } else {
+                
+                menuItem.title = LocalizedStrings.showBookmark.string
+            }
+            
+            return true
+            
+        case #selector(ExternalBrowserWindowController.selectBookmark(_:)):
+            
+            return true
+            
+        case #selector(ExternalBrowserWindowController.reloadContent(_:)):
+            
+            return true
+            
+        default:
+            
+            return false
+            
+        }
+    }
     
-    // MARK: - IBAction
     @IBAction func selectBookmark(_ sender: AnyObject?) {
-        guard let item = sender?.representedObject as? Bookmark
-            else { return }
+        
+        guard let item = sender?.representedObject as? Bookmark else {
+            
+            return
+        }
+        
         move(bookmark: item)
     }
+    
     @IBAction func reloadContent(_ sender: AnyObject?) {
+        
         webView.reload(nil)
     }
+    
     @IBAction func goHome(_ sender: AnyObject?) {
+        
         webView.mainFrameURL = "http://www.dmm.com/"
     }
+    
     @IBAction func clickGoBackSegment(_ sender: AnyObject?) {
-        guard let cell = goSegment.cell as? NSSegmentedCell
-            else { return }
+        
+        guard let cell = goSegment.cell as? NSSegmentedCell else {
+            
+            return
+        }
+        
         let tag = cell.tag(forSegment: cell.selectedSegment)
         switch tag {
-        case 0:
-            webView.goBack(nil)
-        case 1:
-            webView.goForward(nil)
-        default:
-            break
+            
+        case 0: webView.goBack(nil)
+            
+        case 1: webView.goForward(nil)
+            
+        default: break
+            
         }
     }
+    
     @IBAction func addBookmark(_ sender: AnyObject?) {
-        guard let window = window,
-            let bookmark = BookmarkManager.shared().createNewBookmark()
-            else { return }
-        bookmark.name = window.title
-        bookmark.urlString = webView.mainFrameURL
-        bookmark.windowContentSize = windowContentSize
-        bookmark.contentVisibleRect = contentVisibleRect
-        bookmark.canResize = canResize
-        bookmark.canScroll = canScroll
-        bookmark.scrollDelay = 0.5
+        
+        guard let window = window else {
+            
+            return
+        }
+        _ = BookmarkManager.shared.createNewBookmark { bookmark in
+            
+            bookmark.name = window.title
+            bookmark.urlString = self.webView.mainFrameURL
+            bookmark.windowContentSize = self.windowContentSize
+            bookmark.contentVisibleRect = self.contentVisibleRect
+            bookmark.canResize = self.canResize
+            bookmark.canScroll = self.canScroll
+            bookmark.scrollDelay = 0.5
+            
+            return true
+        }
     }
+    
     @IBAction func showBookmark(_ sender: AnyObject?) {
-        guard let window = window,
-            let _ = bookmarkListViwController,
-            !bookmarkShowing
-            else { return }
+        
+        guard let window = window else {
+            
+            return
+        }
+        guard let _ = bookmarkListViwController else {
+            
+            return
+        }
+        guard !bookmarkShowing else {
+            
+            return
+        }
+        
         bookmarkShowing = true
         
         var frame = bookmarkListView.frame
@@ -221,68 +319,100 @@ class ExternalBrowserWindowController: NSWindowController {
         var newFrame = webView.frame
         
         if showsBookmarkList() {
+            
             frame.origin.x = -200
             newFrame.origin.x = 0
             newFrame.size.width = window.frame.size.width
+            
         } else {
+            
             frame.origin.x = 0
             newFrame.origin.x = 200
             newFrame.size.width = window.frame.size.width - 200
         }
         
-        let webAnime: [String : Any] = [
-            NSViewAnimationTargetKey: webView,
-            NSViewAnimationEndFrameKey: NSValue(rect: newFrame)
-        ]
-        let bookmarkAnime: [String : Any] = [
-            NSViewAnimationTargetKey: bookmarkListView,
-            NSViewAnimationEndFrameKey: NSValue(rect: frame)
-        ]
-        let anime = NSViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
-        anime.delegate = self
-        anime.start()
+        let webAnime = ViewAnimationAttributes(target: webView, endFrame: newFrame)
+        let bookmarkAnime = ViewAnimationAttributes(target: bookmarkListView, endFrame: frame)
+
+        let anime = ViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
+        anime.start { [weak self] in
+            
+            self?.bookmarkShowing = false
+        }
     }
+    
     @IBAction func scrollLeft(_ sender: AnyObject?) {
+        
         var rect = contentVisibleRect
         rect.origin.x += 1
         contentVisibleRect = rect
     }
+    
     @IBAction func scrollRight(_ sender: AnyObject?) {
+        
         var rect = contentVisibleRect
         rect.origin.x -= 1
         contentVisibleRect = rect
     }
+    
     @IBAction func scrollUp(_ sender: AnyObject?) {
+        
         var rect = contentVisibleRect
         rect.origin.y += 1
         contentVisibleRect = rect
     }
+    
     @IBAction func scrollDown(_ sender: AnyObject?) {
+        
         var rect = contentVisibleRect
         rect.origin.y -= 1
         contentVisibleRect = rect
     }
+    
     @IBAction func increaseWidth(_ sender: AnyObject?) {
-        guard let window = window else { return }
+        
+        guard let window = window else {
+            
+            return
+        }
+        
         var frame = window.frame
         frame.size.width += 1
         window.setFrame(frame, display: true)
     }
+    
     @IBAction func decreaseWidth(_ sender: AnyObject?) {
-        guard let window = window else { return }
+        
+        guard let window = window else {
+            
+            return
+        }
+        
         var frame = window.frame
         frame.size.width -= 1
         window.setFrame(frame, display: true)
     }
+    
     @IBAction func increaseHeight(_ sender: AnyObject?) {
-        guard let window = window else { return }
+        
+        guard let window = window else {
+            
+            return
+        }
+        
         var frame = window.frame
         frame.size.height += 1
         frame.origin.y -= 1
         window.setFrame(frame, display: true)
     }
+    
     @IBAction func decreaseHeight(_ sender: AnyObject?) {
-        guard let window = window else { return }
+        
+        guard let window = window else {
+            
+            return
+        }
+        
         var frame = window.frame
         frame.size.height -= 1
         frame.origin.y += 1
@@ -291,37 +421,54 @@ class ExternalBrowserWindowController: NSWindowController {
 }
 
 extension ExternalBrowserWindowController: BookmarkListViewControllerDelegate {
+    
     func didSelectBookmark(_ bookmark: Bookmark) {
+        
         move(bookmark: bookmark)
     }
 }
 
-extension ExternalBrowserWindowController: NSAnimationDelegate {
-    func animationDidEnd(_ animation: NSAnimation) {
-        bookmarkShowing = false
-    }
-}
-
 extension ExternalBrowserWindowController: WebFrameLoadDelegate, WebPolicyDelegate {
     
-    func updateContentVisibleRect(_ timer: Timer) {
-        guard let item = timer.userInfo as? Bookmark else { return }
+    @objc func updateContentVisibleRect(_ timer: Timer) {
+        
+        guard let item = timer.userInfo as? Bookmark else {
+            
+            return
+        }
+        
         contentVisibleRect = item.contentVisibleRect
     }
+    
     func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
+        
         if let waitingBookmarkItem = waitingBookmarkItem {
-            Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay, target: self, selector: .updateContentVisibleRect, userInfo: waitingBookmarkItem, repeats: false)
+            
+            Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay,
+                                 target: self,
+                                 selector: #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:)),
+                                 userInfo: waitingBookmarkItem,
+                                 repeats: false)
         }
         waitingBookmarkItem = nil
     }
-    func webView(_ webView: WebView!, decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!, request: URLRequest!, frame: WebFrame!, decisionListener listener: WebPolicyDecisionListener!) {
+    
+    func webView(_ webView: WebView!,
+                 decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!,
+                 request: URLRequest!,
+                 frame: WebFrame!,
+                 decisionListener listener: WebPolicyDecisionListener!) {
+        
         if actionInformation?[WebActionNavigationTypeKey] as? WebNavigationType == .linkClicked {
+            
             if canMovePage {
+                
                 listener.use()
             }
+            
             return
         }
+        
         listener.use()
     }
 }
-