diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index 24c2a1b88..0c40f67c5 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -571,7 +571,6 @@ namespace Terminal.Gui {
if (autoSize && value.Anchor (0) != TextFormatter.Size.Width
- (TextFormatter.IsHorizontalDirection (TextDirection)
&& TextFormatter.Text.Contains (HotKeySpecifier) ? 1 : 0)) {
-
autoSize = false;
}
SetMinWidthHeight ();
@@ -600,7 +599,6 @@ namespace Terminal.Gui {
if (autoSize && value.Anchor (0) != TextFormatter.Size.Height
- (TextFormatter.IsVerticalDirection (TextDirection)
&& TextFormatter.Text.Contains (HotKeySpecifier) ? 1 : 0)) {
-
autoSize = false;
}
SetMinWidthHeight ();
diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs
index cde610256..66bca7fb4 100644
--- a/Terminal.Gui/Views/TextView.cs
+++ b/Terminal.Gui/Views/TextView.cs
@@ -1659,8 +1659,10 @@ namespace Terminal.Gui {
}
///
- /// Gets or sets a value indicating whether pressing the TAB key in a
- /// types a TAB character in the view instead of moving the focus to the next view in the tab order.
+ /// Gets or sets whether the inserts a tab character into the text or ignores
+ /// tab input. If set to `false` and the user presses the tab key (or shift-tab) the focus will move to the
+ /// next view (or previous with shift-tab). The default is `true`; if the user presses the tab key, a tab
+ /// character will be inserted into the text.
///
public bool AllowsTab {
get => allowsTab;
diff --git a/Terminal.Gui/Windows/Wizard.cs b/Terminal.Gui/Windows/Wizard.cs
index 926cd4b86..cd8b3dc20 100644
--- a/Terminal.Gui/Windows/Wizard.cs
+++ b/Terminal.Gui/Windows/Wizard.cs
@@ -30,6 +30,8 @@ namespace Terminal.Gui {
// 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;
+ // The controlPane is a separate view, so when devs add controls to the Step and help is visible, Y = Pos.AnchorEnd()
+ // will work as expected.
private View controlPane = new FrameView ();
///
@@ -74,8 +76,8 @@ namespace Terminal.Gui {
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;
-
+ this.ColorScheme = Colors.Dialog;
+
Y = 0;
Height = Dim.Fill (1); // for button frame
Width = Dim.Fill ();
@@ -178,7 +180,7 @@ namespace Terminal.Gui {
if (showControls) {
if (showHelp) {
Controls.Width = Dim.Percent (70);
- helpTextView.X = Pos.Right (Controls) ;
+ helpTextView.X = Pos.Right (Controls);
helpTextView.Width = Dim.Fill ();
} else {
@@ -195,29 +197,7 @@ namespace Terminal.Gui {
Controls.Visible = showControls;
helpTextView.Visible = showHelp;
}
- }
-
- ///
- /// If the is not the first step in the wizard, this button causes
- /// the event to be fired and the wizard moves to the previous step.
- ///
- ///
- /// Use the event to be notified when the user attempts to go back.
- ///
- public Button BackButton { get => backBtn; }
- private Button backBtn;
-
- ///
- /// If the is the last step in the wizard, this button causes
- /// the event to be fired and the wizard to close. If the step is not the last step,
- /// the event will be fired and the wizard will move next step.
- ///
- ///
- /// Use the and events to be notified
- /// when the user attempts go to the next step or finish the wizard.
- ///
- public Button NextFinishButton { get => nextfinishBtn; }
- private Button nextfinishBtn;
+ } // WizardStep
///
/// Initializes a new instance of the class using positioning.
@@ -259,46 +239,90 @@ namespace Terminal.Gui {
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;
- }
- };
+ backBtn.Clicked += BackBtn_Clicked;
+ nextfinishBtn.Clicked += NextfinishBtn_Clicked;
+ Loaded += Wizard_Loaded;
+ Closing += Wizard_Closing;
}
- private List steps = new List ();
- private int currentStep = 0;
+ private bool finishedPressed = false;
+
+ private void Wizard_Closing (ToplevelClosingEventArgs obj)
+ {
+ if (!finishedPressed) {
+ var args = new WizardButtonEventArgs ();
+ Cancelled?.Invoke (args);
+ }
+ }
+
+ private void Wizard_Loaded ()
+ {
+ foreach (var step in steps) {
+ step.Y = 0;
+ }
+ if (steps.Count > 0) {
+ CurrentStep = steps.First.Value;
+ }
+ }
+
+ private void NextfinishBtn_Clicked ()
+ {
+ if (CurrentStep == steps.Last.Value) {
+ var args = new WizardButtonEventArgs ();
+ Finished?.Invoke (args);
+ if (!args.Cancel) {
+ finishedPressed = true;
+ Application.RequestStop (this);
+ }
+ } else {
+ var args = new WizardButtonEventArgs ();
+ MovingNext?.Invoke (args);
+ if (!args.Cancel) {
+ var current = steps.Find (CurrentStep);
+ if (current != null && current.Next != null) {
+ GotoStep (current.Next.Value);
+ }
+ }
+ }
+ }
+
+ private void BackBtn_Clicked ()
+ {
+ var args = new WizardButtonEventArgs ();
+ MovingBack?.Invoke (args);
+ if (!args.Cancel) {
+ var current = steps.Find (CurrentStep);
+ if (current != null && current.Previous != null) {
+ GotoStep (current.Previous.Value);
+ }
+ }
+ }
+
+ private LinkedList steps = new LinkedList ();
+ private WizardStep currentStep = null;
+
+ ///
+ /// If the is not the first step in the wizard, this button causes
+ /// the event to be fired and the wizard moves to the previous step.
+ ///
+ ///
+ /// Use the event to be notified when the user attempts to go back.
+ ///
+ public Button BackButton { get => backBtn; }
+ private Button backBtn;
+
+ ///
+ /// If the is the last step in the wizard, this button causes
+ /// the event to be fired and the wizard to close. If the step is not the last step,
+ /// the event will be fired and the wizard will move next step.
+ ///
+ ///
+ /// Use the and events to be notified
+ /// when the user attempts go to the next step or finish the wizard.
+ ///
+ public Button NextFinishButton { get => nextfinishBtn; }
+ private Button nextfinishBtn;
///
/// Adds a step to the wizard. The Next and Back buttons navigate through the added steps in the
@@ -308,8 +332,9 @@ namespace Terminal.Gui {
/// The "Next..." button of the last step added will read "Finish" (unless changed from default).
public void AddStep (WizardStep newStep)
{
- steps.Add (newStep);
+ steps.AddLast (newStep);
this.Add (newStep);
+ SetNeedsLayout ();
}
///
@@ -322,7 +347,7 @@ namespace Terminal.Gui {
}
set {
wizardTitle = value;
- base.Title = $"{wizardTitle}{(steps.Count > 0 ? " - " + steps [currentStep].Title : string.Empty)}";
+ base.Title = $"{wizardTitle}{(steps.Count > 0 ? " - " + currentStep.Title : string.Empty)}";
}
}
private ustring wizardTitle = ustring.Empty;
@@ -330,16 +355,16 @@ namespace Terminal.Gui {
///
/// for transition events.
///
- public class WizardStepEventArgs : EventArgs {
+ public class WizardButtonEventArgs : EventArgs {
///
/// Set to true to cancel the transition to the next step.
///
public bool Cancel { get; set; }
///
- /// Initializes a new instance of
+ /// Initializes a new instance of
///
- public WizardStepEventArgs ()
+ public WizardButtonEventArgs ()
{
Cancel = false;
}
@@ -349,7 +374,7 @@ namespace Terminal.Gui {
/// This event is raised when the Back button in the is clicked. The Back button is always
/// the first button in the array of Buttons passed to the constructor, if any.
///
- public event Action MovingBack;
+ public event Action MovingBack;
///
/// This event is raised when the Next/Finish button in the is clicked. The Next/Finish button is always
@@ -357,7 +382,7 @@ namespace Terminal.Gui {
/// raised if the is the last Step in the Wizard flow
/// (otherwise the event is raised).
///
- public event Action MovingNext;
+ public event Action MovingNext;
///
/// This event is raised when the Next/Finish button in the is clicked. The Next/Finish button is always
@@ -365,69 +390,143 @@ namespace Terminal.Gui {
/// raised if the is the last Step in the Wizard flow
/// (otherwise the event is raised).
///
- public event Action Finished;
+ public event Action Finished;
+
///
- /// This event is raised when the current step )) in the changes.
+ /// This event is raised when the user has cancelled the (with Ctrl-Q or ESC).
///
- public event Action CurrentStepChanged;
+ public event Action Cancelled;
///
/// for events.
///
- public class CurrentStepChangedEventArgs : EventArgs {
+ public class StepChangeEventArgs : EventArgs {
///
- /// The new current .
+ /// The current (or previous) .
///
- public int CurrentStepIndex { get; }
+ public WizardStep OldStep { get; }
///
- /// Initializes a new instance of
+ /// The the is changing to or has changed to.
///
- /// The new current .
- public CurrentStepChangedEventArgs (int currentStepIndex)
+ public WizardStep NewStep { get; }
+
+ ///
+ /// Event handlers can set to true before returning to cancel the step transition.
+ ///
+ public bool Cancel { get; set; }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// The current .
+ /// The new .
+ public StepChangeEventArgs (WizardStep oldStep, WizardStep newStep)
{
- CurrentStepIndex = currentStepIndex;
+ OldStep = oldStep;
+ NewStep = newStep;
+ Cancel = false;
}
}
+ ///
+ /// This event is raised when the current ) is about to change. Use
+ /// to abort the transition.
+ ///
+ public event Action StepChanging;
+
+ ///
+ /// This event is raised after the has changed the .
+ ///
+ public event Action StepChanged;
+
///
/// Gets or sets the currently active .
///
- public int CurrentStep {
+ public WizardStep CurrentStep {
get => currentStep;
set {
- currentStep = value;
- OnCurrentStepChanged ();
+ GotoStep (value);
}
}
///
- /// Called when the current has changed ().
+ /// Called when the is about to transition to another . Fires the event.
///
- public virtual void OnCurrentStepChanged ()
+ /// The step the Wizard is about to change from
+ /// The step the Wizard is about to change to
+ /// True if the change is to be cancelled.
+ public virtual bool OnStepChanging (WizardStep oldStep, WizardStep newStep)
{
- CurrentStepChanged?.Invoke (new CurrentStepChangedEventArgs (currentStep));
- // Hide all but the first step
+ var args = new StepChangeEventArgs (oldStep, newStep);
+ StepChanging?.Invoke (args);
+ return args.Cancel;
+ }
+
+
+ ///
+ /// Called when the has completed transition to a new . Fires the event.
+ ///
+ /// The step the Wizard changed from
+ /// The step the Wizard has changed to
+ /// True if the change is to be cancelled.
+ public virtual bool OnStepChanged (WizardStep oldStep, WizardStep newStep)
+ {
+ var args = new StepChangeEventArgs (oldStep, newStep);
+ StepChanged?.Invoke (args);
+ return args.Cancel;
+ }
+ ///
+ /// Changes to the specified .
+ ///
+ /// The step to go to.
+ /// True if the transition to the step succeeded. False if the step was not found or the operation was cancelled.
+ public bool GotoStep (WizardStep newStep)
+ {
+ if (OnStepChanging (currentStep, newStep)) {
+ return false;
+ }
+
+ // Hide all but the new step
foreach (WizardStep step in steps) {
- step.Visible = (steps [currentStep] == step);
+ step.Visible = (step == newStep);
}
- // TODO: Add support for "Wizard Title - Step Title"
- base.Title = $"{wizardTitle}{(steps.Count > 0 ? " - " + steps [currentStep].Title : string.Empty)}";
+ base.Title = $"{wizardTitle}{(steps.Count > 0 ? " - " + newStep.Title : string.Empty)}";
- backBtn.Text = steps [currentStep].BackButtonText != ustring.Empty ? steps [currentStep].BackButtonText : "_Back";
- if (currentStep == 0) {
- backBtn.Visible = false;
+ // TODO: Move strings to loc
+
+ // Configure the Back button
+ backBtn.Text = newStep.BackButtonText != ustring.Empty ? newStep.BackButtonText : "_Back";
+ backBtn.Visible = (newStep != steps.First.Value);
+
+ // Configure the Next/Finished button
+ if (newStep == steps.Last.Value) {
+ nextfinishBtn.Text = newStep.NextButtonText != ustring.Empty ? newStep.NextButtonText : "Fi_nish";
} else {
- backBtn.Visible = true;
+ nextfinishBtn.Text = newStep.NextButtonText != ustring.Empty ? newStep.NextButtonText : "_Next...";
}
- if (currentStep == steps.Count - 1) {
- nextfinishBtn.Text = steps [currentStep].NextButtonText != ustring.Empty ? steps [currentStep].NextButtonText : "Fi_nish";
+ // Set focus to the nav buttons
+ if (backBtn.HasFocus) {
+ backBtn.SetFocus ();
} else {
- nextfinishBtn.Text = steps [currentStep].NextButtonText != ustring.Empty ? steps [currentStep].NextButtonText : "_Next...";
+ nextfinishBtn.SetFocus ();
}
+
+ var oldStep = currentStep;
+ currentStep = newStep;
+
+ LayoutSubviews ();
+ Redraw (this.Bounds);
+
+ if (OnStepChanged (oldStep, currentStep)) {
+ // For correctness we do this, but it's meaningless because there's nothing to cancel
+ return false;
+ }
+
+ return true;
}
}
}
\ No newline at end of file
diff --git a/UICatalog/Scenarios/Dialogs.cs b/UICatalog/Scenarios/Dialogs.cs
index 4f99d4568..766c1e719 100644
--- a/UICatalog/Scenarios/Dialogs.cs
+++ b/UICatalog/Scenarios/Dialogs.cs
@@ -215,6 +215,18 @@ namespace UICatalog.Scenarios {
};
dialog.Add (add);
+ var addChar = new Button ($"Add a {Char.ConvertFromUtf32(CODE_POINT)} to each button") {
+ X = Pos.Center (),
+ Y = Pos.Center () + 1
+ };
+ addChar.Clicked += () => {
+ foreach (var button in buttons) {
+ button.Text += Char.ConvertFromUtf32 (CODE_POINT);
+ }
+ dialog.LayoutSubviews ();
+ };
+ dialog.Add (addChar);
+
Application.Run (dialog);
buttonPressedLabel.Text = $"{clicked}";
diff --git a/UICatalog/Scenarios/Wizards.cs b/UICatalog/Scenarios/Wizards.cs
index 8ec9ca9cc..80a178f78 100644
--- a/UICatalog/Scenarios/Wizards.cs
+++ b/UICatalog/Scenarios/Wizards.cs
@@ -16,7 +16,6 @@ namespace UICatalog.Scenarios {
X = Pos.Center (),
Y = 0,
Width = Dim.Percent (75),
- Height = 10,
ColorScheme = Colors.Base,
};
Win.Add (frame);
@@ -69,9 +68,18 @@ namespace UICatalog.Scenarios {
};
frame.Add (titleEdit);
+ var useStepView = new CheckBox () {
+ Text = "Add 3rd step controls to WizardStep instead of WizardStep.Controls",
+ Checked = false,
+ X = Pos.Left (titleEdit),
+ Y = Pos.Bottom (titleEdit)
+ };
+ frame.Add (useStepView);
+
+
void Top_Loaded ()
{
- frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + 2;
+ frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + Dim.Height (useStepView) + 2;
Top.Loaded -= Top_Loaded;
}
Top.Loaded += Top_Loaded;
@@ -127,6 +135,11 @@ namespace UICatalog.Scenarios {
actionLabel.Text = "Finished";
};
+ wizard.Cancelled += (args) => {
+ //args.Cancel = true;
+ actionLabel.Text = "Cancelled";
+ };
+
// Add 1st step
var firstStep = new Wizard.WizardStep ("End User License Agreement");
wizard.AddStep (firstStep);
@@ -138,6 +151,15 @@ namespace UICatalog.Scenarios {
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.";
+
+
+ View viewForControls = secondStep.Controls;
+ ustring frameMsg = "Added to WizardStep.Controls";
+ if (useStepView.Checked) {
+ viewForControls = secondStep;
+ frameMsg = "Added to WizardStep directly";
+ }
+
var buttonLbl = new Label () { Text = "Second Step Button: ", AutoSize = true, X = 1, Y = 1 };
var button = new Button () {
Text = "Press Me",
@@ -147,13 +169,28 @@ namespace UICatalog.Scenarios {
button.Clicked += () => {
MessageBox.Query ("Wizard Scenario", "The Second Step Button was pressed.");
};
- secondStep.Controls.Add (buttonLbl, button);
+ viewForControls.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);
+ viewForControls.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);
+ viewForControls.Add (lbl, lastNameField);
+ var checkBox = new CheckBox () { Text = "Un-check me!", Checked = true, X = Pos.Left (lastNameField), Y = Pos.Bottom (lastNameField) };
+ viewForControls.Add (checkBox);
+
+ // Add a frame to demonstrate difference between adding controls to
+ // WizardStep.Controls vs. WizardStep directly. This is here to demonstrate why
+ // adding to .Controls is preferred.
+ var frame = new FrameView ($"A Broken Frame - {frameMsg}") {
+ X = 0,
+ Y = Pos.Bottom (checkBox) + 2,
+ Width = Dim.Fill (),
+ Height = 4,
+ //ColorScheme = Colors.Error,
+ };
+ frame.Add (new TextField ("This is a TextField inside of the frame."));
+ viewForControls.Add (frame);
// Add 3rd step
var thirdStep = new Wizard.WizardStep ("Third Step");
@@ -169,20 +206,35 @@ namespace UICatalog.Scenarios {
thirdStep.Controls.Add (progLbl, progressBar);
// Add 4th step
- var fourthStep = new Wizard.WizardStep ("Hidden Help pane");
+ var fourthStep = new Wizard.WizardStep ("Step Four");
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.",
+ Text = "This step (Step Four) shows how to hide the Help pane. The control pane contains this TextView (but it's hard to tell it's a TextView because of Issue #1800).",
X = 0,
Y = 0,
Width = Dim.Fill (),
Height = Dim.Fill (),
WordWrap = true,
+ AllowsTab = false
};
fourthStep.Controls.Add (someText);
+ //fourthStep.NextButtonText = "4";
var scrollBar = new ScrollBarView (someText, true);
+ wizard.StepChanging += (args) => {
+ if (args.NewStep == fourthStep) {
+ var btn = MessageBox.ErrorQuery ("Wizards", "Move to Step Four?", "Yes", "No");
+ args.Cancel = btn == 1;
+ }
+ };
+
+ wizard.StepChanged += (args) => {
+ if (args.NewStep == fourthStep) {
+ var btn = MessageBox.ErrorQuery ("Wizards", "Yay. Moved to Step Four", "Ok");
+ }
+ };
+
scrollBar.ChangedPosition += () => {
someText.TopRow = scrollBar.Position;
if (someText.TopRow != scrollBar.Position) {
@@ -216,13 +268,8 @@ namespace UICatalog.Scenarios {
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) {
diff --git a/UnitTests/WizardTests.cs b/UnitTests/WizardTests.cs
index 43aec149f..70b4d2bea 100644
--- a/UnitTests/WizardTests.cs
+++ b/UnitTests/WizardTests.cs
@@ -93,6 +93,37 @@ namespace Terminal.Gui.Views {
// and that the title is correct
public void OneStepWizard_Shows ()
{
+ var d = ((FakeDriver)Application.Driver);
+
+ var title = "1234";
+ var stepTitle = "ABCD";
+
+ int width = 30;
+ int height = 7;
+ d.SetBufferSize (width, height);
+
+ var btnBackText = "Back";
+ var btnBack = string.Empty; // $"{d.LeftBracket} {btnBackText} {d.RightBracket}";
+ var btnNextText = "Finish"; // "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 - 7)}{d.URDCorner}";
+ var row2 = $"{d.VDLine}{new String (' ', width - 2)}{d.VDLine}";
+ var row3 = row2;
+ var row4 = row3;
+ 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 };
+ wizard.AddStep (new Wizard.WizardStep (stepTitle));
+ //wizard.LayoutSubviews ();
+ var firstIteration = false;
+ var runstate = Application.Begin (wizard);
+ Application.RunMainLoopIteration (ref runstate, true, ref firstIteration);
+
+ GraphViewTests.AssertDriverContentsWithFrameAre ($"{topRow}\n{row2}\n{row3}\n{row4}\n{separatorRow}\n{buttonRow}\n{bottomRow}", output);
+ Application.End (runstate);
}
[Fact, AutoInitShutdown]
@@ -150,7 +181,7 @@ namespace Terminal.Gui.Views {
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 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}";