feat: add back the preferences for the new layout algo

This commit is contained in:
louis.pontoise authored and lwouis committed 2020-03-10 14:00:37 +09:00
1 parent 89977d78ee
commit d52eb6d074
6 files changed
+72 -47

No files matched your search

+2 -2
View File
@@ -40,8 +40,8 @@ func keyboardHandler(proxy: CGEventTapProxy, type: CGEventType, event_: CGEvent,
if type == .keyDown || type == .keyUp || type == .flagsChanged { if type == .keyDown || type == .keyUp || type == .flagsChanged {
if let event = NSEvent(cgEvent: event_) { if let event = NSEvent(cgEvent: event_) {
let isTab = event.keyCode == Preferences.tabKeyCode let isTab = event.keyCode == Preferences.tabKeyCode
let isMetaChanged = Preferences.metaKeyCodes!.contains(event.keyCode) let isMetaChanged = Preferences.metaKeyCodes.contains(event.keyCode)
let isMetaDown = event.modifierFlags.contains(Preferences.metaModifierFlag!) let isMetaDown = event.modifierFlags.contains(Preferences.metaModifierFlag)
let isRightArrow = event.keyCode == kVK_RightArrow let isRightArrow = event.keyCode == kVK_RightArrow
let isLeftArrow = event.keyCode == kVK_LeftArrow let isLeftArrow = event.keyCode == kVK_LeftArrow
let isEscape = event.keyCode == kVK_Escape let isEscape = event.keyCode == kVK_Escape
+37 -18
View File
@@ -5,18 +5,11 @@ import Carbon.HIToolbox.Events
class Preferences { class Preferences {
// the following constant are not exposed as preferences but may be in the future, probably through macro preferences // the following constant are not exposed as preferences but may be in the future, probably through macro preferences
static let windowMaterial = NSVisualEffectView.Material.dark static let windowMaterial = NSVisualEffectView.Material.dark
static let iconSize = CGFloat(32)
static let fontColor = NSColor.white static let fontColor = NSColor.white
static let fontHeight = CGFloat(15)
static let font = NSFont.systemFont(ofSize: fontHeight)
static let windowPadding = CGFloat(23) static let windowPadding = CGFloat(23)
static let interCellPadding = CGFloat(5) static let interCellPadding = CGFloat(5)
static let intraCellPadding = CGFloat(5) static let intraCellPadding = CGFloat(5)
static let fontIconSize = CGFloat(20) static let fontIconSize = CGFloat(20)
static let maxScreenUsage = CGFloat(0.8)
static let minCellsPerRow = CGFloat(5)
static let maxCellsPerRow = minCellsPerRow * 2
static let nCellsRows = CGFloat(3)
static let themeMacro = MacroPreferenceHelper<(CGFloat, CGFloat, CGFloat, NSColor, NSColor)>([ static let themeMacro = MacroPreferenceHelper<(CGFloat, CGFloat, CGFloat, NSColor, NSColor)>([
MacroPreference(" macOS", (0, 5, 20, .clear, NSColor(red: 0, green: 0, blue: 0, alpha: 0.4))), MacroPreference(" macOS", (0, 5, 20, .clear, NSColor(red: 0, green: 0, blue: 0, alpha: 0.4))),
@@ -33,6 +26,12 @@ class Preferences {
]) ])
static var defaults: [String: String] = [ static var defaults: [String: String] = [
"maxScreenUsage": "80",
"minCellsPerRow": "5",
"maxCellsPerRow": "10",
"minRows": "3",
"iconSize": "32",
"fontHeight": "15",
"tabKeyCode": String(kVK_Tab), "tabKeyCode": String(kVK_Tab),
"metaKey": metaKeyMacro.macros[0].label, "metaKey": metaKeyMacro.macros[0].label,
"windowDisplayDelay": "0", "windowDisplayDelay": "0",
@@ -42,17 +41,24 @@ class Preferences {
] ]
static var rawValues = [String: String]() static var rawValues = [String: String]()
static var cellBorderWidth: CGFloat? static var cellBorderWidth: CGFloat!
static var cellCornerRadius: CGFloat? static var cellCornerRadius: CGFloat!
static var tabKeyCode: UInt16? static var tabKeyCode: UInt16!
static var highlightBorderColor: NSColor? static var highlightBorderColor: NSColor!
static var highlightBackgroundColor: NSColor? static var highlightBackgroundColor: NSColor!
static var metaKeyCodes: [UInt16]? static var metaKeyCodes: [UInt16]!
static var metaModifierFlag: NSEvent.ModifierFlags? static var metaModifierFlag: NSEvent.ModifierFlags!
static var windowDisplayDelay: DispatchTimeInterval? static var windowDisplayDelay: DispatchTimeInterval!
static var windowCornerRadius: CGFloat? static var windowCornerRadius: CGFloat!
static var showOnScreen: ShowOnScreenPreference? static var showOnScreen: ShowOnScreenPreference!
static var hideSpaceNumberLabels: Bool? static var hideSpaceNumberLabels: Bool!
static var maxScreenUsage: CGFloat!
static var iconSize: CGFloat!
static var fontHeight: CGFloat!
static var font: NSFont!
static var minCellsPerRow: CGFloat!
static var maxCellsPerRow: CGFloat!
static var minRows: CGFloat!
private static let defaultsFile = fileFromPreferencesFolder("alt-tab-macos-defaults.json") private static let defaultsFile = fileFromPreferencesFolder("alt-tab-macos-defaults.json")
private static let userFile = fileFromPreferencesFolder("alt-tab-macos.json") private static let userFile = fileFromPreferencesFolder("alt-tab-macos.json")
@@ -84,6 +90,19 @@ class Preferences {
static func updateAndValidateFromString(_ valueName: String, _ value: String) throws { static func updateAndValidateFromString(_ valueName: String, _ value: String) throws {
switch valueName { switch valueName {
case "maxScreenUsage":
maxScreenUsage = try CGFloat(CGFloat(value).orThrow() / 100)
case "minCellsPerRow":
minCellsPerRow = try CGFloat(value).orThrow()
case "maxCellsPerRow":
maxCellsPerRow = try CGFloat(value).orThrow()
case "minRows":
minRows = try CGFloat(value).orThrow()
case "iconSize":
iconSize = try CGFloat(value).orThrow()
case "fontHeight":
fontHeight = try CGFloat(value).orThrow()
font = NSFont.systemFont(ofSize: fontHeight)
case "tabKeyCode": case "tabKeyCode":
tabKeyCode = try UInt16(value).orThrow() tabKeyCode = try UInt16(value).orThrow()
case "metaKey": case "metaKey":
+1 -1
View File
@@ -92,7 +92,7 @@ class App: NSApplication, NSApplicationDelegate, NSWindowDelegate {
Windows.refreshAllThumbnails() Windows.refreshAllThumbnails()
Windows.focusedWindowIndex = 0 Windows.focusedWindowIndex = 0
Windows.cycleFocusedWindowIndex(step) Windows.cycleFocusedWindowIndex(step)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Preferences.windowDisplayDelay!, execute: { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Preferences.windowDisplayDelay, execute: {
self.refreshOpenUi() self.refreshOpenUi()
if self.uiWorkShouldBeDone { self.thumbnailsPanel?.show() } if self.uiWorkShouldBeDone { self.thumbnailsPanel?.show() }
}) })
+7 -7
View File
@@ -34,8 +34,8 @@ class Cell: NSCollectionViewItem {
override var isSelected: Bool { override var isSelected: Bool {
didSet { didSet {
view.layer!.backgroundColor = isSelected ? Preferences.highlightBackgroundColor!.cgColor : .clear view.layer!.backgroundColor = isSelected ? Preferences.highlightBackgroundColor.cgColor : .clear
view.layer!.borderColor = isSelected ? Preferences.highlightBorderColor!.cgColor : .clear view.layer!.borderColor = isSelected ? Preferences.highlightBorderColor.cgColor : .clear
} }
} }
@@ -55,7 +55,7 @@ class Cell: NSCollectionViewItem {
label.font = Preferences.font label.font = Preferences.font
hiddenIcon.isHidden = !window!.isHidden hiddenIcon.isHidden = !window!.isHidden
minimizedIcon.isHidden = !window!.isMinimized minimizedIcon.isHidden = !window!.isMinimized
spaceIcon.isHidden = element.spaceIndex == nil || Spaces.isSingleSpace || Preferences.hideSpaceNumberLabels! spaceIcon.isHidden = element.spaceIndex == nil || Spaces.isSingleSpace || Preferences.hideSpaceNumberLabels
if !spaceIcon.isHidden { if !spaceIcon.isHidden {
if element.isOnAllSpaces { if element.isOnAllSpaces {
spaceIcon.setStar() spaceIcon.setStar()
@@ -93,8 +93,8 @@ class Cell: NSCollectionViewItem {
let vStackView = NSStackView() let vStackView = NSStackView()
vStackView.wantsLayer = true vStackView.wantsLayer = true
vStackView.layer!.backgroundColor = .clear vStackView.layer!.backgroundColor = .clear
vStackView.layer!.cornerRadius = Preferences.cellCornerRadius! vStackView.layer!.cornerRadius = Preferences.cellCornerRadius
vStackView.layer!.borderWidth = Preferences.cellBorderWidth! vStackView.layer!.borderWidth = Preferences.cellBorderWidth
vStackView.layer!.borderColor = .clear vStackView.layer!.borderColor = .clear
vStackView.edgeInsets = NSEdgeInsets(top: Preferences.intraCellPadding, left: Preferences.intraCellPadding, bottom: Preferences.intraCellPadding, right: Preferences.intraCellPadding) vStackView.edgeInsets = NSEdgeInsets(top: Preferences.intraCellPadding, left: Preferences.intraCellPadding, bottom: Preferences.intraCellPadding, right: Preferences.intraCellPadding)
vStackView.orientation = .vertical vStackView.orientation = .vertical
@@ -104,7 +104,7 @@ class Cell: NSCollectionViewItem {
} }
static func downscaleFactor() -> CGFloat { static func downscaleFactor() -> CGFloat {
let nCellsBeforePotentialOverflow = Preferences.nCellsRows * Preferences.minCellsPerRow let nCellsBeforePotentialOverflow = Preferences.minRows * Preferences.minCellsPerRow
guard CGFloat(Windows.list.count) > nCellsBeforePotentialOverflow else { return 1 } guard CGFloat(Windows.list.count) > nCellsBeforePotentialOverflow else { return 1 }
// TODO: replace this buggy heuristic with a correct implementation of downscaling // TODO: replace this buggy heuristic with a correct implementation of downscaling
return nCellsBeforePotentialOverflow / (nCellsBeforePotentialOverflow + (sqrt(CGFloat(Windows.list.count) - nCellsBeforePotentialOverflow) * 2)) return nCellsBeforePotentialOverflow / (nCellsBeforePotentialOverflow + (sqrt(CGFloat(Windows.list.count) - nCellsBeforePotentialOverflow) * 2))
@@ -119,7 +119,7 @@ class Cell: NSCollectionViewItem {
} }
static func height(_ screen: NSScreen) -> CGFloat { static func height(_ screen: NSScreen) -> CGFloat {
return (ThumbnailsPanel.heightMax(screen) / Preferences.nCellsRows - Preferences.interCellPadding) * Cell.downscaleFactor() return (ThumbnailsPanel.heightMax(screen) / Preferences.minRows - Preferences.interCellPadding) * Cell.downscaleFactor()
} }
static func width(_ image: NSImage?, _ screen: NSScreen) -> CGFloat { static func width(_ image: NSImage?, _ screen: NSScreen) -> CGFloat {
+24 -18
View File
@@ -78,14 +78,20 @@ class PreferencesWindow: NSWindow, NSWindowDelegate {
} }
return [ return [
makeLabelWithDropdown("Alt key", rawName: "metaKey", values: Preferences.metaKeyMacro.labels), makeLabelWithDropdown("Alt key", "metaKey", Preferences.metaKeyMacro.labels),
makeLabelWithInput("Tab key", rawName: "tabKeyCode", width: 33, suffixText: "KeyCodes Reference", suffixUrl: "https://eastmanreference.com/complete-list-of-applescript-key-codes", validator: tabKeyCodeValidator), makeLabelWithInput("Tab key", "tabKeyCode", 33, "KeyCodes Reference", "https://eastmanreference.com/complete-list-of-applescript-key-codes", tabKeyCodeValidator),
makeHorizontalSeparator(), makeHorizontalSeparator(),
makeLabelWithDropdown("Theme", rawName: "theme", values: Preferences.themeMacro.labels), makeLabelWithDropdown("Theme", "theme", Preferences.themeMacro.labels),
makeLabelWithCheckbox("Hide space number labels", rawName: "hideSpaceNumberLabels"), makeLabelWithSlider("Max size on screen", "maxScreenUsage", 10, 100, 10, true, "%"),
makeLabelWithSlider("Min windows per row", "minCellsPerRow", 1, 20, 20, true),
makeLabelWithSlider("Max windows per row", "maxCellsPerRow", 1, 40, 20, true),
makeLabelWithSlider("Min rows of windows", "minRows", 1, 20, 20, true),
makeLabelWithSlider("Window app icon size", "iconSize", 0, 64, 11, false, "px"),
makeLabelWithSlider("Window title font size", "fontHeight", 0, 64, 11, false, "px"),
makeLabelWithCheckbox("Hide space number labels", "hideSpaceNumberLabels"),
makeHorizontalSeparator(), makeHorizontalSeparator(),
makeLabelWithSlider("Window apparition delay", rawName: "windowDisplayDelay", minValue: 0, maxValue: 2000, numberOfTickMarks: 0, unitText: "ms"), makeLabelWithSlider("Apparition delay", "windowDisplayDelay", 0, 2000, 11, false, "ms"),
makeLabelWithDropdown("Show on", rawName: "showOnScreen", values: Preferences.showOnScreenMacro.labels) makeLabelWithDropdown("Show on", "showOnScreen", Preferences.showOnScreenMacro.labels)
] ]
} }
@@ -96,7 +102,7 @@ class PreferencesWindow: NSWindow, NSWindowDelegate {
return view return view
} }
private func makeLabelWithInput(_ labelText: String, rawName: String, width: CGFloat? = nil, suffixText: String? = nil, suffixUrl: String? = nil, validator: ((String) -> Bool)? = nil) -> NSStackView { private func makeLabelWithInput(_ labelText: String, _ rawName: String, _ width: CGFloat? = nil, _ suffixText: String? = nil, _ suffixUrl: String? = nil, _ validator: ((String) -> Bool)? = nil) -> NSStackView {
let input = TextField(Preferences.rawValues[rawName]!) let input = TextField(Preferences.rawValues[rawName]!)
input.validationHandler = validator input.validationHandler = validator
input.delegate = input input.delegate = input
@@ -105,24 +111,24 @@ class PreferencesWindow: NSWindow, NSWindowDelegate {
input.widthAnchor.constraint(equalToConstant: width!).isActive = true input.widthAnchor.constraint(equalToConstant: width!).isActive = true
} }
return makeLabelWithProvidedControl(labelText, rawName: rawName, control: input, suffixText: suffixText, suffixUrl: suffixUrl) return makeLabelWithProvidedControl(labelText, rawName, input, suffixText, nil, suffixUrl)
} }
private func makeLabelWithCheckbox(_ labelText: String, rawName: String) -> NSStackView { private func makeLabelWithCheckbox(_ labelText: String, _ rawName: String) -> NSStackView {
let checkbox = NSButton.init(checkboxWithTitle: "", target: nil, action: nil) let checkbox = NSButton.init(checkboxWithTitle: "", target: nil, action: nil)
setControlValue(checkbox, Preferences.rawValues[rawName]!) setControlValue(checkbox, Preferences.rawValues[rawName]!)
return makeLabelWithProvidedControl(labelText, rawName: rawName, control: checkbox) return makeLabelWithProvidedControl(labelText, rawName, checkbox)
} }
private func makeLabelWithDropdown(_ labelText: String, rawName: String, values: [String], suffixText: String? = nil) -> NSStackView { private func makeLabelWithDropdown(_ labelText: String, _ rawName: String, _ values: [String], _ suffixText: String? = nil) -> NSStackView {
let popUp = NSPopUpButton() let popUp = NSPopUpButton()
popUp.addItems(withTitles: values) popUp.addItems(withTitles: values)
popUp.selectItem(withTitle: Preferences.rawValues[rawName]!) popUp.selectItem(withTitle: Preferences.rawValues[rawName]!)
return makeLabelWithProvidedControl(labelText, rawName: rawName, control: popUp, suffixText: suffixText) return makeLabelWithProvidedControl(labelText, rawName, popUp, suffixText)
} }
private func makeLabelWithSlider(_ labelText: String, rawName: String, minValue: Double, maxValue: Double, numberOfTickMarks: Int, unitText: String = "") -> NSStackView { private func makeLabelWithSlider(_ labelText: String, _ rawName: String, _ minValue: Double, _ maxValue: Double, _ numberOfTickMarks: Int, _ allowsTickMarkValuesOnly: Bool, _ unitText: String = "") -> NSStackView {
let value = Preferences.rawValues[rawName]! let value = Preferences.rawValues[rawName]!
let suffixText = value + unitText let suffixText = value + unitText
let slider = NSSlider() let slider = NSSlider()
@@ -130,14 +136,14 @@ class PreferencesWindow: NSWindow, NSWindowDelegate {
slider.maxValue = maxValue slider.maxValue = maxValue
slider.stringValue = value slider.stringValue = value
slider.numberOfTickMarks = numberOfTickMarks slider.numberOfTickMarks = numberOfTickMarks
slider.allowsTickMarkValuesOnly = numberOfTickMarks > 1 slider.allowsTickMarkValuesOnly = allowsTickMarkValuesOnly
slider.tickMarkPosition = .below slider.tickMarkPosition = .below
slider.isContinuous = true slider.isContinuous = true
return makeLabelWithProvidedControl(labelText, rawName: rawName, control: slider, suffixText: suffixText, suffixWidth: 60) return makeLabelWithProvidedControl(labelText, rawName, slider, suffixText, 60)
} }
private func makeLabelWithProvidedControl(_ labelText: String?, rawName: String, control: NSControl, suffixText: String? = nil, suffixWidth: CGFloat? = nil, suffixUrl: String? = nil) -> NSStackView { private func makeLabelWithProvidedControl(_ labelText: String?, _ rawName: String, _ control: NSControl, _ suffixText: String? = nil, _ suffixWidth: CGFloat? = nil, _ suffixUrl: String? = nil) -> NSStackView {
let label = NSTextField(wrappingLabelWithString: (labelText != nil ? labelText! + ": " : "")) let label = NSTextField(wrappingLabelWithString: (labelText != nil ? labelText! + ": " : ""))
label.alignment = .right label.alignment = .right
label.widthAnchor.constraint(equalToConstant: labelWidth).isActive = true label.widthAnchor.constraint(equalToConstant: labelWidth).isActive = true
@@ -150,14 +156,14 @@ class PreferencesWindow: NSWindow, NSWindowDelegate {
let containerView = NSStackView(views: [label, control]) let containerView = NSStackView(views: [label, control])
if suffixText != nil { if suffixText != nil {
let suffix = makeSuffix(controlName: rawName, text: suffixText!, width: suffixWidth, url: suffixUrl) let suffix = makeSuffix(rawName, suffixText!, suffixWidth, suffixUrl)
containerView.addView(suffix, in: .leading) containerView.addView(suffix, in: .leading)
} }
return containerView return containerView
} }
private func makeSuffix(controlName: String, text: String, width: CGFloat? = nil, url: String? = nil) -> NSTextField { private func makeSuffix(_ controlName: String, _ text: String, _ width: CGFloat? = nil, _ url: String? = nil) -> NSTextField {
let suffix: NSTextField let suffix: NSTextField
if url == nil { if url == nil {
suffix = NSTextField(labelWithString: text) suffix = NSTextField(labelWithString: text)
+1 -1
View File
@@ -41,7 +41,7 @@ class ThumbnailsPanel: NSPanel, NSCollectionViewDataSource, NSCollectionViewDele
backgroundView.material = Preferences.windowMaterial backgroundView.material = Preferences.windowMaterial
backgroundView.state = .active backgroundView.state = .active
backgroundView.wantsLayer = true backgroundView.wantsLayer = true
backgroundView.layer!.cornerRadius = Preferences.windowCornerRadius! backgroundView.layer!.cornerRadius = Preferences.windowCornerRadius
return backgroundView return backgroundView
} }