feat: moved all modules settings to the new design

This commit is contained in:
Serhiy Mytrovtsiy
2024-04-24 06:10:27 +02:00
parent ab4dcbfd94
commit f873fdaa3d
36 changed files with 901 additions and 1131 deletions

View File

@@ -305,130 +305,6 @@ public extension NSView {
return view
}
func selectSettingsRowV1(title: String, action: Selector, items: [String], selected: String) -> NSView {
let view = NSStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.heightAnchor.constraint(equalToConstant: Constants.Settings.row).isActive = true
view.orientation = .horizontal
view.alignment = .centerY
view.distribution = .fill
view.spacing = 0
let titleField: NSTextField = LabelField(frame: NSRect(x: 0, y: 0, width: 0, height: 0), title)
titleField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
titleField.textColor = .textColor
let select: NSPopUpButton = NSPopUpButton()
select.target = self
select.action = action
let menu = NSMenu()
items.forEach { (color: String) in
if color.contains("separator") {
menu.addItem(NSMenuItem.separator())
} else {
let interfaceMenu = NSMenuItem(title: color, action: nil, keyEquivalent: "")
menu.addItem(interfaceMenu)
if selected == color {
interfaceMenu.state = .on
}
}
}
select.menu = menu
select.sizeToFit()
view.addArrangedSubview(titleField)
view.addArrangedSubview(NSView())
view.addArrangedSubview(select)
return view
}
func fieldSettingRow(_ sender: NSTextFieldDelegate, title: String, value: String, placeholder: String? = nil, width: CGFloat = 215) -> NSView {
let view: NSStackView = NSStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.heightAnchor.constraint(equalToConstant: Constants.Settings.row).isActive = true
view.orientation = .horizontal
view.alignment = .centerY
view.distribution = .fill
view.spacing = 0
let titleField: NSTextField = LabelField(frame: NSRect.zero, title)
titleField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
titleField.textColor = .textColor
let valueField: NSTextField = NSTextField()
valueField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
valueField.textColor = .textColor
valueField.isEditable = true
valueField.isSelectable = true
valueField.isBezeled = false
valueField.wantsLayer = true
valueField.canDrawSubviewsIntoLayer = true
valueField.usesSingleLineMode = true
valueField.maximumNumberOfLines = 1
valueField.focusRingType = .none
valueField.stringValue = value
valueField.delegate = sender
if let placeholder {
valueField.placeholderString = placeholder
}
valueField.alignment = .natural
view.addArrangedSubview(titleField)
view.addArrangedSubview(NSView())
view.addArrangedSubview(valueField)
valueField.widthAnchor.constraint(equalToConstant: width).isActive = true
return view
}
func sliderSettingsRow(title: String, action: Selector, value: Int, initialValue: String, isHidden: Bool = false, min: Double = 1, max: Double = 100) -> NSView {
let view: NSStackView = NSStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.heightAnchor.constraint(equalToConstant: Constants.Settings.row * 1.2).isActive = true
view.orientation = .horizontal
view.alignment = .centerY
view.distribution = .fill
view.spacing = 0
view.isHidden = isHidden
let titleField: NSTextField = LabelField(frame: NSRect(x: 0, y: 0, width: 0, height: 0), title)
titleField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
titleField.textColor = .textColor
let container: NSView = NSView()
container.identifier = NSUserInterfaceItemIdentifier("container")
let valueField: NSTextField = LabelField(frame: NSRect(x: 0, y: 21, width: 195, height: 15), initialValue)
valueField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
valueField.textColor = .textColor
valueField.alignment = .center
let slider = NSSlider(frame: NSRect(x: 0, y: -5, width: 195, height: 0))
slider.minValue = min
slider.maxValue = max
slider.intValue = Int32(value)
slider.target = self
slider.isContinuous = true
slider.action = action
slider.sizeToFit()
container.addSubview(valueField)
container.addSubview(slider)
view.addArrangedSubview(titleField)
view.addArrangedSubview(NSView())
view.addArrangedSubview(container)
container.widthAnchor.constraint(equalToConstant: 195).isActive = true
container.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
return view
}
func selectView(action: Selector, items: [KeyValue_p], selected: String) -> NSPopUpButton {
let select: NSPopUpButton = NSPopUpButton(frame: NSRect(x: 0, y: 0, width: 50, height: 28))
select.target = self
@@ -483,6 +359,33 @@ public extension NSView {
field.isSelectable = true
return field
}
func sliderView(action: Selector, value: Int, initialValue: String, min: Double = 1, max: Double = 100, valueWidth: CGFloat = 40) -> NSView {
let view: NSStackView = NSStackView()
view.orientation = .horizontal
view.widthAnchor.constraint(equalToConstant: 195).isActive = true
let valueField: NSTextField = LabelField(initialValue)
valueField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
valueField.textColor = .textColor
valueField.alignment = .center
valueField.widthAnchor.constraint(equalToConstant: valueWidth).isActive = true
let slider = NSSlider()
slider.controlSize = .small
slider.minValue = min
slider.maxValue = max
slider.intValue = Int32(value)
slider.target = self
slider.isContinuous = true
slider.action = action
slider.sizeToFit()
view.addArrangedSubview(slider)
view.addArrangedSubview(valueField)
return view
}
}
public class NSButtonWithPadding: NSButton {

View File

@@ -960,17 +960,9 @@ public func process(path: String, arguments: [String]) -> String? {
public class SettingsContainerView: NSStackView {
public init() {
super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
super.init(frame: NSRect.zero)
self.translatesAutoresizingMaskIntoConstraints = false
self.orientation = .vertical
self.distribution = .gravityAreas
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
}
@@ -1351,24 +1343,32 @@ var isDarkMode: Bool {
}
public class PreferencesSection: NSStackView {
public init(_ components: [PreferencesRow] = []) {
private let container: NSStackView = NSStackView()
public init(label: String = "", _ components: [PreferencesRow] = []) {
super.init(frame: .zero)
self.orientation = .vertical
self.spacing = 0
self.wantsLayer = true
self.layer?.cornerRadius = 5
self.layer?.borderColor = NSColor.separatorColor.withAlphaComponent(0.05).cgColor
self.layer?.borderWidth = 1
self.layer?.backgroundColor = NSColor.quaternaryLabelColor.withAlphaComponent(0.025).cgColor
if label != "" {
self.addLabel(label)
}
self.edgeInsets = NSEdgeInsets(
self.container.orientation = .vertical
self.container.wantsLayer = true
self.container.layer?.cornerRadius = 5
self.container.layer?.borderColor = NSColor.separatorColor.withAlphaComponent(0.05).cgColor
self.container.layer?.borderWidth = 1
self.container.layer?.backgroundColor = NSColor.quaternaryLabelColor.withAlphaComponent(0.025).cgColor
self.container.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin/2,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin/2,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin/2
self.container.spacing = Constants.Settings.margin/2
self.addArrangedSubview(self.container)
for item in components {
self.add(item)
@@ -1380,21 +1380,39 @@ public class PreferencesSection: NSStackView {
}
public override func updateLayer() {
self.layer?.borderColor = NSColor.separatorColor.withAlphaComponent(0.05).cgColor
self.layer?.backgroundColor = NSColor.quaternaryLabelColor.withAlphaComponent(0.025).cgColor
self.container.layer?.borderColor = NSColor.separatorColor.withAlphaComponent(0.05).cgColor
self.container.layer?.backgroundColor = NSColor.quaternaryLabelColor.withAlphaComponent(0.025).cgColor
}
public func add(_ view: NSView) {
if !self.subviews.isEmpty {
self.addArrangedSubview(PreferencesSeparator())
}
private func addLabel(_ value: String) {
let view = NSStackView()
view.heightAnchor.constraint(equalToConstant: 26).isActive = true
let space = NSView()
space.widthAnchor.constraint(equalToConstant: 4).isActive = true
let field: NSTextField = TextView()
field.font = NSFont.systemFont(ofSize: 12, weight: .semibold)
field.stringValue = value
view.addArrangedSubview(space)
view.addArrangedSubview(field)
view.addArrangedSubview(NSView())
self.addArrangedSubview(view)
}
public func add(_ view: NSView) {
if !self.container.subviews.isEmpty {
self.container.addArrangedSubview(PreferencesSeparator())
}
self.container.addArrangedSubview(view)
}
public func toggleVisibility(_ at: Int, newState: Bool) {
for i in self.subviews.indices where i/2 == at && Double(i).remainder(dividingBy: 2) == 0 {
self.subviews[i-1].isHidden = !newState
self.subviews[i].isHidden = !newState
for i in self.container.subviews.indices where i/2 == at && Double(i).remainder(dividingBy: 2) == 0 {
self.container.subviews[i-1].isHidden = !newState
self.container.subviews[i].isHidden = !newState
}
}
}
@@ -1417,22 +1435,16 @@ public class PreferencesSeparator: NSView {
}
public class PreferencesRow: NSStackView {
public init(_ title: String? = nil, component: NSView) {
public init(_ title: String? = nil, _ description: String? = nil, component: NSView) {
super.init(frame: .zero)
self.orientation = .horizontal
self.distribution = .fill
self.alignment = .top
self.edgeInsets = NSEdgeInsets(top: Constants.Settings.margin/2, left: 0, bottom: Constants.Settings.margin/2, right: 0)
self.alignment = .centerY
self.edgeInsets = NSEdgeInsets(top: Constants.Settings.margin/2, left: 0, bottom: (Constants.Settings.margin/2) - 1, right: 0)
self.spacing = 0
let field: NSTextField = TextView()
field.font = NSFont.systemFont(ofSize: 13, weight: .regular)
if let title {
field.stringValue = title
self.addArrangedSubview(field)
}
self.addArrangedSubview(self.text(title, description))
self.addArrangedSubview(NSView())
self.addArrangedSubview(component)
}
@@ -1440,4 +1452,38 @@ public class PreferencesRow: NSStackView {
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func text(_ title: String? = nil, _ description: String? = nil) -> NSView {
let view: NSStackView = NSStackView()
view.orientation = .vertical
view.spacing = 0
if let title {
let field: NSTextField = TextView()
field.font = NSFont.systemFont(ofSize: 12, weight: .regular)
field.stringValue = title
view.addArrangedSubview(field)
}
if let description {
let field: NSTextField = TextView()
field.font = NSFont.systemFont(ofSize: 12, weight: .regular)
field.textColor = .secondaryLabelColor
field.stringValue = description
view.addArrangedSubview(field)
view.addArrangedSubview(NSView())
view.alignment = .leading
}
return view
}
}
public func restartApp(_ sender: Any, afterDelay seconds: TimeInterval = 0.5) -> Never {
let task = Process()
task.launchPath = "/bin/sh"
task.arguments = ["-c", "sleep \(seconds); open \"\(Bundle.main.bundlePath)\""]
task.launch()
NSApp.terminate(sender)
exit(0)
}

View File

@@ -29,6 +29,7 @@ public struct module_c {
internal var availableWidgets: [widget_t] = []
internal var widgetsConfig: NSDictionary = NSDictionary()
internal var settingsConfig: NSDictionary = NSDictionary()
init(in path: String) {
let dict: NSDictionary = NSDictionary(contentsOfFile: path)!
@@ -67,6 +68,10 @@ public struct module_c {
self.availableWidgets = list.sorted(by: { $0.1 < $1.1 }).map{ (widget_t(rawValue: $0.key) ?? .unknown) }
}
if let settingsDict = dict["Settings"] as? NSDictionary {
self.settingsConfig = settingsDict
}
}
}

View File

@@ -25,12 +25,6 @@ open class NotificationsWrapper: NSStackView {
self.orientation = .vertical
self.distribution = .gravityAreas
self.translatesAutoresizingMaskIntoConstraints = false
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
}

View File

@@ -23,6 +23,10 @@ public protocol Settings_v: NSView {
open class Settings: NSStackView, Settings_p {
private var config: UnsafePointer<module_c>
private var widgets: [Widget]
private var segmentedControl: NSSegmentedControl?
private var tabView: NSTabView?
private var moduleSettings: Settings_v?
private var popupSettings: Popup_p?
private var notificationsSettings: NotificationsWrapper?
@@ -33,7 +37,7 @@ open class Settings: NSStackView, Settings_p {
private var notificationsSettingsContainer: NSStackView?
private var enableControl: NSControl?
private var oneViewRow: NSView?
private var oneViewBtn: NSSwitch?
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"))
@@ -51,6 +55,9 @@ open class Settings: NSStackView, Settings_p {
}
}
private var isPopupSettingsAvailable: Bool
private var isNotificationsSettingsAvailable: Bool
init(config: UnsafePointer<module_c>, widgets: UnsafeMutablePointer<[Widget]>, enabled: Bool, moduleSettings: Settings_v?, popupSettings: Popup_p?, notificationsSettings: NotificationsWrapper?) {
self.config = config
self.widgets = widgets.pointee
@@ -58,6 +65,9 @@ open class Settings: NSStackView, Settings_p {
self.popupSettings = popupSettings
self.notificationsSettings = notificationsSettings
self.isPopupSettingsAvailable = config.pointee.settingsConfig["popup"] as? Bool ?? false
self.isNotificationsSettingsAvailable = config.pointee.settingsConfig["notifications"] as? Bool ?? false
super.init(frame: NSRect.zero)
self.orientation = .vertical
@@ -72,10 +82,53 @@ open class Settings: NSStackView, Settings_p {
)
let widgetSelector = WidgetSelectorView(module: self.config.pointee.name, widgets: self.widgets, stateCallback: self.loadWidget)
let tabView = self.settingsView()
self.addArrangedSubview(widgetSelector)
self.addArrangedSubview(tabView)
NotificationCenter.default.addObserver(self, selector: #selector(listenForOneView), name: .toggleOneView, object: nil)
self.segmentedControl?.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -(Constants.Settings.margin*2)).isActive = true
}
deinit {
NotificationCenter.default.removeObserver(self, name: .toggleOneView, object: nil)
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func setState(_ newState: Bool) {
toggleNSControlState(self.enableControl, state: newState ? .on : .off)
}
private func settingsView() -> NSView {
let view = NSStackView()
view.orientation = .vertical
view.spacing = Constants.Settings.margin
var labels: [String] = [
localizedString("Module"),
localizedString("Widgets")
]
if self.isPopupSettingsAvailable {
labels.append(localizedString("Popup"))
}
if self.isNotificationsSettingsAvailable {
labels.append(localizedString("Notifications"))
}
let segmentedControl = NSSegmentedControl(labels: labels, trackingMode: .selectOne, target: self, action: #selector(self.switchTabs))
segmentedControl.segmentDistribution = .fillEqually
segmentedControl.selectSegment(withTag: 0)
self.segmentedControl = segmentedControl
let tabView = NSTabView()
tabView.tabViewType = .topTabsBezelBorder
tabView.tabViewBorderType = .line
tabView.tabViewType = .noTabsNoBorder
tabView.tabViewBorderType = .none
tabView.drawsBackground = false
self.tabView = tabView
let moduleTab: NSTabViewItem = NSTabViewItem()
moduleTab.label = localizedString("Module")
@@ -90,6 +143,7 @@ open class Settings: NSStackView, Settings_p {
container.addArrangedSubview(scrollView)
return container
}()
tabView.addTabViewItem(moduleTab)
let widgetTab: NSTabViewItem = NSTabViewItem()
widgetTab.label = localizedString("Widgets")
@@ -100,48 +154,38 @@ open class Settings: NSStackView, Settings_p {
self.loadWidgetSettings()
return view
}()
let popupTab: NSTabViewItem = NSTabViewItem()
popupTab.label = localizedString("Popup")
popupTab.view = {
let view = ScrollableStackView(frame: tabView.frame)
view.stackView.spacing = 0
self.popupSettingsContainer = view.stackView
self.loadPopupSettings()
return view
}()
let notificationsTab: NSTabViewItem = NSTabViewItem()
notificationsTab.label = localizedString("Notifications")
notificationsTab.view = {
let view = ScrollableStackView(frame: tabView.frame)
view.stackView.spacing = 0
self.notificationsSettingsContainer = view.stackView
self.loadNotificationsSettings()
return view
}()
tabView.addTabViewItem(moduleTab)
tabView.addTabViewItem(widgetTab)
tabView.addTabViewItem(popupTab)
tabView.addTabViewItem(notificationsTab)
self.addArrangedSubview(widgetSelector)
self.addArrangedSubview(tabView)
if self.isPopupSettingsAvailable {
let popupTab: NSTabViewItem = NSTabViewItem()
popupTab.label = localizedString("Popup")
popupTab.view = {
let view = ScrollableStackView(frame: tabView.frame)
view.stackView.spacing = 0
self.popupSettingsContainer = view.stackView
self.loadPopupSettings()
return view
}()
tabView.addTabViewItem(popupTab)
}
NotificationCenter.default.addObserver(self, selector: #selector(listenForOneView), name: .toggleOneView, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self, name: .toggleOneView, object: nil)
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func setState(_ newState: Bool) {
toggleNSControlState(self.enableControl, state: newState ? .on : .off)
if self.isNotificationsSettingsAvailable {
let notificationsTab: NSTabViewItem = NSTabViewItem()
notificationsTab.label = localizedString("Notifications")
notificationsTab.view = {
let view = ScrollableStackView(frame: tabView.frame)
view.stackView.spacing = 0
self.notificationsSettingsContainer = view.stackView
self.loadNotificationsSettings()
return view
}()
tabView.addTabViewItem(notificationsTab)
}
view.addArrangedSubview(segmentedControl)
view.addArrangedSubview(tabView)
return view
}
private func loadWidget() {
@@ -169,31 +213,14 @@ open class Settings: NSStackView, Settings_p {
}
if self.widgets.filter({ $0.isActive }).count > 1 {
let container = NSStackView()
container.orientation = .vertical
container.distribution = .gravityAreas
container.translatesAutoresizingMaskIntoConstraints = false
container.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
container.spacing = Constants.Settings.margin
let row = toggleSettingRow(
title: "\(localizedString("Merge widgets"))",
let btn = switchView(
action: #selector(self.toggleOneView),
state: self.oneViewState
)
container.addArrangedSubview(row)
findAndToggleEnableNSControlState(row, state: !self.globalOneView)
if self.globalOneView {
findAndToggleNSControlState(row, state: .on)
}
self.oneViewRow = row
self.widgetSettingsContainer?.addArrangedSubview(container)
self.oneViewBtn = btn
self.widgetSettingsContainer?.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Merge widgets"), component: btn)
]))
}
for i in 0...list.count - 1 {
@@ -225,6 +252,10 @@ open class Settings: NSStackView, Settings_p {
}
}
@objc func switchTabs(sender: NSSegmentedControl) {
self.tabView?.selectTabViewItem(at: sender.selectedSegment)
}
@objc private func toggleOneView(_ sender: NSControl) {
guard !self.globalOneView else { return }
self.oneViewState = controlState(sender)
@@ -233,10 +264,9 @@ open class Settings: NSStackView, Settings_p {
@objc private func listenForOneView(_ notification: Notification) {
guard notification.userInfo?["module"] == nil else { return }
findAndToggleEnableNSControlState(self.oneViewRow, state: !self.globalOneView)
self.oneViewBtn?.isEnabled = !self.globalOneView
if !self.globalOneView {
findAndToggleNSControlState(self.oneViewRow, state: self.oneViewState ? .on : .off)
self.oneViewBtn?.state = self.oneViewState ? .on : .off
}
}
}
@@ -527,20 +557,14 @@ internal class WidgetPreview: NSStackView {
internal class WidgetSettings: NSStackView {
public init(title: String, image: NSImage, settingsView: NSView) {
super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
super.init(frame: NSRect.zero)
self.translatesAutoresizingMaskIntoConstraints = false
self.orientation = .vertical
self.edgeInsets = NSEdgeInsets(
top: 0,
left: Constants.Settings.margin,
bottom: 0,
right: Constants.Settings.margin
)
self.spacing = 0
self.addArrangedSubview(self.header(title, image))
self.addArrangedSubview(self.settings(settingsView))
self.addArrangedSubview(settingsView)
}
required init?(coder: NSCoder) {
@@ -597,22 +621,4 @@ internal class WidgetSettings: NSStackView {
return container
}
private func settings(_ view: NSView) -> NSView {
let container = NSStackView()
container.orientation = .vertical
container.spacing = 0
container.wantsLayer = true
container.layer?.backgroundColor = NSColor.init(calibratedWhite: 0.1, alpha: 0.06).cgColor
container.layer?.cornerRadius = 4
container.edgeInsets = NSEdgeInsets(
top: 2,
left: 2,
bottom: 2,
right: 2
)
container.addArrangedSubview(view)
return container
}
}

View File

@@ -77,5 +77,12 @@
<integer>4</integer>
</dict>
</dict>
<key>Settings</key>
<dict>
<key>popup</key>
<true/>
<key>notifications</key>
<true/>
</dict>
</dict>
</plist>

View File

@@ -35,18 +35,18 @@ class Notifications: NotificationsWrapper {
self.lowLevel = Store.shared.string(key: "\(self.module)_notifications_low", defaultValue: self.lowLevel)
self.highLevel = Store.shared.string(key: "\(self.module)_notifications_high", defaultValue: self.highLevel)
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Low level notification"),
action: #selector(self.changeLowLevel),
items: notificationLevels,
selected: self.lowLevel
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("High level notification"),
action: #selector(self.changeHighLevel),
items: notificationLevels,
selected: self.highLevel
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Low level notification"), component: selectView(
action: #selector(self.changeLowLevel),
items: notificationLevels,
selected: self.lowLevel
)),
PreferencesRow(localizedString("High level notification"), component: selectView(
action: #selector(self.changeHighLevel),
items: notificationLevels,
selected: self.highLevel
))
]))
}
required init?(coder: NSCoder) {
@@ -84,7 +84,6 @@ class Notifications: NotificationsWrapper {
self.lowLevel = key.isEmpty ? "" : "\(Double(key) ?? 0)"
Store.shared.set(key: "\(self.module)_notifications_low", value: self.lowLevel)
}
@objc private func changeHighLevel(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else { return }
self.highLevel = key.isEmpty ? "" : "\(Double(key) ?? 0)"

View File

@@ -328,11 +328,12 @@ internal class Popup: PopupWrapper {
public override func settings() -> NSView? {
let view = SettingsContainerView()
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Colorize battery"),
action: #selector(toggleColor),
state: self.colorState
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Colorize battery"), component: switchView(
action: #selector(self.toggleColor),
state: self.colorState
))
]))
return view
}

View File

@@ -28,16 +28,8 @@ internal class Settings: NSStackView, Settings_v {
self.numberOfProcesses = Store.shared.int(key: "\(self.title)_processes", defaultValue: self.numberOfProcesses)
self.timeFormat = Store.shared.string(key: "\(self.title)_timeFormat", defaultValue: self.timeFormat)
super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
super.init(frame: NSRect.zero)
self.orientation = .vertical
self.distribution = .gravityAreas
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
}
@@ -48,20 +40,22 @@ internal class Settings: NSStackView, Settings_v {
public func load(widgets: [widget_t]) {
self.subviews.forEach{ $0.removeFromSuperview() }
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Number of top processes"),
action: #selector(changeNumberOfProcesses),
items: NumbersOfProcesses.map{ "\($0)" },
selected: "\(self.numberOfProcesses)"
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Number of top processes"), component: selectView(
action: #selector(self.changeNumberOfProcesses),
items: NumbersOfProcesses.map{ KeyValue_t(key: "\($0)", value: "\($0)") },
selected: "\(self.numberOfProcesses)"
))
]))
if !widgets.filter({ $0 == .battery }).isEmpty {
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Time format"),
action: #selector(toggleTimeFormat),
items: ShortLong,
selected: self.timeFormat
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Time format"), component: selectView(
action: #selector(toggleTimeFormat),
items: ShortLong,
selected: self.timeFormat
))
]))
}
}
@@ -72,11 +66,8 @@ internal class Settings: NSStackView, Settings_v {
self.callbackWhenUpdateNumberOfProcesses()
}
}
@objc private func toggleTimeFormat(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
self.timeFormat = key
Store.shared.set(key: "\(self.title)_timeFormat", value: key)
self.callback()

View File

@@ -34,5 +34,12 @@
<integer>1</integer>
</dict>
</dict>
<key>Settings</key>
<dict>
<key>popup</key>
<false/>
<key>notifications</key>
<false/>
</dict>
</dict>
</plist>

View File

@@ -16,23 +16,22 @@ internal class Settings: NSStackView, Settings_v {
public var callback: (() -> Void) = {}
private var list: [String: Bool] = [:]
private let emptyView: EmptyView = EmptyView(msg: localizedString("No Bluetooth devices are available"))
private var section: PreferencesSection = PreferencesSection()
public init() {
super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
self.orientation = .vertical
self.distribution = .gravityAreas
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
self.addArrangedSubview(NSView())
self.addArrangedSubview(self.emptyView)
self.addArrangedSubview(self.section)
self.section.isHidden = true
self.addArrangedSubview(NSView())
}
required init?(coder: NSCoder) {
@@ -43,44 +42,38 @@ internal class Settings: NSStackView, Settings_v {
internal func setList(_ list: [BLEDevice]) {
if self.list.count != list.count && !self.list.isEmpty {
self.subviews.filter({ $0 is NSStackView && ($0 as! NSStackView).identifier != NSUserInterfaceItemIdentifier(rawValue: "emptyView") }).forEach{ $0.removeFromSuperview() }
self.section.removeFromSuperview()
self.section = PreferencesSection()
self.addArrangedSubview(self.section)
self.list = [:]
}
if list.isEmpty && self.emptyView.isHidden {
self.emptyView.isHidden = false
self.section.isHidden = true
return
} else if !list.isEmpty && !self.emptyView.isHidden {
self.emptyView.isHidden = true
self.section.isHidden = false
}
list.forEach { (d: BLEDevice) in
if self.list[d.id] == nil {
let row: NSView = toggleSettingRow(
title: d.name,
let btn = switchView(
action: #selector(self.handleSelection),
state: d.state
)
row.subviews.filter{ $0 is NSControl }.forEach { (control: NSView) in
control.identifier = NSUserInterfaceItemIdentifier(rawValue: "\(d.uuid?.uuidString ?? d.address)")
}
btn.identifier = NSUserInterfaceItemIdentifier(rawValue: "\(d.uuid?.uuidString ?? d.address)")
section.add(PreferencesRow(d.name, component: btn))
self.list[d.id] = true
self.addArrangedSubview(row)
}
}
}
@objc private func handleSelection(_ sender: NSControl) {
guard let id = sender.identifier else { return }
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
}
Store.shared.set(key: "ble_\(id.rawValue)", value: state! == NSControl.StateValue.on)
let value = controlState(sender)
Store.shared.set(key: "ble_\(id.rawValue)", value: value)
self.callback()
}
}

View File

@@ -81,5 +81,12 @@
<integer>5</integer>
</dict>
</dict>
<key>Settings</key>
<dict>
<key>popup</key>
<true/>
<key>notifications</key>
<true/>
</dict>
</dict>
</plist>

View File

@@ -40,41 +40,37 @@ class Notifications: NotificationsWrapper {
self.eCoresLoadLevel = Store.shared.string(key: "\(self.module)_notifications_eCoresLoad", defaultValue: self.eCoresLoadLevel)
self.pCoresLoadLevel = Store.shared.string(key: "\(self.module)_notifications_pCoresLoad", defaultValue: self.pCoresLoadLevel)
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Total load"),
action: #selector(self.changeTotalLoad),
items: notificationLevels,
selected: self.totalLoadLevel
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("System load"),
action: #selector(self.changeSystemLoad),
items: notificationLevels,
selected: self.systemLoadLevel
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("User load"),
action: #selector(self.changeUserLoad),
items: notificationLevels,
selected: self.userLoadLevel
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Total load"), component: selectView(
action: #selector(self.changeTotalLoad),
items: notificationLevels,
selected: self.totalLoadLevel
)),
PreferencesRow(localizedString("System load"), component: selectView(
action: #selector(self.changeSystemLoad),
items: notificationLevels,
selected: self.systemLoadLevel
)),
PreferencesRow(localizedString("User load"), component: selectView(
action: #selector(self.changeUserLoad),
items: notificationLevels,
selected: self.userLoadLevel
))
]))
#if arch(arm64)
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Efficiency cores load"),
action: #selector(self.changeECoresLoad),
items: notificationLevels,
selected: self.eCoresLoadLevel
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Performance cores load"),
action: #selector(self.changePCoresLoad),
items: notificationLevels,
selected: self.pCoresLoadLevel
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Efficiency cores load"), component: selectView(
action: #selector(self.changeECoresLoad),
items: notificationLevels,
selected: self.eCoresLoadLevel
)),
PreferencesRow(localizedString("Performance cores load"), component: selectView(
action: #selector(self.changePCoresLoad),
items: notificationLevels,
selected: self.pCoresLoadLevel
))
]))
#endif
}

