TileViewNesting.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. using System.Linq;
  2. using Terminal.Gui;
  3. namespace UICatalog.Scenarios;
  4. [ScenarioMetadata ("Tile View Nesting", "Demonstrates recursive nesting of TileViews")]
  5. [ScenarioCategory ("Controls")]
  6. [ScenarioCategory ("LineView")]
  7. public class TileViewNesting : Scenario
  8. {
  9. private CheckBox _cbBorder;
  10. private CheckBox _cbHorizontal;
  11. private CheckBox _cbTitles;
  12. private CheckBox _cbUseLabels;
  13. private bool _loaded;
  14. private TextField _textField;
  15. private int _viewsCreated;
  16. private int _viewsToCreate;
  17. private View _workArea;
  18. /// <summary>Setup the scenario.</summary>
  19. public override void Setup ()
  20. {
  21. // Scenario Windows.
  22. Win.Title = GetName ();
  23. Win.Y = 1;
  24. var lblViews = new Label { Text = "Number Of Views:" };
  25. _textField = new() { X = Pos.Right (lblViews), Width = 10, Text = "2" };
  26. _textField.TextChanged += (s, e) => SetupTileView ();
  27. _cbHorizontal = new() { X = Pos.Right (_textField) + 1, Text = "Horizontal" };
  28. _cbHorizontal.Toggle += (s, e) => SetupTileView ();
  29. _cbBorder = new() { X = Pos.Right (_cbHorizontal) + 1, Text = "Border" };
  30. _cbBorder.Toggle += (s, e) => SetupTileView ();
  31. _cbTitles = new() { X = Pos.Right (_cbBorder) + 1, Text = "Titles" };
  32. _cbTitles.Toggle += (s, e) => SetupTileView ();
  33. _cbUseLabels = new() { X = Pos.Right (_cbTitles) + 1, Text = "Use Labels" };
  34. _cbUseLabels.Toggle += (s, e) => SetupTileView ();
  35. _workArea = new() { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill () };
  36. var menu = new MenuBar
  37. {
  38. Menus =
  39. [
  40. new ("_File", new MenuItem [] { new ("_Quit", "", () => Quit ()) })
  41. ]
  42. };
  43. Win.Add (lblViews);
  44. Win.Add (_textField);
  45. Win.Add (_cbHorizontal);
  46. Win.Add (_cbBorder);
  47. Win.Add (_cbTitles);
  48. Win.Add (_cbUseLabels);
  49. Win.Add (_workArea);
  50. SetupTileView ();
  51. Top.Add (menu);
  52. Win.Loaded += (s, e) => _loaded = true;
  53. }
  54. private void AddMoreViews (TileView to)
  55. {
  56. if (_viewsCreated == _viewsToCreate)
  57. {
  58. return;
  59. }
  60. if (!(to.Tiles.ElementAt (0).ContentView is TileView))
  61. {
  62. Split (to, true);
  63. }
  64. if (!(to.Tiles.ElementAt (1).ContentView is TileView))
  65. {
  66. Split (to, false);
  67. }
  68. if (to.Tiles.ElementAt (0).ContentView is TileView && to.Tiles.ElementAt (1).ContentView is TileView)
  69. {
  70. AddMoreViews ((TileView)to.Tiles.ElementAt (0).ContentView);
  71. AddMoreViews ((TileView)to.Tiles.ElementAt (1).ContentView);
  72. }
  73. }
  74. private View CreateContentControl (int number) { return _cbUseLabels.State == CheckState.Checked ? CreateLabelView (number) : CreateTextView (number); }
  75. private View CreateLabelView (int number)
  76. {
  77. return new Label
  78. {
  79. Width = Dim.Fill (),
  80. Height = 1,
  81. Text = number.ToString ().Repeat (1000),
  82. CanFocus = true
  83. };
  84. }
  85. private View CreateTextView (int number)
  86. {
  87. return new TextView
  88. {
  89. Width = Dim.Fill (), Height = Dim.Fill (), Text = number.ToString ().Repeat (1000), AllowsTab = false
  90. //WordWrap = true, // TODO: This is very slow (like 10s to render with 45 views)
  91. };
  92. }
  93. private TileView CreateTileView (int titleNumber, Orientation orientation)
  94. {
  95. var toReturn = new TileView
  96. {
  97. Width = Dim.Fill (),
  98. Height = Dim.Fill (),
  99. // flip the orientation
  100. Orientation = orientation
  101. };
  102. toReturn.Tiles.ElementAt (0).Title = _cbTitles.State == CheckState.Checked ? $"View {titleNumber}" : string.Empty;
  103. toReturn.Tiles.ElementAt (1).Title = _cbTitles.State == CheckState.Checked ? $"View {titleNumber + 1}" : string.Empty;
  104. return toReturn;
  105. }
  106. private int GetNumberOfViews ()
  107. {
  108. if (int.TryParse (_textField.Text, out int views) && views >= 0)
  109. {
  110. return views;
  111. }
  112. return 0;
  113. }
  114. private void Quit () { Application.RequestStop (); }
  115. private void SetupTileView ()
  116. {
  117. int numberOfViews = GetNumberOfViews ();
  118. CheckState titles = _cbTitles.State;
  119. CheckState border = _cbBorder.State;
  120. CheckState startHorizontal = _cbHorizontal.State;
  121. foreach (View sub in _workArea.Subviews)
  122. {
  123. sub.Dispose ();
  124. }
  125. _workArea.RemoveAll ();
  126. if (numberOfViews <= 0)
  127. {
  128. return;
  129. }
  130. TileView root = CreateTileView (1, startHorizontal == CheckState.Checked ? Orientation.Horizontal : Orientation.Vertical);
  131. root.Tiles.ElementAt (0).ContentView.Add (CreateContentControl (1));
  132. root.Tiles.ElementAt (0).Title = _cbTitles.State == CheckState.Checked ? "View 1" : string.Empty;
  133. root.Tiles.ElementAt (1).ContentView.Add (CreateContentControl (2));
  134. root.Tiles.ElementAt (1).Title = _cbTitles.State == CheckState.Checked ? "View 2" : string.Empty;
  135. root.LineStyle = border == CheckState.Checked? LineStyle.Rounded : LineStyle.None;
  136. _workArea.Add (root);
  137. if (numberOfViews == 1)
  138. {
  139. root.Tiles.ElementAt (1).ContentView.Visible = false;
  140. }
  141. if (numberOfViews > 2)
  142. {
  143. _viewsCreated = 2;
  144. _viewsToCreate = numberOfViews;
  145. AddMoreViews (root);
  146. }
  147. if (_loaded)
  148. {
  149. _workArea.LayoutSubviews ();
  150. }
  151. }
  152. private void Split (TileView to, bool left)
  153. {
  154. if (_viewsCreated == _viewsToCreate)
  155. {
  156. return;
  157. }
  158. TileView newView;
  159. if (left)
  160. {
  161. to.TrySplitTile (0, 2, out newView);
  162. }
  163. else
  164. {
  165. to.TrySplitTile (1, 2, out newView);
  166. }
  167. _viewsCreated++;
  168. // During splitting the old Title will have been migrated to View1 so we only need
  169. // to set the Title on View2 (the one that gets our new TextView)
  170. newView.Tiles.ElementAt (1).Title = _cbTitles.State == CheckState.Checked ? $"View {_viewsCreated}" : string.Empty;
  171. // Flip orientation
  172. newView.Orientation = to.Orientation == Orientation.Vertical
  173. ? Orientation.Horizontal
  174. : Orientation.Vertical;
  175. newView.Tiles.ElementAt (1).ContentView.Add (CreateContentControl (_viewsCreated));
  176. }
  177. }