55// Created by Abe Malla on 12/22/24.
66//
77
8+ import AppKit
9+
810extension ItemBoxWindowController {
911 /// Will constrain the window's frame to be within the visible screen
1012 public func constrainWindowToScreenEdges( cursorRect: NSRect ) {
@@ -59,7 +61,7 @@ extension ItemBoxWindowController {
5961
6062 // MARK: - Private Methods
6163
62- private static func makeWindow( ) -> NSWindow {
64+ static func makeWindow( ) -> NSWindow {
6365 let window = NSWindow (
6466 contentRect: NSRect ( origin: . zero, size: self . DEFAULT_SIZE) ,
6567 styleMask: [ . resizable, . fullSizeContentView, . nonactivatingPanel] ,
@@ -72,7 +74,7 @@ extension ItemBoxWindowController {
7274 return window
7375 }
7476
75- private static func configureWindow( _ window: NSWindow ) {
77+ static func configureWindow( _ window: NSWindow ) {
7678 window. titleVisibility = . hidden
7779 window. titlebarAppearsTransparent = true
7880 window. isExcludedFromWindowsMenu = true
@@ -86,7 +88,7 @@ extension ItemBoxWindowController {
8688 window. minSize = Self . DEFAULT_SIZE
8789 }
8890
89- private static func configureWindowContent( _ window: NSWindow ) {
91+ static func configureWindowContent( _ window: NSWindow ) {
9092 guard let contentView = window. contentView else { return }
9193
9294 contentView. wantsLayer = true
@@ -108,7 +110,7 @@ extension ItemBoxWindowController {
108110 contentView. shadow = innerShadow
109111 }
110112
111- private func configureTableView( ) {
113+ func configureTableView( ) {
112114 tableView. delegate = self
113115 tableView. dataSource = self
114116 tableView. headerView = nil
@@ -125,7 +127,7 @@ extension ItemBoxWindowController {
125127 tableView. addTableColumn ( column)
126128 }
127129
128- private func configureScrollView( ) {
130+ func configureScrollView( ) {
129131 scrollView. documentView = tableView
130132 scrollView. hasVerticalScroller = true
131133 scrollView. verticalScroller = NoSlotScroller ( )
@@ -150,7 +152,7 @@ extension ItemBoxWindowController {
150152
151153 /// Updates the item box window's height based on the number of items.
152154 /// If there are no items, the default label will be displayed instead.
153- private func updateItemBoxWindowAndContents( ) {
155+ func updateItemBoxWindowAndContents( ) {
154156 guard let window = self . window else {
155157 return
156158 }
@@ -185,7 +187,7 @@ extension ItemBoxWindowController {
185187 window. minSize = NSSize ( width: Self . DEFAULT_SIZE. width, height: newHeight)
186188 }
187189
188- private func configureNoItemsLabel( ) {
190+ func configureNoItemsLabel( ) {
189191 window? . contentView? . addSubview ( noItemsLabel)
190192
191193 NSLayoutConstraint . activate ( [
@@ -195,7 +197,7 @@ extension ItemBoxWindowController {
195197 }
196198
197199 /// Calculate the window height for a given number of rows.
198- private static func rowsToWindowHeight( for numberOfRows: CGFloat ) -> CGFloat {
200+ static func rowsToWindowHeight( for numberOfRows: CGFloat ) -> CGFloat {
199201 let wholeRows = floor ( numberOfRows)
200202 let partialRow = numberOfRows - wholeRows
201203
@@ -231,3 +233,32 @@ extension ItemBoxWindowController: NSTableViewDataSource, NSTableViewDelegate {
231233 return true
232234 }
233235}
236+
237+ private class ItemBoxRowView : NSTableRowView {
238+ override func drawSelection( in dirtyRect: NSRect ) {
239+ guard isSelected else { return }
240+ guard let context = NSGraphicsContext . current? . cgContext else { return }
241+
242+ context. saveGState ( )
243+ defer { context. restoreGState ( ) }
244+
245+ // Create a rect that's inset from the edges and has proper padding
246+ // TODO: We create a new selectionRect instead of using dirtyRect
247+ // because there is a visual bug when holding down the arrow keys
248+ // to select the first or last item, which draws a clipped
249+ // rectangular highlight shape instead of the whole rectangle.
250+ // Replace this when it gets fixed.
251+ let selectionRect = NSRect (
252+ x: WINDOW_PADDING,
253+ y: 0 ,
254+ width: bounds. width - ( WINDOW_PADDING * 2 ) ,
255+ height: bounds. height
256+ )
257+ let cornerRadius : CGFloat = 5
258+ let path = NSBezierPath ( roundedRect: selectionRect, xRadius: cornerRadius, yRadius: cornerRadius)
259+ let selectionColor = NSColor . gray. withAlphaComponent ( 0.19 )
260+
261+ context. setFillColor ( selectionColor. cgColor)
262+ path. fill ( )
263+ }
264+ }
0 commit comments