diff --git a/Terminal.Gui/Drawing/Aligner.cs b/Terminal.Gui/Drawing/Aligner.cs index df880bbfb..4ffcc573f 100644 --- a/Terminal.Gui/Drawing/Aligner.cs +++ b/Terminal.Gui/Drawing/Aligner.cs @@ -14,7 +14,7 @@ public class Aligner : INotifyPropertyChanged /// /// /// - /// provides additional options for aligning items in a container. + /// provides additional options for aligning items in a container. /// /// public Alignment Alignment @@ -32,13 +32,13 @@ public class Aligner : INotifyPropertyChanged /// /// Gets or sets the modes controlling . /// - public AlignmentModes AlignmentMode + public AlignmentModes AlignmentModes { get => _alignmentMode; set { _alignmentMode = value; - PropertyChanged?.Invoke (this, new (nameof (AlignmentMode))); + PropertyChanged?.Invoke (this, new (nameof (AlignmentModes))); } } @@ -62,11 +62,11 @@ public class Aligner : INotifyPropertyChanged /// /// Takes a list of item sizes and returns a list of the positions of those items when aligned within - /// using the and settings. + /// using the and settings. /// /// The sizes of the items to align. /// The locations of the items, from left/top to right/bottom. - public int [] Align (int [] sizes) { return Align (Alignment, AlignmentMode, ContainerSize, sizes); } + public int [] Align (int [] sizes) { return Align (Alignment, AlignmentModes, ContainerSize, sizes); } /// /// Takes a list of item sizes and returns a list of the positions of those items when aligned within diff --git a/Terminal.Gui/Resources/config.json b/Terminal.Gui/Resources/config.json index 975605419..8380a14f5 100644 --- a/Terminal.Gui/Resources/config.json +++ b/Terminal.Gui/Resources/config.json @@ -25,6 +25,7 @@ { "Default": { "Dialog.DefaultButtonAlignment": "End", + "Dialog.DefaultButtonAlignmentModes": "AddSpaceBetweenItems", "FrameView.DefaultBorderStyle": "Single", "Window.DefaultBorderStyle": "Single", "ColorSchemes": [ diff --git a/Terminal.Gui/View/Layout/Pos.cs b/Terminal.Gui/View/Layout/Pos.cs index 2e630e812..ccd782ba8 100644 --- a/Terminal.Gui/View/Layout/Pos.cs +++ b/Terminal.Gui/View/Layout/Pos.cs @@ -145,15 +145,15 @@ public abstract class Pos /// Creates a object that aligns a set of views according to the specified alignment setting. /// /// The alignment. - /// The optional alignment modes. + /// The optional alignment modes. /// /// The optional, unique identifier for the set of views to align according to /// . /// /// - public static Pos Align (Alignment alignment, AlignmentModes mode = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems, int groupId = 0) + public static Pos Align (Alignment alignment, AlignmentModes modes = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems, int groupId = 0) { - return new PosAlign (alignment, mode, groupId); + return new PosAlign (alignment, modes, groupId); } /// diff --git a/Terminal.Gui/View/Layout/PosAlign.cs b/Terminal.Gui/View/Layout/PosAlign.cs index 1c829295a..62afa2beb 100644 --- a/Terminal.Gui/View/Layout/PosAlign.cs +++ b/Terminal.Gui/View/Layout/PosAlign.cs @@ -114,12 +114,12 @@ public class PosAlign : Pos /// Enables alignment of a set of views. /// /// - /// + /// /// The unique identifier for the set of views to align according to . - public PosAlign (Alignment alignment, AlignmentModes mode = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems, int groupId = 0) + public PosAlign (Alignment alignment, AlignmentModes modes = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems, int groupId = 0) { Aligner.Alignment = alignment; - Aligner.AlignmentMode = mode; + Aligner.AlignmentModes = modes; _groupId = groupId; Aligner.PropertyChanged += Aligner_PropertyChanged; } diff --git a/Terminal.Gui/Views/Dialog.cs b/Terminal.Gui/Views/Dialog.cs index 9876ec3ba..70d0f2502 100644 --- a/Terminal.Gui/Views/Dialog.cs +++ b/Terminal.Gui/Views/Dialog.cs @@ -52,6 +52,7 @@ public class Dialog : Window Modal = true; ButtonAlignment = DefaultButtonAlignment; + ButtonAlignmentModes = DefaultButtonAlignmentModes; AddCommand ( Command.QuitToplevel, @@ -100,6 +101,11 @@ public class Dialog : Window /// Determines how the s are aligned along the bottom of the dialog. public Alignment ButtonAlignment { get; set; } + /// + /// Gets or sets the alignment modes for the dialog's buttons. + /// + public AlignmentModes ButtonAlignmentModes { get; set; } + /// Optional buttons to lay out at the bottom of the dialog. public Button [] Buttons { @@ -124,6 +130,12 @@ public class Dialog : Window [JsonConverter (typeof (JsonStringEnumConverter))] public static Alignment DefaultButtonAlignment { get; set; } = Alignment.End; + /// The default for . + /// This property can be set in a Theme. + [SerializableConfigurationProperty (Scope = typeof (ThemeScope))] + [JsonConverter (typeof (JsonStringEnumConverter))] + public static AlignmentModes DefaultButtonAlignmentModes { get; set; } = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems; + /// /// Adds a to the , its layout will be controlled by the /// @@ -136,7 +148,8 @@ public class Dialog : Window return; } - button.X = Pos.Align (ButtonAlignment); + // Use a distinct GroupId so users can use Pos.Align for other views in the Dialog + button.X = Pos.Align (ButtonAlignment, ButtonAlignmentModes, groupId: GetHashCode ()); button.Y = Pos.AnchorEnd (); _buttons.Add (button); diff --git a/Terminal.Gui/Views/MessageBox.cs b/Terminal.Gui/Views/MessageBox.cs index e8d70d65e..10a40ec39 100644 --- a/Terminal.Gui/Views/MessageBox.cs +++ b/Terminal.Gui/Views/MessageBox.cs @@ -340,17 +340,16 @@ public static class MessageBox } } - Alignment buttonJust = Dialog.DefaultButtonAlignment; - Dialog.DefaultButtonAlignment = Alignment.Center; var d = new Dialog { + ButtonAlignment = Alignment.Center, + ButtonAlignmentModes = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems, Buttons = buttonList.ToArray (), Title = title, BorderStyle = DefaultBorderStyle, Width = Dim.Auto (DimAutoStyle.Content, minimumContentDim: Dim.Percent(60)), Height = Dim.Auto (DimAutoStyle.Content), }; - Dialog.DefaultButtonAlignment = buttonJust; if (width != 0) { diff --git a/Terminal.Gui/Views/Wizard/Wizard.cs b/Terminal.Gui/Views/Wizard/Wizard.cs index e29a7f5df..deeda162d 100644 --- a/Terminal.Gui/Views/Wizard/Wizard.cs +++ b/Terminal.Gui/Views/Wizard/Wizard.cs @@ -67,7 +67,8 @@ public class Wizard : Dialog public Wizard () { // TODO: LastEndRestStart will enable a "Quit" button to always appear at the far left - // ButtonAlignment = Alignment.LastEndRestStart; + ButtonAlignment = Alignment.Start; + ButtonAlignmentModes |= AlignmentModes.IgnoreFirstOrLast; BorderStyle = LineStyle.Double; //// Add a horiz separator diff --git a/UICatalog/Scenarios/Dialogs.cs b/UICatalog/Scenarios/Dialogs.cs index 5270d3766..dfaf86744 100644 --- a/UICatalog/Scenarios/Dialogs.cs +++ b/UICatalog/Scenarios/Dialogs.cs @@ -146,7 +146,7 @@ public class Dialogs : Scenario }; frame.Add (label); - var labels = new [] { "Start", "End", "Center", "Fill", "FirstStartRestEnd", "LastEndRestStart" }; + var labels = Enum.GetNames (); var alignmentGroup = new RadioGroup { X = Pos.Right (label) + 1, diff --git a/UICatalog/Scenarios/PosAlignDemo.cs b/UICatalog/Scenarios/PosAlignDemo.cs index b38457bb5..b611e829a 100644 --- a/UICatalog/Scenarios/PosAlignDemo.cs +++ b/UICatalog/Scenarios/PosAlignDemo.cs @@ -85,13 +85,13 @@ public sealed class PosAlignDemo : Scenario if (dimension == Dimension.Width) { - ignoreFirstOrLast.Checked = _horizAligner.AlignmentMode.HasFlag (AlignmentModes.IgnoreFirstOrLast); + ignoreFirstOrLast.Checked = _horizAligner.AlignmentModes.HasFlag (AlignmentModes.IgnoreFirstOrLast); ignoreFirstOrLast.X = Pos.Align (_horizAligner.Alignment); ignoreFirstOrLast.Y = Pos.Top (alignRadioGroup); } else { - ignoreFirstOrLast.Checked = _vertAligner.AlignmentMode.HasFlag (AlignmentModes.IgnoreFirstOrLast); + ignoreFirstOrLast.Checked = _vertAligner.AlignmentModes.HasFlag (AlignmentModes.IgnoreFirstOrLast); ignoreFirstOrLast.X = Pos.Left (alignRadioGroup); ignoreFirstOrLast.Y = Pos.Align (_vertAligner.Alignment); } @@ -100,18 +100,18 @@ public sealed class PosAlignDemo : Scenario { if (dimension == Dimension.Width) { - _horizAligner.AlignmentMode = e.NewValue is { } && + _horizAligner.AlignmentModes = e.NewValue is { } && e.NewValue.Value ? - _horizAligner.AlignmentMode | AlignmentModes.IgnoreFirstOrLast : - _horizAligner.AlignmentMode & ~AlignmentModes.IgnoreFirstOrLast; + _horizAligner.AlignmentModes | AlignmentModes.IgnoreFirstOrLast : + _horizAligner.AlignmentModes & ~AlignmentModes.IgnoreFirstOrLast; UpdatePosAlignObjects (appWindow, dimension, _horizAligner); } else { - _vertAligner.AlignmentMode = e.NewValue is { } && + _vertAligner.AlignmentModes = e.NewValue is { } && e.NewValue.Value ? - _vertAligner.AlignmentMode | AlignmentModes.IgnoreFirstOrLast : - _vertAligner.AlignmentMode & ~AlignmentModes.IgnoreFirstOrLast; + _vertAligner.AlignmentModes | AlignmentModes.IgnoreFirstOrLast : + _vertAligner.AlignmentModes & ~AlignmentModes.IgnoreFirstOrLast; UpdatePosAlignObjects (appWindow, dimension, _vertAligner); } }; @@ -125,13 +125,13 @@ public sealed class PosAlignDemo : Scenario if (dimension == Dimension.Width) { - addSpacesBetweenItems.Checked = _horizAligner.AlignmentMode.HasFlag (AlignmentModes.AddSpaceBetweenItems); + addSpacesBetweenItems.Checked = _horizAligner.AlignmentModes.HasFlag (AlignmentModes.AddSpaceBetweenItems); addSpacesBetweenItems.X = Pos.Align (_horizAligner.Alignment); addSpacesBetweenItems.Y = Pos.Top (alignRadioGroup); } else { - addSpacesBetweenItems.Checked = _vertAligner.AlignmentMode.HasFlag (AlignmentModes.AddSpaceBetweenItems); + addSpacesBetweenItems.Checked = _vertAligner.AlignmentModes.HasFlag (AlignmentModes.AddSpaceBetweenItems); addSpacesBetweenItems.X = Pos.Left (alignRadioGroup); addSpacesBetweenItems.Y = Pos.Align (_vertAligner.Alignment); } @@ -140,18 +140,18 @@ public sealed class PosAlignDemo : Scenario { if (dimension == Dimension.Width) { - _horizAligner.AlignmentMode = e.NewValue is { } && + _horizAligner.AlignmentModes = e.NewValue is { } && e.NewValue.Value ? - _horizAligner.AlignmentMode | AlignmentModes.AddSpaceBetweenItems : - _horizAligner.AlignmentMode & ~AlignmentModes.AddSpaceBetweenItems; + _horizAligner.AlignmentModes | AlignmentModes.AddSpaceBetweenItems : + _horizAligner.AlignmentModes & ~AlignmentModes.AddSpaceBetweenItems; UpdatePosAlignObjects (appWindow, dimension, _horizAligner); } else { - _vertAligner.AlignmentMode = e.NewValue is { } && + _vertAligner.AlignmentModes = e.NewValue is { } && e.NewValue.Value ? - _vertAligner.AlignmentMode | AlignmentModes.AddSpaceBetweenItems : - _vertAligner.AlignmentMode & ~AlignmentModes.AddSpaceBetweenItems; + _vertAligner.AlignmentModes | AlignmentModes.AddSpaceBetweenItems : + _vertAligner.AlignmentModes & ~AlignmentModes.AddSpaceBetweenItems; UpdatePosAlignObjects (appWindow, dimension, _vertAligner); } @@ -282,7 +282,7 @@ public sealed class PosAlignDemo : Scenario PosAlign posAlign = view.X as PosAlign; view.X = new PosAlign ( aligner.Alignment, - aligner.AlignmentMode, + aligner.AlignmentModes, posAlign!.GroupId); view.Margin.Thickness = new (_leftMargin, 0, 0, 0); @@ -292,7 +292,7 @@ public sealed class PosAlignDemo : Scenario PosAlign posAlign = view.Y as PosAlign; view.Y = new PosAlign ( aligner.Alignment, - aligner.AlignmentMode, + aligner.AlignmentModes, posAlign!.GroupId); @@ -322,7 +322,7 @@ public sealed class PosAlignDemo : Scenario container.Padding.Thickness = new Thickness (8, 1, 0, 0); container.Padding.ColorScheme = Colors.ColorSchemes ["error"]; - Aligner widthAligner = new () { AlignmentMode = AlignmentModes.StartToEnd }; + Aligner widthAligner = new () { AlignmentModes = AlignmentModes.StartToEnd }; RadioGroup widthAlignRadioGroup = new () { RadioLabels = Enum.GetNames (), @@ -338,7 +338,7 @@ public sealed class PosAlignDemo : Scenario UpdatePosAlignObjects (container, Dimension.Width, widthAligner); }; - Aligner heightAligner = new () { AlignmentMode = AlignmentModes.StartToEnd }; + Aligner heightAligner = new () { AlignmentModes = AlignmentModes.StartToEnd }; RadioGroup heightAlignRadioGroup = new () { RadioLabels = Enum.GetNames (), @@ -365,8 +365,8 @@ public sealed class PosAlignDemo : Scenario Width = 5 }; - v.X = Pos.Align (widthAligner.Alignment, widthAligner.AlignmentMode, groupId: i / 3); - v.Y = Pos.Align (heightAligner.Alignment,heightAligner.AlignmentMode, groupId: i % 3 + 10); + v.X = Pos.Align (widthAligner.Alignment, widthAligner.AlignmentModes, groupId: i / 3); + v.Y = Pos.Align (heightAligner.Alignment,heightAligner.AlignmentModes, groupId: i % 3 + 10); container.Add (v); } diff --git a/UnitTests/Drawing/AlignerTests.cs b/UnitTests/Drawing/AlignerTests.cs index d0d56520c..e4370556c 100644 --- a/UnitTests/Drawing/AlignerTests.cs +++ b/UnitTests/Drawing/AlignerTests.cs @@ -383,7 +383,7 @@ public class AlignerTests (ITestOutputHelper output) int [] positions = new Aligner { Alignment = alignment, - AlignmentMode = AlignmentModes.StartToEnd | modes, + AlignmentModes = AlignmentModes.StartToEnd | modes, ContainerSize = containerSize }.Align (sizes); AssertAlignment (alignment, sizes, containerSize, positions, expected);