import Cocoa
import WebKit
-fileprivate extension Selector {
- static let addBookmark = #selector(ExternalBrowserWindowController.addBookmark(_:))
- static let showBookmark = #selector(ExternalBrowserWindowController.showBookmark(_:))
- static let selectBookmark = #selector(ExternalBrowserWindowController.selectBookmark(_:))
- static let reloadContent = #selector(ExternalBrowserWindowController.reloadContent(_:))
- static let updateContentVisibleRect = #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:))
-}
-
-class ExternalBrowserWindowController: NSWindowController {
- let managedObjectContext = BookmarkManager.shared().manageObjectContext
-
- deinit {
- webView.removeObserver(self, forKeyPath: "canGoBack")
- webView.removeObserver(self, forKeyPath: "canGoForward")
- }
+final class ExternalBrowserWindowController: NSWindowController {
+
+ @IBOutlet private var webView: WebView!
+ @IBOutlet private var goSegment: NSSegmentedControl!
+ @IBOutlet private var bookmarkListView: NSView!
- @IBOutlet var webView: WebView!
- @IBOutlet var goSegment: NSSegmentedControl!
- @IBOutlet var bookmarkListView: NSView!
+ private var canGoBackObservation: NSKeyValueObservation?
+ private var canGoForwardObservation: NSKeyValueObservation?
- override var windowNibName: String! {
- return "ExternalBrowserWindowController"
+ override var windowNibName: NSNib.Name {
+
+ return .nibName(instanceOf: self)
}
- dynamic var canResize: Bool = true {
+
+ @objc dynamic var canResize: Bool = true {
+
willSet {
- guard let window = window else { return }
- if canResize == newValue { return }
- var style = window.styleMask.rawValue
+
+ if canResize == newValue {
+
+ return
+ }
+
if newValue {
- style |= NSResizableWindowMask.rawValue
+
+ window?.styleMask.insert(.resizable)
+
} else {
- style &= ~NSResizableWindowMask.rawValue
+
+ window?.styleMask.remove(.resizable)
}
- window.styleMask = NSWindowStyleMask(rawValue: style)
}
}
- dynamic var canScroll: Bool = true {
+
+ @objc dynamic var canScroll: Bool = true {
+
willSet {
- guard let webView = webView else { return }
- if canScroll == newValue { return }
- if newValue {
- webView.mainFrame.frameView.allowsScrolling = true
- } else {
- webView.mainFrame.frameView.allowsScrolling = false
+
+ if canScroll == newValue {
+
+ return
}
+
+ webView?.mainFrame.frameView.allowsScrolling = newValue
}
}
- dynamic var canMovePage: Bool = true
+ @objc dynamic var canMovePage: Bool = true
var urlString: String? {
+
return webView.mainFrameURL
}
+
var windowContentSize: NSSize {
+
get {
- guard let window = window else { return .zero }
+
+ guard let window = window else {
+
+ return .zero
+ }
+
return window.contentRect(forFrameRect: window.frame).size
}
set {
- guard let window = window else { return }
+
+ guard let window = window else {
+
+ return
+ }
+
var contentRect: NSRect = .zero
contentRect.size = newValue
var newFrame = window.frameRect(forContentRect: contentRect)
let frame = window.frame
- newFrame.origin.x = NSMinX(frame)
- newFrame.origin.y = NSMaxY(frame) - NSHeight(newFrame)
+ newFrame.origin.x = frame.minX
+ newFrame.origin.y = frame.maxY - newFrame.height
window.setFrame(newFrame, display: true)
}
}
+
var contentVisibleRect: NSRect {
- get {
- return webView.mainFrame.frameView.documentView.visibleRect
- }
- set {
- webView.mainFrame.frameView.documentView.scrollToVisible(newValue)
- }
+
+ get { return webView.mainFrame.frameView.documentView.visibleRect }
+ set { webView.mainFrame.frameView.documentView.scrollToVisible(newValue) }
}
- fileprivate var bookmarkShowing: Bool = false
- fileprivate var waitingBookmarkItem: Bookmark?
+ private var bookmarkShowing: Bool = false
+ private var waitingBookmarkItem: Bookmark?
- private lazy var bookmarkListViwController: BookmarkListViewController? = {
- [weak self] in
- guard let `self` = self else { return nil }
+ private lazy var bookmarkListViwController: BookmarkListViewController? = { [weak self] in
+
+ guard let `self` = self else {
+
+ return nil
+ }
+
let controller = BookmarkListViewController()
self.bookmarkListView = controller.view
controller.delegate = self
}()
override func windowDidLoad() {
+
super.windowDidLoad()
- webView.addObserver(self, forKeyPath: "canGoBack", context: nil)
- webView.addObserver(self, forKeyPath: "canGoForward", context: nil)
- webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
- webView.frameLoadDelegate = self
- }
- override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
- if keyPath == "canGoBack" {
- goSegment.setEnabled(webView.canGoBack, forSegment: 0)
- return
- }
- if keyPath == "canGoForward" {
- goSegment.setEnabled(webView.canGoForward, forSegment: 1)
- return
+ canGoBackObservation = webView.observe(\WebView.canGoBack) { [weak self] _, _ in
+
+ guard let `self` = self else {
+
+ return
+ }
+
+ self.goSegment.setEnabled(self.webView.canGoBack, forSegment: 0)
}
-
- super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
- }
- override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
- guard let action = menuItem.action else { return false }
- switch action {
- case Selector.addBookmark:
- return webView.mainFrameURL != nil
- case Selector.showBookmark:
- if showsBookmarkList() {
- menuItem.title = NSLocalizedString("Hide Bookmark", comment: "Menu item title, Hide Bookmark")
- } else {
- menuItem.title = NSLocalizedString("Show Bookmark", comment: "Menu item title, Show Bookmark")
+ canGoForwardObservation = webView.observe(\WebView.canGoForward) { [weak self] _, _ in
+
+ guard let `self` = self else {
+
+ return
}
- return true
- case Selector.selectBookmark:
- return true
- case Selector.reloadContent:
- return true
- default:
- return false
+
+ self.goSegment.setEnabled(self.webView.canGoForward, forSegment: 1)
}
+
+ webView.applicationNameForUserAgent = AppDelegate.shared.appNameForUserAgent
+ webView.frameLoadDelegate = self
}
+
override func swipe(with event: NSEvent) {
+
if event.deltaX > 0 && showsBookmarkList() {
+
showBookmark(nil)
}
+
if event.deltaX < 0 && !showsBookmarkList() {
+
showBookmark(nil)
}
}
- fileprivate func move(bookmark: Bookmark) {
+ private func move(bookmark: Bookmark) {
+
if !canMovePage {
+
AppDelegate.shared.createNewBrowser().move(bookmark: bookmark)
+
return
}
canScroll = bookmark.canScroll
waitingBookmarkItem = bookmark
}
- fileprivate func showsBookmarkList() -> Bool {
+
+ private func showsBookmarkList() -> Bool {
+
return webView.frame.origin.x > 0
}
+}
+
+extension ExternalBrowserWindowController: NSWindowDelegate {
+
+ func windowWillClose(_ notification: Notification) {
+
+ webView.policyDelegate = nil
+ webView.uiDelegate = nil
+ webView.downloadDelegate = nil
+ webView.frameLoadDelegate = nil
+ }
+}
+
+// MARK: - IBAction
+extension ExternalBrowserWindowController {
+
+ override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+
+ guard let action = menuItem.action else {
+
+ return false
+ }
+
+ switch action {
+
+ case #selector(ExternalBrowserWindowController.addBookmark(_:)):
+
+ return webView.mainFrameURL != nil
+
+ case #selector(ExternalBrowserWindowController.showBookmark(_:)):
+
+ if showsBookmarkList() {
+
+ menuItem.title = LocalizedStrings.hideBookmark.string
+
+ } else {
+
+ menuItem.title = LocalizedStrings.showBookmark.string
+ }
+
+ return true
+
+ case #selector(ExternalBrowserWindowController.selectBookmark(_:)):
+
+ return true
+
+ case #selector(ExternalBrowserWindowController.reloadContent(_:)):
+
+ return true
+
+ default:
+
+ return false
+
+ }
+ }
- // MARK: - IBAction
@IBAction func selectBookmark(_ sender: AnyObject?) {
- guard let item = sender?.representedObject as? Bookmark
- else { return }
+
+ guard let item = sender?.representedObject as? Bookmark else {
+
+ return
+ }
+
move(bookmark: item)
}
+
@IBAction func reloadContent(_ sender: AnyObject?) {
+
webView.reload(nil)
}
+
@IBAction func goHome(_ sender: AnyObject?) {
+
webView.mainFrameURL = "http://www.dmm.com/"
}
+
@IBAction func clickGoBackSegment(_ sender: AnyObject?) {
- guard let cell = goSegment.cell as? NSSegmentedCell
- else { return }
+
+ guard let cell = goSegment.cell as? NSSegmentedCell else {
+
+ return
+ }
+
let tag = cell.tag(forSegment: cell.selectedSegment)
switch tag {
- case 0:
- webView.goBack(nil)
- case 1:
- webView.goForward(nil)
- default:
- break
+
+ case 0: webView.goBack(nil)
+
+ case 1: webView.goForward(nil)
+
+ default: break
+
}
}
+
@IBAction func addBookmark(_ sender: AnyObject?) {
- guard let window = window,
- let bookmark = BookmarkManager.shared().createNewBookmark()
- else { return }
- bookmark.name = window.title
- bookmark.urlString = webView.mainFrameURL
- bookmark.windowContentSize = windowContentSize
- bookmark.contentVisibleRect = contentVisibleRect
- bookmark.canResize = canResize
- bookmark.canScroll = canScroll
- bookmark.scrollDelay = 0.5
+
+ guard let window = window else {
+
+ return
+ }
+ _ = BookmarkManager.shared.createNewBookmark { bookmark in
+
+ bookmark.name = window.title
+ bookmark.urlString = self.webView.mainFrameURL
+ bookmark.windowContentSize = self.windowContentSize
+ bookmark.contentVisibleRect = self.contentVisibleRect
+ bookmark.canResize = self.canResize
+ bookmark.canScroll = self.canScroll
+ bookmark.scrollDelay = 0.5
+
+ return true
+ }
}
+
@IBAction func showBookmark(_ sender: AnyObject?) {
- guard let window = window,
- let _ = bookmarkListViwController,
- !bookmarkShowing
- else { return }
+
+ guard let window = window else {
+
+ return
+ }
+ guard let _ = bookmarkListViwController else {
+
+ return
+ }
+ guard !bookmarkShowing else {
+
+ return
+ }
+
bookmarkShowing = true
var frame = bookmarkListView.frame
var newFrame = webView.frame
if showsBookmarkList() {
+
frame.origin.x = -200
newFrame.origin.x = 0
newFrame.size.width = window.frame.size.width
+
} else {
+
frame.origin.x = 0
newFrame.origin.x = 200
newFrame.size.width = window.frame.size.width - 200
}
- let webAnime: [String : Any] = [
- NSViewAnimationTargetKey: webView,
- NSViewAnimationEndFrameKey: NSValue(rect: newFrame)
- ]
- let bookmarkAnime: [String : Any] = [
- NSViewAnimationTargetKey: bookmarkListView,
- NSViewAnimationEndFrameKey: NSValue(rect: frame)
- ]
- let anime = NSViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
- anime.delegate = self
- anime.start()
+ let webAnime = ViewAnimationAttributes(target: webView, endFrame: newFrame)
+ let bookmarkAnime = ViewAnimationAttributes(target: bookmarkListView, endFrame: frame)
+
+ let anime = ViewAnimation(viewAnimations: [webAnime, bookmarkAnime])
+ anime.start { [weak self] in
+
+ self?.bookmarkShowing = false
+ }
}
+
@IBAction func scrollLeft(_ sender: AnyObject?) {
+
var rect = contentVisibleRect
rect.origin.x += 1
contentVisibleRect = rect
}
+
@IBAction func scrollRight(_ sender: AnyObject?) {
+
var rect = contentVisibleRect
rect.origin.x -= 1
contentVisibleRect = rect
}
+
@IBAction func scrollUp(_ sender: AnyObject?) {
+
var rect = contentVisibleRect
rect.origin.y += 1
contentVisibleRect = rect
}
+
@IBAction func scrollDown(_ sender: AnyObject?) {
+
var rect = contentVisibleRect
rect.origin.y -= 1
contentVisibleRect = rect
}
+
@IBAction func increaseWidth(_ sender: AnyObject?) {
- guard let window = window else { return }
+
+ guard let window = window else {
+
+ return
+ }
+
var frame = window.frame
frame.size.width += 1
window.setFrame(frame, display: true)
}
+
@IBAction func decreaseWidth(_ sender: AnyObject?) {
- guard let window = window else { return }
+
+ guard let window = window else {
+
+ return
+ }
+
var frame = window.frame
frame.size.width -= 1
window.setFrame(frame, display: true)
}
+
@IBAction func increaseHeight(_ sender: AnyObject?) {
- guard let window = window else { return }
+
+ guard let window = window else {
+
+ return
+ }
+
var frame = window.frame
frame.size.height += 1
frame.origin.y -= 1
window.setFrame(frame, display: true)
}
+
@IBAction func decreaseHeight(_ sender: AnyObject?) {
- guard let window = window else { return }
+
+ guard let window = window else {
+
+ return
+ }
+
var frame = window.frame
frame.size.height -= 1
frame.origin.y += 1
}
extension ExternalBrowserWindowController: BookmarkListViewControllerDelegate {
+
func didSelectBookmark(_ bookmark: Bookmark) {
+
move(bookmark: bookmark)
}
}
-extension ExternalBrowserWindowController: NSAnimationDelegate {
- func animationDidEnd(_ animation: NSAnimation) {
- bookmarkShowing = false
- }
-}
-
extension ExternalBrowserWindowController: WebFrameLoadDelegate, WebPolicyDelegate {
- func updateContentVisibleRect(_ timer: Timer) {
- guard let item = timer.userInfo as? Bookmark else { return }
+ @objc func updateContentVisibleRect(_ timer: Timer) {
+
+ guard let item = timer.userInfo as? Bookmark else {
+
+ return
+ }
+
contentVisibleRect = item.contentVisibleRect
}
+
func webView(_ sender: WebView!, didFinishLoadFor frame: WebFrame!) {
+
if let waitingBookmarkItem = waitingBookmarkItem {
- Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay, target: self, selector: .updateContentVisibleRect, userInfo: waitingBookmarkItem, repeats: false)
+
+ Timer.scheduledTimer(timeInterval: waitingBookmarkItem.scrollDelay,
+ target: self,
+ selector: #selector(ExternalBrowserWindowController.updateContentVisibleRect(_:)),
+ userInfo: waitingBookmarkItem,
+ repeats: false)
}
waitingBookmarkItem = nil
}
- func webView(_ webView: WebView!, decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!, request: URLRequest!, frame: WebFrame!, decisionListener listener: WebPolicyDecisionListener!) {
+
+ func webView(_ webView: WebView!,
+ decidePolicyForNavigationAction actionInformation: [AnyHashable: Any]!,
+ request: URLRequest!,
+ frame: WebFrame!,
+ decisionListener listener: WebPolicyDecisionListener!) {
+
if actionInformation?[WebActionNavigationTypeKey] as? WebNavigationType == .linkClicked {
+
if canMovePage {
+
listener.use()
}
+
return
}
+
listener.use()
}
}
-