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 TextField { X = Pos.Right (lblViews), Width = 10, Text = "2" };
  26. _textField.TextChanged += (s, e) => SetupTileView ();
  27. _cbHorizontal = new CheckBox { X = Pos.Right (_textField) + 1, Text = "Horizontal" };
  28. _cbHorizontal.Toggled += (s, e) => SetupTileView ();
  29. _cbBorder = new CheckBox { X = Pos.Right (_cbHorizontal) + 1, Text = "Border" };
  30. _cbBorder.Toggled += (s, e) => SetupTileView ();
  31. _cbTitles = new CheckBox { X = Pos.Right (_cbBorder) + 1, Text = "Titles" };
  32. _cbTitles.Toggled += (s, e) => SetupTileView ();
  33. _cbUseLabels = new CheckBox { X = Pos.Right (_cbTitles) + 1, Text = "Use Labels" };
  34. _cbUseLabels.Toggled += (s, e) => SetupTileView ();
  35. _workArea = new View { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill () };
  36. var menu = new MenuBar
  37. {
  38. Menus =
  39. [
  40. new MenuBarItem ("_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 (bool)_cbUseLabels.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. AutoSize = false,
  82. Text = number.ToString ().Repeat (1000),
  83. CanFocus = true
  84. };
  85. }
  86. private View CreateTextView (int number)
  87. {
  88. return new TextView
  89. {
  90. Width = Dim.Fill (), Height = Dim.Fill (), Text = number.ToString ().Repeat (1000), AllowsTab = false
  91. //WordWrap = true, // TODO: This is very slow (like 10s to render with 45 views)
  92. };
  93. }
  94. private TileView CreateTileView (int titleNumber, Orientation orientation)
  95. {
  96. var toReturn = new TileView
  97. {
  98. Width = Dim.Fill (),
  99. Height = Dim.Fill (),
  100. // flip the orientation
  101. Orientation = orientation
  102. };
  103. toReturn.Tiles.ElementAt (0).Title = (bool)_cbTitles.Checked ? $"View {titleNumber}" : string.Empty;
  104. toReturn.Tiles.ElementAt (1).Title = (bool)_cbTitles.Checked ? $"View {titleNumber + 1}" : string.Empty;
  105. return toReturn;
  106. }
  107. private int GetNumberOfViews ()
  108. {
  109. if (int.TryParse (_textField.Text, out int views) && views >= 0)
  110. {
  111. return views;
  112. }
  113. return 0;
  114. }
  115. private void Quit () { Application.RequestStop (); }
  116. private void SetupTileView ()
  117. {
  118. int numberOfViews = GetNumberOfViews ();
  119. bool? titles = _cbTitles.Checked;
  120. bool? border = _cbBorder.Checked;
  121. bool? startHorizontal = _cbHorizontal.Checked;
  122. foreach (View sub in _workArea.Subviews)
  123. {
  124. sub.Dispose ();
  125. }
  126. _workArea.RemoveAll ();
  127. if (numberOfViews <= 0)
  128. {
  129. return;
  130. }
  131. TileView root = CreateTileView (1, (bool)startHorizontal ? Orientation.Horizontal : Orientation.Vertical);
  132. root.Tiles.ElementAt (0).ContentView.Add (CreateContentControl (1));
  133. root.Tiles.ElementAt (0).Title = (bool)_cbTitles.Checked ? "View 1" : string.Empty;
  134. root.Tiles.ElementAt (1).ContentView.Add (CreateContentControl (2));
  135. root.Tiles.ElementAt (1).Title = (bool)_cbTitles.Checked ? "View 2" : string.Empty;
  136. root.LineStyle = (bool)border ? LineStyle.Rounded : LineStyle.None;
  137. _workArea.Add (root);
  138. if (numberOfViews == 1)
  139. {
  140. root.Tiles.ElementAt (1).ContentView.Visible = false;
  141. }
  142. if (numberOfViews > 2)
  143. {
  144. _viewsCreated = 2;
  145. _viewsToCreate = numberOfViews;
  146. AddMoreViews (root);
  147. }
  148. if (_loaded)
  149. {
  150. _workArea.LayoutSubviews ();
  151. }
  152. }
  153. private void Split (TileView to, bool left)
  154. {
  155. if (_viewsCreated == _viewsToCreate)
  156. {
  157. return;
  158. }
  159. TileView newView;
  160. if (left)
  161. {
  162. to.TrySplitTile (0, 2, out newView);
  163. }
  164. else
  165. {
  166. to.TrySplitTile (1, 2, out newView);
  167. }
  168. _viewsCreated++;
  169. // During splitting the old Title will have been migrated to View1 so we only need
  170. // to set the Title on View2 (the one that gets our new TextView)
  171. newView.Tiles.ElementAt (1).Title = (bool)_cbTitles.Checked ? $"View {_viewsCreated}" : string.Empty;
  172. // Flip orientation
  173. newView.Orientation = to.Orientation == Orientation.Vertical
  174. ? Orientation.Horizontal
  175. : Orientation.Vertical;
  176. newView.Tiles.ElementAt (1).ContentView.Add (CreateContentControl (_viewsCreated));
  177. }
  178. }