Skip to content

Commit ba9293f

Browse files
committed
Merge branch 'main' of tig:migueldeicaza/gui.cs
2 parents debe918 + 028e7e5 commit ba9293f

File tree

3 files changed

+147
-221
lines changed

3 files changed

+147
-221
lines changed

Terminal.Gui/Views/TextValidateField.cs

+73-138
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,14 @@ public interface ITextValidateProvider {
8181
bool IsValid { get; }
8282

8383
/// <summary>
84-
/// Set the input text, and get the formatted string for display.
84+
/// Set the input text and get the current value.
8585
/// </summary>
8686
ustring Text { get; set; }
8787

8888
/// <summary>
89-
/// Mask used for validation.
90-
/// Not always a mask, can by a regex expression.
91-
/// TODO: Maybe we can change the name.
89+
/// Gets the formatted string for display.
9290
/// </summary>
93-
ustring Mask { get; set; }
91+
ustring DisplayText { get; }
9492
}
9593

9694
//////////////////////////////////////////////////////////////////////////////
@@ -107,33 +105,37 @@ public interface ITextValidateProvider {
107105
/// </summary>
108106
public class NetMaskedTextProvider : ITextValidateProvider {
109107
MaskedTextProvider provider;
110-
string text;
111108

112109
/// <summary>
113110
/// Empty Constructor
114111
/// </summary>
115-
public NetMaskedTextProvider () { }
112+
public NetMaskedTextProvider (string mask)
113+
{
114+
Mask = mask;
115+
}
116116

117-
///<inheritdoc/>
117+
/// <summary>
118+
/// Mask property
119+
/// </summary>
118120
public ustring Mask {
119121
get {
120122
return provider?.Mask;
121123
}
122124
set {
125+
var current = provider != null ? provider.ToString (false, false) : string.Empty;
123126
provider = new MaskedTextProvider (value == ustring.Empty ? "&&&&&&" : value.ToString ());
124-
if (string.IsNullOrEmpty (text) == false) {
125-
provider.Set (text);
127+
if (string.IsNullOrEmpty (current) == false) {
128+
provider.Set (current);
126129
}
127130
}
128131
}
129132

130133
///<inheritdoc/>
131134
public ustring Text {
132135
get {
133-
return provider.ToDisplayString ();
136+
return provider.ToString ();
134137
}
135138
set {
136-
text = value.ToString ();
137139
provider.Set (value.ToString ());
138140
}
139141
}
@@ -144,6 +146,9 @@ public ustring Text {
144146
///<inheritdoc/>
145147
public bool Fixed => true;
146148

149+
///<inheritdoc/>
150+
public ustring DisplayText => provider.ToDisplayString ();
151+
147152
///<inheritdoc/>
148153
public int Cursor (int pos)
149154
{
@@ -212,20 +217,25 @@ public bool InsertAt (char ch, int pos)
212217
public class TextRegexProvider : ITextValidateProvider {
213218
Regex regex;
214219
List<Rune> text;
215-
List<Rune> mask;
220+
List<Rune> pattern;
216221

217222
/// <summary>
218-
/// Empty Constructor
223+
/// Empty Constructor.
219224
/// </summary>
220-
public TextRegexProvider () { }
225+
public TextRegexProvider (string pattern)
226+
{
227+
Pattern = pattern;
228+
}
221229

222-
///<inheritdoc/>
223-
public ustring Mask {
230+
/// <summary>
231+
/// Regex pattern property.
232+
/// </summary>
233+
public ustring Pattern {
224234
get {
225-
return ustring.Make (mask);
235+
return ustring.Make (pattern);
226236
}
227237
set {
228-
mask = value.ToRuneList ();
238+
pattern = value.ToRuneList ();
229239
CompileMask ();
230240
SetupText ();
231241
}
@@ -242,6 +252,9 @@ public ustring Text {
242252
}
243253
}
244254

255+
///<inheritdoc/>
256+
public ustring DisplayText => Text;
257+
245258
///<inheritdoc/>
246259
public bool IsValid {
247260
get {
@@ -257,6 +270,7 @@ public bool IsValid {
257270
/// </summary>
258271
public bool ValidateOnInput { get; set; } = true;
259272

273+
260274
bool Validate (List<Rune> text)
261275
{
262276
var match = regex.Match (ustring.Make (text).ToString ());
@@ -340,7 +354,7 @@ void SetupText ()
340354
/// </summary>
341355
private void CompileMask ()
342356
{
343-
regex = new Regex (ustring.Make (mask).ToString (), RegexOptions.Compiled);
357+
regex = new Regex (ustring.Make (pattern).ToString (), RegexOptions.Compiled);
344358
}
345359
}
346360
#endregion
@@ -349,58 +363,66 @@ private void CompileMask ()
349363
/// <summary>
350364
/// Text field that validates input through a <see cref="ITextValidateProvider"/>
351365
/// </summary>
352-
/// <typeparam name="T"></typeparam>
353-
public class TextValidateField<T> : View, ITextValidateProvider where T : class {
366+
public class TextValidateField : View {
354367

355368
ITextValidateProvider provider;
356369
int cursorPosition = 0;
357370

358371
/// <summary>
359-
/// Initializes a new instance of the <see cref="TextValidateField{T}"/> class using <see cref="LayoutStyle.Computed"/> positioning.
372+
/// Initializes a new instance of the <see cref="TextValidateField"/> class using <see cref="LayoutStyle.Computed"/> positioning.
360373
/// </summary>
361-
public TextValidateField ()
374+
public TextValidateField () : this (null)
362375
{
363376
}
364377

365378
/// <summary>
366-
/// Initializes a new instance of the <see cref="TextValidateField{T}"></see> class using <see cref="LayoutStyle.Computed"/> positioning.
379+
/// Initializes a new instance of the <see cref="TextValidateField"/> class using <see cref="LayoutStyle.Computed"/> positioning.
367380
/// </summary>
368-
/// <param name="mask">Mask</param>
369-
public TextValidateField (ustring mask) : this (mask, ustring.Empty) { }
370-
371-
/// <summary>
372-
/// Initializes a new instance of the <see cref="TextValidateField{T}"/> class using <see cref="LayoutStyle.Computed"/> positioning.
373-
/// </summary>
374-
/// <param name="mask"></param>
375-
/// <param name="text">Initial Value</param>
376-
public TextValidateField (ustring mask, ustring text)
381+
public TextValidateField (ITextValidateProvider provider)
377382
{
378-
provider = Activator.CreateInstance (typeof (T)) as ITextValidateProvider;
383+
if (provider != null) {
384+
Provider = provider;
385+
}
379386

380-
Mask = mask;
381-
Text = text;
387+
Initialize ();
388+
}
382389

383-
this.Width = text == ustring.Empty ? 20 : Text.Length;
384-
this.Height = 1;
385-
this.CanFocus = true;
390+
void Initialize ()
391+
{
392+
Height = 1;
393+
CanFocus = true;
386394
}
387395

388396
/// <summary>
389-
/// Get the Provider
397+
/// Provider
390398
/// </summary>
391-
public T Provider => (T)provider;
399+
public ITextValidateProvider Provider {
400+
get => provider;
401+
set {
402+
provider = value;
403+
if (provider.Fixed == true) {
404+
this.Width = provider.DisplayText == ustring.Empty ? 10 : Text.Length;
405+
}
406+
HomeKeyHandler ();
407+
SetNeedsDisplay ();
408+
}
409+
}
392410

393411
///<inheritdoc/>
394412
public override bool MouseEvent (MouseEvent mouseEvent)
395413
{
396-
var c = provider.Cursor (mouseEvent.X - GetMargins (Frame.Width).left);
397-
if (provider.Fixed == false && TextAlignment == TextAlignment.Right && Text.Length > 0) {
398-
c += 1;
414+
if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)) {
415+
416+
var c = provider.Cursor (mouseEvent.X - GetMargins (Frame.Width).left);
417+
if (provider.Fixed == false && TextAlignment == TextAlignment.Right && Text.Length > 0) {
418+
c += 1;
419+
}
420+
cursorPosition = c;
421+
SetFocus ();
422+
SetNeedsDisplay ();
423+
return true;
399424
}
400-
cursorPosition = c;
401-
SetFocus ();
402-
SetNeedsDisplay ();
403-
return true;
425+
return false;
404426
}
405427

406428
/// <summary>
@@ -424,22 +446,6 @@ public override bool MouseEvent (MouseEvent mouseEvent)
424446
}
425447
}
426448

427-
/// <summary>
428-
/// Mask
429-
/// </summary>
430-
public ustring Mask {
431-
get {
432-
return provider.Mask;
433-
}
434-
set {
435-
provider.Mask = value;
436-
437-
cursorPosition = provider.CursorStart ();
438-
439-
SetNeedsDisplay ();
440-
}
441-
}
442-
443449
///inheritdoc/>
444450
public override void PositionCursor ()
445451
{
@@ -501,8 +507,8 @@ public override void Redraw (Rect bounds)
501507
// Content
502508
Driver.SetAttribute (textColor);
503509
// Content
504-
for (int i = 0; i < provider.Text.Length; i++) {
505-
Driver.AddRune (provider.Text [i]);
510+
for (int i = 0; i < provider.DisplayText.Length; i++) {
511+
Driver.AddRune (provider.DisplayText [i]);
506512
}
507513

508514
// Right Margin
@@ -615,75 +621,6 @@ public override bool ProcessKey (KeyEvent kb)
615621
return true;
616622
}
617623

618-
/// <summary>
619-
/// Set Cursor position to <paramref name="pos" />.
620-
/// </summary>
621-
/// <param name="pos"></param>
622-
/// <returns>Return first valid position.</returns>
623-
public int Cursor (int pos)
624-
{
625-
return provider.Cursor (pos);
626-
}
627-
628-
/// <summary>
629-
/// First valid position before <paramref name="pos" />.
630-
/// </summary>
631-
/// <param name="pos"></param>
632-
/// <returns>New cursor position if any, otherwise returns <paramref name="pos" /></returns>
633-
public int CursorLeft (int pos)
634-
{
635-
return provider.CursorLeft (pos);
636-
}
637-
638-
/// <summary>
639-
/// First valid position after <paramref name="pos" />.
640-
/// </summary>
641-
/// <param name="pos">Current position.</param>
642-
/// <returns>New cursor position if any, otherwise returns <paramref name="pos" /></returns>
643-
public int CursorRight (int pos)
644-
{
645-
return provider.CursorRight (pos);
646-
}
647-
648-
/// <summary>
649-
/// Find the first valid character position.
650-
/// </summary>
651-
/// <returns>New cursor position.</returns>
652-
public int CursorStart ()
653-
{
654-
return provider.CursorStart ();
655-
}
656-
657-
/// <summary>
658-
/// Find the last valid character position.
659-
/// </summary>
660-
/// <returns>New cursor position.</returns>
661-
public int CursorEnd ()
662-
{
663-
return provider.CursorEnd ();
664-
}
665-
666-
/// <summary>
667-
/// Deletes the current character in <paramref name="pos" />.
668-
/// </summary>
669-
/// <param name="pos"></param>
670-
/// <returns>true if the character was successfully removed, otherwise false.</returns>
671-
public bool Delete (int pos)
672-
{
673-
return provider.Delete (pos);
674-
}
675-
676-
/// <summary>
677-
/// Insert character <paramref name="ch" /> in position <paramref name="pos" />.
678-
/// </summary>
679-
/// <param name="ch"></param>
680-
/// <param name="pos"></param>
681-
/// <returns>true if the character was successfully inserted, otherwise false.</returns>
682-
public bool InsertAt (char ch, int pos)
683-
{
684-
return provider.InsertAt (ch, pos);
685-
}
686-
687624
/// <summary>
688625
/// This property returns true if the input is valid.
689626
/// </summary>
@@ -696,7 +633,5 @@ public virtual bool IsValid {
696633
return provider.IsValid;
697634
}
698635
}
699-
700-
public bool Fixed => throw new NotImplementedException ();
701636
}
702637
}

UICatalog/Scenarios/Text.cs

+13-13
Original file line numberDiff line numberDiff line change
@@ -112,35 +112,35 @@ public override void Setup ()
112112
_timeField.TimeChanged += TimeChanged;
113113

114114
// MaskedTextProvider
115-
var netProvider = new Label (".Net MaskedTextProvider [ 999 000 LLL >LLL| AAA aaa ]") {
115+
var netProviderLabel = new Label (".Net MaskedTextProvider [ 999 000 LLL >LLL| AAA aaa ]") {
116116
X = Pos.Left (dateField),
117117
Y = Pos.Bottom (dateField) + 1
118118
};
119-
Win.Add (netProvider);
119+
Win.Add (netProviderLabel);
120120

121-
var netProviderField = new TextValidateField<NetMaskedTextProvider> ("999 000 LLL >LLL| AAA aaa") {
122-
X = Pos.Right (netProvider) + 1,
123-
Y = Pos.Y (netProvider),
124-
Width = 40,
125-
TextAlignment = TextAlignment.Centered
121+
var netProvider = new NetMaskedTextProvider ("999 000 LLL > LLL | AAA aaa");
122+
123+
var netProviderField = new TextValidateField (netProvider) {
124+
X = Pos.Right (netProviderLabel) + 1,
125+
Y = Pos.Y (netProviderLabel)
126126
};
127+
127128
Win.Add (netProviderField);
128129

129130
// TextRegexProvider
130131
var regexProvider = new Label ("Gui.cs TextRegexProvider [ ^([0-9]?[0-9]?[0-9]|1000)$ ]") {
131-
X = Pos.Left (netProvider),
132-
Y = Pos.Bottom (netProvider) + 1
132+
X = Pos.Left (netProviderLabel),
133+
Y = Pos.Bottom (netProviderLabel) + 1
133134
};
134135
Win.Add (regexProvider);
135136

136-
var regexProviderField = new TextValidateField<TextRegexProvider> ("^([0-9]?[0-9]?[0-9]|1000)$") {
137+
var provider2 = new TextRegexProvider ("^([0-9]?[0-9]?[0-9]|1000)$") { ValidateOnInput = false };
138+
var regexProviderField = new TextValidateField (provider2) {
137139
X = Pos.Right (regexProvider) + 1,
138140
Y = Pos.Y (regexProvider),
139-
Width = 40,
141+
Width = 30,
140142
TextAlignment = TextAlignment.Centered
141143
};
142-
// Access the inner Provider to configure.
143-
regexProviderField.Provider.ValidateOnInput = false;
144144

145145
Win.Add (regexProviderField);
146146
}

0 commit comments

Comments
 (0)