123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Terminal.Gui;
- namespace UICatalog.Scenarios;
- [ScenarioMetadata ("Pos.Align", "Demonstrates Pos.Align")]
- [ScenarioCategory ("Layout")]
- public sealed class PosAlignDemo : Scenario
- {
- private readonly Aligner _horizAligner = new () { AlignmentModes = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems};
- private int _leftMargin;
- private readonly Aligner _vertAligner = new () { AlignmentModes = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems };
- private int _topMargin;
- public override void Main ()
- {
- // Init
- Application.Init ();
- // Setup - Create a top-level application window and configure it.
- Window appWindow = new ()
- {
- Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()} - {GetDescription ()}"
- };
- SetupControls (appWindow, Dimension.Width, Colors.ColorSchemes ["TopLevel"]);
- SetupControls (appWindow, Dimension.Height, Colors.ColorSchemes ["Error"]);
- Setup3By3Grid (appWindow);
- // Run - Start the application.
- Application.Run (appWindow);
- appWindow.Dispose ();
- // Shutdown - Calling Application.Shutdown is required.
- Application.Shutdown ();
- }
- private void SetupControls (Window appWindow, Dimension dimension, ColorScheme colorScheme)
- {
- RadioGroup alignRadioGroup = new ()
- {
- RadioLabels = Enum.GetNames<Alignment> (),
- ColorScheme = colorScheme
- };
- if (dimension == Dimension.Width)
- {
- alignRadioGroup.X = Pos.Align (_horizAligner.Alignment);
- alignRadioGroup.Y = Pos.Center ();
- }
- else
- {
- alignRadioGroup.X = Pos.Center ();
- alignRadioGroup.Y = Pos.Align (_vertAligner.Alignment);
- }
- alignRadioGroup.SelectedItemChanged += (s, e) =>
- {
- if (dimension == Dimension.Width)
- {
- _horizAligner.Alignment =
- (Alignment)Enum.Parse (
- typeof (Alignment),
- alignRadioGroup.RadioLabels [alignRadioGroup.SelectedItem]);
- UpdatePosAlignObjects (appWindow, dimension, _horizAligner);
- }
- else
- {
- _vertAligner.Alignment =
- (Alignment)Enum.Parse (
- typeof (Alignment),
- alignRadioGroup.RadioLabels [alignRadioGroup.SelectedItem]);
- UpdatePosAlignObjects (appWindow, dimension, _vertAligner);
- }
- };
- appWindow.Add (alignRadioGroup);
- CheckBox endToStartCheckBox = new ()
- {
- ColorScheme = colorScheme,
- Text = "EndToStart"
- };
- if (dimension == Dimension.Width)
- {
- endToStartCheckBox.State = _horizAligner.AlignmentModes.HasFlag (AlignmentModes.EndToStart) ? CheckState.Checked : CheckState.UnChecked;
- endToStartCheckBox.X = Pos.Align (_horizAligner.Alignment);
- endToStartCheckBox.Y = Pos.Top (alignRadioGroup);
- }
- else
- {
- endToStartCheckBox.State = _vertAligner.AlignmentModes.HasFlag (AlignmentModes.EndToStart) ? CheckState.Checked : CheckState.UnChecked;
- endToStartCheckBox.X = Pos.Left (alignRadioGroup);
- endToStartCheckBox.Y = Pos.Align (_vertAligner.Alignment);
- }
- endToStartCheckBox.Toggle += (s, e) =>
- {
- if (dimension == Dimension.Width)
- {
- _horizAligner.AlignmentModes = e.NewValue == CheckState.Checked
- ? _horizAligner.AlignmentModes | AlignmentModes.EndToStart
- : _horizAligner.AlignmentModes & ~AlignmentModes.EndToStart;
- UpdatePosAlignObjects (appWindow, dimension, _horizAligner);
- }
- else
- {
- _vertAligner.AlignmentModes = e.NewValue == CheckState.Checked
- ? _vertAligner.AlignmentModes | AlignmentModes.EndToStart
- : _vertAligner.AlignmentModes & ~AlignmentModes.EndToStart;
- UpdatePosAlignObjects (appWindow, dimension, _vertAligner);
- }
- };
- appWindow.Add (endToStartCheckBox);
- CheckBox ignoreFirstOrLast = new ()
- {
- ColorScheme = colorScheme,
- Text = "IgnoreFirstOrLast"
- };
- if (dimension == Dimension.Width)
- {
- ignoreFirstOrLast.State = _horizAligner.AlignmentModes.HasFlag (AlignmentModes.IgnoreFirstOrLast) ? CheckState.Checked : CheckState.UnChecked;
- ignoreFirstOrLast.X = Pos.Align (_horizAligner.Alignment);
- ignoreFirstOrLast.Y = Pos.Top (alignRadioGroup);
- }
- else
- {
- ignoreFirstOrLast.State = _vertAligner.AlignmentModes.HasFlag (AlignmentModes.IgnoreFirstOrLast) ? CheckState.Checked : CheckState.UnChecked;
- ignoreFirstOrLast.X = Pos.Left (alignRadioGroup);
- ignoreFirstOrLast.Y = Pos.Align (_vertAligner.Alignment);
- }
- ignoreFirstOrLast.Toggle += (s, e) =>
- {
- if (dimension == Dimension.Width)
- {
- _horizAligner.AlignmentModes = e.NewValue == CheckState.Checked
- ? _horizAligner.AlignmentModes | AlignmentModes.IgnoreFirstOrLast
- : _horizAligner.AlignmentModes & ~AlignmentModes.IgnoreFirstOrLast;
- UpdatePosAlignObjects (appWindow, dimension, _horizAligner);
- }
- else
- {
- _vertAligner.AlignmentModes = e.NewValue == CheckState.Checked
- ? _vertAligner.AlignmentModes | AlignmentModes.IgnoreFirstOrLast
- : _vertAligner.AlignmentModes & ~AlignmentModes.IgnoreFirstOrLast;
- UpdatePosAlignObjects (appWindow, dimension, _vertAligner);
- }
- };
- appWindow.Add (ignoreFirstOrLast);
- CheckBox addSpacesBetweenItems = new ()
- {
- ColorScheme = colorScheme,
- Text = "AddSpaceBetweenItems"
- };
- if (dimension == Dimension.Width)
- {
- addSpacesBetweenItems.State = _horizAligner.AlignmentModes.HasFlag (AlignmentModes.AddSpaceBetweenItems) ? CheckState.Checked : CheckState.UnChecked;
- addSpacesBetweenItems.X = Pos.Align (_horizAligner.Alignment);
- addSpacesBetweenItems.Y = Pos.Top (alignRadioGroup);
- }
- else
- {
- addSpacesBetweenItems.State = _vertAligner.AlignmentModes.HasFlag (AlignmentModes.AddSpaceBetweenItems) ? CheckState.Checked : CheckState.UnChecked;
- addSpacesBetweenItems.X = Pos.Left (alignRadioGroup);
- addSpacesBetweenItems.Y = Pos.Align (_vertAligner.Alignment);
- }
- addSpacesBetweenItems.Toggle += (s, e) =>
- {
- if (dimension == Dimension.Width)
- {
- _horizAligner.AlignmentModes = e.NewValue == CheckState.Checked
- ? _horizAligner.AlignmentModes | AlignmentModes.AddSpaceBetweenItems
- : _horizAligner.AlignmentModes & ~AlignmentModes.AddSpaceBetweenItems;
- UpdatePosAlignObjects (appWindow, dimension, _horizAligner);
- }
- else
- {
- _vertAligner.AlignmentModes = e.NewValue == CheckState.Checked
- ? _vertAligner.AlignmentModes | AlignmentModes.AddSpaceBetweenItems
- : _vertAligner.AlignmentModes & ~AlignmentModes.AddSpaceBetweenItems;
- UpdatePosAlignObjects (appWindow, dimension, _vertAligner);
- }
- };
- appWindow.Add (addSpacesBetweenItems);
- CheckBox margin = new ()
- {
- ColorScheme = colorScheme,
- Text = "Margin"
- };
- if (dimension == Dimension.Width)
- {
- margin.X = Pos.Align (_horizAligner.Alignment);
- margin.Y = Pos.Top (alignRadioGroup);
- }
- else
- {
- margin.X = Pos.Left (addSpacesBetweenItems);
- margin.Y = Pos.Align (_vertAligner.Alignment);
- }
- margin.Toggle += (s, e) =>
- {
- if (dimension == Dimension.Width)
- {
- _leftMargin = e.NewValue == CheckState.Checked ? 1 : 0;
- UpdatePosAlignObjects (appWindow, dimension, _horizAligner);
- }
- else
- {
- _topMargin = e.NewValue == CheckState.Checked ? 1 : 0;
- UpdatePosAlignObjects (appWindow, dimension, _vertAligner);
- }
- };
- appWindow.Add (margin);
- List<Button> addedViews =
- [
- new ()
- {
- X = dimension == Dimension.Width ? Pos.Align (_horizAligner.Alignment) : Pos.Left (alignRadioGroup),
- Y = dimension == Dimension.Width ? Pos.Top (alignRadioGroup) : Pos.Align (_vertAligner.Alignment),
- Text = NumberToWords.Convert (0)
- }
- ];
- Buttons.NumericUpDown<int> addedViewsUpDown = new()
- {
- Width = 9,
- Title = "Added",
- ColorScheme = colorScheme,
- BorderStyle = LineStyle.None,
- Value = addedViews.Count
- };
- if (dimension == Dimension.Width)
- {
- addedViewsUpDown.X = Pos.Align (_horizAligner.Alignment);
- addedViewsUpDown.Y = Pos.Top (alignRadioGroup);
- addedViewsUpDown.Border.Thickness = new (0, 1, 0, 0);
- }
- else
- {
- addedViewsUpDown.X = Pos.Left (alignRadioGroup);
- addedViewsUpDown.Y = Pos.Align (_vertAligner.Alignment);
- addedViewsUpDown.Border.Thickness = new (1, 0, 0, 0);
- }
- addedViewsUpDown.ValueChanging += (s, e) =>
- {
- if (e.NewValue < 0)
- {
- e.Cancel = true;
- return;
- }
- // Add or remove buttons
- if (e.NewValue < e.CurrentValue)
- {
- // Remove buttons
- for (int i = e.CurrentValue - 1; i >= e.NewValue; i--)
- {
- Button button = addedViews [i];
- appWindow.Remove (button);
- addedViews.RemoveAt (i);
- button.Dispose ();
- }
- }
- if (e.NewValue > e.CurrentValue)
- {
- // Add buttons
- for (int i = e.CurrentValue; i < e.NewValue; i++)
- {
- var button = new Button
- {
- X = dimension == Dimension.Width ? Pos.Align (_horizAligner.Alignment) : Pos.Left (alignRadioGroup),
- Y = dimension == Dimension.Width ? Pos.Top (alignRadioGroup) : Pos.Align (_vertAligner.Alignment),
- Text = NumberToWords.Convert (i + 1)
- };
- appWindow.Add (button);
- addedViews.Add (button);
- }
- }
- };
- appWindow.Add (addedViewsUpDown);
- appWindow.Add (addedViews [0]);
- }
- private void UpdatePosAlignObjects (View superView, Dimension dimension, Aligner aligner)
- {
- foreach (View view in superView.Subviews.Where (v => dimension == Dimension.Width ? v.X is PosAlign : v.Y is PosAlign))
- {
- if (dimension == Dimension.Width ? view.X is PosAlign : view.Y is PosAlign)
- {
- //posAlign.Aligner.Alignment = _horizAligner.Alignment;
- //posAlign.Aligner.AlignmentMode = _horizAligner.AlignmentMode;
- // BUGBUG: Create and assign a new Pos object because we currently have no way for X to be notified
- // BUGBUG: of changes in the Pos object. See https://github.com/gui-cs/Terminal.Gui/issues/3485
- if (dimension == Dimension.Width)
- {
- var posAlign = view.X as PosAlign;
- view.X = Pos.Align (
- aligner.Alignment,
- aligner.AlignmentModes,
- posAlign!.GroupId);
- view.Margin.Thickness = new (_leftMargin, view.Margin.Thickness.Top, view.Margin.Thickness.Right, view.Margin.Thickness.Bottom);
- }
- else
- {
- var posAlign = view.Y as PosAlign;
- view.Y = Pos.Align (
- aligner.Alignment,
- aligner.AlignmentModes,
- posAlign!.GroupId);
- view.Margin.Thickness = new (view.Margin.Thickness.Left, _topMargin, view.Margin.Thickness.Right, view.Margin.Thickness.Bottom);
- }
- }
- }
- superView.LayoutSubviews ();
- }
- /// <summary>
- /// Creates a 3x3 grid of views with two GroupIds: One for aligning X and one for aligning Y.
- /// Demonstrates using PosAlign to create a grid of views that flow.
- /// </summary>
- /// <param name="appWindow"></param>
- private void Setup3By3Grid (View appWindow)
- {
- var container = new FrameView
- {
- Title = "3 by 3",
- X = Pos.AnchorEnd (),
- Y = Pos.AnchorEnd (),
- Width = Dim.Percent (40),
- Height = Dim.Percent (40)
- };
- container.Padding.Thickness = new (8, 1, 0, 0);
- container.Padding.ColorScheme = Colors.ColorSchemes ["error"];
- Aligner widthAligner = new () { AlignmentModes = AlignmentModes.StartToEnd };
- RadioGroup widthAlignRadioGroup = new ()
- {
- RadioLabels = Enum.GetNames<Alignment> (),
- Orientation = Orientation.Horizontal,
- X = Pos.Center ()
- };
- container.Padding.Add (widthAlignRadioGroup);
- widthAlignRadioGroup.SelectedItemChanged += (sender, e) =>
- {
- widthAligner.Alignment =
- (Alignment)Enum.Parse (
- typeof (Alignment),
- widthAlignRadioGroup.RadioLabels [widthAlignRadioGroup.SelectedItem]);
- UpdatePosAlignObjects (container, Dimension.Width, widthAligner);
- };
- Aligner heightAligner = new () { AlignmentModes = AlignmentModes.StartToEnd };
- RadioGroup heightAlignRadioGroup = new ()
- {
- RadioLabels = Enum.GetNames<Alignment> (),
- Orientation = Orientation.Vertical,
- Y = Pos.Center ()
- };
- container.Padding.Add (heightAlignRadioGroup);
- heightAlignRadioGroup.SelectedItemChanged += (sender, e) =>
- {
- heightAligner.Alignment =
- (Alignment)Enum.Parse (
- typeof (Alignment),
- heightAlignRadioGroup.RadioLabels [heightAlignRadioGroup.SelectedItem]);
- UpdatePosAlignObjects (container, Dimension.Height, heightAligner);
- };
- for (var i = 0; i < 9; i++)
- {
- var v = new View
- {
- Title = $"{i}",
- BorderStyle = LineStyle.Dashed,
- Height = 3,
- Width = 5
- };
- v.X = Pos.Align (widthAligner.Alignment, widthAligner.AlignmentModes, i / 3);
- v.Y = Pos.Align (heightAligner.Alignment, heightAligner.AlignmentModes, i % 3 + 10);
- container.Add (v);
- }
- appWindow.Add (container);
- }
- }
|