mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Revert "Revert "Use glyphs for checkmarks & selection""
This reverts commit db8f591b56.
This commit is contained in:
@@ -531,20 +531,10 @@ namespace Terminal.Gui {
|
||||
RightTee = Curses.ACS_RTEE;
|
||||
TopTee = Curses.ACS_TTEE;
|
||||
BottomTee = Curses.ACS_BTEE;
|
||||
Checked = '\u221a';
|
||||
UnChecked = ' ';
|
||||
Selected = '\u25cf';
|
||||
UnSelected = '\u25cc';
|
||||
RightArrow = Curses.ACS_RARROW;
|
||||
LeftArrow = Curses.ACS_LARROW;
|
||||
UpArrow = Curses.ACS_UARROW;
|
||||
DownArrow = Curses.ACS_DARROW;
|
||||
LeftDefaultIndicator = '\u25e6';
|
||||
RightDefaultIndicator = '\u25e6';
|
||||
LeftBracket = '[';
|
||||
RightBracket = ']';
|
||||
OnMeterSegment = '\u258c';
|
||||
OffMeterSegement = ' ';
|
||||
|
||||
Colors.TopLevel = new ColorScheme ();
|
||||
Colors.Base = new ColorScheme ();
|
||||
|
||||
@@ -182,33 +182,6 @@ namespace Terminal.Gui {
|
||||
Colors.Error.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Red);
|
||||
Colors.Error.HotFocus = Colors.Error.HotNormal;
|
||||
|
||||
HLine = '\u2500';
|
||||
VLine = '\u2502';
|
||||
Stipple = '\u2592';
|
||||
Diamond = '\u25c6';
|
||||
ULCorner = '\u250C';
|
||||
LLCorner = '\u2514';
|
||||
URCorner = '\u2510';
|
||||
LRCorner = '\u2518';
|
||||
LeftTee = '\u251c';
|
||||
RightTee = '\u2524';
|
||||
TopTee = '\u22a4';
|
||||
BottomTee = '\u22a5';
|
||||
Checked = '\u221a';
|
||||
UnChecked = ' ';
|
||||
Selected = '\u25cf';
|
||||
UnSelected = '\u25cc';
|
||||
RightArrow = '\u25ba';
|
||||
LeftArrow = '\u25c4';
|
||||
UpArrow = '\u25b2';
|
||||
DownArrow = '\u25bc';
|
||||
LeftDefaultIndicator = '\u25e6';
|
||||
RightDefaultIndicator = '\u25e6';
|
||||
LeftBracket = '[';
|
||||
RightBracket = ']';
|
||||
OnMeterSegment = '\u258c';
|
||||
OffMeterSegement = ' ';
|
||||
|
||||
//MockConsole.Clear ();
|
||||
}
|
||||
|
||||
|
||||
@@ -152,33 +152,6 @@ namespace Terminal.Gui {
|
||||
Colors.Error.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Red);
|
||||
Colors.Error.HotFocus = Colors.Error.HotNormal;
|
||||
Console.Clear ();
|
||||
|
||||
HLine = '\u2500';
|
||||
VLine = '\u2502';
|
||||
Stipple = '\u2592';
|
||||
Diamond = '\u25c6';
|
||||
ULCorner = '\u250C';
|
||||
LLCorner = '\u2514';
|
||||
URCorner = '\u2510';
|
||||
LRCorner = '\u2518';
|
||||
LeftTee = '\u251c';
|
||||
RightTee = '\u2524';
|
||||
TopTee = '\u22a4';
|
||||
BottomTee = '\u22a5';
|
||||
Checked = '\u221a';
|
||||
UnChecked = ' ';
|
||||
Selected = '\u25cf';
|
||||
UnSelected = '\u25cc';
|
||||
RightArrow = '\u25ba';
|
||||
LeftArrow = '\u25c4';
|
||||
UpArrow = '\u25b2';
|
||||
DownArrow = '\u25bc';
|
||||
LeftDefaultIndicator = '\u25e6';
|
||||
RightDefaultIndicator = '\u25e6';
|
||||
LeftBracket = '[';
|
||||
RightBracket = ']';
|
||||
OnMeterSegment = '\u258c';
|
||||
OffMeterSegement = ' ';
|
||||
}
|
||||
|
||||
public override Attribute MakeAttribute (Color fore, Color back)
|
||||
|
||||
@@ -563,33 +563,6 @@ namespace Terminal.Gui {
|
||||
Colors.Error.Focus = MakeColor (ConsoleColor.White, ConsoleColor.DarkRed);
|
||||
Colors.Error.HotNormal = MakeColor (ConsoleColor.Black, ConsoleColor.White);
|
||||
Colors.Error.HotFocus = MakeColor (ConsoleColor.Black, ConsoleColor.DarkRed);
|
||||
|
||||
HLine = '\u2500';
|
||||
VLine = '\u2502';
|
||||
Stipple = '\u2591';
|
||||
Diamond = '\u25ca';
|
||||
ULCorner = '\u250C';
|
||||
LLCorner = '\u2514';
|
||||
URCorner = '\u2510';
|
||||
LRCorner = '\u2518';
|
||||
LeftTee = '\u251c';
|
||||
RightTee = '\u2524';
|
||||
TopTee = '\u252c';
|
||||
BottomTee = '\u2534';
|
||||
Checked = '\u221a';
|
||||
UnChecked = ' ';
|
||||
Selected = '\u25cf';
|
||||
UnSelected = '\u25cc';
|
||||
RightArrow = '\u25ba';
|
||||
LeftArrow = '\u25c4';
|
||||
UpArrow = '\u25b2';
|
||||
DownArrow = '\u25bc';
|
||||
LeftDefaultIndicator = '\u25e6';
|
||||
RightDefaultIndicator = '\u25e6';
|
||||
LeftBracket = '[';
|
||||
RightBracket = ']';
|
||||
OnMeterSegment = '\u258c';
|
||||
OffMeterSegement = ' ';
|
||||
}
|
||||
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
|
||||
@@ -913,132 +913,132 @@ namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// Horizontal line character.
|
||||
/// </summary>
|
||||
public Rune HLine;
|
||||
public Rune HLine = '\u2500';
|
||||
|
||||
/// <summary>
|
||||
/// Vertical line character.
|
||||
/// </summary>
|
||||
public Rune VLine;
|
||||
public Rune VLine = '\u2502';
|
||||
|
||||
/// <summary>
|
||||
/// Stipple pattern
|
||||
/// </summary>
|
||||
public Rune Stipple;
|
||||
public Rune Stipple = '\u2591';
|
||||
|
||||
/// <summary>
|
||||
/// Diamond character
|
||||
/// </summary>
|
||||
public Rune Diamond;
|
||||
public Rune Diamond = '\u25ca';
|
||||
|
||||
/// <summary>
|
||||
/// Upper left corner
|
||||
/// </summary>
|
||||
public Rune ULCorner;
|
||||
public Rune ULCorner = '\u250C';
|
||||
|
||||
/// <summary>
|
||||
/// Lower left corner
|
||||
/// </summary>
|
||||
public Rune LLCorner;
|
||||
public Rune LLCorner = '\u2514';
|
||||
|
||||
/// <summary>
|
||||
/// Upper right corner
|
||||
/// </summary>
|
||||
public Rune URCorner;
|
||||
public Rune URCorner = '\u2510';
|
||||
|
||||
/// <summary>
|
||||
/// Lower right corner
|
||||
/// </summary>
|
||||
public Rune LRCorner;
|
||||
public Rune LRCorner = '\u2518';
|
||||
|
||||
/// <summary>
|
||||
/// Left tee
|
||||
/// </summary>
|
||||
public Rune LeftTee;
|
||||
public Rune LeftTee = '\u251c';
|
||||
|
||||
/// <summary>
|
||||
/// Right tee
|
||||
/// </summary>
|
||||
public Rune RightTee;
|
||||
public Rune RightTee = '\u2524';
|
||||
|
||||
/// <summary>
|
||||
/// Top tee
|
||||
/// </summary>
|
||||
public Rune TopTee;
|
||||
public Rune TopTee = '\u252c';
|
||||
|
||||
/// <summary>
|
||||
/// The bottom tee.
|
||||
/// </summary>
|
||||
public Rune BottomTee;
|
||||
public Rune BottomTee = '\u2534';
|
||||
|
||||
/// <summary>
|
||||
/// Checkmark.
|
||||
/// </summary>
|
||||
public Rune Checked;
|
||||
public Rune Checked = '\u221a';
|
||||
|
||||
/// <summary>
|
||||
/// Un-checked checkmark.
|
||||
/// </summary>
|
||||
public Rune UnChecked;
|
||||
public Rune UnChecked = '\u2574';
|
||||
|
||||
/// <summary>
|
||||
/// Selected mark.
|
||||
/// </summary>
|
||||
public Rune Selected;
|
||||
public Rune Selected = '\u25cf';
|
||||
|
||||
/// <summary>
|
||||
/// Un-selected selected mark.
|
||||
/// </summary>
|
||||
public Rune UnSelected;
|
||||
public Rune UnSelected = '\u25cc';
|
||||
|
||||
/// <summary>
|
||||
/// Right Arrow.
|
||||
/// </summary>
|
||||
public Rune RightArrow;
|
||||
public Rune RightArrow = '\u25ba';
|
||||
|
||||
/// <summary>
|
||||
/// Left Arrow.
|
||||
/// </summary>
|
||||
public Rune LeftArrow;
|
||||
public Rune LeftArrow = '\u25c4';
|
||||
|
||||
/// <summary>
|
||||
/// Down Arrow.
|
||||
/// </summary>
|
||||
public Rune DownArrow;
|
||||
public Rune DownArrow = '\u25bc';
|
||||
|
||||
/// <summary>
|
||||
/// Up Arrow.
|
||||
/// </summary>
|
||||
public Rune UpArrow;
|
||||
public Rune UpArrow = '\u25b2';
|
||||
|
||||
/// <summary>
|
||||
/// Left indicator for default action (e.g. for <see cref="Button"/>).
|
||||
/// </summary>
|
||||
public Rune LeftDefaultIndicator;
|
||||
public Rune LeftDefaultIndicator = '\u25e6';
|
||||
|
||||
/// <summary>
|
||||
/// Right indicator for default action (e.g. for <see cref="Button"/>).
|
||||
/// </summary>
|
||||
public Rune RightDefaultIndicator;
|
||||
public Rune RightDefaultIndicator = '\u25e6';
|
||||
|
||||
/// <summary>
|
||||
/// Left frame/bracket (e.g. '[' for <see cref="Button"/>).
|
||||
/// </summary>
|
||||
public Rune LeftBracket;
|
||||
public Rune LeftBracket = '[';
|
||||
|
||||
/// <summary>
|
||||
/// Right frame/bracket (e.g. ']' for <see cref="Button"/>).
|
||||
/// </summary>
|
||||
public Rune RightBracket;
|
||||
public Rune RightBracket = ']';
|
||||
|
||||
/// <summary>
|
||||
/// On Segment indicator for meter views (e.g. <see cref="ProgressBar"/>.
|
||||
/// </summary>
|
||||
public Rune OnMeterSegment;
|
||||
public Rune OnMeterSegment = '\u258c';
|
||||
|
||||
/// <summary>
|
||||
/// Off Segment indicator for meter views (e.g. <see cref="ProgressBar"/>.
|
||||
/// </summary>
|
||||
public Rune OffMeterSegement;
|
||||
public Rune OffMeterSegement = ' ';
|
||||
|
||||
/// <summary>
|
||||
/// Make the attribute for the foreground and background colors.
|
||||
|
||||
@@ -115,11 +115,12 @@ namespace Terminal.Gui {
|
||||
{
|
||||
Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal);
|
||||
Move (0, 0);
|
||||
Driver.AddStr (Checked ? "[x] " : "[ ] ");
|
||||
Move (4, 0);
|
||||
Driver.AddRune (Checked ? Driver.Checked : Driver.UnChecked);
|
||||
Driver.AddRune (' ');
|
||||
Move (2, 0);
|
||||
Driver.AddStr (Text);
|
||||
if (hot_pos != -1) {
|
||||
Move (4 + hot_pos, 0);
|
||||
Move (2 + hot_pos, 0);
|
||||
Driver.SetAttribute (HasFocus ? ColorScheme.HotFocus : ColorScheme.HotNormal);
|
||||
Driver.AddRune (hot_key);
|
||||
}
|
||||
@@ -128,7 +129,7 @@ namespace Terminal.Gui {
|
||||
///<inheritdoc/>
|
||||
public override void PositionCursor ()
|
||||
{
|
||||
Move (1, 0);
|
||||
Move (0, 0);
|
||||
}
|
||||
|
||||
///<inheritdoc/>
|
||||
|
||||
@@ -180,7 +180,19 @@ namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// If set to true allows more than one item to be selected. If false only allow one item selected.
|
||||
/// </summary>
|
||||
public bool AllowsMultipleSelection { get; set; } = true;
|
||||
public bool AllowsMultipleSelection { get => allowsMultipleSelection;
|
||||
set {
|
||||
allowsMultipleSelection = value;
|
||||
if (Source != null && !allowsMultipleSelection) {
|
||||
// Clear all selections except selected
|
||||
for (int i = 0; i < Source.Count; i++) {
|
||||
if (Source.IsMarked (i) && i != selected) {
|
||||
Source.SetMark (i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item that is displayed at the top of the <see cref="ListView"/>.
|
||||
@@ -293,7 +305,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
var item = top;
|
||||
bool focused = HasFocus;
|
||||
int col = allowsMarking ? 4 : 0;
|
||||
int col = allowsMarking ? 2 : 0;
|
||||
|
||||
for (int row = 0; row < f.Height; row++, item++) {
|
||||
bool isSelected = item == selected;
|
||||
@@ -310,7 +322,8 @@ namespace Terminal.Gui {
|
||||
Driver.AddRune (' ');
|
||||
} else {
|
||||
if (allowsMarking) {
|
||||
Driver.AddStr (source.IsMarked (item) ? (AllowsMultipleSelection ? "[x] " : "(o)") : (AllowsMultipleSelection ? "[ ] " : "( )"));
|
||||
Driver.AddRune (source.IsMarked (item) ? (AllowsMultipleSelection ? Driver.Selected : Driver.Checked) : (AllowsMultipleSelection ? Driver.UnSelected : Driver.UnChecked));
|
||||
Driver.AddRune (' ');
|
||||
}
|
||||
Source.Render (this, Driver, isSelected, item, col, row, f.Width - col);
|
||||
}
|
||||
@@ -539,6 +552,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
|
||||
int lastSelectedItem = -1;
|
||||
private bool allowsMultipleSelection = true;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the SelectedChanged event if it is defined.
|
||||
@@ -595,9 +609,9 @@ namespace Terminal.Gui {
|
||||
public override void PositionCursor ()
|
||||
{
|
||||
if (allowsMarking)
|
||||
Move (1, selected - top);
|
||||
else
|
||||
Move (0, selected - top);
|
||||
else
|
||||
Move (Bounds.Width - 1, selected - top);
|
||||
}
|
||||
|
||||
///<inheritdoc/>
|
||||
|
||||
@@ -398,11 +398,10 @@ namespace Terminal.Gui {
|
||||
uncheckedChar = Driver.UnChecked;
|
||||
}
|
||||
|
||||
// Support Checked even though CHeckType wasn't set
|
||||
// Support Checked even though CheckType wasn't set
|
||||
if (item.Checked) {
|
||||
textToDraw = ustring.Make (new Rune [] { checkChar, ' ' }) + item.Title;
|
||||
} else if (item.CheckType.HasFlag (MenuItemCheckStyle.Checked) ||
|
||||
item.CheckType.HasFlag (MenuItemCheckStyle.Radio)) {
|
||||
} else if (item.CheckType.HasFlag (MenuItemCheckStyle.Checked) || item.CheckType.HasFlag (MenuItemCheckStyle.Radio)) {
|
||||
textToDraw = ustring.Make (new Rune [] { uncheckedChar, ' ' }) + item.Title;
|
||||
} else {
|
||||
textToDraw = item.Title;
|
||||
|
||||
155
UICatalog/Scenarios/ListViewWithSelection.cs
Normal file
155
UICatalog/Scenarios/ListViewWithSelection.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using NStack;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Terminal.Gui;
|
||||
|
||||
namespace UICatalog {
|
||||
[ScenarioMetadata (Name: "List View With Selection", Description: "ListView with colunns and selection")]
|
||||
[ScenarioCategory ("Controls")]
|
||||
class ListViewWithSelection : Scenario {
|
||||
|
||||
public CheckBox _customRenderCB;
|
||||
public CheckBox _allowMarkingCB;
|
||||
public CheckBox _allowMultipleCB;
|
||||
public ListView _listView;
|
||||
|
||||
public List<Type> _scenarios = Scenario.GetDerivedClasses<Scenario>().OrderBy (t => Scenario.ScenarioMetadata.GetName (t)).ToList ();
|
||||
|
||||
public override void Setup ()
|
||||
{
|
||||
_customRenderCB = new CheckBox ("Render with columns") {
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Height = 1,
|
||||
};
|
||||
Win.Add (_customRenderCB);
|
||||
_customRenderCB.Toggled += _customRenderCB_Toggled; ;
|
||||
|
||||
_allowMarkingCB = new CheckBox ("Allow Marking") {
|
||||
X = Pos.Right (_customRenderCB) + 1,
|
||||
Y = 0,
|
||||
Height = 1,
|
||||
};
|
||||
Win.Add (_allowMarkingCB);
|
||||
_allowMarkingCB.Toggled += AllowMarkingCB_Toggled;
|
||||
|
||||
_allowMultipleCB = new CheckBox ("Allow Multi-Select") {
|
||||
X = Pos.Right (_allowMarkingCB) + 1,
|
||||
Y = 0,
|
||||
Height = 1,
|
||||
Visible = _allowMarkingCB.Checked
|
||||
};
|
||||
Win.Add (_allowMultipleCB);
|
||||
_allowMultipleCB.Toggled += AllowMultipleCB_Toggled;
|
||||
|
||||
_listView = new ListView () {
|
||||
X = 1,
|
||||
Y = 2,
|
||||
Height = Dim.Fill (),
|
||||
Width = Dim.Fill (1),
|
||||
//ColorScheme = Colors.TopLevel,
|
||||
AllowsMarking = false,
|
||||
AllowsMultipleSelection = false
|
||||
};
|
||||
Win.Add (_listView);
|
||||
|
||||
|
||||
_listView.SetSource (_scenarios);
|
||||
|
||||
}
|
||||
|
||||
private void _customRenderCB_Toggled (bool prev)
|
||||
{
|
||||
if (prev) {
|
||||
_listView.SetSource (_scenarios);
|
||||
} else {
|
||||
_listView.Source = new ScenarioListDataSource (_scenarios);
|
||||
}
|
||||
|
||||
Win.SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
private void AllowMarkingCB_Toggled (bool prev)
|
||||
{
|
||||
_listView.AllowsMarking = !prev;
|
||||
_allowMultipleCB.Visible = _listView.AllowsMarking;
|
||||
Win.SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
private void AllowMultipleCB_Toggled (bool prev)
|
||||
{
|
||||
_listView.AllowsMultipleSelection = !prev;
|
||||
Win.SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
// This is basicaly the same implementation used by the UICatalog main window
|
||||
internal class ScenarioListDataSource : IListDataSource {
|
||||
int _nameColumnWidth = 30;
|
||||
private List<Type> scenarios;
|
||||
BitArray marks;
|
||||
int count;
|
||||
|
||||
public List<Type> Scenarios {
|
||||
get => scenarios;
|
||||
set {
|
||||
if (value != null) {
|
||||
count = value.Count;
|
||||
marks = new BitArray (count);
|
||||
scenarios = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool IsMarked (int item)
|
||||
{
|
||||
if (item >= 0 && item < count)
|
||||
return marks [item];
|
||||
return false;
|
||||
}
|
||||
|
||||
public int Count => Scenarios != null ? Scenarios.Count : 0;
|
||||
|
||||
public ScenarioListDataSource (List<Type> itemList) => Scenarios = itemList;
|
||||
|
||||
public void Render (ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width)
|
||||
{
|
||||
container.Move (col, line);
|
||||
// Equivalent to an interpolated string like $"{Scenarios[item].Name, -widtestname}"; if such a thing were possible
|
||||
var s = String.Format (String.Format ("{{0,{0}}}", -_nameColumnWidth), Scenario.ScenarioMetadata.GetName (Scenarios [item]));
|
||||
RenderUstr (driver, $"{s} {Scenario.ScenarioMetadata.GetDescription (Scenarios [item])}", col, line, width);
|
||||
}
|
||||
|
||||
public void SetMark (int item, bool value)
|
||||
{
|
||||
if (item >= 0 && item < count)
|
||||
marks [item] = value;
|
||||
}
|
||||
|
||||
// A slightly adapted method from: https://github.com/migueldeicaza/gui.cs/blob/fc1faba7452ccbdf49028ac49f0c9f0f42bbae91/Terminal.Gui/Views/ListView.cs#L433-L461
|
||||
private void RenderUstr (ConsoleDriver driver, ustring ustr, int col, int line, int width)
|
||||
{
|
||||
int used = 0;
|
||||
int index = 0;
|
||||
while (index < ustr.Length) {
|
||||
(var rune, var size) = Utf8.DecodeRune (ustr, index, index - ustr.Length);
|
||||
var count = Rune.ColumnWidth (rune);
|
||||
if (used + count >= width) break;
|
||||
driver.AddRune (rune);
|
||||
used += count;
|
||||
index += size;
|
||||
}
|
||||
|
||||
while (used < width) {
|
||||
driver.AddRune (' ');
|
||||
used++;
|
||||
}
|
||||
}
|
||||
|
||||
public IList ToList ()
|
||||
{
|
||||
return Scenarios;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user