diff --git a/Example/demo.cs b/Example/demo.cs
index 272810f4b..0e431422a 100644
--- a/Example/demo.cs
+++ b/Example/demo.cs
@@ -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);
diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs
index d72a55595..ca42eb848 100644
--- a/Terminal.Gui/Core/Application.cs
+++ b/Terminal.Gui/Core/Application.cs
@@ -481,6 +481,7 @@ namespace Terminal.Gui {
if (closeDriver) {
MainLoop = null;
Driver.End ();
+ Driver = null;
}
_initialized = false;
diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs
index bb647bf21..4e2c6ca1d 100644
--- a/Terminal.Gui/Core/Toplevel.cs
+++ b/Terminal.Gui/Core/Toplevel.cs
@@ -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) {
diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index fa5988253..1d50cfe5b 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -911,9 +911,12 @@ namespace Terminal.Gui {
///
/// Redraws this view and its subviews; only redraws the views that have been flagged for a re-display.
///
- /// The view-relative region to redraw.
+ /// The bounds (view-relative region) to redraw.
///
///
+ /// Always use (view-relative) when calling , NOT (superview-relative).
+ ///
+ ///
/// 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.
///
@@ -1318,15 +1321,45 @@ namespace Terminal.Gui {
}
///
- /// Invoked when a view starts executing or
- /// when the dimensions of the view have changed, for example in
+ /// Event arguments for the event.
+ ///
+ public class LayoutEventArgs : EventArgs {
+ ///
+ /// The view-relative bounds of the before it was laid out.
+ ///
+ public Rect OldBounds { get; set; }
+ }
+
+ ///
+ /// Fired after the Views's method has completed.
+ ///
+ ///
+ /// Subscribe to this event to perform tasks when the has been resized or the layout has otherwise changed.
+ ///
+ public event EventHandler LayoutComplete;
+
+ ///
+ /// Raises the event. Called from after all sub-views have been laid out.
+ ///
+ internal virtual void OnLayoutComplete (LayoutEventArgs args)
+ {
+ LayoutComplete?.Invoke (this, args);
+ }
+
+ ///
+ /// 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.
///
+ ///
+ /// Calls (which raises the event) before it returns.
+ ///
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 ();
var edges = new HashSet<(View, View)> ();
@@ -1363,6 +1396,8 @@ namespace Terminal.Gui {
}
layoutNeeded = false;
+
+ OnLayoutComplete (new LayoutEventArgs () { OldBounds = oldBounds });
}
///
diff --git a/Terminal.Gui/Views/ComboBox.cs b/Terminal.Gui/Views/ComboBox.cs
index e5ff53dce..a89879f8d 100644
--- a/Terminal.Gui/Views/ComboBox.cs
+++ b/Terminal.Gui/Views/ComboBox.cs
@@ -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) {
diff --git a/Terminal.Gui/Views/Label.cs b/Terminal.Gui/Views/Label.cs
index 361d66d8f..af56003c2 100644
--- a/Terminal.Gui/Views/Label.cs
+++ b/Terminal.Gui/Views/Label.cs
@@ -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);
diff --git a/Terminal.Gui/Views/StatusBar.cs b/Terminal.Gui/Views/StatusBar.cs
index bf298816d..1fd3448d6 100644
--- a/Terminal.Gui/Views/StatusBar.cs
+++ b/Terminal.Gui/Views/StatusBar.cs
@@ -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);
}
diff --git a/Terminal.Gui/Windows/Dialog.cs b/Terminal.Gui/Windows/Dialog.cs
index 904d73491..1455ebacd 100644
--- a/Terminal.Gui/Windows/Dialog.cs
+++ b/Terminal.Gui/Windows/Dialog.cs
@@ -61,6 +61,8 @@ namespace Terminal.Gui {
Add (b);
}
}
+
+ //LayoutComplete += (sender, a) => AdjustButtonLayout ();
}
///
@@ -98,14 +100,13 @@ namespace Terminal.Gui {
}
return buttons.Select (b => b.Bounds.Width).Sum () + buttons.Count() - 1;
}
-
///
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);
diff --git a/Terminal.Gui/Windows/MessageBox.cs b/Terminal.Gui/Windows/MessageBox.cs
index a95b9c3ee..3ade88f57 100644
--- a/Terminal.Gui/Windows/MessageBox.cs
+++ b/Terminal.Gui/Windows/MessageBox.cs
@@ -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);
}
diff --git a/UICatalog/Scenarios/ComputedLayout.cs b/UICatalog/Scenarios/ComputedLayout.cs
index 6bbb4dbe8..0ca45c525 100644
--- a/UICatalog/Scenarios/ComputedLayout.cs
+++ b/UICatalog/Scenarios/ComputedLayout.cs
@@ -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)];
};
diff --git a/UICatalog/Scenarios/Scrolling.cs b/UICatalog/Scenarios/Scrolling.cs
index 64197021d..da989d02f 100644
--- a/UICatalog/Scenarios/Scrolling.cs
+++ b/UICatalog/Scenarios/Scrolling.cs
@@ -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)];
};
diff --git a/UICatalog/Scenarios/SystemConsole.cs b/UICatalog/Scenarios/SystemConsole.cs
index a08bea893..a27ce5789 100644
--- a/UICatalog/Scenarios/SystemConsole.cs
+++ b/UICatalog/Scenarios/SystemConsole.cs
@@ -14,6 +14,7 @@ namespace UICatalog {
public override void RequestStop ()
{
base.RequestStop ();
+ Application.UseSystemConsole = false;
}
public override void Run ()
diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs
index 90fa27a34..d48441e10 100644
--- a/UICatalog/UICatalog.cs
+++ b/UICatalog/UICatalog.cs
@@ -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 ();
}
+ ///
+ /// This shows the selection UI. Each time it is run, it calls Application.Init to reset everything.
+ ///
+ ///
+ 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;
+ }
+
+
///
/// Create all controls. This gets called once and the controls remain with their state between Sceanrio runs.
///
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 {
});
}
- ///
- /// This shows the selection UI. Each time it is run, it calls Application.Init to reset everything.
- ///
- ///
- 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 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;
}
-
}
///
@@ -293,15 +288,7 @@ namespace UICatalog {
///
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 ();
}
}