OSDN Git Service

関数名を変更
[kcd/KCD.git] / KCD / ExternalBrowserWindowController.swift
1 //
2 //  ExternalBrowserWindowController.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2016/12/23.
6 //  Copyright © 2016年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10 import WebKit
11
12 final class ExternalBrowserWindowController: NSWindowController {
13         
14     @IBOutlet var webView: WebView!
15     @IBOutlet var goSegment: NSSegmentedControl!
16     @IBOutlet var bookmarkListView: NSView!
17     
18     private var canGoBackObservation: NSKeyValueObservation?
19     private var canGoForwardObservation: NSKeyValueObservation?
20     
21     override var windowNibName: NSNib.Name {
22         
23         return .nibName(instanceOf: self)
24     }
25     
26     @objc dynamic var canResize: Bool = true {
27         
28         willSet {
29             guard let window = window else { return }
30             
31             if canResize == newValue { return }
32             
33             var styleMask = window.styleMask
34             if newValue {
35                 
36                 styleMask.insert(.resizable)
37                 
38             } else {
39                 
40                 styleMask.remove(.resizable)
41             }
42             
43             window.styleMask = styleMask
44         }
45     }
46     
47     @objc dynamic var canScroll: Bool = true {
48         
49         willSet {
50             guard let webView = webView else { return }
51             
52             if canScroll == newValue { return }
53             
54             webView.mainFrame.frameView.allowsScrolling = newValue
55         }
56     }
57     @objc dynamic var canMovePage: Bool = true
58     
59     var urlString: String? {
60         
61         return webView.mainFrameURL
62     }
63     
64     var windowContentSize: NSSize {
65         
66         get {
67             guard let window = window else { return .zero }
68             
69             return window.contentRect(forFrameRect: window.frame).size
70         }
71         set {
72             guard let window = window else { return }
73             
74             var contentRect: NSRect = .zero
75             contentRect.size = newValue
76             var newFrame = window.frameRect(forContentRect: contentRect)
77             let frame = window.frame
78             newFrame.origin.x = frame.minX
79             newFrame.origin.y = frame.maxY - newFrame.height
80             window.setFrame(newFrame, display: true)
81         }
82     }
83     
84     var contentVisibleRect: NSRect {
85         
86         get { return webView.mainFrame.frameView.documentView.visibleRect }
87         set { webView.mainFrame.frameView.documentView.scrollToVisible(newValue) }
88     }
89     
90     private var bookmarkShowing: Bool = false
91     private var waitingBookmarkItem: Bookmark?
92     
93     private lazy var bookmarkListViwController: BookmarkListViewController? = { [weak self] in
94         
95         guard let `self` = self else { return nil }
96         
97         let controller = BookmarkListViewController()
98         self.bookmarkListView = controller.view
99         controller.delegate = self
100         
101         var frame = self.webView.frame
102         frame.size.width = 200
103         frame.origin.x = -200
104         self.bookmarkListView.frame = frame
105         self.webView.superview?.addSubview(self.bookmarkListView, positioned: .below, relativeTo: self.webView)
106         
107         return controller
108     }()
109     
110     override func windowDidLoad() {
111         
112         super.windowDidLoad()
113         
114         canGoBackObservation = webView.observe(\WebView.canGoBack) { [weak self] _, _ in
115             
116             guard let `self` = self else { return }
117             
118             self.goSegment.setEnabled(self.webView.canGoBack, forSegment: 0)
119         }
120         canGoForwardObservation = webView.observe(\WebView.canGoForward) { [weak self] _, _ in
121             
122             guard let `self` = self else { return }
123             
124             self.goSegment.setEnabled(self.webView.canGoForward, forSegment: 1)
125         }
126         
127         webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
128         webView.frameLoadDelegate = self
129     }
130     
131     override func swipe(with event: NSEvent) {
132         
133         if event.deltaX > 0 && showsBookmarkList() {
134             
135             showBookmark(nil)
136         }
137         
138         if event.deltaX < 0 && !showsBookmarkList() {
139             
140             showBookmark(nil)
141         }
142     }
143     
144     private func move(bookmark: Bookmark) {
145         
146         if !canMovePage {
147             
148             AppDelegate.shared.createNewBrowser().move(bookmark: bookmark)
149             return
150         }
151         
152         webView.mainFrameURL = bookmark.urlString
153         windowContentSize = bookmark.windowContentSize
154         canResize = bookmark.canResize
155         canScroll = bookmark.canScroll
156         waitingBookmarkItem = bookmark
157     }
158     
159     private func showsBookmarkList() -> Bool {
160         
161         return webView.frame.origin.x > 0
162     }
163 }
164
165 extension ExternalBrowserWindowController: NSWindowDelegate {
166     
167     func windowWillClose(_ notification: Notification) {
168         
169         webView.policyDelegate = nil
170         webView.uiDelegate = nil
171         webView.downloadDelegate = nil
172         webView.frameLoadDelegate = nil
173     }
174 }
175
176 // MARK: - IBAction
177 extension ExternalBrowserWindowController {
178     
179     override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
180         
181         guard let action = menuItem.action else { return false }
182         
183         switch action {
184             
185         case #selector(ExternalBrowserWindowController.addBookmark(_:)):
186             return webView.mainFrameURL != nil
187             
188         case #selector(ExternalBrowserWindowController.showBookmark(_:)):
189             if showsBookmarkList() {
190                 
191                 menuItem.title = LocalizedStrings.hideBookmark.string
192                 
193             } else {
194                 
195                 menuItem.title = LocalizedStrings.showBookmark.string
196             }
197             return true
198             
199         case #selector(ExternalBrowserWindowController.selectBookmark(_:)):
200             return true
201             
202         case #selector(ExternalBrowserWindowController.reloadContent(_:)):
203             return true
204             
205         default:
206             return false
207         }
208     }
209     
210     @IBAction func selectBookmark(_ sender: AnyObject?) {
211         
212         guard let item = sender?.representedObject as? Bookmark else { return }
213         
214         move(bookmark: item)
215     }
216     
217     @IBAction func reloadContent(_ sender: AnyObject?) {
218         
219         webView.reload(nil)
220     }
221     
222     @IBAction func goHome(_ sender: AnyObject?) {
223         
224         webView.mainFrameURL = "http://www.dmm.com/"
225     }
226     
227     @IBAction func clickGoBackSegment(_ sender: AnyObject?) {
228         
229         guard let cell = goSegment.cell as? NSSegmentedCell else { return }
230         
231         let tag = cell.tag(forSegment: cell.selectedSegment)
232         switch tag {
233             
234         case 0: webView.goBack(nil)
235             
236         case 1: webView.goForward(nil)
237             
238         default: break
239         }
240     }
241     
242     @IBAction func addBookmark(_ sender: AnyObject?) {
243         
244         guard let window = window else { return }
245         guard let bookmark = BookmarkManager.shared.createNewBookmark() else { return }
246         
247         bookmark.name = window.title
248         bookmark.urlString = webView.mainFrameURL
249         bookmark.windowContentSize = windowContentSize
250         bookmark.contentVisibleRect = contentVisibleRect
251         bookmark.canResize = canResize
252         bookmark.canScroll = canScroll
253         bookmark.scrollDelay = 0.5
254     }
255     
256     @IBAction func showBookmark(_ sender: AnyObject?) {
257         
258         guard let window = window else { return }
259         guard let _ = bookmarkListViwController else { return }
260         guard !bookmarkShowing else { return }
261         
262         bookmarkShowing = true
263         
264         var frame = bookmarkListView.frame
265         frame.size.height = webView.frame.size.height
266         bookmarkListView.frame = frame
267         
268         var newFrame = webView.frame
269         
270         if showsBookmarkList() {
271             
272             frame.origin.x = -200
273             newFrame.origin.x = 0
274             newFrame.size.width = window.frame.size.width
275             
276         } else {
277             
278             frame.origin.x = 0
279             newFrame.origin.x = 200
280             newFrame.size.width = window.frame.size.width - 200
281         }
282         
283         let webAnime: [NSViewAnimation.Key: Any] = [
284             .target: webView,
285             .endFrame: NSValue(rect: newFrame)
286         ]
287         let bookmarkAnime: [NSViewAnimation.Key: Any] = [
288             .target: bookmarkListView,
289             .endFrame: NSValue(rect: frame)
290         ]
291         let anime = NSViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
292         anime.delegate = self
293         anime.start()
294     }
295     
296     @IBAction func scrollLeft(_ sender: AnyObject?) {
297         
298         var rect = contentVisibleRect
299         rect.origin.x += 1
300         contentVisibleRect = rect
301     }
302     
303     @IBAction func scrollRight(_ sender: AnyObject?) {
304         
305         var rect = contentVisibleRect
306         rect.origin.x -= 1
307         contentVisibleRect = rect
308     }
309     
310     @IBAction func scrollUp(_ sender: AnyObject?) {
311         
312         var rect = contentVisibleRect
313         rect.origin.y += 1
314         contentVisibleRect = rect
315     }
316     
317     @IBAction func scrollDown(_ sender: AnyObject?) {
318         
319         var rect = contentVisibleRect
320         rect.origin.y -= 1
321         contentVisibleRect = rect
322     }
323     
324     @IBAction func increaseWidth(_ sender: AnyObject?) {
325         
326         guard let window = window else { return }
327         
328         var frame = window.frame
329         frame.size.width += 1
330         window.setFrame(frame, display: true)
331     }
332     
333     @IBAction func decreaseWidth(_ sender: AnyObject?) {
334         
335         guard let window = window else { return }
336         
337         var frame = window.frame
338         frame.size.width -= 1
339         window.setFrame(frame, display: true)
340     }
341     
342     @IBAction func increaseHeight(_ sender: AnyObject?) {
343         
344         guard let window = window else { return }
345         
346         var frame = window.frame
347         frame.size.height += 1
348         frame.origin.y -= 1
349         window.setFrame(frame, display: true)
350     }
351     
352     @IBAction func decreaseHeight(_ sender: AnyObject?) {
353         
354         guard let window = window else { return }
355         
356         var frame = window.frame
357         frame.size.height -= 1
358         frame.origin.y += 1
359         window.setFrame(frame, display: true)
360     }
361 }
362
363 extension ExternalBrowserWindowController: BookmarkListViewControllerDelegate {
364     
365     func didSelectBookmark(_ bookmark: Bookmark) {
366         
367         move(bookmark: bookmark)
368     }
369 }
370
371 extension ExternalBrowserWindowController: NSAnimationDelegate {
372     
373     func animationDidEnd(_ animation: NSAnimation) {
374         
375         bookmarkShowing = false
376     }
377 }
378
379 extension ExternalBrowserWindowController: WebFrameLoadDelegate, WebPolicyDelegate {
380     
381     @objc func updateContentVisibleRect(_ timer: Timer) {
382         
383         guard let item = timer.userInfo as? Bookmark else { return }
384         
385         contentVisibleRect = item.contentVisibleRect
386     }
387     
388     func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
389         
390         if let waitingBookmarkItem = waitingBookmarkItem {
391             
392             Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay,
393                                  target: self,
394                                  selector: #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:)),
395                                  userInfo: waitingBookmarkItem,
396                                  repeats: false)
397         }
398         waitingBookmarkItem = nil
399     }
400     
401     func webView(_ webView: WebView!,
402                  decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!,
403                  request: URLRequest!,
404                  frame: WebFrame!,
405                  decisionListener listener: WebPolicyDecisionListener!) {
406         
407         if actionInformation?[WebActionNavigationTypeKey] as? WebNavigationType == .linkClicked {
408             
409             if canMovePage {
410                 
411                 listener.use()
412             }
413             
414             return
415         }
416         
417         listener.use()
418     }
419 }