Skip to content

Commit

Permalink
feat: split max screen size preference into width/height (closes #579)
Browse files Browse the repository at this point in the history
  • Loading branch information
lwouis committed Sep 8, 2020
1 parent af5ed9b commit 6e2e5b4
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 29 deletions.
35 changes: 18 additions & 17 deletions src/logic/Preferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import ShortcutRecorder
let defaults = UserDefaults.standard

class Preferences {
static var defaultsDependingOnScreenRatio_ = defaultsDependingOnScreenRatio()

// default values
static var defaultValues: [String: String] = [
"maxScreenUsage": "80",
"maxWidthOnScreen": "80",
"maxHeightOnScreen": "80",
"iconSize": "32",
"fontHeight": "15",
"holdShortcut": "",
Expand Down Expand Up @@ -73,9 +72,10 @@ class Preferences {
static var intraCellPadding: CGFloat { 5 }

// persisted values
static var maxScreenUsage: CGFloat { defaults.cgfloat("maxScreenUsage") / CGFloat(100) }
static var minCellsPerRow: CGFloat { defaults.cgfloat("minCellsPerRow") }
static var maxCellsPerRow: CGFloat { defaults.cgfloat("maxCellsPerRow") }
static var maxWidthOnScreen: CGFloat { defaults.cgfloat("maxWidthOnScreen") / CGFloat(100) }
static var maxHeightOnScreen: CGFloat { defaults.cgfloat("maxHeightOnScreen") / CGFloat(100) }
static var windowMaxWidthInRow: CGFloat { defaults.cgfloat("windowMaxWidthInRow") / CGFloat(100) }
static var windowMinWidthInRow: CGFloat { defaults.cgfloat("windowMinWidthInRow") / CGFloat(100) }
static var rowsCount: CGFloat { defaults.cgfloat("rowsCount") }
static var iconSize: CGFloat { defaults.cgfloat("iconSize") }
static var fontHeight: CGFloat { defaults.cgfloat("fontHeight") }
Expand Down Expand Up @@ -188,6 +188,13 @@ class Preferences {
defaults.set(App.version, forKey: preferencesVersion)
}

private static func migrateMaxSizeOnScreenToWidthAndHeight() {
if let old = defaults.string(forKey: "maxScreenUsage") {
defaults.set(old, forKey: "maxWidthOnScreen")
defaults.set(old, forKey: "maxHeightOnScreen")
}
}

// dropdowns preferences used to store English text; now they store indexes
static func migrateDropdownMenuPreference(_ preference: String, _ oldAndNew: [String: String]) {
if let old = defaults.string(forKey: preference),
Expand All @@ -206,19 +213,13 @@ class Preferences {
}
}

static func defaultsDependingOnScreenRatio() -> [String: String] {
let ratio = Screen.mainScreenRatio()
// landscape
if ratio > 1 {
// 15/10 and wider; tested with 16/10 and 16/9
if ratio > (15 / 10) {
return ["rowsCount": "4", "minCellsPerRow": "4", "maxCellsPerRow": "7"]
}
// narrower than 15/10; tested with 4/3
return ["rowsCount": "3", "minCellsPerRow": "4", "maxCellsPerRow": "7"]
static func rowCountDependingOnScreenRatio() -> String {
// landscape; tested with 4/3, 16/10, 16/9
if Screen.mainScreenRatio() > 1 {
return "4"
}
// vertical; tested with 10/16
return ["rowsCount": "6", "minCellsPerRow": "3", "maxCellsPerRow": "4"]
return "6"
}

static func keyAboveTabDependingOnInputSource() -> String {
Expand Down
6 changes: 3 additions & 3 deletions src/ui/main-window/ThumbnailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class ThumbnailView: NSStackView {
}
dockLabelIcon.setFrameOrigin(NSPoint(x: appIcon.frame.maxX - dockLabelIcon.fittingSize.width - 1, y: appIcon.frame.maxY - dockLabelIcon.fittingSize.height + 4))
}
assignIfDifferent(&frame.size.width, max((Preferences.hideThumbnails ? hStackView.fittingSize.width : thumbnail.frame.size.width) + Preferences.intraCellPadding * 2, ThumbnailView.widthMin(screen)))
assignIfDifferent(&frame.size.width, max((Preferences.hideThumbnails ? hStackView.fittingSize.width : thumbnail.frame.size.width) + Preferences.intraCellPadding * 2, ThumbnailView.widthMin(screen)).rounded())
assignIfDifferent(&frame.size.height, newHeight)
let fontIconWidth = CGFloat([fullscreenIcon, minimizedIcon, hiddenIcon, spaceIcon].filter { !$0.isHidden }.count) * (Preferences.fontHeight + Preferences.intraCellPadding)
assignIfDifferent(&label.textContainer!.size.width, frame.width - Preferences.iconSize - Preferences.intraCellPadding * 3 - fontIconWidth)
Expand Down Expand Up @@ -249,11 +249,11 @@ class ThumbnailView: NSStackView {
}

static func widthMax(_ screen: NSScreen) -> CGFloat {
return (ThumbnailsPanel.widthMax(screen) - Preferences.interCellPadding) / Preferences.minCellsPerRow - Preferences.interCellPadding
return ThumbnailsPanel.widthMax(screen) * Preferences.windowMaxWidthInRow - Preferences.interCellPadding * 2
}

static func widthMin(_ screen: NSScreen) -> CGFloat {
return (ThumbnailsPanel.widthMax(screen) - Preferences.interCellPadding) / Preferences.maxCellsPerRow - Preferences.interCellPadding
return ThumbnailsPanel.widthMax(screen) * Preferences.windowMinWidthInRow - Preferences.interCellPadding * 2
}

static func height(_ screen: NSScreen) -> CGFloat {
Expand Down
4 changes: 2 additions & 2 deletions src/ui/main-window/ThumbnailsPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ class ThumbnailsPanel: NSPanel {
}

static func widthMax(_ screen: NSScreen) -> CGFloat {
return screen.frame.width * Preferences.maxScreenUsage - Preferences.windowPadding * 2
return screen.frame.width * Preferences.maxWidthOnScreen - Preferences.windowPadding * 2
}

static func heightMax(_ screen: NSScreen) -> CGFloat {
return screen.frame.height * Preferences.maxScreenUsage - Preferences.windowPadding * 2
return screen.frame.height * Preferences.maxHeightOnScreen - Preferences.windowPadding * 2
}
}
4 changes: 2 additions & 2 deletions src/ui/preferences-window/LabelAndControl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ class LabelAndControl: NSObject {
}
}

static func makeLabelWithSlider(_ labelText: String, _ rawName: String, _ minValue: Double, _ maxValue: Double, _ numberOfTickMarks: Int, _ allowsTickMarkValuesOnly: Bool, _ unitText: String = "") -> [NSView] {
static func makeLabelWithSlider(_ labelText: String, _ rawName: String, _ minValue: Double, _ maxValue: Double, _ numberOfTickMarks: Int, _ allowsTickMarkValuesOnly: Bool, _ unitText: String = "", extraAction: ActionClosure? = nil) -> [NSView] {
let value = Preferences.getString(rawName)!
let suffixText = MeasurementFormatter().string(from: Measurement(value: Double(value)!, unit: Unit(symbol: unitText)))
let slider = NSSlider()
slider.minValue = minValue
slider.maxValue = maxValue
slider.stringValue = value
slider.isContinuous = true
return makeLabelWithProvidedControl(labelText, rawName, slider, suffixText)
return makeLabelWithProvidedControl(labelText, rawName, slider, suffixText, extraAction: extraAction)
}

static func makeLabelWithProvidedControl(_ labelText: String, _ rawName: String, _ control: NSControl, _ suffixText: String? = nil, _ suffixUrl: String? = nil, labelPosition: LabelPosition = .leftWithSeparator, extraAction: ActionClosure? = nil) -> [NSView] {
Expand Down
34 changes: 29 additions & 5 deletions src/ui/preferences-window/tabs/AppearanceTab.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import Cocoa

class AppearanceTab {
static var rowsCount: [NSView]!
static var minWidthInRow: [NSView]!
static var maxWidthInRow: [NSView]!

static func initTab() -> NSView {
rowsCount = LabelAndControl.makeLabelWithSlider(NSLocalizedString("Rows of thumbnails:", comment: ""), "rowsCount", 1, 20, 20, true)
minWidthInRow = LabelAndControl.makeLabelWithSlider(NSLocalizedString("Window min width in row:", comment: ""), "windowMinWidthInRow", 0, 100, 10, true, "%", extraAction: { _ in capMinMaxWidthInRow() })
maxWidthInRow = LabelAndControl.makeLabelWithSlider(NSLocalizedString("Window max width in row:", comment: ""), "windowMaxWidthInRow", 0, 100, 10, true, "%", extraAction: { _ in capMinMaxWidthInRow() })

let grid = GridView([
LabelAndControl.makeLabelWithDropdown(NSLocalizedString("Theme:", comment: ""), "theme", ThemePreference.allCases),
LabelAndControl.makeLabelWithDropdown(NSLocalizedString("Align windows:", comment: ""), "alignThumbnails", AlignThumbnailsPreference.allCases),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Max size on screen:", comment: ""), "maxScreenUsage", 10, 100, 10, true, "%"),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Rows of windows:", comment: ""), "rowsCount", 1, 20, 20, true),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Min windows per row:", comment: ""), "minCellsPerRow", 1, 20, 20, true),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Max windows per row:", comment: ""), "maxCellsPerRow", 1, 40, 20, true),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Max width on screen:", comment: ""), "maxWidthOnScreen", 10, 100, 10, true, "%"),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Max height on screen:", comment: ""), "maxHeightOnScreen", 10, 100, 10, true, "%"),
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Hide window thumbnails:", comment: ""), "hideThumbnails", extraAction: { _ in toggleRowsCount() }),
rowsCount,
minWidthInRow,
maxWidthInRow,
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Window app icon size:", comment: ""), "iconSize", 0, 128, 11, false, "px"),
LabelAndControl.makeLabelWithSlider(NSLocalizedString("Window title font size:", comment: ""), "fontHeight", 0, 64, 11, false, "px"),
LabelAndControl.makeLabelWithDropdown(NSLocalizedString("Window title truncation:", comment: ""), "titleTruncation", TitleTruncationPreference.allCases),
Expand All @@ -21,12 +31,26 @@ class AppearanceTab {
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Hide colored circles on mouse hover:", comment: ""), "hideColoredCircles"),
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Hide app badges:", comment: ""), "hideAppBadges"),
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Hide apps with no open window:", comment: ""), "hideWindowlessApps"),
LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Hide window thumbnails:", comment: ""), "hideThumbnails"),
])
grid.column(at: 0).xPlacement = .trailing
grid.rowAlignment = .lastBaseline
grid.fit()

toggleRowsCount()
capMinMaxWidthInRow()

return grid
}

static func capMinMaxWidthInRow() {
let minSlider = minWidthInRow[1] as! NSSlider
let maxSlider = maxWidthInRow[1] as! NSSlider
maxSlider.minValue = minSlider.doubleValue
debugPrint(maxSlider.minValue, maxSlider.doubleValue)
LabelAndControl.controlWasChanged(maxSlider, "windowMaxWidthInRow")
}

static func toggleRowsCount() {
(rowsCount[1] as! NSSlider).isEnabled = !Preferences.hideThumbnails
}
}

0 comments on commit 6e2e5b4

Please sign in to comment.