diff --git a/UICatalog/Scenario.cs b/UICatalog/Scenario.cs
index 797cf09a6..e2a28fbcd 100644
--- a/UICatalog/Scenario.cs
+++ b/UICatalog/Scenario.cs
@@ -73,7 +73,7 @@ namespace UICatalog {
/// Overrides that do not call the base., must call before creating any views or calling other Terminal.Gui APIs.
///
///
- public virtual void Init(Toplevel top, ColorScheme colorScheme)
+ public virtual void Init (Toplevel top, ColorScheme colorScheme)
{
Application.Init ();
@@ -177,7 +177,14 @@ namespace UICatalog {
/// list of category names
public List GetCategories () => ScenarioCategory.GetCategories (this.GetType ());
- public override string ToString () => $"{GetName (),-30}{GetDescription ()}";
+ private static int _maxScenarioNameLen = 30;
+
+ ///
+ /// Gets the Scenario Name + Description with the Description padded
+ /// based on the longest known Scenario name.
+ ///
+ ///
+ public override string ToString () => $"{GetName ().PadRight(_maxScenarioNameLen)}{GetDescription ()}";
///
/// Override this to implement the setup logic (create controls, etc...).
@@ -232,12 +239,14 @@ namespace UICatalog {
/// Returns an instance of each defined in the project.
/// https://stackoverflow.com/questions/5411694/get-all-inherited-classes-of-an-abstract-class
///
- public static List GetDerivedClasses ()
+ public static List GetScenarios ()
{
- List objects = new List ();
- foreach (Type type in typeof (T).Assembly.GetTypes ()
- .Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (T)))) {
- objects.Add (type);
+ List objects = new List ();
+ foreach (Type type in typeof (Scenario).Assembly.ExportedTypes
+ .Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (Scenario)))) {
+ var scenario = (Scenario)Activator.CreateInstance (type);
+ objects.Add (scenario);
+ _maxScenarioNameLen = Math.Max (_maxScenarioNameLen, scenario.GetName ().Length + 1);
}
return objects;
}
diff --git a/UICatalog/Scenarios/ListViewWithSelection.cs b/UICatalog/Scenarios/ListViewWithSelection.cs
index 057dcb693..bd1afc40b 100644
--- a/UICatalog/Scenarios/ListViewWithSelection.cs
+++ b/UICatalog/Scenarios/ListViewWithSelection.cs
@@ -3,6 +3,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Nodes;
using Terminal.Gui;
using Attribute = Terminal.Gui.Attribute;
@@ -16,11 +17,13 @@ namespace UICatalog.Scenarios {
public CheckBox _allowMultipleCB;
public ListView _listView;
- public List _scenarios = Scenario.GetDerivedClasses().OrderBy (t => Scenario.ScenarioMetadata.GetName (t)).ToList ();
+ public List _scenarios;
public override void Setup ()
{
- _customRenderCB = new CheckBox ("Render with columns") {
+ _scenarios = Scenario.GetScenarios ().OrderBy (s => s.GetName ()).ToList ();
+
+ _customRenderCB = new CheckBox ("Use custom rendering") {
X = 0,
Y = 0,
Height = 1,
@@ -137,11 +140,11 @@ namespace UICatalog.Scenarios {
// This is basically the same implementation used by the UICatalog main window
internal class ScenarioListDataSource : IListDataSource {
int _nameColumnWidth = 30;
- private List scenarios;
+ private List scenarios;
BitArray marks;
int count, len;
- public List Scenarios {
+ public List Scenarios {
get => scenarios;
set {
if (value != null) {
@@ -163,14 +166,14 @@ namespace UICatalog.Scenarios {
public int Length => len;
- public ScenarioListDataSource (List itemList) => Scenarios = itemList;
+ public ScenarioListDataSource (List itemList) => Scenarios = itemList;
public void Render (ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start = 0)
{
container.Move (col, line);
// Equivalent to an interpolated string like $"{Scenarios[item].Name, -widtestname}"; if such a thing were possible
- var s = String.Format (String.Format ("{{0,{0}}}", -_nameColumnWidth), Scenario.ScenarioMetadata.GetName (Scenarios [item]));
- RenderUstr (driver, $"{s} {Scenario.ScenarioMetadata.GetDescription (Scenarios [item])}", col, line, width, start);
+ var s = String.Format (String.Format ("{{0,{0}}}", -_nameColumnWidth), Scenarios [item].GetName ());
+ RenderUstr (driver, $"{s} ({Scenarios [item].GetDescription ()})", col, line, width, start);
}
public void SetMark (int item, bool value)
@@ -187,8 +190,8 @@ namespace UICatalog.Scenarios {
int maxLength = 0;
for (int i = 0; i < scenarios.Count; i++) {
- var s = String.Format (String.Format ("{{0,{0}}}", -_nameColumnWidth), Scenario.ScenarioMetadata.GetName (Scenarios [i]));
- var sc = $"{s} {Scenario.ScenarioMetadata.GetDescription (Scenarios [i])}";
+ var s = String.Format (String.Format ("{{0,{0}}}", -_nameColumnWidth), Scenarios [i].GetName ());
+ var sc = $"{s} {Scenarios [i].GetDescription ()}";
var l = sc.Length;
if (l > maxLength) {
maxLength = l;
diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs
index 9949c337f..cd625730a 100644
--- a/UICatalog/UICatalog.cs
+++ b/UICatalog/UICatalog.cs
@@ -1,6 +1,5 @@
using NStack;
using System;
-using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
@@ -46,56 +45,73 @@ namespace UICatalog {
/// UI Catalog is a comprehensive sample app and scenario library for
///
public class UICatalogApp {
- private static Toplevel _top;
- private static MenuBar _menu;
private static int _nameColumnWidth;
private static FrameView _leftPane;
private static List _categories;
private static ListView _categoryListView;
private static FrameView _rightPane;
- private static List _scenarios;
+ private static List _scenarios;
private static ListView _scenarioListView;
private static StatusBar _statusBar;
private static StatusItem _capslock;
private static StatusItem _numlock;
private static StatusItem _scrolllock;
- private static int _categoryListViewItem;
- private static int _scenarioListViewItem;
- private static Scenario _runningScenario = null;
+ private static Scenario _selectedScenario = null;
private static bool _useSystemConsole = false;
private static ConsoleDriver.DiagnosticFlags _diagnosticFlags;
private static bool _heightAsBuffer = false;
private static bool _isFirstRunning = true;
+ // When a scenario is run, the main app is killed. These items
+ // are therefore cached so that when the scenario exits the
+ // main app UI can be restored to previous state
+ private static int _cachedScenarioIndex = 0;
+ private static int _cachedCategoryIndex = 0;
+
+ private static StringBuilder _aboutMessage;
+
static void Main (string [] args)
{
Console.OutputEncoding = Encoding.Default;
- if (Debugger.IsAttached)
+ if (Debugger.IsAttached) {
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
+ }
- _scenarios = Scenario.GetDerivedClasses ().OrderBy (t => Scenario.ScenarioMetadata.GetName (t)).ToList ();
+ _scenarios = Scenario.GetScenarios ();
if (args.Length > 0 && args.Contains ("-usc")) {
_useSystemConsole = true;
args = args.Where (val => val != "-usc").ToArray ();
}
if (args.Length > 0) {
- var item = _scenarios.FindIndex (t => Scenario.ScenarioMetadata.GetName (t).Equals (args [0], StringComparison.OrdinalIgnoreCase));
- _runningScenario = (Scenario)Activator.CreateInstance (_scenarios [item]);
+ var item = _scenarios.FindIndex (s => s.GetName ().Equals (args [0], StringComparison.OrdinalIgnoreCase));
+ _selectedScenario = (Scenario)Activator.CreateInstance (_scenarios [item].GetType ());
Application.UseSystemConsole = _useSystemConsole;
Application.Init ();
- _runningScenario.Init (Application.Top, _baseColorScheme);
- _runningScenario.Setup ();
- _runningScenario.Run ();
- _runningScenario = null;
+ _selectedScenario.Init (Application.Top, _colorScheme);
+ _selectedScenario.Setup ();
+ _selectedScenario.Run ();
+ _selectedScenario = null;
Application.Shutdown ();
return;
}
+ _aboutMessage = new StringBuilder ();
+ _aboutMessage.AppendLine (@"A comprehensive sample library for");
+ _aboutMessage.AppendLine (@"");
+ _aboutMessage.AppendLine (@" _______ _ _ _____ _ ");
+ _aboutMessage.AppendLine (@" |__ __| (_) | | / ____| (_) ");
+ _aboutMessage.AppendLine (@" | | ___ _ __ _ __ ___ _ _ __ __ _| || | __ _ _ _ ");
+ _aboutMessage.AppendLine (@" | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | || | |_ | | | | | ");
+ _aboutMessage.AppendLine (@" | | __/ | | | | | | | | | | | (_| | || |__| | |_| | | ");
+ _aboutMessage.AppendLine (@" |_|\___|_| |_| |_| |_|_|_| |_|\__,_|_(_)_____|\__,_|_| ");
+ _aboutMessage.AppendLine (@"");
+ _aboutMessage.AppendLine (@"https://github.com/gui-cs/Terminal.Gui");
+
Scenario scenario;
- while ((scenario = GetScenarioToRun ()) != null) {
+ while ((scenario = SelectScenario ()) != null) {
#if DEBUG_IDISPOSABLE
// Validate there are no outstanding Responder-based instances
// after a scenario was selected to run. This proves the main UI Catalog
@@ -106,18 +122,12 @@ namespace UICatalog {
Responder.Instances.Clear ();
#endif
- scenario.Init (Application.Top, _baseColorScheme);
+ scenario.Init (Application.Top, _colorScheme);
scenario.Setup ();
scenario.Run ();
- //static void LoadedHandler ()
- //{
- // _rightPane.SetFocus ();
- // _top.Loaded -= LoadedHandler;
- //}
-
- //_top.Loaded += LoadedHandler;
-
+ // This call to Application.Shutdown brackets the Application.Init call
+ // made by Scenario.Init()
Application.Shutdown ();
#if DEBUG_IDISPOSABLE
@@ -130,7 +140,9 @@ namespace UICatalog {
#endif
}
- Application.Shutdown ();
+ // This call to Application.Shutdown brackets the Application.Init call
+ // for the main UI Catalog app (in SelectScenario()).
+ //Application.Shutdown ();
#if DEBUG_IDISPOSABLE
// This proves that when the user exited the UI Catalog app
@@ -143,31 +155,24 @@ namespace UICatalog {
}
///
- /// This shows the selection UI. Each time it is run, it calls Application.Init to reset everything.
+ /// Shows the UI Catalog selection UI. When the user selects a Scenario to run, the
+ /// UI Catalog main app UI is killed and the Scenario is run as though it were Application.Top.
+ /// When the Scenario exits, this function exits.
///
///
- private static Scenario GetScenarioToRun ()
+ private static Scenario SelectScenario ()
{
Application.UseSystemConsole = _useSystemConsole;
Application.Init ();
+ if (_colorScheme == null) {
+ // `Colors` is not initilized until the ConsoleDriver is loaded by
+ // Application.Init. Set it only the first time though so it is
+ // preserved between running multiple Scenarios
+ _colorScheme = Colors.Base;
+ }
Application.HeightAsBuffer = _heightAsBuffer;
- // Set this here because not initialized until driver is loaded
- _baseColorScheme = Colors.Base;
-
- StringBuilder aboutMessage = new StringBuilder ();
- aboutMessage.AppendLine (@"A comprehensive sample library for");
- aboutMessage.AppendLine (@"");
- aboutMessage.AppendLine (@" _______ _ _ _____ _ ");
- aboutMessage.AppendLine (@" |__ __| (_) | | / ____| (_) ");
- aboutMessage.AppendLine (@" | | ___ _ __ _ __ ___ _ _ __ __ _| || | __ _ _ _ ");
- aboutMessage.AppendLine (@" | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | || | |_ | | | | | ");
- aboutMessage.AppendLine (@" | | __/ | | | | | | | | | | | (_| | || |__| | |_| | | ");
- aboutMessage.AppendLine (@" |_|\___|_| |_| |_| |_|_|_| |_|\__,_|_(_)_____|\__,_|_| ");
- aboutMessage.AppendLine (@"");
- aboutMessage.AppendLine (@"https://github.com/gui-cs/Terminal.Gui");
-
- _menu = new MenuBar (new MenuBarItem [] {
+ var menu = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_File", new MenuItem [] {
new MenuItem ("_Quit", "Quit UI Catalog", () => Application.RequestStop(), null, null, Key.Q | Key.CtrlMask)
}),
@@ -177,7 +182,7 @@ namespace UICatalog {
new MenuItem ("_gui.cs API Overview", "", () => OpenUrl ("https://gui-cs.github.io/Terminal.Gui/articles/overview.html"), null, null, Key.F1),
new MenuItem ("gui.cs _README", "", () => OpenUrl ("https://github.com/gui-cs/Terminal.Gui"), null, null, Key.F2),
new MenuItem ("_About...",
- "About UI Catalog", () => MessageBox.Query ("About UI Catalog", aboutMessage.ToString(), "_Ok"), null, null, Key.CtrlMask | Key.A),
+ "About UI Catalog", () => MessageBox.Query ("About UI Catalog", _aboutMessage.ToString(), "_Ok"), null, null, Key.CtrlMask | Key.A),
}),
});
@@ -186,7 +191,7 @@ namespace UICatalog {
Y = 1, // for menu
Width = 25,
Height = Dim.Fill (1),
- CanFocus = false,
+ CanFocus = true,
Shortcut = Key.CtrlMask | Key.C
};
_leftPane.Title = $"{_leftPane.Title} ({_leftPane.ShortcutTag})";
@@ -218,7 +223,7 @@ namespace UICatalog {
_rightPane.Title = $"{_rightPane.Title} ({_rightPane.ShortcutTag})";
_rightPane.ShortcutAction = () => _rightPane.SetFocus ();
- _nameColumnWidth = Scenario.ScenarioMetadata.GetName (_scenarios.OrderByDescending (t => Scenario.ScenarioMetadata.GetName (t).Length).FirstOrDefault ()).Length;
+ _nameColumnWidth = _scenarios.OrderByDescending (s => s.GetName ().Length).FirstOrDefault ().GetName ().Length;
_scenarioListView = new ListView () {
X = 0,
@@ -232,9 +237,6 @@ namespace UICatalog {
_scenarioListView.OpenSelectedItem += _scenarioListView_OpenSelectedItem;
_rightPane.Add (_scenarioListView);
- _categoryListView.SelectedItem = _categoryListViewItem;
- _categoryListView.OnSelectedChanged ();
-
_capslock = new StatusItem (Key.CharMask, "Caps", null);
_numlock = new StatusItem (Key.CharMask, "Num", null);
_scrolllock = new StatusItem (Key.CharMask, "Scroll", null);
@@ -247,60 +249,76 @@ namespace UICatalog {
_numlock,
_scrolllock,
new StatusItem(Key.Q | Key.CtrlMask, "~CTRL-Q~ Quit", () => {
- if (_runningScenario is null){
+ if (_selectedScenario is null){
// This causes GetScenarioToRun to return null
- _runningScenario = null;
+ _selectedScenario = null;
Application.RequestStop();
} else {
- _runningScenario.RequestStop();
+ _selectedScenario.RequestStop();
}
}),
new StatusItem(Key.F10, "~F10~ Hide/Show Status Bar", () => {
_statusBar.Visible = !_statusBar.Visible;
_leftPane.Height = Dim.Fill(_statusBar.Visible ? 1 : 0);
_rightPane.Height = Dim.Fill(_statusBar.Visible ? 1 : 0);
- _top.LayoutSubviews();
- _top.SetChildNeedsDisplay();
+ Application.Top.LayoutSubviews();
+ Application.Top.SetChildNeedsDisplay();
}),
new StatusItem (Key.CharMask, Application.Driver.GetType ().Name, null),
};
- SetColorScheme ();
- _top = Application.Top;
- _top.KeyDown += KeyDownHandler;
- _top.Add (_menu);
- _top.Add (_leftPane);
- _top.Add (_rightPane);
- _top.Add (_statusBar);
+ Application.Top.ColorScheme = _colorScheme;
+ Application.Top.KeyDown += KeyDownHandler;
+ Application.Top.Add (menu);
+ Application.Top.Add (_leftPane);
+ Application.Top.Add (_rightPane);
+ Application.Top.Add (_statusBar);
- void TopHandler () {
- if (_runningScenario != null) {
- _runningScenario = null;
+ void TopHandler ()
+ {
+ if (_selectedScenario != null) {
+ _selectedScenario = null;
_isFirstRunning = false;
}
if (!_isFirstRunning) {
_rightPane.SetFocus ();
}
- _top.Loaded -= TopHandler;
+ Application.Top.Loaded -= TopHandler;
}
- _top.Loaded += TopHandler;
- // The following code was moved to the TopHandler event
- // because in the MainLoop.EventsPending (wait)
- // from the Application.RunLoop with the WindowsDriver
- // the OnReady event is triggered due the Focus event.
- // On CursesDriver and NetDriver the focus event won't be triggered
- // and if it's possible I don't know how to do it.
- //void ReadyHandler ()
- //{
- // if (!_isFirstRunning) {
- // _rightPane.SetFocus ();
- // }
- // _top.Ready -= ReadyHandler;
- //}
- //_top.Ready += ReadyHandler;
+ Application.Top.Loaded += TopHandler;
- Application.Run (_top);
- return _runningScenario;
+ // Restore previous selections
+ _categoryListView.SelectedItem = _cachedCategoryIndex;
+ _scenarioListView.SelectedItem = _cachedScenarioIndex;
+
+ // Run UI Catalog UI. When it exits, if _runningScenario is != null then
+ // a Scenario was selected. Otherwise, the user wants to exit UI Catalog.
+ Application.Run (Application.Top);
+
+ // BUGBUG: Shouldn't Application.Shutdown() be called here? Why is it currently
+ // outside of the SelectScenario() loop?
+ Application.Shutdown ();
+
+ return _selectedScenario;
+ }
+
+
+ ///
+ /// Launches the selected scenario, setting the global _runningScenario
+ ///
+ ///
+ private static void _scenarioListView_OpenSelectedItem (EventArgs e)
+ {
+ if (_selectedScenario is null) {
+ // Save selected item state
+ _cachedCategoryIndex = _categoryListView.SelectedItem;
+ _cachedScenarioIndex = _scenarioListView.SelectedItem;
+ // Create new instance of scenario (even though Scenarios contains instances)
+ _selectedScenario = (Scenario)Activator.CreateInstance (_scenarioListView.Source.ToList () [_scenarioListView.SelectedItem].GetType ());
+
+ // Tell the main app to stop
+ Application.RequestStop ();
+ }
}
static List