Skip to content

Commit 6718938

Browse files
committed
fix: position popovers using table view geometry instead of cell view bounds
Fixes #209. Cell views can be recycled/relaid-out during click processing, causing popovers to appear at incorrect positions (e.g. window center).
1 parent 50b14d1 commit 6718938

2 files changed

Lines changed: 27 additions & 21 deletions

File tree

TablePro/Views/Results/DataGridView+TypePicker.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@ extension TableViewCoordinator {
1515
column: Int,
1616
columnIndex: Int
1717
) {
18-
guard let cellView = tableView.view(atColumn: column, row: row, makeIfNecessary: false),
18+
guard tableView.view(atColumn: column, row: row, makeIfNecessary: false) != nil,
1919
let rowData = rowProvider.row(at: row) else { return }
2020

2121
let currentValue = rowData.value(at: columnIndex) ?? ""
2222
let dbType = databaseType ?? .mysql
2323

24+
let cellRect = tableView.rect(ofRow: row).intersection(tableView.rect(ofColumn: column))
2425
PopoverPresenter.show(
25-
relativeTo: cellView.bounds,
26-
of: cellView
26+
relativeTo: cellRect,
27+
of: tableView
2728
) { [weak self] dismiss in
2829
TypePickerContentView(
2930
databaseType: dbType,

TablePro/Views/Results/Extensions/DataGridView+Popovers.swift

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ extension TableViewCoordinator {
1414
let currentValue = rowData.value(at: columnIndex)
1515
let columnType = rowProvider.columnTypes[columnIndex]
1616

17-
guard let cellView = tableView.view(atColumn: column, row: row, makeIfNecessary: false) else { return }
17+
guard tableView.view(atColumn: column, row: row, makeIfNecessary: false) != nil else { return }
1818

19+
let cellRect = tableView.rect(ofRow: row).intersection(tableView.rect(ofColumn: column))
1920
DatePickerPopoverController.shared.show(
20-
relativeTo: cellView.bounds,
21-
of: cellView,
21+
relativeTo: cellRect,
22+
of: tableView,
2223
value: currentValue,
2324
columnType: columnType
2425
) { [weak self] newValue in
@@ -48,12 +49,13 @@ extension TableViewCoordinator {
4849
guard let rowData = rowProvider.row(at: row) else { return }
4950
let currentValue = rowData.value(at: columnIndex)
5051

51-
guard let cellView = tableView.view(atColumn: column, row: row, makeIfNecessary: false) else { return }
52+
guard tableView.view(atColumn: column, row: row, makeIfNecessary: false) != nil else { return }
5253
guard let databaseType, let connectionId else { return }
5354

55+
let cellRect = tableView.rect(ofRow: row).intersection(tableView.rect(ofColumn: column))
5456
PopoverPresenter.show(
55-
relativeTo: cellView.bounds,
56-
of: cellView,
57+
relativeTo: cellRect,
58+
of: tableView,
5759
contentSize: NSSize(width: 420, height: 320)
5860
) { [weak self] dismiss in
5961
ForeignKeyPopoverContentView(
@@ -79,11 +81,12 @@ extension TableViewCoordinator {
7981
guard let rowData = rowProvider.row(at: row) else { return }
8082
let currentValue = rowData.value(at: columnIndex)
8183

82-
guard let cellView = tableView.view(atColumn: column, row: row, makeIfNecessary: false) else { return }
84+
guard tableView.view(atColumn: column, row: row, makeIfNecessary: false) != nil else { return }
8385

86+
let cellRect = tableView.rect(ofRow: row).intersection(tableView.rect(ofColumn: column))
8487
PopoverPresenter.show(
85-
relativeTo: cellView.bounds,
86-
of: cellView,
88+
relativeTo: cellRect,
89+
of: tableView,
8790
contentSize: NSSize(width: 420, height: 340)
8891
) { [weak self] dismiss in
8992
JSONEditorContentView(
@@ -103,7 +106,7 @@ extension TableViewCoordinator {
103106
}
104107

105108
func showEnumPopover(tableView: NSTableView, row: Int, column: Int, columnIndex: Int) {
106-
guard let cellView = tableView.view(atColumn: column, row: row, makeIfNecessary: false),
109+
guard tableView.view(atColumn: column, row: row, makeIfNecessary: false) != nil,
107110
let rowData = rowProvider.row(at: row) else { return }
108111
let columnName = rowProvider.columns[columnIndex]
109112
guard let allowedValues = rowProvider.columnEnumValues[columnName] else { return }
@@ -117,9 +120,10 @@ extension TableViewCoordinator {
117120
}
118121
values.append(contentsOf: allowedValues)
119122

123+
let cellRect = tableView.rect(ofRow: row).intersection(tableView.rect(ofColumn: column))
120124
PopoverPresenter.show(
121-
relativeTo: cellView.bounds,
122-
of: cellView
125+
relativeTo: cellRect,
126+
of: tableView
123127
) { [weak self] dismiss in
124128
EnumPopoverContentView(
125129
allValues: values,
@@ -134,7 +138,7 @@ extension TableViewCoordinator {
134138
}
135139

136140
func showSetPopover(tableView: NSTableView, row: Int, column: Int, columnIndex: Int) {
137-
guard let cellView = tableView.view(atColumn: column, row: row, makeIfNecessary: false),
141+
guard tableView.view(atColumn: column, row: row, makeIfNecessary: false) != nil,
138142
let rowData = rowProvider.row(at: row) else { return }
139143
let columnName = rowProvider.columns[columnIndex]
140144
guard let allowedValues = rowProvider.columnEnumValues[columnName] else { return }
@@ -152,9 +156,10 @@ extension TableViewCoordinator {
152156
selections[value] = currentSet.contains(value)
153157
}
154158

159+
let cellRect = tableView.rect(ofRow: row).intersection(tableView.rect(ofColumn: column))
155160
PopoverPresenter.show(
156-
relativeTo: cellView.bounds,
157-
of: cellView
161+
relativeTo: cellRect,
162+
of: tableView
158163
) { [weak self] dismiss in
159164
SetPopoverContentView(
160165
allowedValues: allowedValues,
@@ -168,7 +173,7 @@ extension TableViewCoordinator {
168173
}
169174

170175
func showDropdownMenu(tableView: NSTableView, row: Int, column: Int, columnIndex: Int) {
171-
guard let cellView = tableView.view(atColumn: column, row: row, makeIfNecessary: false),
176+
guard tableView.view(atColumn: column, row: row, makeIfNecessary: false) != nil,
172177
let rowData = rowProvider.row(at: row) else { return }
173178

174179
let currentValue = rowData.value(at: columnIndex)
@@ -185,8 +190,8 @@ extension TableViewCoordinator {
185190
menu.addItem(item)
186191
}
187192

188-
let cellRect = cellView.bounds
189-
menu.popUp(positioning: nil, at: NSPoint(x: cellRect.minX, y: cellRect.maxY), in: cellView)
193+
let cellRect = tableView.rect(ofRow: row).intersection(tableView.rect(ofColumn: column))
194+
menu.popUp(positioning: nil, at: NSPoint(x: cellRect.minX, y: cellRect.maxY), in: tableView)
190195
}
191196

192197
@objc func dropdownMenuItemSelected(_ sender: NSMenuItem) {

0 commit comments

Comments
 (0)