View File

@@ -52,6 +52,7 @@ internal class Popup: PopupWrapper {
private var eCoresColorView: NSView? = nil
private var pCoresColorView: NSView? = nil
private var chartPrefSection: PreferencesSection? = nil
private var sliderView: NSView? = nil
private var lineChart: LineChartView? = nil
@@ -472,71 +473,62 @@ internal class Popup: PopupWrapper {
public override func settings() -> NSView? {
let view = SettingsContainerView()
view.addArrangedSubview(selectSettingsRow(
title: localizedString("System color"),
action: #selector(self.toggleSystemColor),
items: Color.allColors,
selected: self.systemColorState.key
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("System color"), component: selectView(
action: #selector(self.toggleSystemColor),
items: Color.allColors,
selected: self.systemColorState.key
)),
PreferencesRow(localizedString("User color"), component: selectView(
action: #selector(self.toggleUserColor),
items: Color.allColors,
selected: self.userColorState.key
)),
PreferencesRow(localizedString("Idle color"), component: selectView(
action: #selector(self.toggleIdleColor),
items: Color.allColors,
selected: self.idleColorState.key
))
]))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("User color"),
action: #selector(self.toggleUserColor),
items: Color.allColors,
selected: self.userColorState.key
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Efficiency cores color"), component: selectView(
action: #selector(self.toggleECoresColor),
items: Color.allColors,
selected: self.eCoresColorState.key
)),
PreferencesRow(localizedString("Performance cores color"), component: selectView(
action: #selector(self.togglePCoresColor),
items: Color.allColors,
selected: self.pCoresColorState.key
))
]))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Idle color"),
action: #selector(self.toggleIdleColor),
items: Color.allColors,
selected: self.idleColorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Chart color"),
action: #selector(self.toggleChartColor),
items: Color.allColors,
selected: self.chartColorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Efficiency cores color"),
action: #selector(self.toggleeCoresColor),
items: Color.allColors,
selected: self.eCoresColorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Performance cores color"),
action: #selector(self.togglepCoresColor),
items: Color.allColors,
selected: self.pCoresColorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Chart duration"),
action: #selector(self.toggleLineChartHistory),
items: LineChartHistory,
selected: "\(self.lineChartHistory)"
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Main chart scaling"),
action: #selector(self.toggleLineChartScale),
items: Scale.allCases,
selected: self.lineChartScale.key
))
let slider = sliderSettingsRow(
title: localizedString("Scale value"),
self.sliderView = sliderView(
action: #selector(self.toggleLineChartFixedScale),
value: Int(self.lineChartFixedScale * 100),
initialValue: "\(Int(self.lineChartFixedScale * 100)) %",
isHidden: self.lineChartScale != .fixed
initialValue: "\(Int(self.lineChartFixedScale * 100)) %"
)
self.sliderView = slider
view.addArrangedSubview(slider)
self.chartPrefSection = PreferencesSection([
PreferencesRow(localizedString("Chart color"), component: selectView(
action: #selector(self.toggleChartColor),
items: Color.allColors,
selected: self.chartColorState.key
)),
PreferencesRow(localizedString("Chart history"), component: selectView(
action: #selector(self.toggleLineChartHistory),
items: LineChartHistory,
selected: "\(self.lineChartHistory)"
)),
PreferencesRow(localizedString("Main chart scaling"), component: selectView(
action: #selector(self.toggleLineChartScale),
items: Scale.allCases,
selected: self.lineChartScale.key
)),
PreferencesRow(localizedString("Scale value"), component: self.sliderView!)
])
view.addArrangedSubview(self.chartPrefSection!)
self.chartPrefSection?.toggleVisibility(3, newState: self.lineChartScale == .fixed)
return view
}
@@ -578,7 +570,7 @@ internal class Popup: PopupWrapper {
self.lineChart?.color = color
}
}
@objc private func toggleeCoresColor(_ sender: NSMenuItem) {
@objc private func toggleECoresColor(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String, let newValue = Color.allColors.first(where: { $0.key == key }) else {
return
}
@@ -586,7 +578,7 @@ internal class Popup: PopupWrapper {
Store.shared.set(key: "\(self.title)_eCoresColor", value: key)
self.eCoresColorView?.layer?.backgroundColor = (newValue.additional as? NSColor)?.cgColor
}
@objc private func togglepCoresColor(_ sender: NSMenuItem) {
@objc private func togglePCoresColor(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String, let newValue = Color.allColors.first(where: { $0.key == key }) else {
return
}
@@ -603,7 +595,7 @@ internal class Popup: PopupWrapper {
@objc private func toggleLineChartScale(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String,
let value = Scale.allCases.first(where: { $0.key == key }) else { return }
self.sliderView?.isHidden = value != .fixed
self.chartPrefSection?.toggleVisibility(3, newState: value == .fixed)
self.lineChartScale = value
self.lineChart?.setScale(self.lineChartScale, fixedScale: self.lineChartFixedScale)
Store.shared.set(key: "\(self.title)_lineChartScale", value: key)
@@ -612,8 +604,7 @@ internal class Popup: PopupWrapper {
@objc private func toggleLineChartFixedScale(_ sender: NSSlider) {
let value = Int(sender.doubleValue)
if let container = self.sliderView?.subviews.first(where: { $0.identifier == NSUserInterfaceItemIdentifier("container") }),
let field = container.subviews.first(where: { $0 is NSTextField }), let view = field as? NSTextField {
if let field = self.sliderView?.subviews.first(where: { $0 is NSTextField }), let view = field as? NSTextField {
view.stringValue = "\(value) %"
}

View File

@@ -31,10 +31,10 @@ internal class Settings: NSStackView, Settings_v {
public var setInterval: ((_ value: Int) -> Void) = {_ in }
public var setTopInterval: ((_ value: Int) -> Void) = {_ in }
private var hyperthreadView: NSView? = nil
private var splitValueView: NSView? = nil
private var usagePerCoreView: NSView? = nil
private var groupByClustersView: NSView? = nil
private var hyperthreadView: NSSwitch? = nil
private var splitValueView: NSSwitch? = nil
private var usagePerCoreView: NSSwitch? = nil
private var groupByClustersView: NSSwitch? = nil
public init(_ module: ModuleType) {
self.title = module.rawValue
@@ -56,12 +56,6 @@ internal class Settings: NSStackView, Settings_v {
self.orientation = .vertical
self.distribution = .gravityAreas
self.translatesAutoresizingMaskIntoConstraints = false
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
}
@@ -79,78 +73,79 @@ internal class Settings: NSStackView, Settings_v {
hasIPG = CFBundleCreate(kCFAllocatorDefault, bundleURL) != nil
#endif
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Update interval"),
action: #selector(changeUpdateInterval),
items: ReaderUpdateIntervals.map{ "\($0) sec" },
selected: "\(self.updateIntervalValue) sec"
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Update interval"), component: selectView(
action: #selector(self.changeUpdateInterval),
items: ReaderUpdateIntervals.map{ KeyValue_t(key: "\($0)", value: "\($0) sec") },
selected: "\(self.updateIntervalValue) sec"
)),
PreferencesRow(localizedString("Update interval for top processes"), component: selectView(
action: #selector(self.changeUpdateTopInterval),
items: ReaderUpdateIntervals.map{ KeyValue_t(key: "\($0)", value: "\($0) sec") },
selected: "\(self.updateTopIntervalValue) sec"
))
]))
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Update interval for top processes"),
action: #selector(changeUpdateTopInterval),
items: ReaderUpdateIntervals.map{ "\($0) sec" },
selected: "\(self.updateTopIntervalValue) sec"
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Number of top processes"), component: selectView(
action: #selector(self.changeNumberOfProcesses),
items: NumbersOfProcesses.map{ KeyValue_t(key: "\($0)", value: "\($0)") },
selected: "\(self.numberOfProcesses)"
))
]))
if !widgets.filter({ $0 == .barChart }).isEmpty {
self.usagePerCoreView = toggleSettingRow(
title: localizedString("Show usage per core"),
action: #selector(toggleUsagePerCore),
self.splitValueView = switchView(
action: #selector(self.toggleSplitValue),
state: self.splitValueState
)
self.usagePerCoreView = switchView(
action: #selector(self.toggleUsagePerCore),
state: self.usagePerCoreState
)
self.addArrangedSubview(self.usagePerCoreView!)
if self.usagePerCoreState || self.clustersGroupState {
self.splitValueView?.isEnabled = false
self.splitValueView?.state = .off
}
var rows: [PreferencesRow] = [
PreferencesRow(localizedString("Show usage per core"), component: self.usagePerCoreView!)
]
#if arch(arm64)
self.groupByClustersView = toggleSettingRow(
title: localizedString("Cluster grouping"),
action: #selector(toggleClustersGroup),
self.groupByClustersView = switchView(
action: #selector(self.toggleClustersGroup),
state: self.clustersGroupState
)
self.addArrangedSubview(self.groupByClustersView!)
rows.append(PreferencesRow(localizedString("Cluster grouping"), component: self.groupByClustersView!))
#endif
if self.hasHyperthreadingCores {
self.hyperthreadView = toggleSettingRow(
title: localizedString("Show hyper-threading cores"),
action: #selector(toggleMultithreading),
self.hyperthreadView = switchView(
action: #selector(self.toggleMultithreading),
state: self.hyperthreadState
)
if !self.usagePerCoreState {
findAndToggleEnableNSControlState(self.hyperthreadView, state: false)
findAndToggleNSControlState(self.hyperthreadView, state: .off)
self.hyperthreadView?.isEnabled = false
self.hyperthreadView?.state = .off
}
self.addArrangedSubview(self.hyperthreadView!)
rows.append(PreferencesRow(localizedString("Show hyper-threading cores"), component: self.hyperthreadView!))
}
rows.append(PreferencesRow(localizedString("Split the value (System/User)"), component: self.splitValueView!))
self.splitValueView = toggleSettingRow(
title: localizedString("Split the value (System/User)"),
action: #selector(toggleSplitValue),
state: self.splitValueState
)
if self.usagePerCoreState || self.clustersGroupState {
findAndToggleEnableNSControlState(self.splitValueView, state: false)
findAndToggleNSControlState(self.splitValueView, state: .off)
}
self.addArrangedSubview(self.splitValueView!)
self.addArrangedSubview(PreferencesSection(rows))
}
#if arch(x86_64)
if hasIPG {
self.addArrangedSubview(toggleSettingRow(
title: "\(localizedString("CPU frequency")) (IPG)",
action: #selector(toggleIPG),
state: self.IPGState
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow("\(localizedString("CPU frequency")) (IPG)", component: switchView(
action: #selector(self.toggleIPG),
state: self.IPGState
))
]))
}
#endif
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Number of top processes"),
action: #selector(changeNumberOfProcesses),
items: NumbersOfProcesses.map{ "\($0)" },
selected: "\(self.numberOfProcesses)"
))
}
@objc private func changeUpdateInterval(_ sender: NSMenuItem) {
@@ -189,23 +184,23 @@ internal class Settings: NSStackView, Settings_v {
Store.shared.set(key: "\(self.title)_usagePerCore", value: self.usagePerCoreState)
self.callback()
findAndToggleEnableNSControlState(self.hyperthreadView, state: self.usagePerCoreState)
findAndToggleEnableNSControlState(self.splitValueView, state: !(self.usagePerCoreState || self.clustersGroupState))
self.hyperthreadView?.isEnabled = self.usagePerCoreState
self.splitValueView?.isEnabled = !(self.usagePerCoreState || self.clustersGroupState)
if !self.usagePerCoreState {
self.hyperthreadState = false
Store.shared.set(key: "\(self.title)_hyperhreading", value: self.hyperthreadState)
findAndToggleNSControlState(self.hyperthreadView, state: .off)
self.hyperthreadView?.state = .off
} else {
self.splitValueState = false
Store.shared.set(key: "\(self.title)_splitValue", value: self.splitValueState)
findAndToggleNSControlState(self.splitValueView, state: .off)
self.splitValueView?.state = .off
}
if self.clustersGroupState && self.usagePerCoreState {
self.clustersGroupState = false
Store.shared.set(key: "\(self.title)_clustersGroup", value: self.clustersGroupState)
findAndToggleNSControlState(self.groupByClustersView, state: .off)
self.groupByClustersView?.state = .off
}
}
@@ -259,10 +254,10 @@ internal class Settings: NSStackView, Settings_v {
self.clustersGroupState = state! == .on ? true : false
Store.shared.set(key: "\(self.title)_clustersGroup", value: self.clustersGroupState)
findAndToggleEnableNSControlState(self.splitValueView, state: !(self.usagePerCoreState || self.clustersGroupState))
self.splitValueView?.isEnabled = !(self.usagePerCoreState || self.clustersGroupState)
if self.clustersGroupState && self.usagePerCoreState {
findAndToggleNSControlState(self.usagePerCoreView, state: .off)
self.usagePerCoreView?.state = .off
let toggle: NSSwitch = NSSwitch()
toggle.state = .off
self.toggleUsagePerCore(toggle)

View File

@@ -32,5 +32,12 @@
<integer>1</integer>
</dict>
</dict>
<key>Settings</key>
<dict>
<key>popup</key>
<true/>
<key>notifications</key>
<false/>
</dict>
</dict>
</plist>

View File

@@ -57,12 +57,6 @@ internal class Settings: NSStackView, Settings_v, NSTableViewDelegate, NSTableVi
self.orientation = .vertical
self.distribution = .gravityAreas
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = 0
self.scrollView.documentView = self.tableView
@@ -115,7 +109,7 @@ internal class Settings: NSStackView, Settings_v, NSTableViewDelegate, NSTableVi
self.addArrangedSubview(self.footer())
NSLayoutConstraint.activate([
self.scrollView.heightAnchor.constraint(equalToConstant: 278)
self.scrollView.heightAnchor.constraint(equalToConstant: 296)
])
}
@@ -126,21 +120,19 @@ internal class Settings: NSStackView, Settings_v, NSTableViewDelegate, NSTableVi
private func footer() -> NSView {
let view = NSStackView()
view.heightAnchor.constraint(equalToConstant: 27).isActive = true
view.spacing = 0
view.spacing = 4
view.orientation = .horizontal
var addButton: NSButton {
let btn = NSButton()
btn.widthAnchor.constraint(equalToConstant: 27).isActive = true
btn.heightAnchor.constraint(equalToConstant: 27).isActive = true
btn.bezelStyle = .regularSquare
btn.translatesAutoresizingMaskIntoConstraints = false
btn.bezelStyle = .rounded
if #available(macOS 11.0, *) {
btn.image = iconFromSymbol(name: "plus", scale: .large)
btn.image = iconFromSymbol(name: "plus", scale: .medium)
} else {
btn.title = "Add"
btn.title = localizedString("Add")
}
btn.isBordered = false
btn.action = #selector(self.addNewClock)
btn.target = self
btn.toolTip = localizedString("Add new clock")
@@ -151,14 +143,12 @@ internal class Settings: NSStackView, Settings_v, NSTableViewDelegate, NSTableVi
let btn = NSButton()
btn.widthAnchor.constraint(equalToConstant: 27).isActive = true
btn.heightAnchor.constraint(equalToConstant: 27).isActive = true
btn.bezelStyle = .regularSquare
btn.translatesAutoresizingMaskIntoConstraints = false
btn.bezelStyle = .rounded
if #available(macOS 11.0, *) {
btn.image = iconFromSymbol(name: "minus", scale: .large)
btn.image = iconFromSymbol(name: "minus", scale: .medium)
} else {
btn.title = "Add"
btn.title = localizedString("Delete")
}
btn.isBordered = false
btn.action = #selector(self.deleteClock)
btn.target = self
btn.toolTip = localizedString("Delete selected clock")
@@ -170,6 +160,16 @@ internal class Settings: NSStackView, Settings_v, NSTableViewDelegate, NSTableVi
view.addArrangedSubview(addButton)
view.addArrangedSubview(NSView())
let helpBtn = NSButton()
helpBtn.widthAnchor.constraint(equalToConstant: 27).isActive = true
helpBtn.heightAnchor.constraint(equalToConstant: 27).isActive = true
helpBtn.bezelStyle = .helpButton
helpBtn.title = ""
helpBtn.action = #selector(self.openFormatHelp)
helpBtn.target = self
helpBtn.toolTip = localizedString("Help with datetime format")
view.addArrangedSubview(helpBtn)
self.footerView = view
return view
}
@@ -197,7 +197,6 @@ internal class Settings: NSStackView, Settings_v, NSTableViewDelegate, NSTableVi
text.delegate = self
text.stringValue = id == nameColumnID ? item.name : item.format
text.translatesAutoresizingMaskIntoConstraints = false
cell.addSubview(text)
text.widthAnchor.constraint(equalTo: cell.widthAnchor).isActive = true
text.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = true
@@ -251,12 +250,10 @@ internal class Settings: NSStackView, Settings_v, NSTableViewDelegate, NSTableVi
guard let key = sender.representedObject as? String, let id = sender.identifier, let i = Int(id.rawValue) else { return }
self.list[i].tz = key
}
@objc private func toggleClock(_ sender: NSButton) {
guard let id = sender.identifier, let i = Int(id.rawValue) else { return }
self.list[i].enabled = sender.state == NSControl.StateValue.on
}
@objc private func addNewClock(_ sender: Any) {
self.list.append(Clock_t(name: "Clock \(self.list.count)", format: Clock.local.format, tz: Clock.local.tz))
self.tableView.reloadData()
@@ -267,4 +264,7 @@ internal class Settings: NSStackView, Settings_v, NSTableViewDelegate, NSTableVi
self.tableView.reloadData()
self.deleteButton?.removeFromSuperview()
}
@objc private func openFormatHelp(_ sender: NSButton) {
NSWorkspace.shared.open(URL(string: "https://www.nsdateformatter.com")!)
}
}

