feat: add new setting for auto size (closes #3669)
This commit is contained in:
1 parent
b9e0344da4
commit
c51376fd26
8 files changed
+88
-21
No files matched your search
@@ -121,6 +121,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Ask whether to send crash reports" = "Ask whether to send crash reports";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Auto" = "Auto";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Auto-install updates periodically" = "Auto-install updates periodically";
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"AltTab will show if the window is currently minimized or fullscreen with a status icon." = "AltTab will show if the window is currently minimized or fullscreen with a status icon.";
|
||||
"Always" = "Always";
|
||||
"Always send crash reports" = "Always send crash reports";
|
||||
"Auto" = "Auto";
|
||||
"and press" = "and press";
|
||||
"and press:" = "and press:";
|
||||
"Animations" = "Animations";
|
||||
|
||||
+30
-16
@@ -2,6 +2,7 @@ import Cocoa
|
||||
|
||||
class Appearance {
|
||||
// size
|
||||
static var resolvedSize = AppearanceSizePreference.medium
|
||||
static var hideThumbnails = Bool(false)
|
||||
static var windowPadding = CGFloat(1000)
|
||||
static var windowCornerRadius = CGFloat(1000)
|
||||
@@ -54,16 +55,29 @@ class Appearance {
|
||||
private static func updateSize() {
|
||||
let isHorizontalScreen = NSScreen.preferred.isHorizontal()
|
||||
maxWidthOnScreen = AppearanceTestable.comfortableWidth(NSScreen.preferred.physicalSize().map { $0.width })
|
||||
if currentStyle == .appIcons {
|
||||
appIconsSize()
|
||||
} else if currentStyle == .titles {
|
||||
titlesSize(isHorizontalScreen)
|
||||
} else {
|
||||
thumbnailsSize(isHorizontalScreen)
|
||||
}
|
||||
let sizeToApply: AppearanceSizePreference = currentSize == .auto ? .large : currentSize
|
||||
resolvedSize = sizeToApply
|
||||
applyConcreteSize(sizeToApply, isHorizontalScreen)
|
||||
updateFont()
|
||||
}
|
||||
|
||||
static func applySize(_ size: AppearanceSizePreference) {
|
||||
let isHorizontalScreen = NSScreen.preferred.isHorizontal()
|
||||
resolvedSize = size
|
||||
applyConcreteSize(size, isHorizontalScreen)
|
||||
updateFont()
|
||||
}
|
||||
|
||||
private static func applyConcreteSize(_ size: AppearanceSizePreference, _ isHorizontalScreen: Bool) {
|
||||
if currentStyle == .appIcons {
|
||||
appIconsSize(size)
|
||||
} else if currentStyle == .titles {
|
||||
titlesSize(isHorizontalScreen, size)
|
||||
} else {
|
||||
thumbnailsSize(isHorizontalScreen, size)
|
||||
}
|
||||
}
|
||||
|
||||
private static func updateTheme() {
|
||||
highlightBorderWidth = currentStyle == .titles ? 2 : 3
|
||||
if currentTheme == .dark {
|
||||
@@ -79,7 +93,7 @@ class Appearance {
|
||||
}
|
||||
}
|
||||
|
||||
private static func thumbnailsSize(_ isHorizontalScreen: Bool) {
|
||||
private static func thumbnailsSize(_ isHorizontalScreen: Bool, _ size: AppearanceSizePreference) {
|
||||
hideThumbnails = false
|
||||
windowPadding = 18
|
||||
windowCornerRadius = 23
|
||||
@@ -90,7 +104,7 @@ class Appearance {
|
||||
windowCornerRadius = 43
|
||||
cellCornerRadius = 18
|
||||
}
|
||||
switch currentSize {
|
||||
switch size {
|
||||
case .small:
|
||||
rowsCount = isHorizontalScreen ? 5 : 8
|
||||
iconSize = 16
|
||||
@@ -99,7 +113,7 @@ class Appearance {
|
||||
rowsCount = isHorizontalScreen ? 4 : 7
|
||||
iconSize = 26
|
||||
fontHeight = 14
|
||||
case .large:
|
||||
case .large, .auto:
|
||||
rowsCount = isHorizontalScreen ? 3 : 6
|
||||
iconSize = 28
|
||||
fontHeight = 16
|
||||
@@ -108,7 +122,7 @@ class Appearance {
|
||||
(windowMinWidthInRow, windowMaxWidthInRow) = AppearanceTestable.goodValuesForThumbnailsWidthMinMax(tilesPanelRatio, rowsCount)
|
||||
}
|
||||
|
||||
private static func appIconsSize() {
|
||||
private static func appIconsSize(_ size: AppearanceSizePreference) {
|
||||
hideThumbnails = true
|
||||
windowPadding = 25
|
||||
windowCornerRadius = 23
|
||||
@@ -120,7 +134,7 @@ class Appearance {
|
||||
windowMinWidthInRow = 0.04
|
||||
windowMaxWidthInRow = 0.3
|
||||
rowsCount = 1
|
||||
switch currentSize {
|
||||
switch size {
|
||||
case .small:
|
||||
iconSize = 70
|
||||
fontHeight = 13
|
||||
@@ -135,7 +149,7 @@ class Appearance {
|
||||
windowCornerRadius = 55
|
||||
cellCornerRadius = 35
|
||||
}
|
||||
case .large:
|
||||
case .large, .auto:
|
||||
windowPadding = 28
|
||||
iconSize = 150
|
||||
fontHeight = 16
|
||||
@@ -146,7 +160,7 @@ class Appearance {
|
||||
}
|
||||
}
|
||||
|
||||
private static func titlesSize(_ isHorizontalScreen: Bool) {
|
||||
private static func titlesSize(_ isHorizontalScreen: Bool, _ size: AppearanceSizePreference) {
|
||||
hideThumbnails = true
|
||||
windowPadding = 18
|
||||
windowCornerRadius = 23
|
||||
@@ -155,14 +169,14 @@ class Appearance {
|
||||
windowMinWidthInRow = 0.6
|
||||
windowMaxWidthInRow = 0.9
|
||||
rowsCount = 1
|
||||
switch currentSize {
|
||||
switch size {
|
||||
case .small:
|
||||
iconSize = 18
|
||||
fontHeight = 13
|
||||
case .medium:
|
||||
iconSize = 24
|
||||
fontHeight = 14
|
||||
case .large:
|
||||
case .large, .auto:
|
||||
iconSize = 30
|
||||
fontHeight = 16
|
||||
}
|
||||
|
||||
@@ -424,12 +424,14 @@ enum AppearanceSizePreference: CaseIterable, SfSymbolMacroPreference {
|
||||
case small
|
||||
case medium
|
||||
case large
|
||||
case auto
|
||||
|
||||
var localizedString: LocalizedString {
|
||||
switch self {
|
||||
case .small: return NSLocalizedString("Small", comment: "")
|
||||
case .medium: return NSLocalizedString("Medium", comment: "")
|
||||
case .large: return NSLocalizedString("Large", comment: "")
|
||||
case .auto: return NSLocalizedString("Auto", comment: "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,6 +440,7 @@ enum AppearanceSizePreference: CaseIterable, SfSymbolMacroPreference {
|
||||
case .small: return "moonphase.waning.gibbous.inverse"
|
||||
case .medium: return "moonphase.last.quarter.inverse"
|
||||
case .large: return "moonphase.waning.crescent.inverse"
|
||||
case .auto: return "sparkles"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class Preferences {
|
||||
"hideColoredCircles": "false",
|
||||
"windowDisplayDelay": "100",
|
||||
"appearanceStyle": AppearanceStylePreference.thumbnails.indexAsString,
|
||||
"appearanceSize": AppearanceSizePreference.medium.indexAsString,
|
||||
"appearanceSize": AppearanceSizePreference.auto.indexAsString,
|
||||
"appearanceTheme": AppearanceThemePreference.system.indexAsString,
|
||||
"theme": ThemePreference.macOs.indexAsString,
|
||||
"showOnScreen": ShowOnScreenPreference.active.indexAsString,
|
||||
|
||||
@@ -43,12 +43,12 @@ class WindowlessAppIndicator: NSView {
|
||||
|
||||
static func getAppearanceParameter() -> AppearanceParameter {
|
||||
if Preferences.appearanceStyle == .thumbnails || Preferences.appearanceStyle == .appIcons {
|
||||
if Preferences.appearanceSize == .large {
|
||||
if Appearance.resolvedSize == .large {
|
||||
return AppearanceParameter(width: 12, height: 5, cornerRadius: 2)
|
||||
}
|
||||
return AppearanceParameter(width: 10, height: 5, cornerRadius: 2)
|
||||
}
|
||||
if Preferences.appearanceSize == .large {
|
||||
if Appearance.resolvedSize == .large {
|
||||
return AppearanceParameter(width: 8, height: 3, cornerRadius: 1)
|
||||
}
|
||||
return AppearanceParameter(width: 6, height: 3, cornerRadius: 1)
|
||||
|
||||
@@ -204,7 +204,7 @@ class TileView: FlippedView {
|
||||
private func updateAppIconsLabelFrame() {
|
||||
let viewWidth = frame.width
|
||||
let labelWidth = fullTitleWidth
|
||||
let padding = (Preferences.appearanceSize == .small ? 0 : ( Preferences.appearanceSize == .medium ? 1 : 2)) * Appearance.intraCellPadding
|
||||
let padding = (Appearance.resolvedSize == .small ? 0 : (Appearance.resolvedSize == .medium ? 1 : 2)) * Appearance.intraCellPadding
|
||||
let maxAllowedLabelWidth = getMaxAllowedLabelWidth()
|
||||
let sidesToOffset: CGFloat = (isFirstInRow ? 1 : 0) + (isLastInRow ? 1 : 0)
|
||||
let paddingForOffset = sidesToOffset * padding
|
||||
@@ -500,7 +500,7 @@ class TileView: FlippedView {
|
||||
|
||||
private func updateDockLabelIconPosition() {
|
||||
let iconSize = max(appIcon.frame.width, appIcon.frame.height)
|
||||
let offset = (iconSize * (Preferences.appearanceStyle == .appIcons && Preferences.appearanceSize == .large ? 0.03 : 0.05)).rounded()
|
||||
let offset = (iconSize * (Preferences.appearanceStyle == .appIcons && Appearance.resolvedSize == .large ? 0.03 : 0.05)).rounded()
|
||||
let badgeTopRightX = appIcon.frame.maxX + offset
|
||||
let badgeTopRightY = appIcon.frame.minY - offset
|
||||
assignIfDifferent(&dockLabelIcon.frame.origin.x, badgeTopRightX - dockLabelIcon.frame.width)
|
||||
|
||||
@@ -363,6 +363,10 @@ class TilesView: NSObject {
|
||||
|
||||
func updateItemsAndLayout(_ preservedScrollOrigin: CGPoint?) {
|
||||
let widthMax = TilesPanel.maxThumbnailsWidth().rounded()
|
||||
if Preferences.appearanceSize == .auto {
|
||||
resolveAutoSize(widthMax)
|
||||
Self.updateCachedSizes()
|
||||
}
|
||||
if let (maxX, maxY, labelHeight, rowSignature) = layoutTileViews(widthMax) {
|
||||
layoutParentViews(maxX, widthMax, maxY, labelHeight)
|
||||
if Preferences.alignThumbnails == .center {
|
||||
@@ -401,6 +405,48 @@ class TilesView: NSObject {
|
||||
scrollView.reflectScrolledClipView(scrollView.contentView)
|
||||
}
|
||||
|
||||
private func resolveAutoSize(_ widthMax: CGFloat) {
|
||||
let searchReservedHeight: CGFloat = searchMode == .off ? 0 : searchBarHeight() + 10
|
||||
let heightMax = max(0, TilesPanel.maxThumbnailsHeight() - searchReservedHeight)
|
||||
for size in [AppearanceSizePreference.large, .medium, .small] {
|
||||
Appearance.applySize(size)
|
||||
Self.updateCachedSizes()
|
||||
let maxY = dryRunLayoutTileViews(widthMax)
|
||||
if size == .small || maxY <= heightMax { return }
|
||||
}
|
||||
}
|
||||
|
||||
private func dryRunLayoutTileViews(_ widthMax: CGFloat) -> CGFloat {
|
||||
let labelHeight = Self.layoutCache.labelHeight
|
||||
let height = TileView.height(labelHeight)
|
||||
let isLeftToRight = App.shared.userInterfaceLayoutDirection == .leftToRight
|
||||
let startingX = isLeftToRight ? Appearance.interCellPadding : widthMax - Appearance.interCellPadding
|
||||
var currentX = startingX
|
||||
var currentY = Appearance.interCellPadding
|
||||
var maxY = currentY + height + Appearance.interCellPadding
|
||||
var index = 0
|
||||
while index < TilesView.recycledViews.count {
|
||||
guard App.app.appIsBeingUsed else { return maxY }
|
||||
defer { index += 1 }
|
||||
let view = TilesView.recycledViews[index]
|
||||
guard index < Windows.list.count else { break }
|
||||
let window = Windows.list[index]
|
||||
guard Windows.shouldDisplay(window) else { view.frame = .zero; continue }
|
||||
view.updateRecycledCellWithNewContent(window, index, height)
|
||||
let width = view.frame.size.width
|
||||
let projectedX = projectedWidth(currentX, width).rounded(.down)
|
||||
if needNewLine(projectedX, widthMax) {
|
||||
currentX = startingX
|
||||
currentY = (currentY + height + Appearance.interCellPadding).rounded(.down)
|
||||
currentX = projectedWidth(currentX, width).rounded(.down)
|
||||
maxY = max(currentY + height + Appearance.interCellPadding, maxY)
|
||||
} else {
|
||||
currentX = projectedX
|
||||
}
|
||||
}
|
||||
return maxY
|
||||
}
|
||||
|
||||
private func layoutTileViews(_ widthMax: CGFloat) -> (CGFloat, CGFloat, CGFloat, [Int])? {
|
||||
let labelHeight = Self.layoutCache.labelHeight
|
||||
let height = TileView.height(labelHeight)
|
||||
|
||||
Reference in new issue
Block a user