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(_:)):
207 return webView.mainFrameURL != nil
209 case #selector(ExternalBrowserWindowController.showBookmark(_:)):
210 if showsBookmarkList() {
212 menuItem.title = LocalizedStrings.hideBookmark.string
216 menuItem.title = LocalizedStrings.showBookmark.string
220 case #selector(ExternalBrowserWindowController.selectBookmark(_:)):
223 case #selector(ExternalBrowserWindowController.reloadContent(_:)):
232 @IBAction func selectBookmark(_ sender: AnyObject?) {
234 guard let item = sender?.representedObject as? Bookmark else {
242 @IBAction func reloadContent(_ sender: AnyObject?) {
247 @IBAction func goHome(_ sender: AnyObject?) {
249 webView.mainFrameURL = "http://www.dmm.com/"
252 @IBAction func clickGoBackSegment(_ sender: AnyObject?) {
254 guard let cell = goSegment.cell as? NSSegmentedCell else {
259 let tag = cell.tag(forSegment: cell.selectedSegment)
262 case 0: webView.goBack(nil)
264 case 1: webView.goForward(nil)
271 @IBAction func addBookmark(_ sender: AnyObject?) {
273 guard let window = window else {
277 _ = BookmarkManager.shared.createNewBookmark { bookmark in
279 bookmark.name = window.title
280 bookmark.urlString = self.webView.mainFrameURL
281 bookmark.windowContentSize = self.windowContentSize
282 bookmark.contentVisibleRect = self.contentVisibleRect
283 bookmark.canResize = self.canResize
284 bookmark.canScroll = self.canScroll
285 bookmark.scrollDelay = 0.5
291 @IBAction func showBookmark(_ sender: AnyObject?) {
293 guard let window = window else {
297 guard let _ = bookmarkListViwController else {
301 guard !bookmarkShowing else {
306 bookmarkShowing = true
308 var frame = bookmarkListView.frame
309 frame.size.height = webView.frame.size.height
310 bookmarkListView.frame = frame
312 var newFrame = webView.frame
314 if showsBookmarkList() {
316 frame.origin.x = -200
317 newFrame.origin.x = 0
318 newFrame.size.width = window.frame.size.width
323 newFrame.origin.x = 200
324 newFrame.size.width = window.frame.size.width - 200
327 let webAnime = ViewAnimationAttributes(target: webView, endFrame: newFrame)
328 let bookmarkAnime = ViewAnimationAttributes(target: bookmarkListView, endFrame: frame)
330 let anime = ViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
331 anime.start { [weak self] in
333 self?.bookmarkShowing = false
337 @IBAction func scrollLeft(_ sender: AnyObject?) {
339 var rect = contentVisibleRect
341 contentVisibleRect = rect
344 @IBAction func scrollRight(_ sender: AnyObject?) {
346 var rect = contentVisibleRect
348 contentVisibleRect = rect
351 @IBAction func scrollUp(_ sender: AnyObject?) {
353 var rect = contentVisibleRect
355 contentVisibleRect = rect
358 @IBAction func scrollDown(_ sender: AnyObject?) {
360 var rect = contentVisibleRect
362 contentVisibleRect = rect
365 @IBAction func increaseWidth(_ sender: AnyObject?) {
367 guard let window = window else {
372 var frame = window.frame
373 frame.size.width += 1
374 window.setFrame(frame, display: true)
377 @IBAction func decreaseWidth(_ sender: AnyObject?) {
379 guard let window = window else {
384 var frame = window.frame
385 frame.size.width -= 1
386 window.setFrame(frame, display: true)
389 @IBAction func increaseHeight(_ sender: AnyObject?) {
391 guard let window = window else {
396 var frame = window.frame
397 frame.size.height += 1
399 window.setFrame(frame, display: true)
402 @IBAction func decreaseHeight(_ sender: AnyObject?) {
404 guard let window = window else {
409 var frame = window.frame
410 frame.size.height -= 1
412 window.setFrame(frame, display: true)
416 extension ExternalBrowserWindowController: BookmarkListViewControllerDelegate {
418 func didSelectBookmark(_ bookmark: Bookmark) {
420 move(bookmark: bookmark)
424 extension ExternalBrowserWindowController: WebFrameLoadDelegate, WebPolicyDelegate {
426 @objc func updateContentVisibleRect(_ timer: Timer) {
428 guard let item = timer.userInfo as? Bookmark else {
433 contentVisibleRect = item.contentVisibleRect
436 func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
438 if let waitingBookmarkItem = waitingBookmarkItem {
440 Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay,
442 selector: #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:)),
443 userInfo: waitingBookmarkItem,
446 waitingBookmarkItem = nil
449 func webView(_ webView: WebView!,
450 decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!,
451 request: URLRequest!,
453 decisionListener listener: WebPolicyDecisionListener!) {
455 if actionInformation?[WebActionNavigationTypeKey] as? WebNavigationType == .linkClicked {