View File

@@ -117,5 +117,12 @@
</array>
</dict>
</dict>
<key>Settings</key>
<dict>
<key>popup</key>
<true/>
<key>notifications</key>
<true/>
</dict>
</dict>
</plist>

View File

@@ -27,12 +27,13 @@ class Notifications: NotificationsWrapper {
self.utilizationLevel = Store.shared.string(key: "\(self.module)_notifications_utilization", defaultValue: self.utilizationLevel)
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Usage"),
action: #selector(self.changeUsage),
items: notificationLevels,
selected: self.utilizationLevel
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Usage"), component: selectView(
action: #selector(self.changeUsage),
items: notificationLevels,
selected: self.utilizationLevel
))
]))
}
required init?(coder: NSCoder) {

View File

@@ -19,6 +19,7 @@ internal class Popup: PopupWrapper {
private var readColor: NSColor { self.readColorState.additional as? NSColor ?? NSColor.systemRed }
private var writeColorState: Color = .secondRed
private var writeColor: NSColor { self.writeColorState.additional as? NSColor ?? NSColor.systemBlue }
private var reverseOrderState: Bool = false
private var disks: NSStackView = {
let view = NSStackView()
@@ -45,6 +46,7 @@ internal class Popup: PopupWrapper {
self.readColorState = Color.fromString(Store.shared.string(key: "\(self.title)_readColor", defaultValue: self.readColorState.key))
self.writeColorState = Color.fromString(Store.shared.string(key: "\(self.title)_writeColor", defaultValue: self.writeColorState.key))
self.reverseOrderState = Store.shared.bool(key: "\(self.title)_reverseOrder", defaultValue: self.reverseOrderState)
self.orientation = .vertical
self.distribution = .fill
@@ -170,19 +172,25 @@ internal class Popup: PopupWrapper {
public override func settings() -> NSView? {
let view = SettingsContainerView()
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Write color"),
action: #selector(toggleWriteColor),
items: Color.allColors,
selected: self.writeColorState.key
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Write color"), component: selectView(
action: #selector(self.toggleWriteColor),
items: Color.allColors,
selected: self.writeColorState.key
)),
PreferencesRow(localizedString("Read color"), component: selectView(
action: #selector(self.toggleReadColor),
items: Color.allColors,
selected: self.readColorState.key
))
]))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Read color"),
action: #selector(toggleReadColor),
items: Color.allColors,
selected: self.readColorState.key
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Reverse order"), component: switchView(
action: #selector(self.toggleReverseOrder),
state: self.reverseOrderState
))
]))
return view
}
@@ -215,6 +223,14 @@ internal class Popup: PopupWrapper {
}
}
}
@objc private func toggleReverseOrder(_ sender: NSControl) {
self.reverseOrderState = controlState(sender)
for view in self.disks.subviews.filter({ $0 is DiskView }).map({ $0 as! DiskView }) {
view.setChartReverseOrder(self.reverseOrderState)
}
Store.shared.set(key: "\(self.title)_reverseOrder", value: self.reverseOrderState)
self.display()
}
}
internal class DiskView: NSStackView {
@@ -303,6 +319,9 @@ internal class DiskView: NSStackView {
public func setChartColor(read: NSColor? = nil, write: NSColor? = nil) {
self.chartView.setColors(read: read, write: write)
}
public func setChartReverseOrder(_ newValue: Bool) {
self.chartView.setReverseOrder(newValue)
}
}
internal class NameView: NSStackView {
@@ -429,6 +448,9 @@ internal class ChartView: NSStackView {
private var writeColor: NSColor {
Color.fromString(Store.shared.string(key: "\(ModuleType.disk.rawValue)_writeColor", defaultValue: Color.secondRed.key)).additional as! NSColor
}
private var reverseOrder: Bool {
Store.shared.bool(key: "\(ModuleType.disk.rawValue)_reverseOrder", defaultValue: false)
}
public init(width: CGFloat) {
super.init(frame: NSRect(x: 0, y: 0, width: width, height: 36))
@@ -441,7 +463,7 @@ internal class ChartView: NSStackView {
y: 1,
width: self.frame.width,
height: self.frame.height - 2
), num: 120, outColor: self.writeColor, inColor: self.readColor)
), num: 120, reversedOrder: self.reverseOrder, outColor: self.writeColor, inColor: self.readColor)
self.chart = chart
self.addArrangedSubview(chart)
@@ -465,6 +487,10 @@ internal class ChartView: NSStackView {
public func setColors(read: NSColor? = nil, write: NSColor? = nil) {
self.chart?.setColors(in: read, out: write)
}
public func setReverseOrder(_ newValue: Bool) {
self.chart?.setReverseOrder(newValue)
}
}
internal class BarView: NSView {

View File

@@ -17,7 +17,6 @@ internal class Settings: NSStackView, Settings_v {
private var removableState: Bool = false
private var updateIntervalValue: Int = 10
private var notificationLevel: String = "Disabled"
private var numberOfProcesses: Int = 5
private var baseValue: String = "byte"
@@ -28,7 +27,6 @@ internal class Settings: NSStackView, Settings_v {
private var selectedDisk: String
private var button: NSPopUpButton?
private var intervalSelectView: NSView? = nil
private var list: [String] = []
@@ -38,21 +36,12 @@ internal class Settings: NSStackView, Settings_v {
self.selectedDisk = Store.shared.string(key: "\(self.title)_disk", defaultValue: "")
self.removableState = Store.shared.bool(key: "\(self.title)_removable", defaultValue: self.removableState)
self.updateIntervalValue = Store.shared.int(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue)
self.notificationLevel = Store.shared.string(key: "\(self.title)_notificationLevel", defaultValue: self.notificationLevel)
self.numberOfProcesses = Store.shared.int(key: "\(self.title)_processes", defaultValue: self.numberOfProcesses)
self.baseValue = Store.shared.string(key: "\(self.title)_base", defaultValue: self.baseValue)
super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
super.init(frame: NSRect.zero)
self.wantsLayer = true
self.orientation = .vertical
self.distribution = .gravityAreas
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
}
@@ -63,69 +52,44 @@ internal class Settings: NSStackView, Settings_v {
public func load(widgets: [widget_t]) {
self.subviews.forEach{ $0.removeFromSuperview() }
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Number of top processes"),
action: #selector(changeNumberOfProcesses),
items: NumbersOfProcesses.map{ "\($0)" },
selected: "\(self.numberOfProcesses)"
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Update interval"), component: selectView(
action: #selector(self.changeUpdateInterval),
items: ReaderUpdateIntervals.map{ KeyValue_t(key: "\($0)", value: "\($0) sec") },
selected: "\(self.updateIntervalValue) sec"
))
]))
self.intervalSelectView = selectSettingsRowV1(
title: localizedString("Update interval"),
action: #selector(changeUpdateInterval),
items: (ReaderUpdateIntervals + [90, 120, 180, 240, 300]).map{ "\($0) sec" },
selected: "\(self.updateIntervalValue) sec"
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Number of top processes"), component: selectView(
action: #selector(self.changeNumberOfProcesses),
items: NumbersOfProcesses.map{ KeyValue_t(key: "\($0)", value: "\($0)") },
selected: "\(self.numberOfProcesses)"
))
]))
self.button = selectView(
action: #selector(self.handleSelection),
items: [],
selected: ""
)
self.addArrangedSubview(self.intervalSelectView!)
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Disk to show"), component: self.button!),
PreferencesRow(localizedString("Show removable disks"), component: switchView(
action: #selector(self.toggleRemovable),
state: self.removableState
))
]))
if widgets.contains(where: { $0 == .speed }) {
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Base"),
action: #selector(toggleBase),
items: SpeedBase,
selected: self.baseValue
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Base"), component: selectView(
action: #selector(self.toggleBase),
items: SpeedBase,
selected: self.baseValue
))
]))
}
self.addDiskSelector()
self.addArrangedSubview(toggleSettingRow(
title: localizedString("Show removable disks"),
action: #selector(toggleRemovable),
state: self.removableState
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Notification level"),
action: #selector(changeNotificationLevel),
items: notificationLevels,
selected: self.notificationLevel == "Disabled" ? self.notificationLevel : "\(Int((Double(self.notificationLevel) ?? 0)*100))%"
))
}
private func addDiskSelector() {
let view: NSStackView = NSStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.heightAnchor.constraint(equalToConstant: Constants.Settings.row).isActive = true
view.orientation = .horizontal
view.alignment = .centerY
view.distribution = .fill
view.spacing = 0
let rowTitle: NSTextField = LabelField(frame: NSRect(x: 0, y: 0, width: 0, height: 17), localizedString("Disk to show"))
rowTitle.font = NSFont.systemFont(ofSize: 13, weight: .light)
rowTitle.textColor = .textColor
self.button = NSPopUpButton(frame: NSRect(x: 0, y: 0, width: 0, height: 30))
self.button!.target = self
self.button?.action = #selector(self.handleSelection)
self.button?.addItems(withTitles: list)
view.addArrangedSubview(rowTitle)
view.addArrangedSubview(NSView())
view.addArrangedSubview(self.button!)
self.addArrangedSubview(view)
}
internal func setList(_ list: Disks) {
@@ -152,36 +116,22 @@ internal class Settings: NSStackView, Settings_v {
self.callbackWhenUpdateNumberOfProcesses()
}
}
@objc private func handleSelection(_ sender: NSPopUpButton) {
guard let item = sender.selectedItem else { return }
self.selectedDisk = item.title
Store.shared.set(key: "\(self.title)_disk", value: item.title)
self.selectedDiskHandler(item.title)
}
@objc private func toggleRemovable(_ sender: NSControl) {
self.removableState = controlState(sender)
Store.shared.set(key: "\(self.title)_removable", value: self.removableState)
self.callback()
}
@objc private func changeUpdateInterval(_ sender: NSMenuItem) {
if let value = Int(sender.title.replacingOccurrences(of: " sec", with: "")) {
self.setUpdateInterval(value: value)
}
}
@objc func changeNotificationLevel(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else { return }
if key == "Disabled" {
Store.shared.set(key: "\(self.title)_notificationLevel", value: key)
} else if let value = Double(key.replacingOccurrences(of: "%", with: "")) {
Store.shared.set(key: "\(self.title)_notificationLevel", value: "\(value/100)")
}
}
public func setUpdateInterval(value: Int) {
self.updateIntervalValue = value
Store.shared.set(key: "\(self.title)_updateInterval", value: value)

View File

@@ -73,5 +73,12 @@
<integer>4</integer>
</dict>
</dict>
<key>Settings</key>
<dict>
<key>popup</key>
<false/>
<key>notifications</key>
<true/>
</dict>
</dict>
</plist>

View File

@@ -27,12 +27,13 @@ class Notifications: NotificationsWrapper {
self.usageLevel = Store.shared.string(key: "\(self.module)_notifications_usage", defaultValue: self.usageLevel)
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Usage"),
action: #selector(self.changeUsage),
items: notificationLevels,
selected: self.usageLevel
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Usage"), component: selectView(
action: #selector(self.changeUsage),
items: notificationLevels,
selected: self.usageLevel
))
]))
}
required init?(coder: NSCoder) {

View File

@@ -37,12 +37,6 @@ internal class Settings: NSStackView, Settings_v {
self.wantsLayer = true
self.orientation = .vertical
self.distribution = .gravityAreas
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
}
@@ -53,51 +47,33 @@ internal class Settings: NSStackView, Settings_v {
public func load(widgets: [widget_t]) {
self.subviews.forEach{ $0.removeFromSuperview() }
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Update interval"),
action: #selector(changeUpdateInterval),
items: ReaderUpdateIntervals.map{ "\($0) sec" },
selected: "\(self.updateIntervalValue) sec"
))
if !widgets.filter({ $0 == .mini }).isEmpty {
self.addArrangedSubview(toggleSettingRow(
title: localizedString("Show GPU type"),
action: #selector(toggleShowType),
state: self.showTypeValue
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Update interval"), component: selectView(
action: #selector(self.changeUpdateInterval),
items: ReaderUpdateIntervals.map{ KeyValue_t(key: "\($0)", value: "\($0) sec") },
selected: "\(self.updateIntervalValue) sec"
))
]))
#if arch(x86_64)
if !widgets.filter({ $0 == .mini }).isEmpty {
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Show GPU type"), component: switchView(
action: #selector(self.toggleShowType),
state: self.showTypeValue
))
]))
}
#endif
self.addGPUSelector()
}
private func addGPUSelector() {
let view: NSStackView = NSStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.heightAnchor.constraint(equalToConstant: Constants.Settings.row).isActive = true
view.orientation = .horizontal
view.alignment = .centerY
view.distribution = .fill
view.spacing = 0
let title: NSTextField = LabelField(frame: NSRect(x: 0, y: 0, width: 0, height: 17), localizedString("GPU to show"))
title.font = NSFont.systemFont(ofSize: 13, weight: .light)
title.textColor = .textColor
let container: NSGridView = NSGridView(frame: NSRect(x: 0, y: 0, width: view.frame.width - 100, height: 26))
container.yPlacement = .center
container.xPlacement = .trailing
let button = NSPopUpButton(frame: NSRect(x: 0, y: 0, width: 200, height: 30))
button.target = self
button.action = #selector(self.handleSelection)
self.button = button
container.addRow(with: [button])
view.addArrangedSubview(title)
view.addArrangedSubview(NSView())
view.addArrangedSubview(container)
self.addArrangedSubview(view)
self.button = selectView(
action: #selector(self.handleSelection),
items: [],
selected: ""
)
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("GPU to show"), component: self.button!)
]))
}
internal func setList(_ gpus: GPUs) {
@@ -108,10 +84,7 @@ internal class Settings: NSStackView, Settings_v {
gpus.active().forEach{ list.append(KeyValue_t(key: $0.model, value: $0.model)) }
DispatchQueue.main.async(execute: {
guard let button = self.button else {
return
}
guard let button = self.button else { return }
if button.menu?.items.count != list.count {
let menu = NSMenu()
@@ -141,26 +114,14 @@ internal class Settings: NSStackView, Settings_v {
self.setInterval(value)
}
}
@objc private func handleSelection(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else {
return
}
guard let key = sender.representedObject as? String else { return }
self.selectedGPU = key
Store.shared.set(key: "\(self.title)_gpu", value: key)
self.selectedGPUHandler(key)
}
@objc func toggleShowType(_ 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.showTypeValue = state! == .on ? true : false
@objc private func toggleShowType(_ sender: NSControl) {
self.showTypeValue = controlState(sender)
Store.shared.set(key: "\(self.title)_showType", value: self.showTypeValue)
self.callback()
}

View File

@@ -55,5 +55,12 @@
</dict>
</dict>
</dict>
<key>Settings</key>
<dict>
<key>popup</key>
<true/>
<key>notifications</key>
<false/>
</dict>
</dict>
</plist>

View File

@@ -503,38 +503,40 @@ internal class Popup: PopupWrapper {
public override func settings() -> NSView? {
let view = SettingsContainerView()
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Color of upload"),
action: #selector(toggleUploadColor),
items: Color.allColors,
selected: self.uploadColorState.key
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Color of upload"), component: selectView(
action: #selector(self.toggleUploadColor),
items: Color.allColors,
selected: self.uploadColorState.key
)),
PreferencesRow(localizedString("Color of download"), component: selectView(
action: #selector(self.toggleDownloadColor),
items: Color.allColors,
selected: self.downloadColorState.key
))
]))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Color of download"),
action: #selector(toggleDownloadColor),
items: Color.allColors,
selected: self.downloadColorState.key
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Reverse order"), component: switchView(
action: #selector(self.toggleReverseOrder),
state: self.reverseOrderState
))
]))
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Reverse order"),
action: #selector(toggleReverseOrder),
state: self.reverseOrderState
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Main chart scaling"), component: selectView(
action: #selector(self.toggleChartScale),
items: Scale.allCases.filter({ $0 != .fixed }),
selected: self.chartScale.key
))
]))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Main chart scaling"),
action: #selector(self.toggleChartScale),
items: Scale.allCases.filter({ $0 != .fixed }),
selected: self.chartScale.key
))
view.addArrangedSubview(toggleSettingRow(
title: localizedString("Public IP"),
action: #selector(self.togglePublicIP),
state: self.publicIPState
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Public IP"), component: switchView(
action: #selector(self.togglePublicIP),
state: self.publicIPState
))
]))
return view
}

