TimeField.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. //
  2. // TimeField.cs: text entry for time
  3. //
  4. // Author: Jörg Preiß
  5. //
  6. // Licensed under the MIT license
  7. //
  8. using System;
  9. using System.Globalization;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using NStack;
  13. namespace Terminal.Gui {
  14. /// <summary>
  15. /// Time edit widget
  16. /// </summary>
  17. /// <remarks>
  18. /// This widget provides time editing functionality, and mouse support.
  19. /// </remarks>
  20. public class TimeField : TextField {
  21. bool isShort;
  22. int longFieldLen = 8;
  23. int shortFieldLen = 5;
  24. int FieldLen { get { return isShort ? shortFieldLen : longFieldLen; } }
  25. string longFormat = " hh:mm:ss";
  26. string shortFormat = " hh:mm";
  27. string Format { get { return isShort ? shortFormat : longFormat; } }
  28. /// <summary>
  29. /// Public constructor that creates a time edit field at an absolute position and fixed size.
  30. /// </summary>
  31. /// <param name="x">The x coordinate.</param>
  32. /// <param name="y">The y coordinate.</param>
  33. /// <param name="time">Initial time contents.</param>
  34. /// <param name="isShort">If true, the seconds are hidden.</param>
  35. public TimeField (int x, int y, DateTime time, bool isShort = false) : base (x, y, isShort ? 7 : 10, "")
  36. {
  37. this.isShort = isShort;
  38. CursorPosition = 1;
  39. Time = time;
  40. }
  41. /// <summary>
  42. /// Gets or sets the time in the widget.
  43. /// </summary>
  44. /// <remarks>
  45. /// </remarks>
  46. public DateTime Time {
  47. get {
  48. if (!DateTime.TryParseExact (Text.ToString (), Format, CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime result)) return new DateTime ();
  49. return result;
  50. }
  51. set {
  52. this.Text = value.ToString (Format);
  53. }
  54. }
  55. bool SetText (Rune key)
  56. {
  57. var text = TextModel.ToRunes (Text);
  58. var newText = text.GetRange (0, CursorPosition);
  59. newText.Add (key);
  60. if (CursorPosition < FieldLen)
  61. newText = newText.Concat (text.GetRange (CursorPosition + 1, text.Count - (CursorPosition + 1))).ToList ();
  62. return SetText (ustring.Make (newText));
  63. }
  64. bool SetText (ustring text)
  65. {
  66. if (!DateTime.TryParseExact (text.ToString (), Format, CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime result))
  67. return false;
  68. Text = text;
  69. return true;
  70. }
  71. void IncCursorPosition ()
  72. {
  73. if (CursorPosition == FieldLen)
  74. return;
  75. if (Text [++CursorPosition] == ':')
  76. CursorPosition++;
  77. }
  78. void DecCursorPosition ()
  79. {
  80. if (CursorPosition == 1)
  81. return;
  82. if (Text [--CursorPosition] == ':')
  83. CursorPosition--;
  84. }
  85. void AdjCursorPosition ()
  86. {
  87. if (Text [CursorPosition] == ':')
  88. CursorPosition++;
  89. }
  90. public override bool ProcessKey (KeyEvent kb)
  91. {
  92. switch (kb.Key) {
  93. case Key.DeleteChar:
  94. case Key.ControlD:
  95. SetText ('0');
  96. break;
  97. case Key.Delete:
  98. case Key.Backspace:
  99. SetText ('0');
  100. DecCursorPosition ();
  101. break;
  102. // Home, C-A
  103. case Key.Home:
  104. case Key.ControlA:
  105. CursorPosition = 1;
  106. break;
  107. case Key.CursorLeft:
  108. case Key.ControlB:
  109. DecCursorPosition ();
  110. break;
  111. case Key.End:
  112. case Key.ControlE: // End
  113. CursorPosition = FieldLen;
  114. break;
  115. case Key.CursorRight:
  116. case Key.ControlF:
  117. IncCursorPosition ();
  118. break;
  119. default:
  120. // Ignore non-numeric characters.
  121. if (kb.Key < (Key)((int)'0') || kb.Key > (Key)((int)'9'))
  122. return false;
  123. if (SetText (TextModel.ToRunes (ustring.Make ((uint)kb.Key)).First ()))
  124. IncCursorPosition ();
  125. return true;
  126. }
  127. return true;
  128. }
  129. public override bool MouseEvent (MouseEvent ev)
  130. {
  131. if (!ev.Flags.HasFlag (MouseFlags.Button1Clicked))
  132. return false;
  133. if (!HasFocus)
  134. SuperView.SetFocus (this);
  135. var point = ev.X;
  136. if (point > FieldLen)
  137. point = FieldLen;
  138. if (point < 1)
  139. point = 1;
  140. CursorPosition = point;
  141. AdjCursorPosition ();
  142. return true;
  143. }
  144. }
  145. }