Gemini/Gemini/BrowserWindowController.swift

166 lines
5.4 KiB
Swift

//
// BrowserWindowController.swift
// Gemini
//
// Created by Shadowfacts on 7/15/20.
//
import Cocoa
import SwiftUI
import Combine
import BrowserCore
class BrowserWindowController: NSWindowController {
@IBOutlet weak var toolbar: NSToolbar!
private var locationTextField: NSTextField?
private var urlUpdater: Cancellable?
let navigator = NavigationManager(url: AppDelegate.homePage)
convenience init() {
self.init(windowNibName: "BrowserWindowController")
}
override func windowDidLoad() {
super.windowDidLoad()
contentViewController = NSHostingController(rootView: ContentView(navigator: navigator))
urlUpdater = navigator.$currentURL.sink(receiveValue: self.currentURLChanged(_:))
}
private func currentURLChanged(_ newValue: URL) {
locationTextField?.stringValue = newValue.absoluteString
window?.title = newValue.absoluteString
}
override func newWindowForTab(_ sender: Any?) {
(NSApp.delegate as! AppDelegate).createNewWindowTab(attachedTo: window!)
}
}
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)
if #available(macOS 10.16, *) {
item.image = NSImage(systemSymbolName: "chevron.left", accessibilityDescription: "Go Back")
} else {
item.image = NSImage(named: NSImage.goBackTemplateName)
}
item.label = "Go Back"
item.paletteLabel = "Go Back"
item.toolTip = "Go to the previous page"
item.target = navigator
item.action = #selector(NavigationManager.back)
item.isBordered = true
if #available(macOS 10.16, *) {
item.isNavigational = true
}
return item
}
private func createForwardToolbarItem() -> NSToolbarItem {
let item = NSToolbarItem(itemIdentifier: .goForward)
if #available(macOS 10.16, *) {
item.image = NSImage(systemSymbolName: "chevron.right", accessibilityDescription: "Go Forward")
} else {
item.image = NSImage(named: NSImage.goForwardTemplateName)
}
item.label = "Go Forward"
item.paletteLabel = "Go Forward"
item.toolTip = "Go to the next page"
item.target = navigator
item.action = #selector(NavigationManager.forward)
item.isBordered = true
if #available(macOS 10.16, *) {
item.isNavigational = true
}
return item
}
}
extension NavigationManager: NSToolbarItemValidation {
public func validateToolbarItem(_ item: NSToolbarItem) -> Bool {
if item.itemIdentifier == .goBack {
return !backStack.isEmpty
} else if item.itemIdentifier == .goForward {
return !forwardStack.isEmpty
} 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)
}
}