Added horizontal scenario stuff

This commit is contained in:
Tig
2024-06-13 08:52:55 -07:00
parent 2a3808a7c0
commit f02ca8abc0
6 changed files with 334 additions and 151 deletions

View File

@@ -1,14 +1,17 @@
#nullable enable #nullable enable
namespace Terminal.Gui; namespace Terminal.Gui;
#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
/// <summary> /// <summary>
/// Provides context for a <see cref="Command"/> that is being invoked. /// Provides context for a <see cref="Command"/> that is being invoked.
/// </summary /// </summary
/// <remarks> /// <remarks>
/// <para> /// <para>
/// To define a <see cref="Command"/> that is invoked with context, /// To define a <see cref="Command"/> that is invoked with context,
/// use <see cref="View.AddCommand(Command,Func{CommandContext,Nullable{bool}})"/> /// use <see cref="View.AddCommand(Command,Func{CommandContext,System.Nullable{bool}})"/>.
/// </para> /// </para>
/// </remarks> /// </remarks>
#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
public record struct CommandContext public record struct CommandContext
{ {
/// <summary> /// <summary>

View File

@@ -336,6 +336,24 @@ public abstract class Pos
/// <returns></returns> /// <returns></returns>
internal virtual bool ReferencesOtherViews () { return false; } internal virtual bool ReferencesOtherViews () { return false; }
public bool Has (Type type, out Pos pos)
{
pos = this;
if (type == GetType())
{
return true;
}
// If we are a PosCombine, we have to check the left and right
// to see if they are of the type we are looking for.
if (this is PosCombine { } combine && (combine.Left.Has (type, out pos) || combine.Right.Has (type, out pos)))
{
return true;
}
return false;
}
#endregion virtual methods #endregion virtual methods
#region operators #region operators

View File

@@ -70,59 +70,67 @@ public class PosAlign : Pos
List<int> dimensionsList = new (); List<int> dimensionsList = new ();
// PERF: If this proves a perf issue, consider caching a ref to this list in each item // PERF: If this proves a perf issue, consider caching a ref to this list in each item
List<View> viewsInGroup = views.Where ( List<PosAlign?> posAligns = views.Select (
v => v =>
{ {
return dimension switch switch (dimension)
{ {
Dimension.Width when v.X is PosAlign alignX => alignX.GroupId == groupId, case Dimension.Width when v.X.Has (typeof (PosAlign), out var pos):
Dimension.Height when v.Y is PosAlign alignY => alignY.GroupId == groupId,
_ => false
};
})
.ToList ();
if (viewsInGroup.Count == 0) if (pos is PosAlign posAlignX && posAlignX.GroupId == groupId)
{ {
return; return posAlignX;
} }
break;
case Dimension.Height when v.Y.Has (typeof (PosAlign), out var pos):
if (pos is PosAlign posAlignY && posAlignY.GroupId == groupId)
{
return posAlignY;
}
break;
}
return null;
})
.ToList ();
// PERF: We iterate over viewsInGroup multiple times here. // PERF: We iterate over viewsInGroup multiple times here.
Aligner? firstInGroup = null; Aligner? firstInGroup = null;
// Update the dimensionList with the sizes of the views // Update the dimensionList with the sizes of the views
for (var index = 0; index < viewsInGroup.Count; index++) for (var index = 0; index < posAligns.Count; index++)
{ {
View view = viewsInGroup [index]; if (posAligns [index] is { })
PosAlign? posAlign = dimension == Dimension.Width ? view.X as PosAlign : view.Y as PosAlign;
if (posAlign is { })
{ {
if (index == 0) if (firstInGroup is null)
{ {
firstInGroup = posAlign.Aligner; firstInGroup = posAligns [index]!.Aligner;
} }
dimensionsList.Add (dimension == Dimension.Width ? view.Frame.Width : view.Frame.Height); dimensionsList.Add (dimension == Dimension.Width ? views [index].Frame.Width : views [index].Frame.Height);
} }
} }
if (firstInGroup is null)
{
return;
}
// Update the first item in the group with the new container size. // Update the first item in the group with the new container size.
firstInGroup!.ContainerSize = size; firstInGroup.ContainerSize = size;
// Align // Align
int [] locations = firstInGroup.Align (dimensionsList.ToArray ()); int [] locations = firstInGroup.Align (dimensionsList.ToArray ());
// Update the cached location for each item // Update the cached location for each item
for (var index = 0; index < viewsInGroup.Count; index++) for (int posIndex = 0, locIndex = 0; posIndex < posAligns.Count; posIndex++)
{ {
View view = viewsInGroup [index]; if (posAligns [posIndex] is { })
PosAlign? align = dimension == Dimension.Width ? view.X as PosAlign : view.Y as PosAlign;
if (align is { })
{ {
align._cachedLocation = locations [index]; posAligns [posIndex]!._cachedLocation = locations [locIndex++];
} }
} }
} }
@@ -168,6 +176,14 @@ public class PosAlign : Pos
return 0; return 0;
} }
// TODO: PosAlign.CalculateMinDimension is a hack. Need to figure out a better way of doing this.
/// <summary>
/// Returns the minimum size a group of views with the same <paramref name="groupId"/> can be.
/// </summary>
/// <param name="groupId"></param>
/// <param name="views"></param>
/// <param name="dimension"></param>
/// <returns></returns>
public static int CalculateMinDimension (int groupId, IList<View> views, Dimension dimension) public static int CalculateMinDimension (int groupId, IList<View> views, Dimension dimension)
{ {
List<int> dimensionsList = new (); List<int> dimensionsList = new ();
@@ -177,11 +193,11 @@ public class PosAlign : Pos
v => v =>
{ {
return dimension switch return dimension switch
{ {
Dimension.Width when v.X is PosAlign alignX => alignX.GroupId == groupId, Dimension.Width when v.X is PosAlign alignX => alignX.GroupId == groupId,
Dimension.Height when v.Y is PosAlign alignY => alignY.GroupId == groupId, Dimension.Height when v.Y is PosAlign alignY => alignY.GroupId == groupId,
_ => false _ => false
}; };
}) })
.ToList (); .ToList ();
@@ -192,8 +208,6 @@ public class PosAlign : Pos
// PERF: We iterate over viewsInGroup multiple times here. // PERF: We iterate over viewsInGroup multiple times here.
Aligner? firstInGroup = null;
// Update the dimensionList with the sizes of the views // Update the dimensionList with the sizes of the views
for (var index = 0; index < viewsInGroup.Count; index++) for (var index = 0; index < viewsInGroup.Count; index++)
{ {
@@ -203,26 +217,11 @@ public class PosAlign : Pos
if (posAlign is { }) if (posAlign is { })
{ {
if (index == 0)
{
firstInGroup = posAlign.Aligner;
//if (!posAlign._cachedLocation.HasValue)
//{
// AlignAndUpdateGroup (groupId, viewsInGroup, dimension, firstInGroup.ContainerSize );
//}
}
dimensionsList.Add (dimension == Dimension.Width ? view.Frame.Width : view.Frame.Height); dimensionsList.Add (dimension == Dimension.Width ? view.Frame.Width : view.Frame.Height);
} }
} }
// Align // Align
var aligner = firstInGroup;
aligner.ContainerSize = dimensionsList.Sum();
int [] locations = aligner.Align (dimensionsList.ToArray ());
return dimensionsList.Sum (); return dimensionsList.Sum ();
} }
} }

