TileViewNesting.cs 6.7 KB

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