2020-07-15 22:30:12 +00:00
|
|
|
//
|
|
|
|
// BrowserWindowController.swift
|
|
|
|
// Gemini
|
|
|
|
//
|
|
|
|
// Created by Shadowfacts on 7/15/20.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Cocoa
|
|
|
|
import SwiftUI
|
|
|
|
import Combine
|
2020-07-16 03:45:37 +00:00
|
|
|
import BrowserCore
|
2020-07-15 22:30:12 +00:00
|
|
|
|
|
|
|
class BrowserWindowController: NSWindowController {
|
|
|
|
|
|
|
|
@IBOutlet weak var toolbar: NSToolbar!
|
|
|
|
|
|
|
|
private var locationTextField: NSTextField?
|
|
|
|
|
2020-07-16 03:09:42 +00:00
|
|
|
private var urlUpdater: Cancellable?
|
|
|
|
|
|
|
|
let navigator = NavigationManager(url: AppDelegate.homePage)
|
2020-07-15 22:30:12 +00:00
|
|
|
|
|
|
|
convenience init() {
|
|
|
|
self.init(windowNibName: "BrowserWindowController")
|
|
|
|
}
|
|
|
|
|
|
|
|
override func windowDidLoad() {
|
|
|
|
super.windowDidLoad()
|
|
|
|
|
2020-07-22 22:25:56 +00:00
|
|
|
contentViewController = NSHostingController(rootView: ContentView(navigator: navigator))
|
2020-07-15 22:30:12 +00:00
|
|
|
|
2020-07-23 13:18:59 +00:00
|
|
|
urlUpdater = navigator.$currentURL.receive(on: DispatchQueue.main).sink(receiveValue: self.currentURLChanged(_:))
|
2020-07-15 22:30:12 +00:00
|
|
|
}
|
|
|
|
|
2020-07-16 03:09:42 +00:00
|
|
|
private func currentURLChanged(_ newValue: URL) {
|
2020-07-15 22:30:12 +00:00
|
|
|
locationTextField?.stringValue = newValue.absoluteString
|
2020-07-16 03:09:42 +00:00
|
|
|
|
|
|
|
window?.title = newValue.absoluteString
|
|
|
|
}
|
|
|
|
|
|
|
|
override func newWindowForTab(_ sender: Any?) {
|
|
|
|
(NSApp.delegate as! AppDelegate).createNewWindowTab(attachedTo: window!)
|
2020-07-15 22:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
extension NSToolbarItem.Identifier {
|
|
|
|
static let locationField = NSToolbarItem.Identifier("Gemini.locationField")
|
|
|
|
static let goBack = NSToolbarItem.Identifier("Gemini.goBack")
|
|
|
|
static let goForward = NSToolbarItem.Identifier("Gemini.goForward")
|
|
|
|
}
|
|
|
|
|
|
|
|
extension BrowserWindowController: NSToolbarDelegate {
|
|
|
|
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
|
|
|
return [
|
|
|
|
.space,
|
|
|
|
.flexibleSpace,
|
|
|
|
.locationField,
|
|
|
|
.goBack,
|
|
|
|
.goForward
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
|
|
|
return [
|
|
|
|
.goBack,
|
|
|
|
.goForward,
|
|
|
|
.flexibleSpace,
|
|
|
|
.locationField,
|
|
|
|
.flexibleSpace,
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
|
|
|
|
if itemIdentifier == .locationField {
|
|
|
|
return createLocationFieldToolbarItem()
|
|
|
|
} else if itemIdentifier == .goBack {
|
|
|
|
return createBackToolbarItem()
|
|
|
|
} else if itemIdentifier == .goForward {
|
|
|
|
return createForwardToolbarItem()
|
|
|
|
}
|
|
|
|
return NSToolbarItem(itemIdentifier: itemIdentifier)
|
|
|
|
}
|
|
|
|
|
|
|
|
private func createLocationFieldToolbarItem() -> NSToolbarItem {
|
|
|
|
let item = NSToolbarItem(itemIdentifier: .locationField)
|
|
|
|
item.label = "Location"
|
|
|
|
item.paletteLabel = "Location"
|
|
|
|
let textField = NSTextField(string: navigator.currentURL.absoluteString)
|
|
|
|
textField.delegate = self
|
|
|
|
NSLayoutConstraint.activate([
|
|
|
|
textField.heightAnchor.constraint(equalToConstant: 22),
|
|
|
|
textField.widthAnchor.constraint(lessThanOrEqualToConstant: 500),
|
|
|
|
textField.widthAnchor.constraint(greaterThanOrEqualToConstant: 250)
|
|
|
|
])
|
|
|
|
locationTextField = textField
|
|
|
|
item.view = textField
|
|
|
|
return item
|
|
|
|
}
|
|
|
|
|
|
|
|
private func createBackToolbarItem() -> NSToolbarItem {
|
|
|
|
let item = NSToolbarItem(itemIdentifier: .goBack)
|
2020-07-16 03:12:01 +00:00
|
|
|
if #available(macOS 10.16, *) {
|
|
|
|
item.image = NSImage(systemSymbolName: "chevron.left", accessibilityDescription: "Go Back")
|
|
|
|
} else {
|
|
|
|
item.image = NSImage(named: NSImage.goBackTemplateName)
|
|
|
|
}
|
2020-07-15 22:30:12 +00:00
|
|
|
item.label = "Go Back"
|
|
|
|
item.paletteLabel = "Go Back"
|
|
|
|
item.toolTip = "Go to the previous page"
|
2020-09-30 21:59:52 +00:00
|
|
|
item.target = self
|
|
|
|
item.action = #selector(back)
|
2020-07-15 22:30:12 +00:00
|
|
|
item.isBordered = true
|
|
|
|
if #available(macOS 10.16, *) {
|
|
|
|
item.isNavigational = true
|
|
|
|
}
|
|
|
|
return item
|
|
|
|
}
|
|
|
|
|
|
|
|
private func createForwardToolbarItem() -> NSToolbarItem {
|
|
|
|
let item = NSToolbarItem(itemIdentifier: .goForward)
|
2020-07-16 03:12:01 +00:00
|
|
|
if #available(macOS 10.16, *) {
|
|
|
|
item.image = NSImage(systemSymbolName: "chevron.right", accessibilityDescription: "Go Forward")
|
|
|
|
} else {
|
|
|
|
item.image = NSImage(named: NSImage.goForwardTemplateName)
|
|
|
|
}
|
2020-07-15 22:30:12 +00:00
|
|
|
item.label = "Go Forward"
|
|
|
|
item.paletteLabel = "Go Forward"
|
|
|
|
item.toolTip = "Go to the next page"
|
2020-09-30 21:59:52 +00:00
|
|
|
item.target = self
|
|
|
|
item.action = #selector(forward)
|
2020-07-15 22:30:12 +00:00
|
|
|
item.isBordered = true
|
|
|
|
if #available(macOS 10.16, *) {
|
|
|
|
item.isNavigational = true
|
|
|
|
}
|
|
|
|
return item
|
|
|
|
}
|
|
|
|
|
2020-09-30 21:59:52 +00:00
|
|
|
@objc private func back() {
|
|
|
|
navigator.back()
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc private func forward() {
|
|
|
|
navigator.forward()
|
|
|
|
}
|
|
|
|
|
2020-07-15 22:30:12 +00:00
|
|
|
}
|
|
|
|
|
2020-09-30 21:59:52 +00:00
|
|
|
extension BrowserWindowController: NSToolbarItemValidation {
|
2020-07-16 03:45:37 +00:00
|
|
|
public func validateToolbarItem(_ item: NSToolbarItem) -> Bool {
|
2020-07-15 22:30:12 +00:00
|
|
|
if item.itemIdentifier == .goBack {
|
2020-09-30 21:59:52 +00:00
|
|
|
return !navigator.backStack.isEmpty
|
2020-07-15 22:30:12 +00:00
|
|
|
} else if item.itemIdentifier == .goForward {
|
2020-09-30 21:59:52 +00:00
|
|
|
return !navigator.forwardStack.isEmpty
|
2020-07-15 22:30:12 +00:00
|
|
|
} else {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension BrowserWindowController: NSTextFieldDelegate {
|
|
|
|
func controlTextDidEndEditing(_ obj: Notification) {
|
|
|
|
guard let textField = locationTextField else { return }
|
|
|
|
guard let newURL = URL(string: textField.stringValue) else {
|
|
|
|
let alert = NSAlert()
|
|
|
|
alert.alertStyle = .warning
|
|
|
|
alert.messageText = "You specified a malformed URL"
|
|
|
|
alert.addButton(withTitle: "OK")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
navigator.changeURL(newURL)
|
|
|
|
}
|
|
|
|
}
|