mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2026-01-02 01:03:29 +01:00
Merge branch 'mondo_onlayoutcomplete_clip_msgboxdlg' of tig:tig/gui.cs
This commit is contained in:
@@ -638,7 +638,7 @@ static class Demo {
|
||||
var bottom2 = new Label ("This should go on the bottom of another top-level!");
|
||||
top.Add (bottom2);
|
||||
|
||||
Application.Loaded += (sender, e) => {
|
||||
top.LayoutComplete += (sender, e) => {
|
||||
bottom.X = win.X;
|
||||
bottom.Y = Pos.Bottom (win) - Pos.Top (win) - margin;
|
||||
bottom2.X = Pos.Left (win);
|
||||
|
||||
@@ -481,6 +481,7 @@ namespace Terminal.Gui {
|
||||
if (closeDriver) {
|
||||
MainLoop = null;
|
||||
Driver.End ();
|
||||
Driver = null;
|
||||
}
|
||||
|
||||
_initialized = false;
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace Terminal.Gui {
|
||||
if (IsCurrentTop || this == Application.Top) {
|
||||
if (NeedDisplay != null && !NeedDisplay.IsEmpty) {
|
||||
Driver.SetAttribute (Colors.TopLevel.Normal);
|
||||
Clear (bounds);
|
||||
Clear (Frame);
|
||||
Driver.SetAttribute (Colors.Base.Normal);
|
||||
}
|
||||
foreach (var view in Subviews) {
|
||||
|
||||
@@ -911,9 +911,12 @@ namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// Redraws this view and its subviews; only redraws the views that have been flagged for a re-display.
|
||||
/// </summary>
|
||||
/// <param name="bounds">The view-relative region to redraw.</param>
|
||||
/// <param name="bounds">The bounds (view-relative region) to redraw.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Always use <see cref="Bounds"/> (view-relative) when calling <see cref="Redraw(Rect)"/>, NOT <see cref="Frame"/> (superview-relative).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Views should set the color that they want to use on entry, as otherwise this will inherit
|
||||
/// the last color that was set globaly on the driver.
|
||||
/// </para>
|
||||
@@ -1318,15 +1321,45 @@ namespace Terminal.Gui {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a view starts executing or
|
||||
/// when the dimensions of the view have changed, for example in
|
||||
/// Event arguments for the <see cref="LayoutComplete"/> event.
|
||||
/// </summary>
|
||||
public class LayoutEventArgs : EventArgs {
|
||||
/// <summary>
|
||||
/// The view-relative bounds of the <see cref="View"/> before it was laid out.
|
||||
/// </summary>
|
||||
public Rect OldBounds { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired after the Views's <see cref="LayoutSubviews"/> method has completed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Subscribe to this event to perform tasks when the <see cref="View"/> has been resized or the layout has otherwise changed.
|
||||
/// </remarks>
|
||||
public event EventHandler<LayoutEventArgs> LayoutComplete;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="LayoutComplete"/> event. Called from <see cref="LayoutSubviews"/> after all sub-views have been laid out.
|
||||
/// </summary>
|
||||
internal virtual void OnLayoutComplete (LayoutEventArgs args)
|
||||
{
|
||||
LayoutComplete?.Invoke (this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a view starts executing or when the dimensions of the view have changed, for example in
|
||||
/// response to the container view or terminal resizing.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Calls <see cref="OnLayoutComplete"/> (which raises the <see cref="LayoutComplete"/> event) before it returns.
|
||||
/// </remarks>
|
||||
public virtual void LayoutSubviews ()
|
||||
{
|
||||
if (!layoutNeeded)
|
||||
return;
|
||||
|
||||
Rect oldBounds = Bounds;
|
||||
|
||||
// Sort out the dependencies of the X, Y, Width, Height properties
|
||||
var nodes = new HashSet<View> ();
|
||||
var edges = new HashSet<(View, View)> ();
|
||||
@@ -1363,6 +1396,8 @@ namespace Terminal.Gui {
|
||||
}
|
||||
|
||||
layoutNeeded = false;
|
||||
|
||||
OnLayoutComplete (new LayoutEventArgs () { OldBounds = oldBounds });
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ToString"/>
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Terminal.Gui {
|
||||
SetValue (searchset [listview.SelectedItem]);
|
||||
};
|
||||
|
||||
Application.Loaded += (object sender, Application.ResizedEventArgs e) => {
|
||||
LayoutComplete += (sender, a) => {
|
||||
// Determine if this view is hosted inside a dialog
|
||||
for (View view = this.SuperView; view != null; view = view.SuperView) {
|
||||
if (view is Dialog) {
|
||||
|
||||
@@ -99,6 +99,8 @@ namespace Terminal.Gui {
|
||||
|
||||
static ustring ClipAndJustify (ustring str, int width, TextAlignment talign)
|
||||
{
|
||||
// Get rid of any '\r' added by Windows
|
||||
str = str.Replace ("\r", ustring.Empty);
|
||||
int slen = str.RuneCount;
|
||||
if (slen > width){
|
||||
var uints = str.ToRunes (width);
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace Terminal.Gui {
|
||||
Width = Dim.Fill ();
|
||||
Height = 1;
|
||||
|
||||
Application.Loaded += (sender, e) => {
|
||||
LayoutComplete += (sender, e) => {
|
||||
X = 0;
|
||||
Height = 1;
|
||||
#if SNAP_TO_TOP
|
||||
@@ -132,7 +132,7 @@ namespace Terminal.Gui {
|
||||
case StatusBarStyle.SnapToBottom:
|
||||
#endif
|
||||
if (Parent == null) {
|
||||
Y = e.Rows - 1;
|
||||
Y = Driver.Rows - 1;
|
||||
} else {
|
||||
Y = Pos.Bottom (Parent);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace Terminal.Gui {
|
||||
Add (b);
|
||||
}
|
||||
}
|
||||
|
||||
//LayoutComplete += (sender, a) => AdjustButtonLayout ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -98,14 +100,13 @@ namespace Terminal.Gui {
|
||||
}
|
||||
return buttons.Select (b => b.Bounds.Width).Sum () + buttons.Count() - 1;
|
||||
}
|
||||
|
||||
///<inheritdoc cref="LayoutSubviews"/>
|
||||
public override void LayoutSubviews ()
|
||||
{
|
||||
int buttonsWidth = GetButtonsWidth ();
|
||||
|
||||
int shiftLeft = Math.Max((Bounds.Width - buttonsWidth) / 2 - 2, 0);
|
||||
for (int i = buttons.Count - 1; i >= 0 ; i--) {
|
||||
int shiftLeft = Math.Max ((Bounds.Width - buttonsWidth) / 2 - 2, 0);
|
||||
for (int i = buttons.Count - 1; i >= 0; i--) {
|
||||
Button button = buttons [i];
|
||||
shiftLeft += button.Frame.Width + 1;
|
||||
button.X = Pos.AnchorEnd (shiftLeft);
|
||||
|
||||
@@ -91,12 +91,11 @@ namespace Terminal.Gui {
|
||||
return QueryFull (true, 0, 0, title, message, buttons);
|
||||
}
|
||||
|
||||
|
||||
static int QueryFull (bool useErrorColors, int width, int height, ustring title, ustring message, params ustring [] buttons)
|
||||
{
|
||||
const int defaultWidth = 30;
|
||||
int textWidth = Label.MaxWidth (message, width);
|
||||
int textHeight = message.Count(ustring.Make('\n')) + 1;
|
||||
int textHeight = message.Count (ustring.Make ('\n')) + 1;
|
||||
int msgboxHeight = Math.Max (1, textHeight) + 4; // textHeight + (top + top padding + buttons + bottom)
|
||||
|
||||
// Create button array for Dialog
|
||||
@@ -126,15 +125,12 @@ namespace Terminal.Gui {
|
||||
|
||||
if (message != null) {
|
||||
var l = new Label (textWidth > width ? 0 : (width - 4 - textWidth) / 2, 1, message);
|
||||
//l.ColorScheme = Colors.Menu;
|
||||
if (true) { //width == 0 & height == 0) {
|
||||
l.LayoutStyle = LayoutStyle.Computed;
|
||||
l.TextAlignment = TextAlignment.Centered;
|
||||
l.X = Pos.Center ();
|
||||
l.Y = Pos.Center ();
|
||||
l.Width = Dim.Fill (2);
|
||||
l.Height = Dim.Fill (2);
|
||||
}
|
||||
l.LayoutStyle = LayoutStyle.Computed;
|
||||
l.TextAlignment = TextAlignment.Centered;
|
||||
l.X = Pos.Center ();
|
||||
l.Y = Pos.Center ();
|
||||
l.Width = Dim.Fill (2);
|
||||
l.Height = Dim.Fill (2);
|
||||
d.Add (l);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace UICatalog {
|
||||
ColorScheme = Colors.Error
|
||||
};
|
||||
|
||||
Application.Resized += (sender, a) => {
|
||||
Win.LayoutComplete += (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)];
|
||||
};
|
||||
|
||||
@@ -121,8 +121,9 @@ namespace UICatalog {
|
||||
};
|
||||
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)];
|
||||
Win.LayoutComplete += (sender, a) => {
|
||||
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)];
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace UICatalog {
|
||||
public override void RequestStop ()
|
||||
{
|
||||
base.RequestStop ();
|
||||
Application.UseSystemConsole = false;
|
||||
}
|
||||
|
||||
public override void Run ()
|
||||
|
||||
@@ -58,6 +58,8 @@ namespace UICatalog {
|
||||
private static StatusItem _scrolllock;
|
||||
|
||||
private static Scenario _runningScenario = null;
|
||||
private static bool _useSystemConsole = false;
|
||||
private static MenuItem _sysConsoleMenu;
|
||||
|
||||
static void Main (string [] args)
|
||||
{
|
||||
@@ -79,6 +81,7 @@ namespace UICatalog {
|
||||
|
||||
Scenario scenario = GetScenarioToRun ();
|
||||
while (scenario != null) {
|
||||
Application.UseSystemConsole = _useSystemConsole;
|
||||
Application.Init ();
|
||||
scenario.Init (Application.Top);
|
||||
scenario.Setup ();
|
||||
@@ -89,20 +92,65 @@ namespace UICatalog {
|
||||
Application.Shutdown ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This shows the selection UI. Each time it is run, it calls Application.Init to reset everything.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static Scenario GetScenarioToRun ()
|
||||
{
|
||||
Application.UseSystemConsole = false;
|
||||
Application.Init ();
|
||||
|
||||
if (_menu == null) {
|
||||
Setup ();
|
||||
}
|
||||
|
||||
_top = Application.Top;
|
||||
|
||||
_top.KeyDown += KeyDownHandler;
|
||||
|
||||
_top.Add (_menu);
|
||||
_top.Add (_leftPane);
|
||||
_top.Add (_rightPane);
|
||||
_top.Add (_statusBar);
|
||||
|
||||
_top.Ready += (o, a) => {
|
||||
if (_runningScenario != null) {
|
||||
_top.SetFocus (_rightPane);
|
||||
_runningScenario = null;
|
||||
}
|
||||
};
|
||||
|
||||
Application.Run (_top, false);
|
||||
Application.Shutdown ();
|
||||
return _runningScenario;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create all controls. This gets called once and the controls remain with their state between Sceanrio runs.
|
||||
/// </summary>
|
||||
private static void Setup ()
|
||||
{
|
||||
StringBuilder aboutMessage = new StringBuilder ();
|
||||
aboutMessage.AppendLine ("UI Catalog is a comprehensive sample library for Terminal.Gui\n");
|
||||
aboutMessage.AppendLine ("UI Catalog is a comprehensive sample library for Terminal.Gui");
|
||||
aboutMessage.AppendLine ("");
|
||||
aboutMessage.AppendLine ($"Version: {typeof(UICatalogApp).Assembly.GetName ().Version}");
|
||||
aboutMessage.Append ($"Using Terminal.Gui Version: {typeof (Terminal.Gui.Application).Assembly.GetName ().Version}\n");
|
||||
aboutMessage.AppendLine ($"Using Terminal.Gui Version: {typeof (Terminal.Gui.Application).Assembly.GetName ().Version}");
|
||||
aboutMessage.AppendLine ("");
|
||||
|
||||
void HandleSysConsoleMenuChange ()
|
||||
{
|
||||
_useSystemConsole = !_useSystemConsole;
|
||||
_sysConsoleMenu.Title = $"[{(_useSystemConsole ? 'x' : ' ')}] _Use System Console";
|
||||
}
|
||||
_sysConsoleMenu = new MenuItem ($"[{(_useSystemConsole ? 'x' : ' ')}] _Use System Console", "", () => HandleSysConsoleMenuChange ());
|
||||
|
||||
_menu = new MenuBar (new MenuBarItem [] {
|
||||
new MenuBarItem ("_File", new MenuItem [] {
|
||||
new MenuItem ("_Quit", "", () => Application.RequestStop() )
|
||||
}),
|
||||
new MenuBarItem ("_Settings", new MenuItem [] { _sysConsoleMenu }),
|
||||
new MenuBarItem ("_About...", "About this app", () => MessageBox.Query ("About UI Catalog", aboutMessage.ToString(), "Ok")),
|
||||
});
|
||||
|
||||
@@ -150,24 +198,17 @@ namespace UICatalog {
|
||||
CanFocus = true,
|
||||
};
|
||||
|
||||
//_scenarioListView.OnKeyPress += (KeyEvent ke) => {
|
||||
// if (_top.MostFocused == _scenarioListView && ke.Key == Key.Enter) {
|
||||
// _scenarioListView_OpenSelectedItem (null, null);
|
||||
// }
|
||||
//};
|
||||
|
||||
_scenarioListView.OpenSelectedItem += _scenarioListView_OpenSelectedItem;
|
||||
_rightPane.Add (_scenarioListView);
|
||||
|
||||
_categoryListView.SelectedItem = 0;
|
||||
_categoryListView.OnSelectedChanged ();
|
||||
|
||||
_capslock = new StatusItem (Key.CharMask, "CapslockOff", null);
|
||||
_numlock = new StatusItem (Key.CharMask, "NumlockOff", null);
|
||||
_scrolllock = new StatusItem (Key.CharMask, "ScrolllockOff", null);
|
||||
_capslock = new StatusItem (Key.CharMask, "Capslock", null);
|
||||
_numlock = new StatusItem (Key.CharMask, "Numlock", null);
|
||||
_scrolllock = new StatusItem (Key.CharMask, "Scrolllock", null);
|
||||
|
||||
_statusBar = new StatusBar (new StatusItem [] {
|
||||
//new StatusItem(Key.F1, "~F1~ Help", () => Help()),
|
||||
new StatusItem(Key.ControlQ, "~CTRL-Q~ Quit", () => {
|
||||
if (_runningScenario is null){
|
||||
// This causes GetScenarioToRun to return null
|
||||
@@ -183,51 +224,6 @@ namespace UICatalog {
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This shows the selection UI. Each time it is run, it calls Application.Init to reset everything.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static Scenario GetScenarioToRun ()
|
||||
{
|
||||
Application.Init ();
|
||||
|
||||
if (_menu == null) {
|
||||
Setup ();
|
||||
}
|
||||
|
||||
_top = Application.Top;
|
||||
|
||||
_top.KeyDown += KeyDownHandler;
|
||||
|
||||
_top.Add (_menu);
|
||||
_top.Add (_leftPane);
|
||||
_top.Add (_rightPane);
|
||||
_top.Add (_statusBar);
|
||||
|
||||
// HACK: There is no other way to SetFocus before Application.Run. See Issue #445
|
||||
#if false
|
||||
if (_runningScenario != null)
|
||||
Application.Iteration += Application_Iteration;
|
||||
#else
|
||||
_top.Ready += (o, a) => {
|
||||
if (_runningScenario != null) {
|
||||
_top.SetFocus (_rightPane);
|
||||
_runningScenario = null;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
Application.Run (_top, false);
|
||||
return _runningScenario;
|
||||
}
|
||||
|
||||
#if false
|
||||
private static void Application_Iteration (object sender, EventArgs e)
|
||||
{
|
||||
Application.Iteration -= Application_Iteration;
|
||||
_top.SetFocus (_rightPane);
|
||||
}
|
||||
#endif
|
||||
private static void _scenarioListView_OpenSelectedItem (object sender, EventArgs e)
|
||||
{
|
||||
if (_runningScenario is null) {
|
||||
@@ -240,7 +236,7 @@ namespace UICatalog {
|
||||
internal class ScenarioListDataSource : IListDataSource {
|
||||
public List<Type> Scenarios { get; set; }
|
||||
|
||||
public bool IsMarked (int item) => false;// Scenarios [item].IsMarked;
|
||||
public bool IsMarked (int item) => false;
|
||||
|
||||
public int Count => Scenarios.Count;
|
||||
|
||||
@@ -282,7 +278,6 @@ namespace UICatalog {
|
||||
{
|
||||
return Scenarios;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -293,15 +288,7 @@ namespace UICatalog {
|
||||
/// <param name="ke"></param>
|
||||
private static void KeyDownHandler (object sender, View.KeyEventEventArgs a)
|
||||
{
|
||||
if (_runningScenario != null) {
|
||||
//switch (ke.Key) {
|
||||
//case Key.Esc:
|
||||
// //_runningScenario.RequestStop ();
|
||||
// break;
|
||||
//case Key.Enter:
|
||||
// break;
|
||||
//}<
|
||||
} else if (a.KeyEvent.Key == Key.Tab || a.KeyEvent.Key == Key.BackTab) {
|
||||
if (a.KeyEvent.Key == Key.Tab || a.KeyEvent.Key == Key.BackTab) {
|
||||
// BUGBUG: Work around Issue #434 by implementing our own TAB navigation
|
||||
if (_top.MostFocused == _categoryListView)
|
||||
_top.SetFocus (_rightPane);
|
||||
@@ -310,26 +297,26 @@ namespace UICatalog {
|
||||
}
|
||||
|
||||
if (a.KeyEvent.IsCapslock) {
|
||||
_capslock.Title = "CapslockOn";
|
||||
_capslock.Title = "Capslock: On";
|
||||
_statusBar.SetNeedsDisplay ();
|
||||
} else {
|
||||
_capslock.Title = "CapslockOff";
|
||||
_capslock.Title = "Capslock: Off";
|
||||
_statusBar.SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
if (a.KeyEvent.IsNumlock) {
|
||||
_numlock.Title = "NumlockOn";
|
||||
_numlock.Title = "Numlock: On";
|
||||
_statusBar.SetNeedsDisplay ();
|
||||
} else {
|
||||
_numlock.Title = "NumlockOff";
|
||||
_numlock.Title = "Numlock: Off";
|
||||
_statusBar.SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
if (a.KeyEvent.IsScrolllock) {
|
||||
_scrolllock.Title = "ScrolllockOn";
|
||||
_scrolllock.Title = "Scrolllock: On";
|
||||
_statusBar.SetNeedsDisplay ();
|
||||
} else {
|
||||
_scrolllock.Title = "ScrolllockOff";
|
||||
_scrolllock.Title = "Scrolllock: Off";
|
||||
_statusBar.SetNeedsDisplay ();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user