Files
Terminal.Gui/UICatalog/Scenarios/Scrolling.cs
BDisp ea24de3a27 Fixes #2482. Refactor Redraw - Non-virtual with the right set of virtual OnXXX methods. (#2577)
* Fixes #2482. Refactor Redraw - Non-virtual with the right set of virtual OnXXX methods.

* Change documentation comments.

* Fixes #2575 - TableView to use interface instead of System.Data.DataTable (#2576)

* WIP: Add ITableDataSource

* WIP: Refactor TableView

* WIP: Port CSVEditor

* WIP: Port TableEditor

* WIP: Port MultiColouredTable scenario

* Fix bug of adding duplicate column styles

* Update tests to use DataTableSource

* Tidy up

* Add EnumerableTableDataSource<T>

* Add test for EnumerableTableDataSource

* Add test for EnumerableTableDataSource

* Add code example to xmldoc

* Add ProcessTable scenario

* Rename ITableDataSource to ITableSource and update docs

* Rename EnumerableTableDataSource to EnumerableTableSource

* Fixed Frame != Bounds; changed UICat Scenarios list to use tableview!

* Fix scroll resetting in ProcessTable scenario

* Fix unit tests by setting Frame to same as Bounds

* Document why we have to measure our data for use with TableView

---------

Co-authored-by: Tig Kindel <tig@users.noreply.github.com>

* Fixes #2582 - Refactors FileDialog for cleaner data model (#2583)

* WIP: Add ITableDataSource

* WIP: Refactor TableView

* WIP: Port CSVEditor

* WIP: Port TableEditor

* WIP: Port MultiColouredTable scenario

* Fix bug of adding duplicate column styles

* Update tests to use DataTableSource

* Tidy up

* Add EnumerableTableDataSource<T>

* Add test for EnumerableTableDataSource

* Add test for EnumerableTableDataSource

* Add code example to xmldoc

* Add ProcessTable scenario

* Rename ITableDataSource to ITableSource and update docs

* Rename EnumerableTableDataSource to EnumerableTableSource

* Fixed Frame != Bounds; changed UICat Scenarios list to use tableview!

* Fix scroll resetting in ProcessTable scenario

* Fix unit tests by setting Frame to same as Bounds

* Document why we have to measure our data for use with TableView

* WIP: Simplify FileDialogs use of TableView

* WIP start migrating sorter

* WIP new filedialog table source mostly working

* WIP remove sorter class

* Refactor GetOrderByValue to be adjacent to GetColumnValue

* Fix collection navigator back so it ignores icon

* Fix unit tests

* Tidy up

* Fix UseColors

* Add test for UseColors

---------

Co-authored-by: Tig Kindel <tig@users.noreply.github.com>

* Fixes #2196. TextView: Setting Text places cursor at beginning, unlike TextField (#2572)

* Fixes #2196. TextView: Setting Text places cursor at beginning, unlike TextField

* Change all private members to have the _prefix.

* Renamed local member to prevLayoutStyle.

* Helper function for SetNeedsDisplay.

* Fixes #2569. Borders scenarios needed to be refactored. (#2570)

* Fixes #2569. Borders scenarios needed to be refactored.

* Fix border title with width equal to 4 and thickness top grater than 1.

* Improves border manipulation on borders scenarios.

* Prevents null value on the margin, border and padding thickness on the border scenarios.

* Remove NStack using dependence and fix prior commit.

* Refactoring the Frames scenario.

* Deleted borders scenarios.

* I did not realize that it was changed to SetSubViewNeedsDisplay.

* Re-layout; fixed colorpicker; fixed radio group

* Remove Thickness.IsEmpty as requested.

* Change the Frames scenario as requested.

---------

Co-authored-by: Tig Kindel <tig@users.noreply.github.com>

