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 private var webView: WebView!
15 @IBOutlet private var goSegment: NSSegmentedControl!
16 @IBOutlet private 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 {
30 if canResize == newValue {
37 window?.styleMask.insert(.resizable)
41 window?.styleMask.remove(.resizable)
46 @objc dynamic var canScroll: Bool = true {
50 if canScroll == newValue {
55 webView?.mainFrame.frameView.allowsScrolling = newValue
58 @objc dynamic var canMovePage: Bool = true
60 var urlString: String? {
62 return webView.mainFrameURL
65 var windowContentSize: NSSize {
69 guard let window = window else {
74 return window.contentRect(forFrameRect: window.frame).size
78 guard let window = window else {
83 var contentRect: NSRect = .zero
84 contentRect.size = newValue
85 var newFrame = window.frameRect(forContentRect: contentRect)
86 let frame = window.frame
87 newFrame.origin.x = frame.minX
88 newFrame.origin.y = frame.maxY - newFrame.height
89 window.setFrame(newFrame, display: true)
93 var contentVisibleRect: NSRect {
95 get { return webView.mainFrame.frameView.documentView.visibleRect }
96 set { webView.mainFrame.frameView.documentView.scrollToVisible(newValue) }
99 private var bookmarkShowing: Bool = false
100 private var waitingBookmarkItem: Bookmark?
102 private lazy var bookmarkListViwController: BookmarkListViewController? = { [weak self] in
104 guard let `self` = self else {
109 let controller = BookmarkListViewController()
110 self.bookmarkListView = controller.view
111 controller.delegate = self
113 var frame = self.webView.frame
114 frame.size.width = 200
115 frame.origin.x = -200
116 self.bookmarkListView.frame = frame
117 self.webView.superview?.addSubview(self.bookmarkListView, positioned: .below, relativeTo: self.webView)
122 override func windowDidLoad() {
124 super.windowDidLoad()
126 canGoBackObservation = webView.observe(\WebView.canGoBack) { [weak self] _, _ in
128 guard let `self` = self else {
133 self.goSegment.setEnabled(self.webView.canGoBack, forSegment: 0)
135 canGoForwardObservation = webView.observe(\WebView.canGoForward) { [weak self] _, _ in
137 guard let `self` = self else {
142 self.goSegment.setEnabled(self.webView.canGoForward, forSegment: 1)
145 webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
146 webView.frameLoadDelegate = self
149 override func swipe(with event: NSEvent) {
151 if event.deltaX > 0 && showsBookmarkList() {
156 if event.deltaX < 0 && !showsBookmarkList() {
162 private func move(bookmark: Bookmark) {
166 AppDelegate.shared.createNewBrowser().move(bookmark: bookmark)
171 webView.mainFrameURL = bookmark.urlString
172 windowContentSize = bookmark.windowContentSize
173 canResize = bookmark.canResize
174 canScroll = bookmark.canScroll
175 waitingBookmarkItem = bookmark
178 private func showsBookmarkList() -> Bool {
180 return webView.frame.origin.x > 0
184 extension ExternalBrowserWindowController: NSWindowDelegate {
186 func windowWillClose(_ notification: Notification) {
188 webView.policyDelegate = nil
189 webView.uiDelegate = nil
190 webView.downloadDelegate = nil
191 webView.frameLoadDelegate = nil
196 extension ExternalBrowserWindowController {
198 override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
200 guard let action = menuItem.action else {
207 case #selector(ExternalBrowserWindowController.addBookmark(_:)):
209 return webView.mainFrameURL != nil
211 case #selector(ExternalBrowserWindowController.showBookmark(_:)):
213 if showsBookmarkList() {
215 menuItem.title = LocalizedStrings.hideBookmark.string
219 menuItem.title = LocalizedStrings.showBookmark.string
224 case #selector(ExternalBrowserWindowController.selectBookmark(_:)):
228 case #selector(ExternalBrowserWindowController.reloadContent(_:)):
239 @IBAction func selectBookmark(_ sender: AnyObject?) {
241 guard let item = sender?.representedObject as? Bookmark else {
249 @IBAction func reloadContent(_ sender: AnyObject?) {
254 @IBAction func goHome(_ sender: AnyObject?) {
256 webView.mainFrameURL = "http://www.dmm.com/"
259 @IBAction func clickGoBackSegment(_ sender: AnyObject?) {
261 guard let cell = goSegment.cell as? NSSegmentedCell else {
266 let tag = cell.tag(forSegment: cell.selectedSegment)
269 case 0: webView.goBack(nil)
271 case 1: webView.goForward(nil)
278 @IBAction func addBookmark(_ sender: AnyObject?) {
280 guard let window = window else {
284 _ = BookmarkManager.shared.createNewBookmark { bookmark in
286 bookmark.name = window.title
287 bookmark.urlString = self.webView.mainFrameURL
288 bookmark.windowContentSize = self.windowContentSize
289 bookmark.contentVisibleRect = self.contentVisibleRect
290 bookmark.canResize = self.canResize
291 bookmark.canScroll = self.canScroll
292 bookmark.scrollDelay = 0.5
298 @IBAction func showBookmark(_ sender: AnyObject?) {
300 guard let window = window else {
304 guard let _ = bookmarkListViwController else {
308 guard !bookmarkShowing else {
313 bookmarkShowing = true
315 var frame = bookmarkListView.frame
316 frame.size.height = webView.frame.size.height
317 bookmarkListView.frame = frame
319 var newFrame = webView.frame
321 if showsBookmarkList() {
323 frame.origin.x = -200
324 newFrame.origin.x = 0
325 newFrame.size.width = window.frame.size.width
330 newFrame.origin.x = 200
331 newFrame.size.width = window.frame.size.width - 200
334 let webAnime = ViewAnimationAttributes(target: webView, endFrame: newFrame)
335 let bookmarkAnime = ViewAnimationAttributes(target: bookmarkListView, endFrame: frame)
337 let anime = ViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
338 anime.start { [weak self] in
340 self?.bookmarkShowing = false
344 @IBAction func scrollLeft(_ sender: AnyObject?) {
346 var rect = contentVisibleRect
348 contentVisibleRect = rect
351 @IBAction func scrollRight(_ sender: AnyObject?) {
353 var rect = contentVisibleRect
355 contentVisibleRect = rect
358 @IBAction func scrollUp(_ sender: AnyObject?) {
360 var rect = contentVisibleRect
362 contentVisibleRect = rect
365 @IBAction func scrollDown(_ sender: AnyObject?) {
367 var rect = contentVisibleRect
369 contentVisibleRect = rect
372 @IBAction func increaseWidth(_ sender: AnyObject?) {
374 guard let window = window else {
379 var frame = window.frame
380 frame.size.width += 1
381 window.setFrame(frame, display: true)
384 @IBAction func decreaseWidth(_ sender: AnyObject?) {
386 guard let window = window else {
391 var frame = window.frame
392 frame.size.width -= 1
393 window.setFrame(frame, display: true)
396 @IBAction func increaseHeight(_ sender: AnyObject?) {
398 guard let window = window else {
403 var frame = window.frame
404 frame.size.height += 1
406 window.setFrame(frame, display: true)
409 @IBAction func decreaseHeight(_ sender: AnyObject?) {
411 guard let window = window else {
416 var frame = window.frame
417 frame.size.height -= 1
419 window.setFrame(frame, display: true)
423 extension ExternalBrowserWindowController: BookmarkListViewControllerDelegate {
425 func didSelectBookmark(_ bookmark: Bookmark) {
427 move(bookmark: bookmark)
431 extension ExternalBrowserWindowController: WebFrameLoadDelegate, WebPolicyDelegate {
433 @objc func updateContentVisibleRect(_ timer: Timer) {
435 guard let item = timer.userInfo as? Bookmark else {
440 contentVisibleRect = item.contentVisibleRect
443 func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
445 if let waitingBookmarkItem = waitingBookmarkItem {
447 Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay,
449 selector: #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:)),
450 userInfo: waitingBookmarkItem,
453 waitingBookmarkItem = nil
456 func webView(_ webView: WebView!,
457 decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!,
458 request: URLRequest!,
460 decisionListener listener: WebPolicyDecisionListener!) {
462 if actionInformation?[WebActionNavigationTypeKey] as? WebNavigationType == .linkClicked {