2 // ExternalBrowserWindowController.swift
5 // Created by Hori,Masaki on 2016/12/23.
6 // Copyright © 2016年 Hori,Masaki. All rights reserved.
12 fileprivate extension Selector {
13 static let addBookmark = #selector(ExternalBrowserWindowController.addBookmark(_:))
14 static let showBookmark = #selector(ExternalBrowserWindowController.showBookmark(_:))
15 static let selectBookmark = #selector(ExternalBrowserWindowController.selectBookmark(_:))
16 static let reloadContent = #selector(ExternalBrowserWindowController.reloadContent(_:))
17 static let updateContentVisibleRect = #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:))
20 class ExternalBrowserWindowController: NSWindowController {
21 let managedObjectContext = BookmarkManager.shared().manageObjectContext
24 webView.removeObserver(self, forKeyPath: "canGoBack")
25 webView.removeObserver(self, forKeyPath: "canGoForward")
28 @IBOutlet var webView: WebView!
29 @IBOutlet var goSegment: NSSegmentedControl!
30 @IBOutlet var bookmarkListView: NSView!
32 override var windowNibName: String! {
33 return "ExternalBrowserWindowController"
35 dynamic var canResize: Bool = true {
37 guard let window = window else { return }
38 if canResize == newValue { return }
39 var style = window.styleMask.rawValue
41 style |= NSResizableWindowMask.rawValue
43 style &= ~NSResizableWindowMask.rawValue
45 window.styleMask = NSWindowStyleMask(rawValue: style)
48 dynamic var canScroll: Bool = true {
50 guard let webView = webView else { return }
51 if canScroll == newValue { return }
53 webView.mainFrame.frameView.allowsScrolling = true
55 webView.mainFrame.frameView.allowsScrolling = false
59 dynamic var canMovePage: Bool = true
61 var urlString: String? {
62 return webView.mainFrameURL
64 var windowContentSize: NSSize {
66 guard let window = window else { return .zero }
67 return window.contentRect(forFrameRect: window.frame).size
70 guard let window = window else { return }
71 var contentRect: NSRect = .zero
72 contentRect.size = newValue
73 var newFrame = window.frameRect(forContentRect: contentRect)
74 let frame = window.frame
75 newFrame.origin.x = NSMinX(frame)
76 newFrame.origin.y = NSMaxY(frame) - NSHeight(newFrame)
77 window.setFrame(newFrame, display: true)
80 var contentVisibleRect: NSRect {
82 return webView.mainFrame.frameView.documentView.visibleRect
85 webView.mainFrame.frameView.documentView.scrollToVisible(newValue)
89 fileprivate var bookmarkShowing: Bool = false
90 fileprivate var waitingBookmarkItem: Bookmark?
92 private lazy var bookmarkListViwController: BookmarkListViewController? = {
94 guard let `self` = self else { return nil }
95 let controller = BookmarkListViewController()
96 self.bookmarkListView = controller.view
97 controller.delegate = self
99 var frame = self.webView.frame
100 frame.size.width = 200
101 frame.origin.x = -200
102 self.bookmarkListView.frame = frame
103 self.webView.superview?.addSubview(self.bookmarkListView, positioned: .below, relativeTo: self.webView)
108 override func windowDidLoad() {
109 super.windowDidLoad()
111 webView.addObserver(self, forKeyPath: "canGoBack", context: nil)
112 webView.addObserver(self, forKeyPath: "canGoForward", context: nil)
113 webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
114 webView.frameLoadDelegate = self
116 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
117 if keyPath == "canGoBack" {
118 goSegment.setEnabled(webView.canGoBack, forSegment: 0)
121 if keyPath == "canGoForward" {
122 goSegment.setEnabled(webView.canGoForward, forSegment: 1)
126 super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
128 override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
129 guard let action = menuItem.action else { return false }
131 case Selector.addBookmark:
132 return webView.mainFrameURL != nil
133 case Selector.showBookmark:
134 if showsBookmarkList() {
135 menuItem.title = NSLocalizedString("Hide Bookmark", comment: "Menu item title, Hide Bookmark")
137 menuItem.title = NSLocalizedString("Show Bookmark", comment: "Menu item title, Show Bookmark")
140 case Selector.selectBookmark:
142 case Selector.reloadContent:
148 override func swipe(with event: NSEvent) {
149 if event.deltaX > 0 && showsBookmarkList() {
152 if event.deltaX < 0 && !showsBookmarkList() {
157 fileprivate func move(bookmark: Bookmark) {
159 AppDelegate.shared.createNewBrowser().move(bookmark: bookmark)
163 webView.mainFrameURL = bookmark.urlString
164 windowContentSize = bookmark.windowContentSize
165 canResize = bookmark.canResize
166 canScroll = bookmark.canScroll
167 waitingBookmarkItem = bookmark
169 fileprivate func showsBookmarkList() -> Bool {
170 return webView.frame.origin.x > 0
174 @IBAction func selectBookmark(_ sender: AnyObject?) {
175 guard let item = sender?.representedObject as? Bookmark
179 @IBAction func reloadContent(_ sender: AnyObject?) {
182 @IBAction func goHome(_ sender: AnyObject?) {
183 webView.mainFrameURL = "http://www.dmm.com/"
185 @IBAction func clickGoBackSegment(_ sender: AnyObject?) {
186 guard let cell = goSegment.cell as? NSSegmentedCell
188 let tag = cell.tag(forSegment: cell.selectedSegment)
193 webView.goForward(nil)
198 @IBAction func addBookmark(_ sender: AnyObject?) {
199 guard let window = window,
200 let bookmark = BookmarkManager.shared().createNewBookmark()
202 bookmark.name = window.title
203 bookmark.urlString = webView.mainFrameURL
204 bookmark.windowContentSize = windowContentSize
205 bookmark.contentVisibleRect = contentVisibleRect
206 bookmark.canResize = canResize
207 bookmark.canScroll = canScroll
208 bookmark.scrollDelay = 0.5
210 @IBAction func showBookmark(_ sender: AnyObject?) {
211 guard let window = window,
212 let _ = bookmarkListViwController,
215 bookmarkShowing = true
217 var frame = bookmarkListView.frame
218 frame.size.height = webView.frame.size.height
219 bookmarkListView.frame = frame
221 var newFrame = webView.frame
223 if showsBookmarkList() {
224 frame.origin.x = -200
225 newFrame.origin.x = 0
226 newFrame.size.width = window.frame.size.width
229 newFrame.origin.x = 200
230 newFrame.size.width = window.frame.size.width - 200
233 let webAnime: [String : Any] = [
234 NSViewAnimationTargetKey: webView,
235 NSViewAnimationEndFrameKey: NSValue(rect: newFrame)
237 let bookmarkAnime: [String : Any] = [
238 NSViewAnimationTargetKey: bookmarkListView,
239 NSViewAnimationEndFrameKey: NSValue(rect: frame)
241 let anime = NSViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
242 anime.delegate = self
245 @IBAction func scrollLeft(_ sender: AnyObject?) {
246 var rect = contentVisibleRect
248 contentVisibleRect = rect
250 @IBAction func scrollRight(_ sender: AnyObject?) {
251 var rect = contentVisibleRect
253 contentVisibleRect = rect
255 @IBAction func scrollUp(_ sender: AnyObject?) {
256 var rect = contentVisibleRect
258 contentVisibleRect = rect
260 @IBAction func scrollDown(_ sender: AnyObject?) {
261 var rect = contentVisibleRect
263 contentVisibleRect = rect
265 @IBAction func increaseWidth(_ sender: AnyObject?) {
266 guard let window = window else { return }
267 var frame = window.frame
268 frame.size.width += 1
269 window.setFrame(frame, display: true)
271 @IBAction func decreaseWidth(_ sender: AnyObject?) {
272 guard let window = window else { return }
273 var frame = window.frame
274 frame.size.width -= 1
275 window.setFrame(frame, display: true)
277 @IBAction func increaseHeight(_ sender: AnyObject?) {
278 guard let window = window else { return }
279 var frame = window.frame
280 frame.size.height += 1
282 window.setFrame(frame, display: true)
284 @IBAction func decreaseHeight(_ sender: AnyObject?) {
285 guard let window = window else { return }
286 var frame = window.frame
287 frame.size.height -= 1
289 window.setFrame(frame, display: true)
293 extension ExternalBrowserWindowController: BookmarkListViewControllerDelegate {
294 func didSelectBookmark(_ bookmark: Bookmark) {
295 move(bookmark: bookmark)
299 extension ExternalBrowserWindowController: NSAnimationDelegate {
300 func animationDidEnd(_ animation: NSAnimation) {
301 bookmarkShowing = false
305 extension ExternalBrowserWindowController: WebFrameLoadDelegate, WebPolicyDelegate {
307 func updateContentVisibleRect(_ timer: Timer) {
308 guard let item = timer.userInfo as? Bookmark else { return }
309 contentVisibleRect = item.contentVisibleRect
311 func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
312 if let waitingBookmarkItem = waitingBookmarkItem {
313 Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay, target: self, selector: .updateContentVisibleRect, userInfo: waitingBookmarkItem, repeats: false)
315 waitingBookmarkItem = nil
317 func webView(_ webView: WebView!, decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!, request: URLRequest!, frame: WebFrame!, decisionListener listener: WebPolicyDecisionListener!) {
318 if actionInformation?[WebActionNavigationTypeKey] as? WebNavigationType == .linkClicked {