2
0

ColorPicker.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. using System;
  2. using NStack;
  3. namespace Terminal.Gui {
  4. /// <summary>
  5. /// The <see cref="ColorPicker"/> <see cref="View"/> Color picker.
  6. /// </summary>
  7. public class ColorPicker : View {
  8. /// <summary>
  9. /// Number of colors on a line.
  10. /// </summary>
  11. private static readonly int colorsPerLine = 8;
  12. /// <summary>
  13. /// Number of color lines.
  14. /// </summary>
  15. private static readonly int lineCount = 2;
  16. /// <summary>
  17. /// Horizontal zoom.
  18. /// </summary>
  19. private static readonly int horizontalZoom = 4;
  20. /// <summary>
  21. /// Vertical zoom.
  22. /// </summary>
  23. private static readonly int verticalZoom = 2;
  24. // Cursor runes.
  25. private static readonly Rune [] cursorRunes = new Rune []
  26. {
  27. 0x250C, 0x2500, 0x2500, 0x2510,
  28. 0x2514, 0x2500, 0x2500, 0x2518
  29. };
  30. /// <summary>
  31. /// Cursor for the selected color.
  32. /// </summary>
  33. public Point Cursor {
  34. get {
  35. return new Point (selectColorIndex % colorsPerLine, selectColorIndex / colorsPerLine);
  36. }
  37. set {
  38. var colorIndex = value.Y * colorsPerLine + value.X;
  39. SelectedColor = (Color)colorIndex;
  40. }
  41. }
  42. /// <summary>
  43. /// Fired when a color is picked.
  44. /// </summary>
  45. public event Action ColorChanged;
  46. private int selectColorIndex = (int)Color.Black;
  47. /// <summary>
  48. /// Selected color.
  49. /// </summary>
  50. public Color SelectedColor {
  51. get {
  52. return (Color)selectColorIndex;
  53. }
  54. set {
  55. selectColorIndex = (int)value;
  56. ColorChanged?.Invoke ();
  57. SetNeedsDisplay ();
  58. }
  59. }
  60. /// <summary>
  61. /// Initializes a new instance of <see cref="ColorPicker"/>.
  62. /// </summary>
  63. public ColorPicker () : base ("Color Picker")
  64. {
  65. Initialize ();
  66. }
  67. /// <summary>
  68. /// Initializes a new instance of <see cref="ColorPicker"/>.
  69. /// </summary>
  70. /// <param name="title">Title.</param>
  71. public ColorPicker (ustring title) : base (title)
  72. {
  73. Initialize ();
  74. }
  75. /// <summary>
  76. /// Initializes a new instance of <see cref="ColorPicker"/>.
  77. /// </summary>
  78. /// <param name="point">Location point.</param>
  79. /// <param name="title">Title.</param>
  80. public ColorPicker (Point point, ustring title) : this (point.X, point.Y, title)
  81. {
  82. }
  83. /// <summary>
  84. /// Initializes a new instance of <see cref="ColorPicker"/>.
  85. /// </summary>
  86. /// <param name="x">X location.</param>
  87. /// <param name="y">Y location.</param>
  88. /// <param name="title">Title</param>
  89. public ColorPicker (int x, int y, ustring title) : base (x, y, title)
  90. {
  91. Initialize ();
  92. }
  93. private void Initialize()
  94. {
  95. CanFocus = true;
  96. Width = colorsPerLine * horizontalZoom;
  97. Height = lineCount * verticalZoom + 1;
  98. AddCommands ();
  99. AddKeyBindings ();
  100. }
  101. /// <summary>
  102. /// Add the commands.
  103. /// </summary>
  104. private void AddCommands ()
  105. {
  106. AddCommand (Command.Left, () => MoveLeft ());
  107. AddCommand (Command.Right, () => MoveRight ());
  108. AddCommand (Command.LineUp, () => MoveUp ());
  109. AddCommand (Command.LineDown, () => MoveDown ());
  110. }
  111. /// <summary>
  112. /// Add the KeyBindinds.
  113. /// </summary>
  114. private void AddKeyBindings ()
  115. {
  116. AddKeyBinding (Key.CursorLeft, Command.Left);
  117. AddKeyBinding (Key.CursorRight, Command.Right);
  118. AddKeyBinding (Key.CursorUp, Command.LineUp);
  119. AddKeyBinding (Key.CursorDown, Command.LineDown);
  120. }
  121. ///<inheritdoc/>
  122. public override void Redraw (Rect bounds)
  123. {
  124. base.Redraw (bounds);
  125. Driver.SetAttribute (HasFocus ? ColorScheme.Focus : GetNormalColor ());
  126. var colorIndex = 0;
  127. for (var y = 0; y < (Height.Anchor (0) - 1) / verticalZoom; y++) {
  128. for (var x = 0; x < Width.Anchor (0) / horizontalZoom; x++) {
  129. var foregroundColorIndex = y == 0 ? colorIndex + colorsPerLine : colorIndex - colorsPerLine;
  130. Driver.SetAttribute (Driver.MakeAttribute ((Color)foregroundColorIndex, (Color)colorIndex));
  131. var selected = x == Cursor.X && y == Cursor.Y;
  132. DrawColorBox (x, y, selected);
  133. colorIndex++;
  134. }
  135. }
  136. }
  137. /// <summary>
  138. /// Draw a box for one color.
  139. /// </summary>
  140. /// <param name="x">X location.</param>
  141. /// <param name="y">Y location</param>
  142. /// <param name="selected"></param>
  143. private void DrawColorBox (int x, int y, bool selected)
  144. {
  145. var index = 0;
  146. for (var zommedY = 0; zommedY < verticalZoom; zommedY++) {
  147. for (var zommedX = 0; zommedX < horizontalZoom; zommedX++) {
  148. Move (x * horizontalZoom + zommedX, y * verticalZoom + zommedY + 1);
  149. if (selected) {
  150. var character = cursorRunes [index];
  151. Driver.AddRune (character);
  152. } else {
  153. Driver.AddRune (' ');
  154. }
  155. index++;
  156. }
  157. }
  158. }
  159. /// <summary>
  160. /// Moves the selected item index to the previous column.
  161. /// </summary>
  162. /// <returns></returns>
  163. public virtual bool MoveLeft ()
  164. {
  165. if (Cursor.X > 0) SelectedColor--;
  166. return true;
  167. }
  168. /// <summary>
  169. /// Moves the selected item index to the next column.
  170. /// </summary>
  171. /// <returns></returns>
  172. public virtual bool MoveRight ()
  173. {
  174. if (Cursor.X < colorsPerLine - 1) SelectedColor++;
  175. return true;
  176. }
  177. /// <summary>
  178. /// Moves the selected item index to the previous row.
  179. /// </summary>
  180. /// <returns></returns>
  181. public virtual bool MoveUp ()
  182. {
  183. if (Cursor.Y > 0) SelectedColor -= colorsPerLine;
  184. return true;
  185. }
  186. /// <summary>
  187. /// Moves the selected item index to the next row.
  188. /// </summary>
  189. /// <returns></returns>
  190. public virtual bool MoveDown ()
  191. {
  192. if (Cursor.Y < lineCount - 1) SelectedColor += colorsPerLine;
  193. return true;
  194. }
  195. ///<inheritdoc/>
  196. public override bool ProcessKey (KeyEvent kb)
  197. {
  198. var result = InvokeKeybindings (kb);
  199. if (result != null)
  200. return (bool)result;
  201. return false;
  202. }
  203. ///<inheritdoc/>
  204. public override bool MouseEvent (MouseEvent me)
  205. {
  206. if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) || !CanFocus)
  207. return false;
  208. SetFocus ();
  209. Cursor = new Point (me.X / horizontalZoom, (me.Y - 1) / verticalZoom);
  210. return true;
  211. }
  212. }
  213. }