Skip to content

Commit 7d14a5e

Browse files
committed
fix(table): checkbox mode sync with selection, click-on-checkbox toggle
Extract ToggleRowSelection for keyboard spacebar. Add checkbox column click detection so clicking the checkbox toggles without clearing other selections. Sync IsChecked state with selection in SelectAll, ClearSelection, ToggleRowSelection, and SelectRange.
1 parent 073a04b commit 7d14a5e

3 files changed

Lines changed: 63 additions & 14 deletions

File tree

SharpConsoleUI/Controls/TableControl/TableControl.Keyboard.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -191,19 +191,8 @@ public bool ProcessKey(ConsoleKeyInfo key)
191191
case ConsoleKey.Spacebar when _checkboxMode && _multiSelectEnabled:
192192
if (_selectedRowIndex >= 0)
193193
{
194-
int dataIdx = MapDisplayToData(_selectedRowIndex);
195-
if (_dataSource == null)
196-
{
197-
lock (_tableLock)
198-
{
199-
if (dataIdx >= 0 && dataIdx < _rows.Count)
200-
{
201-
_rows[dataIdx].IsChecked = !_rows[dataIdx].IsChecked;
202-
Container?.Invalidate(true);
203-
return true;
204-
}
205-
}
206-
}
194+
ToggleRowSelection(_selectedRowIndex);
195+
return true;
207196
}
208197
return false;
209198

SharpConsoleUI/Controls/TableControl/TableControl.Mouse.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public bool ProcessMouseEvent(MouseEventArgs args)
203203
int rowIdx = GetRowIndexAtY(args.Position.Y);
204204
if (rowIdx >= 0)
205205
{
206-
// Multi-select: Ctrl+Click toggles, Shift+Click extends range
206+
// Multi-select: Ctrl+Click toggles, Shift+Click extends range, checkbox click toggles
207207
if (_multiSelectEnabled && args.HasFlag(MouseFlags.ButtonCtrl))
208208
{
209209
ToggleRowSelection(rowIdx);
@@ -216,10 +216,27 @@ public bool ProcessMouseEvent(MouseEventArgs args)
216216
SelectRange(anchor, rowIdx);
217217
SetSelectedRow(rowIdx);
218218
}
219+
else if (_checkboxMode && IsClickOnCheckbox(args.Position.X))
220+
{
221+
// Click on checkbox column — toggle without clearing other selections
222+
ToggleRowSelection(rowIdx);
223+
SetSelectedRow(rowIdx);
224+
}
219225
else
220226
{
221227
if (_multiSelectEnabled)
228+
{
229+
// Clear checkboxes when clicking outside checkbox column
230+
if (_checkboxMode && _dataSource == null)
231+
{
232+
lock (_tableLock)
233+
{
234+
foreach (var row in _rows)
235+
row.IsChecked = false;
236+
}
237+
}
222238
_selectedRowIndices.Clear();
239+
}
223240
SetSelectedRow(rowIdx);
224241
}
225242

@@ -345,6 +362,14 @@ private int GetColumnIndexAtX(int relativeX)
345362
return -1;
346363
}
347364

365+
private bool IsClickOnCheckbox(int relativeX)
366+
{
367+
if (!_checkboxMode) return false;
368+
// Checkbox is rendered as "[x] " or "[ ] " — 4 chars at the start of the row
369+
int checkboxEnd = Margin.Left + (_borderStyle != BorderStyle.None ? 1 : 0) + 4;
370+
return relativeX < checkboxEnd;
371+
}
372+
348373
private bool IsClickOnHeader(MouseEventArgs args)
349374
{
350375
if (!_showHeader) return false;

SharpConsoleUI/Controls/TableControl/TableControl.Selection.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,11 @@ public void SelectAll()
219219
int count = RowCount;
220220
_selectedRowIndices.Clear();
221221
for (int i = 0; i < count; i++)
222+
{
222223
_selectedRowIndices.Add(i);
224+
if (_checkboxMode)
225+
SyncCheckboxState(i);
226+
}
223227
Container?.Invalidate(true);
224228
}
225229

@@ -228,6 +232,14 @@ public void SelectAll()
228232
/// </summary>
229233
public void ClearSelection()
230234
{
235+
if (_checkboxMode && _dataSource == null)
236+
{
237+
lock (_tableLock)
238+
{
239+
foreach (var row in _rows)
240+
row.IsChecked = false;
241+
}
242+
}
231243
_selectedRowIndices.Clear();
232244
Container?.Invalidate(true);
233245
}
@@ -272,6 +284,11 @@ internal void ToggleRowSelection(int displayIndex)
272284
_selectedRowIndices.Remove(displayIndex);
273285
else
274286
_selectedRowIndices.Add(displayIndex);
287+
288+
// Sync checkbox state
289+
if (_checkboxMode)
290+
SyncCheckboxState(displayIndex);
291+
275292
Container?.Invalidate(true);
276293
}
277294

@@ -284,10 +301,28 @@ internal void SelectRange(int fromDisplayIndex, int toDisplayIndex)
284301
int start = Math.Min(fromDisplayIndex, toDisplayIndex);
285302
int end = Math.Max(fromDisplayIndex, toDisplayIndex);
286303
for (int i = start; i <= end; i++)
304+
{
287305
_selectedRowIndices.Add(i);
306+
if (_checkboxMode)
307+
SyncCheckboxState(i);
308+
}
288309
Container?.Invalidate(true);
289310
}
290311

312+
/// <summary>
313+
/// Syncs the IsChecked property of a row with its selection state.
314+
/// </summary>
315+
private void SyncCheckboxState(int displayIndex)
316+
{
317+
if (_dataSource != null) return;
318+
lock (_tableLock)
319+
{
320+
int dataIdx = MapDisplayToData(displayIndex);
321+
if (dataIdx >= 0 && dataIdx < _rows.Count)
322+
_rows[dataIdx].IsChecked = _selectedRowIndices.Contains(displayIndex);
323+
}
324+
}
325+
291326
/// <summary>
292327
/// Returns whether a display row index is selected (in multi-select mode) or is the current selected row.
293328
/// </summary>

0 commit comments

Comments
 (0)