TextAlignmentAndDirection.cs 21 KB

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