* Builds CollectionNavigator support into UI Catalog for TableView (#2584)

* Builds collectionnav support into UI cat for TableView

* Fixes keyboard mapping

* MultiSelect = false for TableView

* MultiSelect = false doesn't unbind ctrl-a

* Fixes #2581 Refactor CollectionNavigator so it supports TableView (#2586)

* Refactor CollectionNavigator to a base and a collection implementation

* Refactor CollectionNavigatorBase to look for first match smartly

* Add TableCollectionNavigator

* Make TableCollectionNavigator a core part of TableView

* Fix bad merge

* Added tests for tableview collection navigator

* Add FileDialogCollectionNavigator which ignores . and directory separator prefixes on file names

* whitespace fixes

---------

Co-authored-by: Tig <tig@users.noreply.github.com>

* Resolving merge conflicts.

* Fix merge errors.

* Fix merge errors.

* Add Command.Accept and snap to the selected glyph when ShowHorizontalScrollIndicator change to true.

* Reformat.

* Reformat again.

---------

Co-authored-by: Thomas Nind <31306100+tznind@users.noreply.github.com>
Co-authored-by: Tig Kindel <tig@users.noreply.github.com>
2023-05-04 13:17:59 +02:00

322 lines
8.6 KiB
C#

using System;
using Terminal.Gui;
namespace UICatalog.Scenarios {
[ScenarioMetadata (Name: "Scrolling", Description: "Demonstrates ScrollView etc...")]
[ScenarioCategory ("Controls")]
[ScenarioCategory ("ScrollView")]
public class Scrolling : Scenario {
class Box10x : View {
int w = 40;
int h = 50;
public bool WantCursorPosition { get; set; } = false;
public Box10x (int x, int y) : base (new Rect (x, y, 20, 10))
{
}
public Size GetContentSize ()
{
return new Size (w, h);
}
public void SetCursorPosition (Point pos)
{
throw new NotImplementedException ();
}
public override void OnDrawContent (Rect contentArea)
{
//Point pos = new Point (region.X, region.Y);
Driver.SetAttribute (ColorScheme.Focus);
for (int y = 0; y < h; y++) {
Move (0, y);
Driver.AddStr (y.ToString ());
for (int x = 0; x < w - y.ToString ().Length; x++) {
//Driver.AddRune ((Rune)('0' + (x + y) % 10));
if (y.ToString ().Length < w)
Driver.AddStr (" ");
}
}
//Move (pos.X, pos.Y);
}
}
class Filler : View {
int w = 40;
int h = 50;
public Filler (Rect rect) : base (rect)
{
w = rect.Width;
h = rect.Height;
}
public Size GetContentSize ()
{
return new Size (w, h);
}
public override void OnDrawContent (Rect contentArea)
{
Driver.SetAttribute (ColorScheme.Focus);
var f = Frame;
w = 0;
h = 0;
for (int y = 0; y < f.Width; y++) {
Move (0, y);
var nw = 0;
for (int x = 0; x < f.Height; x++) {
Rune r;
switch (x % 3) {
case 0:
var er = y.ToString ().ToCharArray (0, 1) [0];
nw += er.ToString ().Length;
Driver.AddRune (er);
if (y > 9) {
er = y.ToString ().ToCharArray (1, 1) [0];
nw += er.ToString ().Length;
Driver.AddRune (er);
}
r = '.';
break;
case 1:
r = 'o';
break;
default:
r = 'O';
break;
}
Driver.AddRune (r);
nw += Rune.RuneLen (r);
}
if (nw > w)
w = nw;
h = y + 1;
}
}
}
public override void Setup ()
{
// Offset Win to stress clipping
Win.X = 1;
Win.Y = 1;
Win.Width = Dim.Fill (1);
Win.Height = Dim.Fill (1);
var label = new Label () {
X = 0,
Y = 0
};
Win.Add (label);
var scrollView = new ScrollView {
Id = "scrollView",
X = 2,
Y = Pos.Bottom (label) + 1,
Width = 50,
Height = 20,
ColorScheme = Colors.TopLevel,
ContentSize = new Size (200, 100),
//ContentOffset = new Point (0, 0),
ShowVerticalScrollIndicator = true,
ShowHorizontalScrollIndicator = true,
};
label.Text = $"{scrollView}\nContentSize: {scrollView.ContentSize}\nContentOffset: {scrollView.ContentOffset}";
const string rule = "0123456789";
var horizontalRuler = new Label () {
X = 0,
Y = 0,
Width = Dim.Fill (),
Height = 2,
ColorScheme = Colors.Error,
AutoSize = false
};
scrollView.Add (horizontalRuler);
const string vrule = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n";
var verticalRuler = new Label () {
X = 0,
Y = 0,
Width = 1,
Height = Dim.Fill (),
ColorScheme = Colors.Error,
AutoSize = false
};
scrollView.Add (verticalRuler);
void Top_Loaded (object sender, EventArgs args)
{
horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)] +
"\n" + "| ".Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)];
verticalRuler.Text = vrule.Repeat ((int)Math.Ceiling ((double)(verticalRuler.Bounds.Height * 2) / (double)rule.Length)) [0..(verticalRuler.Bounds.Height * 2)];
Application.Top.Loaded -= Top_Loaded;
}
Application.Top.Loaded += Top_Loaded;
var pressMeButton = new Button ("Press me!") {
X = 3,
Y = 3,
};
pressMeButton.Clicked += (s, e) => MessageBox.Query (20, 7, "MessageBox", "Neat?", "Yes", "No");
scrollView.Add (pressMeButton);
var aLongButton = new Button ("A very long button. Should be wide enough to demo clipping!") {
X = 3,
Y = 4,
Width = Dim.Fill (3),
};
aLongButton.Clicked += (s, e) => MessageBox.Query (20, 7, "MessageBox", "Neat?", "Yes", "No");
scrollView.Add (aLongButton);
scrollView.Add (new TextField ("This is a test of...") {
X = 3,
Y = 5,
Width = 50,
ColorScheme = Colors.Dialog
});
scrollView.Add (new TextField ("... the emergency broadcast system.") {
X = 3,
Y = 10,
Width = 50,
ColorScheme = Colors.Dialog
});
scrollView.Add (new TextField ("Last line") {
X = 3,
Y = 99,
Width = 50,
ColorScheme = Colors.Dialog
});
// Demonstrate AnchorEnd - Button is anchored to bottom/right
var anchorButton = new Button ("Bottom Right") {
Y = Pos.AnchorEnd () - 1,
};
// TODO: Use Pos.Width instead of (Right-Left) when implemented (#502)
anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton));
anchorButton.Clicked += (s, e) => {
// This demonstrates how to have a dynamically sized button
// Each time the button is clicked the button's text gets longer
// The call to Win.LayoutSubviews causes the Computed layout to
// get updated.
anchorButton.Text += "!";
Win.LayoutSubviews ();
};
scrollView.Add (anchorButton);
Win.Add (scrollView);
var hCheckBox = new CheckBox ("Horizontal Scrollbar", scrollView.ShowHorizontalScrollIndicator) {
X = Pos.X (scrollView),
Y = Pos.Bottom (scrollView),
};
Win.Add (hCheckBox);
var vCheckBox = new CheckBox ("Vertical Scrollbar", scrollView.ShowVerticalScrollIndicator) {
X = Pos.Right (hCheckBox) + 3,
Y = Pos.Bottom (scrollView),
};
Win.Add (vCheckBox);
var t = "Auto Hide Scrollbars";
var ahCheckBox = new CheckBox (t, scrollView.AutoHideScrollBars) {
X = Pos.Left (scrollView),
Y = Pos.Bottom (hCheckBox),
};
var k = "Keep Content Always In Viewport";
var keepCheckBox = new CheckBox (k, scrollView.AutoHideScrollBars) {
X = Pos.Left (scrollView),
Y = Pos.Bottom (ahCheckBox),
};
hCheckBox.Toggled += (s, e) => {
if (ahCheckBox.Checked == false) {
scrollView.ShowHorizontalScrollIndicator = (bool)hCheckBox.Checked;
} else {
hCheckBox.Checked = true;
MessageBox.Query ("Message", "Disable Auto Hide Scrollbars first.", "Ok");
}
};
vCheckBox.Toggled += (s, e) => {
if (ahCheckBox.Checked == false) {
scrollView.ShowVerticalScrollIndicator = (bool)vCheckBox.Checked;
} else {
vCheckBox.Checked = true;
MessageBox.Query ("Message", "Disable Auto Hide Scrollbars first.", "Ok");
}
};
ahCheckBox.Toggled += (s, e) => {
scrollView.AutoHideScrollBars = (bool)ahCheckBox.Checked;
hCheckBox.Checked = true;
vCheckBox.Checked = true;
};
Win.Add (ahCheckBox);
keepCheckBox.Toggled += (s, e) => scrollView.KeepContentAlwaysInViewport = (bool)keepCheckBox.Checked;
Win.Add (keepCheckBox);
//var scrollView2 = new ScrollView (new Rect (55, 2, 20, 8)) {
// ContentSize = new Size (20, 50),
// //ContentOffset = new Point (0, 0),
// ShowVerticalScrollIndicator = true,
// ShowHorizontalScrollIndicator = true
//};
//var filler = new Filler (new Rect (0, 0, 60, 40));
//scrollView2.Add (filler);
//scrollView2.DrawContent += (s,e) => {
// scrollView2.ContentSize = filler.GetContentSize ();
//};
//Win.Add (scrollView2);
//// This is just to debug the visuals of the scrollview when small
//var scrollView3 = new ScrollView (new Rect (55, 15, 3, 3)) {
// ContentSize = new Size (100, 100),
// ShowVerticalScrollIndicator = true,
// ShowHorizontalScrollIndicator = true
//};
//scrollView3.Add (new Box10x (0, 0));
//Win.Add (scrollView3);
int count = 0;
var mousePos = new Label ("Mouse: ") {
X = Pos.Right (scrollView) + 1,
Y = Pos.AnchorEnd (1),
Width = 50,
};
Win.Add (mousePos);
Application.RootMouseEvent += delegate (MouseEvent me) {
mousePos.Text = $"Mouse: ({me.X},{me.Y}) - {me.Flags} {count++}";
};
var progress = new ProgressBar {
X = Pos.Right (scrollView) + 1,
Y = Pos.AnchorEnd (2),
Width = 50
};
Win.Add (progress);
bool pulsing = true;
bool timer (MainLoop caller)
{
progress.Pulse ();
return pulsing;
}
Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (300), timer);
void Top_Unloaded (object sender, EventArgs args)
{
pulsing = false;
Application.Top.Unloaded -= Top_Unloaded;
}
Application.Top.Unloaded += Top_Unloaded;
}
}
}