mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-27 00:07:58 +01:00
Fixing many clipping issues (#580)
* almost got clip rect working * fixes many bugs related to clipping incl #399 * Merge tweaks.
This commit is contained in:
@@ -4,10 +4,13 @@
|
||||
// Authors:
|
||||
// Miguel de Icaza (miguel@gnome.org)
|
||||
//
|
||||
// Define this to enable diagnostics drawing for Window Frames
|
||||
//#define DRAW_WINDOW_FRAME_DIAGNOSTICS
|
||||
using NStack;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
||||
namespace Terminal.Gui {
|
||||
|
||||
/// <summary>
|
||||
@@ -547,6 +550,17 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
#if DRAW_WINDOW_FRAME_DIAGNOSTICS
|
||||
const char leftChar = 'L';
|
||||
const char rightChar = 'R';
|
||||
const char topChar = 'T';
|
||||
const char bottomChar = 'B';
|
||||
#else
|
||||
const char leftChar = clearChar;
|
||||
const char rightChar = clearChar;
|
||||
const char topChar = clearChar;
|
||||
const char bottomChar = clearChar;
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Draws a frame for a window with padding aand n optional visible border inside the padding.
|
||||
/// </summary>
|
||||
@@ -565,11 +579,22 @@ namespace Terminal.Gui {
|
||||
AddRune (ch);
|
||||
}
|
||||
|
||||
// fwidth is count of hLine chars
|
||||
int fwidth = (int)(region.Width - (paddingRight + paddingLeft));
|
||||
|
||||
// fheight is count of vLine chars
|
||||
int fheight = (int)(region.Height - (paddingBottom + paddingTop));
|
||||
int fleft = region.X + paddingLeft;
|
||||
|
||||
// fleft is location of left frame line
|
||||
int fleft = region.X + paddingLeft - 1;
|
||||
|
||||
// fright is location of right frame line
|
||||
int fright = fleft + fwidth + 1;
|
||||
int ftop = region.Y + paddingTop;
|
||||
|
||||
// ftop is location of top frame line
|
||||
int ftop = region.Y + paddingTop - 1;
|
||||
|
||||
// fbottom is locaiton of bottom frame line
|
||||
int fbottom = ftop + fheight + 1;
|
||||
|
||||
Rune hLine = border ? HLine : clearChar;
|
||||
@@ -582,33 +607,33 @@ namespace Terminal.Gui {
|
||||
// Outside top
|
||||
if (paddingTop > 1) {
|
||||
for (int r = region.Y; r < ftop; r++) {
|
||||
for (int c = region.X; c <= fright + paddingRight; c++) {
|
||||
AddRuneAt (c, r, clearChar);
|
||||
for (int c = region.X; c < region.X + region.Width; c++) {
|
||||
AddRuneAt (c, r, topChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Outside top-left
|
||||
for (int c = region.X; c <= fleft; c++) {
|
||||
AddRuneAt (c, ftop, clearChar);
|
||||
for (int c = region.X; c < fleft; c++) {
|
||||
AddRuneAt (c, ftop, leftChar);
|
||||
}
|
||||
|
||||
// Frame top-left corner
|
||||
AddRuneAt (fleft, ftop, paddingTop >= 0 ? (paddingLeft >= 0 ? uLCorner : hLine) : clearChar);
|
||||
AddRuneAt (fleft, ftop, paddingTop >= 0 ? (paddingLeft >= 0 ? uLCorner : hLine) : leftChar);
|
||||
|
||||
// Frame top
|
||||
for (int c = fleft + 1; c <= fright; c++) {
|
||||
AddRuneAt (c, ftop, paddingTop > 0 ? hLine : clearChar);
|
||||
for (int c = fleft + 1; c < fleft + 1 + fwidth; c++) {
|
||||
AddRuneAt (c, ftop, paddingTop > 0 ? hLine : topChar);
|
||||
}
|
||||
|
||||
// Frame top-right corner
|
||||
if (fright > fleft) {
|
||||
AddRuneAt (fright, ftop, paddingTop >= 0 ? (paddingRight >= 0 ? uRCorner : hLine) : clearChar);
|
||||
AddRuneAt (fright, ftop, paddingTop >= 0 ? (paddingRight >= 0 ? uRCorner : hLine) : rightChar);
|
||||
}
|
||||
|
||||
// Outside top-right corner
|
||||
for (int c = fright + 1; c < fright + paddingRight; c++) {
|
||||
AddRuneAt (c, ftop, clearChar);
|
||||
AddRuneAt (c, ftop, rightChar);
|
||||
}
|
||||
|
||||
// Left, Fill, Right
|
||||
@@ -616,11 +641,11 @@ namespace Terminal.Gui {
|
||||
for (int r = ftop + 1; r < fbottom; r++) {
|
||||
// Outside left
|
||||
for (int c = region.X; c < fleft; c++) {
|
||||
AddRuneAt (c, r, clearChar);
|
||||
AddRuneAt (c, r, leftChar);
|
||||
}
|
||||
|
||||
// Frame left
|
||||
AddRuneAt (fleft, r, paddingLeft > 0 ? vLine : clearChar);
|
||||
AddRuneAt (fleft, r, paddingLeft > 0 ? vLine : leftChar);
|
||||
|
||||
// Fill
|
||||
if (fill) {
|
||||
@@ -631,44 +656,54 @@ namespace Terminal.Gui {
|
||||
|
||||
// Frame right
|
||||
if (fright > fleft) {
|
||||
AddRuneAt (fright, r, paddingRight > 0 ? vLine : clearChar);
|
||||
#if DRAW_WINDOW_FRAME_DIAGNOSTICS
|
||||
var v = (char)(((int)'0') + ((r - ftop) % 10)); // vLine;
|
||||
#else
|
||||
var v = vLine;
|
||||
#endif
|
||||
AddRuneAt (fright, r, paddingRight > 0 ? v : rightChar);
|
||||
}
|
||||
|
||||
// Outside right
|
||||
for (int c = fright + 1; c < fright + paddingRight; c++) {
|
||||
AddRuneAt (c, r, clearChar);
|
||||
AddRuneAt (c, r, rightChar);
|
||||
}
|
||||
}
|
||||
|
||||
// Outside Bottom
|
||||
for (int c = region.X; c < fleft; c++) {
|
||||
AddRuneAt (c, fbottom, clearChar);
|
||||
for (int c = region.X; c < region.X + region.Width; c++) {
|
||||
AddRuneAt (c, fbottom, leftChar);
|
||||
}
|
||||
|
||||
// Frame bottom-left
|
||||
AddRuneAt (fleft, fbottom, paddingLeft > 0 ? lLCorner : clearChar);
|
||||
AddRuneAt (fleft, fbottom, paddingLeft > 0 ? lLCorner : leftChar);
|
||||
|
||||
if (fright > fleft) {
|
||||
// Frame bottom
|
||||
for (int c = fleft + 1; c < fright; c++) {
|
||||
AddRuneAt (c, fbottom, paddingBottom > 0 ? hLine : clearChar);
|
||||
#if DRAW_WINDOW_FRAME_DIAGNOSTICS
|
||||
var h = (char)(((int)'0') + ((c - fleft) % 10)); // hLine;
|
||||
#else
|
||||
var h = hLine;
|
||||
#endif
|
||||
AddRuneAt (c, fbottom, paddingBottom > 0 ? h : bottomChar);
|
||||
}
|
||||
|
||||
// Frame bottom-right
|
||||
AddRuneAt (fright, fbottom, paddingRight > 0 ? (paddingBottom > 0 ? lRCorner : hLine) : clearChar);
|
||||
AddRuneAt (fright, fbottom, paddingRight > 0 ? (paddingBottom > 0 ? lRCorner : hLine) : rightChar);
|
||||
}
|
||||
|
||||
// Outside right
|
||||
for (int c = fright + 1; c < fright + paddingRight; c++) {
|
||||
AddRuneAt (c, fbottom, clearChar);
|
||||
AddRuneAt (c, fbottom, rightChar);
|
||||
}
|
||||
}
|
||||
|
||||
// Out bottom - ensure top is always drawn if we overlap
|
||||
if (paddingBottom > 0) {
|
||||
for (int r = fbottom + 1; r < fbottom + paddingBottom; r++) {
|
||||
for (int c = region.X; c <= fright + paddingRight; c++) {
|
||||
AddRuneAt (c, r, clearChar);
|
||||
for (int c = region.X; c < region.X + region.Width; c++) {
|
||||
AddRuneAt (c, r, bottomChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -677,17 +712,19 @@ namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// Draws a frame on the specified region with the specified padding around the frame.
|
||||
/// </summary>
|
||||
/// <param name="region">Region where the frame will be drawn..</param>
|
||||
/// <param name="region">Screen relative region where the frame will be drawn.</param>
|
||||
/// <param name="padding">Padding to add on the sides.</param>
|
||||
/// <param name="fill">If set to <c>true</c> it will clear the contents with the current color, otherwise the contents will be left untouched.</param>
|
||||
/// <remarks>This is a legacy/depcrecated API. Use <see cref="DrawWindowFrame(Rect, int, int, int, int, bool, bool)"/>.</remarks>
|
||||
/// <remarks>A padding value of 0 means there is actually a 1 cell border.</remarks>
|
||||
/// <remarks>This API has been superceded by <see cref="DrawWindowFrame(Rect, int, int, int, int, bool, bool)"/>.</remarks>
|
||||
/// <remarks>This API is equivlalent to calling <c>DrawWindowFrame(Rect, p - 1, p - 1, p - 1, p - 1)</c>. In other words,
|
||||
/// A padding value of 0 means there is actually a one cell border.
|
||||
/// </remarks>
|
||||
public virtual void DrawFrame (Rect region, int padding, bool fill)
|
||||
{
|
||||
// DrawFrame assumes the frame is always at least one row/col thick
|
||||
// DrawWindowFrame assumes a padding of 0 means NO padding
|
||||
padding++;
|
||||
DrawWindowFrame (new Rect (region.X - 1, region.Y - 1, region.Width, region.Height), padding, padding, padding, padding, fill: fill);
|
||||
// DrawFrame assumes the border is always at least one row/col thick
|
||||
// DrawWindowFrame assumes a padding of 0 means NO padding and no frame
|
||||
DrawWindowFrame (new Rect (region.X, region.Y, region.Width, region.Height),
|
||||
padding + 1, padding + 1, padding + 1, padding + 1, fill: fill);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -665,7 +665,7 @@ namespace Terminal.Gui {
|
||||
{
|
||||
var bscreen = RectToScreen (rect);
|
||||
var previous = Driver.Clip;
|
||||
Driver.Clip = ScreenClip (RectToScreen (Bounds));
|
||||
Driver.Clip = ScreenClip (RectToScreen (Bounds));
|
||||
return previous;
|
||||
}
|
||||
|
||||
@@ -678,8 +678,7 @@ namespace Terminal.Gui {
|
||||
public void DrawFrame (Rect rect, int padding = 0, bool fill = false)
|
||||
{
|
||||
var scrRect = RectToScreen (rect);
|
||||
var savedClip = Driver.Clip;
|
||||
Driver.Clip = ScreenClip (RectToScreen (Bounds));
|
||||
var savedClip = ClipToBounds ();
|
||||
Driver.DrawFrame (scrRect, padding, fill);
|
||||
Driver.Clip = savedClip;
|
||||
}
|
||||
@@ -890,7 +889,15 @@ namespace Terminal.Gui {
|
||||
if (view.layoutNeeded)
|
||||
view.LayoutSubviews ();
|
||||
Application.CurrentView = view;
|
||||
view.Redraw (view.Bounds);
|
||||
|
||||
// Ensure we don't make the Driver's clip rect any bigger
|
||||
if (Driver.Clip.IsEmpty || Driver.Clip.Contains(RectToScreen (view.Frame))) {
|
||||
var savedClip = view.ClipToBounds ();
|
||||
view.Redraw (view.Bounds);
|
||||
Driver.Clip = savedClip;
|
||||
} else {
|
||||
view.Redraw (view.Bounds);
|
||||
}
|
||||
}
|
||||
view.NeedDisplay = Rect.Empty;
|
||||
view.childNeedsDisplay = false;
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Terminal.Gui {
|
||||
Driver.AddRune ('x');
|
||||
}
|
||||
}
|
||||
base.Redraw (region);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -153,16 +154,23 @@ namespace Terminal.Gui {
|
||||
///<inheritdoc cref="Redraw"/>
|
||||
public override void Redraw (Rect bounds)
|
||||
{
|
||||
//var padding = 0;
|
||||
Application.CurrentView = this;
|
||||
var scrRect = RectToScreen (new Rect (0, 0, Frame.Width, Frame.Height));
|
||||
var savedClip = Driver.Clip;
|
||||
Driver.Clip = ScreenClip (RectToScreen (Bounds));
|
||||
var scrRect = RectToScreen (new Rect(0, 0, Frame.Width, Frame.Height));
|
||||
|
||||
// BUGBUG: Why do we draw the frame twice? This call is here to clear the content area, I think. Why not just clear that area?
|
||||
if (NeedDisplay != null && !NeedDisplay.IsEmpty) {
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
Driver.DrawFrame (scrRect, padding, true);
|
||||
}
|
||||
contentView.Redraw (contentView.Bounds);
|
||||
|
||||
if (Driver.Clip.IsEmpty || Driver.Clip.Contains (contentView.RectToScreen (contentView.Frame))) {
|
||||
var savedClip = ClipToBounds ();
|
||||
contentView.Redraw (contentView.Bounds);
|
||||
Driver.Clip = savedClip;
|
||||
} else {
|
||||
contentView.Redraw (contentView.Bounds);
|
||||
}
|
||||
ClearNeedsDisplay ();
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
Driver.DrawFrame (scrRect, padding, false);
|
||||
@@ -170,7 +178,6 @@ namespace Terminal.Gui {
|
||||
if (HasFocus)
|
||||
Driver.SetAttribute (ColorScheme.HotNormal);
|
||||
Driver.DrawWindowTitle (scrRect, Title, padding, padding, padding, padding);
|
||||
Driver.Clip = savedClip;
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Terminal.Gui {
|
||||
get => is_default;
|
||||
set {
|
||||
is_default = value;
|
||||
SetWidthHeight (Text, is_default);
|
||||
Update ();
|
||||
}
|
||||
}
|
||||
@@ -65,20 +66,12 @@ namespace Terminal.Gui {
|
||||
public Button (ustring text, bool is_default = false) : base ()
|
||||
{
|
||||
CanFocus = true;
|
||||
Text = text ?? string.Empty;
|
||||
this.IsDefault = is_default;
|
||||
Text = text;
|
||||
int w = SetWidthHeight (text, is_default);
|
||||
Frame = new Rect (0, 0, w, 1);
|
||||
}
|
||||
|
||||
int SetWidthHeight (ustring text, bool is_default)
|
||||
{
|
||||
int w = text.Length + 4 + (is_default ? 2 : 0);
|
||||
Width = w;
|
||||
Height = 1;
|
||||
return w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="Button"/> at the given coordinates, based on the given text
|
||||
/// </summary>
|
||||
@@ -91,6 +84,35 @@ namespace Terminal.Gui {
|
||||
/// <param name="text">The button's text</param>
|
||||
public Button (int x, int y, ustring text) : this (x, y, text, false) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="Button"/> at the given coordinates, based on the given text, and with the specified <see cref="IsDefault"/> value
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the value for is_default is true, a special
|
||||
/// decoration is used, and the enter key on a
|
||||
/// dialog would implicitly activate this button.
|
||||
/// </remarks>
|
||||
/// <param name="x">X position where the button will be shown.</param>
|
||||
/// <param name="y">Y position where the button will be shown.</param>
|
||||
/// <param name="text">The button's text</param>
|
||||
/// <param name="is_default">If set, this makes the button the default button in the current view, which means that if the user presses return on a view that does not handle return, it will be treated as if he had clicked on the button</param>
|
||||
public Button (int x, int y, ustring text, bool is_default)
|
||||
: base (new Rect (x, y, text.Length + 4 + (is_default ? 2 : 0), 1))
|
||||
{
|
||||
CanFocus = true;
|
||||
Text = text ?? string.Empty;
|
||||
this.IsDefault = is_default;
|
||||
}
|
||||
|
||||
|
||||
int SetWidthHeight (ustring text, bool is_default)
|
||||
{
|
||||
int w = text.Length + 4 + (is_default ? 2 : 0);
|
||||
Width = w;
|
||||
Height = 1;
|
||||
return w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The text displayed by this <see cref="Button"/>.
|
||||
/// </summary>
|
||||
@@ -129,27 +151,6 @@ namespace Terminal.Gui {
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="Button"/> at the given coordinates, based on the given text, and with the specified <see cref="IsDefault"/> value
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the value for is_default is true, a special
|
||||
/// decoration is used, and the enter key on a
|
||||
/// dialog would implicitly activate this button.
|
||||
/// </remarks>
|
||||
/// <param name="x">X position where the button will be shown.</param>
|
||||
/// <param name="y">Y position where the button will be shown.</param>
|
||||
/// <param name="text">The button's text</param>
|
||||
/// <param name="is_default">If set, this makes the button the default button in the current view, which means that if the user presses return on a view that does not handle return, it will be treated as if he had clicked on the button</param>
|
||||
public Button (int x, int y, ustring text, bool is_default)
|
||||
: base (new Rect (x, y, text.Length + 4 + (is_default ? 2 : 0), 1))
|
||||
{
|
||||
CanFocus = true;
|
||||
|
||||
this.IsDefault = is_default;
|
||||
Text = text;
|
||||
}
|
||||
|
||||
///<inheritdoc cref="Redraw(Rect)"/>
|
||||
public override void Redraw (Rect region)
|
||||
{
|
||||
|
||||
@@ -137,14 +137,19 @@ namespace Terminal.Gui {
|
||||
var padding = 0;
|
||||
Application.CurrentView = this;
|
||||
var scrRect = RectToScreen (new Rect (0, 0, Frame.Width, Frame.Height));
|
||||
var savedClip = Driver.Clip;
|
||||
Driver.Clip = ScreenClip (RectToScreen (Bounds));
|
||||
|
||||
if (NeedDisplay != null && !NeedDisplay.IsEmpty) {
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
Driver.DrawFrame (scrRect, padding, true);
|
||||
}
|
||||
contentView.Redraw (contentView.Bounds);
|
||||
|
||||
if (Driver.Clip.IsEmpty || Driver.Clip.Contains (contentView.RectToScreen (contentView.Frame))) {
|
||||
var savedClip = ClipToBounds ();
|
||||
contentView.Redraw (contentView.Bounds);
|
||||
Driver.Clip = savedClip;
|
||||
} else {
|
||||
contentView.Redraw (contentView.Bounds);
|
||||
}
|
||||
ClearNeedsDisplay ();
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
Driver.DrawFrame (scrRect, padding, false);
|
||||
@@ -152,7 +157,6 @@ namespace Terminal.Gui {
|
||||
if (HasFocus)
|
||||
Driver.SetAttribute (ColorScheme.HotNormal);
|
||||
Driver.DrawWindowTitle (scrRect, Title, padding, padding, padding, padding);
|
||||
Driver.Clip = savedClip;
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,13 +110,13 @@ namespace Terminal.Gui {
|
||||
///<inheritdoc cref="Redraw(Rect)"/>
|
||||
public override void Redraw (Rect region)
|
||||
{
|
||||
base.Redraw (region);
|
||||
for (int i = 0; i < radioLabels.Length; i++) {
|
||||
Move (0, i);
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
Driver.AddStr (i == selected ? "(o) " : "( ) ");
|
||||
DrawHotString (radioLabels [i], HasFocus && i == cursor, ColorScheme);
|
||||
}
|
||||
base.Redraw (region);
|
||||
}
|
||||
|
||||
///<inheritdoc cref="PositionCursor"/>
|
||||
|
||||
@@ -401,11 +401,14 @@ namespace Terminal.Gui {
|
||||
public override void Redraw(Rect region)
|
||||
{
|
||||
SetViewsNeedsDisplay ();
|
||||
var oldClip = ClipToBounds ();
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
Clear ();
|
||||
base.Redraw(region);
|
||||
Driver.Clip = oldClip;
|
||||
|
||||
var savedClip = ClipToBounds ();
|
||||
contentView.Redraw (contentView.Bounds);
|
||||
vertical.Redraw (vertical.Bounds);
|
||||
horizontal.Redraw (vertical.Bounds);
|
||||
Driver.Clip = savedClip;
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,9 @@ namespace UICatalog {
|
||||
|
||||
y += 2;
|
||||
// BUGBUG: Buttons don't support specifying hotkeys with _?!?
|
||||
Win.Add (button = new Button (10, y, "Te_xt Changer") {
|
||||
Win.Add (button = new Button ("Te_xt Changer") {
|
||||
X = 10,
|
||||
Y = y
|
||||
});
|
||||
button.Clicked = () => button.Text += $"{y++}";
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ namespace UICatalog {
|
||||
[ScenarioMetadata (Name: "MessageBoxes", Description: "Demonstrates how to use MessageBoxes")]
|
||||
[ScenarioCategory ("Controls")]
|
||||
[ScenarioCategory ("Dialogs")]
|
||||
[ScenarioCategory ("Bug Repro")]
|
||||
class MessageBoxes : Scenario {
|
||||
public override void Setup ()
|
||||
{
|
||||
@@ -110,7 +109,6 @@ namespace UICatalog {
|
||||
var styleRadioGroup = new RadioGroup (new [] { "_Query", "_Error" } ) {
|
||||
X = Pos.Right (label) + 1,
|
||||
Y = Pos.Top (label),
|
||||
Width = 5, // BUGBUG: This should cause clipping!
|
||||
};
|
||||
frame.Add (styleRadioGroup);
|
||||
|
||||
@@ -132,7 +130,6 @@ namespace UICatalog {
|
||||
ColorScheme = Colors.Error,
|
||||
};
|
||||
|
||||
// BUGBUG: Why is this button not centered???
|
||||
var showMessageBoxButton = new Button ("Show MessageBox") {
|
||||
X = Pos.Center(),
|
||||
Y = Pos.Bottom (frame) + 2 ,
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace UICatalog {
|
||||
LeftFrame = new FrameView ("Settings") {
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Height = Dim.Percent (100) + 1, // BUGBUG: This +1 should not be needed
|
||||
Height = Dim.Percent (100),
|
||||
Width = Dim.Percent (25)
|
||||
};
|
||||
var lbl = new Label (1, 1, "Tick every (ms):");
|
||||
@@ -223,14 +223,13 @@ namespace UICatalog {
|
||||
|
||||
var startBoth = new Button ("Start Both") {
|
||||
X = Pos.Center (),
|
||||
Y = Pos.AnchorEnd () - 1,
|
||||
Y = Pos.Bottom(mainLoopTimeoutDemo) + 1,
|
||||
};
|
||||
startBoth.Clicked = () => {
|
||||
systemTimerDemo.Start ();
|
||||
mainLoopTimeoutDemo.Start ();
|
||||
};
|
||||
Win.Add (startBoth);
|
||||
|
||||
}
|
||||
|
||||
protected override void Dispose (bool disposing)
|
||||
|
||||
103
UICatalog/Scenarios/Scrolling.cs
Normal file
103
UICatalog/Scenarios/Scrolling.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using Terminal.Gui;
|
||||
|
||||
namespace UICatalog {
|
||||
[ScenarioMetadata (Name: "Scrolling", Description: "Demonstrates ScrollView etc...")]
|
||||
[ScenarioCategory ("Controls")]
|
||||
[ScenarioCategory ("Bug Repro")]
|
||||
|
||||
class Scrolling : Scenario {
|
||||
public override void Setup ()
|
||||
{
|
||||
var label = new Label ("ScrollView (new Rect (2, 2, 50, 20)) with a 200, 100 ContentSize...") {
|
||||
X = 0, Y = 0,
|
||||
ColorScheme = Colors.Dialog
|
||||
};
|
||||
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;
|
||||
|
||||
const string rule = "|123456789";
|
||||
var horizontalRuler = new Label ("") {
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Width = Dim.Fill (1), // BUGBUG: I don't think this should be needed; DimFill() should respect container's frame. X does.
|
||||
ColorScheme = Colors.Error
|
||||
};
|
||||
scrollView.Add (horizontalRuler);
|
||||
const string vrule = "|\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
|
||||
};
|
||||
scrollView.Add (verticalRuler);
|
||||
|
||||
Application.Resized += (sender, a) => {
|
||||
horizontalRuler.Text = rule.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)];
|
||||
};
|
||||
|
||||
scrollView.Add (new Button ("Press me!") {
|
||||
X = 3,
|
||||
Y = 3,
|
||||
Clicked = () => MessageBox.Query (20, 7, "MessageBox", "Neat?", "Yes", "No")
|
||||
});
|
||||
|
||||
scrollView.Add (new Button ("A very long button. Should be wide enough to demo clipping!") {
|
||||
X = 3,
|
||||
Y = 4,
|
||||
Width = 50,
|
||||
Clicked = () => MessageBox.Query (20, 7, "MessageBox", "Neat?", "Yes", "No")
|
||||
});
|
||||
|
||||
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 sytem.") {
|
||||
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 = () => {
|
||||
// Ths 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,22 +30,42 @@ namespace UICatalog {
|
||||
|
||||
public override void Setup ()
|
||||
{
|
||||
static int About ()
|
||||
{
|
||||
//return MessageBox.Query (50, 10, "About UI Catalog", "UI Catalog is a comprehensive sample library for Terminal.Gui", "Ok")
|
||||
|
||||
var about = new Window (new Rect (0, 0, 50, 10), "About UI catalog", 0) {
|
||||
X = Pos.Center (),
|
||||
Y = Pos.Center (),
|
||||
Width = 50,
|
||||
Height = 10,
|
||||
LayoutStyle = LayoutStyle.Computed,
|
||||
ColorScheme = Colors.Error,
|
||||
|
||||
};
|
||||
//about.Add (new Label ("UI Catalog is a comprehensive sample library for Terminal.Gui"));
|
||||
|
||||
Application.Run (about);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int margin = 2;
|
||||
int padding = 0;
|
||||
int height = 10;
|
||||
int padding = 1;
|
||||
int contentHeight = 7;
|
||||
var listWin = new List<View> ();
|
||||
Win = new Window ($"{listWin.Count} - Scenario: {GetName ()}", padding) {
|
||||
X = Pos.Center (),
|
||||
Y = 1,
|
||||
Width = Dim.Fill (10),
|
||||
Height = Dim.Percent (15),
|
||||
Height = Dim.Percent (15)
|
||||
};
|
||||
Win.ColorScheme = Colors.Dialog;
|
||||
Win.Add (new Button ("Press me! (Y = 0)") {
|
||||
Win.Add (new Button ($"Padding of container is {padding}") {
|
||||
X = Pos.Center (),
|
||||
Y = 0,
|
||||
ColorScheme = Colors.Error,
|
||||
Clicked = () => MessageBox.ErrorQuery (30, 10, Win.Title.ToString (), "Neat?", "Yes", "No")
|
||||
Clicked = () => About()
|
||||
});
|
||||
Win.Add (new Button ("Press ME! (Y = Pos.AnchorEnd(1))") {
|
||||
X = Pos.Center (),
|
||||
@@ -55,13 +75,13 @@ namespace UICatalog {
|
||||
Top.Add (Win);
|
||||
listWin.Add (Win);
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
for (var i = 0; i < 3; i++) {
|
||||
Window win = null;
|
||||
win = new Window ($"{listWin.Count} - Loop {i}", padding) {
|
||||
win = new Window ($"{listWin.Count} - Window Loop - padding = {i}", i) {
|
||||
X = margin,
|
||||
Y = Pos.Bottom (listWin.Last ()) + (margin),
|
||||
Width = Dim.Fill (margin),
|
||||
Height = height,
|
||||
Height = contentHeight + (i*2) + 2,
|
||||
};
|
||||
win.ColorScheme = Colors.Dialog;
|
||||
win.Add (new Button ("Press me! (Y = 0)") {
|
||||
@@ -101,14 +121,14 @@ namespace UICatalog {
|
||||
X = margin,
|
||||
Y = Pos.Bottom (listWin.Last ()) + (margin / 2),
|
||||
Width = Dim.Fill (margin),
|
||||
Height = height,
|
||||
Height = contentHeight + 2, // 2 for default padding
|
||||
};
|
||||
frame.ColorScheme = Colors.Dialog;
|
||||
frame.Add (new Button ("Press me! (Y = 0)") {
|
||||
frame.Add (new Label ("This is a Label! (Y = 0)") {
|
||||
X = Pos.Center (),
|
||||
Y = 0,
|
||||
ColorScheme = Colors.Error,
|
||||
Clicked = () => MessageBox.ErrorQuery (30, 10, frame.Title.ToString (), "Neat?", "Yes", "No")
|
||||
//Clicked = () => MessageBox.ErrorQuery (30, 10, frame.Title.ToString (), "Neat?", "Yes", "No")
|
||||
});
|
||||
var subWinofFV = new Window ("this is a Sub-Window") {
|
||||
X = Pos.Percent (0),
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace UICatalog {
|
||||
new MenuBarItem ("_File", new MenuItem [] {
|
||||
new MenuItem ("_Quit", "", () => Application.RequestStop() )
|
||||
}),
|
||||
new MenuBarItem ("_About...", "About this app", () => MessageBox.Query (0, 10, "About UI Catalog", "UI Catalog is a comprehensive sample library for Terminal.Gui", "Ok")),
|
||||
new MenuBarItem ("_About...", "About this app", () => MessageBox.Query (50, 10, "About UI Catalog", "UI Catalog is a comprehensive sample library for Terminal.Gui", "Ok")),
|
||||
});
|
||||
|
||||
_leftPane = new Window ("Categories") {
|
||||
@@ -163,6 +163,8 @@ namespace UICatalog {
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user