mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Adds multi-step Wizard view (#1783)
* Initial commit for Wizard
* Fixes #1777 - Dialog button justification. Adds unit tests
* Added missing API doc
* Work in progress
* Added tests for wide chars
* Tests
* more tests
* wip
* fixed test that broke by adjusting dialog button alignment
* fixed test that broke by adjusting dialog button alignment
* Fixed Dialogs scenario crash re: Parse v TryParse
* broke tests. can't figure out how.
* Revert "broke tests. can't figure out how."
This reverts commit f3c53928ac.
* Fixed unit tests
* Reverted workaround that doesn't work
* Refactor and cleanup
This commit is contained in:
@@ -152,7 +152,7 @@ namespace Terminal.Gui {
|
||||
|
||||
void LayoutStartedHandler ()
|
||||
{
|
||||
if (buttons.Count == 0) return;
|
||||
if (buttons.Count == 0 || !IsInitialized) return;
|
||||
|
||||
int shiftLeft = 0;
|
||||
|
||||
|
||||
417
Terminal.Gui/Windows/Wizard.cs
Normal file
417
Terminal.Gui/Windows/Wizard.cs
Normal file
@@ -0,0 +1,417 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NStack;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// Provides a step-based "wizard" UI. The Wizard supports multiple steps. Each step (<see cref="WizardStep"/>) can host
|
||||
/// arbitrary <see cref="View"/>s, much like a <see cref="Dialog"/>. Each step also has a pane for help text. Along the
|
||||
/// bottom of the Wizard view are customizable buttons enabling the user to navigate forward and backward through the Wizard.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
public class Wizard : Dialog {
|
||||
|
||||
/// <summary>
|
||||
/// One step for the Wizard. The <see cref="WizardStep"/> view hosts two sub-views: 1) add <see cref="View"/>s to <see cref="WizardStep.Controls"/>,
|
||||
/// 2) use <see cref="WizardStep.HelpText"/> to set the contents of the <see cref="TextView"/> that shows on the
|
||||
/// right side. Use <see cref="WizardStep.showControls"/> and <see cref="WizardStep.showHelp"/> to
|
||||
/// control wether the control or help pane are shown.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If <see cref="Button"/>s are added, do not set <see cref="Button.IsDefault"/> to true as this will conflict
|
||||
/// with the Next button of the Wizard.
|
||||
/// </remarks>
|
||||
public class WizardStep : View {
|
||||
/// <summary>
|
||||
/// The title of the <see cref="WizardStep"/>.
|
||||
/// </summary>
|
||||
public ustring Title { get => title; set => title = value; }
|
||||
// TODO: Update Wizard title when step title is changed if step is current - this will require step to slueth it's parent
|
||||
private ustring title;
|
||||
|
||||
private View controlPane = new FrameView ();
|
||||
|
||||
/// <summary>
|
||||
/// THe pane that holds the controls for the <see cref="WizardStep"/>. Use <see cref="WizardStep.Controls"/> `Add(View`) to add
|
||||
/// controls. Note that the Controls view is sized to take 70% of the Wizard's width and the <see cref="WizardStep.HelpText"/>
|
||||
/// takes the other 30%. This can be adjusted by setting `Width` from `Dim.Percent(70)` to
|
||||
/// another value. If <see cref="WizardStep.ShowHelp"/> is set to `false` the control pane will fill the entire
|
||||
/// Wizard.
|
||||
/// </summary>
|
||||
public View Controls { get => controlPane; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets or gets help text for the <see cref="WizardStep"/>.If <see cref="WizardStep.ShowHelp"/> is set to
|
||||
/// `false` the control pane will fill the entire wizard.
|
||||
/// </summary>
|
||||
/// <remarks>The help text is displayed using a read-only <see cref="TextView"/>.</remarks>
|
||||
public ustring HelpText { get => helpTextView.Text; set => helpTextView.Text = value; }
|
||||
private TextView helpTextView = new TextView ();
|
||||
|
||||
/// <summary>
|
||||
/// Sets or gets the text for the back button. The back button will only be visible on
|
||||
/// steps after the first step.
|
||||
/// </summary>
|
||||
/// <remarks>The default text is "Back"</remarks>
|
||||
public ustring BackButtonText { get; set; } = ustring.Empty;
|
||||
// TODO: Update button text of Wizard button when step's button text is changed if step is current - this will require step to slueth it's parent
|
||||
|
||||
/// <summary>
|
||||
/// Sets or gets the text for the next/finish button.
|
||||
/// </summary>
|
||||
/// <remarks>The default text is "Next..." if the Pane is not the last pane. Otherwise it is "Finish"</remarks>
|
||||
public ustring NextButtonText { get; set; } = ustring.Empty;
|
||||
// TODO: Update button text of Wizard button when step's button text is changed if step is current - this will require step to slueth it's parent
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Wizard"/> class using <see cref="LayoutStyle.Computed"/> positioning.
|
||||
/// </summary>
|
||||
/// <param name="title">Title for the Step. Will be appended to the containing Wizard's title as
|
||||
/// "Wizard Title - Wizard Step Title" when this step is active.</param>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
public WizardStep (ustring title)
|
||||
{
|
||||
this.Title = title; // this.Title holds just the "Wizard Title"; base.Title holds "Wizard Title - Step Title"
|
||||
this.ColorScheme = Colors.Menu;
|
||||
|
||||
Y = 0;
|
||||
Height = Dim.Fill (1); // for button frame
|
||||
Width = Dim.Fill ();
|
||||
|
||||
Controls.ColorScheme = Colors.Dialog;
|
||||
Controls.Border.BorderStyle = BorderStyle.None;
|
||||
Controls.Border.Padding = new Thickness (0);
|
||||
Controls.Border.BorderThickness = new Thickness (0);
|
||||
this.Add (Controls);
|
||||
|
||||
helpTextView.ColorScheme = Colors.Menu;
|
||||
helpTextView.Y = 0;
|
||||
helpTextView.ReadOnly = true;
|
||||
helpTextView.WordWrap = true;
|
||||
this.Add (helpTextView);
|
||||
ShowHide ();
|
||||
|
||||
var scrollBar = new ScrollBarView (helpTextView, true);
|
||||
|
||||
scrollBar.ChangedPosition += () => {
|
||||
helpTextView.TopRow = scrollBar.Position;
|
||||
if (helpTextView.TopRow != scrollBar.Position) {
|
||||
scrollBar.Position = helpTextView.TopRow;
|
||||
}
|
||||
helpTextView.SetNeedsDisplay ();
|
||||
};
|
||||
|
||||
scrollBar.VisibleChanged += () => {
|
||||
if (scrollBar.Visible && helpTextView.RightOffset == 0) {
|
||||
helpTextView.RightOffset = 1;
|
||||
} else if (!scrollBar.Visible && helpTextView.RightOffset == 1) {
|
||||
helpTextView.RightOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
helpTextView.DrawContent += (e) => {
|
||||
scrollBar.Size = helpTextView.Lines;
|
||||
scrollBar.Position = helpTextView.TopRow;
|
||||
if (scrollBar.OtherScrollBarView != null) {
|
||||
scrollBar.OtherScrollBarView.Size = helpTextView.Maxlength;
|
||||
scrollBar.OtherScrollBarView.Position = helpTextView.LeftColumn;
|
||||
}
|
||||
scrollBar.LayoutSubviews ();
|
||||
scrollBar.Refresh ();
|
||||
};
|
||||
this.Add (scrollBar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true (the default) the help will be visible. If false, the help will not be shown and the control pane will
|
||||
/// fill the wizard step.
|
||||
/// </summary>
|
||||
public bool ShowHelp {
|
||||
get => showHelp;
|
||||
set {
|
||||
showHelp = value;
|
||||
ShowHide ();
|
||||
}
|
||||
}
|
||||
private bool showHelp = true;
|
||||
|
||||
/// <summary>
|
||||
/// If true (the default) the <see cref="Controls"/> View will be visible. If false, the controls will not be shown and the help will
|
||||
/// fill the wizard step.
|
||||
/// </summary>
|
||||
public bool ShowControls {
|
||||
get => showControls;
|
||||
set {
|
||||
showControls = value;
|
||||
ShowHide ();
|
||||
}
|
||||
}
|
||||
private bool showControls = true;
|
||||
|
||||
/// <summary>
|
||||
/// Does the work to show and hide the controls, help, and buttons as appropriate
|
||||
/// </summary>
|
||||
private void ShowHide ()
|
||||
{
|
||||
Controls.Height = Dim.Fill (1);
|
||||
helpTextView.Height = Dim.Fill (1);
|
||||
helpTextView.Width = Dim.Fill ();
|
||||
|
||||
if (showControls) {
|
||||
if (showHelp) {
|
||||
Controls.Width = Dim.Percent (70);
|
||||
helpTextView.X = Pos.Right (Controls) ;
|
||||
helpTextView.Width = Dim.Fill ();
|
||||
|
||||
} else {
|
||||
Controls.Width = Dim.Percent (100);
|
||||
}
|
||||
} else {
|
||||
if (showHelp) {
|
||||
helpTextView.X = 0;
|
||||
} else {
|
||||
// Error - no pane shown
|
||||
}
|
||||
|
||||
}
|
||||
Controls.Visible = showControls;
|
||||
helpTextView.Visible = showHelp;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="CurrentStep"/> is not the first step in the wizard, this button causes
|
||||
/// the <see cref="MovingBack"/> event to be fired and the wizard moves to the previous step.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use the <see cref="MovingBack"></see> event to be notified when the user attempts to go back.
|
||||
/// </remarks>
|
||||
public Button BackButton { get => backBtn; }
|
||||
private Button backBtn;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="CurrentStep"/> is the last step in the wizard, this button causes
|
||||
/// the <see cref="Finished"/> event to be fired and the wizard to close. If the step is not the last step,
|
||||
/// the <see cref="MovingNext"/> event will be fired and the wizard will move next step.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use the <see cref="MovingNext"></see> and <see cref="Finished"></see> events to be notified
|
||||
/// when the user attempts go to the next step or finish the wizard.
|
||||
/// </remarks>
|
||||
public Button NextFinishButton { get => nextfinishBtn; }
|
||||
private Button nextfinishBtn;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Wizard"/> class using <see cref="LayoutStyle.Computed"/> positioning.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Wizard will be vertically and horizontally centered in the container.
|
||||
/// After initialization use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> change size and position.
|
||||
/// </remarks>
|
||||
public Wizard () : this (ustring.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Wizard"/> class using <see cref="LayoutStyle.Computed"/> positioning.
|
||||
/// </summary>
|
||||
/// <param name="title">Title for the Wizard.</param>
|
||||
/// <remarks>
|
||||
/// The Wizard will be vertically and horizontally centered in the container.
|
||||
/// After initialization use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> change size and position.
|
||||
/// </remarks>
|
||||
public Wizard (ustring title) : base (title)
|
||||
{
|
||||
wizardTitle = title;
|
||||
// Using Justify causes the Back and Next buttons to be hard justified against
|
||||
// the left and right edge
|
||||
ButtonAlignment = ButtonAlignments.Justify;
|
||||
this.Border.BorderStyle = BorderStyle.Double;
|
||||
|
||||
// Add a horiz separator
|
||||
var separator = new LineView (Graphs.Orientation.Horizontal) {
|
||||
Y = Pos.AnchorEnd (2)
|
||||
};
|
||||
Add (separator);
|
||||
|
||||
backBtn = new Button ("_Back") { AutoSize = true };
|
||||
AddButton (backBtn);
|
||||
|
||||
nextfinishBtn = new Button ("_Next...") { AutoSize = true };
|
||||
nextfinishBtn.IsDefault = true;
|
||||
AddButton (nextfinishBtn);
|
||||
|
||||
backBtn.Clicked += () => {
|
||||
var args = new WizardStepEventArgs ();
|
||||
MovingBack?.Invoke (args);
|
||||
if (!args.Cancel) {
|
||||
if (currentStep > 0) {
|
||||
CurrentStep--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
nextfinishBtn.Clicked += () => {
|
||||
if (currentStep == steps.Count - 1) {
|
||||
var args = new WizardStepEventArgs ();
|
||||
Finished?.Invoke (args);
|
||||
if (!args.Cancel) {
|
||||
Application.RequestStop (this);
|
||||
}
|
||||
} else {
|
||||
var args = new WizardStepEventArgs ();
|
||||
MovingNext?.Invoke (args);
|
||||
if (!args.Cancel) {
|
||||
CurrentStep++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Loaded += () => {
|
||||
foreach (var step in steps) {
|
||||
step.Y = 0;
|
||||
}
|
||||
if (steps.Count > 0) {
|
||||
|
||||
CurrentStep = 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private List<WizardStep> steps = new List<WizardStep> ();
|
||||
private int currentStep = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a step to the wizard. The Next and Back buttons navigate through the added steps in the
|
||||
/// order they were added.
|
||||
/// </summary>
|
||||
/// <param name="newStep"></param>
|
||||
/// <remarks>The "Next..." button of the last step added will read "Finish" (unless changed from default).</remarks>
|
||||
public void AddStep (WizardStep newStep)
|
||||
{
|
||||
steps.Add (newStep);
|
||||
this.Add (newStep);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The title of the Wizard, shown at the top of the Wizard with " - currentStep.Title" appended.
|
||||
/// </summary>
|
||||
public new ustring Title {
|
||||
get {
|
||||
// The base (Dialog) Title holds the full title ("Wizard Title - Step Title")
|
||||
return base.Title;
|
||||
}
|
||||
set {
|
||||
wizardTitle = value;
|
||||
base.Title = $"{wizardTitle}{(steps.Count > 0 ? " - " + steps [currentStep].Title : string.Empty)}";
|
||||
}
|
||||
}
|
||||
private ustring wizardTitle = ustring.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="EventArgs"/> for <see cref="WizardStep"/> transition events.
|
||||
/// </summary>
|
||||
public class WizardStepEventArgs : EventArgs {
|
||||
/// <summary>
|
||||
/// Set to true to cancel the transition to the next step.
|
||||
/// </summary>
|
||||
public bool Cancel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="WizardStepEventArgs"/>
|
||||
/// </summary>
|
||||
public WizardStepEventArgs ()
|
||||
{
|
||||
Cancel = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when the Back button in the <see cref="Wizard"/> is clicked. The Back button is always
|
||||
/// the first button in the array of Buttons passed to the <see cref="Wizard"/> constructor, if any.
|
||||
/// </summary>
|
||||
public event Action<WizardStepEventArgs> MovingBack;
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when the Next/Finish button in the <see cref="Wizard"/> is clicked. The Next/Finish button is always
|
||||
/// the last button in the array of Buttons passed to the <see cref="Wizard"/> constructor, if any. This event is only
|
||||
/// raised if the <see cref="CurrentStep"/> is the last Step in the Wizard flow
|
||||
/// (otherwise the <see cref="Finished"/> event is raised).
|
||||
/// </summary>
|
||||
public event Action<WizardStepEventArgs> MovingNext;
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when the Next/Finish button in the <see cref="Wizard"/> is clicked. The Next/Finish button is always
|
||||
/// the last button in the array of Buttons passed to the <see cref="Wizard"/> constructor, if any. This event is only
|
||||
/// raised if the <see cref="CurrentStep"/> is the last Step in the Wizard flow
|
||||
/// (otherwise the <see cref="Finished"/> event is raised).
|
||||
/// </summary>
|
||||
public event Action<WizardStepEventArgs> Finished;
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when the current step )<see cref="CurrentStep"/>) in the <see cref="Wizard"/> changes.
|
||||
/// </summary>
|
||||
public event Action<CurrentStepChangedEventArgs> CurrentStepChanged;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="EventArgs"/> for <see cref="WizardStep"/> events.
|
||||
/// </summary>
|
||||
public class CurrentStepChangedEventArgs : EventArgs {
|
||||
/// <summary>
|
||||
/// The new current <see cref="WizardStep"/>.
|
||||
/// </summary>
|
||||
public int CurrentStepIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="CurrentStepChangedEventArgs"/>
|
||||
/// </summary>
|
||||
/// <param name="currentStepIndex">The new current <see cref="WizardStep"/>.</param>
|
||||
public CurrentStepChangedEventArgs (int currentStepIndex)
|
||||
{
|
||||
CurrentStepIndex = currentStepIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the currently active <see cref="WizardStep"/>.
|
||||
/// </summary>
|
||||
public int CurrentStep {
|
||||
get => currentStep;
|
||||
set {
|
||||
currentStep = value;
|
||||
OnCurrentStepChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the current <see cref="WizardStep"/> has changed (<see cref="CurrentStep"/>).
|
||||
/// </summary>
|
||||
public virtual void OnCurrentStepChanged ()
|
||||
{
|
||||
CurrentStepChanged?.Invoke (new CurrentStepChangedEventArgs (currentStep));
|
||||
// Hide all but the first step
|
||||
foreach (WizardStep step in steps) {
|
||||
step.Visible = (steps [currentStep] == step);
|
||||
}
|
||||
|
||||
// TODO: Add support for "Wizard Title - Step Title"
|
||||
base.Title = $"{wizardTitle}{(steps.Count > 0 ? " - " + steps [currentStep].Title : string.Empty)}";
|
||||
|
||||
backBtn.Text = steps [currentStep].BackButtonText != ustring.Empty ? steps [currentStep].BackButtonText : "_Back";
|
||||
if (currentStep == 0) {
|
||||
backBtn.Visible = false;
|
||||
} else {
|
||||
backBtn.Visible = true;
|
||||
}
|
||||
|
||||
if (currentStep == steps.Count - 1) {
|
||||
nextfinishBtn.Text = steps [currentStep].NextButtonText != ustring.Empty ? steps [currentStep].NextButtonText : "Fi_nish";
|
||||
} else {
|
||||
nextfinishBtn.Text = steps [currentStep].NextButtonText != ustring.Empty ? steps [currentStep].NextButtonText : "_Next...";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,18 @@
|
||||
"UICatalog : -usc": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "-usc"
|
||||
},
|
||||
"Wizards": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "Wizards"
|
||||
},
|
||||
"Dialogs": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "Dialogs"
|
||||
},
|
||||
"Buttons": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "Buttons"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,6 +174,13 @@ namespace UICatalog.Scenarios {
|
||||
};
|
||||
buttons.Add (button);
|
||||
}
|
||||
if (buttons.Count > 1) {
|
||||
buttons [1].Text = "Accept";
|
||||
buttons [1].IsDefault = true;
|
||||
buttons [0].Visible = false;
|
||||
buttons [0].Text = "_Back";
|
||||
buttons [0].IsDefault = false;
|
||||
}
|
||||
|
||||
// This tests dynamically adding buttons; ensuring the dialog resizes if needed and
|
||||
// the buttons are laid out correctly
|
||||
@@ -202,7 +209,9 @@ namespace UICatalog.Scenarios {
|
||||
};
|
||||
buttons.Add (button);
|
||||
dialog.AddButton (button);
|
||||
button.TabIndex = buttons [buttons.Count - 2].TabIndex + 1;
|
||||
if (buttons.Count > 1) {
|
||||
button.TabIndex = buttons [buttons.Count - 2].TabIndex + 1;
|
||||
}
|
||||
};
|
||||
dialog.Add (add);
|
||||
|
||||
|
||||
237
UICatalog/Scenarios/Wizards.cs
Normal file
237
UICatalog/Scenarios/Wizards.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using NStack;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Terminal.Gui;
|
||||
|
||||
namespace UICatalog.Scenarios {
|
||||
[ScenarioMetadata (Name: "Wizards", Description: "Demonstrates how to the Wizard class")]
|
||||
[ScenarioCategory ("Dialogs")]
|
||||
public class Wizards : Scenario {
|
||||
public override void Setup ()
|
||||
{
|
||||
Win.ColorScheme = Colors.Base;
|
||||
var frame = new FrameView ("Wizard Options") {
|
||||
X = Pos.Center (),
|
||||
Y = 0,
|
||||
Width = Dim.Percent (75),
|
||||
Height = 10,
|
||||
ColorScheme = Colors.Base,
|
||||
};
|
||||
Win.Add (frame);
|
||||
|
||||
var label = new Label ("Width:") {
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Width = 15,
|
||||
Height = 1,
|
||||
TextAlignment = Terminal.Gui.TextAlignment.Right,
|
||||
};
|
||||
frame.Add (label);
|
||||
var widthEdit = new TextField ("80") {
|
||||
X = Pos.Right (label) + 1,
|
||||
Y = Pos.Top (label),
|
||||
Width = 5,
|
||||
Height = 1
|
||||
};
|
||||
frame.Add (widthEdit);
|
||||
|
||||
label = new Label ("Height:") {
|
||||
X = 0,
|
||||
Y = Pos.Bottom (label),
|
||||
Width = Dim.Width (label),
|
||||
Height = 1,
|
||||
TextAlignment = Terminal.Gui.TextAlignment.Right,
|
||||
};
|
||||
frame.Add (label);
|
||||
var heightEdit = new TextField ("20") {
|
||||
X = Pos.Right (label) + 1,
|
||||
Y = Pos.Top (label),
|
||||
Width = 5,
|
||||
Height = 1
|
||||
};
|
||||
frame.Add (heightEdit);
|
||||
|
||||
label = new Label ("Title:") {
|
||||
X = 0,
|
||||
Y = Pos.Bottom (label),
|
||||
Width = Dim.Width (label),
|
||||
Height = 1,
|
||||
TextAlignment = Terminal.Gui.TextAlignment.Right,
|
||||
};
|
||||
frame.Add (label);
|
||||
var titleEdit = new TextField ("Title") {
|
||||
X = Pos.Right (label) + 1,
|
||||
Y = Pos.Top (label),
|
||||
Width = Dim.Fill (),
|
||||
Height = 1
|
||||
};
|
||||
frame.Add (titleEdit);
|
||||
|
||||
void Top_Loaded ()
|
||||
{
|
||||
frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + 2;
|
||||
Top.Loaded -= Top_Loaded;
|
||||
}
|
||||
Top.Loaded += Top_Loaded;
|
||||
|
||||
label = new Label ("Action:") {
|
||||
X = Pos.Center (),
|
||||
Y = Pos.AnchorEnd (1),
|
||||
AutoSize = true,
|
||||
TextAlignment = Terminal.Gui.TextAlignment.Right,
|
||||
};
|
||||
Win.Add (label);
|
||||
var actionLabel = new Label (" ") {
|
||||
X = Pos.Right (label),
|
||||
Y = Pos.AnchorEnd (1),
|
||||
AutoSize = true,
|
||||
ColorScheme = Colors.Error,
|
||||
};
|
||||
|
||||
var showWizardButton = new Button ("Show Wizard") {
|
||||
X = Pos.Center (),
|
||||
Y = Pos.Bottom (frame) + 2,
|
||||
IsDefault = true,
|
||||
};
|
||||
showWizardButton.Clicked += () => {
|
||||
try {
|
||||
int width = 0;
|
||||
int.TryParse (widthEdit.Text.ToString (), out width);
|
||||
int height = 0;
|
||||
int.TryParse (heightEdit.Text.ToString (), out height);
|
||||
|
||||
if (width < 1 || height < 1) {
|
||||
MessageBox.ErrorQuery ("Nope", "Height and width must be greater than 0 (much bigger)", "Ok");
|
||||
return;
|
||||
}
|
||||
|
||||
var wizard = new Wizard (titleEdit.Text) {
|
||||
Width = width,
|
||||
Height = height
|
||||
};
|
||||
|
||||
wizard.MovingBack += (args) => {
|
||||
//args.Cancel = true;
|
||||
actionLabel.Text = "Moving Back";
|
||||
};
|
||||
|
||||
wizard.MovingNext += (args) => {
|
||||
//args.Cancel = true;
|
||||
actionLabel.Text = "Moving Next";
|
||||
};
|
||||
|
||||
wizard.Finished += (args) => {
|
||||
//args.Cancel = true;
|
||||
actionLabel.Text = "Finished";
|
||||
};
|
||||
|
||||
// Add 1st step
|
||||
var firstStep = new Wizard.WizardStep ("End User License Agreement");
|
||||
wizard.AddStep (firstStep);
|
||||
firstStep.ShowControls = false;
|
||||
firstStep.NextButtonText = "Accept!";
|
||||
firstStep.HelpText = "This is the End User License Agreement.\n\n\n\n\n\nThis is a test of the emergency broadcast system. This is a test of the emergency broadcast system.\nThis is a test of the emergency broadcast system.\n\n\nThis is a test of the emergency broadcast system.\n\nThis is a test of the emergency broadcast system.\n\n\n\nThe end of the EULA.";
|
||||
|
||||
// Add 2nd step
|
||||
var secondStep = new Wizard.WizardStep ("Second Step");
|
||||
wizard.AddStep (secondStep);
|
||||
secondStep.HelpText = "This is the help text for the Second Step.\n\nPress the button to see a message box.\n\nEnter name too.";
|
||||
var buttonLbl = new Label () { Text = "Second Step Button: ", AutoSize = true, X = 1, Y = 1 };
|
||||
var button = new Button () {
|
||||
Text = "Press Me",
|
||||
X = Pos.Right (buttonLbl),
|
||||
Y = Pos.Top (buttonLbl)
|
||||
};
|
||||
button.Clicked += () => {
|
||||
MessageBox.Query ("Wizard Scenario", "The Second Step Button was pressed.");
|
||||
};
|
||||
secondStep.Controls.Add (buttonLbl, button);
|
||||
var lbl = new Label () { Text = "First Name: ", AutoSize = true, X = 1, Y = Pos.Bottom (buttonLbl) };
|
||||
var firstNameField = new TextField () { Width = 30, X = Pos.Right (lbl), Y = Pos.Top (lbl) };
|
||||
secondStep.Controls.Add (lbl, firstNameField);
|
||||
lbl = new Label () { Text = "Last Name: ", AutoSize = true, X = 1, Y = Pos.Bottom (lbl) };
|
||||
var lastNameField = new TextField () { Width = 30, X = Pos.Right (lbl), Y = Pos.Top (lbl) };
|
||||
secondStep.Controls.Add (lbl, lastNameField);
|
||||
|
||||
// Add 3rd step
|
||||
var thirdStep = new Wizard.WizardStep ("Third Step");
|
||||
wizard.AddStep (thirdStep);
|
||||
thirdStep.HelpText = "This is the help text for the Third Step.";
|
||||
var progLbl = new Label () { Text = "Third Step ProgressBar: ", AutoSize = true, X = 1, Y = 10 };
|
||||
var progressBar = new ProgressBar () {
|
||||
X = Pos.Right (progLbl),
|
||||
Y = Pos.Top (progLbl),
|
||||
Width = 40,
|
||||
Fraction = 0.42F
|
||||
};
|
||||
thirdStep.Controls.Add (progLbl, progressBar);
|
||||
|
||||
// Add 4th step
|
||||
var fourthStep = new Wizard.WizardStep ("Hidden Help pane");
|
||||
wizard.AddStep (fourthStep);
|
||||
fourthStep.ShowHelp = false;
|
||||
var someText = new TextView () {
|
||||
Text = "This step shows how to hide the Help pane. The control pane contains this TextView.",
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Width = Dim.Fill (),
|
||||
Height = Dim.Fill (),
|
||||
WordWrap = true,
|
||||
};
|
||||
fourthStep.Controls.Add (someText);
|
||||
var scrollBar = new ScrollBarView (someText, true);
|
||||
|
||||
scrollBar.ChangedPosition += () => {
|
||||
someText.TopRow = scrollBar.Position;
|
||||
if (someText.TopRow != scrollBar.Position) {
|
||||
scrollBar.Position = someText.TopRow;
|
||||
}
|
||||
someText.SetNeedsDisplay ();
|
||||
};
|
||||
|
||||
scrollBar.VisibleChanged += () => {
|
||||
if (scrollBar.Visible && someText.RightOffset == 0) {
|
||||
someText.RightOffset = 1;
|
||||
} else if (!scrollBar.Visible && someText.RightOffset == 1) {
|
||||
someText.RightOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
someText.DrawContent += (e) => {
|
||||
scrollBar.Size = someText.Lines;
|
||||
scrollBar.Position = someText.TopRow;
|
||||
if (scrollBar.OtherScrollBarView != null) {
|
||||
scrollBar.OtherScrollBarView.Size = someText.Maxlength;
|
||||
scrollBar.OtherScrollBarView.Position = someText.LeftColumn;
|
||||
}
|
||||
scrollBar.LayoutSubviews ();
|
||||
scrollBar.Refresh ();
|
||||
};
|
||||
fourthStep.Controls.Add (scrollBar);
|
||||
|
||||
// Add last step
|
||||
var lastStep = new Wizard.WizardStep ("The last step");
|
||||
wizard.AddStep (lastStep);
|
||||
lastStep.HelpText = "The wizard is complete! Press the Finish button to continue. Pressing ESC will cancel the wizard.";
|
||||
|
||||
|
||||
// TODO: Demo setting initial Pane
|
||||
|
||||
wizard.Finished += (args) => {
|
||||
Application.RequestStop (wizard);
|
||||
};
|
||||
|
||||
Application.Run (wizard);
|
||||
|
||||
} catch (FormatException) {
|
||||
actionLabel.Text = "Invalid Options";
|
||||
}
|
||||
};
|
||||
Win.Add (showWizardButton);
|
||||
|
||||
Win.Add (actionLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,10 @@ namespace Terminal.Gui.Views {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
private Application.RunState RunButtonTestDialog (string title, int width, Dialog.ButtonAlignments align, params Button [] btns)
|
||||
private (Application.RunState, Dialog) RunButtonTestDialog (string title, int width, Dialog.ButtonAlignments align, params Button [] btns)
|
||||
{
|
||||
var dlg = new Dialog (title, width, 3, btns) { ButtonAlignment = align };
|
||||
return Application.Begin (dlg);
|
||||
return (Application.Begin (dlg), dlg);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -30,6 +30,7 @@ namespace Terminal.Gui.Views {
|
||||
public void ButtonAlignment_One ()
|
||||
{
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
Application.RunState runstate = null;
|
||||
|
||||
var title = "1234";
|
||||
// E.g "|[ ok ]|"
|
||||
@@ -41,28 +42,28 @@ namespace Terminal.Gui.Views {
|
||||
|
||||
d.SetBufferSize (width, 3);
|
||||
|
||||
var runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btnText));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btnText));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Justify
|
||||
buttonRow = $"{d.VLine} {d.LeftBracket} {btnText} {d.RightBracket}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btnText));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btnText));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Right
|
||||
buttonRow = $"{d.VLine} {d.LeftBracket} {btnText} {d.RightBracket}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btnText));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btnText));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Left
|
||||
buttonRow = $"{d.VLine}{d.LeftBracket} {btnText} {d.RightBracket} {d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btnText));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btnText));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
}
|
||||
@@ -71,6 +72,8 @@ namespace Terminal.Gui.Views {
|
||||
[AutoInitShutdown]
|
||||
public void ButtonAlignment_Two ()
|
||||
{
|
||||
Application.RunState runstate = null;
|
||||
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
@@ -87,36 +90,100 @@ namespace Terminal.Gui.Views {
|
||||
|
||||
d.SetBufferSize (buttonRow.Length, 3);
|
||||
|
||||
var runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Justify
|
||||
buttonRow = $@"{d.VLine}{btn1} {btn2}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Right
|
||||
buttonRow = $@"{d.VLine} {btn1} {btn2}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Left
|
||||
buttonRow = $@"{d.VLine}{btn1} {btn2} {d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void ButtonAlignment_Two_Hidden ()
|
||||
{
|
||||
Application.RunState runstate = null;
|
||||
bool firstIteration = false;
|
||||
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
// E.g "|[ yes ][ no ]|"
|
||||
var btn1Text = "yes";
|
||||
var btn1 = $"{d.LeftBracket} {btn1Text} {d.RightBracket}";
|
||||
var btn2Text = "no";
|
||||
var btn2 = $"{d.LeftBracket} {btn2Text} {d.RightBracket}";
|
||||
|
||||
var buttonRow = $@"{d.VLine} {btn1} {btn2} {d.VLine}";
|
||||
var width = buttonRow.Length;
|
||||
var topRow = $"┌ {title} {new String (d.HLine.ToString () [0], width - title.Length - 4)}┐";
|
||||
var bottomRow = $"└{new String (d.HLine.ToString () [0], width - 2)}┘";
|
||||
|
||||
d.SetBufferSize (buttonRow.Length, 3);
|
||||
|
||||
Dialog dlg = null;
|
||||
Button button1, button2;
|
||||
|
||||
//// Default (Center)
|
||||
//button1 = new Button (btn1Text);
|
||||
//button2 = new Button (btn2Text);
|
||||
//(runstate, dlg) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, button1, button2);
|
||||
//button1.Visible = false;
|
||||
//Application.RunMainLoopIteration (ref runstate, true, ref firstIteration);
|
||||
//buttonRow = $@"{d.VLine} {btn2} {d.VLine}";
|
||||
//GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
//Application.End (runstate);
|
||||
|
||||
// Justify
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
button1 = new Button (btn1Text);
|
||||
button2 = new Button (btn2Text);
|
||||
(runstate, dlg) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, button1, button2);
|
||||
button1.Visible = false;
|
||||
Application.RunMainLoopIteration (ref runstate, true, ref firstIteration);
|
||||
buttonRow = $@"{d.VLine} {btn2}{d.VLine}";
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
//// Right
|
||||
//buttonRow = $@"{d.VLine} {btn1} {btn2}{d.VLine}";
|
||||
//Assert.Equal (width, buttonRow.Length);
|
||||
//(runstate, dlg) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text));
|
||||
//GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
//Application.End (runstate);
|
||||
|
||||
//// Left
|
||||
//buttonRow = $@"{d.VLine}{btn1} {btn2} {d.VLine}";
|
||||
//Assert.Equal (width, buttonRow.Length);
|
||||
//(runstate, dlg) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text));
|
||||
//GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
//Application.End (runstate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void ButtonAlignment_Three ()
|
||||
{
|
||||
Application.RunState runstate = null;
|
||||
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
@@ -135,28 +202,28 @@ namespace Terminal.Gui.Views {
|
||||
|
||||
d.SetBufferSize (buttonRow.Length, 3);
|
||||
|
||||
var runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Justify
|
||||
buttonRow = $@"{d.VLine}{btn1} {btn2} {btn3}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Right
|
||||
buttonRow = $@"{d.VLine} {btn1} {btn2} {btn3}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Left
|
||||
buttonRow = $@"{d.VLine}{btn1} {btn2} {btn3} {d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
}
|
||||
@@ -165,6 +232,8 @@ namespace Terminal.Gui.Views {
|
||||
[AutoInitShutdown]
|
||||
public void ButtonAlignment_Four ()
|
||||
{
|
||||
Application.RunState runstate = null;
|
||||
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
@@ -186,28 +255,28 @@ namespace Terminal.Gui.Views {
|
||||
d.SetBufferSize (buttonRow.Length, 3);
|
||||
|
||||
// Default - Center
|
||||
var runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Justify
|
||||
buttonRow = $"{d.VLine}{btn1} {btn2} {btn3} {btn4}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Right
|
||||
buttonRow = $"{d.VLine} {btn1} {btn2} {btn3} {btn4}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Left
|
||||
buttonRow = $"{d.VLine}{btn1} {btn2} {btn3} {btn4} {d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
}
|
||||
@@ -216,6 +285,8 @@ namespace Terminal.Gui.Views {
|
||||
[AutoInitShutdown]
|
||||
public void ButtonAlignment_Four_Wider ()
|
||||
{
|
||||
Application.RunState runstate = null;
|
||||
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
@@ -240,28 +311,28 @@ namespace Terminal.Gui.Views {
|
||||
d.SetBufferSize (width, 3);
|
||||
|
||||
// Default - Center
|
||||
var runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Justify
|
||||
buttonRow = $"{d.VLine}{btn1} {btn2} {btn3} {btn4}{d.VLine}";
|
||||
Assert.Equal (width, ustring.Make (buttonRow).ConsoleWidth);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Right
|
||||
buttonRow = $"{d.VLine} {btn1} {btn2} {btn3} {btn4}{d.VLine}";
|
||||
Assert.Equal (width, ustring.Make (buttonRow).ConsoleWidth);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Left
|
||||
buttonRow = $"{d.VLine}{btn1} {btn2} {btn3} {btn4} {d.VLine}";
|
||||
Assert.Equal (width, ustring.Make (buttonRow).ConsoleWidth);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
}
|
||||
@@ -270,6 +341,8 @@ namespace Terminal.Gui.Views {
|
||||
[AutoInitShutdown]
|
||||
public void ButtonAlignment_Four_WideOdd ()
|
||||
{
|
||||
Application.RunState runstate = null;
|
||||
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
@@ -293,28 +366,28 @@ namespace Terminal.Gui.Views {
|
||||
d.SetBufferSize (buttonRow.Length, 3);
|
||||
|
||||
// Default - Center
|
||||
var runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Justify
|
||||
buttonRow = $"{d.VLine}{btn1} {btn2} {btn3} {btn4}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Right
|
||||
buttonRow = $"{d.VLine} {btn1} {btn2} {btn3} {btn4}{d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
|
||||
// Left
|
||||
buttonRow = $"{d.VLine}{btn1} {btn2} {btn3} {btn4} {d.VLine}";
|
||||
Assert.Equal (width, buttonRow.Length);
|
||||
runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, new Button (btn1Text), new Button (btn2Text), new Button (btn3Text), new Button (btn4Text));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
}
|
||||
@@ -323,6 +396,8 @@ namespace Terminal.Gui.Views {
|
||||
[AutoInitShutdown]
|
||||
public void Zero_Buttons_Works ()
|
||||
{
|
||||
Application.RunState runstate = null;
|
||||
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
@@ -333,7 +408,7 @@ namespace Terminal.Gui.Views {
|
||||
var bottomRow = $"└{new String (d.HLine.ToString () [0], width - 2)}┘";
|
||||
d.SetBufferSize (buttonRow.Length, 3);
|
||||
|
||||
var runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, null);
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, null);
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
|
||||
Application.End (runstate);
|
||||
@@ -343,6 +418,8 @@ namespace Terminal.Gui.Views {
|
||||
[AutoInitShutdown]
|
||||
public void One_Button_Works ()
|
||||
{
|
||||
Application.RunState runstate = null;
|
||||
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
@@ -354,7 +431,7 @@ namespace Terminal.Gui.Views {
|
||||
var bottomRow = $"└{new String (d.HLine.ToString () [0], width - 2)}┘";
|
||||
d.SetBufferSize (buttonRow.Length, 3);
|
||||
|
||||
var runstate = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btnText));
|
||||
(runstate, var _) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, new Button (btnText));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
Application.End (runstate);
|
||||
}
|
||||
@@ -363,6 +440,8 @@ namespace Terminal.Gui.Views {
|
||||
[AutoInitShutdown]
|
||||
public void Add_Button_Works ()
|
||||
{
|
||||
Application.RunState runstate = null;
|
||||
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
@@ -380,7 +459,7 @@ namespace Terminal.Gui.Views {
|
||||
|
||||
// Default (center)
|
||||
var dlg = new Dialog (title, width, 3, new Button (btn1Text)) { ButtonAlignment = Dialog.ButtonAlignments.Center };
|
||||
var runstate = Application.Begin (dlg);
|
||||
runstate = Application.Begin (dlg);
|
||||
var buttonRow = $"{d.VLine} {btn1} {d.VLine}";
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
|
||||
|
||||
164
UnitTests/WizardTests.cs
Normal file
164
UnitTests/WizardTests.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Terminal.Gui;
|
||||
using Xunit;
|
||||
using System.Globalization;
|
||||
using Xunit.Abstractions;
|
||||
using NStack;
|
||||
|
||||
namespace Terminal.Gui.Views {
|
||||
|
||||
public class WizardTests {
|
||||
readonly ITestOutputHelper output;
|
||||
|
||||
public WizardTests (ITestOutputHelper output)
|
||||
{
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
private void RunButtonTestWizard (string title, int width, int height)
|
||||
{
|
||||
var wizard = new Wizard (title) { Width = width, Height = height };
|
||||
Application.End (Application.Begin (wizard));
|
||||
}
|
||||
|
||||
// =========== WizardStep Tests
|
||||
[Fact, AutoInitShutdown]
|
||||
public void WizardStep_Title ()
|
||||
{
|
||||
// Verify default title
|
||||
|
||||
// Verify set actually changes property
|
||||
|
||||
// Verify set changes Wizard title (TODO: NOT YET IMPLEMENTED)
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
public void WizardStep_ButtonText ()
|
||||
{
|
||||
// Verify default button text
|
||||
|
||||
// Verify set actually changes property
|
||||
|
||||
// Verify set actually changes buttons for the current step
|
||||
}
|
||||
|
||||
// =========== Wizard Tests
|
||||
[Fact, AutoInitShutdown]
|
||||
public void DefaultConstructor_SizedProperly ()
|
||||
{
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var wizard = new Wizard ();
|
||||
Assert.NotEqual (0, wizard.Width);
|
||||
Assert.NotEqual (0, wizard.Height);
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
// Verify a zero-step wizard doesn't crash and shows a blank wizard
|
||||
// and that the title is correct
|
||||
public void ZeroStepWizard_Shows ()
|
||||
{
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
var stepTitle = "";
|
||||
|
||||
int width = 30;
|
||||
int height = 6;
|
||||
d.SetBufferSize (width, height);
|
||||
|
||||
var btnBackText = "Back";
|
||||
var btnBack = $"{d.LeftBracket} {btnBackText} {d.RightBracket}";
|
||||
var btnNextText = "Next...";
|
||||
var btnNext = $"{d.LeftBracket}{d.LeftDefaultIndicator} {btnNextText} {d.RightDefaultIndicator}{d.RightBracket}";
|
||||
|
||||
var topRow = $"{d.ULDCorner} {title}{stepTitle} {new String (d.HDLine.ToString () [0], width - title.Length - stepTitle.Length - 4)}{d.URDCorner}";
|
||||
var row2 = $"{d.VDLine}{new String (' ', width - 2)}{d.VDLine}";
|
||||
var row3 = row2;
|
||||
var separatorRow = $"{d.VDLine}{new String (d.HLine.ToString () [0], width - 2)}{d.VDLine}";
|
||||
var buttonRow = $"{d.VDLine}{btnBack}{new String (' ', width - btnBack.Length - btnNext.Length - 2)}{btnNext}{d.VDLine}";
|
||||
var bottomRow = $"{d.LLDCorner}{new String (d.HDLine.ToString () [0], width - 2)}{d.LRDCorner}";
|
||||
|
||||
var wizard = new Wizard (title) { Width = width, Height = height };
|
||||
Application.End (Application.Begin (wizard));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{row2}\n{row3}\n{separatorRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
// This test verifies that a single step wizard shows the correct buttons
|
||||
// and that the title is correct
|
||||
public void OneStepWizard_Shows ()
|
||||
{
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
// This test verifies that the 2nd step in a wizard with 2 steps
|
||||
// shows the correct buttons on both steps
|
||||
// and that the title is correct
|
||||
public void TwoStepWizard_Next_Shows_SecondStep ()
|
||||
{
|
||||
// verify step one
|
||||
|
||||
// Next
|
||||
|
||||
// verify step two
|
||||
|
||||
// Back
|
||||
|
||||
// verify step one again
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
// This test verifies that the 2nd step in a wizard with more than 2 steps
|
||||
// shows the correct buttons on all steps
|
||||
// and that the title is correct
|
||||
public void ThreeStepWizard_Next_Shows_Steps ()
|
||||
{
|
||||
|
||||
// verify step one
|
||||
|
||||
// Next
|
||||
|
||||
// verify step two
|
||||
|
||||
// Back
|
||||
|
||||
// verify step one again
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
// this test is needed because Wizard overrides Dialog's title behavior ("Title - StepTitle")
|
||||
public void Setting_Title_Works ()
|
||||
{
|
||||
var d = ((FakeDriver)Application.Driver);
|
||||
|
||||
var title = "1234";
|
||||
var stepTitle = " - ABCD";
|
||||
|
||||
int width = 40;
|
||||
int height = 4;
|
||||
d.SetBufferSize (width, height);
|
||||
|
||||
var btnNextText = "Finish";
|
||||
var btnNext = $"{d.LeftBracket}{d.LeftDefaultIndicator} {btnNextText} {d.RightDefaultIndicator}{d.RightBracket}";
|
||||
|
||||
var topRow = $"{d.ULDCorner} {title}{stepTitle} {new String (d.HDLine.ToString () [0], width - title.Length - stepTitle.Length - 4)}{d.URDCorner}";
|
||||
var separatorRow = $"{d.VDLine}{new String (d.HLine.ToString () [0], width - 2)}{d.VDLine}";
|
||||
|
||||
// Once this is fixed, revert to commented out line: https://github.com/migueldeicaza/gui.cs/issues/1791
|
||||
var buttonRow = $"{d.VDLine}{new String (' ', width - btnNext.Length - 3)}{btnNext} {d.VDLine}";
|
||||
//var buttonRow = $"{d.VDLine}{new String (' ', width - btnNext.Length - 2)}{btnNext}{d.VDLine}";
|
||||
var bottomRow = $"{d.LLDCorner}{new String (d.HDLine.ToString () [0], width - 2)}{d.LRDCorner}";
|
||||
|
||||
var wizard = new Wizard (title) { Width = width, Height = height };
|
||||
wizard.AddStep (new Wizard.WizardStep ("ABCD"));
|
||||
|
||||
Application.End (Application.Begin (wizard));
|
||||
GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{separatorRow}\n{buttonRow}\n{bottomRow}", output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user