TextAlignmentsAndDirection.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Terminal.Gui;
  6. namespace UICatalog.Scenarios;
  7. [ScenarioMetadata ("Text Alignment and Direction", "Demos horizontal and vertical text alignment and text direction.")]
  8. [ScenarioCategory ("Text and Formatting")]
  9. public class TextAlignmentsAndDirections : Scenario
  10. {
  11. public override void Main ()
  12. {
  13. Application.Init ();
  14. Window app = new ()
  15. {
  16. Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
  17. };
  18. // string txt = ".\n...\n.....\nHELLO\n.....\n...\n.";
  19. // string txt = "┌──┴──┐\n┤HELLO├\n└──┬──┘";
  20. var txt = "HELLO WORLD";
  21. var color1 = new ColorScheme { Normal = new (Color.Black, Color.Gray) };
  22. var color2 = new ColorScheme { Normal = new (Color.Black, Color.DarkGray) };
  23. List<Label> txts = new (); // single line
  24. List<Label> mtxts = new (); // multi line
  25. // Horizontal Single-Line
  26. var labelHL = new Label
  27. {
  28. X = 1,
  29. Y = 1,
  30. Width = 9,
  31. Height = 1,
  32. TextAlignment = TextAlignment.Right,
  33. ColorScheme = Colors.ColorSchemes ["Dialog"],
  34. Text = "Left"
  35. };
  36. var labelHC = new Label
  37. {
  38. X = 1,
  39. Y = 2,
  40. Width = 9,
  41. Height = 1,
  42. TextAlignment = TextAlignment.Right,
  43. ColorScheme = Colors.ColorSchemes ["Dialog"],
  44. Text = "Centered"
  45. };
  46. var labelHR = new Label
  47. {
  48. X = 1,
  49. Y = 3,
  50. Width = 9,
  51. Height = 1,
  52. TextAlignment = TextAlignment.Right,
  53. ColorScheme = Colors.ColorSchemes ["Dialog"],
  54. Text = "Right"
  55. };
  56. var labelHJ = new Label
  57. {
  58. X = 1,
  59. Y = 4,
  60. Width = 9,
  61. Height = 1,
  62. TextAlignment = TextAlignment.Right,
  63. ColorScheme = Colors.ColorSchemes ["Dialog"],
  64. Text = "Justified"
  65. };
  66. var txtLabelHL = new Label
  67. {
  68. X = Pos.Right (labelHL) + 1,
  69. Y = Pos.Y (labelHL),
  70. Width = Dim.Fill (1) - 9,
  71. Height = 1,
  72. ColorScheme = color1,
  73. TextAlignment = TextAlignment.Left,
  74. Text = txt
  75. };
  76. var txtLabelHC = new Label
  77. {
  78. X = Pos.Right (labelHC) + 1,
  79. Y = Pos.Y (labelHC),
  80. Width = Dim.Fill (1) - 9,
  81. Height = 1,
  82. ColorScheme = color2,
  83. TextAlignment = TextAlignment.Centered,
  84. Text = txt
  85. };
  86. var txtLabelHR = new Label
  87. {
  88. X = Pos.Right (labelHR) + 1,
  89. Y = Pos.Y (labelHR),
  90. Width = Dim.Fill (1) - 9,
  91. Height = 1,
  92. ColorScheme = color1,
  93. TextAlignment = TextAlignment.Right,
  94. Text = txt
  95. };
  96. var txtLabelHJ = new Label
  97. {
  98. X = Pos.Right (labelHJ) + 1,
  99. Y = Pos.Y (labelHJ),
  100. Width = Dim.Fill (1) - 9,
  101. Height = 1,
  102. ColorScheme = color2,
  103. TextAlignment = TextAlignment.Justified,
  104. Text = txt
  105. };
  106. txts.Add (txtLabelHL);
  107. txts.Add (txtLabelHC);
  108. txts.Add (txtLabelHR);
  109. txts.Add (txtLabelHJ);
  110. app.Add (labelHL);
  111. app.Add (txtLabelHL);
  112. app.Add (labelHC);
  113. app.Add (txtLabelHC);
  114. app.Add (labelHR);
  115. app.Add (txtLabelHR);
  116. app.Add (labelHJ);
  117. app.Add (txtLabelHJ);
  118. // Vertical Single-Line
  119. var labelVT = new Label
  120. {
  121. X = Pos.AnchorEnd (8),
  122. Y = 1,
  123. Width = 2,
  124. Height = 9,
  125. ColorScheme = color1,
  126. TextDirection = TextDirection.TopBottom_LeftRight,
  127. VerticalTextAlignment = VerticalTextAlignment.Bottom,
  128. Text = "Top"
  129. };
  130. labelVT.TextFormatter.WordWrap = false;
  131. var labelVM = new Label
  132. {
  133. X = Pos.AnchorEnd (6),
  134. Y = 1,
  135. Width = 2,
  136. Height = 9,
  137. ColorScheme = color1,
  138. TextDirection = TextDirection.TopBottom_LeftRight,
  139. VerticalTextAlignment = VerticalTextAlignment.Bottom,
  140. Text = "Middle"
  141. };
  142. labelVM.TextFormatter.WordWrap = false;
  143. var labelVB = new Label
  144. {
  145. X = Pos.AnchorEnd (4),
  146. Y = 1,
  147. Height = 9,
  148. ColorScheme = color1,
  149. TextDirection = TextDirection.TopBottom_LeftRight,
  150. VerticalTextAlignment = VerticalTextAlignment.Bottom,
  151. Text = "Bottom"
  152. };
  153. labelVB.TextFormatter.WordWrap = false;
  154. var labelVJ = new Label
  155. {
  156. X = Pos.AnchorEnd (2),
  157. Y = 1,
  158. Width = 2,
  159. Height = 9,
  160. ColorScheme = color1,
  161. TextDirection = TextDirection.TopBottom_LeftRight,
  162. VerticalTextAlignment = VerticalTextAlignment.Bottom,
  163. Text = "Justified"
  164. };
  165. labelVJ.TextFormatter.WordWrap = false;
  166. var txtLabelVT = new Label
  167. {
  168. X = Pos.X (labelVT),
  169. Y = Pos.Bottom (labelVT) + 1,
  170. Width = 2,
  171. Height = Dim.Fill (1),
  172. ColorScheme = color1,
  173. TextDirection = TextDirection.TopBottom_LeftRight,
  174. VerticalTextAlignment = VerticalTextAlignment.Top,
  175. Text = txt
  176. };
  177. txtLabelVT.TextFormatter.WordWrap = false;
  178. var txtLabelVM = new Label
  179. {
  180. X = Pos.X (labelVM),
  181. Y = Pos.Bottom (labelVM) + 1,
  182. Width = 2,
  183. Height = Dim.Fill (1),
  184. ColorScheme = color2,
  185. TextDirection = TextDirection.TopBottom_LeftRight,
  186. VerticalTextAlignment = VerticalTextAlignment.Middle,
  187. Text = txt
  188. };
  189. txtLabelVM.TextFormatter.WordWrap = false;
  190. var txtLabelVB = new Label
  191. {
  192. X = Pos.X (labelVB),
  193. Y = Pos.Bottom (labelVB) + 1,
  194. Width = 2,
  195. Height = Dim.Fill (1),
  196. ColorScheme = color1,
  197. TextDirection = TextDirection.TopBottom_LeftRight,
  198. VerticalTextAlignment = VerticalTextAlignment.Bottom,
  199. Text = txt
  200. };
  201. txtLabelVB.TextFormatter.WordWrap = false;
  202. var txtLabelVJ = new Label
  203. {
  204. X = Pos.X (labelVJ),
  205. Y = Pos.Bottom (labelVJ) + 1,
  206. Width = 2,
  207. Height = Dim.Fill (1),
  208. ColorScheme = color2,
  209. TextDirection = TextDirection.TopBottom_LeftRight,
  210. VerticalTextAlignment = VerticalTextAlignment.Justified,
  211. Text = txt
  212. };
  213. txtLabelVJ.TextFormatter.WordWrap = false;
  214. txts.Add (txtLabelVT);
  215. txts.Add (txtLabelVM);
  216. txts.Add (txtLabelVB);
  217. txts.Add (txtLabelVJ);
  218. app.Add (labelVT);
  219. app.Add (txtLabelVT);
  220. app.Add (labelVM);
  221. app.Add (txtLabelVM);
  222. app.Add (labelVB);
  223. app.Add (txtLabelVB);
  224. app.Add (labelVJ);
  225. app.Add (txtLabelVJ);
  226. // Multi-Line
  227. var container = new View
  228. {
  229. X = 0,
  230. Y = Pos.Bottom (txtLabelHJ),
  231. Width = Dim.Fill (31),
  232. Height = Dim.Fill (4),
  233. ColorScheme = color2
  234. };
  235. var txtLabelTL = new Label
  236. {
  237. X = 1 /* */,
  238. Y = 1,
  239. Width = Dim.Percent (100f / 3f),
  240. Height = Dim.Percent (100f / 3f),
  241. TextAlignment = TextAlignment.Left,
  242. VerticalTextAlignment = VerticalTextAlignment.Top,
  243. ColorScheme = color1,
  244. Text = txt
  245. };
  246. txtLabelTL.TextFormatter.MultiLine = true;
  247. var txtLabelTC = new Label
  248. {
  249. X = Pos.Right (txtLabelTL) + 2,
  250. Y = 1,
  251. Width = Dim.Percent (100f / 3f),
  252. Height = Dim.Percent (100f / 3f),
  253. TextAlignment = TextAlignment.Centered,
  254. VerticalTextAlignment = VerticalTextAlignment.Top,
  255. ColorScheme = color1,
  256. Text = txt
  257. };
  258. txtLabelTC.TextFormatter.MultiLine = true;
  259. var txtLabelTR = new Label
  260. {
  261. X = Pos.Right (txtLabelTC) + 2,
  262. Y = 1,
  263. Width = Dim.Percent (100f, true),
  264. Height = Dim.Percent (100f / 3f),
  265. TextAlignment = TextAlignment.Right,
  266. VerticalTextAlignment = VerticalTextAlignment.Top,
  267. ColorScheme = color1,
  268. Text = txt
  269. };
  270. txtLabelTR.TextFormatter.MultiLine = true;
  271. var txtLabelML = new Label
  272. {
  273. X = Pos.X (txtLabelTL),
  274. Y = Pos.Bottom (txtLabelTL) + 1,
  275. Width = Dim.Width (txtLabelTL),
  276. Height = Dim.Percent (100f / 3f),
  277. TextAlignment = TextAlignment.Left,
  278. VerticalTextAlignment = VerticalTextAlignment.Middle,
  279. ColorScheme = color1,
  280. Text = txt
  281. };
  282. txtLabelML.TextFormatter.MultiLine = true;
  283. var txtLabelMC = new Label
  284. {
  285. X = Pos.X (txtLabelTC),
  286. Y = Pos.Bottom (txtLabelTC) + 1,
  287. Width = Dim.Width (txtLabelTC),
  288. Height = Dim.Percent (100f / 3f),
  289. TextAlignment = TextAlignment.Centered,
  290. VerticalTextAlignment = VerticalTextAlignment.Middle,
  291. ColorScheme = color1,
  292. Text = txt
  293. };
  294. txtLabelMC.TextFormatter.MultiLine = true;
  295. var txtLabelMR = new Label
  296. {
  297. X = Pos.X (txtLabelTR),
  298. Y = Pos.Bottom (txtLabelTR) + 1,
  299. Width = Dim.Percent (100f, true),
  300. Height = Dim.Percent (100f / 3f),
  301. TextAlignment = TextAlignment.Right,
  302. VerticalTextAlignment = VerticalTextAlignment.Middle,
  303. ColorScheme = color1,
  304. Text = txt
  305. };
  306. txtLabelMR.TextFormatter.MultiLine = true;
  307. var txtLabelBL = new Label
  308. {
  309. X = Pos.X (txtLabelML),
  310. Y = Pos.Bottom (txtLabelML) + 1,
  311. Width = Dim.Width (txtLabelML),
  312. Height = Dim.Percent (100f, true),
  313. TextAlignment = TextAlignment.Left,
  314. VerticalTextAlignment = VerticalTextAlignment.Bottom,
  315. ColorScheme = color1,
  316. Text = txt
  317. };
  318. txtLabelBL.TextFormatter.MultiLine = true;
  319. var txtLabelBC = new Label
  320. {
  321. X = Pos.X (txtLabelMC),
  322. Y = Pos.Bottom (txtLabelMC) + 1,
  323. Width = Dim.Width (txtLabelMC),
  324. Height = Dim.Percent (100f, true),
  325. TextAlignment = TextAlignment.Centered,
  326. VerticalTextAlignment = VerticalTextAlignment.Bottom,
  327. ColorScheme = color1,
  328. Text = txt
  329. };
  330. txtLabelBC.TextFormatter.MultiLine = true;
  331. var txtLabelBR = new Label
  332. {
  333. X = Pos.X (txtLabelMR),
  334. Y = Pos.Bottom (txtLabelMR) + 1,
  335. Width = Dim.Percent (100f, true),
  336. Height = Dim.Percent (100f, true),
  337. TextAlignment = TextAlignment.Right,
  338. VerticalTextAlignment = VerticalTextAlignment.Bottom,
  339. ColorScheme = color1,
  340. Text = txt
  341. };
  342. txtLabelBR.TextFormatter.MultiLine = true;
  343. mtxts.Add (txtLabelTL);
  344. mtxts.Add (txtLabelTC);
  345. mtxts.Add (txtLabelTR);
  346. mtxts.Add (txtLabelML);
  347. mtxts.Add (txtLabelMC);
  348. mtxts.Add (txtLabelMR);
  349. mtxts.Add (txtLabelBL);
  350. mtxts.Add (txtLabelBC);
  351. mtxts.Add (txtLabelBR);
  352. // Save Alignments in Data
  353. foreach (Label t in mtxts)
  354. {
  355. t.Data = new { h = t.TextAlignment, v = t.VerticalTextAlignment };
  356. }
  357. container.Add (txtLabelTL);
  358. container.Add (txtLabelTC);
  359. container.Add (txtLabelTR);
  360. container.Add (txtLabelML);
  361. container.Add (txtLabelMC);
  362. container.Add (txtLabelMR);
  363. container.Add (txtLabelBL);
  364. container.Add (txtLabelBC);
  365. container.Add (txtLabelBR);
  366. app.Add (container);
  367. // Edit Text
  368. var editText = new TextView
  369. {
  370. X = 1,
  371. Y = Pos.Bottom (container) + 1,
  372. Width = Dim.Fill (10),
  373. Height = Dim.Fill (1),
  374. ColorScheme = Colors.ColorSchemes ["TopLevel"],
  375. Text = txt
  376. };
  377. editText.MouseClick += (s, m) =>
  378. {
  379. foreach (Label v in txts)
  380. {
  381. v.Text = editText.Text;
  382. }
  383. foreach (Label v in mtxts)
  384. {
  385. v.Text = editText.Text;
  386. }
  387. };
  388. app.KeyUp += (s, m) =>
  389. {
  390. foreach (Label v in txts)
  391. {
  392. v.Text = editText.Text;
  393. }
  394. foreach (Label v in mtxts)
  395. {
  396. v.Text = editText.Text;
  397. }
  398. };
  399. editText.SetFocus ();
  400. app.Add (editText);
  401. // JUSTIFY CHECKBOX
  402. var justifyCheckbox = new CheckBox
  403. {
  404. X = Pos.Right (container) + 1,
  405. Y = Pos.Y (container) + 1,
  406. Width = Dim.Fill (10),
  407. Height = 1,
  408. Text = "Justify"
  409. };
  410. justifyCheckbox.Toggled += (s, e) => ToggleJustify (e.OldValue is { } && (bool)e.OldValue);
  411. app.Add (justifyCheckbox);
  412. // WRAP CHECKBOX
  413. var wrapCheckbox = new CheckBox
  414. {
  415. X = Pos.Right (container) + 1,
  416. Y = Pos.Y (justifyCheckbox) + 1,
  417. AutoSize = false,
  418. Width = Dim.Fill (10),
  419. Height = 1,
  420. Text = "Word Wrap",
  421. Checked = true
  422. };
  423. wrapCheckbox.Toggled += (s, e) =>
  424. {
  425. if (e.OldValue == true)
  426. {
  427. foreach (Label t in mtxts)
  428. {
  429. t.TextFormatter.WordWrap = false;
  430. }
  431. }
  432. else
  433. {
  434. foreach (Label t in mtxts)
  435. {
  436. t.TextFormatter.WordWrap = true;
  437. }
  438. }
  439. };
  440. app.Add (wrapCheckbox);
  441. // Direction Options
  442. List<TextDirection> directionsEnum = Enum.GetValues (typeof (TextDirection)).Cast<TextDirection> ().ToList ();
  443. var directionOptions = new RadioGroup
  444. {
  445. X = Pos.Right (container) + 1,
  446. Y = Pos.Bottom (wrapCheckbox) + 1,
  447. Width = Dim.Fill (10),
  448. Height = Dim.Fill (1),
  449. HotKeySpecifier = (Rune)'\xffff',
  450. RadioLabels = directionsEnum.Select (e => e.ToString ()).ToArray ()
  451. };
  452. directionOptions.SelectedItemChanged += (s, ev) =>
  453. {
  454. var justChecked = justifyCheckbox.Checked is { } && (bool)justifyCheckbox.Checked;
  455. if (justChecked)
  456. {
  457. ToggleJustify (true);
  458. }
  459. foreach (Label v in mtxts)
  460. {
  461. v.TextDirection = (TextDirection)ev.SelectedItem;
  462. }
  463. if (justChecked)
  464. {
  465. ToggleJustify (false);
  466. }
  467. };
  468. app.Add (directionOptions);
  469. Application.Run (app);
  470. app.Dispose ();
  471. void ToggleJustify (bool oldValue)
  472. {
  473. if (oldValue == true)
  474. {
  475. foreach (Label t in mtxts)
  476. {
  477. t.TextAlignment = (TextAlignment)((dynamic)t.Data).h;
  478. t.VerticalTextAlignment = (VerticalTextAlignment)((dynamic)t.Data).v;
  479. }
  480. }
  481. else
  482. {
  483. foreach (Label t in mtxts)
  484. {
  485. if (TextFormatter.IsVerticalDirection (t.TextDirection))
  486. {
  487. t.VerticalTextAlignment = VerticalTextAlignment.Justified;
  488. t.TextAlignment = ((dynamic)t.Data).h;
  489. }
  490. else
  491. {
  492. t.TextAlignment = TextAlignment.Justified;
  493. t.VerticalTextAlignment = ((dynamic)t.Data).v;
  494. }
  495. }
  496. }
  497. }
  498. }
  499. }