WizardStep.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. namespace Terminal.Gui;
  2. /// <summary>
  3. /// Represents a basic step that is displayed in a <see cref="Wizard"/>. The <see cref="WizardStep"/> view is
  4. /// divided horizontally in two. On the left is the content view where <see cref="View"/>s can be added, On the right
  5. /// is the help for the step. Set <see cref="WizardStep.HelpText"/> to set the help text. If the help text is empty the
  6. /// help pane will not be shown. If there are no Views added to the WizardStep the <see cref="HelpText"/> (if not
  7. /// empty) will fill the wizard step.
  8. /// </summary>
  9. /// <remarks>
  10. /// If <see cref="Button"/>s are added, do not set <see cref="Button.IsDefault"/> to true as this will conflict
  11. /// with the Next button of the Wizard. Subscribe to the <see cref="View.VisibleChanged"/> event to be notified when
  12. /// the step is active; see also: <see cref="Wizard.StepChanged"/>. To enable or disable a step from being shown to the
  13. /// user, set <see cref="View.Enabled"/>.
  14. /// </remarks>
  15. public class WizardStep : View
  16. {
  17. ///// <summary>
  18. ///// The title of the <see cref="WizardStep"/>.
  19. ///// </summary>
  20. ///// <remarks>The Title is only displayed when the <see cref="Wizard"/> is used as a modal pop-up (see <see cref="Wizard.Modal"/>.</remarks>
  21. //public new string Title {
  22. // // BUGBUG: v2 - No need for this as View now has Title w/ notifications.
  23. // get => title;
  24. // set {
  25. // if (!OnTitleChanging (title, value)) {
  26. // var old = title;
  27. // title = value;
  28. // OnTitleChanged (old, title);
  29. // }
  30. // base.Title = value;
  31. // SetNeedsDraw ();
  32. // }
  33. //}
  34. //private string title = string.Empty;
  35. // The contentView works like the ContentView in FrameView.
  36. private readonly View _contentView = new ()
  37. {
  38. CanFocus = true,
  39. TabStop = TabBehavior.TabStop,
  40. Id = "WizardStep._contentView"
  41. };
  42. private readonly TextView _helpTextView = new ()
  43. {
  44. CanFocus = true,
  45. TabStop = TabBehavior.TabStop,
  46. ReadOnly = true,
  47. WordWrap = true,
  48. AllowsTab = false,
  49. Id = "WizardStep._helpTextView"
  50. };
  51. /// <summary>
  52. /// Initializes a new instance of the <see cref="Wizard"/> class.
  53. /// </summary>
  54. public WizardStep ()
  55. {
  56. TabStop = TabBehavior.TabStop;
  57. CanFocus = true;
  58. BorderStyle = LineStyle.None;
  59. base.Add (_contentView);
  60. base.Add (_helpTextView);
  61. // BUGBUG: v2 - Disabling scrolling for now
  62. //var scrollBar = new ScrollBarView (helpTextView, true);
  63. //scrollBar.ChangedPosition += (s,e) => {
  64. // helpTextView.TopRow = scrollBar.Position;
  65. // if (helpTextView.TopRow != scrollBar.Position) {
  66. // scrollBar.Position = helpTextView.TopRow;
  67. // }
  68. // helpTextView.SetNeedsDraw ();
  69. //};
  70. //scrollBar.OtherScrollBarView.ChangedPosition += (s,e) => {
  71. // helpTextView.LeftColumn = scrollBar.OtherScrollBarView.Position;
  72. // if (helpTextView.LeftColumn != scrollBar.OtherScrollBarView.Position) {
  73. // scrollBar.OtherScrollBarView.Position = helpTextView.LeftColumn;
  74. // }
  75. // helpTextView.SetNeedsDraw ();
  76. //};
  77. //scrollBar.VisibleChanged += (s,e) => {
  78. // if (scrollBar.Visible && helpTextView.RightOffset == 0) {
  79. // helpTextView.RightOffset = 1;
  80. // } else if (!scrollBar.Visible && helpTextView.RightOffset == 1) {
  81. // helpTextView.RightOffset = 0;
  82. // }
  83. //};
  84. //scrollBar.OtherScrollBarView.VisibleChanged += (s,e) => {
  85. // if (scrollBar.OtherScrollBarView.Visible && helpTextView.BottomOffset == 0) {
  86. // helpTextView.BottomOffset = 1;
  87. // } else if (!scrollBar.OtherScrollBarView.Visible && helpTextView.BottomOffset == 1) {
  88. // helpTextView.BottomOffset = 0;
  89. // }
  90. //};
  91. //helpTextView.DrawContent += (s,e) => {
  92. // scrollBar.Size = helpTextView.Lines;
  93. // scrollBar.Position = helpTextView.TopRow;
  94. // if (scrollBar.OtherScrollBarView is { }) {
  95. // scrollBar.OtherScrollBarView.Size = helpTextView.Maxlength;
  96. // scrollBar.OtherScrollBarView.Position = helpTextView.LeftColumn;
  97. // }
  98. // scrollBar.LayoutSubviews ();
  99. // scrollBar.Refresh ();
  100. //};
  101. //base.Add (scrollBar);
  102. ShowHide ();
  103. }
  104. /// <summary>Sets or gets the text for the back button. The back button will only be visible on steps after the first step.</summary>
  105. /// <remarks>The default text is "Back"</remarks>
  106. public string BackButtonText { get; set; } = string.Empty;
  107. /// <summary>
  108. /// Sets or gets help text for the <see cref="WizardStep"/>.If <see cref="WizardStep.HelpText"/> is empty the help
  109. /// pane will not be visible and the content will fill the entire WizardStep.
  110. /// </summary>
  111. /// <remarks>The help text is displayed using a read-only <see cref="TextView"/>.</remarks>
  112. public string HelpText
  113. {
  114. get => _helpTextView.Text;
  115. set
  116. {
  117. _helpTextView.Text = value;
  118. ShowHide ();
  119. SetNeedsDraw ();
  120. }
  121. }
  122. /// <summary>Sets or gets the text for the next/finish button.</summary>
  123. /// <remarks>The default text is "Next..." if the Pane is not the last pane. Otherwise it is "Finish"</remarks>
  124. public string NextButtonText { get; set; } = string.Empty;
  125. /// <summary>Add the specified <see cref="View"/> to the <see cref="WizardStep"/>.</summary>
  126. /// <param name="view"><see cref="View"/> to add to this container</param>
  127. public override View Add (View view)
  128. {
  129. _contentView.Add (view);
  130. if (view.CanFocus)
  131. {
  132. CanFocus = true;
  133. }
  134. ShowHide ();
  135. return view;
  136. }
  137. /// <summary>Removes a <see cref="View"/> from <see cref="WizardStep"/>.</summary>
  138. /// <remarks></remarks>
  139. public override View Remove (View view)
  140. {
  141. SetNeedsDraw ();
  142. View container = view?.SuperView;
  143. if (container == this)
  144. {
  145. base.Remove (view);
  146. }
  147. else
  148. {
  149. container?.Remove (view);
  150. }
  151. if (_contentView.InternalSubviews.Count < 1)
  152. {
  153. CanFocus = false;
  154. }
  155. ShowHide ();
  156. return view;
  157. }
  158. /// <summary>Removes all <see cref="View"/>s from the <see cref="WizardStep"/>.</summary>
  159. /// <remarks></remarks>
  160. public override void RemoveAll ()
  161. {
  162. _contentView.RemoveAll ();
  163. ShowHide ();
  164. }
  165. /// <summary>Does the work to show and hide the contentView and helpView as appropriate</summary>
  166. internal void ShowHide ()
  167. {
  168. _contentView.Height = Dim.Fill ();
  169. _helpTextView.Height = Dim.Height(_contentView);
  170. _helpTextView.Width = Dim.Fill ();
  171. if (_contentView.InternalSubviews?.Count > 0)
  172. {
  173. if (_helpTextView.Text.Length > 0)
  174. {
  175. _contentView.Width = Dim.Percent (70);
  176. _helpTextView.X = Pos.Right (_contentView);
  177. _helpTextView.Width = Dim.Fill ();
  178. }
  179. else
  180. {
  181. _contentView.Width = Dim.Fill ();
  182. }
  183. }
  184. else
  185. {
  186. if (_helpTextView.Text.Length > 0)
  187. {
  188. _helpTextView.X = 0;
  189. }
  190. // Error - no pane shown
  191. }
  192. _contentView.Visible = _contentView.InternalSubviews?.Count > 0;
  193. _helpTextView.Visible = _helpTextView.Text.Length > 0;
  194. }
  195. } // end of WizardStep class