diff --git a/src/logic/Application.swift b/src/logic/Application.swift index 755820e6..64916df7 100644 --- a/src/logic/Application.swift +++ b/src/logic/Application.swift @@ -70,7 +70,9 @@ class Application: NSObject { private func addWindows(_ axWindows: [AXUIElement]) { let windows = axWindows.map { Window($0, self) } Windows.list.insertAndScaleRecycledPool(windows, at: 0) - Windows.cycleFocusedWindowIndex(windows.count) + if App.app.appIsBeingUsed { + Windows.cycleFocusedWindowIndex(windows.count) + } App.app.refreshOpenUi(windows) } diff --git a/src/logic/Preferences.swift b/src/logic/Preferences.swift index 2d45b217..23123e0f 100644 --- a/src/logic/Preferences.swift +++ b/src/logic/Preferences.swift @@ -40,7 +40,7 @@ class Preferences { // not exposed as preferences now but may be in the future, probably through macro preferences static var windowMaterial: NSVisualEffectView.Material { .dark } static var fontColor: NSColor { .white } - static var windowPadding: CGFloat { 23 } + static var windowPadding: CGFloat { 18 } static var interCellPadding: CGFloat { 5 } static var intraCellPadding: CGFloat { 5 } static var fontIconSize: CGFloat { 20 } @@ -223,8 +223,8 @@ enum ThemePreference: String, CaseIterable, MacroPreference { var themeParameters: ThemeParameters { switch self { - case .macOs: return ThemeParameters(label: self.localizedString, cellBorderWidth: 0, cellCornerRadius: 5, windowCornerRadius: 20, highlightBorderColor: .clear, highlightBackgroundColor: NSColor(red: 0, green: 0, blue: 0, alpha: 0.4)) - case .windows10: return ThemeParameters(label: self.localizedString, cellBorderWidth: 2, cellCornerRadius: 0, windowCornerRadius: 0, highlightBorderColor: .white, highlightBackgroundColor: .clear) + case .macOs: return ThemeParameters(label: localizedString, cellBorderWidth: 0, cellCornerRadius: 10, windowCornerRadius: 23, highlightBorderColor: .clear, highlightBackgroundColor: NSColor(red: 0, green: 0, blue: 0, alpha: 0.4)) + case .windows10: return ThemeParameters(label: localizedString, cellBorderWidth: 2, cellCornerRadius: 0, windowCornerRadius: 0, highlightBorderColor: .white, highlightBackgroundColor: .clear) } } } diff --git a/src/logic/Windows.swift b/src/logic/Windows.swift index cafa72ef..ac0db0b5 100644 --- a/src/logic/Windows.swift +++ b/src/logic/Windows.swift @@ -8,11 +8,14 @@ class Windows { static var windowsInSubscriptionRetryLoop = [String]() static func updateFocusedWindowIndex(_ newIndex: Int) { - previousFocusedWindowIndex = focusedWindowIndex - focusedWindowIndex = newIndex - let focusedView = ThumbnailsView.recycledViews[focusedWindowIndex] - ThumbnailsPanel.highlightCell(ThumbnailsView.recycledViews[previousFocusedWindowIndex], focusedView) - App.app.thumbnailsPanel.thumbnailsView.scrollView.contentView.scrollToVisible(focusedView.frame) + if newIndex != focusedWindowIndex { + previousFocusedWindowIndex = focusedWindowIndex + focusedWindowIndex = newIndex + let focusedView = ThumbnailsView.recycledViews[focusedWindowIndex] + ThumbnailsView.recycledViews[previousFocusedWindowIndex].highlight(false) + focusedView.highlight(true) + App.app.thumbnailsPanel.thumbnailsView.scrollView.contentView.scrollToVisible(focusedView.frame) + } } static func focusedWindow() -> Window? { diff --git a/src/ui/main-window/ThumbnailView.swift b/src/ui/main-window/ThumbnailView.swift index 6edd0cb2..1ce36870 100644 --- a/src/ui/main-window/ThumbnailView.swift +++ b/src/ui/main-window/ThumbnailView.swift @@ -8,18 +8,55 @@ class ThumbnailView: NSStackView { var minimizedIcon = ThumbnailFontIconView(ThumbnailFontIconView.sfSymbolCircledMinusSign, Preferences.fontIconSize, .white) var hiddenIcon = ThumbnailFontIconView(ThumbnailFontIconView.sfSymbolCircledDotSign, Preferences.fontIconSize, .white) var spaceIcon = ThumbnailFontIconView(ThumbnailFontIconView.sfSymbolCircledNumber0, Preferences.fontIconSize, .white) + var hStackView: NSStackView! var mouseDownCallback: (() -> Void)! var mouseMovedCallback: (() -> Void)! var dragAndDropTimer: Timer? + var isHighlighted = false convenience init() { self.init(frame: .zero) - let hStackView = makeHStackView() - setupView(hStackView) + setupView() + observeDragAndDrop() + } + + private func setupView() { + wantsLayer = true + layer!.backgroundColor = .clear + layer!.borderColor = .clear + layer!.cornerRadius = Preferences.cellCornerRadius + layer!.borderWidth = Preferences.cellBorderWidth + edgeInsets = NSEdgeInsets(top: Preferences.intraCellPadding, left: Preferences.intraCellPadding, bottom: Preferences.intraCellPadding, right: Preferences.intraCellPadding) + orientation = .vertical + spacing = Preferences.intraCellPadding let shadow = ThumbnailView.makeShadow(.gray) thumbnail.shadow = shadow appIcon.shadow = shadow - observeDragAndDrop() + hStackView = NSStackView(views: [appIcon, label, hiddenIcon, minimizedIcon, spaceIcon]) + hStackView.spacing = Preferences.intraCellPadding + setViews([hStackView, thumbnail], in: .leading) + } + + func highlight(_ highlight: Bool) { + if isHighlighted != highlight { + isHighlighted = highlight + if frame != NSRect.zero { + highlightOrNot() + } + } + } + + func highlightOrNot() { + layer!.backgroundColor = isHighlighted ? Preferences.highlightBackgroundColor.cgColor : .clear + layer!.borderColor = isHighlighted ? Preferences.highlightBorderColor.cgColor : .clear + let frameInset: CGFloat = Preferences.intraCellPadding * (isHighlighted ? -1 : 1) + frame = frame.insetBy(dx: frameInset, dy: frameInset) + let edgeInsets_: CGFloat = Preferences.intraCellPadding * (isHighlighted ? 2 : 1) + edgeInsets.top = edgeInsets_ + edgeInsets.right = edgeInsets_ + edgeInsets.bottom = edgeInsets_ + edgeInsets.left = edgeInsets_ + debugPrint("louis", isHighlighted, frame.width, label.string) } func updateRecycledCellWithNewContent(_ element: Window, _ index: Int, _ newHeight: CGFloat, _ screen: NSScreen) { @@ -123,19 +160,15 @@ class ThumbnailView: NSStackView { } static func widthMax(_ screen: NSScreen) -> CGFloat { - return ThumbnailsPanel.widthMax(screen) / Preferences.minCellsPerRow - Preferences.interCellPadding + return (ThumbnailsPanel.widthMax(screen) - Preferences.interCellPadding) / Preferences.minCellsPerRow - Preferences.interCellPadding } static func widthMin(_ screen: NSScreen) -> CGFloat { - return ThumbnailsPanel.widthMax(screen) / Preferences.maxCellsPerRow - Preferences.interCellPadding + return (ThumbnailsPanel.widthMax(screen) - Preferences.interCellPadding) / Preferences.maxCellsPerRow - Preferences.interCellPadding } static func height(_ screen: NSScreen) -> CGFloat { - return ThumbnailsPanel.heightMax(screen) / Preferences.rowsCount - Preferences.interCellPadding - } - - static func width(_ image: NSImage?, _ screen: NSScreen) -> CGFloat { - return max(thumbnailSize(image, screen).0 + Preferences.intraCellPadding * 2, ThumbnailView.widthMin(screen)) + return (ThumbnailsPanel.heightMax(screen) - Preferences.interCellPadding) / Preferences.rowsCount - Preferences.interCellPadding } static func thumbnailSize(_ image: NSImage?, _ screen: NSScreen) -> (CGFloat, CGFloat) { @@ -151,24 +184,4 @@ class ThumbnailView: NSStackView { } return (thumbnailWidth, image.size.height * thumbnailWidth / image.size.width) } - - private func makeHStackView() -> NSStackView { - let hStackView = NSStackView() - hStackView.spacing = Preferences.intraCellPadding - hStackView.setViews([appIcon, label, hiddenIcon, minimizedIcon, spaceIcon], in: .leading) - return hStackView - } - - private func setupView(_ hStackView: NSStackView) { - wantsLayer = true - layer!.backgroundColor = .clear - layer!.cornerRadius = Preferences.cellCornerRadius - layer!.borderWidth = Preferences.cellBorderWidth - layer!.borderColor = .clear - edgeInsets = NSEdgeInsets(top: Preferences.intraCellPadding, left: Preferences.intraCellPadding, bottom: Preferences.intraCellPadding, right: Preferences.intraCellPadding) - orientation = .vertical - spacing = Preferences.intraCellPadding - setViews([hStackView, thumbnail], in: .leading) - } } - diff --git a/src/ui/main-window/ThumbnailsPanel.swift b/src/ui/main-window/ThumbnailsPanel.swift index a1acb802..11e0639c 100644 --- a/src/ui/main-window/ThumbnailsPanel.swift +++ b/src/ui/main-window/ThumbnailsPanel.swift @@ -25,13 +25,6 @@ class ThumbnailsPanel: NSPanel { thumbnailsView.scrollView.flashScrollers() } - static func highlightCell(_ previousView: NSView, _ newView: NSView) { - previousView.layer!.backgroundColor = .clear - previousView.layer!.borderColor = .clear - newView.layer!.backgroundColor = Preferences.highlightBackgroundColor.cgColor - newView.layer!.borderColor = Preferences.highlightBorderColor.cgColor - } - static func widthMax(_ screen: NSScreen) -> CGFloat { return screen.frame.width * Preferences.maxScreenUsage - Preferences.windowPadding * 2 } diff --git a/src/ui/main-window/ThumbnailsView.swift b/src/ui/main-window/ThumbnailsView.swift index 4a9c0e7e..0a064966 100644 --- a/src/ui/main-window/ThumbnailsView.swift +++ b/src/ui/main-window/ThumbnailsView.swift @@ -40,10 +40,10 @@ class ThumbnailsView: NSVisualEffectView { let widthMax = ThumbnailsPanel.widthMax(screen).rounded() let heightMax = ThumbnailsPanel.heightMax(screen).rounded() let height = ThumbnailView.height(screen).rounded(.down) - var currentX = CGFloat(0) - var currentY = CGFloat(0) + var currentX = Preferences.interCellPadding + var currentY = Preferences.interCellPadding var maxX = CGFloat(0) - var maxY = height + var maxY = currentY + height + Preferences.interCellPadding var newViews = [ThumbnailView]() rows.removeAll() rows.append([ThumbnailView]()) @@ -53,13 +53,13 @@ class ThumbnailsView: NSVisualEffectView { let view = ThumbnailsView.recycledViews[index] view.updateRecycledCellWithNewContent(window, index, height, screen) let width = view.frame.size.width - if (currentX + width).rounded(.down) > widthMax { - currentX = CGFloat(0) - currentY = (currentY + Preferences.interCellPadding + height).rounded(.down) - maxY = max(currentY + height, maxY) + if (currentX + width + Preferences.interCellPadding).rounded(.down) > widthMax { + currentX = Preferences.interCellPadding + currentY = (currentY + height + Preferences.interCellPadding).rounded(.down) + maxY = max(currentY + height + Preferences.interCellPadding, maxY) rows.append([ThumbnailView]()) } else { - maxX = max(currentX + width, maxX) + maxX = max(currentX + width + Preferences.interCellPadding, maxX) } view.frame.origin = CGPoint(x: currentX, y: currentY) currentX = (currentX + Preferences.interCellPadding + width).rounded(.down) @@ -76,23 +76,27 @@ class ThumbnailsView: NSVisualEffectView { if Preferences.alignThumbnails == .center { centerRows(maxX) } + Windows.list.enumerated().first { (index, _) in + let view = ThumbnailsView.recycledViews[index] + if view.isHighlighted { + view.highlightOrNot() + } + return view.isHighlighted + } } func centerRows(_ maxX: CGFloat) { var rowStartIndex = 0 - var rowWidth = CGFloat(0) - var rowY = CGFloat(0) + var rowWidth = Preferences.interCellPadding + var rowY = Preferences.interCellPadding for (index, _) in Windows.list.enumerated() { let view = ThumbnailsView.recycledViews[index] if view.frame.origin.y == rowY { - rowWidth += Preferences.interCellPadding + view.frame.size.width + rowWidth += view.frame.size.width + Preferences.interCellPadding } else { - if rowStartIndex == 0 { - rowWidth -= Preferences.interCellPadding // first row has 1 extra padding - } shiftRow(maxX, rowWidth, rowStartIndex, index) rowStartIndex = index - rowWidth = view.frame.size.width + rowWidth = Preferences.interCellPadding + view.frame.size.width + Preferences.interCellPadding rowY = view.frame.origin.y } }