mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-29 17:28:01 +01:00
* Added View.DefaultCommand etc... Started on dedicated scenario * Fixed un-shifted hotkeys -> Fixed Key Equals. Fixed WindowsDriver passing wrong key. Etc. * Fixed Key Bindings and HotKeys * Fixed Key Bindings and HotKeys * Label now correctly supports hotkey * Disabled unix hot keys because they are annoying and get in the way * Updated nuget. fixed warnings * Trying to fix ci/ci issue * Trying to fix ci/ci issue * Trying to fix ci/ci issue * Changed TextChangingEventArgs to inherit from CancelEventArgs * TextChangingEventArgs -> TextEventArgs * Simplified Text events by having only on args class * Fixed unit tests fail * Simplified by removing TitleEventArgs * POC of Title being primary for hotkey. Label and Button hacked to work * POC of Title being primary for hotkey. Label and Button hacked to work - all unit tests pass * Dropped Microsoft.NETFramework.ReferenceAssemblies * Fixed Dialogs scenario hotkeys * Fixed build warnings * Fixed Border Title render bug * Regiggering default command handling * Regiggering default command handling * Checkbox clean up * Added StateEventArgs POC * Command.Default -> Command.HotKey * Command.Default -> Command.HotKey - fixed TableView * Command.Default -> Command.HotKey - fixed TableView * Updated reactive example * Fixed Toplevel.BringOverlappedTopToFront - was reordering SubViews when it shouldn't * WIP - broke * Finished impl of StateEventArgs * Deleted ToggleEventArgs.cs. Added StateEventArgs.cs * XML doc fix * Removed old code * Removed commented out code * Label.Clicked -> Label.Accept (missed this before) * Removed Labels as Buttons scenario as it's not really useful * Moved SubView tests to own file * Moved SubView tests to own file * Simplified Text test * Added OnAccept test * Deleted DefaultCommand * Modernized CheckBox * New button test * Cleaned up RadioGroup; added tests * KeyCode->Key in ListView * Added ListView unit tests * ListView now does Accept correctly * TreeView now does Accept correctly * Cleaned up some TextField tests * TextView now handles Accept properly; updated CharMap and Adornments scenarios to test * Fixed ComboBox to deal with TextView now handles Accept properly; updated CharMap and Adornments scenarios to test * Removed un-needed using statement
281 lines
9.1 KiB
C#
281 lines
9.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using JetBrains.Annotations;
|
|
using Terminal.Gui;
|
|
|
|
namespace UICatalog.Scenarios;
|
|
|
|
[ScenarioMetadata ("List View With Selection", "ListView with columns and selection")]
|
|
[ScenarioCategory ("Controls")]
|
|
[ScenarioCategory ("ListView")]
|
|
public class ListViewWithSelection : Scenario
|
|
{
|
|
public CheckBox _allowMarkingCB;
|
|
public CheckBox _allowMultipleCB;
|
|
public CheckBox _customRenderCB;
|
|
public ListView _listView;
|
|
public List<Scenario> _scenarios;
|
|
|
|
public override void Setup ()
|
|
{
|
|
_scenarios = GetScenarios ();
|
|
|
|
_customRenderCB = new CheckBox { X = 0, Y = 0, Text = "Use custom rendering" };
|
|
Win.Add (_customRenderCB);
|
|
_customRenderCB.Toggled += _customRenderCB_Toggled;
|
|
|
|
_allowMarkingCB = new CheckBox
|
|
{
|
|
X = Pos.Right (_customRenderCB) + 1, Y = 0, Text = "Allow Marking", AllowNullChecked = false
|
|
};
|
|
Win.Add (_allowMarkingCB);
|
|
_allowMarkingCB.Toggled += AllowMarkingCB_Toggled;
|
|
|
|
_allowMultipleCB = new CheckBox
|
|
{
|
|
X = Pos.Right (_allowMarkingCB) + 1,
|
|
Y = 0,
|
|
Visible = (bool)_allowMarkingCB.Checked,
|
|
Text = "Allow Multi-Select"
|
|
};
|
|
Win.Add (_allowMultipleCB);
|
|
_allowMultipleCB.Toggled += AllowMultipleCB_Toggled;
|
|
|
|
_listView = new ListView
|
|
{
|
|
X = 1,
|
|
Y = 2,
|
|
Height = Dim.Fill (),
|
|
Width = Dim.Fill (1),
|
|
|
|
//ColorScheme = Colors.ColorSchemes ["TopLevel"],
|
|
AllowsMarking = false,
|
|
AllowsMultipleSelection = false
|
|
};
|
|
_listView.RowRender += ListView_RowRender;
|
|
Win.Add (_listView);
|
|
|
|
var scrollBar = new ScrollBarView (_listView, true);
|
|
|
|
scrollBar.ChangedPosition += (s, e) =>
|
|
{
|
|
_listView.TopItem = scrollBar.Position;
|
|
|
|
if (_listView.TopItem != scrollBar.Position)
|
|
{
|
|
scrollBar.Position = _listView.TopItem;
|
|
}
|
|
|
|
_listView.SetNeedsDisplay ();
|
|
};
|
|
|
|
scrollBar.OtherScrollBarView.ChangedPosition += (s, e) =>
|
|
{
|
|
_listView.LeftItem = scrollBar.OtherScrollBarView.Position;
|
|
|
|
if (_listView.LeftItem != scrollBar.OtherScrollBarView.Position)
|
|
{
|
|
scrollBar.OtherScrollBarView.Position = _listView.LeftItem;
|
|
}
|
|
|
|
_listView.SetNeedsDisplay ();
|
|
};
|
|
|
|
_listView.DrawContent += (s, e) =>
|
|
{
|
|
scrollBar.Size = _listView.Source.Count - 1;
|
|
scrollBar.Position = _listView.TopItem;
|
|
scrollBar.OtherScrollBarView.Size = _listView.MaxLength - 1;
|
|
scrollBar.OtherScrollBarView.Position = _listView.LeftItem;
|
|
scrollBar.Refresh ();
|
|
};
|
|
|
|
_listView.SetSource (_scenarios);
|
|
|
|
var k = "Keep Content Always In Viewport";
|
|
|
|
var keepCheckBox = new CheckBox
|
|
{
|
|
X = Pos.AnchorEnd (k.Length + 3), Y = 0, Text = k, Checked = scrollBar.AutoHideScrollBars
|
|
};
|
|
keepCheckBox.Toggled += (s, e) => scrollBar.KeepContentAlwaysInViewport = (bool)keepCheckBox.Checked;
|
|
Win.Add (keepCheckBox);
|
|
}
|
|
|
|
private void _customRenderCB_Toggled (object sender, StateEventArgs<bool?> stateEventArgs)
|
|
{
|
|
if (stateEventArgs.OldValue == true)
|
|
{
|
|
_listView.SetSource (_scenarios);
|
|
}
|
|
else
|
|
{
|
|
_listView.Source = new ScenarioListDataSource (_scenarios);
|
|
}
|
|
|
|
Win.SetNeedsDisplay ();
|
|
}
|
|
|
|
private void AllowMarkingCB_Toggled (object sender, [NotNull] StateEventArgs<bool?> stateEventArgs)
|
|
{
|
|
_listView.AllowsMarking = (bool)!stateEventArgs.OldValue;
|
|
_allowMultipleCB.Visible = _listView.AllowsMarking;
|
|
Win.SetNeedsDisplay ();
|
|
}
|
|
|
|
private void AllowMultipleCB_Toggled (object sender, [NotNull] StateEventArgs<bool?> stateEventArgs)
|
|
{
|
|
_listView.AllowsMultipleSelection = (bool)!stateEventArgs.OldValue;
|
|
Win.SetNeedsDisplay ();
|
|
}
|
|
|
|
private void ListView_RowRender (object sender, ListViewRowEventArgs obj)
|
|
{
|
|
if (obj.Row == _listView.SelectedItem)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_listView.AllowsMarking && _listView.Source.IsMarked (obj.Row))
|
|
{
|
|
obj.RowAttribute = new Attribute (Color.BrightRed, Color.BrightYellow);
|
|
|
|
return;
|
|
}
|
|
|
|
if (obj.Row % 2 == 0)
|
|
{
|
|
obj.RowAttribute = new Attribute (Color.BrightGreen, Color.Magenta);
|
|
}
|
|
else
|
|
{
|
|
obj.RowAttribute = new Attribute (Color.BrightMagenta, Color.Green);
|
|
}
|
|
}
|
|
|
|
// This is basically the same implementation used by the UICatalog main window
|
|
internal class ScenarioListDataSource : IListDataSource
|
|
{
|
|
private readonly int _nameColumnWidth = 30;
|
|
private int count;
|
|
private BitArray marks;
|
|
private List<Scenario> scenarios;
|
|
public ScenarioListDataSource (List<Scenario> itemList) { Scenarios = itemList; }
|
|
|
|
public List<Scenario> Scenarios
|
|
{
|
|
get => scenarios;
|
|
set
|
|
{
|
|
if (value != null)
|
|
{
|
|
count = value.Count;
|
|
marks = new BitArray (count);
|
|
scenarios = value;
|
|
Length = GetMaxLengthItem ();
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool IsMarked (int item)
|
|
{
|
|
if (item >= 0 && item < count)
|
|
{
|
|
return marks [item];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public int Count => Scenarios != null ? Scenarios.Count : 0;
|
|
public int Length { get; private set; }
|
|
|
|
public void Render (
|
|
ListView container,
|
|
ConsoleDriver driver,
|
|
bool selected,
|
|
int item,
|
|
int col,
|
|
int line,
|
|
int width,
|
|
int start = 0
|
|
)
|
|
{
|
|
container.Move (col, line);
|
|
|
|
// Equivalent to an interpolated string like $"{Scenarios[item].Name, -widtestname}"; if such a thing were possible
|
|
string s = string.Format (
|
|
string.Format ("{{0,{0}}}", -_nameColumnWidth),
|
|
Scenarios [item].GetName ()
|
|
);
|
|
RenderUstr (driver, $"{s} ({Scenarios [item].GetDescription ()})", col, line, width, start);
|
|
}
|
|
|
|
public void SetMark (int item, bool value)
|
|
{
|
|
if (item >= 0 && item < count)
|
|
{
|
|
marks [item] = value;
|
|
}
|
|
}
|
|
|
|
public IList ToList () { return Scenarios; }
|
|
|
|
private int GetMaxLengthItem ()
|
|
{
|
|
if (scenarios?.Count == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
var maxLength = 0;
|
|
|
|
for (var i = 0; i < scenarios.Count; i++)
|
|
{
|
|
string s = string.Format (
|
|
string.Format ("{{0,{0}}}", -_nameColumnWidth),
|
|
Scenarios [i].GetName ()
|
|
);
|
|
var sc = $"{s} {Scenarios [i].GetDescription ()}";
|
|
int l = sc.Length;
|
|
|
|
if (l > maxLength)
|
|
{
|
|
maxLength = l;
|
|
}
|
|
}
|
|
|
|
return maxLength;
|
|
}
|
|
|
|
// A slightly adapted method from: https://github.com/gui-cs/Terminal.Gui/blob/fc1faba7452ccbdf49028ac49f0c9f0f42bbae91/Terminal.Gui/Views/ListView.cs#L433-L461
|
|
private void RenderUstr (ConsoleDriver driver, string ustr, int col, int line, int width, int start = 0)
|
|
{
|
|
var used = 0;
|
|
int index = start;
|
|
|
|
while (index < ustr.Length)
|
|
{
|
|
(Rune rune, int size) = ustr.DecodeRune (index, index - ustr.Length);
|
|
int count = rune.GetColumns ();
|
|
|
|
if (used + count >= width)
|
|
{
|
|
break;
|
|
}
|
|
|
|
driver.AddRune (rune);
|
|
used += count;
|
|
index += size;
|
|
}
|
|
|
|
while (used < width)
|
|
{
|
|
driver.AddRune ((Rune)' ');
|
|
used++;
|
|
}
|
|
}
|
|
}
|
|
}
|