TextEffectsScenario.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. using System.Collections.Generic;
  2. using Terminal.Gui;
  3. namespace UICatalog.Scenarios;
  4. [ScenarioMetadata ("Text Effects", "Text Effects.")]
  5. [ScenarioCategory ("Colors")]
  6. [ScenarioCategory ("Text and Formatting")]
  7. public class TextEffectsScenario : Scenario
  8. {
  9. private TabView _tabView;
  10. /// <summary>
  11. /// Enable or disable looping of the gradient colors.
  12. /// </summary>
  13. public static bool LoopingGradient;
  14. public override void Main ()
  15. {
  16. Application.Init ();
  17. var w = new Window
  18. {
  19. Width = Dim.Fill (),
  20. Height = Dim.Fill (),
  21. Title = "Text Effects Scenario"
  22. };
  23. w.Loaded += (s, e) => { SetupGradientLineCanvas (w, w.Frame.Size); };
  24. w.SizeChanging += (s, e) =>
  25. {
  26. if (e.Size.HasValue)
  27. {
  28. SetupGradientLineCanvas (w, e.Size.Value);
  29. }
  30. };
  31. w.ColorScheme = new ()
  32. {
  33. Normal = new (ColorName16.White, ColorName16.Black),
  34. Focus = new (ColorName16.Black, ColorName16.White),
  35. HotNormal = new (ColorName16.White, ColorName16.Black),
  36. HotFocus = new (ColorName16.White, ColorName16.Black),
  37. Disabled = new (ColorName16.Gray, ColorName16.Black)
  38. };
  39. // Creates a window that occupies the entire terminal with a title.
  40. _tabView = new ()
  41. {
  42. Width = Dim.Fill (),
  43. Height = Dim.Fill ()
  44. };
  45. var gradientsView = new GradientsView
  46. {
  47. Width = Dim.Fill (),
  48. Height = Dim.Fill ()
  49. };
  50. var t1 = new Tab
  51. {
  52. View = gradientsView,
  53. DisplayText = "Gradients"
  54. };
  55. var cbLooping = new CheckBox
  56. {
  57. Text = "Looping",
  58. Y = Pos.AnchorEnd (1)
  59. };
  60. cbLooping.CheckedStateChanging += (s, e) =>
  61. {
  62. LoopingGradient = e.NewValue == CheckState.Checked;
  63. SetupGradientLineCanvas (w, w.Frame.Size);
  64. _tabView.SetNeedsDisplay ();
  65. };
  66. gradientsView.Add (cbLooping);
  67. _tabView.AddTab (t1, false);
  68. w.Add (_tabView);
  69. Application.Run (w);
  70. w.Dispose ();
  71. Application.Shutdown ();
  72. Dispose ();
  73. }
  74. private static void SetupGradientLineCanvas (View w, Size size)
  75. {
  76. GetAppealingGradientColors (out List<Color> stops, out List<int> steps);
  77. var g = new Gradient (stops, steps, LoopingGradient);
  78. var fore = new GradientFill (
  79. new (0, 0, size.Width, size.Height),
  80. g,
  81. GradientDirection.Diagonal);
  82. var back = new SolidFill (new (ColorName16.Black));
  83. w.LineCanvas.Fill = new (
  84. fore,
  85. back);
  86. }
  87. public static void GetAppealingGradientColors (out List<Color> stops, out List<int> steps)
  88. {
  89. // Define the colors of the gradient stops with more appealing colors
  90. stops =
  91. [
  92. new (0, 128, 255), // Bright Blue
  93. new (0, 255, 128), // Bright Green
  94. new (255, 255), // Bright Yellow
  95. new (255, 128), // Bright Orange
  96. new (255, 0, 128)
  97. ];
  98. // Define the number of steps between each color for smoother transitions
  99. // If we pass only a single value then it will assume equal steps between all pairs
  100. steps = [15];
  101. }
  102. }
  103. internal class GradientsView : View
  104. {
  105. private const int GRADIENT_WIDTH = 30;
  106. private const int GRADIENT_HEIGHT = 15;
  107. private const int LABEL_HEIGHT = 1;
  108. private const int GRADIENT_WITH_LABEL_HEIGHT = GRADIENT_HEIGHT + LABEL_HEIGHT + 1; // +1 for spacing
  109. protected override bool OnDrawingContent (Rectangle viewport)
  110. {
  111. DrawTopLineGradient (viewport);
  112. var x = 2;
  113. var y = 3;
  114. List<(string Label, GradientDirection Direction)> gradients = new ()
  115. {
  116. ("Horizontal", GradientDirection.Horizontal),
  117. ("Vertical", GradientDirection.Vertical),
  118. ("Radial", GradientDirection.Radial),
  119. ("Diagonal", GradientDirection.Diagonal)
  120. };
  121. foreach ((string label, GradientDirection direction) in gradients)
  122. {
  123. if (x + GRADIENT_WIDTH > viewport.Width)
  124. {
  125. x = 2; // Reset to left margin
  126. y += GRADIENT_WITH_LABEL_HEIGHT; // Move down to next row
  127. }
  128. DrawLabeledGradientArea (label, direction, x, y);
  129. x += GRADIENT_WIDTH + 2; // Move right for next gradient, +2 for spacing
  130. }
  131. return true;
  132. }
  133. private void DrawLabeledGradientArea (string label, GradientDirection direction, int xOffset, int yOffset)
  134. {
  135. DrawGradientArea (direction, xOffset, yOffset);
  136. CenterText (label, xOffset, yOffset + GRADIENT_HEIGHT); // Adjusted for text below the gradient
  137. }
  138. private void CenterText (string text, int xOffset, int yOffset)
  139. {
  140. if (yOffset + 1 >= Viewport.Height)
  141. {
  142. // Not enough space for label
  143. return;
  144. }
  145. int width = text.Length;
  146. int x = xOffset + (GRADIENT_WIDTH - width) / 2; // Center the text within the gradient area width
  147. SetAttribute (GetNormalColor ());
  148. Move (x, yOffset + 1);
  149. Driver.AddStr (text);
  150. }
  151. private void DrawGradientArea (GradientDirection direction, int xOffset, int yOffset)
  152. {
  153. // Define the colors of the gradient stops
  154. List<Color> stops =
  155. [
  156. new (255, 0), // Red
  157. new (0, 255), // Green
  158. new (238, 130, 238)
  159. ];
  160. // Define the number of steps between each color
  161. List<int> steps = [10, 10]; // 10 steps between Red -> Green, and Green -> Blue
  162. // Create the gradient
  163. var radialGradient = new Gradient (stops, steps, TextEffectsScenario.LoopingGradient);
  164. // Define the size of the rectangle
  165. int maxRow = GRADIENT_HEIGHT; // Adjusted to keep aspect ratio
  166. int maxColumn = GRADIENT_WIDTH;
  167. // Build the coordinate-color mapping for a radial gradient
  168. Dictionary<Point, Color> gradientMapping = radialGradient.BuildCoordinateColorMapping (maxRow, maxColumn, direction);
  169. // Print the gradient
  170. for (var row = 0; row <= maxRow; row++)
  171. {
  172. for (var col = 0; col <= maxColumn; col++)
  173. {
  174. var coord = new Point (col, row);
  175. Color color = gradientMapping [coord];
  176. SetColor (color);
  177. AddRune (col + xOffset, row + yOffset, new ('█'));
  178. }
  179. }
  180. }
  181. private void DrawTopLineGradient (Rectangle viewport)
  182. {
  183. // Define the colors of the rainbow
  184. List<Color> stops =
  185. [
  186. new (255, 0), // Red
  187. new (255, 165), // Orange
  188. new (255, 255), // Yellow
  189. new (0, 128), // Green
  190. new (0, 0, 255), // Blue
  191. new (75, 0, 130), // Indigo
  192. new (238, 130, 238)
  193. ];
  194. // Define the number of steps between each color
  195. List<int> steps =
  196. [
  197. 20, // between Red and Orange
  198. 20, // between Orange and Yellow
  199. 20, // between Yellow and Green
  200. 20, // between Green and Blue
  201. 20, // between Blue and Indigo
  202. 20
  203. ];
  204. // Create the gradient
  205. var rainbowGradient = new Gradient (stops, steps, TextEffectsScenario.LoopingGradient);
  206. for (var x = 0; x < viewport.Width; x++)
  207. {
  208. double fraction = (double)x / (viewport.Width - 1);
  209. Color color = rainbowGradient.GetColorAtFraction (fraction);
  210. SetColor (color);
  211. AddRune (x, 0, new ('█'));
  212. }
  213. }
  214. private void SetColor (Color color) { SetAttribute (new (color, color)); }
  215. }