using NStack;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Terminal.Gui;
using Microsoft.DotNet.PlatformAbstractions;
using Rune = System.Rune;
///
/// UI Catalog is a comprehensive sample library for Terminal.Gui. It provides a simple UI for adding to the catalog of scenarios.
///
///
///
/// UI Catalog attempts to satisfy the following goals:
///
///
///
/// -
///
/// Be an easy to use showcase for Terminal.Gui concepts and features.
///
///
/// -
///
/// Provide sample code that illustrates how to properly implement said concepts & features.
///
///
/// -
///
/// Make it easy for contributors to add additional samples in a structured way.
///
///
///
///
///
/// See the project README for more details (https://github.com/gui-cs/Terminal.Gui/tree/master/UICatalog/README.md).
///
///
namespace UICatalog {
///
/// UI Catalog is a comprehensive sample app and scenario library for
///
class UICatalogApp {
static void Main (string [] args)
{
Console.OutputEncoding = Encoding.Default;
if (Debugger.IsAttached) {
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
}
_scenarios = Scenario.GetScenarios ();
_categories = Scenario.GetAllCategories ();
_nameColumnWidth = _scenarios.OrderByDescending (s => s.GetName ().Length).FirstOrDefault ().GetName ().Length;
if (args.Length > 0 && args.Contains ("-usc")) {
_useSystemConsole = true;
args = args.Where (val => val != "-usc").ToArray ();
}
// If a Scenario name has been provided on the commandline
// run it and exit when done.
if (args.Length > 0) {
var item = _scenarios.FindIndex (s => s.GetName ().Equals (args [0], StringComparison.OrdinalIgnoreCase));
_selectedScenario = (Scenario)Activator.CreateInstance (_scenarios [item].GetType ());
Application.UseSystemConsole = _useSystemConsole;
Application.Init ();
_selectedScenario.Init (_colorScheme);
_selectedScenario.Setup ();
_selectedScenario.Run ();
_selectedScenario.Dispose ();
_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 = RunUICatalogTopLevel ()) != null) {
VerifyObjectsWereDisposed ();
scenario.Init (_colorScheme);
scenario.Setup ();
scenario.Run ();
scenario.Dispose ();
// This call to Application.Shutdown brackets the Application.Init call
// made by Scenario.Init() above
Application.Shutdown ();
VerifyObjectsWereDisposed ();
}
VerifyObjectsWereDisposed ();
}
///
/// 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.
///
///
static Scenario RunUICatalogTopLevel ()
{
Application.UseSystemConsole = _useSystemConsole;
// Run UI Catalog UI. When it exits, if _selectedScenario is != null then
// a Scenario was selected. Otherwise, the user wants to exit UI Catalog.
Application.Init ();
Application.Run ();
Application.Shutdown ();
return _selectedScenario;
}
static List _scenarios;
static List _categories;
static int _nameColumnWidth;
// 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
static int _cachedScenarioIndex = 0;
static int _cachedCategoryIndex = 0;
static StringBuilder _aboutMessage;
// If set, holds the scenario the user selected
static Scenario _selectedScenario = null;
static bool _useSystemConsole = false;
static ConsoleDriver.DiagnosticFlags _diagnosticFlags;
static bool _isFirstRunning = true;
static ColorScheme _colorScheme;
///
/// This is the main UI Catalog app view. It is run fresh when the app loads (if a Scenario has not been passed on
/// the command line) and each time a Scenario ends.
///
class UICatalogTopLevel : Toplevel {
public MenuItem miIsMouseDisabled;
public FrameView LeftPane;
public ListView CategoryListView;
public FrameView RightPane;
public ListView ScenarioListView;
public StatusItem Capslock;
public StatusItem Numlock;
public StatusItem Scrolllock;
public StatusItem DriverName;
public StatusItem OS;
public UICatalogTopLevel ()
{
ColorScheme = _colorScheme = Colors.Base;
MenuBar = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_File", new MenuItem [] {
new MenuItem ("_Quit", "Quit UI Catalog", () => RequestStop(), null, null, Key.Q | Key.CtrlMask)
}),
new MenuBarItem ("_Color Scheme", CreateColorSchemeMenuItems()),
new MenuBarItem ("Diag_nostics", CreateDiagnosticMenuItems()),
new MenuBarItem ("_Help", new MenuItem [] {
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),
}),
});
Capslock = new StatusItem (Key.CharMask, "Caps", null);
Numlock = new StatusItem (Key.CharMask, "Num", null);
Scrolllock = new StatusItem (Key.CharMask, "Scroll", null);
DriverName = new StatusItem (Key.CharMask, "Driver:", null);
OS = new StatusItem (Key.CharMask, "OS:", null);
StatusBar = new StatusBar () {
Visible = true,
};
StatusBar.Items = new StatusItem [] {
new StatusItem(Key.Q | Key.CtrlMask, "~CTRL-Q~ Quit", () => {
if (_selectedScenario is null){
// This causes GetScenarioToRun to return null
_selectedScenario = null;
RequestStop();
} else {
_selectedScenario.RequestStop();
}
}),
new StatusItem(Key.F10, "~F10~ Status Bar", () => {
StatusBar.Visible = !StatusBar.Visible;
LeftPane.Height = Dim.Fill(StatusBar.Visible ? 1 : 0);
RightPane.Height = Dim.Fill(StatusBar.Visible ? 1 : 0);
LayoutSubviews();
SetChildNeedsDisplay();
}),
DriverName,
OS
};
LeftPane = new FrameView ("Categories") {
X = 0,
Y = 1, // for menu
Width = 25,
Height = Dim.Fill (1),
CanFocus = true,
Shortcut = Key.CtrlMask | Key.C
};
LeftPane.Title = $"{LeftPane.Title} ({LeftPane.ShortcutTag})";
LeftPane.ShortcutAction = () => LeftPane.SetFocus ();
CategoryListView = new ListView (_categories) {
X = 0,
Y = 0,
Width = Dim.Fill (0),
Height = Dim.Fill (0),
AllowsMarking = false,
CanFocus = true,
};
CategoryListView.OpenSelectedItem += (a) => {
RightPane.SetFocus ();
};
CategoryListView.SelectedItemChanged += CategoryListView_SelectedChanged;
LeftPane.Add (CategoryListView);
RightPane = new FrameView ("Scenarios") {
X = 25,
Y = 1, // for menu
Width = Dim.Fill (),
Height = Dim.Fill (1),
CanFocus = true,
Shortcut = Key.CtrlMask | Key.S
};
RightPane.Title = $"{RightPane.Title} ({RightPane.ShortcutTag})";
RightPane.ShortcutAction = () => RightPane.SetFocus ();
ScenarioListView = new ListView () {
X = 0,
Y = 0,
Width = Dim.Fill (0),
Height = Dim.Fill (0),
AllowsMarking = false,
CanFocus = true,
};
ScenarioListView.OpenSelectedItem += ScenarioListView_OpenSelectedItem;
RightPane.Add (ScenarioListView);
KeyDown += KeyDownHandler;
Add (MenuBar);
Add (LeftPane);
Add (RightPane);
Add (StatusBar);
Loaded += LoadedHandler;
// Restore previous selections
CategoryListView.SelectedItem = _cachedCategoryIndex;
ScenarioListView.SelectedItem = _cachedScenarioIndex;
}
void LoadedHandler ()
{
if (_colorScheme == null) {
ColorScheme = _colorScheme = Colors.Base;
}
miIsMouseDisabled.Checked = Application.IsMouseDisabled;
DriverName.Title = $"Driver: {Driver.GetType ().Name}";
OS.Title = $"OS: {Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystem} {Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystemVersion}";
if (_selectedScenario != null) {
_selectedScenario = null;
_isFirstRunning = false;
}
if (!_isFirstRunning) {
RightPane.SetFocus ();
}
Loaded -= LoadedHandler;
}
///
/// Launches the selected scenario, setting the global _selectedScenario
///
///
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 ();
}
}
List