2
0
Эх сурвалжийг харах

Merge pull request #941 from tig/glyphs_for_checks_selection

Use glyphs for checkmarks & selection
Charlie Kindel 4 жил өмнө
parent
commit
34724d7d3d

+ 0 - 10
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -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 ();

+ 0 - 27
Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs

@@ -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 ();
 		}
 

+ 0 - 27
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -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)

+ 0 - 27
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -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)]

+ 26 - 26
Terminal.Gui/Core/ConsoleDriver.cs

@@ -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.

+ 3 - 3
Terminal.Gui/Directory.Build.props

@@ -14,9 +14,9 @@
           
        e.g. If AssemblyVersion is 1.2.3.4, Version could be EITHER 1.2.3.4 or 1.2.3-pre.4 depending on whether it's a pre-release or not.
     -->
-    <Version>1.0.0-pre.2</Version>
-    <AssemblyVersion>1.0.0.2</AssemblyVersion>
-    <FileVersion>1.0.0.2</FileVersion>    
+    <Version>1.0.0-pre.3</Version>
+    <AssemblyVersion>1.0.0.3</AssemblyVersion>
+    <FileVersion>1.0.0.3</FileVersion>    
     <Authors>Miguel de Icaza, Charlie Kindel (@tig), @BDisp</Authors>
   </PropertyGroup>
 

+ 5 - 4
Terminal.Gui/Views/Checkbox.cs

@@ -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/>

+ 19 - 5
Terminal.Gui/Views/ListView.cs

@@ -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/>

+ 2 - 3
Terminal.Gui/Views/Menu.cs

@@ -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 - 0
UICatalog/Scenarios/ListViewWithSelection.cs

@@ -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;
+			}
+		}
+	}
+}