From 736e7cd732b163a20d68aac59debb53ed3653bb8 Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Fri, 2 Dec 2022 17:04:07 +0100 Subject: [PATCH] feat: redesigned the settings view to work with light/dark mode (#1008) --- Kit/constants.swift | 4 +- Kit/module/module.swift | 27 ++-- Kit/module/settings.swift | 194 ++++++------------------- Stats/Views/Dashboard.swift | 12 +- Stats/Views/Settings.swift | 275 +++++++++++++++++++++--------------- 5 files changed, 227 insertions(+), 285 deletions(-) diff --git a/Kit/constants.swift b/Kit/constants.swift index 27a8e688..91cb1d86 100644 --- a/Kit/constants.swift +++ b/Kit/constants.swift @@ -21,8 +21,8 @@ public struct Popup_c_s { } public struct Settings_c_s { - public let width: CGFloat = 539 - public let height: CGFloat = 479 + public let width: CGFloat = 540 + public let height: CGFloat = 480 public let margin: CGFloat = 10 public let row: CGFloat = 30 } diff --git a/Kit/module/module.swift b/Kit/module/module.swift index 3373d11c..54aaacc2 100644 --- a/Kit/module/module.swift +++ b/Kit/module/module.swift @@ -131,13 +131,6 @@ open class Module: Module_p { moduleSettings: self.settingsView, popupSettings: self.popupView ) - self.settings?.toggleCallback = { [weak self] in - self?.toggleEnabled() - if self?.pauseState == true { - self?.pauseState = false - NotificationCenter.default.post(name: .pause, object: nil, userInfo: ["state": false]) - } - } self.popup = PopupWindow(title: self.config.name, view: self.popupView, visibilityCallback: self.visibilityCallback) } @@ -208,15 +201,6 @@ open class Module: Module_p { debug("Module disabled", log: self.log) } - // toggle module state - private func toggleEnabled() { - if self.enabled { - self.disable() - } else { - self.enable() - } - } - // add reader to module. If module is enabled will fire a read function and start a reader public func addReader(_ reader: Reader_p) { self.readers.append(reader) @@ -320,8 +304,19 @@ open class Module: Module_p { } else if !state && self.enabled { self.disable() } + } else { + if self.enabled { + self.disable() + } else { + self.enable() + } } } + + if self.pauseState == true { + self.pauseState = false + NotificationCenter.default.post(name: .pause, object: nil, userInfo: ["state": false]) + } } } diff --git a/Kit/module/settings.swift b/Kit/module/settings.swift index 87b9536a..aacbbe8e 100644 --- a/Kit/module/settings.swift +++ b/Kit/module/settings.swift @@ -12,7 +12,6 @@ import Cocoa public protocol Settings_p: NSView { - var toggleCallback: () -> Void { get set } func setState(_ newState: Bool) } @@ -22,8 +21,6 @@ public protocol Settings_v: NSView { } open class Settings: NSStackView, Settings_p { - public var toggleCallback: () -> Void = {} - private var config: UnsafePointer private var widgets: [Widget] private var moduleSettings: Settings_v? @@ -35,14 +32,6 @@ open class Settings: NSStackView, Settings_p { private var enableControl: NSControl? - private let headerSeparator: NSView = { - let view: NSView = NSView() - view.heightAnchor.constraint(equalToConstant: 1).isActive = true - view.wantsLayer = true - view.layer?.backgroundColor = NSColor(hexString: "#d1d1d1").cgColor - - return view - }() private let noWidgetsView: EmptyView = EmptyView(msg: localizedString("No available widgets to configure")) private let noPopupSettingsView: EmptyView = EmptyView(msg: localizedString("No options to configure for the popup in this module")) @@ -61,136 +50,43 @@ open class Settings: NSStackView, Settings_p { self.moduleSettings = moduleSettings self.popupSettings = popupSettings - super.init(frame: NSRect(x: 0, y: 0, width: Constants.Settings.width, height: Constants.Settings.height)) - - NotificationCenter.default.addObserver(self, selector: #selector(externalModuleToggle), name: .toggleModule, object: nil) - - self.wantsLayer = true - self.appearance = NSAppearance(named: .aqua) - self.layer?.backgroundColor = NSColor(hexString: "#ececec").cgColor + super.init(frame: NSRect.zero) self.orientation = .vertical self.alignment = .width self.distribution = .fill - self.spacing = 0 - - self.addArrangedSubview(self.header(enabled)) - self.addArrangedSubview(self.headerSeparator) - self.addArrangedSubview(self.body()) - - self.addArrangedSubview(NSView()) - } - - deinit { - NotificationCenter.default.removeObserver(self) - } - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - parts - - private func header(_ enabled: Bool) -> NSStackView { - let view: NSStackView = NSStackView() - - view.orientation = .horizontal - view.distribution = .fillEqually - view.alignment = .centerY - view.distribution = .fillProportionally - view.spacing = 0 - view.edgeInsets = NSEdgeInsets( + self.spacing = Constants.Settings.margin + self.edgeInsets = NSEdgeInsets( top: Constants.Settings.margin, left: Constants.Settings.margin, bottom: Constants.Settings.margin, right: Constants.Settings.margin ) - let titleView = NSTextField() - titleView.isEditable = false - titleView.isSelectable = false - titleView.isBezeled = false - titleView.wantsLayer = true - titleView.textColor = .black - titleView.backgroundColor = .clear - titleView.canDrawSubviewsIntoLayer = true - titleView.alignment = .natural - titleView.font = NSFont.systemFont(ofSize: 18, weight: .light) - titleView.stringValue = localizedString(self.config.pointee.name) + let widgetSelector = WidgetSelectorView(module: self.config.pointee.name, widgets: self.widgets, stateCallback: self.loadWidget) - var toggleBtn: NSControl = NSControl() - if #available(OSX 10.15, *) { - let switchButton = NSSwitch() - switchButton.state = enabled ? .on : .off - switchButton.action = #selector(self.toggleEnable) - switchButton.target = self - - toggleBtn = switchButton - } else { - let button: NSButton = NSButton() - button.setButtonType(.switch) - button.state = enabled ? .on : .off - button.title = "" - button.action = #selector(self.toggleEnable) - button.isBordered = false - button.isTransparent = false - button.target = self - - toggleBtn = button - } - self.enableControl = toggleBtn - - view.addArrangedSubview(titleView) - view.addArrangedSubview(NSView()) - view.addArrangedSubview(toggleBtn) - - return view - } - - private func body() -> NSStackView { - let view: NSStackView = NSStackView() - - view.translatesAutoresizingMaskIntoConstraints = false - view.orientation = .vertical - view.edgeInsets = NSEdgeInsets( - top: Constants.Settings.margin, - left: Constants.Settings.margin, - bottom: Constants.Settings.margin, - right: Constants.Settings.margin - ) - view.spacing = Constants.Settings.margin - - view.addArrangedSubview(WidgetSelectorView(module: self.config.pointee.name, widgets: self.widgets, stateCallback: self.loadWidget)) - view.addArrangedSubview(self.settings()) - - return view - } - - // MARK: - views - - private func settings() -> NSView { - let view: NSTabView = NSTabView(frame: NSRect(x: 0, y: 0, - width: Constants.Settings.width - Constants.Settings.margin*2, - height: Constants.Settings.height - 40 - Constants.Widget.height - (Constants.Settings.margin*5) - )) - view.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true - view.heightAnchor.constraint(equalToConstant: view.frame.height).isActive = true - view.tabViewType = .topTabsBezelBorder - view.tabViewBorderType = .line + let tabView = NSTabView() + tabView.tabViewType = .topTabsBezelBorder + tabView.tabViewBorderType = .line let moduleTab: NSTabViewItem = NSTabViewItem() moduleTab.label = localizedString("Module settings") moduleTab.view = { - let view = ScrollableStackView(frame: view.frame) - self.moduleSettingsContainer = view.stackView + let container = NSStackView() + container.translatesAutoresizingMaskIntoConstraints = false + + let scrollView = ScrollableStackView() + self.moduleSettingsContainer = scrollView.stackView self.loadModuleSettings() - return view + + container.addArrangedSubview(scrollView) + return container }() let widgetTab: NSTabViewItem = NSTabViewItem() widgetTab.label = localizedString("Widget settings") widgetTab.view = { - let view = ScrollableStackView(frame: view.frame) + let view = ScrollableStackView(frame: tabView.frame) view.stackView.spacing = 0 self.widgetSettingsContainer = view.stackView self.loadWidgetSettings() @@ -200,34 +96,27 @@ open class Settings: NSStackView, Settings_p { let popupTab: NSTabViewItem = NSTabViewItem() popupTab.label = localizedString("Popup settings") popupTab.view = { - let view = ScrollableStackView(frame: view.frame) + let view = ScrollableStackView(frame: tabView.frame) view.stackView.spacing = 0 self.popupSettingsContainer = view.stackView self.loadPopupSettings() return view }() - view.addTabViewItem(moduleTab) - view.addTabViewItem(widgetTab) - view.addTabViewItem(popupTab) + tabView.addTabViewItem(moduleTab) + tabView.addTabViewItem(widgetTab) + tabView.addTabViewItem(popupTab) - return view + self.addArrangedSubview(widgetSelector) + self.addArrangedSubview(tabView) } - // MARK: - helpers - - @objc private func toggleEnable(_ sender: Any) { - self.toggleCallback() + deinit { + NotificationCenter.default.removeObserver(self) } - @objc private func externalModuleToggle(_ notification: Notification) { - if let name = notification.userInfo?["module"] as? String { - if name == self.config.pointee.name { - if let state = notification.userInfo?["state"] as? Bool { - toggleNSControlState(self.enableControl, state: state ? .on : .off) - } - } - } + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") } public func setState(_ newState: Bool) { @@ -249,7 +138,6 @@ open class Settings: NSStackView, Settings_p { self.moduleSettingsContainer?.addArrangedSubview(NSView()) } } - private func loadWidgetSettings() { self.widgetSettingsContainer?.subviews.forEach{ $0.removeFromSuperview() } let list = self.widgets.filter({ $0.isActive && $0.type != .label }) @@ -301,14 +189,7 @@ open class Settings: NSStackView, Settings_p { } @objc private func toggleOneView(_ sender: NSControl) { - var state: NSControl.StateValue? = nil - if #available(OSX 10.15, *) { - state = sender is NSSwitch ? (sender as! NSSwitch).state: nil - } else { - state = sender is NSButton ? (sender as! NSButton).state: nil - } - - self.oneViewState = state! == .on ? true : false + self.oneViewState = controlState(sender) NotificationCenter.default.post(name: .toggleOneView, object: nil, userInfo: ["module": self.config.pointee.name]) } } @@ -317,15 +198,26 @@ class WidgetSelectorView: NSStackView { private var module: String private var stateCallback: () -> Void = {} + private var background: NSVisualEffectView = { + let view = NSVisualEffectView(frame: NSRect.zero) + view.blendingMode = .withinWindow + if #available(macOS 10.14, *) { + view.material = .contentBackground + } else { + view.material = .popover + } + view.state = .active + return view + }() + public init(module: String, widgets: [Widget], stateCallback: @escaping () -> Void) { self.module = module self.stateCallback = stateCallback - super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0)) + super.init(frame: NSRect.zero) self.translatesAutoresizingMaskIntoConstraints = false self.wantsLayer = true - self.layer?.backgroundColor = .white self.layer?.cornerRadius = 3 self.edgeInsets = NSEdgeInsets( top: Constants.Settings.margin, @@ -375,6 +267,7 @@ class WidgetSelectorView: NSStackView { } self.addArrangedSubview(NSView()) + self.addSubview(self.background, positioned: .below, relativeTo: .none) NSLayoutConstraint.activate([ self.heightAnchor.constraint(equalToConstant: Constants.Widget.height + (Constants.Settings.margin*2)), @@ -387,6 +280,10 @@ class WidgetSelectorView: NSStackView { fatalError("init(coder:) has not been implemented") } + override func updateLayer() { + self.background.setFrameSize(self.frame.size) + } + override func mouseDown(with event: NSEvent) { let location = convert(event.locationInWindow, from: nil) guard let targetIdx = self.views.firstIndex(where: { $0.hitTest(location) != nil }), @@ -501,6 +398,7 @@ internal class WidgetPreview: NSStackView { self.layer?.cornerRadius = 2 self.layer?.borderColor = NSColor(hexString: "#dddddd").cgColor self.layer?.borderWidth = 1 + self.layer?.backgroundColor = NSColor.white.cgColor self.identifier = NSUserInterfaceItemIdentifier(rawValue: type.rawValue) self.toolTip = localizedString("Move widget", type.name()) diff --git a/Stats/Views/Dashboard.swift b/Stats/Views/Dashboard.swift index 3275a4d2..0c700a87 100644 --- a/Stats/Views/Dashboard.swift +++ b/Stats/Views/Dashboard.swift @@ -25,11 +25,9 @@ class Dashboard: NSScrollView { self.drawsBackground = false self.borderType = .noBorder + self.scrollerStyle = .overlay self.hasVerticalScroller = true self.hasHorizontalScroller = false - self.autohidesScrollers = true - self.horizontalScrollElasticity = .none - self.automaticallyAdjustsContentInsets = false NotificationCenter.default.addObserver(self, selector: #selector(windowOpens), name: .openModuleSettings, object: nil) @@ -56,8 +54,10 @@ class Dashboard: NSScrollView { grid.row(at: 2).height = specsView.frame.height self.documentView = grid - if let documentView = self.documentView { - documentView.scroll(NSPoint(x: 0, y: documentView.bounds.size.height)) + DispatchQueue.main.async { + if let documentView = self.documentView { + documentView.scroll(NSPoint(x: 0, y: documentView.bounds.size.height)) + } } } @@ -66,7 +66,7 @@ class Dashboard: NSScrollView { } private func versions() -> NSView { - let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: 280)) + let view: NSView = NSView(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: 220)) let h: CGFloat = 120+60+18 let container: NSGridView = NSGridView(frame: NSRect(x: 0, y: (view.frame.height-h)/2, width: self.frame.width, height: h)) diff --git a/Stats/Views/Settings.swift b/Stats/Views/Settings.swift index 77db6cbf..87d9ba1a 100644 --- a/Stats/Views/Settings.swift +++ b/Stats/Views/Settings.swift @@ -12,9 +12,21 @@ import Cocoa import Kit -class SettingsWindow: NSWindow, NSWindowDelegate { +public extension NSToolbarItem.Identifier { + static let toggleButton = NSToolbarItem.Identifier("toggleButton") +} + +class SettingsWindow: NSWindow, NSWindowDelegate, NSToolbarDelegate { static let size: CGSize = CGSize(width: 720, height: 480) - private let vc: SettingsView = SettingsView() + + private let mainView: MainView = MainView(frame: NSRect(x: 0, y: 0, width: 540, height: 480)) + private let sidebarView: SidebarView = SidebarView(frame: NSRect(x: 0, y: 0, width: 180, height: 480)) + + private var dashboard: NSView = Dashboard() + private var settings: ApplicationSettings = ApplicationSettings() + + private var toggleButton: NSControl? = nil + private var activeModuleName: String? = nil private var pauseState: Bool { Store.shared.bool(key: "pause", defaultValue: false) @@ -33,29 +45,59 @@ class SettingsWindow: NSWindow, NSWindowDelegate { defer: false ) - self.contentViewController = self.vc - self.titlebarAppearsTransparent = true - self.backgroundColor = .clear - self.center() - self.setIsVisible(false) + let sidebarViewController = NSSplitViewController() - let windowController = NSWindowController() - windowController.window = self - windowController.loadWindow() + let sidebarVC: NSViewController = NSViewController(nibName: nil, bundle: nil) + sidebarVC.view = self.sidebarView + let mainVC: NSViewController = NSViewController(nibName: nil, bundle: nil) + mainVC.view = self.mainView + + let sidebarItem = NSSplitViewItem(sidebarWithViewController: sidebarVC) + let contentItem = NSSplitViewItem(viewController: mainVC) + + sidebarItem.canCollapse = false + contentItem.canCollapse = false + + sidebarViewController.addSplitViewItem(sidebarItem) + sidebarViewController.addSplitViewItem(contentItem) let newToolbar = NSToolbar(identifier: "eu.exelban.Stats.Settings.Toolbar") newToolbar.allowsUserCustomization = false newToolbar.autosavesConfiguration = true newToolbar.displayMode = .default newToolbar.showsBaselineSeparator = true + newToolbar.delegate = self self.toolbar = newToolbar + self.contentViewController = sidebarViewController + self.titlebarAppearsTransparent = true + self.backgroundColor = .clear +// self.center() + self.setIsVisible(true) + let windowController = NSWindowController() + windowController.window = self + windowController.loadWindow() + + NSLayoutConstraint.activate([ + self.sidebarView.widthAnchor.constraint(equalToConstant: 180), + self.mainView.widthAnchor.constraint(equalToConstant: 540), + self.mainView.container.widthAnchor.constraint(equalToConstant: 540), + self.mainView.container.topAnchor.constraint(equalTo: (self.contentLayoutGuide as! NSLayoutGuide).topAnchor), + self.mainView.container.bottomAnchor.constraint(equalTo: (self.contentLayoutGuide as! NSLayoutGuide).bottomAnchor) + ]) + + NotificationCenter.default.addObserver(self, selector: #selector(menuCallback), name: .openModuleSettings, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(toggleSettingsHandler), name: .toggleSettings, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(externalModuleToggle), name: .toggleModule, object: nil) + + self.sidebarView.openMenu("Dashboard") } deinit { NotificationCenter.default.removeObserver(self, name: .toggleSettings, object: nil) + NotificationCenter.default.removeObserver(self, name: .openModuleSettings, object: nil) + NotificationCenter.default.removeObserver(self, name: .toggleModule, object: nil) } override func performKeyEquivalent(with event: NSEvent) -> Bool { @@ -68,10 +110,55 @@ class SettingsWindow: NSWindow, NSWindowDelegate { return true } } - return super.performKeyEquivalent(with: event) } + override func mouseUp(with: NSEvent) { + NotificationCenter.default.post(name: .clickInSettings, object: nil, userInfo: nil) + } + + func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? { + switch itemIdentifier { + case .toggleButton: + var toggleBtn: NSControl = NSControl() + if #available(OSX 10.15, *) { + let switchButton = NSSwitch() + switchButton.state = .on + switchButton.action = #selector(self.toggleEnable) + switchButton.target = self + toggleBtn = switchButton + } else { + let button: NSButton = NSButton() + button.setButtonType(.switch) + button.state = .on + button.title = "" + button.action = #selector(self.toggleEnable) + button.isBordered = false + button.isTransparent = false + button.target = self + toggleBtn = button + } + self.toggleButton = toggleBtn + + let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier) + toolbarItem.label = "Toggle the module" + toolbarItem.paletteLabel = "Toggle the module" + toolbarItem.toolTip = "Toggle the module" + toolbarItem.view = toggleBtn + + return toolbarItem + default: + return nil + } + } + + func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { + return [.flexibleSpace, .toggleButton] + } + func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { + return [.flexibleSpace, .toggleButton] + } + @objc private func toggleSettingsHandler(_ notification: Notification) { if !self.isVisible { self.setIsVisible(true) @@ -82,112 +169,102 @@ class SettingsWindow: NSWindow, NSWindowDelegate { } if let name = notification.userInfo?["module"] as? String { - self.vc.openMenu(name) + self.sidebarView.openMenu(name) } } - public func setModules() { - self.vc.setModules(modules) - if !self.pauseState && modules.filter({ $0.enabled != false && $0.available != false && !$0.menuBar.widgets.filter({ $0.isActive }).isEmpty }).isEmpty { - self.setIsVisible(true) - } - } - - public func openMenu(_ title: String) { - self.vc.openMenu(title) - } - - override func mouseUp(with: NSEvent) { - NotificationCenter.default.post(name: .clickInSettings, object: nil, userInfo: nil) - } -} - -private class SettingsView: NSSplitViewController { - private var modules: [Module] = [] - - private let split: NSSplitView = SplitView() - - private let sidebar: SidebarView = SidebarView(frame: NSRect(x: 0, y: 0, width: 180, height: 480)) - private let main: MainView = MainView(frame: NSRect(x: 0, y: 0, width: 540, height: 480)) - - private var dashboard: NSView = Dashboard() - private var settings: ApplicationSettings = ApplicationSettings() - - init() { - super.init(nibName: nil, bundle: nil) - self.splitView = self.split - - let sidebarVC: NSViewController = NSViewController(nibName: nil, bundle: nil) - sidebarVC.view = self.sidebar - let mainVC: NSViewController = NSViewController(nibName: nil, bundle: nil) - mainVC.view = self.main - - let sidebarItem = NSSplitViewItem(sidebarWithViewController: sidebarVC) - let contentItem = NSSplitViewItem(viewController: mainVC) - - self.addSplitViewItem(sidebarItem) - self.addSplitViewItem(contentItem) - - self.splitViewItems[0].canCollapse = false - - NotificationCenter.default.addObserver(self, selector: #selector(menuCallback), name: .openModuleSettings, object: nil) - - self.openMenu("Dashboard") - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public func openMenu(_ title: String) { - self.sidebar.openMenu(title) - } - - public func setModules(_ list: [Module]) { - self.sidebar.setModules(list) - self.modules = list - } - @objc private func menuCallback(_ notification: Notification) { if let title = notification.userInfo?["module"] as? String { var view: NSView = NSView() - if let detectedModule = self.modules.first(where: { $0.config.name == title }) { + if let detectedModule = modules.first(where: { $0.config.name == title }) { if let v = detectedModule.settings { view = v } + self.activeModuleName = detectedModule.config.name + toggleNSControlState(self.toggleButton, state: detectedModule.enabled ? .on : .off) + self.toggleButton?.isHidden = false } else if title == "Dashboard" { view = self.dashboard + self.toggleButton?.isHidden = true } else if title == "Settings" { self.settings.viewWillAppear() view = self.settings + self.toggleButton?.isHidden = true } - self.main.setView(view) - self.sidebar.openMenu(title) + self.title = localizedString(title) + + self.mainView.setView(view) + self.sidebarView.openMenu(title) } } + + @objc private func toggleEnable(_ sender: NSControl) { + guard let moduleName = self.activeModuleName else { return } + NotificationCenter.default.post(name: .toggleModule, object: nil, userInfo: ["module": moduleName, "state": controlState(sender)]) + } + + @objc private func externalModuleToggle(_ notification: Notification) { + if let name = notification.userInfo?["module"] as? String, name == self.activeModuleName { + if let state = notification.userInfo?["state"] as? Bool { + toggleNSControlState(self.toggleButton, state: state ? .on : .off) + } + } + } + + public func setModules() { + self.sidebarView.setModules(modules) + if !self.pauseState && modules.filter({ $0.enabled != false && $0.available != false && !$0.menuBar.widgets.filter({ $0.isActive }).isEmpty }).isEmpty { + self.setIsVisible(true) + } + self.sidebarView.openMenu("Network") + } } -private class SplitView: NSSplitView, NSSplitViewDelegate { - init() { +// MARK: - MainView + +private class MainView: NSView { + public let container: NSStackView + + override init(frame: NSRect) { + self.container = NSStackView(frame: NSRect(x: 0, y: 0, width: frame.width, height: frame.height)) + + let foreground = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: frame.width, height: frame.height)) + foreground.blendingMode = .withinWindow + if #available(macOS 10.14, *) { + foreground.material = .windowBackground + } else { + foreground.material = .popover + } + foreground.state = .active + super.init(frame: NSRect.zero) - self.isVertical = true - self.delegate = self + self.container.translatesAutoresizingMaskIntoConstraints = false - self.widthAnchor.constraint(equalToConstant: SettingsWindow.size.width).isActive = true - self.heightAnchor.constraint(equalToConstant: SettingsWindow.size.height).isActive = true + self.addSubview(foreground, positioned: .below, relativeTo: .none) + self.addSubview(self.container) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - override func cursorUpdate(with event: NSEvent) { - NSCursor.arrow.set() + public func setView(_ view: NSView) { + self.container.subviews.forEach{ $0.removeFromSuperview() } + self.container.addArrangedSubview(view) + + NSLayoutConstraint.activate([ + view.leftAnchor.constraint(equalTo: self.container.leftAnchor), + view.rightAnchor.constraint(equalTo: self.container.rightAnchor), + view.topAnchor.constraint(equalTo: self.container.topAnchor), + view.bottomAnchor.constraint(equalTo: self.container.bottomAnchor) + ]) } } +// MARK: - Sidebar + private class SidebarView: NSStackView { private let scrollView: ScrollableStackView @@ -433,31 +510,3 @@ private class MenuItem: NSView { self.active = false } } - -private class MainView: NSView { - override init(frame: NSRect) { - super.init(frame: frame) - - self.wantsLayer = true - - let foreground = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: frame.width, height: frame.height)) - foreground.blendingMode = .withinWindow - if #available(macOS 10.14, *) { - foreground.material = .windowBackground - } else { - foreground.material = .popover - } - foreground.state = .active - - self.addSubview(foreground, positioned: .below, relativeTo: .none) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public func setView(_ view: NSView) { - self.subviews.filter{ !($0 is NSVisualEffectView) }.forEach{ $0.removeFromSuperview() } - self.addSubview(view) - } -}