Skip to content

Commit 97d4c0a

Browse files
committed
Refactored RadioGroup to just use Commands
1 parent 9563ec9 commit 97d4c0a

File tree

2 files changed

+154
-193
lines changed

2 files changed

+154
-193
lines changed

Terminal.Gui/Views/RadioGroup.cs

Lines changed: 151 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -16,162 +16,22 @@ public RadioGroup ()
1616
Width = Dim.Auto (DimAutoStyle.Content);
1717
Height = Dim.Auto (DimAutoStyle.Content);
1818

19-
2019
// Select (Space key or mouse click) - The default implementation sets focus. RadioGroup does not.
21-
AddCommand (
22-
Command.Select,
23-
(ctx) =>
24-
{
25-
bool cursorChanged = false;
26-
if (SelectedItem == Cursor)
27-
{
28-
cursorChanged = MoveDownRight ();
29-
if (!cursorChanged)
30-
{
31-
cursorChanged = MoveHome ();
32-
}
33-
}
34-
35-
bool selectedItemChanged = false;
36-
if (SelectedItem != Cursor)
37-
{
38-
selectedItemChanged = ChangeSelectedItem (Cursor);
39-
}
40-
41-
if (cursorChanged || selectedItemChanged)
42-
{
43-
if (RaiseSelecting (ctx) == true)
44-
{
45-
return true;
46-
}
47-
}
20+
AddCommand (Command.Select, HandleSelectCommand);
4821

49-
return cursorChanged || selectedItemChanged;
50-
});
51-
52-
// Accept (Enter key) - Raise Accept event - DO NOT advance state
53-
AddCommand (Command.Accept, RaiseAccepting);
22+
// Accept (Enter key or Doubleclick) - Raise Accept event - DO NOT advance state
23+
AddCommand (Command.Accept, HandleAcceptCommand);
5424

5525
// Hotkey - ctx may indicate a radio item hotkey was pressed. Behavior depends on HasFocus
5626
// If HasFocus and it's this.HotKey invoke Select command - DO NOT raise Accept
5727
// If it's a radio item HotKey select that item and raise Selected event - DO NOT raise Accept
5828
// If nothing is selected, select first and raise Selected event - DO NOT raise Accept
59-
AddCommand (Command.HotKey,
60-
ctx =>
61-
{
62-
// If the command did not come from a keyboard event, ignore it
63-
if (ctx is not CommandContext<KeyBinding> keyCommandContext)
64-
{
65-
return false;
66-
}
67-
68-
var item = keyCommandContext.Binding.Data as int?;
69-
70-
if (HasFocus)
71-
{
72-
if (keyCommandContext is { Binding : { } } && (item is null || HotKey == keyCommandContext.Binding.Key?.NoAlt.NoCtrl.NoShift))
73-
{
74-
// It's this.HotKey OR Another View (Label?) forwarded the hotkey command to us - Act just like `Space` (Select)
75-
return InvokeCommand (Command.Select);
76-
}
77-
}
78-
79-
if (item is { } && item < _radioLabels.Count)
80-
{
81-
if (item.Value == SelectedItem)
82-
{
83-
return true;
84-
}
85-
86-
// If a RadioItem.HotKey is pressed we always set the selected item - never SetFocus
87-
bool selectedItemChanged = ChangeSelectedItem (item.Value);
88-
89-
if (selectedItemChanged)
90-
{
91-
// Doesn't matter if it's handled
92-
RaiseSelecting (ctx);
93-
return true;
94-
}
95-
96-
97-
return false;
98-
}
99-
100-
if (SelectedItem == -1 && ChangeSelectedItem (0))
101-
{
102-
if (RaiseSelecting (ctx) == true)
103-
{
104-
return true;
105-
}
106-
return false;
107-
}
108-
109-
if (RaiseHandlingHotKey () == true)
110-
{
111-
return true;
112-
};
113-
114-
// Default Command.Hotkey sets focus
115-
SetFocus ();
116-
117-
return true;
118-
});
119-
120-
AddCommand (
121-
Command.Up,
122-
() =>
123-
{
124-
if (!HasFocus)
125-
{
126-
return false;
127-
}
128-
129-
return MoveUpLeft ();
130-
}
131-
);
29+
AddCommand (Command.HotKey, HandleHotKeyCommand);
13230

