diff --git a/Example/demo.cs b/Example/demo.cs
index 0e431422a..2e4be94e4 100644
--- a/Example/demo.cs
+++ b/Example/demo.cs
@@ -335,12 +335,12 @@ static class Demo {
$"{mi.Title.ToString ()} selected. Is from submenu: {mi.GetMenuBarItem ()}", "Ok");
}
- static void MenuKeysStyle_Toggled (object sender, EventArgs e)
+ static void MenuKeysStyle_Toggled (object sender, bool e)
{
menu.UseKeysUpDownAsKeysLeftRight = menuKeysStyle.Checked;
}
- static void MenuAutoMouseNav_Toggled (object sender, EventArgs e)
+ static void MenuAutoMouseNav_Toggled (object sender, bool e)
{
menu.WantMousePositionReports = menuAutoMouseNav.Checked;
}
diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index 1d50cfe5b..c6936909e 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -929,6 +929,9 @@ namespace Terminal.Gui {
{
var clipRect = new Rect (Point.Empty, frame.Size);
+ // Invoke DrawContentEvent
+ OnDrawContent (bounds);
+
if (subviews != null) {
foreach (var view in subviews) {
if (view.NeedDisplay != null && (!view.NeedDisplay.IsEmpty || view.childNeedsDisplay)) {
@@ -941,7 +944,11 @@ namespace Terminal.Gui {
// Clip the sub-view
var savedClip = ClipToBounds ();
+
+ // Draw the subview
view.Redraw (view.Bounds);
+
+ // Undo the clip
Driver.Clip = savedClip;
}
view.NeedDisplay = Rect.Empty;
@@ -952,6 +959,31 @@ namespace Terminal.Gui {
ClearNeedsDisplay ();
}
+ ///
+ /// Event invoked when the content area of the View is to be drawn.
+ ///
+ ///
+ ///
+ /// Will be invoked before any subviews added with have been drawn.
+ ///
+ ///
+ /// Rect provides the view-relative rectangle describing the currently visible viewport into the .
+ ///
+ ///
+ public event EventHandler DrawContent;
+
+ ///
+ /// Enables overrides to draw infinitely scrolled content and/or a background behind added controls.
+ ///
+ /// The view-relative rectangle describing the currently visible viewport into the
+ ///
+ /// This method will be called before any subviews added with have been drawn.
+ ///
+ public virtual void OnDrawContent (Rect viewport)
+ {
+ DrawContent?.Invoke (this, viewport);
+ }
+
///
/// Causes the specified subview to have focus.
///
diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj
index 77c3a2342..d78c6950d 100644
--- a/Terminal.Gui/Terminal.Gui.csproj
+++ b/Terminal.Gui/Terminal.Gui.csproj
@@ -78,6 +78,15 @@
* More robust error handing in Pos/Dim. Fixes #355 stack overflow with Pos based on the size of windows at startup. Added a OnResized action to set the Pos after the terminal are resized. (Thanks @bdisp!)
* Fixes #389 Window layouting breaks when resizing. (Thanks @bdisp!)
* Fixes #557 MessageBox needs to take ustrings (BREAKING CHANGE). (Thanks @tig!)
+ * Fixes ScrollView in several key ways. (Thanks @tig!)
+ * Now supports Computed layout and has constructors that don't require parameters.
+ * ScrollBarViews are now positioned using Computed layout versus error prone absoulte
+ * ScrollBarViews now correctly position themselves when one, either, or both are on/off.
+ * IsVertical is now a public property that does the expected thing when changed
+ * Mouse handling is better; there's still a bug where the mouse doesn't get grabbed by the ScrollView initially but I think this is a broader problem. I need @BDisp's help on this.
+ * Supports "infinite scrolling" via the new OnDrawContent/DrawContent event on the View class.
+ * The Scrolling Scenario was enhanced to demo dynamically adding/removing horizontal/vertical scrollbars (and to prove it was working right).
+ * The Checkbox.Toggled event is now an EventHandler event and passes previous state. (Thanks @tig!)
0.81:
* Fix ncurses engine for macOS/Linux, it works again
diff --git a/Terminal.Gui/Views/Checkbox.cs b/Terminal.Gui/Views/Checkbox.cs
index 57421db73..a9c18c045 100644
--- a/Terminal.Gui/Views/Checkbox.cs
+++ b/Terminal.Gui/Views/Checkbox.cs
@@ -23,9 +23,16 @@ namespace Terminal.Gui {
///
/// Client code can hook up to this event, it is
/// raised when the is activated either with
- /// the mouse or the keyboard.
+ /// the mouse or the keyboard. The passed bool contains the previous state.
///
- public event EventHandler Toggled;
+ public event EventHandler Toggled;
+
+ ///
+ /// Called when the property changes. Invokes the event.
+ ///
+ public virtual void OnToggled (bool previousChecked) {
+ Toggled?.Invoke (this, previousChecked);
+ }
///
/// Initializes a new instance of based on the given text, uses Computed layout and sets the height and width.
@@ -122,11 +129,9 @@ namespace Terminal.Gui {
public override bool ProcessKey (KeyEvent kb)
{
if (kb.KeyValue == ' ') {
+ var previousChecked = Checked;
Checked = !Checked;
-
- if (Toggled != null)
- Toggled (this, EventArgs.Empty);
-
+ OnToggled (previousChecked);
SetNeedsDisplay ();
return true;
}
@@ -140,11 +145,11 @@ namespace Terminal.Gui {
return false;
SuperView.SetFocus (this);
+ var previousChecked = Checked;
Checked = !Checked;
+ OnToggled (previousChecked);
SetNeedsDisplay ();
- if (Toggled != null)
- Toggled (this, EventArgs.Empty);
return true;
}
}
diff --git a/Terminal.Gui/Views/ScrollView.cs b/Terminal.Gui/Views/ScrollView.cs
index 2e9c8e74d..bd63f2240 100644
--- a/Terminal.Gui/Views/ScrollView.cs
+++ b/Terminal.Gui/Views/ScrollView.cs
@@ -6,9 +6,7 @@
//
//
// TODO:
-// - Mouse handling in scrollbarview
// - focus in scrollview
-// - keyboard handling in scrollview to scroll
// - focus handling in scrollview to auto scroll to focused view
// - Raise events
// - Perhaps allow an option to not display the scrollbar arrow indicators?
@@ -31,13 +29,26 @@ namespace Terminal.Gui {
///
///
public class ScrollBarView : View {
- bool vertical;
- int size, position;
+ bool vertical = false;
+ int size = 0, position = 0;
///
- /// The size that this scrollbar represents
+ /// If set to true this is a vertical scrollbar, otherwise, the scrollbar is horizontal.
+ ///
+ public bool IsVertical {
+ get => vertical;
+ set {
+ vertical = value;
+ SetNeedsDisplay ();
+ }
+ }
+
+ ///
+ /// The size of content the scrollbar represents.
///
/// The size.
+ /// The is typically the size of the virtual content. E.g. when a Scrollbar is
+ /// part of a the Size is set to the appropriate dimension of .
public int Size {
get => size;
set {
@@ -52,7 +63,7 @@ namespace Terminal.Gui {
public event Action ChangedPosition;
///
- /// The position to show the scrollbar at.
+ /// The position, relative to , to set the scrollbar at.
///
/// The position.
public int Position {
@@ -70,13 +81,40 @@ namespace Terminal.Gui {
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class using layout.
///
/// Frame for the scrollbar.
+ public ScrollBarView (Rect rect) : this (rect, 0, 0, false) { }
+
+ ///
+ /// Initializes a new instance of the class using layout.
+ ///
+ /// Frame for the scrollbar.
+ /// The size that this scrollbar represents. Sets the property.
+ /// The position within this scrollbar. Sets the property.
+ /// If set to true this is a vertical scrollbar, otherwise, the scrollbar is horizontal. Sets the property.
+ public ScrollBarView (Rect rect, int size, int position, bool isVertical) : base (rect)
+ {
+ Init (size, position, isVertical);
+ }
+
+ ///
+ /// Initializes a new instance of the class using layout.
+ ///
+ public ScrollBarView () : this (0, 0, false) { }
+
+ ///
+ /// Initializes a new instance of the class using layout.
+ ///
/// The size that this scrollbar represents.
/// The position within this scrollbar.
/// If set to true this is a vertical scrollbar, otherwise, the scrollbar is horizontal.
- public ScrollBarView (Rect rect, int size, int position, bool isVertical) : base (rect)
+ public ScrollBarView (int size, int position, bool isVertical) : base ()
+ {
+ Init (size, position, isVertical);
+ }
+
+ void Init (int size, int position, bool isVertical)
{
vertical = isVertical;
this.position = position;
@@ -84,11 +122,8 @@ namespace Terminal.Gui {
WantContinuousButtonPressed = true;
}
- ///
- /// Redraw the scrollbar
- ///
- /// Region to be redrawn.
- public override void Redraw(Rect region)
+ ///
+ public override void Redraw (Rect region)
{
if (ColorScheme == null)
return;
@@ -113,7 +148,7 @@ namespace Terminal.Gui {
special = Driver.Stipple;
else
special = Driver.Diamond;
- Driver.AddRune(special);
+ Driver.AddRune (special);
}
} else {
bh -= 2;
@@ -125,7 +160,7 @@ namespace Terminal.Gui {
Move (col, Bounds.Height - 1);
Driver.AddRune ('v');
for (int y = 0; y < bh; y++) {
- Move (col, y+1);
+ Move (col, y + 1);
if (y < by1 - 1 || y > by2)
special = Driver.Stipple;
else {
@@ -195,7 +230,7 @@ namespace Terminal.Gui {
}
///
- public override bool MouseEvent(MouseEvent me)
+ public override bool MouseEvent (MouseEvent me)
{
if (me.Flags != MouseFlags.Button1Pressed && me.Flags != MouseFlags.Button1Clicked &&
!me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition))
@@ -239,39 +274,66 @@ namespace Terminal.Gui {
}
///
- /// Scrollviews are views that present a window into a virtual space where children views are added. Similar to the iOS UIScrollView.
+ /// Scrollviews are views that present a window into a virtual space where subviews are added. Similar to the iOS UIScrollView.
///
///
///
- /// The subviews that are added to this scrollview are offset by the
- /// ContentOffset property. The view itself is a window into the
- /// space represented by the ContentSize.
+ /// The subviews that are added to this are offset by the
+ /// property. The view itself is a window into the
+ /// space represented by the .
///
///
- ///
+ /// Use the
///
///
public class ScrollView : View {
- View contentView;
+ View contentView = null;
ScrollBarView vertical, horizontal;
///
- /// Constructs a ScrollView
+ /// Initializes a new instance of the class using positioning.
///
///
public ScrollView (Rect frame) : base (frame)
+ {
+ Init (frame);
+ }
+
+
+ ///
+ /// Initializes a new instance of the class using positioning.
+ ///
+ public ScrollView () : base ()
+ {
+ Init (new Rect (0, 0, 0, 0));
+ }
+
+ void Init (Rect frame)
{
contentView = new View (frame);
- vertical = new ScrollBarView (new Rect (frame.Width - 1, 0, 1, frame.Height), frame.Height, 0, isVertical: true);
+ vertical = new ScrollBarView (1, 0, isVertical: true) {
+ X = Pos.AnchorEnd (1),
+ Y = 0,
+ Width = 1,
+ Height = Dim.Fill (showHorizontalScrollIndicator ? 1 : 0)
+ };
vertical.ChangedPosition += delegate {
ContentOffset = new Point (ContentOffset.X, vertical.Position);
};
- horizontal = new ScrollBarView (new Rect (0, frame.Height-1, frame.Width-1, 1), frame.Width-1, 0, isVertical: false);
+ horizontal = new ScrollBarView (1, 0, isVertical: false) {
+ X = 0,
+ Y = Pos.AnchorEnd (1),
+ Width = Dim.Fill (showVerticalScrollIndicator ? 1 : 0),
+ Height = 1
+ };
horizontal.ChangedPosition += delegate {
ContentOffset = new Point (horizontal.Position, ContentOffset.Y);
};
base.Add (contentView);
CanFocus = true;
+
+ MouseEnter += View_MouseEnter;
+ MouseLeave += View_MouseLeave;
}
Size contentSize;
@@ -305,7 +367,7 @@ namespace Terminal.Gui {
return contentOffset;
}
set {
- contentOffset = new Point (-Math.Abs (value.X), -Math.Abs(value.Y));
+ contentOffset = new Point (-Math.Abs (value.X), -Math.Abs (value.Y));
contentView.Frame = new Rect (contentOffset, contentSize);
vertical.Position = Math.Max (0, -contentOffset.Y);
horizontal.Position = Math.Max (0, -contentOffset.X);
@@ -322,12 +384,9 @@ namespace Terminal.Gui {
if (!IsOverridden (view)) {
view.MouseEnter += View_MouseEnter;
view.MouseLeave += View_MouseLeave;
- vertical.MouseEnter += View_MouseEnter;
- vertical.MouseLeave += View_MouseLeave;
- horizontal.MouseEnter += View_MouseEnter;
- horizontal.MouseLeave += View_MouseLeave;
}
contentView.Add (view);
+ SetNeedsLayout ();
}
void View_MouseLeave (object sender, MouseEventEventArgs e)
@@ -359,11 +418,17 @@ namespace Terminal.Gui {
return;
showHorizontalScrollIndicator = value;
- SetNeedsDisplay ();
- if (value)
+ SetNeedsLayout ();
+ if (value) {
base.Add (horizontal);
- else
+ horizontal.MouseEnter += View_MouseEnter;
+ horizontal.MouseLeave += View_MouseLeave;
+ } else {
Remove (horizontal);
+ horizontal.MouseEnter -= View_MouseEnter;
+ horizontal.MouseLeave -= View_MouseLeave;
+ }
+ vertical.Height = Dim.Fill (showHorizontalScrollIndicator ? 1 : 0);
}
}
@@ -372,9 +437,9 @@ namespace Terminal.Gui {
///
///
///
- public override void RemoveAll()
+ public override void RemoveAll ()
{
- contentView.RemoveAll();
+ contentView.RemoveAll ();
}
///
@@ -388,31 +453,46 @@ namespace Terminal.Gui {
return;
showVerticalScrollIndicator = value;
- SetNeedsDisplay ();
- if (value)
+ SetNeedsLayout ();
+ if (value) {
base.Add (vertical);
- else
+ vertical.MouseEnter += View_MouseEnter;
+ vertical.MouseLeave += View_MouseLeave;
+ } else {
Remove (vertical);
+ vertical.MouseEnter -= View_MouseEnter;
+ vertical.MouseLeave -= View_MouseLeave;
+ }
+ horizontal.Width = Dim.Fill (showVerticalScrollIndicator ? 1 : 0);
}
}
- ///
- /// This event is raised when the contents have scrolled
- ///
- //public event Action Scrolled;
- public override void Redraw(Rect region)
+ ///
+ public override void Redraw (Rect region)
{
- SetViewsNeedsDisplay ();
Driver.SetAttribute (ColorScheme.Normal);
+ SetViewsNeedsDisplay ();
Clear ();
var savedClip = ClipToBounds ();
+ OnDrawContent (new Rect (ContentOffset,
+ new Size (Bounds.Width - (ShowVerticalScrollIndicator ? 1 : 0),
+ Bounds.Height - (ShowHorizontalScrollIndicator ? 1 : 0))));
contentView.Redraw (contentView.Bounds);
Driver.Clip = savedClip;
- vertical.Redraw (vertical.Bounds);
- horizontal.Redraw (horizontal.Bounds);
- Driver.Clip = savedClip;
+ if (ShowVerticalScrollIndicator) {
+ vertical.Redraw (vertical.Bounds);
+ }
+
+ if (ShowHorizontalScrollIndicator) {
+ horizontal.Redraw (horizontal.Bounds);
+ }
+
+ // Fill in the bottom left corner
+ if (ShowVerticalScrollIndicator && ShowHorizontalScrollIndicator) {
+ AddRune (Bounds.Width - 1, Bounds.Height - 1, ' ');
+ }
Driver.SetAttribute (ColorScheme.Normal);
}
@@ -424,7 +504,7 @@ namespace Terminal.Gui {
}
///
- public override void PositionCursor()
+ public override void PositionCursor ()
{
if (InternalSubviews.Count == 0)
Driver.Move (0, 0);
@@ -490,7 +570,7 @@ namespace Terminal.Gui {
}
///
- public override bool ProcessKey(KeyEvent kb)
+ public override bool ProcessKey (KeyEvent kb)
{
if (base.ProcessKey (kb))
return true;
diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs
index a6d782fe4..7e665ecdc 100644
--- a/Terminal.Gui/Views/TextView.cs
+++ b/Terminal.Gui/Views/TextView.cs
@@ -771,32 +771,12 @@ namespace Terminal.Gui {
case Key.ControlN:
case Key.CursorDown:
- if (currentRow + 1 < model.Count) {
- if (columnTrack == -1)
- columnTrack = currentColumn;
- currentRow++;
- if (currentRow >= topRow + Frame.Height) {
- topRow++;
- SetNeedsDisplay ();
- }
- TrackColumn ();
- PositionCursor ();
- }
+ MoveDown ();
break;
case Key.ControlP:
case Key.CursorUp:
- if (currentRow > 0) {
- if (columnTrack == -1)
- columnTrack = currentColumn;
- currentRow--;
- if (currentRow < topRow) {
- topRow--;
- SetNeedsDisplay ();
- }
- TrackColumn ();
- PositionCursor ();
- }
+ MoveUp ();
break;
case Key.ControlF:
@@ -1024,6 +1004,18 @@ namespace Terminal.Gui {
SetNeedsDisplay (new Rect (0, currentRow - topRow, 2, Frame.Height));
break;
+ case Key.CtrlMask | Key.End:
+ currentRow = model.Count;
+ TrackColumn ();
+ PositionCursor ();
+ break;
+
+ case Key.CtrlMask | Key.Home:
+ currentRow = 0;
+ TrackColumn ();
+ PositionCursor ();
+ break;
+
default:
// Ignore control characters and other special keys
if (kb.Key < Key.Space || kb.Key > Key.CharMask)
@@ -1043,6 +1035,36 @@ namespace Terminal.Gui {
return true;
}
+ private void MoveUp ()
+ {
+ if (currentRow > 0) {
+ if (columnTrack == -1)
+ columnTrack = currentColumn;
+ currentRow--;
+ if (currentRow < topRow) {
+ topRow--;
+ SetNeedsDisplay ();
+ }
+ TrackColumn ();
+ PositionCursor ();
+ }
+ }
+
+ private void MoveDown ()
+ {
+ if (currentRow + 1 < model.Count) {
+ if (columnTrack == -1)
+ columnTrack = currentColumn;
+ currentRow++;
+ if (currentRow >= topRow + Frame.Height) {
+ topRow++;
+ SetNeedsDisplay ();
+ }
+ TrackColumn ();
+ PositionCursor ();
+ }
+ }
+
IEnumerable<(int col, int row, Rune rune)> ForwardIterator (int col, int row)
{
if (col < 0 || row < 0)
@@ -1173,28 +1195,37 @@ namespace Terminal.Gui {
///
public override bool MouseEvent (MouseEvent ev)
{
- if (!ev.Flags.HasFlag (MouseFlags.Button1Clicked)) {
+ if (!ev.Flags.HasFlag (MouseFlags.Button1Clicked) &&
+ !ev.Flags.HasFlag (MouseFlags.WheeledDown) && !ev.Flags.HasFlag (MouseFlags.WheeledUp)) {
return false;
}
if (!HasFocus)
SuperView.SetFocus (this);
-
- if (model.Count > 0) {
- var maxCursorPositionableLine = (model.Count - 1) - topRow;
- if (ev.Y > maxCursorPositionableLine) {
- currentRow = maxCursorPositionableLine;
- } else {
- currentRow = ev.Y + topRow;
+ if (ev.Flags == MouseFlags.Button1Clicked) {
+ if (model.Count > 0) {
+ var maxCursorPositionableLine = (model.Count - 1) - topRow;
+ if (ev.Y > maxCursorPositionableLine) {
+ currentRow = maxCursorPositionableLine;
+ } else {
+ currentRow = ev.Y + topRow;
+ }
+ var r = GetCurrentLine ();
+ if (ev.X - leftColumn >= r.Count)
+ currentColumn = r.Count - leftColumn;
+ else
+ currentColumn = ev.X - leftColumn;
}
- var r = GetCurrentLine ();
- if (ev.X - leftColumn >= r.Count)
- currentColumn = r.Count - leftColumn;
- else
- currentColumn = ev.X - leftColumn;
+ PositionCursor ();
+ } else if (ev.Flags == MouseFlags.WheeledDown) {
+ lastWasKill = false;
+ MoveDown ();
+ } else if (ev.Flags == MouseFlags.WheeledUp) {
+ lastWasKill = false;
+ MoveUp ();
}
- PositionCursor ();
+
return true;
}
}
diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs
index 3413d418a..ebb69639c 100644
--- a/UICatalog/Scenarios/Buttons.cs
+++ b/UICatalog/Scenarios/Buttons.cs
@@ -118,6 +118,16 @@ namespace UICatalog {
};
Win.Add (moveBtn);
+ // Demonstrates how changing the View.Frame property can SIZE Views (#583)
+ y += 2;
+ var sizeBtn = new Button (10, y, "Size This Button via Frame") {
+ ColorScheme = Colors.Error,
+ };
+ moveBtn.Clicked = () => {
+ sizeBtn.Frame = new Rect (sizeBtn.Frame.X, sizeBtn.Frame.Y, sizeBtn.Frame.Width + 5, sizeBtn.Frame.Height);
+ };
+ Win.Add (sizeBtn);
+
// Demo changing hotkey
ustring MoveHotkey (ustring txt)
{
diff --git a/UICatalog/Scenarios/CharacterMap.cs b/UICatalog/Scenarios/CharacterMap.cs
new file mode 100644
index 000000000..96288504d
--- /dev/null
+++ b/UICatalog/Scenarios/CharacterMap.cs
@@ -0,0 +1,123 @@
+using NStack;
+using System.Collections.Generic;
+using System.Text;
+using Terminal.Gui;
+
+namespace UICatalog {
+ ///
+ /// This Scenario demonstrates building a custom control (a class deriving from View) that:
+ /// - Provides a simple "Character Map" application (like Windows' charmap.exe).
+ /// - Helps test unicode character rendering in Terminal.Gui
+ /// - Illustrates how to use ScrollView to do infinite scrolling
+ ///
+ [ScenarioMetadata (Name: "Character Map", Description: "Illustrates a custom control and Unicode")]
+ [ScenarioCategory ("Text")]
+ [ScenarioCategory ("Controls")]
+ class CharacterMap : Scenario {
+ public override void Setup ()
+ {
+ var charMap = new CharMap () { X = 0, Y = 0, Width = CharMap.RowWidth + 2, Height = Dim.Fill(), Start = 0x2500,
+ ColorScheme = Colors.Dialog};
+
+ Win.Add (charMap);
+
+ Button CreateBlock(Window win, ustring title, int start, int end, View align)
+ {
+ var button = new Button ($"{title} (U+{start:x5}-{end:x5})") {
+ X = Pos.X (align),
+ Y = Pos.Bottom (align),
+ Clicked = () => {
+ charMap.Start = start;
+ },
+ };
+ win.Add (button);
+ return button;
+ };
+
+ var label = new Label ("Unicode Blocks:") { X = Pos.Right (charMap) + 2, Y = Pos.Y (charMap) };
+ Win.Add (label);
+ var button = CreateBlock (Win, "Currency Symbols", 0x20A0, 0x20CF, label);
+ button = CreateBlock (Win, "Letterlike Symbols", 0x2100, 0x214F, button);
+ button = CreateBlock (Win, "Arrows", 0x2190, 0x21ff, button);
+ button = CreateBlock (Win, "Mathematical symbols", 0x2200, 0x22ff, button);
+ button = CreateBlock (Win, "Miscellaneous Technical", 0x2300, 0x23ff, button);
+ button = CreateBlock (Win, "Box Drawing & Geometric Shapes", 0x2500, 0x25ff, button);
+ button = CreateBlock (Win, "Miscellaneous Symbols", 0x2600, 0x26ff, button);
+ button = CreateBlock (Win, "Dingbats", 0x2700, 0x27ff, button);
+ button = CreateBlock (Win, "Braille", 0x2800, 0x28ff, button);
+ button = CreateBlock (Win, "Miscellaneous Symbols and Arrows", 0x2b00, 0x2bff, button);
+ button = CreateBlock (Win, "Alphabetic Presentation Forms", 0xFB00, 0xFb4f, button);
+ button = CreateBlock (Win, "Cuneiform Numbers and Punctuation[1", 0x12400, 0x1240f, button);
+ button = CreateBlock (Win, "Chess Symbols", 0x1FA00, 0x1FA0f, button);
+ button = CreateBlock (Win, "End", CharMap.MaxCodePointVal - 16, CharMap.MaxCodePointVal, button);
+ }
+ }
+
+ class CharMap : ScrollView {
+
+ ///
+ /// Specifies the starting offset for the character map. The default is 0x2500
+ /// which is the Box Drawing characters.
+ ///
+ public int Start {
+ get => _start;
+ set {
+ _start = value;
+ ContentOffset = new Point (0, _start / 16);
+
+ SetNeedsDisplay ();
+ }
+ }
+ int _start = 0x2500;
+
+ public static int MaxCodePointVal => 0xE0FFF;
+
+ // Row Header + space + (space + char + space)
+ public static int RowHeaderWidth => $"U+{MaxCodePointVal:x5}".Length;
+ public static int RowWidth => RowHeaderWidth + 1 + (" c ".Length * 16);
+
+ public CharMap ()
+ {
+ ContentSize = new Size (CharMap.RowWidth, MaxCodePointVal / 16);
+ ShowVerticalScrollIndicator = true;
+ ShowHorizontalScrollIndicator = false;
+ LayoutComplete += (sender, args) => {
+ if (Bounds.Width <= RowWidth) {
+ ShowHorizontalScrollIndicator = true;
+ } else {
+ ShowHorizontalScrollIndicator = false;
+ }
+ };
+
+ DrawContent += CharMap_DrawContent;
+ }
+
+#if true
+ private void CharMap_DrawContent (object sender, Rect viewport)
+ {
+ for (int header = 0; header < 16; header++) {
+ Move (viewport.X + RowHeaderWidth + 1 + (header * 3), 0);
+ Driver.AddStr ($" {header:x} ");
+ }
+ for (int row = 0; row < viewport.Height - 1; row++) {
+ int val = (-viewport.Y + row) * 16;
+ if (val < MaxCodePointVal) {
+ var rowLabel = $"U+{val / 16:x4}x";
+ Move (0, row + 1);
+ Driver.AddStr (rowLabel);
+ for (int col = 0; col < 16; col++) {
+ Move (viewport.X + RowHeaderWidth + 1 + (col * 3), 0 + row + 1);
+ Driver.AddStr ($" {(char)((-viewport.Y + row) * 16 + col)} ");
+ }
+ }
+ }
+ }
+#else
+ public override void OnDrawContent (Rect viewport)
+ {
+ CharMap_DrawContent(this, viewport);
+ base.OnDrawContent (viewport);
+ }
+#endif
+ }
+}
diff --git a/UICatalog/Scenarios/Scrolling.cs b/UICatalog/Scenarios/Scrolling.cs
index da989d02f..27425d61d 100644
--- a/UICatalog/Scenarios/Scrolling.cs
+++ b/UICatalog/Scenarios/Scrolling.cs
@@ -95,12 +95,13 @@ namespace UICatalog {
Win.Add (label);
// BUGBUG: ScrollView only supports Absolute Positioning (#72)
- var scrollView = new ScrollView (new Rect (2, 2, 50, 20));
- scrollView.ColorScheme = Colors.TopLevel;
- scrollView.ContentSize = new Size (200, 100);
- //ContentOffset = new Point (0, 0),
- scrollView.ShowVerticalScrollIndicator = true;
- scrollView.ShowHorizontalScrollIndicator = true;
+ var scrollView = new ScrollView (new Rect (2, 2, 50, 20)) {
+ ColorScheme = Colors.TopLevel,
+ ContentSize = new Size (200, 100),
+ //ContentOffset = new Point (0, 0),
+ ShowVerticalScrollIndicator = true,
+ ShowHorizontalScrollIndicator = true,
+ };
const string rule = "|123456789";
var horizontalRuler = new Label ("") {
@@ -177,13 +178,31 @@ namespace UICatalog {
};
scrollView.Add (anchorButton);
+ var hCheckBox = new CheckBox ("Horizontal Scrollbar", scrollView.ShowHorizontalScrollIndicator) {
+ X = Pos.X(scrollView),
+ Y = Pos.Bottom(scrollView) + 1,
+ };
+ hCheckBox.Toggled += (sender, previousChecked) => {
+ scrollView.ShowHorizontalScrollIndicator = ((CheckBox)sender).Checked;
+ };
+ Win.Add (hCheckBox);
+
+ var vCheckBox = new CheckBox ("Vertical Scrollbar", scrollView.ShowVerticalScrollIndicator) {
+ X = Pos.Right (hCheckBox) + 3,
+ Y = Pos.Bottom (scrollView) + 1,
+ };
+ vCheckBox.Toggled += (sender, previousChecked) => {
+ scrollView.ShowVerticalScrollIndicator = ((CheckBox)sender).Checked;
+ };
+ Win.Add (vCheckBox);
+
var scrollView2 = new ScrollView (new Rect (55, 2, 20, 8)) {
ContentSize = new Size (20, 50),
//ContentOffset = new Point (0, 0),
ShowVerticalScrollIndicator = true,
ShowHorizontalScrollIndicator = true
};
- scrollView2.Add (new Filler(new Rect (0, 0, 60, 40)));
+ scrollView2.Add (new Filler (new Rect (0, 0, 60, 40)));
// This is just to debug the visuals of the scrollview when small
var scrollView3 = new ScrollView (new Rect (55, 15, 3, 3)) {
@@ -205,7 +224,7 @@ namespace UICatalog {
var progress = new ProgressBar ();
progress.X = 5;
- progress.Y = Pos.AnchorEnd (3);
+ progress.Y = Pos.AnchorEnd (2);
progress.Width = 50;
bool timer (MainLoop caller)
{
diff --git a/UICatalog/Scenarios/TextAlignment.cs b/UICatalog/Scenarios/TextAlignments.cs
similarity index 97%
rename from UICatalog/Scenarios/TextAlignment.cs
rename to UICatalog/Scenarios/TextAlignments.cs
index 1f4beb019..219d10e0f 100644
--- a/UICatalog/Scenarios/TextAlignment.cs
+++ b/UICatalog/Scenarios/TextAlignments.cs
@@ -6,7 +6,7 @@ using Terminal.Gui;
namespace UICatalog {
[ScenarioMetadata (Name: "Text Alignment", Description: "Demonstrates text alignment")]
[ScenarioCategory ("Text")]
- class TextAlignment : Scenario {
+ class TextAlignments : Scenario {
public override void Setup ()
{
int i = 1;
diff --git a/UICatalog/Scenarios/Unicode.cs b/UICatalog/Scenarios/Unicode.cs
index bf7acee93..197f5bc32 100644
--- a/UICatalog/Scenarios/Unicode.cs
+++ b/UICatalog/Scenarios/Unicode.cs
@@ -10,8 +10,6 @@ namespace UICatalog {
class UnicodeInMenu : Scenario {
public override void Setup ()
{
- const int margin = 1;
-
var menu = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_Файл", new MenuItem [] {
new MenuItem ("_Создать", "Creates new file", null),
@@ -27,14 +25,9 @@ namespace UICatalog {
});
Top.Add (menu);
- var label = new Label ("Button:") { X = margin, Y = margin };
+ var label = new Label ("Button:") { X = 0, Y = 1 };
Win.Add (label);
- var button = new Button (" ~ s gui.cs master ↑10") { X = 15, Y = Pos.Y (label) };
- Win.Add (button);
-
- label = new Label ("Button:") { X = Pos.X (label), Y = Pos.Bottom (label) + 1 };
- Win.Add (label);
- var button2 = new Button ("Со_хранить") { X = 15, Y = Pos.Y (label), Width = Dim.Percent (50) };
+ var button2 = new Button ("Со_хранить") { X = 15, Y = Pos.Y (label), Width = Dim.Percent (50), };
Win.Add (button2);
label = new Label ("CheckBox:") { X = Pos.X (label), Y = Pos.Bottom (label) + 1 };