using System.Text; namespace UICatalog.Scenarios; [ScenarioMetadata ("Buttons", "Demonstrates all sorts of Buttons.")] [ScenarioCategory ("Controls")] [ScenarioCategory ("Layout")] public class Buttons : Scenario { public override void Main () { Application.Init (); using IApplication app = Application.Instance; using Window main = new (); main.Title = GetQuitKeyAndName (); // Add a label & text field so we can demo IsDefault Label editLabel = new () { X = 0, Y = 0, Text = "TextField (to demo IsDefault):" }; main.Add (editLabel); // Add a TextField using Absolute layout. TextField edit = new () { X = 31, Width = 15, HotKey = Key.Y.WithAlt }; main.Add (edit); // This is the default button (IsDefault = true); if user presses ENTER in the TextField // the scenario will quit Button defaultButton = new () { X = Pos.Center (), Y = Pos.AnchorEnd (), IsDefault = true, Text = "_Quit" }; main.Add (defaultButton); // Note we handle Accept on main, not defaultButton main.Accepting += (s, _) => (s as View)?.App!.RequestStop (); Button swapButton = new () { X = 50, Width = 45, Height = 3, Text = "S_wap Default (Size = 45, 3)", SchemeName = "Error" }; swapButton.Accepting += (_, e) => { e.Handled = !swapButton.IsDefault; defaultButton.IsDefault = !defaultButton.IsDefault; swapButton.IsDefault = !swapButton.IsDefault; }; defaultButton.Accepting += (s, e) => { e.Handled = !defaultButton.IsDefault; if (e.Handled) { MessageBox.ErrorQuery ( (s as View)?.App!, "Error", "This button is no longer the Quit button; the Swap Default button is.", "_Ok"); } }; main.Add (swapButton); Label colorButtonsLabel = new () { X = 0, Y = Pos.Bottom (swapButton) + 1, Text = "Color Buttons: " }; main.Add (colorButtonsLabel); View prev = colorButtonsLabel; foreach (KeyValuePair scheme in SchemeManager.GetSchemesForCurrentTheme ()) { Button colorButton = new () { X = Pos.Right (prev), Y = Pos.Y (colorButtonsLabel), Text = $"_{scheme.Key}", SchemeName = scheme.Key }; DoMessage (colorButton, colorButton.Text); main.Add (colorButton); prev = colorButton; } Button button; main.Add ( button = new () { X = 2, Y = Pos.Bottom (colorButtonsLabel) + 1, Text = "A super l_öng Button that will probably expose a bug in clipping or wrapping of text. Will it?" } ); DoMessage (button, button.Text); // Note the 'N' in 'Newline' will be the hotkey main.Add ( button = new () { X = 2, Y = Pos.Bottom (button), Height = 2, Text = "a Newline\nin the button" } ); button.Accepting += (s, e) => { MessageBox.Query ((s as View)?.App!, "Message", "Is There A Question?", "Yes", "No"); e.Handled = true; }; var textChanger = new Button { X = 2, Y = Pos.Bottom (button), Text = "Te_xt Changer" }; main.Add (textChanger); textChanger.Accepting += (_, e) => { textChanger.Text += "!"; e.Handled = true; }; main.Add ( button = new () { X = Pos.Right (textChanger) + 2, Y = Pos.Y (textChanger), Text = """This will move as "Text Changer" grows""" } ); button.Accepting += (_, args) => { args.Handled = true; }; Button removeButton = new () { X = 2, Y = Pos.Bottom (button), SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Error), Title = "Press to remove this button" }; main.Add (removeButton); // This in interesting test case because `moveBtn` and below are laid out relative to this one! removeButton.Accepting += (_, e) => { removeButton.Visible = false; e.Handled = true; }; FrameView computedFrame = new () { X = 0, Y = Pos.Bottom (removeButton), Width = Dim.Percent (50), Height = 6, Title = "Frame (Width = 50%)" }; main.Add (computedFrame); // Demonstrates how changing the View.Frame property can move Views Button moveBtn = new () { X = 0, Y = Pos.Center () - 1, Width = 30, SchemeName = "Error", Text = "Move This \u263b Button v_ia Pos" }; moveBtn.Accepting += (_, e) => { moveBtn.X = moveBtn.Frame.X + 5; e.Handled = true; }; computedFrame.Add (moveBtn); // Demonstrates how changing the View.Frame property can SIZE Views (#583) Button sizeBtn = new () { Y = Pos.Center () + 1, X = 0, Width = 30, Text = "Grow This \u263a Button _via Pos", SchemeName = "Error" }; sizeBtn.Accepting += (_, e) => { sizeBtn.Width = sizeBtn.Frame.Width + 5; e.Handled = true; }; computedFrame.Add (sizeBtn); FrameView absoluteFrame = new () { X = Pos.Right (computedFrame), Y = Pos.Top (computedFrame), Width = Dim.Fill (), Height = Dim.Height (computedFrame), Title = "Frame (Width = Fill)" }; main.Add (absoluteFrame); // Demonstrates how changing the View.Frame property can move Views Button moveBtnA = new () { SchemeName = "Error", Text = "Move This Button via Frame" }; moveBtnA.Accepting += (_, e) => { moveBtnA.Frame = moveBtnA.Frame with { X = moveBtnA.Frame.X + 5 }; e.Handled = true; }; absoluteFrame.Add (moveBtnA); // Demonstrates how changing the View.Frame property can SIZE Views (#583) Button sizeBtnA = new () { Y = 2, SchemeName = "Error", Text = " ~  s  gui.cs   main ↑_10 = Сохранить" }; sizeBtnA.Accepting += (_, e) => { sizeBtnA.Frame = sizeBtnA.Frame with { Width = sizeBtnA.Frame.Width + 5 }; e.Handled = true; }; absoluteFrame.Add (sizeBtnA); Label label = new () { X = 2, Y = Pos.Bottom (computedFrame), // ReSharper disable once StringLiteralTypo Text = "Text Ali_gnment (changes all buttons): " }; main.Add (label); OptionSelector osAlignment = new () { X = Pos.Right (label) + 1, Y = Pos.Top (label), Width = 20, Value = Alignment.Center, AssignHotKeys = true, Title = "_9 OptionSelector", BorderStyle = LineStyle.Dotted // CanFocus = false }; main.Add (osAlignment); // Demo changing hotkey string MoveHotkey (string txt) { // Remove the '_' List runes = txt.ToRuneList (); int i = runes.IndexOf ((Rune)'_'); var start = ""; if (i > -1) { start = StringExtensions.ToString (runes.GetRange (0, i)); } txt = start + StringExtensions.ToString (runes.GetRange (i + 1, runes.Count - (i + 1))); runes = txt.ToRuneList (); // Move over one or go to start i++; if (i >= runes.Count) { i = 0; } // Slip in the '_' start = StringExtensions.ToString (runes.GetRange (0, i)); return start + '_' + StringExtensions.ToString (runes.GetRange (i, runes.Count - i)); } Button moveHotKeyBtn = new () { X = 2, Y = Pos.Bottom (osAlignment), Width = Dim.Width (computedFrame) - 2, SchemeName = "Runnable", Text = "Click to Change th_is Button's Hotkey" }; moveHotKeyBtn.Accepting += (_, e) => { moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text); e.Handled = true; }; main.Add (moveHotKeyBtn); Button moveUnicodeHotKeyBtn = new () { X = Pos.Left (absoluteFrame) + 1, Y = Pos.Bottom (osAlignment), Width = Dim.Width (absoluteFrame) - 2, SchemeName = "Runnable", Text = " ~  s  gui.cs   main ↑10 = Сохранить" }; moveUnicodeHotKeyBtn.Accepting += (_, e) => { moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text); e.Handled = true; }; main.Add (moveUnicodeHotKeyBtn); osAlignment.ValueChanged += (_, args) => { if (args.Value is null) { return; } // ReSharper disable once AccessToDisposedClosure SetTextAlignmentForAllButtons (main, args.Value.Value); }; label = new () { X = 0, Y = Pos.Bottom (moveUnicodeHotKeyBtn) + 1, Title = "Numeric Up/Down (press-and-_hold):" }; NumericUpDown numericUpDown = new () { Value = 69, X = Pos.Right (label) + 1, Y = Pos.Top (label) }; numericUpDown.ValueChanged += NumericUpDownValueChanged; void NumericUpDownValueChanged (object sender, EventArgs e) { } main.Add (label, numericUpDown); label = new () { X = 0, Y = Pos.Bottom (numericUpDown), // ReSharper disable once StringLiteralTypo Title = "No Repea_t:" }; var noRepeatAcceptCount = 0; Button noRepeatButton = new () { X = Pos.Right (label) + 1, Y = Pos.Top (label), Title = $"Accepting Count: {noRepeatAcceptCount}", WantContinuousButtonPressed = false }; noRepeatButton.Accepting += (_, e) => { noRepeatButton.Title = $"Accepting Count: {++noRepeatAcceptCount}"; Logging.Trace ("noRepeatButton Button Pressed"); e.Handled = true; }; main.Add (label, noRepeatButton); label = new () { X = Pos.Right (noRepeatButton) + 1, Y = Pos.Top (label), Title = "N_o Repeat (no highlight):" }; var noRepeatNoHighlightAcceptCount = 0; Button noRepeatNoHighlight = new () { X = Pos.Right (label) + 1, Y = Pos.Top (label), Title = $"Accepting Count: {noRepeatNoHighlightAcceptCount}", WantContinuousButtonPressed = false, HighlightStates = MouseState.None }; noRepeatNoHighlight.Accepting += (_, e) => { noRepeatNoHighlight.Title = $"Accepting Count: {++noRepeatNoHighlightAcceptCount}"; Logging.Trace ("noRepeatNoHighlight Button Pressed"); e.Handled = true; }; main.Add (label, noRepeatNoHighlight); label = new () { X = 0, Y = Pos.Bottom (noRepeatNoHighlight), Title = "Repeat (_press-and-hold):" }; var repeatButtonAcceptingCount = 0; Button repeatButton = new () { Id = "repeatButton", X = Pos.Right (label) + 1, Y = Pos.Top (label), Title = $"Accepting Co_unt: {repeatButtonAcceptingCount}", WantContinuousButtonPressed = true }; repeatButton.Accepting += (_, e) => { repeatButton.Title = $"Accepting Co_unt: {++repeatButtonAcceptingCount}"; e.Handled = true; }; CheckBox enableCb = new () { X = Pos.Right (repeatButton) + 1, Y = Pos.Top (repeatButton), Title = "Enabled", CheckedState = CheckState.Checked }; enableCb.CheckedStateChanging += (_, _) => { repeatButton.Enabled = !repeatButton.Enabled; }; main.Add (label, repeatButton, enableCb); NumericUpDown decNumericUpDown = new () { // ReSharper disable once StringLiteralTypo Title = "Hexadecima_l", Value = 911, Increment = 1, Format = "{0:X}", X = 0, Y = Pos.Bottom (repeatButton), BorderStyle = LineStyle.Single, Width = 15 }; main.Add (decNumericUpDown); app.Run (main); return; static void DoMessage (Button button, string txt) { button.Accepting += (s, e) => { MessageBox.Query ((s as View)?.App!, "Message", $"Did you click {txt}?", "Yes", "No"); e.Handled = true; }; } } private static void SetTextAlignmentForAllButtons (View root, Alignment alignment) { foreach (Button button in GetAllSubViewsOfType