Skip to content

Commit 09bf311

Browse files
committed
Use Ctrl+click for additive DataGrid sorting
1 parent f6ca0ba commit 09bf311

File tree

5 files changed

+56
-5
lines changed

5 files changed

+56
-5
lines changed

samples/ControlsDemo/Demos/DataGridDemo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public override Visual Build(DemoContext context)
6868

6969
return new VStack(
7070
DemoUi.Hint("Wrap DataGridControl in a ScrollViewer to show scrollbars."),
71-
DemoUi.Hint("Click a header sort button to cycle off/descending/ascending. Shift+click adds a secondary sort."),
71+
DemoUi.Hint("Click a header sort button to cycle off/descending/ascending. Ctrl+click adds a secondary sort."),
7272
DemoUi.Hint("Ctrl+F: search (find), F3/Shift+F3: next/previous match"),
7373
DemoUi.Hint("F4: toggle filter row, F2: edit current cell"),
7474
controls,

site/docs/controls/datagrid.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ Sorting is opt-in per UI column:
105105
- set `DataGridColumn.Sortable = true` to show the header sort button,
106106
- optionally set `DataGridColumn<T>.SortComparer` to override the default `Comparer<T>.Default`,
107107
- click the header sort button to cycle `None -> Descending -> Ascending -> None`,
108-
- `Shift+click` adds/removes secondary sorts so multi-column sorts are additive and stable.
108+
- `Ctrl+click` adds/removes secondary sorts so multi-column sorts are additive and stable (`Alt+click` is also accepted).
109109

110110
You can also sort programmatically:
111111

@@ -121,7 +121,7 @@ When the view is a `DataGridDocumentView`, any configured `SortComparer` is forw
121121
- `Ctrl+F`: open find UI (uses `SearchReplacePopup` in find mode)
122122
- `F3` / `Shift+F3`: next / previous match
123123
- `F4`: toggle filter row (when `View` is filterable)
124-
- click header sort button: toggle sort (`Shift+click` for additive multi-sort)
124+
- click header sort button: toggle sort (`Ctrl+click` for additive multi-sort; `Alt+click` also works)
125125
- Arrow keys / PageUp / PageDown: navigate the current cell
126126
- `F2` or `Enter`: edit current cell (when editable)
127127

site/docs/specs/controls/datagrid.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ Suggested UX:
704704

705705
- sortable columns render a sort button in the header (right aligned inside the header cell)
706706
- click the sort button toggles `None → Desc → Asc → None`
707-
- `Shift+click` adds/removes secondary sort (multi-sort)
707+
- `Ctrl+click` adds/removes secondary sort (multi-sort); `Alt+click` MAY be accepted as an equivalent terminal-safe modifier
708708
- programmatic sorting is available through `DataGridControl.TrySetColumnSortDirection(...)`
709709
- the default `DataGridDocumentView` preserves row stability by using the full active sort description list and falling
710710
back to document order for ties

src/XenoAtom.Terminal.UI.Tests/DataGridSortingTests.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,54 @@ static string GetRenderedText(TerminalAppTestDriver currentDriver)
149149
Assert.AreEqual("a", ((SortRow)view.CurrentSnapshot.GetRowModel(0)).Name);
150150
}
151151