View File

@@ -48,7 +48,7 @@ public class ColorPicker : View
private void ColorPicker_MouseClick (object sender, MouseEventEventArgs me) private void ColorPicker_MouseClick (object sender, MouseEventEventArgs me)
{ {
if (CanFocus) // if (CanFocus)
{ {
Cursor = new Point (me.MouseEvent.Position.X / _boxWidth, me.MouseEvent.Position.Y / _boxHeight); Cursor = new Point (me.MouseEvent.Position.X / _boxWidth, me.MouseEvent.Position.Y / _boxHeight);
SetFocus (); SetFocus ();

View File

@@ -27,8 +27,7 @@ namespace Terminal.Gui;
/// right side. /// right side.
/// </para> /// </para>
/// <para> /// <para>
/// The command text can be set by setting the <see cref="CommandView"/>'s Text property or by setting /// The command text can be set by setting the <see cref="CommandView"/>'s Text property.
/// <see cref="View.Title"/>.
/// </para> /// </para>
/// <para> /// <para>
/// The help text can be set by setting the <see cref="HelpText"/> property or by setting <see cref="View.Text"/>. /// The help text can be set by setting the <see cref="HelpText"/> property or by setting <see cref="View.Text"/>.
@@ -59,27 +58,31 @@ public class Shortcut : View
TitleChanged += Shortcut_TitleChanged; // This needs to be set before CommandView is set TitleChanged += Shortcut_TitleChanged; // This needs to be set before CommandView is set
CommandView = new (); CommandView = new ()
{
Width = Dim.Auto (),
Height = Dim.Auto (),
};
HelpView.Id = "_helpView"; HelpView.Id = "_helpView";
HelpView.CanFocus = false; HelpView.CanFocus = false;
SetHelpViewDefaultLayout (); SetHelpViewDefaultLayout ();
Add (HelpView); Add (HelpView);
HelpView.MouseClick += Shortcut_MouseClick;
KeyView.Id = "_keyView"; KeyView.Id = "_keyView";
KeyView.CanFocus = false; KeyView.CanFocus = false;
SetKeyViewDefaultLayout (); SetKeyViewDefaultLayout ();
Add (KeyView); Add (KeyView);
// If the user clicks anywhere on the Shortcut, other than the CommandView, invoke the Command
MouseClick += Shortcut_MouseClick;
HelpView.MouseClick += Shortcut_MouseClick;
KeyView.MouseClick += Shortcut_MouseClick; KeyView.MouseClick += Shortcut_MouseClick;
MouseClick += Shortcut_MouseClick; LayoutStarted += OnLayoutStarted;
Initialized += OnInitialized; Initialized += OnInitialized;
LayoutStarted += OnLayoutStarted;
return; return;
void OnInitialized (object sender, EventArgs e) void OnInitialized (object sender, EventArgs e)
@@ -111,10 +114,19 @@ public class Shortcut : View
// Helper to set Width consistently // Helper to set Width consistently
Dim GetWidthDimAuto () Dim GetWidthDimAuto ()
{ {
// TODO: PosAlign.CalculateMinDimension is a hack. Need to figure out a better way of doing this.
return Dim.Auto (DimAutoStyle.Content, maximumContentDim: Dim.Func (() => PosAlign.CalculateMinDimension (0, Subviews, Dimension.Width))); return Dim.Auto (DimAutoStyle.Content, maximumContentDim: Dim.Func (() => PosAlign.CalculateMinDimension (0, Subviews, Dimension.Width)));
} }
} }
/// <summary>
/// Gets or sets the <see cref="Orientation"/> for this <see cref="Shortcut"/>. The default is
/// <see cref="Orientation.Horizontal"/>, which is ideal for status bars and toolbars. If set to <see cref="Orientation.Vertical"/>,
/// the Shortcut will be configured for vertical layout, which is ideal for menus.
/// </summary>
public Orientation Orientation { get; set; } = Orientation.Horizontal;
// When one of the subviews is "empty" we don't want to show it. So we // When one of the subviews is "empty" we don't want to show it. So we
// Use Add/Remove. We need to be careful to add them in the right order // Use Add/Remove. We need to be careful to add them in the right order
// so Pos.Align works correctly. // so Pos.Align works correctly.
@@ -122,7 +134,7 @@ public class Shortcut : View
{ {
RemoveAll (); RemoveAll ();
if (!string.IsNullOrEmpty (CommandView.Text)) if (CommandView.Visible)
{ {
Add (CommandView); Add (CommandView);
} }
@@ -161,7 +173,7 @@ public class Shortcut : View
if (currentWidth < _minimumDimAutoWidth) if (currentWidth < _minimumDimAutoWidth)
{ {
int delta = _minimumDimAutoWidth.Value - currentWidth; int delta = _minimumDimAutoWidth.Value - currentWidth;
int maxHelpWidth = int.Max (0, HelpView.Text.GetColumns () + 2 - delta); int maxHelpWidth = int.Max (0, HelpView.Text.GetColumns () + Margin.Thickness.Horizontal - delta);
switch (maxHelpWidth) switch (maxHelpWidth)
{ {
@@ -180,13 +192,14 @@ public class Shortcut : View
case 2: case 2:
// Scrunch just the right margin // Scrunch just the right margin
HelpView.Margin.Thickness = new (1, 0, 0, 0); var t = GetMarginThickness ();
HelpView.Margin.Thickness = new (t.Right, t.Top, t.Left - 1, t.Bottom);
break; break;
default: default:
// Default margin // Default margin
HelpView.Margin.Thickness = new (1, 0, 1, 0); HelpView.Margin.Thickness = GetMarginThickness ();
break; break;
} }
@@ -208,6 +221,18 @@ public class Shortcut : View
} }
} }
private Thickness GetMarginThickness ()
{
if (Orientation == Orientation.Vertical)
{
return new Thickness (1, 0, 1, 0);
}
else
{
return new Thickness (1, 0, 1, 0);
}
}
private Color? _savedForeColor; private Color? _savedForeColor;
private void Shortcut_Highlight (object sender, HighlightEventArgs e) private void Shortcut_Highlight (object sender, HighlightEventArgs e)
@@ -339,18 +364,26 @@ public class Shortcut : View
// TODO: Determine if it makes sense to allow the CommandView to be focusable. // TODO: Determine if it makes sense to allow the CommandView to be focusable.
// Right now, we don't set CanFocus to false here. // Right now, we don't set CanFocus to false here.
_commandView.CanFocus = false; //_commandView.CanFocus = true;
//// Bar will set the width of all CommandViews to the width of the widest CommandViews.
////if (_commandView.Width == Dim.Absolute(0))
//{
// _commandView.Width = Dim.Auto ();
//}
////if (_commandView.Height == Dim.Absolute (0))
//{
// _commandView.Height = Dim.Auto ();
//}
// Bar will set the width of all CommandViews to the width of the widest CommandViews.
_commandView.Width = Dim.Auto ();
_commandView.Height = Dim.Auto ();
_commandView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast); _commandView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast);
_commandView.Y = 0; //Pos.Center (); _commandView.Y = 0; //Pos.Center ();
_commandView.MouseClick += Shortcut_MouseClick; _commandView.MouseClick += Shortcut_MouseClick;
_commandView.Accept += CommandViewAccept; _commandView.Accept += CommandViewAccept;
_commandView.Margin.Thickness = new (1, 0, 1, 0); _commandView.Margin.Thickness = GetMarginThickness ();
_commandView.HotKeyChanged += (s, e) => _commandView.HotKeyChanged += (s, e) =>
{ {
@@ -364,7 +397,6 @@ public class Shortcut : View
_commandView.HotKeySpecifier = new ('_'); _commandView.HotKeySpecifier = new ('_');
Title = _commandView.Text; Title = _commandView.Text;
_commandView.TextChanged += CommandViewTextChanged;
SetHelpViewDefaultLayout (); SetHelpViewDefaultLayout ();
SetKeyViewDefaultLayout (); SetKeyViewDefaultLayout ();
@@ -373,8 +405,6 @@ public class Shortcut : View
return; return;
void CommandViewMouseEvent (object sender, MouseEventEventArgs e) { e.Handled = true; }
void CommandViewTextChanged (object sender, StateEventArgs<string> e) void CommandViewTextChanged (object sender, StateEventArgs<string> e)
{ {
Title = _commandView.Text; Title = _commandView.Text;
@@ -417,11 +447,12 @@ public class Shortcut : View
private void SetHelpViewDefaultLayout () private void SetHelpViewDefaultLayout ()
{ {
HelpView.Margin.Thickness = new (1, 0, 1, 0); HelpView.Margin.Thickness = GetMarginThickness ();
HelpView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast); HelpView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast);
HelpView.Y = 0; //Pos.Center (), HelpView.Y = 0; //Pos.Center (),
HelpView.Width = Dim.Auto (DimAutoStyle.Text); HelpView.Width = Dim.Auto (DimAutoStyle.Text);
HelpView.Height = Dim.Height (CommandView); HelpView.Height = CommandView?.IsAdded == true ? Dim.Height (CommandView) : 1;
HelpView.Visible = true; HelpView.Visible = true;
HelpView.VerticalTextAlignment = Alignment.Center; HelpView.VerticalTextAlignment = Alignment.Center;
} }
@@ -537,12 +568,12 @@ public class Shortcut : View
private void SetKeyViewDefaultLayout () private void SetKeyViewDefaultLayout ()
{ {
KeyView.Margin.Thickness = new (1, 0, 1, 0); KeyView.Margin.Thickness = GetMarginThickness();
KeyView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast); KeyView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast);
//KeyView.Y = Pos.Center (); //KeyView.Y = Pos.Center ();
KeyView.Width = Dim.Auto (DimAutoStyle.Text, Dim.Func (GetMinimumKeyViewSize)); KeyView.Width = Dim.Auto (DimAutoStyle.Text, Dim.Func (GetMinimumKeyViewSize));
KeyView.Height = Dim.Height (CommandView); KeyView.Height = CommandView?.IsAdded == true ? Dim.Height (CommandView) : 1;
KeyView.Visible = true; KeyView.Visible = true;
// Right align the text in the keyview // Right align the text in the keyview
@@ -582,6 +613,7 @@ public class Shortcut : View
switch (KeyBindingScope) switch (KeyBindingScope)
{ {
case KeyBindingScope.Application: case KeyBindingScope.Application:
handled = false;
break; break;
case KeyBindingScope.Focused: case KeyBindingScope.Focused:
@@ -663,18 +695,9 @@ public class Shortcut : View
/// <inheritdoc/> /// <inheritdoc/>
public override bool OnLeave (View view) public override bool OnLeave (View view)
{ {
// Reset the color scheme (to SuperView).
ColorScheme = null; ColorScheme = null;
return base.OnLeave (view);
if (SuperView is { })
{
ColorScheme = new (SuperView?.ColorScheme)
{
Normal = SuperView.ColorScheme.Normal,
HotNormal = SuperView.ColorScheme.HotNormal
};
}
return base.OnLeave (view); return base.OnLeave (view);
} }

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Timers;
using Terminal.Gui; using Terminal.Gui;
namespace UICatalog.Scenarios; namespace UICatalog.Scenarios;
@@ -34,15 +35,16 @@ public class Shortcuts : Scenario
{ {
X = Pos.AnchorEnd (), X = Pos.AnchorEnd (),
Width = 40, Width = 40,
Height = Dim.Fill (), Height = Dim.Fill (4),
ColorScheme = Colors.ColorSchemes ["Toplevel"], ColorScheme = Colors.ColorSchemes ["Toplevel"],
Source = new ListWrapper<string> (eventSource) Source = new ListWrapper<string> (eventSource)
}; };
Application.Top.Add (eventLog); Application.Top.Add (eventLog);
var shortcut1 = new Shortcut var vShortcut1 = new Shortcut
{ {
X = 20, Orientation = Orientation.Vertical,
X = 0,
Width = 35, Width = 35,
Title = "A_pp Shortcut", Title = "A_pp Shortcut",
Key = Key.F1, Key = Key.F1,
@@ -50,14 +52,15 @@ public class Shortcuts : Scenario
KeyBindingScope = KeyBindingScope.Application, KeyBindingScope = KeyBindingScope.Application,
BorderStyle = LineStyle.Dotted BorderStyle = LineStyle.Dotted
}; };
shortcut1.Border.Thickness = new (1, 1, 1, 1); vShortcut1.Border.Thickness = new (1, 1, 1, 1);
Application.Top.Add (shortcut1); Application.Top.Add (vShortcut1);
var shortcut2 = new Shortcut var vShortcut2 = new Shortcut
{ {
X = 20, Orientation = Orientation.Vertical,
Y = Pos.Bottom (shortcut1) - 1, X = 0,
Width = Dim.Width (shortcut1), Y = Pos.Bottom (vShortcut1) - 1,
Width = Dim.Width (vShortcut1),
Key = Key.F2, Key = Key.F2,
Text = "Width is ^", Text = "Width is ^",
KeyBindingScope = KeyBindingScope.HotKey, KeyBindingScope = KeyBindingScope.HotKey,
@@ -69,71 +72,73 @@ public class Shortcuts : Scenario
} }
}; };
((RadioGroup)shortcut2.CommandView).SelectedItemChanged += (o, args) => ((RadioGroup)vShortcut2.CommandView).SelectedItemChanged += (o, args) =>
{ {
eventSource.Add ($"SelectedItemChanged: {o.GetType ().Name} - {args.SelectedItem}"); eventSource.Add ($"SelectedItemChanged: {o.GetType ().Name} - {args.SelectedItem}");
eventLog.MoveDown (); eventLog.MoveDown ();
}; };
shortcut2.Accept += (o, args) => vShortcut2.Accept += (o, args) =>
{ {
// Cycle to next item. If at end, set 0 // Cycle to next item. If at end, set 0
if (((RadioGroup)shortcut2.CommandView).SelectedItem < ((RadioGroup)shortcut2.CommandView).RadioLabels.Length - 1) if (((RadioGroup)vShortcut2.CommandView).SelectedItem < ((RadioGroup)vShortcut2.CommandView).RadioLabels.Length - 1)
{ {
((RadioGroup)shortcut2.CommandView).SelectedItem++; ((RadioGroup)vShortcut2.CommandView).SelectedItem++;
} }
else else
{ {
((RadioGroup)shortcut2.CommandView).SelectedItem = 0; ((RadioGroup)vShortcut2.CommandView).SelectedItem = 0;
} }
}; };
shortcut2.Border.Thickness = new (1, 1, 1, 1); vShortcut2.Border.Thickness = new (1, 1, 1, 1);
Application.Top.Add (shortcut2); Application.Top.Add (vShortcut2);
var shortcut3 = new Shortcut var vShortcut3 = new Shortcut
{ {
X = 20, Orientation = Orientation.Vertical,
Y = Pos.Bottom (shortcut2), X = 0,
Y = Pos.Bottom (vShortcut2),
CommandView = new CheckBox { Text = "_Align" }, CommandView = new CheckBox { Text = "_Align" },
Key = Key.F3, Key = Key.F3,
HelpText = "Width is Fill", HelpText = "Width is Fill",
Width = Dim.Fill () - Dim.Width (eventLog), Width = Dim.Fill () - Dim.Width (eventLog),
KeyBindingScope = KeyBindingScope.HotKey, KeyBindingScope = KeyBindingScope.HotKey,
BorderStyle = LineStyle.Dotted BorderStyle = LineStyle.Rounded
}; };
shortcut3.CommandView.CanFocus = true; vShortcut3.Border.Thickness = new (1, 1, 1, 0);
shortcut3.Border.Thickness = new (1, 1, 1, 0);
((CheckBox)shortcut3.CommandView).Toggled += (s, e) => ((CheckBox)vShortcut3.CommandView).Toggled += (s, e) =>
{ {
if (shortcut3.CommandView is CheckBox cb) if (vShortcut3.CommandView is CheckBox cb)
{ {
eventSource.Add ($"Toggled: {cb.Text}"); eventSource.Add ($"Toggled: {cb.Text}");
eventLog.MoveDown (); eventLog.MoveDown ();
var max = 0; var max = 0;
var toAlign = Application.Top.Subviews.Where (v => v is Shortcut s && s.Orientation == Orientation.Vertical && s.BorderStyle == LineStyle.Rounded);
if (e.NewValue == true) if (e.NewValue == true)
{ {
foreach (Shortcut peer in Application.Top.Subviews.Where (v => v is Shortcut)!) foreach (Shortcut peer in toAlign)
{ {
max = Math.Max (max, peer.KeyView.Text.GetColumns ()); max = Math.Max (max, peer.KeyView.Text.GetColumns ());
} }
} }
foreach (Shortcut peer in Application.Top.Subviews.Where (v => v is Shortcut)!) foreach (Shortcut peer in toAlign)
{ {
peer.MinimumKeyViewSize = max; peer.MinimumKeyViewSize = max;
} }
} }
}; };
Application.Top.Add (shortcut3); Application.Top.Add (vShortcut3);
var shortcut4 = new Shortcut var vShortcut4 = new Shortcut
{ {
X = 20, Orientation = Orientation.Vertical,
Y = Pos.Bottom (shortcut3), X = 0,
Width = Dim.Width (shortcut3), Y = Pos.Bottom (vShortcut3),
Width = Dim.Width (vShortcut3),
CommandView = new Button CommandView = new Button
{ {
Title = "B_utton", Title = "B_utton",
@@ -141,41 +146,56 @@ public class Shortcuts : Scenario
HelpText = "Width is Fill", HelpText = "Width is Fill",
Key = Key.K, Key = Key.K,
KeyBindingScope = KeyBindingScope.HotKey, KeyBindingScope = KeyBindingScope.HotKey,
BorderStyle = LineStyle.Dotted BorderStyle = LineStyle.Rounded
}; };
Button button = (Button)shortcut4.CommandView; Button button = (Button)vShortcut4.CommandView;
shortcut4.CommandView.Accept += Button_Clicked; vShortcut4.CommandView.Accept += Button_Clicked;
shortcut4.CommandView.CanFocus = true; vShortcut4.Border.Thickness = new (1, 0, 1, 0);
shortcut4.Border.Thickness = new (1, 0, 1,0);
Application.Top.Add (shortcut4); Application.Top.Add (vShortcut4);
var shortcut5 = new Shortcut var vShortcut5 = new Shortcut
{ {
X = 20, Orientation = Orientation.Vertical,
Y = Pos.Bottom (shortcut4) , X = 0,
Width = Dim.Width (shortcut4), Y = Pos.Bottom (vShortcut4),
Width = Dim.Width (vShortcut4),
Title = "Fi_ve",
Key = Key.F5.WithCtrl.WithAlt.WithShift, Key = Key.F5.WithCtrl.WithAlt.WithShift,
HelpText = "Width is Fill", HelpText = "CommandView.CanFocus",
KeyBindingScope = KeyBindingScope.HotKey, KeyBindingScope = KeyBindingScope.HotKey,
BorderStyle = LineStyle.Dotted BorderStyle = LineStyle.Rounded,
CommandView = new CheckBox { Text = "_CanFocus" },
}; };
shortcut5.Border.Thickness = new (1, 0, 1, 1); vShortcut5.Border.Thickness = new (1, 0, 1, 1);
Application.Top.Add (shortcut5); ((CheckBox)vShortcut5.CommandView).Toggled += (s, e) =>
{
if (vShortcut5.CommandView is CheckBox cb)
{
eventSource.Add ($"Toggled: {cb.Text}");
eventLog.MoveDown ();
var shortcutSlider = new Shortcut foreach (Shortcut peer in Application.Top.Subviews.Where (v => v is Shortcut)!)
{
peer.CanFocus = e.NewValue == true;
peer.CommandView.CanFocus = e.NewValue == true;
}
}
};
Application.Top.Add (vShortcut5);
var vShortcutSlider = new Shortcut
{ {
X = 20, Orientation = Orientation.Vertical,
Y = Pos.Bottom (shortcut5) - 1, X = 0,
Y = Pos.Bottom (vShortcut5) - 1,
Key = Key.F5, Key = Key.F5,
HelpText = "Width is Fill", HelpText = "Width is Fill",
Width = Dim.Width (shortcut5), Width = Dim.Width (vShortcut5),
KeyBindingScope = KeyBindingScope.HotKey, KeyBindingScope = KeyBindingScope.HotKey,
BorderStyle = LineStyle.Dotted, BorderStyle = LineStyle.Rounded,
CommandView = new Slider<string> CommandView = new Slider<string>
{ {
Orientation = Orientation.Vertical, Orientation = Orientation.Vertical,
@@ -183,31 +203,151 @@ public class Shortcuts : Scenario
} }
}; };
((Slider<string>)shortcutSlider.CommandView).Options = new () { new () { Legend = "A" }, new () { Legend = "B" }, new () { Legend = "C" } }; ((Slider<string>)vShortcutSlider.CommandView).Options = new () { new () { Legend = "A" }, new () { Legend = "B" }, new () { Legend = "C" } };
((Slider<string>)shortcutSlider.CommandView).SetOption (0); ((Slider<string>)vShortcutSlider.CommandView).SetOption (0);
shortcutSlider.Border.Thickness = new (1, 1, 1, 1); vShortcutSlider.Border.Thickness = new (1, 1, 1, 1);
((Slider<string>)shortcutSlider.CommandView).OptionsChanged += (o, args) => ((Slider<string>)vShortcutSlider.CommandView).OptionsChanged += (o, args) =>
{ {
eventSource.Add ($"OptionsChanged: {o.GetType ().Name} - {args.Options}"); eventSource.Add ($"OptionsChanged: {o.GetType ().Name} - {args.Options}");
eventLog.MoveDown (); eventLog.MoveDown ();
}; };
Application.Top.Add (shortcutSlider); Application.Top.Add (vShortcutSlider);
var shortcut6 = new Shortcut var vShortcut6 = new Shortcut
{ {
X = 20, Orientation = Orientation.Vertical,
Y = Pos.Bottom (shortcutSlider) - 1, X = 0,
Width = Dim.Width (shortcutSlider), Y = Pos.Bottom (vShortcutSlider) - 1,
Width = Dim.Width (vShortcutSlider),
Title = "_No Key", Title = "_No Key",
HelpText = "Keyless", HelpText = "Keyless",
BorderStyle = LineStyle.Dotted BorderStyle = LineStyle.Rounded
}; };
shortcut6.Border.Thickness = new (1, 1, 1, 1); vShortcut6.Border.Thickness = new (1, 1, 1, 1);
Application.Top.Add (vShortcut6);
((CheckBox)vShortcut3.CommandView).OnToggled();
// Horizontal
var hShortcut1 = new Shortcut
{
X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
Y = Pos.Bottom (eventLog) + 1,
Key = Key.F7,
HelpText = "Horizontal",
BorderStyle = LineStyle.Dashed,
CanFocus = false
};
hShortcut1.Border.Thickness = new (0, 0, 1, 0);
hShortcut1.CommandView = new ProgressBar
{
Text = "Progress",
Title = "P",
Fraction = 0.5f,
Width = 10,
Height = 1,
ProgressBarStyle = ProgressBarStyle.Continuous
};
hShortcut1.CommandView.Width = 10;
hShortcut1.CommandView.Height = 1;
hShortcut1.CommandView.CanFocus = false;
Timer timer = new (10)
{
AutoReset = true,
};
timer.Elapsed += (o, args) =>
{
if (hShortcut1.CommandView is ProgressBar pb)
{
if (pb.Fraction == 1.0)
{
pb.Fraction = 0;
}
pb.Fraction += 0.01f;
Application.Wakeup ();
pb.SetNeedsDisplay ();
}
};
timer.Start ();
Application.Top.Add (hShortcut1);
var textField = new TextField ()
{
Text = "Edit me",
Width = 10,
Height = 1,
CanFocus = true
};
var hShortcut2 = new Shortcut
{
X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
Y = Pos.Top (hShortcut1),
Key = Key.F8,
HelpText = "Edit",
CanFocus = true,
BorderStyle = LineStyle.Dashed,
CommandView = textField,
};
hShortcut2.Border.Thickness = new (0, 0, 1, 0);
Application.Top.Add (hShortcut2);
var hShortcutBG = new Shortcut
{
X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1)-1,
Y = Pos.Top (hShortcut2),
Key = Key.F9,
HelpText = "BG Color",
BorderStyle = LineStyle.Dashed,
CanFocus = false
};
var bgColor = new ColorPicker ()
{
CanFocus = false,
BoxHeight = 1,
BoxWidth = 1,
};
bgColor.ColorChanged += (o, args) =>
{
Application.Top.ColorScheme = new ColorScheme (Application.Top.ColorScheme)
{
Normal = new Attribute (Application.Top.ColorScheme.Normal.Foreground, args.Color),
};
};
hShortcutBG.CommandView = bgColor;
hShortcutBG.Border.Thickness = new (1, 0, 1, 0);
Application.Top.Add (hShortcutBG);
var hShortcut3 = new Shortcut
{
X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
Y = Pos.Top (hShortcut2),
Key = Key.Esc,
KeyBindingScope = KeyBindingScope.Application,
Title = "Quit",
HelpText = "App Scope",
BorderStyle = LineStyle.Dashed,
CanFocus = false
};
hShortcut3.Border.Thickness = new (0);
hShortcut3.Accept += (o, args) =>
{
Application.RequestStop ();
};
Application.Top.Add (hShortcut3);
Application.Top.Add (shortcut6);
foreach (View sh in Application.Top.Subviews.Where (v => v is Shortcut)!) foreach (View sh in Application.Top.Subviews.Where (v => v is Shortcut)!)
{ {