feat: split max screen size preference into width/height (closes #579)

This commit is contained in:
Louis Pontoise authored and lwouis committed 2020-09-08 19:44:35 +09:00
1 parent af5ed9b213
commit 6e2e5b47fc
5 files changed
+54 -29

No files matched your search

+18 -17
View File
@@ -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": "⌥",
@@ -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") }
@@ -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),
@@ -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 {
+3 -3
View File
@@ -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)
@@ -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 {
+2 -2
View File
@@ -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
}
}
@@ -63,7 +63,7 @@ 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()
@@ -71,7 +71,7 @@ class LabelAndControl: NSObject {
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] {
@@ -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),
@@ -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
}
}