View File

@@ -30,9 +30,8 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
public var publicIPRefreshIntervalCallback: (() -> Void) = {}
private let title: String
private var button: NSPopUpButton?
private var valueField: NSTextField?
private var sliderView: NSView? = nil
private var section: PreferencesSection? = nil
private var list: [Network_interface] = []
@@ -54,7 +53,9 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
self.publicIPRefreshInterval = Store.shared.string(key: "\(self.title)_publicIPRefreshInterval", defaultValue: self.publicIPRefreshInterval)
self.baseValue = Store.shared.string(key: "\(self.title)_base", defaultValue: self.baseValue)
super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
super.init(frame: NSRect.zero)
self.orientation = .vertical
self.spacing = Constants.Settings.margin
for interface in SCNetworkInterfaceCopyAll() as NSArray {
if let bsdName = SCNetworkInterfaceGetBSDName(interface as! SCNetworkInterface),
@@ -62,16 +63,6 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
self.list.append(Network_interface(displayName: displayName as String, BSDName: bsdName as String))
}
}
self.orientation = .vertical
self.distribution = .gravityAreas
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
}
required init?(coder: NSCoder) {
@@ -81,88 +72,19 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
public func load(widgets: [widget_t]) {
self.subviews.forEach{ $0.removeFromSuperview() }
let slider = sliderSettingsRow(
title: localizedString("Widget activation threshold"),
action: #selector(self.sliderCallback),
value: self.widgetActivationThreshold,
initialValue: self.widgetActivationThreshold != 0 ? "\(self.widgetActivationThreshold) KB" : localizedString("Disabled"),
min: 0,
max: 1024
)
self.sliderView = slider
self.addArrangedSubview(slider)
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Number of top processes"),
action: #selector(changeNumberOfProcesses),
items: NumbersOfProcesses.map{ "\($0)" },
selected: "\(self.numberOfProcesses)"
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Reset data usage"),
action: #selector(toggleUsageReset),
items: AppUpdateIntervals.dropLast(2).filter({ $0.key != "Silent" }),
selected: self.usageReset
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Reader type"),
action: #selector(changeReaderType),
items: NetworkReaders,
selected: self.readerType
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Base"),
action: #selector(toggleBase),
items: SpeedBase,
selected: self.baseValue
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Auto-refresh public IP address"),
action: #selector(toggleRefreshIPInterval),
items: PublicIPAddressRefreshIntervals,
selected: self.publicIPRefreshInterval
))
self.addArrangedSubview(self.interfaceSelector())
if self.vpnConnection {
self.addArrangedSubview(toggleSettingRow(
title: localizedString("VPN mode"),
action: #selector(toggleVPNMode),
state: self.VPNModeState
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Number of top processes"), component: selectView(
action: #selector(self.changeNumberOfProcesses),
items: NumbersOfProcesses.map{ KeyValue_t(key: "\($0)", value: "\($0)") },
selected: "\(self.numberOfProcesses)"
))
}
self.addArrangedSubview(fieldSettingRow(self,
title: localizedString("Connectivity host (ICMP)"),
value: self.ICMPHost,
placeholder: localizedString("Leave empty to disable the check")
))
}
private func interfaceSelector() -> NSView {
let view = NSStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.heightAnchor.constraint(equalToConstant: Constants.Settings.row).isActive = true
view.orientation = .horizontal
view.alignment = .centerY
view.distribution = .fill
view.spacing = 0
let titleField: NSTextField = LabelField(frame: NSRect(x: 0, y: 0, width: 0, height: 0), localizedString("Network interface"))
titleField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
titleField.textColor = .textColor
let select: NSPopUpButton = NSPopUpButton()
select.target = self
select.action = #selector(self.handleSelection)
select.isEnabled = self.readerType == "interface"
self.button = select
]))
let interfaces = selectView(
action: #selector(self.handleSelection),
items: [],
selected: ""
)
let selectedInterface = Store.shared.string(key: "\(self.title)_interface", defaultValue: "")
let menu = NSMenu()
let autodetection = NSMenuItem(title: localizedString("Autodetection"), action: nil, keyEquivalent: "")
@@ -170,7 +92,6 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
autodetection.tag = 128
menu.addItem(autodetection)
menu.addItem(NSMenuItem.separator())
self.list.forEach { (interface: Network_interface) in
let interfaceMenu = NSMenuItem(title: "\(interface.displayName) (\(interface.BSDName))", action: nil, keyEquivalent: "")
interfaceMenu.identifier = NSUserInterfaceItemIdentifier(rawValue: interface.BSDName)
@@ -179,22 +100,79 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
interfaceMenu.state = .on
}
}
select.menu = menu
select.sizeToFit()
interfaces.menu = menu
interfaces.sizeToFit()
if selectedInterface == "" {
select.selectItem(withTag: 128)
interfaces.selectItem(withTag: 128)
}
view.addArrangedSubview(titleField)
view.addArrangedSubview(NSView())
view.addArrangedSubview(select)
var prefs: [PreferencesRow] = [
PreferencesRow(localizedString("Reader type"), component: selectView(
action: #selector(self.changeReaderType),
items: NetworkReaders,
selected: self.readerType
)),
PreferencesRow(localizedString("Network interface"), component: interfaces),
PreferencesRow(localizedString("Base"), component: selectView(
action: #selector(self.toggleBase),
items: SpeedBase,
selected: self.baseValue
)),
PreferencesRow(localizedString("Reset data usage"), component: selectView(
action: #selector(self.toggleUsageReset),
items: AppUpdateIntervals.dropLast(2).filter({ $0.key != "Silent" }),
selected: self.usageReset
)),
PreferencesRow(localizedString("Auto-refresh public IP address"), component: selectView(
action: #selector(self.toggleRefreshIPInterval),
items: PublicIPAddressRefreshIntervals,
selected: self.publicIPRefreshInterval
))
]
if self.vpnConnection {
prefs.append(PreferencesRow(localizedString("VPN mode"), component: switchView(
action: #selector(self.toggleVPNMode),
state: self.VPNModeState
)))
}
let section = PreferencesSection(prefs)
section.toggleVisibility(1, newState: self.readerType == "interface")
self.addArrangedSubview(section)
self.section = section
return view
self.sliderView = sliderView(
action: #selector(self.sliderCallback),
value: self.widgetActivationThreshold,
initialValue: self.widgetActivationThreshold != 0 ? "\(self.widgetActivationThreshold) KB" : localizedString("Disabled"),
min: 0,
max: 1024,
valueWidth: 70
)
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Widget activation threshold"), component: self.sliderView!)
]))
let valueField: NSTextField = NSTextField()
valueField.widthAnchor.constraint(equalToConstant: 250).isActive = true
valueField.font = NSFont.systemFont(ofSize: 12, weight: .regular)
valueField.textColor = .textColor
valueField.isEditable = true
valueField.isSelectable = true
valueField.isBezeled = false
valueField.canDrawSubviewsIntoLayer = true
valueField.usesSingleLineMode = true
valueField.maximumNumberOfLines = 1
valueField.focusRingType = .none
valueField.stringValue = self.ICMPHost
valueField.delegate = self
valueField.placeholderString = localizedString("Leave empty to disable the check")
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Connectivity host (ICMP)"), component: valueField)
]))
}
@objc func handleSelection(_ sender: NSPopUpButton) {
@objc private func handleSelection(_ sender: NSPopUpButton) {
guard let item = sender.selectedItem, let id = item.identifier?.rawValue else { return }
if id == "autodetection" {
@@ -207,7 +185,6 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
self.callback()
}
@objc private func changeNumberOfProcesses(_ sender: NSMenuItem) {
if let value = Int(sender.title) {
self.numberOfProcesses = value
@@ -215,32 +192,26 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
self.callbackWhenUpdateNumberOfProcesses()
}
}
@objc private func changeReaderType(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else { return }
self.readerType = key
Store.shared.set(key: "\(self.title)_reader", value: key)
self.button?.isEnabled = self.readerType == "interface"
self.section?.toggleVisibility(1, newState: self.readerType == "interface")
NotificationCenter.default.post(name: .resetTotalNetworkUsage, object: nil, userInfo: nil)
}
@objc private func toggleUsageReset(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else { return }
self.usageReset = key
Store.shared.set(key: "\(self.title)_usageReset", value: key)
self.usageResetCallback()
}
@objc func toggleVPNMode(_ sender: NSControl) {
self.VPNModeState = controlState(sender)
Store.shared.set(key: "\(self.title)_VPNMode", value: self.VPNModeState)
}
@objc private func sliderCallback(_ sender: NSSlider) {
let value = Int(sender.doubleValue)
if let container = self.sliderView?.subviews.first(where: { $0.identifier == NSUserInterfaceItemIdentifier("container") }),
let field = container.subviews.first(where: { $0 is NSTextField }), let view = field as? NSTextField {
if let field = self.sliderView?.subviews.first(where: { $0 is NSTextField }), let view = field as? NSTextField {
view.stringValue = value == 0 ? localizedString("Disabled") : "\(value) KB"
}
self.widgetActivationThreshold = value
@@ -261,7 +232,6 @@ internal class Settings: NSStackView, Settings_v, NSTextFieldDelegate {
Store.shared.set(key: "\(self.title)_publicIPRefreshInterval", value: self.publicIPRefreshInterval)
self.publicIPRefreshIntervalCallback()
}
@objc private func toggleBase(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else { return }
self.baseValue = key

View File

@@ -93,5 +93,12 @@
<integer>6</integer>
</dict>
</dict>
<key>Settings</key>
<dict>
<key>popup</key>
<true/>
<key>notifications</key>
<true/>
</dict>
</dict>
</plist>

View File

@@ -57,30 +57,28 @@ class Notifications: NotificationsWrapper {
self.pressureLevel = Store.shared.string(key: "\(self.module)_notifications_pressure", defaultValue: self.pressureLevel)
self.swapSize = Store.shared.string(key: "\(self.module)_notifications_swap", defaultValue: self.swapSize)
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Usage"),
action: #selector(self.changeTotalUsage),
items: notificationLevels,
selected: self.totalUsageLevel
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Free memory (less than)"),
action: #selector(self.changeFree),
items: notificationLevels,
selected: self.freeLevel
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Memory pressure"),
action: #selector(self.changePressure),
items: memoryPressureLevels.filter({ $0.key != "normal" }),
selected: self.pressureLevel
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Swap size"),
action: #selector(self.changeSwap),
items: swapSizes,
selected: self.swapSize
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Usage"), component: selectView(
action: #selector(self.changeTotalUsage),
items: notificationLevels,
selected: self.totalUsageLevel
)),
PreferencesRow(localizedString("Free memory (less than)"), component: selectView(
action: #selector(self.changeFree),
items: notificationLevels,
selected: self.freeLevel
)),
PreferencesRow(localizedString("Memory pressure"), component: selectView(
action: #selector(self.changePressure),
items: memoryPressureLevels.filter({ $0.key != "normal" }),
selected: self.pressureLevel
)),
PreferencesRow(localizedString("Swap size"), component: selectView(
action: #selector(self.changeSwap),
items: swapSizes,
selected: self.swapSize
))
]))
}
required init?(coder: NSCoder) {

View File

@@ -55,6 +55,7 @@ internal class Popup: PopupWrapper {
private var lineChartHistory: Int = 180
private var lineChartScale: Scale = .none
private var lineChartFixedScale: Double = 1
private var chartPrefSection: PreferencesSection? = nil
private var appColorState: Color = .secondBlue
private var appColor: NSColor { self.appColorState.additional as? NSColor ?? NSColor.systemRed }
@@ -284,60 +285,54 @@ internal class Popup: PopupWrapper {
public override func settings() -> NSView? {
let view = SettingsContainerView()
view.addArrangedSubview(selectSettingsRow(
title: localizedString("App color"),
action: #selector(toggleAppColor),
items: Color.allColors,
selected: self.appColorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Wired color"),
action: #selector(toggleWiredColor),
items: Color.allColors,
selected: self.wiredColorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Compressed color"),
action: #selector(toggleCompressedColor),
items: Color.allColors,
selected: self.compressedColorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Free color"),
action: #selector(toggleFreeColor),
items: Color.allColors,
selected: self.freeColorState.key
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Chart color"),
action: #selector(toggleChartColor),
items: Color.allColors,
selected: self.chartColorState.key
))
view.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("App color"), component: selectView(
action: #selector(toggleAppColor),
items: Color.allColors,
selected: self.appColorState.key
)),
PreferencesRow(localizedString("Wired color"), component: selectView(
action: #selector(toggleWiredColor),
items: Color.allColors,
selected: self.wiredColorState.key
)),
PreferencesRow(localizedString("Compressed color"), component: selectView(
action: #selector(toggleCompressedColor),
items: Color.allColors,
selected: self.compressedColorState.key
)),
PreferencesRow(localizedString("Free color"), component: selectView(
action: #selector(toggleFreeColor),
items: Color.allColors,
selected: self.freeColorState.key
))
]))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Chart duration"),
action: #selector(self.toggleLineChartHistory),
items: LineChartHistory,
selected: "\(self.lineChartHistory)"
))
view.addArrangedSubview(selectSettingsRow(
title: localizedString("Main chart scaling"),
action: #selector(self.toggleLineChartScale),
items: Scale.allCases,
selected: self.lineChartScale.key
))
let slider = sliderSettingsRow(
title: localizedString("Scale value"),
self.sliderView = sliderView(
action: #selector(self.toggleLineChartFixedScale),
value: Int(self.lineChartFixedScale * 100),
initialValue: "\(Int(self.lineChartFixedScale * 100)) %",
isHidden: self.lineChartScale != .fixed
initialValue: "\(Int(self.lineChartFixedScale * 100)) %"
)
self.sliderView = slider
view.addArrangedSubview(slider)
self.chartPrefSection = PreferencesSection([
PreferencesRow(localizedString("Chart color"), component: selectView(
action: #selector(self.toggleChartColor),
items: Color.allColors,
selected: self.chartColorState.key
)),
PreferencesRow(localizedString("Chart history"), component: selectView(
action: #selector(self.toggleLineChartHistory),
items: LineChartHistory,
selected: "\(self.lineChartHistory)"
)),
PreferencesRow(localizedString("Main chart scaling"), component: selectView(
action: #selector(self.toggleLineChartScale),
items: Scale.allCases,
selected: self.lineChartScale.key
)),
PreferencesRow(localizedString("Scale value"), component: self.sliderView!)
])
self.chartPrefSection?.toggleVisibility(3, newState: self.lineChartScale == .fixed)
view.addArrangedSubview(self.chartPrefSection!)
return view
}
@@ -406,7 +401,7 @@ internal class Popup: PopupWrapper {
@objc private func toggleLineChartScale(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String,
let value = Scale.allCases.first(where: { $0.key == key }) else { return }
self.sliderView?.isHidden = value != .fixed
self.chartPrefSection?.toggleVisibility(3, newState: value == .fixed)
self.lineChartScale = value
self.chart?.setScale(self.lineChartScale, fixedScale: self.lineChartFixedScale)
Store.shared.set(key: "\(self.title)_lineChartScale", value: key)
@@ -415,8 +410,7 @@ internal class Popup: PopupWrapper {
@objc private func toggleLineChartFixedScale(_ sender: NSSlider) {
let value = Int(sender.doubleValue)
if let container = self.sliderView?.subviews.first(where: { $0.identifier == NSUserInterfaceItemIdentifier("container") }),
let field = container.subviews.first(where: { $0 is NSTextField }), let view = field as? NSTextField {
if let field = self.sliderView?.subviews.first(where: { $0 is NSTextField }), let view = field as? NSTextField {
view.stringValue = "\(value) %"
}

View File

@@ -34,16 +34,10 @@ internal class Settings: NSStackView, Settings_v {
self.splitValueState = Store.shared.bool(key: "\(self.title)_splitValue", defaultValue: self.splitValueState)
self.notificationLevel = Store.shared.string(key: "\(self.title)_notificationLevel", defaultValue: self.notificationLevel)
super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
super.init(frame: NSRect.zero)
self.orientation = .vertical
self.distribution = .gravityAreas
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
}
@@ -54,41 +48,35 @@ internal class Settings: NSStackView, Settings_v {
public func load(widgets: [widget_t]) {
self.subviews.forEach{ $0.removeFromSuperview() }
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Update interval"),
action: #selector(changeUpdateInterval),
items: ReaderUpdateIntervals.map{ "\($0) sec" },
selected: "\(self.updateIntervalValue) sec"
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Update interval"), component: selectView(
action: #selector(self.changeUpdateInterval),
items: ReaderUpdateIntervals.map{ KeyValue_t(key: "\($0)", value: "\($0) sec") },
selected: "\(self.updateIntervalValue) sec"
)),
PreferencesRow(localizedString("Update interval for top processes"), component: selectView(
action: #selector(self.changeUpdateTopInterval),
items: ReaderUpdateIntervals.map{ KeyValue_t(key: "\($0)", value: "\($0) sec") },
selected: "\(self.updateTopIntervalValue) sec"
))
]))
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Update interval for top processes"),
action: #selector(changeUpdateTopInterval),
items: ReaderUpdateIntervals.map{ "\($0) sec" },
selected: "\(self.updateTopIntervalValue) sec"
))
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Number of top processes"),
action: #selector(changeNumberOfProcesses),
items: NumbersOfProcesses.map{ "\($0)" },
selected: "\(self.numberOfProcesses)"
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Number of top processes"), component: selectView(
action: #selector(changeNumberOfProcesses),
items: NumbersOfProcesses.map{ KeyValue_t(key: "\($0)", value: "\($0)") },
selected: "\(self.numberOfProcesses)"
))
]))
if !widgets.filter({ $0 == .barChart }).isEmpty {
self.addArrangedSubview(toggleSettingRow(
title: localizedString("Split the value (App/Wired/Compressed)"),
action: #selector(toggleSplitValue),
state: self.splitValueState
))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Split the value (App/Wired/Compressed)"), component: switchView(
action: #selector(toggleSplitValue),
state: self.splitValueState
))
]))
}
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Notification level"),
action: #selector(changeNotificationLevel),
items: notificationLevels,
selected: self.notificationLevel == "disabled" ? self.notificationLevel : "\(Int((Double(self.notificationLevel) ?? 0)*100))%"
))
}
@objc private func changeUpdateInterval(_ sender: NSMenuItem) {
@@ -98,7 +86,6 @@ internal class Settings: NSStackView, Settings_v {
self.setInterval(value)
}
}
@objc private func changeUpdateTopInterval(_ sender: NSMenuItem) {
if let value = Int(sender.title.replacingOccurrences(of: " sec", with: "")) {
self.updateTopIntervalValue = value
@@ -106,7 +93,6 @@ internal class Settings: NSStackView, Settings_v {
self.setTopInterval(value)
}
}
@objc private func changeNumberOfProcesses(_ sender: NSMenuItem) {
if let value = Int(sender.title) {
self.numberOfProcesses = value
@@ -114,27 +100,9 @@ internal class Settings: NSStackView, Settings_v {
self.callbackWhenUpdateNumberOfProcesses()
}
}
@objc func toggleSplitValue(_ 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.splitValueState = state! == .on ? true : false
@objc private func toggleSplitValue(_ sender: NSControl) {
self.splitValueState = controlState(sender)
Store.shared.set(key: "\(self.title)_splitValue", value: self.splitValueState)
self.callback()
}
@objc func changeNotificationLevel(_ sender: NSMenuItem) {
guard let key = sender.representedObject as? String else { return }
if key == "Disabled" {
Store.shared.set(key: "\(self.title)_notificationLevel", value: key)
} else if let value = Double(key.replacingOccurrences(of: "%", with: "")) {
Store.shared.set(key: "\(self.title)_notificationLevel", value: "\(value/100)")
}
}
}

View File

@@ -51,5 +51,12 @@
<integer>2</integer>
</dict>
</dict>
<key>Settings</key>
<dict>
<key>popup</key>
<true/>
<key>notifications</key>
<true/>
</dict>
</dict>
</plist>

View File

@@ -60,44 +60,19 @@ class Notifications: NotificationsWrapper {
}
}
let header = NSStackView()
header.heightAnchor.constraint(equalToConstant: Constants.Settings.row).isActive = true
header.spacing = 0
let titleField: NSTextField = LabelField(frame: NSRect(x: 0, y: 0, width: 0, height: 0), localizedString(typ.rawValue))
titleField.font = NSFont.systemFont(ofSize: 13, weight: .medium)
titleField.textColor = .labelColor
header.addArrangedSubview(titleField)
header.addArrangedSubview(NSView())
self.addArrangedSubview(header)
let container = NSStackView()
container.orientation = .vertical
container.edgeInsets = NSEdgeInsets(top: 0, left: Constants.Settings.margin, bottom: 0, right: Constants.Settings.margin)
container.spacing = 0
let section = PreferencesSection(label: typ.rawValue)
groups.forEach { (group: SensorGroup) in
filtered.filter{ $0.group == group }.forEach { (s: Sensor_p) in
var items = notificationLevels
if s.type == .temperature {
items = temperatureLevels
}
let row: NSView = selectSettingsRow(
title: localizedString(s.name),
let btn = selectView(
action: #selector(self.changeSensorNotificaion),
items: items,
items: s.type == .temperature ? temperatureLevels : notificationLevels,
selected: s.notificationThreshold
)
row.subviews.filter{ $0 is NSControl }.forEach { (control: NSView) in
control.identifier = NSUserInterfaceItemIdentifier(rawValue: s.key)
}
container.addArrangedSubview(row)
btn.identifier = NSUserInterfaceItemIdentifier(rawValue: s.key)
section.add(PreferencesRow(localizedString(s.name), component: btn))
}
}
self.addArrangedSubview(container)
self.addArrangedSubview(section)
}
}