133-
AddCommand (
134-
Command.Down,
135-
() =>
136-
{
137-
if (!HasFocus)
138-
{
139-
return false;
140-
}
141-
142-
return MoveDownRight ();
143-
}
144-
);
145-
146-
AddCommand (
147-
Command.Start,
148-
() =>
149-
{
150-
if (!HasFocus)
151-
{
152-
return false;
153-
}
154-
155-
MoveHome ();
156-
157-
return true;
158-
}
159-
);
160-
161-
AddCommand (
162-
Command.End,
163-
() =>
164-
{
165-
if (!HasFocus)
166-
{
167-
return false;
168-
}
169-
170-
MoveEnd ();
171-
172-
return true;
173-
}
174-
);
31+
AddCommand (Command.Up, () => HasFocus && MoveUpLeft ());
32+
AddCommand (Command.Down, () => HasFocus && MoveDownRight ());
33+
AddCommand (Command.Start, () => HasFocus && MoveHome ());
34+
AddCommand (Command.End, () => HasFocus && MoveEnd ());
17535

17636
// ReSharper disable once UseObjectOrCollectionInitializer
17737
_orientationHelper = new (this);
@@ -181,11 +41,147 @@ public RadioGroup ()
18141

18242
SetupKeyBindings ();
18343

44+
// By default, single click is already bound to Command.Select
45+
MouseBindings.Add (MouseFlags.Button1DoubleClicked, Command.Accept);
46+
18447
SubviewLayout += RadioGroup_LayoutStarted;
18548

