@@ -97,8 +97,8 @@ extension TableViewCoordinator {
9797 editor. onCommit = { [ weak self] row, columnIndex, newValue in
9898 self ? . commitCellEdit ( row: row, columnIndex: columnIndex, newValue: newValue)
9999 }
100- editor. onTabNavigation = { [ weak self] row, column, forward in
101- self ? . handleOverlayTabNavigation ( row: row, column: column, forward : forward )
100+ editor. onMovement = { [ weak self] row, column, movement in
101+ self ? . handleOverlayMovement ( row: row, column: column, movement : movement )
102102 }
103103 overlayViewer? . dismiss ( )
104104 editor. show ( in: tableView, row: row, column: column, columnIndex: columnIndex, value: value)
@@ -116,30 +116,31 @@ extension TableViewCoordinator {
116116 viewer. show ( in: tableView, row: row, column: column, columnIndex: columnIndex, value: value)
117117 }
118118
119- func handleOverlayTabNavigation( row: Int , column: Int , forward: Bool ) {
120- guard let tableView = tableView,
121- let target = tabNavigationTarget ( from: ( row, column) , forward: forward, in: tableView)
119+ /// The cell cursor moves with the editor, through the same `focusCell` the grid's own Tab uses.
120+ /// Selecting the row alone left the cursor on the column the editor came from, so closing the
121+ /// editor put it back where the editing was not, and it never scrolled the target row into
122+ /// view, so a wrap onto the row below the last visible one opened the editor off screen.
123+ func handleOverlayMovement( row: Int , column: Int , movement: CellEditorMovement ) {
124+ guard let tableView = tableView as? KeyHandlingTableView ,
125+ let target = movementTarget ( from: ( row, column) , movement: movement, in: tableView)
122126 else { return }
123127
124- let nextRow = target. row
125- let nextColumn = target. column
126- tableView. selectRowIndexes ( IndexSet ( integer: nextRow) , byExtendingSelection: false )
127- scrollColumnToVisible ( tableColumnIndex: nextColumn)
128+ tableView. focusCell ( row: target. row, column: target. column)
128129
129- guard let nextColumnIndex = DataGridView . dataColumnIndex (
130- for: nextColumn ,
130+ guard let targetColumnIndex = DataGridView . dataColumnIndex (
131+ for: target . column ,
131132 in: tableView,
132133 schema: identitySchema
133134 ) ,
134- nextColumnIndex >= 0 ,
135- case . editable( let value) = editEligibility ( row: nextRow , columnIndex: nextColumnIndex )
135+ targetColumnIndex >= 0 ,
136+ case . editable( let value) = editEligibility ( row: target . row , columnIndex: targetColumnIndex )
136137 else { return }
137138
138139 showOverlayEditor (
139140 tableView: tableView,
140- row: nextRow ,
141- column: nextColumn ,
142- columnIndex: nextColumnIndex ,
141+ row: target . row ,
142+ column: target . column ,
143+ columnIndex: targetColumnIndex ,
143144 value: value
144145 )
145146 }
@@ -148,22 +149,34 @@ extension TableViewCoordinator {
148149 /// previous row's last. Both ends are resolved rather than assumed: the window's spacers and
149150 /// the pool's surplus slots are attached columns too, so neither end of `tableColumns` holds a
150151 /// data column and a fixed position lands on a spacer that swallows the keystroke.
151- private func tabNavigationTarget(
152+ ///
153+ /// Up and Down hold the column and step one row, and neither wraps: a column is a column of one
154+ /// kind of value, so carrying the editor from the last row round to the first is a jump the
155+ /// user did not ask for.
156+ func movementTarget(
152157 from cell: ( row: Int , column: Int ) ,
153- forward : Bool ,
158+ movement : CellEditorMovement ,
154159 in tableView: NSTableView
155160 ) -> ( row: Int , column: Int ) ? {
156- if forward {
161+ switch movement {
162+ case . tab:
157163 if let next = nextPresentedColumnIndex ( after: cell. column) {
158164 return ( cell. row, next)
159165 }
160166 guard cell. row + 1 < tableView. numberOfRows, let first = firstPresentedColumnIndex ( ) else { return nil }
161167 return ( cell. row + 1 , first)
168+ case . backtab:
169+ if let previous = previousPresentedColumnIndex ( before: cell. column) {
170+ return ( cell. row, previous)
171+ }
172+ guard cell. row > 0 , let last = lastPresentedColumnIndex ( ) else { return nil }
173+ return ( cell. row - 1 , last)
174+ case . up:
175+ guard cell. row > 0 else { return nil }
176+ return ( cell. row - 1 , cell. column)
177+ case . down:
178+ guard cell. row + 1 < tableView. numberOfRows else { return nil }
179+ return ( cell. row + 1 , cell. column)
162180 }
163- if let previous = previousPresentedColumnIndex ( before: cell. column) {
164- return ( cell. row, previous)
165- }
166- guard cell. row > 0 , let last = lastPresentedColumnIndex ( ) else { return nil }
167- return ( cell. row - 1 , last)
168181 }
169182}
0 commit comments