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
77 guard let window = window else {
82 var contentRect: NSRect = .zero
83 contentRect.size = newValue
84 var newFrame = window.frameRect(forContentRect: contentRect)
85 let frame = window.frame
86 newFrame.origin.x = frame.minX
87 newFrame.origin.y = frame.maxY - newFrame.height
88 window.setFrame(newFrame, display: true)
92 var contentVisibleRect: NSRect {
94 get { return webView.mainFrame.frameView.documentView.visibleRect }
95 set { webView.mainFrame.frameView.documentView.scrollToVisible(newValue) }
98 private var bookmarkShowing: Bool = false
99 private var waitingBookmarkItem: Bookmark?
101 private lazy var bookmarkListViwController: BookmarkListViewController? = { [weak self] in
103 guard let `self` = self else {
108 let controller = BookmarkListViewController()
109 self.bookmarkListView = controller.view
110 controller.delegate = self
112 var frame = self.webView.frame
113 frame.size.width = 200
114 frame.origin.x = -200
115 self.bookmarkListView.frame = frame
116 self.webView.superview?.addSubview(self.bookmarkListView, positioned: .below, relativeTo: self.webView)
121 override func windowDidLoad() {
123 super.windowDidLoad()
125 canGoBackObservation = webView.observe(\WebView.canGoBack) { [weak self] _, _ in
127 guard let `self` = self else {
132 self.goSegment.setEnabled(self.webView.canGoBack, forSegment: 0)
134 canGoForwardObservation = webView.observe(\WebView.canGoForward) { [weak self] _, _ in
136 guard let `self` = self else {
141 self.goSegment.setEnabled(self.webView.canGoForward, forSegment: 1)
144 webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
145 webView.frameLoadDelegate = self
148 override func swipe(with event: NSEvent) {
150 if event.deltaX > 0 && showsBookmarkList() {
155 if event.deltaX < 0 && !showsBookmarkList() {
161 private func move(bookmark: Bookmark) {
165 AppDelegate.shared.createNewBrowser().move(bookmark: bookmark)
170 webView.mainFrameURL = bookmark.urlString
171 windowContentSize = bookmark.windowContentSize
172 canResize = bookmark.canResize
173 canScroll = bookmark.canScroll
174 waitingBookmarkItem = bookmark
177 private func showsBookmarkList() -> Bool {
179 return webView.frame.origin.x > 0
183 extension ExternalBrowserWindowController: NSWindowDelegate {
185 func windowWillClose(_ notification: Notification) {
187 webView.policyDelegate = nil
188 webView.uiDelegate = nil
189 webView.downloadDelegate = nil
190 webView.frameLoadDelegate = nil
195 extension ExternalBrowserWindowController {
197 override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
199 guard let action = menuItem.action else {
206 case #selector(ExternalBrowserWindowController.addBookmark(_:)):
208 return webView.mainFrameURL != nil
210 case #selector(ExternalBrowserWindowController.showBookmark(_:)):
212 if showsBookmarkList() {
214 menuItem.title = LocalizedStrings.hideBookmark.string
218 menuItem.title = LocalizedStrings.showBookmark.string
223 case #selector(ExternalBrowserWindowController.selectBookmark(_:)):
227 case #selector(ExternalBrowserWindowController.reloadContent(_:)):
238 @IBAction func selectBookmark(_ sender: AnyObject?) {
240 guard let item = sender?.representedObject as? Bookmark else {
248 @IBAction func reloadContent(_ sender: AnyObject?) {
253 @IBAction func goHome(_ sender: AnyObject?) {
255 webView.mainFrameURL = "http://www.dmm.com/"
258 @IBAction func clickGoBackSegment(_ sender: AnyObject?) {
260 guard let cell = goSegment.cell as? NSSegmentedCell else {
265 let tag = cell.tag(forSegment: cell.selectedSegment)
268 case 0: webView.goBack(nil)
270 case 1: webView.goForward(nil)
277 @IBAction func addBookmark(_ sender: AnyObject?) {
279 guard let window = window else {
283 _ = BookmarkManager.shared.createNewBookmark { bookmark in
285 bookmark.name = window.title
286 bookmark.urlString = self.webView.mainFrameURL
287 bookmark.windowContentSize = self.windowContentSize
288 bookmark.contentVisibleRect = self.contentVisibleRect
289 bookmark.canResize = self.canResize
290 bookmark.canScroll = self.canScroll
291 bookmark.scrollDelay = 0.5
297 @IBAction func showBookmark(_ sender: AnyObject?) {
299 guard let window = window else {
303 guard let _ = bookmarkListViwController else {
307 guard !bookmarkShowing else {
312 bookmarkShowing = true
314 var frame = bookmarkListView.frame
315 frame.size.height = webView.frame.size.height
316 bookmarkListView.frame = frame
318 var newFrame = webView.frame
320 if showsBookmarkList() {
322 frame.origin.x = -200
323 newFrame.origin.x = 0
324 newFrame.size.width = window.frame.size.width
329 newFrame.origin.x = 200
330 newFrame.size.width = window.frame.size.width - 200
333 let webAnime = ViewAnimationAttributes(target: webView, endFrame: newFrame)
334 let bookmarkAnime = ViewAnimationAttributes(target: bookmarkListView, endFrame: frame)
336 let anime = ViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
337 anime.start { [weak self] in
339 self?.bookmarkShowing = false
343 @IBAction func scrollLeft(_ sender: AnyObject?) {
345 var rect = contentVisibleRect
347 contentVisibleRect = rect
350 @IBAction func scrollRight(_ sender: AnyObject?) {
352 var rect = contentVisibleRect
354 contentVisibleRect = rect
357 @IBAction func scrollUp(_ sender: AnyObject?) {
359 var rect = contentVisibleRect
361 contentVisibleRect = rect
364 @IBAction func scrollDown(_ sender: AnyObject?) {
366 var rect = contentVisibleRect
368 contentVisibleRect = rect
371 @IBAction func increaseWidth(_ sender: AnyObject?) {
373 guard let window = window else {
378 var frame = window.frame
379 frame.size.width += 1
380 window.setFrame(frame, display: true)
383 @IBAction func decreaseWidth(_ sender: AnyObject?) {
385 guard let window = window else {
390 var frame = window.frame
391 frame.size.width -= 1
392 window.setFrame(frame, display: true)
395 @IBAction func increaseHeight(_ sender: AnyObject?) {
397 guard let window = window else {
402 var frame = window.frame
403 frame.size.height += 1
405 window.setFrame(frame, display: true)
408 @IBAction func decreaseHeight(_ sender: AnyObject?) {
410 guard let window = window else {
415 var frame = window.frame
416 frame.size.height -= 1
418 window.setFrame(frame, display: true)
422 extension ExternalBrowserWindowController: BookmarkListViewControllerDelegate {
424 func didSelectBookmark(_ bookmark: Bookmark) {
426 move(bookmark: bookmark)
430 extension ExternalBrowserWindowController: WebFrameLoadDelegate, WebPolicyDelegate {
432 @objc func updateContentVisibleRect(_ timer: Timer) {
434 guard let item = timer.userInfo as? Bookmark else {
439 contentVisibleRect = item.contentVisibleRect
442 func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
444 if let waitingBookmarkItem = waitingBookmarkItem {
446 Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay,
448 selector: #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:)),
449 userInfo: waitingBookmarkItem,
452 waitingBookmarkItem = nil
455 func webView(_ webView: WebView!,
456 decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!,
457 request: URLRequest!,
459 decisionListener listener: WebPolicyDecisionListener!) {
461 if actionInformation?[WebActionNavigationTypeKey] as? WebNavigationType == .linkClicked {