fix: layout was incorrect resulting in thumbnails clipping
This commit is contained in:
1 parent
2a36196661
commit
fd906f46fb
4 files changed
+66
-45
No files matched your search
@@ -10,12 +10,13 @@ class Preferences {
|
||||
static let fontHeight = CGFloat(15)
|
||||
static let font = NSFont.systemFont(ofSize: fontHeight)
|
||||
static let windowPadding = CGFloat(23)
|
||||
static let cellPadding = CGFloat(5)
|
||||
static let interCellPadding = CGFloat(5)
|
||||
static let intraCellPadding = CGFloat(5)
|
||||
static let fontIconSize = CGFloat(20)
|
||||
static let maxScreenUsage = CGFloat(0.8)
|
||||
static let minCellsPerRow = CGFloat(4)
|
||||
static let maxCellsPerRow = CGFloat(6)
|
||||
static let nCellsRows = CGFloat(4)
|
||||
static let minCellsPerRow = CGFloat(3)
|
||||
static let maxCellsPerRow = CGFloat(4)
|
||||
static let nCellsRows = CGFloat(3)
|
||||
|
||||
static let themeMacro = MacroPreferenceHelper<(CGFloat, CGFloat, CGFloat, NSColor, NSColor)>([
|
||||
MacroPreference(" macOS", (0, 5, 20, .clear, NSColor(red: 0, green: 0, blue: 0, alpha: 0.3))),
|
||||
|
||||
+13
-12
@@ -62,8 +62,9 @@ class Cell: NSCollectionViewItem {
|
||||
spaceIcon.setNumber(UInt32(element.spaceIndex!))
|
||||
}
|
||||
}
|
||||
let fontIconWidth = CGFloat([minimizedIcon, hiddenIcon, spaceIcon].filter { !$0.isHidden }.count) * (Preferences.fontIconSize + Preferences.cellPadding)
|
||||
label.textContainer!.size.width = view.frame.width - Preferences.iconSize - Preferences.cellPadding * 3 - fontIconWidth
|
||||
let fontIconWidth = CGFloat([minimizedIcon, hiddenIcon, spaceIcon].filter { !$0.isHidden }.count) * (Preferences.fontIconSize + Preferences.intraCellPadding)
|
||||
label.textContainer!.size.width = view.frame.width - Preferences.iconSize - Preferences.intraCellPadding * 3 - fontIconWidth
|
||||
view.subviews.first!.frame.size = view.frame.size
|
||||
self.mouseDownCallback = mouseDownCallback
|
||||
self.mouseMovedCallback = mouseMovedCallback
|
||||
if view.trackingAreas.count > 0 {
|
||||
@@ -82,7 +83,7 @@ class Cell: NSCollectionViewItem {
|
||||
|
||||
private func makeHStackView() -> NSStackView {
|
||||
let hStackView = NSStackView()
|
||||
hStackView.spacing = Preferences.cellPadding
|
||||
hStackView.spacing = Preferences.intraCellPadding
|
||||
hStackView.setViews([appIcon, label, hiddenIcon, minimizedIcon, spaceIcon], in: .leading)
|
||||
return hStackView
|
||||
}
|
||||
@@ -94,9 +95,9 @@ class Cell: NSCollectionViewItem {
|
||||
vStackView.layer!.cornerRadius = Preferences.cellCornerRadius!
|
||||
vStackView.layer!.borderWidth = Preferences.cellBorderWidth!
|
||||
vStackView.layer!.borderColor = .clear
|
||||
vStackView.edgeInsets = NSEdgeInsets(top: Preferences.cellPadding, left: Preferences.cellPadding, bottom: Preferences.cellPadding, right: Preferences.cellPadding)
|
||||
vStackView.edgeInsets = NSEdgeInsets(top: Preferences.intraCellPadding, left: Preferences.intraCellPadding, bottom: Preferences.intraCellPadding, right: Preferences.intraCellPadding)
|
||||
vStackView.orientation = .vertical
|
||||
vStackView.spacing = Preferences.cellPadding
|
||||
vStackView.spacing = Preferences.intraCellPadding
|
||||
vStackView.setViews([hStackView, thumbnail], in: .leading)
|
||||
return vStackView
|
||||
}
|
||||
@@ -109,19 +110,19 @@ class Cell: NSCollectionViewItem {
|
||||
}
|
||||
|
||||
static func widthMax(_ screen: NSScreen) -> CGFloat {
|
||||
return floor((ThumbnailsPanel.widthMax(screen) / Preferences.minCellsPerRow - Preferences.cellPadding) * Cell.downscaleFactor())
|
||||
return floor((ThumbnailsPanel.widthMax(screen) / Preferences.minCellsPerRow - Preferences.interCellPadding) * Cell.downscaleFactor())
|
||||
}
|
||||
|
||||
static func widthMin(_ screen: NSScreen) -> CGFloat {
|
||||
return floor((ThumbnailsPanel.widthMax(screen) / Preferences.maxCellsPerRow - Preferences.cellPadding) * Cell.downscaleFactor())
|
||||
return floor((ThumbnailsPanel.widthMax(screen) / Preferences.maxCellsPerRow - Preferences.interCellPadding) * Cell.downscaleFactor())
|
||||
}
|
||||
|
||||
static func height(_ screen: NSScreen) -> CGFloat {
|
||||
return floor((ThumbnailsPanel.heightMax(screen) / Preferences.nCellsRows - Preferences.cellPadding) * Cell.downscaleFactor())
|
||||
return floor((ThumbnailsPanel.heightMax(screen) / Preferences.nCellsRows - Preferences.interCellPadding) * Cell.downscaleFactor())
|
||||
}
|
||||
|
||||
static func width(_ image: NSImage?, _ screen: NSScreen) -> CGFloat {
|
||||
return floor(max(thumbnailSize(image, screen).width + Preferences.cellPadding * 2, ThumbnailsPanel.widthMin(screen)))
|
||||
return floor(max(thumbnailSize(image, screen).width + Preferences.intraCellPadding * 2, Cell.widthMin(screen)))
|
||||
}
|
||||
|
||||
static func thumbnailSize(_ image: NSImage?, _ screen: NSScreen) -> NSSize {
|
||||
@@ -130,9 +131,9 @@ class Cell: NSCollectionViewItem {
|
||||
}
|
||||
|
||||
static func thumbnailSize_(_ image: NSImage?, _ screen: NSScreen) -> (CGFloat, CGFloat) {
|
||||
let thumbnailWidthMin = Cell.widthMin(screen) - Preferences.cellPadding * 2
|
||||
let thumbnailHeightMax = Cell.height(screen) - Preferences.cellPadding * 3 - Preferences.iconSize
|
||||
let thumbnailWidthMax = Cell.widthMax(screen) - Preferences.cellPadding * 2
|
||||
let thumbnailWidthMin = Cell.widthMin(screen) - Preferences.intraCellPadding * 2
|
||||
let thumbnailHeightMax = Cell.height(screen) - Preferences.intraCellPadding * 3 - Preferences.iconSize
|
||||
let thumbnailWidthMax = Cell.widthMax(screen) - Preferences.intraCellPadding * 2
|
||||
guard let image = image else { return (thumbnailWidthMin, thumbnailHeightMax) }
|
||||
let imageRatio = image.size.width / image.size.height
|
||||
let thumbnailRatio = thumbnailWidthMax / thumbnailHeightMax
|
||||
|
||||
@@ -2,6 +2,8 @@ import Cocoa
|
||||
|
||||
class CollectionViewCenterFlowLayout: NSCollectionViewFlowLayout {
|
||||
var currentScreen: NSScreen?
|
||||
var widestRow: CGFloat?
|
||||
var totalHeight: CGFloat?
|
||||
|
||||
override func layoutAttributesForElements(in rect: CGRect) -> [NSCollectionViewLayoutAttributes] {
|
||||
let attributes_ = super.layoutAttributesForElements(in: rect)
|
||||
@@ -10,42 +12,51 @@ class CollectionViewCenterFlowLayout: NSCollectionViewFlowLayout {
|
||||
var currentRow: [NSCollectionViewLayoutAttributes] = []
|
||||
var currentRowY = CGFloat(0)
|
||||
var currentRowWidth = CGFloat(0)
|
||||
var previousRowMaxY = CGFloat(0)
|
||||
var currentRowMaxY = CGFloat(0)
|
||||
var previousRowMaxHeight = CGFloat(0)
|
||||
var currentRowMaxHeight = CGFloat(0)
|
||||
var widestRow = CGFloat(0)
|
||||
var totalHeight = CGFloat(0)
|
||||
for (index, attribute) in attributes.enumerated() {
|
||||
let isNewRow = abs(attribute.frame.origin.y - currentRowY) > Cell.height(currentScreen!)
|
||||
if isNewRow {
|
||||
computeOriginXForAllItems(currentRowWidth - Preferences.cellPadding, previousRowMaxY, currentRow)
|
||||
currentRowWidth -= Preferences.interCellPadding
|
||||
widestRow = max(widestRow, currentRowWidth)
|
||||
setCenteredPositionForPreviousRowCells(currentRowWidth, previousRowMaxHeight, currentRow)
|
||||
currentRow.removeAll()
|
||||
currentRowY = attribute.frame.origin.y
|
||||
currentRowWidth = 0
|
||||
previousRowMaxY += currentRowMaxY + Preferences.cellPadding
|
||||
currentRowMaxY = 0
|
||||
previousRowMaxHeight += currentRowMaxHeight + Preferences.interCellPadding
|
||||
currentRowMaxHeight = 0
|
||||
}
|
||||
currentRow.append(attribute)
|
||||
currentRowWidth += attribute.frame.size.width + Preferences.cellPadding
|
||||
widestRow = max(widestRow, currentRowWidth)
|
||||
currentRowMaxY = max(currentRowMaxY, attribute.frame.size.height)
|
||||
currentRowWidth += attribute.frame.size.width + Preferences.interCellPadding
|
||||
currentRowMaxHeight = max(currentRowMaxHeight, attribute.frame.size.height)
|
||||
if index == attributes.count - 1 {
|
||||
computeOriginXForAllItems(currentRowWidth - Preferences.cellPadding, previousRowMaxY, currentRow)
|
||||
totalHeight = previousRowMaxY + currentRowMaxY
|
||||
currentRowWidth -= Preferences.interCellPadding
|
||||
widestRow = max(widestRow, currentRowWidth)
|
||||
totalHeight = previousRowMaxHeight + currentRowMaxHeight
|
||||
setCenteredPositionForPreviousRowCells(currentRowWidth, previousRowMaxHeight, currentRow)
|
||||
}
|
||||
}
|
||||
let newWidth = widestRow - Preferences.cellPadding
|
||||
collectionView!.bounds.origin.x = (collectionView!.frame.size.width - newWidth) / 2
|
||||
collectionView!.frame.size.width = newWidth
|
||||
collectionView!.frame.size.height = totalHeight
|
||||
shiftCenteredElementToTheLeft(attributes, widestRow, totalHeight)
|
||||
self.widestRow = widestRow
|
||||
self.totalHeight = totalHeight
|
||||
return attributes
|
||||
}
|
||||
|
||||
private func computeOriginXForAllItems(_ currentRowWidth: CGFloat, _ previousRowMaxHeight: CGFloat, _ currentRow: [NSCollectionViewLayoutAttributes]) {
|
||||
private func shiftCenteredElementToTheLeft(_ attributes: [NSCollectionViewLayoutAttributes], _ widestRow: CGFloat, _ totalHeight: CGFloat) {
|
||||
let horizontalMargin = floor((collectionView!.frame.size.width - widestRow) / 2)
|
||||
for attribute in attributes {
|
||||
attribute.frame.origin.x -= horizontalMargin
|
||||
}
|
||||
}
|
||||
|
||||
private func setCenteredPositionForPreviousRowCells(_ currentRowWidth: CGFloat, _ previousRowMaxHeight: CGFloat, _ currentRow: [NSCollectionViewLayoutAttributes]) {
|
||||
var marginLeft = (collectionView!.frame.size.width - currentRowWidth) / 2
|
||||
for attribute in currentRow {
|
||||
attribute.frame.origin.x = marginLeft
|
||||
attribute.frame.origin.y = previousRowMaxHeight
|
||||
marginLeft += attribute.frame.size.width + Preferences.cellPadding
|
||||
marginLeft += attribute.frame.size.width + Preferences.interCellPadding
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,9 @@ class ThumbnailsPanel: NSPanel, NSCollectionViewDataSource, NSCollectionViewDele
|
||||
styleMask.remove(.titled)
|
||||
backgroundColor = .clear
|
||||
makeCollectionView()
|
||||
makeBackgroundView()
|
||||
contentView!.addSubview(backgroundView!)
|
||||
backgroundView = ThumbnailsPanel.makeBackgroundView()
|
||||
backgroundView.addSubview(collectionView)
|
||||
contentView!.addSubview(backgroundView)
|
||||
// highest level possible; this allows the app to go on top of context menus
|
||||
level = .screenSaver
|
||||
// helps filter out this window from the thumbnails
|
||||
@@ -34,27 +35,34 @@ class ThumbnailsPanel: NSPanel, NSCollectionViewDataSource, NSCollectionViewDele
|
||||
makeKeyAndOrderFront(nil)
|
||||
}
|
||||
|
||||
private func makeBackgroundView() {
|
||||
backgroundView = NSVisualEffectView()
|
||||
static func makeBackgroundView() -> NSVisualEffectView {
|
||||
let backgroundView = NSVisualEffectView()
|
||||
backgroundView.translatesAutoresizingMaskIntoConstraints = false
|
||||
backgroundView.material = Preferences.windowMaterial
|
||||
backgroundView.state = .active
|
||||
backgroundView.wantsLayer = true
|
||||
backgroundView.layer!.cornerRadius = Preferences.windowCornerRadius!
|
||||
backgroundView.addSubview(collectionView)
|
||||
return backgroundView
|
||||
}
|
||||
|
||||
func makeCollectionView() {
|
||||
collectionView = NSCollectionView()
|
||||
collectionView.dataSource = self
|
||||
collectionView.delegate = self
|
||||
collectionView.collectionViewLayout = CollectionViewCenterFlowLayout()
|
||||
collectionView.collectionViewLayout = makeLayout()
|
||||
collectionView.backgroundColors = [.clear]
|
||||
collectionView.isSelectable = true
|
||||
collectionView.allowsMultipleSelection = false
|
||||
collectionView.register(Cell.self, forItemWithIdentifier: cellId)
|
||||
}
|
||||
|
||||
private func makeLayout() -> CollectionViewCenterFlowLayout {
|
||||
let layout = CollectionViewCenterFlowLayout()
|
||||
layout.minimumInteritemSpacing = Preferences.interCellPadding
|
||||
layout.minimumLineSpacing = Preferences.interCellPadding
|
||||
return layout
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return Windows.list.count
|
||||
}
|
||||
@@ -86,12 +94,16 @@ class ThumbnailsPanel: NSPanel, NSCollectionViewDataSource, NSCollectionViewDele
|
||||
|
||||
func refreshCollectionView(_ screen: NSScreen, _ uiWorkShouldBeDone: Bool) {
|
||||
if uiWorkShouldBeDone { self.currentScreen = screen }
|
||||
if uiWorkShouldBeDone { (collectionView.collectionViewLayout as! CollectionViewCenterFlowLayout).currentScreen = screen }
|
||||
let layout = collectionView.collectionViewLayout as! CollectionViewCenterFlowLayout
|
||||
if uiWorkShouldBeDone { layout.currentScreen = screen }
|
||||
if uiWorkShouldBeDone { layout.invalidateLayout() }
|
||||
if uiWorkShouldBeDone { collectionView.setFrameSize(NSSize(width: ThumbnailsPanel.widthMax(screen), height: ThumbnailsPanel.heightMax(screen))) }
|
||||
if uiWorkShouldBeDone { collectionView.reloadData() }
|
||||
if uiWorkShouldBeDone { collectionView.layoutSubtreeIfNeeded() }
|
||||
if uiWorkShouldBeDone { setContentSize(NSSize(width: collectionView.frame.size.width + Preferences.windowPadding * 2, height: collectionView.frame.size.height + Preferences.windowPadding * 2)) }
|
||||
if uiWorkShouldBeDone { backgroundView!.setFrameSize(frame.size) }
|
||||
if uiWorkShouldBeDone { collectionView.setFrameSize(NSSize(width: layout.widestRow!, height: layout.totalHeight!)) }
|
||||
let windowSize = NSSize(width: layout.widestRow! + Preferences.windowPadding * 2, height: layout.totalHeight! + Preferences.windowPadding * 2)
|
||||
if uiWorkShouldBeDone { setContentSize(windowSize) }
|
||||
if uiWorkShouldBeDone { backgroundView!.setFrameSize(windowSize) }
|
||||
if uiWorkShouldBeDone { collectionView.setFrameOrigin(NSPoint(x: Preferences.windowPadding, y: Preferences.windowPadding)) }
|
||||
}
|
||||
|
||||
@@ -103,10 +115,6 @@ class ThumbnailsPanel: NSPanel, NSCollectionViewDataSource, NSCollectionViewDele
|
||||
return floor(screen.frame.height * Preferences.maxScreenUsage - Preferences.windowPadding * 2)
|
||||
}
|
||||
|
||||
static func widthMin(_ screen: NSScreen) -> CGFloat {
|
||||
return floor(Cell.widthMin(screen) - Preferences.windowPadding * 2)
|
||||
}
|
||||
|
||||
static func heightMin(_ screen: NSScreen) -> CGFloat {
|
||||
return floor(Cell.height(screen) - Preferences.windowPadding * 2)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user