18649
HighlightStyle = HighlightStyle.PressedOutside | HighlightStyle.Pressed;
50+
}
51+
52+
private bool? HandleHotKeyCommand (ICommandContext? ctx)
53+
{
54+
// If the command did not come from a keyboard event, ignore it
55+
if (ctx is not CommandContext<KeyBinding> keyCommandContext)
56+
{
57+
return false;
58+
}
59+
60+
var item = keyCommandContext.Binding.Data as int?;
61+
62+
if (HasFocus)
63+
{
64+
if ((item is null || HotKey == keyCommandContext.Binding.Key?.NoAlt.NoCtrl.NoShift!))
65+
{
66+
// It's this.HotKey OR Another View (Label?) forwarded the hotkey command to us - Act just like `Space` (Select)
67+
return InvokeCommand (Command.Select);
68+
}
69+
}
70+
71+
if (item is { } && item < _radioLabels.Count)
72+
{
73+
if (item.Value == SelectedItem)
74+
{
75+
return true;
76+
}
77+
78+
// If a RadioItem.HotKey is pressed we always set the selected item - never SetFocus
79+
bool selectedItemChanged = ChangeSelectedItem (item.Value);
80+
81+
if (selectedItemChanged)
82+
{
83+
// Doesn't matter if it's handled
84+
RaiseSelecting (ctx);
85+
86+
return true;
87+
}
88+
89+
return false;
90+
}
91+
92+
if (SelectedItem == -1 && ChangeSelectedItem (0))
93+
{
94+
if (RaiseSelecting (ctx) == true)
95+
{
96+
return true;
97+
}
98+
99+
return false;
100+
}
101+
102+
if (RaiseHandlingHotKey () == true)
103+
{
104+
return true;
105+
}
106+
107+
;
108+
109+
// Default Command.Hotkey sets focus
110+
SetFocus ();
111+
112+
return true;
113+
}
114+
115+
private bool? HandleAcceptCommand (ICommandContext? ctx)
116+
{
117+
if (!DoubleClickAccepts
118+
&& ctx is CommandContext<MouseBinding> mouseCommandContext
119+
&& mouseCommandContext.Binding.MouseEventArgs!.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
120+
{
121+
return false;
122+
}
123+
124+
return RaiseAccepting (ctx);
125+
}
126+
127+
private bool? HandleSelectCommand (ICommandContext? ctx)
128+
{
129+
if (ctx is CommandContext<MouseBinding> mouseCommandContext
130+
&& mouseCommandContext.Binding.MouseEventArgs!.Flags.HasFlag (MouseFlags.Button1Clicked))
131+
{
132+
int viewportX = mouseCommandContext.Binding.MouseEventArgs.Position.X;
133+
int viewportY = mouseCommandContext.Binding.MouseEventArgs.Position.Y;
134+
135+
int pos = Orientation == Orientation.Horizontal ? viewportX : viewportY;
136+
137+
int rCount = Orientation == Orientation.Horizontal
138+
? _horizontal!.Last ().pos + _horizontal!.Last ().length
139+
: _radioLabels.Count;
140+
141+
if (pos < rCount)
142+
{
143+
int c = Orientation == Orientation.Horizontal
144+
? _horizontal!.FindIndex (x => x.pos <= viewportX && x.pos + x.length - 2 >= viewportX)
145+
: viewportY;
146+
147+
if (c > -1)
148+
{
149+
// Just like the user pressing the items' hotkey
150+
return InvokeCommand<KeyBinding> (Command.HotKey, new KeyBinding ([Command.HotKey], target: this, data: c)) == true;
151+
}
152+
}
153+
154+
return false;
155+
}
156+
157+
bool cursorChanged = false;
158+
159+
if (SelectedItem == Cursor)
160+
{
161+
cursorChanged = MoveDownRight ();
162+
163+
if (!cursorChanged)
164+
{
165+
cursorChanged = MoveHome ();
166+
}
167+
}
168+
169+
bool selectedItemChanged = false;
170+
171+
if (SelectedItem != Cursor)
172+
{
173+
selectedItemChanged = ChangeSelectedItem (Cursor);
174+
}
175+
176+
if (cursorChanged || selectedItemChanged)
177+
{
178+
if (RaiseSelecting (ctx) == true)
179+
{
180+
return true;
181+
}
182+
}
187183

188-
MouseClick += RadioGroup_MouseClick;
184+
return cursorChanged || selectedItemChanged;
189185
}
190186

191187
// TODO: Fix InvertColorsOnPress - only highlight the selected item
@@ -226,48 +222,6 @@ private void SetupKeyBindings ()
226222
/// </remarks>
227223
public bool DoubleClickAccepts { get; set; } = true;
228224

229-
private void RadioGroup_MouseClick (object? sender, MouseEventArgs e)
230-
{
231-
if (e.Flags.HasFlag (MouseFlags.Button1Clicked))
232-
{
233-
int viewportX = e.Position.X;
234-
int viewportY = e.Position.Y;
235-
236-
int pos = Orientation == Orientation.Horizontal ? viewportX : viewportY;
237-
238-
int rCount = Orientation == Orientation.Horizontal
239-
? _horizontal!.Last ().pos + _horizontal!.Last ().length
240-
: _radioLabels.Count;
241-
242-
if (pos < rCount)
243-
{
244-
int c = Orientation == Orientation.Horizontal
245-
? _horizontal!.FindIndex (x => x.pos <= viewportX && x.pos + x.length - 2 >= viewportX)
246-
: viewportY;
247-
248-
if (c > -1)
249-
{
250-
// Just like the user pressing the items' hotkey
251-
e.Handled = InvokeCommand<KeyBinding> (Command.HotKey, new KeyBinding ([Command.HotKey], target: this, data: c)) == true;
252-
}
253-
}
254-
255-
return;
256-
}
257-
258-
if (DoubleClickAccepts && e.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
259-
{
260-
// NOTE: Drivers ALWAYS generate a Button1Clicked event before Button1DoubleClicked
261-
// NOTE: So, we've already selected an item.
262-
263-
// Just like the user pressing `Enter`
264-
InvokeCommand (Command.Accept);
265-
}
266-
267-
// HACK: Always eat so Select is not invoked by base
268-
e.Handled = true;
269-
}
270-
271225
private List<(int pos, int length)>? _horizontal;
272226
private int _horizontalSpace = 2;
273227

@@ -538,7 +492,12 @@ private bool MoveDownRight ()
538492
return false;
539493
}
540494

541-
private void MoveEnd () { Cursor = Math.Max (_radioLabels.Count - 1, 0); }
495+
private bool MoveEnd ()
496+
{
497+
Cursor = Math.Max (_radioLabels.Count - 1, 0);
498+
499+
return true;
500+
}
542501

543502
private bool MoveHome ()
544503
{

UICatalog/Scenarios/MessageBoxes.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ public override void Main ()
185185

186186
var styleRadioGroup = new RadioGroup
187187
{
188-
X = Pos.Right (label) + 1, Y = Pos.Top (label), RadioLabels = new [] { "_Query", "_Error" }
188+
X = Pos.Right (label) + 1,
189+
Y = Pos.Top (label),
190+
RadioLabels = ["_Query", "_Error"],
189191
};
190192
frame.Add (styleRadioGroup);
191193

0 commit comments

Comments
 (0)