View File

@@ -44,32 +44,32 @@ internal class Popup: PopupWrapper {
private var fanValueState: FanValue = .percentage
private var sensors: [Sensor_p] = []
private let settingsView: NSStackView = SettingsContainerView()
private let settingsView: NSStackView = NSStackView()
private var fanControlState: Bool {
get {
Store.shared.bool(key: "Sensors_fanControl", defaultValue: true)
}
set {
Store.shared.set(key: "Sensors_fanControl", value: newValue)
}
get { Store.shared.bool(key: "Sensors_fanControl", defaultValue: true) }
set { Store.shared.set(key: "Sensors_fanControl", value: newValue) }
}
public init() {
super.init(frame: NSRect( x: 0, y: 0, width: Constants.Popup.width, height: 0))
self.fanValueState = FanValue(rawValue: Store.shared.string(key: "Sensors_popup_fanValue", defaultValue: self.fanValueState.rawValue)) ?? .percentage
self.orientation = .vertical
self.spacing = 0
self.translatesAutoresizingMaskIntoConstraints = false
self.settingsView.addArrangedSubview(selectSettingsRow(
title: localizedString("Fan value"),
action: #selector(self.toggleFanValue),
items: FanValues,
selected: self.fanValueState.rawValue
))
self.settingsView.orientation = .vertical
self.settingsView.spacing = Constants.Settings.margin
self.fanValueState = FanValue(rawValue: Store.shared.string(key: "Sensors_popup_fanValue", defaultValue: self.fanValueState.rawValue)) ?? .percentage
self.settingsView.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Fan value"), component: selectView(
action: #selector(self.toggleFanValue),
items: FanValues,
selected: self.fanValueState.rawValue
))
]))
}
required init?(coder: NSCoder) {
@@ -86,14 +86,9 @@ internal class Popup: PopupWrapper {
self.subviews.forEach({ $0.removeFromSuperview() })
if !reload {
self.settingsView.subviews.forEach({ $0.removeFromSuperview() })
self.settingsView.addArrangedSubview(selectSettingsRow(
title: localizedString("Fan value"),
action: #selector(self.toggleFanValue),
items: FanValues,
selected: self.fanValueState.rawValue
))
self.settingsView.subviews.filter({ $0.identifier == NSUserInterfaceItemIdentifier("sensor") }).forEach { v in
v.removeFromSuperview()
}
}
if !fans.isEmpty {
@@ -141,35 +136,19 @@ internal class Popup: PopupWrapper {
}
if !reload {
let header = NSStackView()
header.heightAnchor.constraint(equalToConstant: Constants.Settings.row).isActive = true
header.spacing = 0
let titleField: NSTextField = LabelField(frame: NSRect(x: 0, y: 0, width: 0, height: 0), localizedString(typ.rawValue))
titleField.font = NSFont.systemFont(ofSize: 13, weight: .medium)
titleField.textColor = .labelColor
header.addArrangedSubview(titleField)
header.addArrangedSubview(NSView())
self.settingsView.addArrangedSubview(header)
let container = NSStackView()
container.orientation = .vertical
container.edgeInsets = NSEdgeInsets(top: 0, left: Constants.Settings.margin, bottom: 0, right: Constants.Settings.margin)
container.spacing = 0
let section = PreferencesSection(label: typ.rawValue)
section.identifier = NSUserInterfaceItemIdentifier("sensor")
groups.forEach { (group: SensorGroup) in
filtered.filter{ $0.group == group }.forEach { (s: Sensor_p) in
let row: NSView = toggleSettingRow(title: localizedString(s.name), action: #selector(self.toggleSensor), state: s.popupState)
row.subviews.filter{ $0 is NSControl }.forEach { (control: NSView) in
control.identifier = NSUserInterfaceItemIdentifier(rawValue: s.key)
}
container.addArrangedSubview(row)
let btn = switchView(
action: #selector(self.toggleSensor),
state: s.popupState
)
btn.identifier = NSUserInterfaceItemIdentifier(rawValue: s.key)
section.add(PreferencesRow(localizedString(s.name), component: btn))
}
}
self.settingsView.addArrangedSubview(container)
self.settingsView.addArrangedSubview(section)
}
if typ == .fan { return }

View File

@@ -33,18 +33,8 @@ internal class Settings: NSStackView, Settings_v {
self.title = module.rawValue
self.hidState = SystemKit.shared.device.platform == .m1 ? true : false
super.init(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
self.wantsLayer = true
super.init(frame: NSRect.zero)
self.orientation = .vertical
self.distribution = .gravityAreas
self.translatesAutoresizingMaskIntoConstraints = false
self.edgeInsets = NSEdgeInsets(
top: Constants.Settings.margin,
left: Constants.Settings.margin,
bottom: Constants.Settings.margin,
right: Constants.Settings.margin
)
self.spacing = Constants.Settings.margin
self.updateIntervalValue = Store.shared.int(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue)
@@ -53,6 +43,44 @@ internal class Settings: NSStackView, Settings_v {
self.fansSyncState = Store.shared.bool(key: "\(self.title)_fansSync", defaultValue: self.fansSyncState)
self.unknownSensorsState = Store.shared.bool(key: "\(self.title)_unknown", defaultValue: self.unknownSensorsState)
self.fanValueState = FanValue(rawValue: Store.shared.string(key: "\(self.title)_fanValue", defaultValue: self.fanValueState.rawValue)) ?? .percentage
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Update interval"), component: selectView(
action: #selector(self.changeUpdateInterval),
items: ReaderUpdateIntervals.map{ KeyValue_t(key: "\($0)", value: "\($0) sec") },
selected: "\(self.updateIntervalValue) sec"
))
]))
self.addArrangedSubview(PreferencesSection([
PreferencesRow(localizedString("Fan value"), component: selectView(
action: #selector(self.toggleFanValue),
items: FanValues,
selected: self.fanValueState.rawValue
)),
PreferencesRow(localizedString("Save the fan speed"), component: switchView(
action: #selector(self.toggleSpeedState),
state: self.fanSpeedState
)),
PreferencesRow(localizedString("Synchronize fan's control"), component: switchView(
action: #selector(self.toggleFansSync),
state: self.fansSyncState
))
]))
var sensorsPrefs: [PreferencesRow] = [
PreferencesRow(localizedString("Show unknown sensors"), component: switchView(
action: #selector(self.toggleuUnknownSensors),
state: self.unknownSensorsState
))
]
if isARM {
sensorsPrefs.append(PreferencesRow(localizedString("HID sensors"), component: switchView(
action: #selector(self.toggleHID),
state: self.hidState
)))
}
self.addArrangedSubview(PreferencesSection(sensorsPrefs))
}
required init?(coder: NSCoder) {
@@ -68,48 +96,10 @@ internal class Settings: NSStackView, Settings_v {
sensors = sensors.filter({ $0.group != .unknown })
}
self.subviews.forEach{ $0.removeFromSuperview() }
self.addArrangedSubview(selectSettingsRowV1(
title: localizedString("Update interval"),
action: #selector(changeUpdateInterval),
items: ReaderUpdateIntervals.map{ "\($0) sec" },
selected: "\(self.updateIntervalValue) sec"
))
self.addArrangedSubview(toggleSettingRow(
title: localizedString("Save the fan speed"),
action: #selector(toggleSpeedState),
state: self.fanSpeedState
))
self.addArrangedSubview(toggleSettingRow(
title: localizedString("Synchronize fan's control"),
action: #selector(toggleFansSync),
state: self.fansSyncState
))
self.addArrangedSubview(selectSettingsRow(
title: localizedString("Fan value"),
action: #selector(toggleFanValue),
items: FanValues,
selected: self.fanValueState.rawValue
))
if isARM {
self.addArrangedSubview(toggleSettingRow(
title: localizedString("HID sensors"),
action: #selector(toggleHID),
state: self.hidState
))
self.subviews.filter({ $0.identifier == NSUserInterfaceItemIdentifier("sensor") }).forEach { v in
v.removeFromSuperview()
}
self.addArrangedSubview(toggleSettingRow(
title: localizedString("Show unknown sensors"),
action: #selector(toggleuUnknownSensors),
state: self.unknownSensorsState
))
var types: [SensorType] = []
sensors.forEach { (s: Sensor_p) in
if !types.contains(s.type) {
@@ -118,18 +108,8 @@ internal class Settings: NSStackView, Settings_v {
}
types.forEach { (typ: SensorType) in
let header = NSStackView()
header.heightAnchor.constraint(equalToConstant: Constants.Settings.row).isActive = true
header.spacing = 0
let titleField: NSTextField = LabelField(frame: NSRect(x: 0, y: 0, width: 0, height: 0), localizedString(typ.rawValue))
titleField.font = NSFont.systemFont(ofSize: 13, weight: .medium)
titleField.textColor = .labelColor
header.addArrangedSubview(titleField)
header.addArrangedSubview(NSView())
self.addArrangedSubview(header)
let section = PreferencesSection(label: typ.rawValue)
section.identifier = NSUserInterfaceItemIdentifier("sensor")
let filtered = sensors.filter{ $0.type == typ }
var groups: [SensorGroup] = []
@@ -138,28 +118,16 @@ internal class Settings: NSStackView, Settings_v {
groups.append(s.group)
}
}
let container = NSStackView()
container.orientation = .vertical
container.edgeInsets = NSEdgeInsets(
top: 0,
left: Constants.Settings.margin,
bottom: 0,
right: Constants.Settings.margin
)
container.spacing = 0
groups.forEach { (group: SensorGroup) in
filtered.filter{ $0.group == group }.forEach { (s: Sensor_p) in
let row: NSView = toggleSettingRow(title: localizedString(s.name), action: #selector(self.toggleFan), state: s.state)
row.subviews.filter{ $0 is NSControl }.forEach { (control: NSView) in
control.identifier = NSUserInterfaceItemIdentifier(rawValue: s.key)
}
container.addArrangedSubview(row)
section.add(PreferencesRow(localizedString(s.name), component: switchView(
action: #selector(self.toggleSensor),
state: s.state
)))
}
}
self.addArrangedSubview(container)
self.addArrangedSubview(section)
}
self.widgets = widgets
@@ -171,12 +139,11 @@ internal class Settings: NSStackView, Settings_v {
self.load(widgets: self.widgets)
}
@objc private func toggleFan(_ sender: NSControl) {
@objc private func toggleSensor(_ sender: NSControl) {
guard let id = sender.identifier else { return }
Store.shared.set(key: "sensor_\(id.rawValue)", value: controlState(sender))
self.callback()
}
@objc private func changeUpdateInterval(_ sender: NSMenuItem) {
if let value = Int(sender.title.replacingOccurrences(of: " sec", with: "")) {
self.updateIntervalValue = value
@@ -184,30 +151,25 @@ internal class Settings: NSStackView, Settings_v {
self.setInterval(value)
}
}
@objc private func toggleSpeedState(_ sender: NSControl) {
self.fanSpeedState = controlState(sender)
Store.shared.set(key: "\(self.title)_speed", value: self.fanSpeedState)
self.callback()
}
@objc private func toggleHID(_ sender: NSControl) {
self.hidState = controlState(sender)
Store.shared.set(key: "\(self.title)_hid", value: self.hidState)
self.HIDcallback()
}
@objc private func toggleFansSync(_ sender: NSControl) {
self.fansSyncState = controlState(sender)
Store.shared.set(key: "\(self.title)_fansSync", value: self.fansSyncState)
}
@objc private func toggleuUnknownSensors(_ sender: NSControl) {
self.unknownSensorsState = controlState(sender)
Store.shared.set(key: "\(self.title)_unknown", value: self.unknownSensorsState)
self.unknownCallback()
}
@objc private func toggleFanValue(_ sender: NSMenuItem) {
if let key = sender.representedObject as? String, let value = FanValue(rawValue: key) {
self.fanValueState = value

View File

@@ -1078,8 +1078,8 @@
children = (
9ABFF902248BEBD700C9041A /* main.swift */,
9ABFF90F248BEE7200C9041A /* readers.swift */,
5EE8037E29C36BDD0063D37D /* portal.swift */,
9ABFF913248C30A800C9041A /* popup.swift */,
5EE8037E29C36BDD0063D37D /* portal.swift */,
9AD64FA124BF86C100419D59 /* settings.swift */,
5CD342F32B2F2FB700225631 /* notifications.swift */,
9ABFF8F9248BEBCB00C9041A /* Info.plist */,