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 = frame.minX
76 newFrame.origin.y = frame.maxY - newFrame.height
77 window.setFrame(newFrame, display: true)
80 var contentVisibleRect: NSRect {
81 get { return webView.mainFrame.frameView.documentView.visibleRect }
82 set { webView.mainFrame.frameView.documentView.scrollToVisible(newValue) }
85 fileprivate var bookmarkShowing: Bool = false
86 fileprivate var waitingBookmarkItem: Bookmark?
88 fileprivate lazy var bookmarkListViwController: BookmarkListViewController? = {
90 guard let `self` = self else { return nil }
91 let controller = BookmarkListViewController()
92 self.bookmarkListView = controller.view
93 controller.delegate = self
95 var frame = self.webView.frame
96 frame.size.width = 200
98 self.bookmarkListView.frame = frame
99 self.webView.superview?.addSubview(self.bookmarkListView, positioned: .below, relativeTo: self.webView)
104 override func windowDidLoad() {
105 super.windowDidLoad()
107 webView.addObserver(self, forKeyPath: "canGoBack", context: nil)
108 webView.addObserver(self, forKeyPath: "canGoForward", context: nil)
109 webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
110 webView.frameLoadDelegate = self
112 override func observeValue(forKeyPath keyPath: String?,
114 change: [NSKeyValueChangeKey: Any]?,
115 context: UnsafeMutableRawPointer?) {
116 if keyPath == "canGoBack" {
117 goSegment.setEnabled(webView.canGoBack, forSegment: 0)
120 if keyPath == "canGoForward" {
121 goSegment.setEnabled(webView.canGoForward, forSegment: 1)
125 super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
127 override func swipe(with event: NSEvent) {
128 if event.deltaX > 0 && showsBookmarkList() {
131 if event.deltaX < 0 && !showsBookmarkList() {
136 fileprivate func move(bookmark: Bookmark) {
138 AppDelegate.shared.createNewBrowser().move(bookmark: bookmark)
142 webView.mainFrameURL = bookmark.urlString
143 windowContentSize = bookmark.windowContentSize
144 canResize = bookmark.canResize
145 canScroll = bookmark.canScroll
146 waitingBookmarkItem = bookmark
148 fileprivate func showsBookmarkList() -> Bool {
149 return webView.frame.origin.x > 0
154 extension ExternalBrowserWindowController {
155 override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
156 guard let action = menuItem.action else { return false }
158 case Selector.addBookmark:
159 return webView.mainFrameURL != nil
160 case Selector.showBookmark:
161 if showsBookmarkList() {
162 menuItem.title = NSLocalizedString("Hide Bookmark", comment: "Menu item title, Hide Bookmark")
164 menuItem.title = NSLocalizedString("Show Bookmark", comment: "Menu item title, Show Bookmark")
167 case Selector.selectBookmark:
169 case Selector.reloadContent:
176 @IBAction func selectBookmark(_ sender: AnyObject?) {
177 guard let item = sender?.representedObject as? Bookmark
181 @IBAction func reloadContent(_ sender: AnyObject?) {
184 @IBAction func goHome(_ sender: AnyObject?) {
185 webView.mainFrameURL = "http://www.dmm.com/"
187 @IBAction func clickGoBackSegment(_ sender: AnyObject?) {
188 guard let cell = goSegment.cell as? NSSegmentedCell
190 let tag = cell.tag(forSegment: cell.selectedSegment)
195 webView.goForward(nil)
200 @IBAction func addBookmark(_ sender: AnyObject?) {
201 guard let window = window,
202 let bookmark = BookmarkManager.shared().createNewBookmark()
204 bookmark.name = window.title
205 bookmark.urlString = webView.mainFrameURL
206 bookmark.windowContentSize = windowContentSize
207 bookmark.contentVisibleRect = contentVisibleRect
208 bookmark.canResize = canResize
209 bookmark.canScroll = canScroll
210 bookmark.scrollDelay = 0.5
212 @IBAction func showBookmark(_ sender: AnyObject?) {
213 guard let window = window,
214 let _ = bookmarkListViwController,
217 bookmarkShowing = true
219 var frame = bookmarkListView.frame
220 frame.size.height = webView.frame.size.height
221 bookmarkListView.frame = frame
223 var newFrame = webView.frame
225 if showsBookmarkList() {
226 frame.origin.x = -200
227 newFrame.origin.x = 0
228 newFrame.size.width = window.frame.size.width
231 newFrame.origin.x = 200
232 newFrame.size.width = window.frame.size.width - 200
235 let webAnime: [String: Any] = [
236 NSViewAnimationTargetKey: webView,
237 NSViewAnimationEndFrameKey: NSValue(rect: newFrame)
239 let bookmarkAnime: [String: Any] = [
240 NSViewAnimationTargetKey: bookmarkListView,
241 NSViewAnimationEndFrameKey: NSValue(rect: frame)
243 let anime = NSViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
244 anime.delegate = self
247 @IBAction func scrollLeft(_ sender: AnyObject?) {
248 var rect = contentVisibleRect
250 contentVisibleRect = rect
252 @IBAction func scrollRight(_ sender: AnyObject?) {
253 var rect = contentVisibleRect
255 contentVisibleRect = rect
257 @IBAction func scrollUp(_ sender: AnyObject?) {
258 var rect = contentVisibleRect
260 contentVisibleRect = rect
262 @IBAction func scrollDown(_ sender: AnyObject?) {
263 var rect = contentVisibleRect
265 contentVisibleRect = rect
267 @IBAction func increaseWidth(_ sender: AnyObject?) {
268 guard let window = window else { return }
269 var frame = window.frame
270 frame.size.width += 1
271 window.setFrame(frame, display: true)
273 @IBAction func decreaseWidth(_ sender: AnyObject?) {
274 guard let window = window else { return }
275 var frame = window.frame
276 frame.size.width -= 1
277 window.setFrame(frame, display: true)
279 @IBAction func increaseHeight(_ sender: AnyObject?) {
280 guard let window = window else { return }
281 var frame = window.frame
282 frame.size.height += 1
284 window.setFrame(frame, display: true)
286 @IBAction func decreaseHeight(_ sender: AnyObject?) {
287 guard let window = window else { return }
288 var frame = window.frame
289 frame.size.height -= 1
291 window.setFrame(frame, display: true)
295 extension ExternalBrowserWindowController: BookmarkListViewControllerDelegate {
296 func didSelectBookmark(_ bookmark: Bookmark) {
297 move(bookmark: bookmark)
301 extension ExternalBrowserWindowController: NSAnimationDelegate {
302 func animationDidEnd(_ animation: NSAnimation) {
303 bookmarkShowing = false
307 extension ExternalBrowserWindowController: WebFrameLoadDelegate, WebPolicyDelegate {
309 func updateContentVisibleRect(_ timer: Timer) {
310 guard let item = timer.userInfo as? Bookmark else { return }
311 contentVisibleRect = item.contentVisibleRect
313 func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
314 if let waitingBookmarkItem = waitingBookmarkItem {
315 Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay,
317 selector: .updateContentVisibleRect,
318 userInfo: waitingBookmarkItem,
321 waitingBookmarkItem = nil
323 func webView(_ webView: WebView!,
324 decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!,
325 request: URLRequest!,
327 decisionListener listener: WebPolicyDecisionListener!) {
328 if actionInformation?[WebActionNavigationTypeKey] as? WebNavigationType == .linkClicked {