2 // ExternalBrowserWindowController.swift
5 // Created by Hori,Masaki on 2016/12/23.
6 // Copyright © 2016年 Hori,Masaki. All rights reserved.
12 final class ExternalBrowserWindowController: NSWindowController {
14 @IBOutlet var webView: WebView!
15 @IBOutlet var goSegment: NSSegmentedControl!
16 @IBOutlet var bookmarkListView: NSView!
18 private var canGoBackObservation: NSKeyValueObservation?
19 private var canGoForwardObservation: NSKeyValueObservation?
21 override var windowNibName: NSNib.Name {
23 return .nibName(instanceOf: self)
26 @objc dynamic var canResize: Bool = true {
29 guard let window = window else { return }
31 if canResize == newValue { return }
33 var styleMask = window.styleMask
36 styleMask.insert(.resizable)
40 styleMask.remove(.resizable)
43 window.styleMask = styleMask
47 @objc dynamic var canScroll: Bool = true {
50 guard let webView = webView else { return }
52 if canScroll == newValue { return }
54 webView.mainFrame.frameView.allowsScrolling = newValue
57 @objc dynamic var canMovePage: Bool = true
59 var urlString: String? {
61 return webView.mainFrameURL
64 var windowContentSize: NSSize {
67 guard let window = window else { return .zero }
69 return window.contentRect(forFrameRect: window.frame).size
72 guard let window = window else { return }
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)
84 var contentVisibleRect: NSRect {
86 get { return webView.mainFrame.frameView.documentView.visibleRect }
87 set { webView.mainFrame.frameView.documentView.scrollToVisible(newValue) }
90 private var bookmarkShowing: Bool = false
91 private var waitingBookmarkItem: Bookmark?
93 private lazy var bookmarkListViwController: BookmarkListViewController? = { [weak self] in
95 guard let `self` = self else { return nil }
97 let controller = BookmarkListViewController()
98 self.bookmarkListView = controller.view
99 controller.delegate = self
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)
110 override func windowDidLoad() {
112 super.windowDidLoad()
114 canGoBackObservation = webView.observe(\WebView.canGoBack) { [weak self] _, _ in
116 guard let `self` = self else { return }
118 self.goSegment.setEnabled(self.webView.canGoBack, forSegment: 0)
120 canGoForwardObservation = webView.observe(\WebView.canGoForward) { [weak self] _, _ in
122 guard let `self` = self else { return }
124 self.goSegment.setEnabled(self.webView.canGoForward, forSegment: 1)
127 webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
128 webView.frameLoadDelegate = self
131 override func swipe(with event: NSEvent) {
133 if event.deltaX > 0 && showsBookmarkList() {
138 if event.deltaX < 0 && !showsBookmarkList() {
144 private func move(bookmark: Bookmark) {
148 AppDelegate.shared.createNewBrowser().move(bookmark: bookmark)
152 webView.mainFrameURL = bookmark.urlString
153 windowContentSize = bookmark.windowContentSize
154 canResize = bookmark.canResize
155 canScroll = bookmark.canScroll
156 waitingBookmarkItem = bookmark
159 private func showsBookmarkList() -> Bool {
161 return webView.frame.origin.x > 0
165 extension ExternalBrowserWindowController: NSWindowDelegate {
167 func windowWillClose(_ notification: Notification) {
169 webView.policyDelegate = nil
170 webView.uiDelegate = nil
171 webView.downloadDelegate = nil
172 webView.frameLoadDelegate = nil
177 extension ExternalBrowserWindowController {
179 override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
181 guard let action = menuItem.action else { return false }
185 case #selector(ExternalBrowserWindowController.addBookmark(_:)):
186 return webView.mainFrameURL != nil
188 case #selector(ExternalBrowserWindowController.showBookmark(_:)):
189 if showsBookmarkList() {
191 menuItem.title = LocalizedStrings.hideBookmark.string
195 menuItem.title = LocalizedStrings.showBookmark.string
199 case #selector(ExternalBrowserWindowController.selectBookmark(_:)):
202 case #selector(ExternalBrowserWindowController.reloadContent(_:)):
210 @IBAction func selectBookmark(_ sender: AnyObject?) {
212 guard let item = sender?.representedObject as? Bookmark else { return }
217 @IBAction func reloadContent(_ sender: AnyObject?) {
222 @IBAction func goHome(_ sender: AnyObject?) {
224 webView.mainFrameURL = "http://www.dmm.com/"
227 @IBAction func clickGoBackSegment(_ sender: AnyObject?) {
229 guard let cell = goSegment.cell as? NSSegmentedCell else { return }
231 let tag = cell.tag(forSegment: cell.selectedSegment)
234 case 0: webView.goBack(nil)
236 case 1: webView.goForward(nil)
242 @IBAction func addBookmark(_ sender: AnyObject?) {
244 guard let window = window else { return }
245 guard let bookmark = BookmarkManager.shared.createNewBookmark() else { return }
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
256 @IBAction func showBookmark(_ sender: AnyObject?) {
258 guard let window = window else { return }
259 guard let _ = bookmarkListViwController else { return }
260 guard !bookmarkShowing else { return }
262 bookmarkShowing = true
264 var frame = bookmarkListView.frame
265 frame.size.height = webView.frame.size.height
266 bookmarkListView.frame = frame
268 var newFrame = webView.frame
270 if showsBookmarkList() {
272 frame.origin.x = -200
273 newFrame.origin.x = 0
274 newFrame.size.width = window.frame.size.width
279 newFrame.origin.x = 200
280 newFrame.size.width = window.frame.size.width - 200
283 let webAnime: [NSViewAnimation.Key: Any] = [
285 .endFrame: NSValue(rect: newFrame)
287 let bookmarkAnime: [NSViewAnimation.Key: Any] = [
288 .target: bookmarkListView,
289 .endFrame: NSValue(rect: frame)
291 let anime = NSViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
292 anime.delegate = self
296 @IBAction func scrollLeft(_ sender: AnyObject?) {
298 var rect = contentVisibleRect
300 contentVisibleRect = rect
303 @IBAction func scrollRight(_ sender: AnyObject?) {
305 var rect = contentVisibleRect
307 contentVisibleRect = rect
310 @IBAction func scrollUp(_ sender: AnyObject?) {
312 var rect = contentVisibleRect
314 contentVisibleRect = rect
317 @IBAction func scrollDown(_ sender: AnyObject?) {
319 var rect = contentVisibleRect
321 contentVisibleRect = rect
324 @IBAction func increaseWidth(_ sender: AnyObject?) {
326 guard let window = window else { return }
328 var frame = window.frame
329 frame.size.width += 1
330 window.setFrame(frame, display: true)
333 @IBAction func decreaseWidth(_ sender: AnyObject?) {
335 guard let window = window else { return }
337 var frame = window.frame
338 frame.size.width -= 1
339 window.setFrame(frame, display: true)
342 @IBAction func increaseHeight(_ sender: AnyObject?) {
344 guard let window = window else { return }
346 var frame = window.frame
347 frame.size.height += 1
349 window.setFrame(frame, display: true)
352 @IBAction func decreaseHeight(_ sender: AnyObject?) {
354 guard let window = window else { return }
356 var frame = window.frame
357 frame.size.height -= 1
359 window.setFrame(frame, display: true)
363 extension ExternalBrowserWindowController: BookmarkListViewControllerDelegate {
365 func didSelectBookmark(_ bookmark: Bookmark) {
367 move(bookmark: bookmark)
371 extension ExternalBrowserWindowController: NSAnimationDelegate {
373 func animationDidEnd(_ animation: NSAnimation) {
375 bookmarkShowing = false
379 extension ExternalBrowserWindowController: WebFrameLoadDelegate, WebPolicyDelegate {
381 @objc func updateContentVisibleRect(_ timer: Timer) {
383 guard let item = timer.userInfo as? Bookmark else { return }
385 contentVisibleRect = item.contentVisibleRect
388 func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
390 if let waitingBookmarkItem = waitingBookmarkItem {
392 Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay,
394 selector: #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:)),
395 userInfo: waitingBookmarkItem,
398 waitingBookmarkItem = nil
401 func webView(_ webView: WebView!,
402 decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!,
403 request: URLRequest!,
405 decisionListener listener: WebPolicyDecisionListener!) {
407 if actionInformation?[WebActionNavigationTypeKey] as? WebNavigationType == .linkClicked {