152+
[TestMethod]
153+
public void DataGrid_Header_Sort_Button_Uses_Ctrl_Click_For_Additive_Sort()
154+
{
155+
var groupAccessor = new BindingAccessor<string>("group", o => ((GroupedSortRow)o).Group, (o, v) => ((GroupedSortRow)o).Group = v);
156+
var nameAccessor = new BindingAccessor<string>("name", o => ((GroupedSortRow)o).Name, (o, v) => ((GroupedSortRow)o).Name = v);
157+
158+
var doc = new DataGridListDocument<GroupedSortRow>();
159+
doc.SetColumns(new[]
160+
{
161+
new DataGridColumnInfo("group", "Group", typeof(string), ReadOnly: false, groupAccessor),
162+
new DataGridColumnInfo("name", "Name", typeof(string), ReadOnly: false, nameAccessor),
163+
});
164+
165+
doc.AddRow(new GroupedSortRow { Group = "B", Name = "a", Sequence = 0 });
166+
doc.AddRow(new GroupedSortRow { Group = "A", Name = "b", Sequence = 1 });
167+
doc.AddRow(new GroupedSortRow { Group = "A", Name = "a", Sequence = 2 });
168+
169+
using var view = new DataGridDocumentView(doc);
170+
171+
var grid = new DataGridControl { View = view, ShowRowAnchor = false };
172+
grid.Columns.Add(new DataGridColumn<string> { Key = "group", TypedValueAccessor = groupAccessor, Width = GridLength.Fixed(7), Sortable = true });
173+
grid.Columns.Add(new DataGridColumn<string> { Key = "name", TypedValueAccessor = nameAccessor, Width = GridLength.Fixed(6), Sortable = true });
174+
175+
using var driver = new TerminalAppTestDriver(grid, TerminalHostKind.Fullscreen, new TerminalSize(16, 5));
176+
driver.Tick();
177+
178+
var groupSortButtonX = grid.Bounds.X + 6;
179+
var nameSortButtonX = grid.Bounds.X + 13;
180+
var sortButtonY = grid.Bounds.Y;
181+
182+
driver.Backend.PushEvent(new TerminalMouseEvent { Kind = TerminalMouseKind.Down, Button = TerminalMouseButton.Left, X = groupSortButtonX, Y = sortButtonY });
183+
driver.Backend.PushEvent(new TerminalMouseEvent { Kind = TerminalMouseKind.Up, Button = TerminalMouseButton.Left, X = groupSortButtonX, Y = sortButtonY });
184+
driver.Tick();
185+
186+
driver.Backend.PushEvent(new TerminalMouseEvent { Kind = TerminalMouseKind.Down, Button = TerminalMouseButton.Left, X = nameSortButtonX, Y = sortButtonY, Modifiers = TerminalModifiers.Ctrl });
187+
driver.Backend.PushEvent(new TerminalMouseEvent { Kind = TerminalMouseKind.Up, Button = TerminalMouseButton.Left, X = nameSortButtonX, Y = sortButtonY, Modifiers = TerminalModifiers.Ctrl });
188+
driver.Tick();
189+
190+
var sorts = grid.SortDescriptions.ToArray();
191+
CollectionAssert.AreEqual(
192+
new[]
193+
{
194+
new DataGridSortDescription("group", DataGridSortDirection.Descending),
195+
new DataGridSortDescription("name", DataGridSortDirection.Descending),
196+
},
197+
sorts);
198+
}
199+
152200
private sealed class SortRow
153201
{
154202
public string Name { get; set; } = string.Empty;

src/XenoAtom.Terminal.UI/Controls/DataGridControl.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,7 @@ protected override void OnPointerReleased(PointerEventArgs e)
13771377
var columns = EnsureResolvedColumns(snapshot, visibleColumns);
13781378
if ((uint)sortColumnIndex < (uint)columns.Count)
13791379
{
1380-
_ = TryToggleColumnSortDirection(columns[sortColumnIndex].Key, additive: (e.Modifiers & TerminalModifiers.Shift) != 0);
1380+
_ = TryToggleColumnSortDirection(columns[sortColumnIndex].Key, additive: IsAdditiveSortModifier(e.Modifiers));
13811381
}
13821382
}
13831383

@@ -1809,6 +1809,9 @@ private void ConfigureSortComparers()
18091809

18101810
private bool CanSort => View is ISortableDataGridView;
18111811

1812+
private static bool IsAdditiveSortModifier(TerminalModifiers modifiers)
1813+
=> (modifiers & (TerminalModifiers.Ctrl | TerminalModifiers.Alt)) != 0;
1814+
18121815
private bool TryGetSortableColumn(string columnKey, out DataGridColumn? column)
18131816
{
18141817
for (var i = 0; i < Columns.Count; i++)

0 commit comments

Comments
 (0)