mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
UI catalog (#387)
* key down/up support * line endings? * line endings * KeyDown/Up support * line endings * line endings * Revert "Drop NuGet restore" This reverts commit5c7a0d05f0. * Revert "Revert "Drop NuGet restore"" This reverts commit2dc5fce865. * updated demo * defined styles * Smarter StatusBar bottom tracking. * Prepping for https://github.com/migueldeicaza/gui.cs/issues/376 * Oops. * Fixed StatusBar 'snap to bottom' * line endings * Revert "Fixed StatusBar 'snap to bottom'" This reverts commit9a91c957e2. * started UICatalog project * Initial working POC. * Fix newlines * merge * textalignment demo tweaks * textalignment demo tweaks * Unicode Menu Scenario * not sure why this keeps changing * re-added project to .sln file * re-enabled status bar * moved scenarios to dir * building a dim and pos demo * terminal.sln * progress...barely * fixed exit * progress with some underlying fixes to Label * added readme * fixes build issue * launch * made default colors readable on Windows * major UI Catalog upgrade * added more demos and updated readme * refactored and added more tests * added ref to Issue #437 * added OnKeyUp support to Curses and Net drivers * more tweaks - grab PR #438 first * Added a OpenSelectedItem event to the ListView #429 * updates * moved KeyUpHandler out of special ESC stuff * more tweaks & improvements * testing top window bug * supported OpenSelectedItem * lots of updates * fixed regression, fixed #444 * better button scenario * tweaks * add Ready event to Toplevel * dotfx .gitignroe * ready for ready * updated colors based on feedback; consolodated config code * tweaked readme * readme * Added Editor demonstrating TextView * Added Editor demonstrating TextView * added hexeditor scenario Co-authored-by: Miguel de Icaza <miguel@gnome.org> Co-authored-by: BDisp <bd.bdisp@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
<RootNamespace>Designer</RootNamespace>
|
<RootNamespace>Designer</RootNamespace>
|
||||||
<AssemblyName>Designer</AssemblyName>
|
<AssemblyName>Designer</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
|
||||||
<TargetFrameworkProfile />
|
<TargetFrameworkProfile />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
<RootNamespace>Terminal</RootNamespace>
|
<RootNamespace>Terminal</RootNamespace>
|
||||||
<AssemblyName>Terminal</AssemblyName>
|
<AssemblyName>Terminal</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<NuGetPackageImportStamp>
|
<NuGetPackageImportStamp>
|
||||||
</NuGetPackageImportStamp>
|
</NuGetPackageImportStamp>
|
||||||
<TargetFrameworkProfile />
|
<TargetFrameworkProfile />
|
||||||
|
|||||||
611
Example/demo.cs.orig
Normal file
611
Example/demo.cs.orig
Normal file
@@ -0,0 +1,611 @@
|
|||||||
|
using Terminal.Gui;
|
||||||
|
using System;
|
||||||
|
using Mono.Terminal;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
|
using NStack;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
static class Demo {
|
||||||
|
//class Box10x : View, IScrollView {
|
||||||
|
class Box10x : View {
|
||||||
|
int w = 40;
|
||||||
|
int h = 50;
|
||||||
|
|
||||||
|
public bool WantCursorPosition { get; set; } = false;
|
||||||
|
|
||||||
|
public Box10x (int x, int y) : base (new Rect (x, y, 20, 10))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size GetContentSize ()
|
||||||
|
{
|
||||||
|
return new Size (w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCursorPosition (Point pos)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Redraw (Rect region)
|
||||||
|
{
|
||||||
|
//Point pos = new Point (region.X, region.Y);
|
||||||
|
Driver.SetAttribute (ColorScheme.Focus);
|
||||||
|
|
||||||
|
for (int y = 0; y < h; y++) {
|
||||||
|
Move (0, y);
|
||||||
|
Driver.AddStr (y.ToString ());
|
||||||
|
for (int x = 0; x < w - y.ToString ().Length; x++) {
|
||||||
|
//Driver.AddRune ((Rune)('0' + (x + y) % 10));
|
||||||
|
if (y.ToString ().Length < w)
|
||||||
|
Driver.AddStr (" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Move (pos.X, pos.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Filler : View {
|
||||||
|
public Filler (Rect rect) : base (rect)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Redraw (Rect region)
|
||||||
|
{
|
||||||
|
Driver.SetAttribute (ColorScheme.Focus);
|
||||||
|
var f = Frame;
|
||||||
|
|
||||||
|
for (int y = 0; y < f.Width; y++) {
|
||||||
|
Move (0, y);
|
||||||
|
for (int x = 0; x < f.Height; x++) {
|
||||||
|
Rune r;
|
||||||
|
switch (x % 3) {
|
||||||
|
case 0:
|
||||||
|
Driver.AddRune (y.ToString ().ToCharArray (0, 1) [0]);
|
||||||
|
if (y > 9)
|
||||||
|
Driver.AddRune (y.ToString ().ToCharArray (1, 1) [0]);
|
||||||
|
r = '.';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r = 'o';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r = 'O';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Driver.AddRune (r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowTextAlignments ()
|
||||||
|
{
|
||||||
|
<<<<<<< HEAD
|
||||||
|
var container = new Window ($"Show Text Alignments") {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
container.OnKeyUp += (KeyEvent ke) => {
|
||||||
|
if (ke.Key == Key.Esc)
|
||||||
|
container.Running = false;
|
||||||
|
};
|
||||||
|
=======
|
||||||
|
var container = new Dialog (
|
||||||
|
"Text Alignments", 70, 20,
|
||||||
|
new Button ("Ok", is_default: true) { Clicked = () => { Application.RequestStop (); } },
|
||||||
|
new Button ("Cancel") { Clicked = () => { Application.RequestStop (); } });
|
||||||
|
|
||||||
|
>>>>>>> cb40c5c2491a559658481d20dd4b6a3343c0183f
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
string txt = "Hello world, how are you doing today?";
|
||||||
|
container.Add (
|
||||||
|
<<<<<<< HEAD
|
||||||
|
new Label ($"{i+1}-{txt}") { TextAlignment = TextAlignment.Left, Y = 3, Width = Dim.Fill () },
|
||||||
|
new Label ($"{i+2}-{txt}") { TextAlignment = TextAlignment.Right, Y = 5, Width = Dim.Fill () },
|
||||||
|
new Label ($"{i+3}-{txt}") { TextAlignment = TextAlignment.Centered, Y = 7, Width = Dim.Fill () },
|
||||||
|
new Label ($"{i+4}-{txt}") { TextAlignment = TextAlignment.Justified, Y = 9, Width = Dim.Fill () }
|
||||||
|
=======
|
||||||
|
new Label (new Rect (0, 1, 50, 3), $"{i+1}-{txt}") { TextAlignment = TextAlignment.Left },
|
||||||
|
new Label (new Rect (0, 3, 50, 3), $"{i+2}-{txt}") { TextAlignment = TextAlignment.Right },
|
||||||
|
new Label (new Rect (0, 5, 50, 3), $"{i+3}-{txt}") { TextAlignment = TextAlignment.Centered },
|
||||||
|
new Label (new Rect (0, 7, 50, 3), $"{i+4}-{txt}") { TextAlignment = TextAlignment.Justified }
|
||||||
|
>>>>>>> cb40c5c2491a559658481d20dd4b6a3343c0183f
|
||||||
|
);
|
||||||
|
|
||||||
|
Application.Run (container);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowEntries (View container)
|
||||||
|
{
|
||||||
|
var scrollView = new ScrollView (new Rect (50, 10, 20, 8)) {
|
||||||
|
ContentSize = new Size (20, 50),
|
||||||
|
//ContentOffset = new Point (0, 0),
|
||||||
|
ShowVerticalScrollIndicator = true,
|
||||||
|
ShowHorizontalScrollIndicator = true
|
||||||
|
};
|
||||||
|
#if false
|
||||||
|
scrollView.Add (new Box10x (0, 0));
|
||||||
|
#else
|
||||||
|
scrollView.Add (new Filler (new Rect (0, 0, 40, 40)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This is just to debug the visuals of the scrollview when small
|
||||||
|
var scrollView2 = new ScrollView (new Rect (72, 10, 3, 3)) {
|
||||||
|
ContentSize = new Size (100, 100),
|
||||||
|
ShowVerticalScrollIndicator = true,
|
||||||
|
ShowHorizontalScrollIndicator = true
|
||||||
|
};
|
||||||
|
scrollView2.Add (new Box10x (0, 0));
|
||||||
|
var progress = new ProgressBar (new Rect (68, 1, 10, 1));
|
||||||
|
bool timer (MainLoop caller)
|
||||||
|
{
|
||||||
|
progress.Pulse ();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (300), timer);
|
||||||
|
|
||||||
|
|
||||||
|
// A little convoluted, this is because I am using this to test the
|
||||||
|
// layout based on referencing elements of another view:
|
||||||
|
|
||||||
|
var login = new Label ("Login: ") { X = 3, Y = 6 };
|
||||||
|
var password = new Label ("Password: ") {
|
||||||
|
X = Pos.Left (login),
|
||||||
|
Y = Pos.Bottom (login) + 1
|
||||||
|
};
|
||||||
|
var loginText = new TextField ("") {
|
||||||
|
X = Pos.Right (password),
|
||||||
|
Y = Pos.Top (login),
|
||||||
|
Width = 40
|
||||||
|
};
|
||||||
|
|
||||||
|
var passText = new TextField ("") {
|
||||||
|
Secret = true,
|
||||||
|
X = Pos.Left (loginText),
|
||||||
|
Y = Pos.Top (password),
|
||||||
|
Width = Dim.Width (loginText)
|
||||||
|
};
|
||||||
|
|
||||||
|
var tf = new Button (3, 19, "Ok");
|
||||||
|
// Add some content
|
||||||
|
container.Add (
|
||||||
|
login,
|
||||||
|
loginText,
|
||||||
|
password,
|
||||||
|
passText,
|
||||||
|
new FrameView (new Rect (3, 10, 25, 6), "Options"){
|
||||||
|
new CheckBox (1, 0, "Remember me"),
|
||||||
|
new RadioGroup (1, 2, new [] { "_Personal", "_Company" }),
|
||||||
|
},
|
||||||
|
new ListView (new Rect (59, 6, 16, 4), new string [] {
|
||||||
|
"First row",
|
||||||
|
"<>",
|
||||||
|
"This is a very long row that should overflow what is shown",
|
||||||
|
"4th",
|
||||||
|
"There is an empty slot on the second row",
|
||||||
|
"Whoa",
|
||||||
|
"This is so cool"
|
||||||
|
}),
|
||||||
|
scrollView,
|
||||||
|
scrollView2,
|
||||||
|
tf,
|
||||||
|
new Button (10, 19, "Cancel"),
|
||||||
|
new TimeField (3, 20, DateTime.Now),
|
||||||
|
new TimeField (23, 20, DateTime.Now, true),
|
||||||
|
new DateField (3, 22, DateTime.Now),
|
||||||
|
new DateField (23, 22, DateTime.Now, true),
|
||||||
|
progress,
|
||||||
|
new Label (3, 24, "Press F9 (on Unix, ESC+9 is an alias) to activate the menubar"),
|
||||||
|
menuKeysStyle,
|
||||||
|
menuAutoMouseNav
|
||||||
|
|
||||||
|
);
|
||||||
|
container.SendSubviewToBack (tf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Label ml2;
|
||||||
|
|
||||||
|
static void NewFile ()
|
||||||
|
{
|
||||||
|
var d = new Dialog (
|
||||||
|
"New File", 50, 20,
|
||||||
|
new Button ("Ok", is_default: true) { Clicked = () => { Application.RequestStop (); } },
|
||||||
|
new Button ("Cancel") { Clicked = () => { Application.RequestStop (); } });
|
||||||
|
ml2 = new Label (1, 1, "Mouse Debug Line");
|
||||||
|
d.Add (ml2);
|
||||||
|
Application.Run (d);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Creates a nested editor
|
||||||
|
static void Editor (Toplevel top)
|
||||||
|
{
|
||||||
|
var tframe = top.Frame;
|
||||||
|
var ntop = new Toplevel (tframe);
|
||||||
|
var menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_File", new MenuItem [] {
|
||||||
|
new MenuItem ("_Close", "", () => {Application.RequestStop ();}),
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_Edit", new MenuItem [] {
|
||||||
|
new MenuItem ("_Copy", "", null),
|
||||||
|
new MenuItem ("C_ut", "", null),
|
||||||
|
new MenuItem ("_Paste", "", null)
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
ntop.Add (menu);
|
||||||
|
|
||||||
|
string fname = null;
|
||||||
|
foreach (var s in new [] { "/etc/passwd", "c:\\windows\\win.ini" })
|
||||||
|
if (System.IO.File.Exists (s)) {
|
||||||
|
fname = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var win = new Window (fname ?? "Untitled") {
|
||||||
|
X = 0,
|
||||||
|
Y = 1,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
ntop.Add (win);
|
||||||
|
|
||||||
|
var text = new TextView (new Rect (0, 0, tframe.Width - 2, tframe.Height - 3));
|
||||||
|
|
||||||
|
if (fname != null)
|
||||||
|
text.Text = System.IO.File.ReadAllText (fname);
|
||||||
|
win.Add (text);
|
||||||
|
|
||||||
|
Application.Run (ntop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Quit ()
|
||||||
|
{
|
||||||
|
var n = MessageBox.Query (50, 7, "Quit Demo", "Are you sure you want to quit this demo?", "Yes", "No");
|
||||||
|
return n == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Close ()
|
||||||
|
{
|
||||||
|
MessageBox.ErrorQuery (50, 7, "Error", "There is nothing to close", "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch what happens when I try to introduce a newline after the first open brace
|
||||||
|
// it introduces a new brace instead, and does not indent. Then watch me fight
|
||||||
|
// the editor as more oddities happen.
|
||||||
|
|
||||||
|
public static void Open ()
|
||||||
|
{
|
||||||
|
var d = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = true };
|
||||||
|
Application.Run (d);
|
||||||
|
|
||||||
|
if (!d.Canceled)
|
||||||
|
MessageBox.Query (50, 7, "Selected File", string.Join (", ", d.FilePaths), "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowHex (Toplevel top)
|
||||||
|
{
|
||||||
|
var tframe = top.Frame;
|
||||||
|
var ntop = new Toplevel (tframe);
|
||||||
|
var menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_File", new MenuItem [] {
|
||||||
|
new MenuItem ("_Close", "", () => {Application.RequestStop ();}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
ntop.Add (menu);
|
||||||
|
|
||||||
|
var win = new Window ("/etc/passwd") {
|
||||||
|
X = 0,
|
||||||
|
Y = 1,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
ntop.Add (win);
|
||||||
|
|
||||||
|
var source = System.IO.File.OpenRead ("/etc/passwd");
|
||||||
|
var hex = new HexView (source) {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
win.Add (hex);
|
||||||
|
Application.Run (ntop);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MenuItemDetails : MenuItem {
|
||||||
|
ustring title;
|
||||||
|
string help;
|
||||||
|
Action action;
|
||||||
|
|
||||||
|
public MenuItemDetails (ustring title, string help, Action action) : base (title, help, action)
|
||||||
|
{
|
||||||
|
this.title = title;
|
||||||
|
this.help = help;
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MenuItemDetails Instance (MenuItem mi)
|
||||||
|
{
|
||||||
|
return (MenuItemDetails)mi.GetMenuItem ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate MenuItem MenuItemDelegate (MenuItemDetails menuItem);
|
||||||
|
|
||||||
|
public static void ShowMenuItem (MenuItem mi)
|
||||||
|
{
|
||||||
|
BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
|
||||||
|
MethodInfo minfo = typeof (MenuItemDetails).GetMethod ("Instance", flags);
|
||||||
|
MenuItemDelegate mid = (MenuItemDelegate)Delegate.CreateDelegate (typeof (MenuItemDelegate), minfo);
|
||||||
|
MessageBox.Query (70, 7, mi.Title.ToString (),
|
||||||
|
$"{mi.Title.ToString ()} selected. Is from submenu: {mi.GetMenuBarItem ()}", "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MenuKeysStyle_Toggled (object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
menu.UseKeysUpDownAsKeysLeftRight = menuKeysStyle.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MenuAutoMouseNav_Toggled (object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
menu.WantMousePositionReports = menuAutoMouseNav.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void Copy ()
|
||||||
|
{
|
||||||
|
TextField textField = menu.LastFocused as TextField;
|
||||||
|
if (textField != null && textField.SelectedLength != 0) {
|
||||||
|
textField.Copy ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Cut ()
|
||||||
|
{
|
||||||
|
TextField textField = menu.LastFocused as TextField;
|
||||||
|
if (textField != null && textField.SelectedLength != 0) {
|
||||||
|
textField.Cut ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Paste ()
|
||||||
|
{
|
||||||
|
TextField textField = menu.LastFocused as TextField;
|
||||||
|
if (textField != null) {
|
||||||
|
textField.Paste ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Help ()
|
||||||
|
{
|
||||||
|
MessageBox.Query (50, 7, "Help", "This is a small help\nBe kind.", "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Selection Demo
|
||||||
|
|
||||||
|
static void ListSelectionDemo (bool multiple)
|
||||||
|
{
|
||||||
|
var d = new Dialog ("Selection Demo", 60, 20,
|
||||||
|
new Button ("Ok", is_default: true) { Clicked = () => { Application.RequestStop (); } },
|
||||||
|
new Button ("Cancel") { Clicked = () => { Application.RequestStop (); } });
|
||||||
|
|
||||||
|
var animals = new List<string> () { "Alpaca", "Llama", "Lion", "Shark", "Goat" };
|
||||||
|
var msg = new Label ("Use space bar or control-t to toggle selection") {
|
||||||
|
X = 1,
|
||||||
|
Y = 1,
|
||||||
|
Width = Dim.Fill () - 1,
|
||||||
|
Height = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
var list = new ListView (animals) {
|
||||||
|
X = 1,
|
||||||
|
Y = 3,
|
||||||
|
Width = Dim.Fill () - 4,
|
||||||
|
Height = Dim.Fill () - 4,
|
||||||
|
AllowsMarking = true,
|
||||||
|
AllowsMultipleSelection = multiple
|
||||||
|
};
|
||||||
|
d.Add (msg, list);
|
||||||
|
Application.Run (d);
|
||||||
|
|
||||||
|
var result = "";
|
||||||
|
for (int i = 0; i < animals.Count; i++) {
|
||||||
|
if (list.Source.IsMarked (i)) {
|
||||||
|
result += animals [i] + " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MessageBox.Query (60, 10, "Selected Animals", result == "" ? "No animals selected" : result, "Ok");
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region OnKeyDown / OnKeyUp Demo
|
||||||
|
private static void OnKeyDownUpDemo ()
|
||||||
|
{
|
||||||
|
var container = new Dialog (
|
||||||
|
"OnKeyDown & OnKeyUp demo", 80, 20,
|
||||||
|
new Button ("Close") { Clicked = () => { Application.RequestStop (); } }) {
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill (),
|
||||||
|
};
|
||||||
|
|
||||||
|
var list = new List<string> ();
|
||||||
|
var listView = new ListView (list) {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
Width = Dim.Fill () - 1,
|
||||||
|
Height = Dim.Fill () - 2,
|
||||||
|
};
|
||||||
|
listView.ColorScheme = Colors.TopLevel;
|
||||||
|
container.Add (listView);
|
||||||
|
|
||||||
|
void KeyUpDown (KeyEvent keyEvent, string updown)
|
||||||
|
{
|
||||||
|
if ((keyEvent.Key & Key.CtrlMask) != 0) {
|
||||||
|
list.Add ($"Key{updown,-4}: Ctrl ");
|
||||||
|
} else if ((keyEvent.Key & Key.AltMask) != 0) {
|
||||||
|
list.Add ($"Key{updown,-4}: Alt ");
|
||||||
|
} else {
|
||||||
|
list.Add ($"Key{updown,-4}: {(((uint)keyEvent.KeyValue & (uint)Key.CharMask) > 26 ? $"{(char)keyEvent.KeyValue}" : $"{keyEvent.Key}")}");
|
||||||
|
}
|
||||||
|
listView.MoveDown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
container.OnKeyDown += (KeyEvent keyEvent) => KeyUpDown (keyEvent, "Down");
|
||||||
|
container.OnKeyUp += (KeyEvent keyEvent) => KeyUpDown (keyEvent, "Up");
|
||||||
|
Application.Run (container);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public static Label ml;
|
||||||
|
public static MenuBar menu;
|
||||||
|
public static CheckBox menuKeysStyle;
|
||||||
|
public static CheckBox menuAutoMouseNav;
|
||||||
|
static void Main ()
|
||||||
|
{
|
||||||
|
if (Debugger.IsAttached)
|
||||||
|
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
|
||||||
|
|
||||||
|
//Application.UseSystemConsole = true;
|
||||||
|
|
||||||
|
Application.Init ();
|
||||||
|
|
||||||
|
var top = Application.Top;
|
||||||
|
|
||||||
|
//Open ();
|
||||||
|
#if true
|
||||||
|
int margin = 3;
|
||||||
|
var win = new Window ("Hello") {
|
||||||
|
X = 1,
|
||||||
|
Y = 1,
|
||||||
|
|
||||||
|
Width = Dim.Fill () - margin,
|
||||||
|
Height = Dim.Fill () - margin
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
var tframe = top.Frame;
|
||||||
|
|
||||||
|
var win = new Window (new Rect (0, 1, tframe.Width, tframe.Height - 1), "Hello");
|
||||||
|
#endif
|
||||||
|
MenuItemDetails [] menuItems = {
|
||||||
|
new MenuItemDetails ("F_ind", "", null),
|
||||||
|
new MenuItemDetails ("_Replace", "", null),
|
||||||
|
new MenuItemDetails ("_Item1", "", null),
|
||||||
|
new MenuItemDetails ("_Not From Sub Menu", "", null)
|
||||||
|
};
|
||||||
|
|
||||||
|
menuItems [0].Action = () => ShowMenuItem (menuItems [0]);
|
||||||
|
menuItems [1].Action = () => ShowMenuItem (menuItems [1]);
|
||||||
|
menuItems [2].Action = () => ShowMenuItem (menuItems [2]);
|
||||||
|
menuItems [3].Action = () => ShowMenuItem (menuItems [3]);
|
||||||
|
|
||||||
|
menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_File", new MenuItem [] {
|
||||||
|
new MenuItem ("Text _Editor Demo", "", () => { Editor (top); }),
|
||||||
|
new MenuItem ("_New", "Creates new file", NewFile),
|
||||||
|
new MenuItem ("_Open", "", Open),
|
||||||
|
new MenuItem ("_Hex", "", () => ShowHex (top)),
|
||||||
|
new MenuItem ("_Close", "", () => Close ()),
|
||||||
|
new MenuItem ("_Disabled", "", () => { }, () => false),
|
||||||
|
null,
|
||||||
|
new MenuItem ("_Quit", "", () => { if (Quit ()) top.Running = false; })
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_Edit", new MenuItem [] {
|
||||||
|
new MenuItem ("_Copy", "", Copy),
|
||||||
|
new MenuItem ("C_ut", "", Cut),
|
||||||
|
new MenuItem ("_Paste", "", Paste),
|
||||||
|
new MenuItem ("_Find and Replace",
|
||||||
|
new MenuBarItem (new MenuItem[] {menuItems [0], menuItems [1] })),
|
||||||
|
menuItems[3]
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_List Demos", new MenuItem [] {
|
||||||
|
new MenuItem ("Select _Multiple Items", "", () => ListSelectionDemo (true)),
|
||||||
|
new MenuItem ("Select _Single Item", "", () => ListSelectionDemo (false)),
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("A_ssorted", new MenuItem [] {
|
||||||
|
new MenuItem ("_Show text alignments", "", () => ShowTextAlignments ()),
|
||||||
|
new MenuItem ("_OnKeyDown/Up", "", () => OnKeyDownUpDemo ())
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_Test Menu and SubMenus", new MenuItem [] {
|
||||||
|
new MenuItem ("SubMenu1Item_1",
|
||||||
|
new MenuBarItem (new MenuItem[] {
|
||||||
|
new MenuItem ("SubMenu2Item_1",
|
||||||
|
new MenuBarItem (new MenuItem [] {
|
||||||
|
new MenuItem ("SubMenu3Item_1",
|
||||||
|
new MenuBarItem (new MenuItem [] { menuItems [2] })
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_About...", "Demonstrates top-level menu item", () => MessageBox.ErrorQuery (50, 7, "About Demo", "This is a demo app for gui.cs", "Ok")),
|
||||||
|
});
|
||||||
|
|
||||||
|
menuKeysStyle = new CheckBox (3, 25, "UseKeysUpDownAsKeysLeftRight", true);
|
||||||
|
menuKeysStyle.Toggled += MenuKeysStyle_Toggled;
|
||||||
|
menuAutoMouseNav = new CheckBox (40, 25, "UseMenuAutoNavigation", true);
|
||||||
|
menuAutoMouseNav.Toggled += MenuAutoMouseNav_Toggled;
|
||||||
|
|
||||||
|
ShowEntries (win);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
ml = new Label (new Rect (3, 17, 47, 1), "Mouse: ");
|
||||||
|
Application.RootMouseEvent += delegate (MouseEvent me) {
|
||||||
|
ml.TextColor = Colors.TopLevel.Normal;
|
||||||
|
ml.Text = $"Mouse: ({me.X},{me.Y}) - {me.Flags} {count++}";
|
||||||
|
};
|
||||||
|
|
||||||
|
var test = new Label (3, 18, "Se iniciará el análisis");
|
||||||
|
win.Add (test);
|
||||||
|
win.Add (ml);
|
||||||
|
|
||||||
|
var drag = new Label ("Drag: ") { X = 70, Y = 24 };
|
||||||
|
var dragText = new TextField ("") {
|
||||||
|
X = Pos.Right (drag),
|
||||||
|
Y = Pos.Top (drag),
|
||||||
|
Width = 40
|
||||||
|
};
|
||||||
|
|
||||||
|
var statusBar = new StatusBar (new StatusItem [] {
|
||||||
|
new StatusItem(Key.F1, "~F1~ Help", () => Help()),
|
||||||
|
new StatusItem(Key.F2, "~F2~ Load", null),
|
||||||
|
new StatusItem(Key.F3, "~F3~ Save", null),
|
||||||
|
new StatusItem(Key.ControlX, "~^X~ Quit", () => { if (Quit ()) top.Running = false; }),
|
||||||
|
}) {
|
||||||
|
Parent = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
win.Add (drag, dragText);
|
||||||
|
#if true
|
||||||
|
// FIXED: This currently causes a stack overflow, because it is referencing a window that has not had its size allocated yet
|
||||||
|
|
||||||
|
var bottom = new Label ("This should go on the bottom of the same top-level!");
|
||||||
|
win.Add (bottom);
|
||||||
|
var bottom2 = new Label ("This should go on the bottom of another top-level!");
|
||||||
|
top.Add (bottom2);
|
||||||
|
|
||||||
|
Application.OnLoad = () => {
|
||||||
|
bottom.X = win.X;
|
||||||
|
bottom.Y = Pos.Bottom (win) - Pos.Top (win) - margin;
|
||||||
|
bottom2.X = Pos.Left (win);
|
||||||
|
bottom2.Y = Pos.Bottom (win);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
top.Add (win);
|
||||||
|
//top.Add (menu);
|
||||||
|
top.Add (menu, statusBar);
|
||||||
|
Application.Run ();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1066,7 +1066,7 @@ namespace Terminal.Gui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when a character key is pressed and occurs after the key down event.
|
/// Invoked when a character key is pressed and occurs after the key up event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<KeyEvent> OnKeyPress;
|
public Action<KeyEvent> OnKeyPress;
|
||||||
|
|
||||||
@@ -1083,7 +1083,6 @@ namespace Terminal.Gui {
|
|||||||
/// <inheritdoc cref="ProcessHotKey"/>
|
/// <inheritdoc cref="ProcessHotKey"/>
|
||||||
public override bool ProcessHotKey (KeyEvent keyEvent)
|
public override bool ProcessHotKey (KeyEvent keyEvent)
|
||||||
{
|
{
|
||||||
OnKeyPress?.Invoke (keyEvent);
|
|
||||||
if (subviews == null || subviews.Count == 0)
|
if (subviews == null || subviews.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
foreach (var view in subviews)
|
foreach (var view in subviews)
|
||||||
@@ -1095,7 +1094,6 @@ namespace Terminal.Gui {
|
|||||||
/// <inheritdoc cref="ProcessColdKey"/>
|
/// <inheritdoc cref="ProcessColdKey"/>
|
||||||
public override bool ProcessColdKey (KeyEvent keyEvent)
|
public override bool ProcessColdKey (KeyEvent keyEvent)
|
||||||
{
|
{
|
||||||
OnKeyPress?.Invoke (keyEvent);
|
|
||||||
if (subviews == null || subviews.Count == 0)
|
if (subviews == null || subviews.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
foreach (var view in subviews)
|
foreach (var view in subviews)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace Terminal.Gui {
|
|||||||
if (sync)
|
if (sync)
|
||||||
Application.Driver.Refresh ();
|
Application.Driver.Refresh ();
|
||||||
ccol++;
|
ccol++;
|
||||||
var runeWidth = Rune.ColumnWidth(rune);
|
var runeWidth = Rune.ColumnWidth (rune);
|
||||||
if (runeWidth > 1) {
|
if (runeWidth > 1) {
|
||||||
for (int i = 1; i < runeWidth; i++) {
|
for (int i = 1; i < runeWidth; i++) {
|
||||||
ccol++;
|
ccol++;
|
||||||
@@ -192,7 +192,7 @@ namespace Terminal.Gui {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessInput (Action<KeyEvent> keyHandler, Action<MouseEvent> mouseHandler)
|
void ProcessInput (Action<KeyEvent> keyHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
|
||||||
{
|
{
|
||||||
int wch;
|
int wch;
|
||||||
var code = Curses.get_wch (out wch);
|
var code = Curses.get_wch (out wch);
|
||||||
@@ -212,6 +212,7 @@ namespace Terminal.Gui {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keyHandler (new KeyEvent (MapCursesKey (wch)));
|
keyHandler (new KeyEvent (MapCursesKey (wch)));
|
||||||
|
keyUpHandler (new KeyEvent (MapCursesKey (wch)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +220,7 @@ namespace Terminal.Gui {
|
|||||||
if (wch == 27) {
|
if (wch == 27) {
|
||||||
Curses.timeout (200);
|
Curses.timeout (200);
|
||||||
|
|
||||||
code = Curses.get_wch (out wch);
|
code = Curses.get_wch (out int wch2);
|
||||||
if (code == Curses.KEY_CODE_YES)
|
if (code == Curses.KEY_CODE_YES)
|
||||||
keyHandler (new KeyEvent (Key.AltMask | MapCursesKey (wch)));
|
keyHandler (new KeyEvent (Key.AltMask | MapCursesKey (wch)));
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
@@ -227,23 +228,28 @@ namespace Terminal.Gui {
|
|||||||
|
|
||||||
// The ESC-number handling, debatable.
|
// The ESC-number handling, debatable.
|
||||||
// Simulates the AltMask itself by pressing Alt + Space.
|
// Simulates the AltMask itself by pressing Alt + Space.
|
||||||
if (wch == (int)Key.Space)
|
if (wch2 == (int)Key.Space)
|
||||||
key = new KeyEvent (Key.AltMask);
|
key = new KeyEvent (Key.AltMask);
|
||||||
else if (wch - (int)Key.Space >= 'A' && wch - (int)Key.Space <= 'Z')
|
else if (wch2 - (int)Key.Space >= 'A' && wch2 - (int)Key.Space <= 'Z')
|
||||||
key = new KeyEvent ((Key)((uint)Key.AltMask + (wch - (int)Key.Space)));
|
key = new KeyEvent ((Key)((uint)Key.AltMask + (wch2 - (int)Key.Space)));
|
||||||
else if (wch >= '1' && wch <= '9')
|
else if (wch2 >= '1' && wch <= '9')
|
||||||
key = new KeyEvent ((Key)((int)Key.F1 + (wch - '0' - 1)));
|
key = new KeyEvent ((Key)((int)Key.F1 + (wch2 - '0' - 1)));
|
||||||
else if (wch == '0')
|
else if (wch2 == '0')
|
||||||
key = new KeyEvent (Key.F10);
|
key = new KeyEvent (Key.F10);
|
||||||
else if (wch == 27)
|
else if (wch2 == 27)
|
||||||
key = new KeyEvent ((Key)wch);
|
key = new KeyEvent ((Key)wch2);
|
||||||
else
|
else
|
||||||
key = new KeyEvent (Key.AltMask | (Key)wch);
|
key = new KeyEvent (Key.AltMask | (Key)wch2);
|
||||||
keyHandler (key);
|
keyHandler (key);
|
||||||
} else
|
} else {
|
||||||
keyHandler (new KeyEvent (Key.Esc));
|
keyHandler (new KeyEvent (Key.Esc));
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
keyHandler (new KeyEvent ((Key)wch));
|
keyHandler (new KeyEvent ((Key)wch));
|
||||||
|
}
|
||||||
|
// Cause OnKeyUp and OnKeyPressed. Note that the special handling for ESC above
|
||||||
|
// will not impact KeyUp.
|
||||||
|
keyUpHandler (new KeyEvent ((Key)wch));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
|
public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
|
||||||
@@ -252,7 +258,7 @@ namespace Terminal.Gui {
|
|||||||
Curses.timeout (-1);
|
Curses.timeout (-1);
|
||||||
|
|
||||||
(mainLoop.Driver as Mono.Terminal.UnixMainLoop).AddWatch (0, Mono.Terminal.UnixMainLoop.Condition.PollIn, x => {
|
(mainLoop.Driver as Mono.Terminal.UnixMainLoop).AddWatch (0, Mono.Terminal.UnixMainLoop.Condition.PollIn, x => {
|
||||||
ProcessInput (keyHandler, mouseHandler);
|
ProcessInput (keyHandler, keyUpHandler, mouseHandler);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -314,7 +320,7 @@ namespace Terminal.Gui {
|
|||||||
Colors.Menu.Focus = Curses.A_BOLD | MakeColor (Curses.COLOR_WHITE, Curses.COLOR_BLACK);
|
Colors.Menu.Focus = Curses.A_BOLD | MakeColor (Curses.COLOR_WHITE, Curses.COLOR_BLACK);
|
||||||
Colors.Menu.HotNormal = Curses.A_BOLD | MakeColor (Curses.COLOR_YELLOW, Curses.COLOR_CYAN);
|
Colors.Menu.HotNormal = Curses.A_BOLD | MakeColor (Curses.COLOR_YELLOW, Curses.COLOR_CYAN);
|
||||||
Colors.Menu.Normal = Curses.A_BOLD | MakeColor (Curses.COLOR_WHITE, Curses.COLOR_CYAN);
|
Colors.Menu.Normal = Curses.A_BOLD | MakeColor (Curses.COLOR_WHITE, Curses.COLOR_CYAN);
|
||||||
Colors.Menu.Disabled = MakeColor(Curses.COLOR_WHITE, Curses.COLOR_CYAN);
|
Colors.Menu.Disabled = MakeColor (Curses.COLOR_WHITE, Curses.COLOR_CYAN);
|
||||||
|
|
||||||
Colors.Dialog.Normal = MakeColor (Curses.COLOR_BLACK, Curses.COLOR_WHITE);
|
Colors.Dialog.Normal = MakeColor (Curses.COLOR_BLACK, Curses.COLOR_WHITE);
|
||||||
Colors.Dialog.Focus = MakeColor (Curses.COLOR_BLACK, Curses.COLOR_CYAN);
|
Colors.Dialog.Focus = MakeColor (Curses.COLOR_BLACK, Curses.COLOR_CYAN);
|
||||||
|
|||||||
@@ -328,6 +328,7 @@ namespace Terminal.Gui {
|
|||||||
if (map == (Key)0xffffffff)
|
if (map == (Key)0xffffffff)
|
||||||
return;
|
return;
|
||||||
keyHandler (new KeyEvent (map));
|
keyHandler (new KeyEvent (map));
|
||||||
|
keyUpHandler (new KeyEvent (map));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -440,15 +440,10 @@ namespace Terminal.Gui {
|
|||||||
|
|
||||||
public WindowsDriver ()
|
public WindowsDriver ()
|
||||||
{
|
{
|
||||||
Colors.TopLevel = new ColorScheme ();
|
|
||||||
|
|
||||||
Colors.TopLevel.Normal = MakeColor (ConsoleColor.Green, ConsoleColor.Black);
|
|
||||||
Colors.TopLevel.Focus = MakeColor (ConsoleColor.White, ConsoleColor.DarkCyan);
|
|
||||||
Colors.TopLevel.HotNormal = MakeColor (ConsoleColor.DarkYellow, ConsoleColor.Black);
|
|
||||||
Colors.TopLevel.HotFocus = MakeColor (ConsoleColor.DarkYellow, ConsoleColor.DarkCyan);
|
|
||||||
|
|
||||||
winConsole = new WindowsConsole ();
|
winConsole = new WindowsConsole ();
|
||||||
|
|
||||||
|
SetupColorsAndBorders ();
|
||||||
|
|
||||||
cols = Console.WindowWidth;
|
cols = Console.WindowWidth;
|
||||||
rows = Console.WindowHeight;
|
rows = Console.WindowHeight;
|
||||||
WindowsConsole.SmallRect.MakeEmpty (ref damageRegion);
|
WindowsConsole.SmallRect.MakeEmpty (ref damageRegion);
|
||||||
@@ -459,6 +454,54 @@ namespace Terminal.Gui {
|
|||||||
Task.Run ((Action)WindowsInputHandler);
|
Task.Run ((Action)WindowsInputHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetupColorsAndBorders ()
|
||||||
|
{
|
||||||
|
Colors.TopLevel = new ColorScheme ();
|
||||||
|
Colors.Base = new ColorScheme ();
|
||||||
|
Colors.Dialog = new ColorScheme ();
|
||||||
|
Colors.Menu = new ColorScheme ();
|
||||||
|
Colors.Error = new ColorScheme ();
|
||||||
|
|
||||||
|
Colors.TopLevel.Normal = MakeColor (ConsoleColor.Green, ConsoleColor.Black);
|
||||||
|
Colors.TopLevel.Focus = MakeColor (ConsoleColor.White, ConsoleColor.DarkCyan);
|
||||||
|
Colors.TopLevel.HotNormal = MakeColor (ConsoleColor.DarkYellow, ConsoleColor.Black);
|
||||||
|
Colors.TopLevel.HotFocus = MakeColor (ConsoleColor.DarkBlue, ConsoleColor.DarkCyan);
|
||||||
|
|
||||||
|
Colors.Base.Normal = MakeColor (ConsoleColor.White, ConsoleColor.DarkBlue);
|
||||||
|
Colors.Base.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
|
||||||
|
Colors.Base.HotNormal = MakeColor (ConsoleColor.DarkCyan, ConsoleColor.DarkBlue);
|
||||||
|
Colors.Base.HotFocus = MakeColor (ConsoleColor.Blue, ConsoleColor.Gray);
|
||||||
|
|
||||||
|
Colors.Menu.Normal = MakeColor (ConsoleColor.White, ConsoleColor.DarkGray);
|
||||||
|
Colors.Menu.Focus = MakeColor (ConsoleColor.White, ConsoleColor.Black);
|
||||||
|
Colors.Menu.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.DarkGray);
|
||||||
|
Colors.Menu.HotFocus = MakeColor (ConsoleColor.Yellow, ConsoleColor.Black);
|
||||||
|
Colors.Menu.Disabled = MakeColor (ConsoleColor.Gray, ConsoleColor.DarkGray);
|
||||||
|
|
||||||
|
Colors.Dialog.Normal = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
|
||||||
|
Colors.Dialog.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.DarkGray);
|
||||||
|
Colors.Dialog.HotNormal = MakeColor (ConsoleColor.DarkBlue, ConsoleColor.Gray);
|
||||||
|
Colors.Dialog.HotFocus = MakeColor (ConsoleColor.DarkBlue, ConsoleColor.DarkGray);
|
||||||
|
|
||||||
|
Colors.Error.Normal = MakeColor (ConsoleColor.DarkRed, ConsoleColor.White);
|
||||||
|
Colors.Error.Focus = MakeColor (ConsoleColor.White, ConsoleColor.DarkRed);
|
||||||
|
Colors.Error.HotNormal = MakeColor (ConsoleColor.Black, ConsoleColor.White);
|
||||||
|
Colors.Error.HotFocus = MakeColor (ConsoleColor.Black, ConsoleColor.DarkRed);
|
||||||
|
|
||||||
|
HLine = '\u2500';
|
||||||
|
VLine = '\u2502';
|
||||||
|
Stipple = '\u2592';
|
||||||
|
Diamond = '\u25c6';
|
||||||
|
ULCorner = '\u250C';
|
||||||
|
LLCorner = '\u2514';
|
||||||
|
URCorner = '\u2510';
|
||||||
|
LRCorner = '\u2518';
|
||||||
|
LeftTee = '\u251c';
|
||||||
|
RightTee = '\u2524';
|
||||||
|
TopTee = '\u22a4';
|
||||||
|
BottomTee = '\u22a5';
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout (LayoutKind.Sequential)]
|
[StructLayout (LayoutKind.Sequential)]
|
||||||
public struct ConsoleKeyInfoEx {
|
public struct ConsoleKeyInfoEx {
|
||||||
public ConsoleKeyInfo consoleKeyInfo;
|
public ConsoleKeyInfo consoleKeyInfo;
|
||||||
@@ -564,11 +607,24 @@ namespace Terminal.Gui {
|
|||||||
case WindowsConsole.EventType.Key:
|
case WindowsConsole.EventType.Key:
|
||||||
var map = MapKey (ToConsoleKeyInfoEx (inputEvent.KeyEvent));
|
var map = MapKey (ToConsoleKeyInfoEx (inputEvent.KeyEvent));
|
||||||
if (map == (Key)0xffffffff) {
|
if (map == (Key)0xffffffff) {
|
||||||
KeyEvent key = default;
|
KeyEvent key = new KeyEvent ();
|
||||||
|
|
||||||
// Shift = VK_SHIFT = 0x10
|
// Shift = VK_SHIFT = 0x10
|
||||||
// Ctrl = VK_CONTROL = 0x11
|
// Ctrl = VK_CONTROL = 0x11
|
||||||
// Alt = VK_MENU = 0x12
|
// Alt = VK_MENU = 0x12
|
||||||
|
|
||||||
|
if (inputEvent.KeyEvent.dwControlKeyState.HasFlag (WindowsConsole.ControlKeyState.CapslockOn)) {
|
||||||
|
inputEvent.KeyEvent.dwControlKeyState &= ~WindowsConsole.ControlKeyState.CapslockOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputEvent.KeyEvent.dwControlKeyState.HasFlag (WindowsConsole.ControlKeyState.ScrolllockOn)) {
|
||||||
|
inputEvent.KeyEvent.dwControlKeyState &= ~WindowsConsole.ControlKeyState.ScrolllockOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputEvent.KeyEvent.dwControlKeyState.HasFlag (WindowsConsole.ControlKeyState.NumlockOn)) {
|
||||||
|
inputEvent.KeyEvent.dwControlKeyState &= ~WindowsConsole.ControlKeyState.NumlockOn;
|
||||||
|
}
|
||||||
|
|
||||||
switch (inputEvent.KeyEvent.dwControlKeyState) {
|
switch (inputEvent.KeyEvent.dwControlKeyState) {
|
||||||
case WindowsConsole.ControlKeyState.RightAltPressed:
|
case WindowsConsole.ControlKeyState.RightAltPressed:
|
||||||
case WindowsConsole.ControlKeyState.RightAltPressed |
|
case WindowsConsole.ControlKeyState.RightAltPressed |
|
||||||
@@ -617,10 +673,10 @@ namespace Terminal.Gui {
|
|||||||
keyUpHandler (key);
|
keyUpHandler (key);
|
||||||
} else {
|
} else {
|
||||||
if (inputEvent.KeyEvent.bKeyDown) {
|
if (inputEvent.KeyEvent.bKeyDown) {
|
||||||
// Key Down - Fire KeyDown Event and KeyStroke (ProcessKey) Event
|
|
||||||
keyDownHandler (new KeyEvent (map));
|
keyDownHandler (new KeyEvent (map));
|
||||||
keyHandler (new KeyEvent (map));
|
|
||||||
} else {
|
} else {
|
||||||
|
// Key Up - Fire KeyDown Event and KeyStroke (ProcessKey) Event
|
||||||
|
keyHandler (new KeyEvent (map));
|
||||||
keyUpHandler (new KeyEvent (map));
|
keyUpHandler (new KeyEvent (map));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -918,6 +974,9 @@ namespace Terminal.Gui {
|
|||||||
case ConsoleKey.OemComma:
|
case ConsoleKey.OemComma:
|
||||||
case ConsoleKey.OemPlus:
|
case ConsoleKey.OemPlus:
|
||||||
case ConsoleKey.OemMinus:
|
case ConsoleKey.OemMinus:
|
||||||
|
if (keyInfo.KeyChar == 0)
|
||||||
|
return Key.Unknown;
|
||||||
|
|
||||||
return (Key)((uint)keyInfo.KeyChar);
|
return (Key)((uint)keyInfo.KeyChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -971,48 +1030,10 @@ namespace Terminal.Gui {
|
|||||||
public override void Init (Action terminalResized)
|
public override void Init (Action terminalResized)
|
||||||
{
|
{
|
||||||
TerminalResized = terminalResized;
|
TerminalResized = terminalResized;
|
||||||
|
SetupColorsAndBorders ();
|
||||||
Colors.Base = new ColorScheme ();
|
|
||||||
Colors.Dialog = new ColorScheme ();
|
|
||||||
Colors.Menu = new ColorScheme ();
|
|
||||||
Colors.Error = new ColorScheme ();
|
|
||||||
|
|
||||||
HLine = '\u2500';
|
|
||||||
VLine = '\u2502';
|
|
||||||
Stipple = '\u2592';
|
|
||||||
Diamond = '\u25c6';
|
|
||||||
ULCorner = '\u250C';
|
|
||||||
LLCorner = '\u2514';
|
|
||||||
URCorner = '\u2510';
|
|
||||||
LRCorner = '\u2518';
|
|
||||||
LeftTee = '\u251c';
|
|
||||||
RightTee = '\u2524';
|
|
||||||
TopTee = '\u22a4';
|
|
||||||
BottomTee = '\u22a5';
|
|
||||||
|
|
||||||
Colors.Base.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Blue);
|
|
||||||
Colors.Base.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
|
|
||||||
Colors.Base.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Blue);
|
|
||||||
Colors.Base.HotFocus = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
|
|
||||||
|
|
||||||
Colors.Menu.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Cyan);
|
|
||||||
Colors.Menu.Focus = MakeColor (ConsoleColor.White, ConsoleColor.Black);
|
|
||||||
Colors.Menu.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
|
|
||||||
Colors.Menu.HotFocus = MakeColor (ConsoleColor.Yellow, ConsoleColor.Black);
|
|
||||||
Colors.Menu.Disabled = MakeColor (ConsoleColor.DarkGray, ConsoleColor.Cyan);
|
|
||||||
|
|
||||||
Colors.Dialog.Normal = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
|
|
||||||
Colors.Dialog.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
|
|
||||||
Colors.Dialog.HotNormal = MakeColor (ConsoleColor.Blue, ConsoleColor.Gray);
|
|
||||||
Colors.Dialog.HotFocus = MakeColor (ConsoleColor.Blue, ConsoleColor.Cyan);
|
|
||||||
|
|
||||||
Colors.Error.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Red);
|
|
||||||
Colors.Error.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
|
|
||||||
Colors.Error.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Red);
|
|
||||||
Colors.Error.HotFocus = Colors.Error.HotNormal;
|
|
||||||
Console.Clear ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ResizeScreen ()
|
void ResizeScreen ()
|
||||||
{
|
{
|
||||||
OutputBuffer = new WindowsConsole.CharInfo [Rows * Cols];
|
OutputBuffer = new WindowsConsole.CharInfo [Rows * Cols];
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace Terminal.Gui {
|
|||||||
ControlSpace = 0,
|
ControlSpace = 0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The key code for the user pressing Control-A
|
/// The key code for the user pressing Control-A
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ControlA = 1,
|
ControlA = 1,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -288,8 +288,7 @@ namespace Terminal.Gui {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes a keyboard event.
|
/// Describes a keyboard event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct KeyEvent {
|
public class KeyEvent {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Symb olid definition for the key.
|
/// Symb olid definition for the key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -321,6 +320,10 @@ namespace Terminal.Gui {
|
|||||||
//public bool IsCtrl => ((uint)Key >= 1) && ((uint)Key <= 26);
|
//public bool IsCtrl => ((uint)Key >= 1) && ((uint)Key <= 26);
|
||||||
public bool IsCtrl => (Key & Key.CtrlMask) != 0;
|
public bool IsCtrl => (Key & Key.CtrlMask) != 0;
|
||||||
|
|
||||||
|
public KeyEvent ()
|
||||||
|
{
|
||||||
|
Key = Key.Unknown;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new KeyEvent from the provided Key value - can be a rune cast into a Key value
|
/// Constructs a new KeyEvent from the provided Key value - can be a rune cast into a Key value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -328,6 +331,28 @@ namespace Terminal.Gui {
|
|||||||
{
|
{
|
||||||
Key = k;
|
Key = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
string msg = "";
|
||||||
|
var key = this.Key;
|
||||||
|
if ((this.Key & Key.ShiftMask) != 0) {
|
||||||
|
msg += "Shift-";
|
||||||
|
}
|
||||||
|
if ((this.Key & Key.CtrlMask) != 0) {
|
||||||
|
msg += "Ctrl-";
|
||||||
|
}
|
||||||
|
if ((this.Key & Key.AltMask) != 0) {
|
||||||
|
msg += "Alt-";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty (msg)) {
|
||||||
|
msg += $"{(((uint)this.KeyValue & (uint)Key.CharMask) > 27 ? $"{(char)this.KeyValue}" : $"{key}")}";
|
||||||
|
} else {
|
||||||
|
msg += $"{(((uint)this.KeyValue & (uint)Key.CharMask) > 27 ? $"{(char)this.KeyValue}" : $"")}";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -486,7 +511,7 @@ namespace Terminal.Gui {
|
|||||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:Terminal.Gui.MouseEvent"/>.
|
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:Terminal.Gui.MouseEvent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A <see cref="T:System.String"/> that represents the current <see cref="T:Terminal.Gui.MouseEvent"/>.</returns>
|
/// <returns>A <see cref="T:System.String"/> that represents the current <see cref="T:Terminal.Gui.MouseEvent"/>.</returns>
|
||||||
public override string ToString()
|
public override string ToString ()
|
||||||
{
|
{
|
||||||
return $"({X},{Y}:{Flags}";
|
return $"({X},{Y}:{Flags}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ namespace Terminal.Gui {
|
|||||||
for (int i = 0; i < spaces; i++)
|
for (int i = 0; i < spaces; i++)
|
||||||
s.Append (' ');
|
s.Append (' ');
|
||||||
if (extras > 0) {
|
if (extras > 0) {
|
||||||
s.Append ('_');
|
//s.Append ('_');
|
||||||
extras--;
|
extras--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,8 +179,11 @@ namespace Terminal.Gui {
|
|||||||
int x;
|
int x;
|
||||||
switch (textAlignment) {
|
switch (textAlignment) {
|
||||||
case TextAlignment.Left:
|
case TextAlignment.Left:
|
||||||
|
x = Frame.Left;
|
||||||
|
break;
|
||||||
case TextAlignment.Justified:
|
case TextAlignment.Justified:
|
||||||
x = 0;
|
Recalc ();
|
||||||
|
x = Frame.Left;
|
||||||
break;
|
break;
|
||||||
case TextAlignment.Right:
|
case TextAlignment.Right:
|
||||||
x = Frame.Right - str.Length;
|
x = Frame.Right - str.Length;
|
||||||
|
|||||||
@@ -294,6 +294,11 @@ namespace Terminal.Gui {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action SelectedChanged;
|
public event Action SelectedChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This event is raised on Enter key or Double Click to open the selected item.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler OpenSelectedItem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles cursor movement for this view, passes all other events.
|
/// Handles cursor movement for this view, passes all other events.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -325,6 +330,11 @@ namespace Terminal.Gui {
|
|||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Key.Enter:
|
||||||
|
OpenSelectedItem?.Invoke (this, new EventArgs ());
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
return base.ProcessKey (kb);
|
return base.ProcessKey (kb);
|
||||||
}
|
}
|
||||||
@@ -451,7 +461,7 @@ namespace Terminal.Gui {
|
|||||||
///<inheritdoc cref="MouseEvent(Gui.MouseEvent)"/>
|
///<inheritdoc cref="MouseEvent(Gui.MouseEvent)"/>
|
||||||
public override bool MouseEvent(MouseEvent me)
|
public override bool MouseEvent(MouseEvent me)
|
||||||
{
|
{
|
||||||
if (!me.Flags.HasFlag (MouseFlags.Button1Clicked))
|
if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!HasFocus)
|
if (!HasFocus)
|
||||||
@@ -469,9 +479,10 @@ namespace Terminal.Gui {
|
|||||||
SetNeedsDisplay ();
|
SetNeedsDisplay ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (SelectedChanged != null)
|
SelectedChanged?.Invoke ();
|
||||||
SelectedChanged();
|
|
||||||
SetNeedsDisplay ();
|
SetNeedsDisplay ();
|
||||||
|
if (me.Flags == MouseFlags.Button1DoubleClicked)
|
||||||
|
OpenSelectedItem?.Invoke (this, new EventArgs ());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
Terminal.sln
10
Terminal.sln
@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Terminal.Gui", "Terminal.Gu
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Designer", "Designer\Designer.csproj", "{1228D992-C801-49BB-839A-7BD28A3FFF0A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Designer", "Designer\Designer.csproj", "{1228D992-C801-49BB-839A-7BD28A3FFF0A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UICatalog", "UICatalog\UICatalog.csproj", "{88979F89-9A42-448F-AE3E-3060145F6375}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
@@ -25,6 +27,14 @@ Global
|
|||||||
{1228D992-C801-49BB-839A-7BD28A3FFF0A}.Debug|x86.Build.0 = Debug|x86
|
{1228D992-C801-49BB-839A-7BD28A3FFF0A}.Debug|x86.Build.0 = Debug|x86
|
||||||
{1228D992-C801-49BB-839A-7BD28A3FFF0A}.Release|x86.ActiveCfg = Release|x86
|
{1228D992-C801-49BB-839A-7BD28A3FFF0A}.Release|x86.ActiveCfg = Release|x86
|
||||||
{1228D992-C801-49BB-839A-7BD28A3FFF0A}.Release|x86.Build.0 = Release|x86
|
{1228D992-C801-49BB-839A-7BD28A3FFF0A}.Release|x86.Build.0 = Release|x86
|
||||||
|
{88979F89-9A42-448F-AE3E-3060145F6375}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{88979F89-9A42-448F-AE3E-3060145F6375}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{88979F89-9A42-448F-AE3E-3060145F6375}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{88979F89-9A42-448F-AE3E-3060145F6375}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(MonoDevelopProperties) = preSolution
|
GlobalSection(MonoDevelopProperties) = preSolution
|
||||||
Policies = $0
|
Policies = $0
|
||||||
|
|||||||
23
UICatalog/.editorconfig
Normal file
23
UICatalog/.editorconfig
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[*.cs]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 8
|
||||||
|
tab_width = 8
|
||||||
|
csharp_new_line_before_open_brace = methods,local_functions
|
||||||
|
csharp_new_line_before_else = false
|
||||||
|
csharp_new_line_before_catch = false
|
||||||
|
csharp_new_line_before_finally = false
|
||||||
|
end_of_line = crlf
|
||||||
|
|
||||||
|
csharp_indent_case_contents = true
|
||||||
|
csharp_indent_switch_labels = false
|
||||||
|
csharp_indent_labels = flush_left
|
||||||
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||||
|
csharp_preserve_single_line_blocks = true
|
||||||
|
dotnet_style_require_accessibility_modifiers = never
|
||||||
|
csharp_style_var_when_type_is_apparent = true
|
||||||
|
csharp_prefer_braces = false
|
||||||
|
csharp_space_before_open_square_brackets = true
|
||||||
|
csharp_space_between_method_call_name_and_opening_parenthesis = true
|
||||||
|
csharp_space_between_method_declaration_name_and_open_parenthesis = true
|
||||||
9
UICatalog/.gitignore
vendored
Normal file
9
UICatalog/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
###############
|
||||||
|
# folder #
|
||||||
|
###############
|
||||||
|
/**/DROP/
|
||||||
|
/**/TEMP/
|
||||||
|
/**/packages/
|
||||||
|
/**/bin/
|
||||||
|
/**/obj/
|
||||||
|
_site
|
||||||
271
UICatalog/Program.cs
Normal file
271
UICatalog/Program.cs
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
using NStack;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
/// <summary>
|
||||||
|
/// Main program for the Terminal.gui UI Catalog app. This app provides a chooser that allows
|
||||||
|
/// for a calalog of UI demos, examples, and tests.
|
||||||
|
/// </summary>
|
||||||
|
class Program {
|
||||||
|
private static Toplevel _top;
|
||||||
|
private static MenuBar _menu;
|
||||||
|
private static int _nameColumnWidth;
|
||||||
|
private static Window _leftPane;
|
||||||
|
private static List<string> _categories;
|
||||||
|
private static ListView _categoryListView;
|
||||||
|
private static Window _rightPane;
|
||||||
|
private static List<Type> _scenarios;
|
||||||
|
private static ListView _scenarioListView;
|
||||||
|
private static StatusBar _statusBar;
|
||||||
|
|
||||||
|
private static Scenario _runningScenario = null;
|
||||||
|
|
||||||
|
static void Main (string [] args)
|
||||||
|
{
|
||||||
|
if (Debugger.IsAttached)
|
||||||
|
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
|
||||||
|
|
||||||
|
_scenarios = Scenario.GetDerivedClassesCollection ().ToList ();
|
||||||
|
|
||||||
|
if (args.Length > 0) {
|
||||||
|
var item = _scenarios.FindIndex (t => Scenario.ScenarioMetadata.GetName (t).Equals (args [0], StringComparison.OrdinalIgnoreCase));
|
||||||
|
_runningScenario = (Scenario)Activator.CreateInstance (_scenarios [item]);
|
||||||
|
Application.Init ();
|
||||||
|
_runningScenario.Init (Application.Top);
|
||||||
|
_runningScenario.Setup ();
|
||||||
|
_runningScenario.Run ();
|
||||||
|
_runningScenario = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scenario scenario = GetScenarioToRun ();
|
||||||
|
while (scenario != null) {
|
||||||
|
Application.Init ();
|
||||||
|
scenario.Init (Application.Top);
|
||||||
|
scenario.Setup ();
|
||||||
|
scenario.Run ();
|
||||||
|
scenario = GetScenarioToRun ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create all controls. This gets called once and the controls remain with their state between Sceanrio runs.
|
||||||
|
/// </summary>
|
||||||
|
private static void Setup ()
|
||||||
|
{
|
||||||
|
_menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_File", new MenuItem [] {
|
||||||
|
new MenuItem ("_Quit", "", () => Application.RequestStop() )
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_About...", "About this app", () => MessageBox.Query (0, 6, "About UI Catalog", "UI Catalog is a comprehensive sample library for Terminal.Gui", "Ok")),
|
||||||
|
});
|
||||||
|
|
||||||
|
_leftPane = new Window ("Categories") {
|
||||||
|
X = 0,
|
||||||
|
Y = 1, // for menu
|
||||||
|
Width = 25,
|
||||||
|
Height = Dim.Fill (),
|
||||||
|
CanFocus = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
_categories = Scenario.GetAllCategories ();
|
||||||
|
_categoryListView = new ListView (_categories) {
|
||||||
|
X = 1,
|
||||||
|
Y = 0,
|
||||||
|
Width = Dim.Fill (0),
|
||||||
|
Height = Dim.Fill (2),
|
||||||
|
AllowsMarking = false,
|
||||||
|
CanFocus = true,
|
||||||
|
};
|
||||||
|
_categoryListView.OpenSelectedItem += (o, a) => {
|
||||||
|
_top.SetFocus (_rightPane);
|
||||||
|
};
|
||||||
|
_categoryListView.SelectedChanged += CategoryListView_SelectedChanged;
|
||||||
|
_leftPane.Add (_categoryListView);
|
||||||
|
|
||||||
|
_rightPane = new Window ("Scenarios") {
|
||||||
|
X = 25,
|
||||||
|
Y = 1, // for menu
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill (),
|
||||||
|
CanFocus = false,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
_nameColumnWidth = Scenario.ScenarioMetadata.GetName (_scenarios.OrderByDescending (t => Scenario.ScenarioMetadata.GetName (t).Length).FirstOrDefault ()).Length;
|
||||||
|
|
||||||
|
_scenarioListView = new ListView () {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
Width = Dim.Fill (0),
|
||||||
|
Height = Dim.Fill (0),
|
||||||
|
AllowsMarking = false,
|
||||||
|
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_SelectedChanged ();
|
||||||
|
|
||||||
|
_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
|
||||||
|
_runningScenario = null;
|
||||||
|
Application.RequestStop();
|
||||||
|
} else {
|
||||||
|
_runningScenario.RequestStop();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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.OnKeyUp += KeyUpHandler;
|
||||||
|
_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);
|
||||||
|
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) {
|
||||||
|
var source = _scenarioListView.Source as ScenarioListDataSource;
|
||||||
|
_runningScenario = (Scenario)Activator.CreateInstance (source.Scenarios [_scenarioListView.SelectedItem]);
|
||||||
|
Application.RequestStop ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ScenarioListDataSource : IListDataSource {
|
||||||
|
public List<Type> Scenarios { get; set; }
|
||||||
|
|
||||||
|
public bool IsMarked (int item) => false;// Scenarios [item].IsMarked;
|
||||||
|
|
||||||
|
public int Count => Scenarios.Count;
|
||||||
|
|
||||||
|
public ScenarioListDataSource (List<Type> itemList) => Scenarios = itemList;
|
||||||
|
|
||||||
|
public void Render (ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMark (int item, bool value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// A slightly adapted method from: https://github.com/migueldeicaza/gui.cs/blob/fc1faba7452ccbdf49028ac49f0c9f0f42bbae91/Terminal.Gui/Views/ListView.cs#L433-L461
|
||||||
|
private void RenderUstr (ConsoleDriver driver, ustring ustr, int col, int line, int width)
|
||||||
|
{
|
||||||
|
int used = 0;
|
||||||
|
int index = 0;
|
||||||
|
while (index < ustr.Length) {
|
||||||
|
(var rune, var size) = Utf8.DecodeRune (ustr, index, index - ustr.Length);
|
||||||
|
var count = Rune.ColumnWidth (rune);
|
||||||
|
if (used + count >= width) break;
|
||||||
|
driver.AddRune (rune);
|
||||||
|
used += count;
|
||||||
|
index += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (used < width) {
|
||||||
|
driver.AddRune (' ');
|
||||||
|
used++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When Scenarios are running we need to override the behavior of the Menu
|
||||||
|
/// and Statusbar to enable Scenarios that use those (or related key input)
|
||||||
|
/// to not be impacted. Same as for tabs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ke"></param>
|
||||||
|
private static void KeyUpHandler (KeyEvent ke)
|
||||||
|
{
|
||||||
|
if (_runningScenario != null) {
|
||||||
|
//switch (ke.Key) {
|
||||||
|
//case Key.Esc:
|
||||||
|
// //_runningScenario.RequestStop ();
|
||||||
|
// break;
|
||||||
|
//case Key.Enter:
|
||||||
|
// break;
|
||||||
|
//}
|
||||||
|
} else if (ke.Key == Key.Tab || ke.Key == Key.BackTab) {
|
||||||
|
// BUGBUG: Work around Issue #434 by implementing our own TAB navigation
|
||||||
|
if (_top.MostFocused == _categoryListView)
|
||||||
|
_top.SetFocus (_rightPane);
|
||||||
|
else
|
||||||
|
_top.SetFocus (_leftPane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CategoryListView_SelectedChanged ()
|
||||||
|
{
|
||||||
|
var item = _categories [_categoryListView.SelectedItem];
|
||||||
|
List<Type> newlist;
|
||||||
|
if (item.Equals ("All")) {
|
||||||
|
newlist = _scenarios;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
newlist = _scenarios.Where (t => Scenario.ScenarioCategory.GetCategories (t).Contains (item)).ToList ();
|
||||||
|
}
|
||||||
|
_scenarioListView.Source = new ScenarioListDataSource (newlist);
|
||||||
|
_scenarioListView.SelectedItem = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
UICatalog/Properties/launchSettings.json
Normal file
8
UICatalog/Properties/launchSettings.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"UICatalog": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"commandLineArgs": "HexEditor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
122
UICatalog/README.md
Normal file
122
UICatalog/README.md
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
# Terminal.Gui UI Catalog
|
||||||
|
|
||||||
|
UI Catalog is a comprehensive sample library for Terminal.Gui. It attempts to satisfy the following goals:
|
||||||
|
|
||||||
|
1. Be an easy to use showcase for Terminal.Gui concepts and features.
|
||||||
|
2. Provide sample code that illustrates how to properly implement said concepts & features.
|
||||||
|
3. Make it easy for contributors to add additional samples in a structured way.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
The original `demo.cs` sample app for Terminal.Gui is neither good to showcase, nor does it explain different concepts. In addition, because it is built on a single source file, it has proven to cause friction when multiple contributors are simultaneously working on different aspects of Terminal.Gui. See [Issue #368](https://github.com/migueldeicaza/Terminal.Gui/issues/368) for more background.
|
||||||
|
|
||||||
|
## How To Use
|
||||||
|
|
||||||
|
`Program.cs` is the main app and provides a UI for selecting and running **Scenarios**. Each **Scenario* is implemented as a class derived from `Scenario` and `Program.cs` uses reflection to dynamically build the UI.
|
||||||
|
|
||||||
|
**Scenarios** are tagged with categories using the `[ScenarioCategory]` attribute. The left pane of the main screen lists the categories. Clicking on a category shows all the scenarios in that category.
|
||||||
|
|
||||||
|
**Scenarios** can be run either from the **UICatalog.exe** app UI or by being specified on the command line:
|
||||||
|
|
||||||
|
```
|
||||||
|
UICatalog.exe <Scenario Name>
|
||||||
|
```
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
UICatalog.exe Buttons
|
||||||
|
```
|
||||||
|
|
||||||
|
When a **Scenario** is run, it runs as though it were a standalone `Terminal.Gui` app. However, scaffolding is provided (in the `Scenario` base class) that (optionally) takes care of `Terminal.Gui` initialization.
|
||||||
|
|
||||||
|
## Contributing by Adding Scenarios
|
||||||
|
|
||||||
|
To add a new **Scenario** simply:
|
||||||
|
|
||||||
|
1. Create a new `.cs` file in the `Scenarios` directory that derives from `Scenario`.
|
||||||
|
2. Add a `[ScenarioMetaData]` attribute to the class specifying the scenario's name and description.
|
||||||
|
3. Add one or more `[ScenarioCategory]` attributes to the class specifying which categories the sceanrio belongs to. If you don't specify a category the sceanrio will show up in "All".
|
||||||
|
4. Implement the `Setup` override which will be called when a user selects the scenario to run.
|
||||||
|
5. Optionally, implement the `Init` and/or `Run` overrides to provide a custom implementation.
|
||||||
|
|
||||||
|
The sample below is provided in the `Scenarios` directory as a generic sample that can be copied and re-named:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Generic", Description: "Generic sample - A template for creating new Scenarios")]
|
||||||
|
[ScenarioCategory ("Controls")]
|
||||||
|
class MyScenario : Scenario {
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
// Put your scenario code here, e.g.
|
||||||
|
Win.Add (new Button ("Press me!") {
|
||||||
|
X = Pos.Center (),
|
||||||
|
Y = Pos.Center (),
|
||||||
|
Clicked = () => MessageBox.Query (20, 7, "Hi", "Neat?", "Yes", "No")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`Scenario` provides a `Toplevel` and `Window` the provides a canvas for the Scenario to operate. The default `Window` shows the Scenario name and supports exiting the Scenario through the `Esc` key.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
To build a more advanced scenario, where control of the `Toplevel` and `Window` is needed (e.g. for scenarios using `MenuBar` or `StatusBar`), simply set the `Top` and `Window` properties as appropriate, as seen in the `UnicodeInMenu` scenario:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Unicode In Menu", Description: "Unicode menus per PR #204")]
|
||||||
|
[ScenarioCategory ("Text")]
|
||||||
|
[ScenarioCategory ("Controls")]
|
||||||
|
class UnicodeInMenu : Scenario {
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
Top = new Toplevel (new Rect (0, 0, Application.Driver.Cols, Application.Driver.Rows));
|
||||||
|
var menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_Файл", new MenuItem [] {
|
||||||
|
new MenuItem ("_Создать", "Creates new file", null),
|
||||||
|
new MenuItem ("_Открыть", "", null),
|
||||||
|
new MenuItem ("Со_хранить", "", null),
|
||||||
|
new MenuItem ("_Выход", "", () => Application.RequestStop() )
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_Edit", new MenuItem [] {
|
||||||
|
new MenuItem ("_Copy", "", null),
|
||||||
|
new MenuItem ("C_ut", "", null),
|
||||||
|
new MenuItem ("_Paste", "", null)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
Top.Add (menu);
|
||||||
|
|
||||||
|
Win = new Window ($"Scenario: {GetName ()}") {
|
||||||
|
X = 0,
|
||||||
|
Y = 1,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
Top.Add (Win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For complete control, the `Init` and `Run` overrides can be implemented. The `base.Init` assigns `Application.Top` to `Top` and creates `Win`. The `base.Run` simply calls `Application.Run(Top)`.
|
||||||
|
|
||||||
|
## Contribution Guidelines
|
||||||
|
|
||||||
|
- Provide a terse, descriptive name for `Scenarios`. Keep them short; the `ListView` that displays them dynamically sizes the column width and long names will make it hard for people to use.
|
||||||
|
- Provide a clear description.
|
||||||
|
- Comment `Scenario` code to describe to others why it's a useful `Scenario`.
|
||||||
|
- Annotate `Scenarios` with `[ScenarioCategory]` attributes. Try to minimize the number of new categories created.
|
||||||
|
- Use the `Bug Rero` Category for `Scnarios` that reproduce bugs.
|
||||||
|
- Include the Github Issue # in the Description.
|
||||||
|
- Once the bug has been fixed in `master` submit another PR to remove the `Scenario` (or modify it to provide a good regression test).
|
||||||
|
- Tag bugs or suggestions for `UI Catalog` in the main `Terminal.Gui` Github Issues with "UICatalog: ".
|
||||||
181
UICatalog/Scenario.cs
Normal file
181
UICatalog/Scenario.cs
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
using NStack;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
/// <summary>
|
||||||
|
/// Base class for each demo/scenario. To define a new sceanrio simply
|
||||||
|
///
|
||||||
|
/// 1) declare a class derived from Scenario,
|
||||||
|
/// 2) Set Name and Description as appropriate using [ScenarioMetadata] attribute
|
||||||
|
/// 3) Set one or more categories with the [ScenarioCategory] attribute
|
||||||
|
/// 4) Implement Setup.
|
||||||
|
/// 5) Optionally, implement Run.
|
||||||
|
///
|
||||||
|
/// The Main program uses reflection to find all sceanarios and adds them to the
|
||||||
|
/// ListViews. Press ENTER to run the selected sceanrio. Press CTRL-Q to exit it.
|
||||||
|
/// </summary>
|
||||||
|
public class Scenario {
|
||||||
|
/// <summary>
|
||||||
|
/// The Top level for the Scenario. This should be set to `Application.Top` in most cases.
|
||||||
|
/// </summary>
|
||||||
|
public Toplevel Top { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public Window Win { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper that provides the default Window implementation with a frame and
|
||||||
|
/// label showing the name of the Scenario and logic to exit back to
|
||||||
|
/// the Scenario picker UI.
|
||||||
|
/// Override Init to provide any `Toplevel` behavior needed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="top"></param>
|
||||||
|
public virtual void Init(Toplevel top)
|
||||||
|
{
|
||||||
|
Top = top;
|
||||||
|
Win = new Window ($"CTRL-Q to Close - Scenario: {GetName ()}") {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
Top.Add (Win);
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.AttributeUsage (System.AttributeTargets.Class)]
|
||||||
|
public class ScenarioMetadata : System.Attribute {
|
||||||
|
/// <summary>
|
||||||
|
/// Scenario Name
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scenario Description
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
public ScenarioMetadata (string Name, string Description)
|
||||||
|
{
|
||||||
|
this.Name = Name;
|
||||||
|
this.Description = Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static helper function to get the Scenario Name given a Type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetName (Type t) => ((ScenarioMetadata)System.Attribute.GetCustomAttributes (t) [0]).Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static helper function to get the Scenario Description given a Type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetDescription (Type t) => ((ScenarioMetadata)System.Attribute.GetCustomAttributes (t) [0]).Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper to get the Scenario Name
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string GetName () => ScenarioMetadata.GetName (this.GetType ());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper to get the Scenario Descripiton
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string GetDescription () => ScenarioMetadata.GetDescription (this.GetType ());
|
||||||
|
|
||||||
|
[System.AttributeUsage (System.AttributeTargets.Class, AllowMultiple = true)]
|
||||||
|
public class ScenarioCategory : System.Attribute {
|
||||||
|
/// <summary>
|
||||||
|
/// Category Name
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public ScenarioCategory (string Name) => this.Name = Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static helper function to get the Scenario Name given a Type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetName (Type t) => ((ScenarioCategory)System.Attribute.GetCustomAttributes (t) [0]).Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static helper function to get the Scenario Categories given a Type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<string> GetCategories (Type t) => System.Attribute.GetCustomAttributes (t)
|
||||||
|
.ToList ()
|
||||||
|
.Where (a => a is ScenarioCategory)
|
||||||
|
.Select (a => ((ScenarioCategory)a).Name)
|
||||||
|
.ToList ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper function to get the Categories of a Scenario
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<string> GetCategories () => ScenarioCategory.GetCategories (this.GetType ());
|
||||||
|
|
||||||
|
public override string ToString () => $"{GetName (),-30}{GetDescription ()}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Override this to implement the Scenario setup logic (create controls, etc...).
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Setup ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the scenario. Override to start the scearnio using a Top level different than `Top`.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Run ()
|
||||||
|
{
|
||||||
|
Application.Run (Top);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stops the scenario. Override to implement shutdown behavior for the Scenario.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void RequestStop ()
|
||||||
|
{
|
||||||
|
Application.RequestStop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of all Categories set by all of the scenarios defined in the project.
|
||||||
|
/// </summary>
|
||||||
|
internal static List<string> GetAllCategories ()
|
||||||
|
{
|
||||||
|
List<string> categories = new List<string> () { "All" };
|
||||||
|
foreach (Type type in typeof (Scenario).Assembly.GetTypes ()
|
||||||
|
.Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (Scenario)))) {
|
||||||
|
List<System.Attribute> attrs = System.Attribute.GetCustomAttributes (type).ToList ();
|
||||||
|
categories = categories.Union (attrs.Where (a => a is ScenarioCategory).Select (a => ((ScenarioCategory)a).Name)).ToList ();
|
||||||
|
}
|
||||||
|
return categories;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an instance of each Scenario defined in the project.
|
||||||
|
/// https://stackoverflow.com/questions/5411694/get-all-inherited-classes-of-an-abstract-class
|
||||||
|
/// </summary>
|
||||||
|
internal static List<Type> GetDerivedClassesCollection ()
|
||||||
|
{
|
||||||
|
List<Type> objects = new List<Type> ();
|
||||||
|
foreach (Type type in typeof (Scenario).Assembly.GetTypes ()
|
||||||
|
.Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (Scenario)))) {
|
||||||
|
objects.Add (type);
|
||||||
|
}
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
UICatalog/Scenarios/Buttons.cs
Normal file
105
UICatalog/Scenarios/Buttons.cs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Buttons", Description: "Demonstrates all sorts of Buttons")]
|
||||||
|
[ScenarioCategory ("Controls")]
|
||||||
|
[ScenarioCategory ("Layout")]
|
||||||
|
class Buttons : Scenario {
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
// Add a label & text field so we can demo IsDefault
|
||||||
|
var editLabel = new Label ("TextField (to demo IsDefault):") {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
};
|
||||||
|
Win.Add (editLabel);
|
||||||
|
var edit = new TextField ("") {
|
||||||
|
X = Pos.Right (editLabel) + 1,
|
||||||
|
Y = Pos.Top (editLabel),
|
||||||
|
Width = Dim.Fill (2),
|
||||||
|
};
|
||||||
|
Win.Add (edit);
|
||||||
|
|
||||||
|
// This is the default button (IsDefault = true); if user presses ENTER in the TextField
|
||||||
|
// the scenario will quit
|
||||||
|
var defaultButton = new Button ("Quit") {
|
||||||
|
X = Pos.Center (),
|
||||||
|
// BUGBUG: Throws an exception
|
||||||
|
//Y= Pos.Bottom(Win),
|
||||||
|
Y = 20,
|
||||||
|
IsDefault = true,
|
||||||
|
Clicked = () => Application.RequestStop (),
|
||||||
|
};
|
||||||
|
Win.Add (defaultButton);
|
||||||
|
|
||||||
|
var y = 2;
|
||||||
|
var button = new Button (10, y, "Base Color") {
|
||||||
|
ColorScheme = Colors.Base,
|
||||||
|
Clicked = () => MessageBox.Query (30, 7, "Message", "Question?", "Yes", "No")
|
||||||
|
};
|
||||||
|
Win.Add (button);
|
||||||
|
|
||||||
|
y += 2;
|
||||||
|
Win.Add (new Button (10, y, "Error Color") {
|
||||||
|
ColorScheme = Colors.Error,
|
||||||
|
Clicked = () => MessageBox.Query (30, 7, "Message", "Question?", "Yes", "No")
|
||||||
|
});
|
||||||
|
|
||||||
|
y += 2;
|
||||||
|
Win.Add (new Button (10, y, "Dialog Color") {
|
||||||
|
ColorScheme = Colors.Dialog,
|
||||||
|
Clicked = () => MessageBox.Query (30, 7, "Message", "Question?", "Yes", "No")
|
||||||
|
});
|
||||||
|
|
||||||
|
y += 2;
|
||||||
|
Win.Add (new Button (10, y, "Menu Color") {
|
||||||
|
ColorScheme = Colors.Menu,
|
||||||
|
Clicked = () => MessageBox.Query (30, 7, "Message", "Question?", "Yes", "No")
|
||||||
|
});
|
||||||
|
|
||||||
|
y += 2;
|
||||||
|
Win.Add (new Button (10, y, "TopLevel Color") {
|
||||||
|
ColorScheme = Colors.TopLevel,
|
||||||
|
Clicked = () => MessageBox.Query (30, 7, "Message", "Question?", "Yes", "No")
|
||||||
|
});
|
||||||
|
|
||||||
|
y += 2;
|
||||||
|
Win.Add (new Button (10, y, "A super long button that will probably expose a bug in clipping or wrapping of text. Will it?") {
|
||||||
|
Clicked = () => MessageBox.Query (30, 7, "Message", "Question?", "Yes", "No")
|
||||||
|
});
|
||||||
|
|
||||||
|
y += 2;
|
||||||
|
// Note the 'N' in 'Newline' will be the hotkey
|
||||||
|
Win.Add (new Button (10, y, "a Newline\nin the button") {
|
||||||
|
Clicked = () => MessageBox.Query (30, 7, "Message", "Question?", "Yes", "No")
|
||||||
|
});
|
||||||
|
|
||||||
|
y += 2;
|
||||||
|
// BUGBUG: Buttons don't support specifying hotkeys with _?!?
|
||||||
|
Win.Add (button = new Button (10, y, "Te_xt Changer") {
|
||||||
|
});
|
||||||
|
button.Clicked = () => button.Text += $"{y++}";
|
||||||
|
|
||||||
|
Win.Add (new Button ("Lets see if this will move as \"Text Changer\" grows") {
|
||||||
|
X = Pos.Right(button) + 10,
|
||||||
|
Y = y,
|
||||||
|
});
|
||||||
|
|
||||||
|
y += 2;
|
||||||
|
Win.Add (new Button (10, y, "Delete") {
|
||||||
|
ColorScheme = Colors.Error,
|
||||||
|
Clicked = () => Win.Remove (button)
|
||||||
|
});
|
||||||
|
|
||||||
|
y += 2;
|
||||||
|
Win.Add (new Button (10, y, "Change Default") {
|
||||||
|
Clicked = () => {
|
||||||
|
defaultButton.IsDefault = !defaultButton.IsDefault;
|
||||||
|
button.IsDefault = !button.IsDefault;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
82
UICatalog/Scenarios/DimAndPosLayout.cs
Normal file
82
UICatalog/Scenarios/DimAndPosLayout.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
/// <summary>
|
||||||
|
/// This Scenario demonstrates how to use Termina.gui's Dim and Pos Layout System.
|
||||||
|
/// [x] - Using Dim.Fill to fill a window
|
||||||
|
/// [x] - Using Dim.Fill and Dim.Pos to automatically align controls based on an initial control
|
||||||
|
/// [ ] - ...
|
||||||
|
/// </summary>
|
||||||
|
[ScenarioMetadata (Name: "DimAndPosLayout", Description: "Demonstrates using the Dim and Pos Layout System")]
|
||||||
|
[ScenarioCategory ("Layout")]
|
||||||
|
class DimAndPosLayout : Scenario {
|
||||||
|
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
Top.LayoutStyle = LayoutStyle.Computed;
|
||||||
|
// Demonstrate using Dim to create a ruler that always measures the top-level window's width
|
||||||
|
// BUGBUG: Dim.Fill returns too big a value sometimes.
|
||||||
|
//const string rule = "|123456789";
|
||||||
|
//var labelRuler = new Label ("ruler") {
|
||||||
|
// 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
|
||||||
|
//};
|
||||||
|
|
||||||
|
//Application.OnResized += () => {
|
||||||
|
// labelRuler.Text = rule.Repeat ((int)Math.Ceiling((double)(labelRuler.Bounds.Width) / (double)rule.Length))[0..(labelRuler.Bounds.Width)];
|
||||||
|
//};
|
||||||
|
|
||||||
|
//win.Add (labelRuler);
|
||||||
|
|
||||||
|
// Demonstrate using Dim to create a window that fills the parent with a margin
|
||||||
|
int margin = 20;
|
||||||
|
var subWin = new Window ($"Sub Windoww with {margin} character margin") {
|
||||||
|
X = margin,
|
||||||
|
Y = 2,
|
||||||
|
Width = Dim.Fill (margin),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
Win.Add (subWin);
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
string txt = "Hello world, how are you doing today";
|
||||||
|
var labelList = new List<Label> ();
|
||||||
|
labelList.Add (new Label ($"Label:"));
|
||||||
|
labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Left, Width = Dim.Fill (1), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()) + 1, ColorScheme = Colors.Dialog });
|
||||||
|
labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Right, Width = Dim.Fill (1), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()) + 1, ColorScheme = Colors.Dialog });
|
||||||
|
labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Centered, Width = Dim.Fill (1), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()) + 1, ColorScheme = Colors.Dialog });
|
||||||
|
labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Justified, Width = Dim.Fill (1), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()) + 1, ColorScheme = Colors.Dialog });
|
||||||
|
|
||||||
|
subWin.Add (labelList.ToArray ());
|
||||||
|
//subWin.LayoutSubviews ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Run ()
|
||||||
|
{
|
||||||
|
base.Run ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StringExtensions {
|
||||||
|
public static string Repeat (this string instr, int n)
|
||||||
|
{
|
||||||
|
if (n <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty (instr) || n == 1) {
|
||||||
|
return instr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StringBuilder (instr.Length * n)
|
||||||
|
.Insert (0, instr, n)
|
||||||
|
.ToString ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
150
UICatalog/Scenarios/Editor.cs
Normal file
150
UICatalog/Scenarios/Editor.cs
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Editor", Description: "A Terminal.Gui Text Editor via TextView")]
|
||||||
|
[ScenarioCategory ("Controls")]
|
||||||
|
[ScenarioCategory ("Text")]
|
||||||
|
class Editor : Scenario {
|
||||||
|
private string _fileName = "demo.txt";
|
||||||
|
private TextView _textView;
|
||||||
|
private bool _saved = true;
|
||||||
|
|
||||||
|
|
||||||
|
public override void Init (Toplevel top)
|
||||||
|
{
|
||||||
|
Top = top;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
var menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_File", new MenuItem [] {
|
||||||
|
new MenuItem ("_New", "", () => New()),
|
||||||
|
new MenuItem ("_Open", "", () => Open()),
|
||||||
|
new MenuItem ("_Save", "", () => Save()),
|
||||||
|
null,
|
||||||
|
new MenuItem ("_Quit", "", () => Quit()),
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_Edit", new MenuItem [] {
|
||||||
|
new MenuItem ("_Copy", "", () => Copy()),
|
||||||
|
new MenuItem ("C_ut", "", () => Cut()),
|
||||||
|
new MenuItem ("_Paste", "", () => Paste())
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
Top.Add (menu);
|
||||||
|
|
||||||
|
var statusBar = new StatusBar (new StatusItem [] {
|
||||||
|
new StatusItem(Key.F2, "~F2~ Open", () => Open()),
|
||||||
|
new StatusItem(Key.F3, "~F3~ Save", () => Save()),
|
||||||
|
new StatusItem(Key.ControlQ, "~^Q~ Quit", () => Quit()),
|
||||||
|
});
|
||||||
|
Top.Add (statusBar);
|
||||||
|
|
||||||
|
CreateDemoFile (_fileName);
|
||||||
|
|
||||||
|
Win = new Window (_fileName ?? "Untitled") {
|
||||||
|
X = 0,
|
||||||
|
Y = 1,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
Top.Add (Win);
|
||||||
|
|
||||||
|
_textView = new TextView () {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill (),
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
LoadFile ();
|
||||||
|
|
||||||
|
Win.Add (_textView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void New ()
|
||||||
|
{
|
||||||
|
Win.Title = _fileName = "Untitled";
|
||||||
|
throw new NotImplementedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadFile ()
|
||||||
|
{
|
||||||
|
if (!_saved) {
|
||||||
|
MessageBox.ErrorQuery (0, 10, "Not Implemented", "Functionality not yet implemented.", "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_fileName != null) {
|
||||||
|
// BUGBUG: #452 TextView.LoadFile keeps file open and provides no way of closing it
|
||||||
|
//_textView.LoadFile(_fileName);
|
||||||
|
_textView.Text = System.IO.File.ReadAllText (_fileName);
|
||||||
|
Win.Title = _fileName;
|
||||||
|
_saved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Paste ()
|
||||||
|
{
|
||||||
|
MessageBox.ErrorQuery (0, 10, "Not Implemented", "Functionality not yet implemented.", "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cut ()
|
||||||
|
{
|
||||||
|
MessageBox.ErrorQuery (0, 10, "Not Implemented", "Functionality not yet implemented.", "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Copy ()
|
||||||
|
{
|
||||||
|
MessageBox.ErrorQuery (0, 10, "Not Implemented", "Functionality not yet implemented.", "Ok");
|
||||||
|
//if (_textView != null && _textView.SelectedLength != 0) {
|
||||||
|
// _textView.Copy ();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Open ()
|
||||||
|
{
|
||||||
|
var d = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = false };
|
||||||
|
Application.Run (d);
|
||||||
|
|
||||||
|
if (!d.Canceled) {
|
||||||
|
_fileName = d.FilePaths [0];
|
||||||
|
LoadFile ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save ()
|
||||||
|
{
|
||||||
|
if (_fileName != null) {
|
||||||
|
// BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
|
||||||
|
// As a result files saved on Windows and then read back will show invalid chars.
|
||||||
|
System.IO.File.WriteAllText (_fileName, _textView.Text.ToString());
|
||||||
|
_saved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Quit ()
|
||||||
|
{
|
||||||
|
Application.RequestStop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateDemoFile(string fileName)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder ();
|
||||||
|
// BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
|
||||||
|
sb.Append ("Hello world.\n");
|
||||||
|
sb.Append ("This is a test of the Emergency Broadcast System.\n");
|
||||||
|
|
||||||
|
var sw = System.IO.File.CreateText (fileName);
|
||||||
|
sw.Write (sb.ToString ());
|
||||||
|
sw.Close ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Run ()
|
||||||
|
{
|
||||||
|
Application.Run (Top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
UICatalog/Scenarios/Generic.cs
Normal file
17
UICatalog/Scenarios/Generic.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Generic", Description: "Generic sample - A template for creating new Scenarios")]
|
||||||
|
[ScenarioCategory ("Controls")]
|
||||||
|
class MyScenario : Scenario {
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
// Put your scenario code here, e.g.
|
||||||
|
Win.Add (new Button ("Press me!") {
|
||||||
|
X = Pos.Center (),
|
||||||
|
Y = Pos.Center (),
|
||||||
|
Clicked = () => MessageBox.Query (20, 7, "Hi", "Neat?", "Yes", "No")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
154
UICatalog/Scenarios/HexEditor.cs
Normal file
154
UICatalog/Scenarios/HexEditor.cs
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "HexEditor", Description: "A Terminal.Gui binary (hex) editor via HexView")]
|
||||||
|
[ScenarioCategory ("Controls")]
|
||||||
|
[ScenarioCategory ("Text")]
|
||||||
|
class HexEditor : Scenario {
|
||||||
|
private string _fileName = "demo.bin";
|
||||||
|
private HexView _hexView;
|
||||||
|
private bool _saved = true;
|
||||||
|
|
||||||
|
|
||||||
|
public override void Init (Toplevel top)
|
||||||
|
{
|
||||||
|
Top = top;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
var menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_File", new MenuItem [] {
|
||||||
|
new MenuItem ("_New", "", () => New()),
|
||||||
|
new MenuItem ("_Open", "", () => Open()),
|
||||||
|
new MenuItem ("_Save", "", () => Save()),
|
||||||
|
null,
|
||||||
|
new MenuItem ("_Quit", "", () => Quit()),
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_Edit", new MenuItem [] {
|
||||||
|
new MenuItem ("_Copy", "", () => Copy()),
|
||||||
|
new MenuItem ("C_ut", "", () => Cut()),
|
||||||
|
new MenuItem ("_Paste", "", () => Paste())
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
Top.Add (menu);
|
||||||
|
|
||||||
|
var statusBar = new StatusBar (new StatusItem [] {
|
||||||
|
//new StatusItem(Key.Enter, "~ENTER~ ApplyEdits", () => { _hexView.ApplyEdits(); }),
|
||||||
|
new StatusItem(Key.F2, "~F2~ Open", () => Open()),
|
||||||
|
new StatusItem(Key.F3, "~F3~ Save", () => Save()),
|
||||||
|
new StatusItem(Key.ControlQ, "~^Q~ Quit", () => Quit()),
|
||||||
|
});
|
||||||
|
Top.Add (statusBar);
|
||||||
|
|
||||||
|
CreateDemoFile (_fileName);
|
||||||
|
|
||||||
|
Win = new Window (_fileName ?? "Untitled") {
|
||||||
|
X = 0,
|
||||||
|
Y = 1,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
Top.Add (Win);
|
||||||
|
|
||||||
|
_hexView = new HexView (LoadFile()) {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill (),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Win.Add (_hexView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void New ()
|
||||||
|
{
|
||||||
|
Win.Title = _fileName = "Untitled";
|
||||||
|
throw new NotImplementedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream LoadFile ()
|
||||||
|
{
|
||||||
|
MemoryStream stream = null;
|
||||||
|
if (!_saved) {
|
||||||
|
MessageBox.ErrorQuery (0, 10, "Not Implemented", "Functionality not yet implemented.", "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_fileName != null) {
|
||||||
|
var bin = System.IO.File.ReadAllBytes (_fileName);
|
||||||
|
stream = new MemoryStream (bin);
|
||||||
|
Win.Title = _fileName;
|
||||||
|
_saved = true;
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Paste ()
|
||||||
|
{
|
||||||
|
MessageBox.ErrorQuery (0, 10, "Not Implemented", "Functionality not yet implemented.", "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cut ()
|
||||||
|
{
|
||||||
|
MessageBox.ErrorQuery (0, 10, "Not Implemented", "Functionality not yet implemented.", "Ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Copy ()
|
||||||
|
{
|
||||||
|
MessageBox.ErrorQuery (0, 10, "Not Implemented", "Functionality not yet implemented.", "Ok");
|
||||||
|
//if (_textView != null && _textView.SelectedLength != 0) {
|
||||||
|
// _textView.Copy ();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Open ()
|
||||||
|
{
|
||||||
|
var d = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = false };
|
||||||
|
Application.Run (d);
|
||||||
|
|
||||||
|
if (!d.Canceled) {
|
||||||
|
_fileName = d.FilePaths [0];
|
||||||
|
_hexView.Source = LoadFile ();
|
||||||
|
_hexView.DisplayStart = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save ()
|
||||||
|
{
|
||||||
|
if (_fileName != null) {
|
||||||
|
using (FileStream fs = new FileStream (_fileName, FileMode.OpenOrCreate)) {
|
||||||
|
_hexView.ApplyEdits ();
|
||||||
|
_hexView.Source.CopyTo (fs);
|
||||||
|
fs.Flush ();
|
||||||
|
}
|
||||||
|
_saved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Quit ()
|
||||||
|
{
|
||||||
|
Application.RequestStop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateDemoFile(string fileName)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder ();
|
||||||
|
// BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
|
||||||
|
sb.Append ("Hello world.\n");
|
||||||
|
sb.Append ("This is a test of the Emergency Broadcast System.\n");
|
||||||
|
|
||||||
|
var sw = System.IO.File.CreateText (fileName);
|
||||||
|
sw.Write (sb.ToString ());
|
||||||
|
sw.Close ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Run ()
|
||||||
|
{
|
||||||
|
Application.Run (Top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
181
UICatalog/Scenarios/Keys.cs
Normal file
181
UICatalog/Scenarios/Keys.cs
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
using NStack;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Keys", Description: "Shows how to handle keyboard input")]
|
||||||
|
[ScenarioCategory ("Input")]
|
||||||
|
class Keys : Scenario {
|
||||||
|
|
||||||
|
static List<string> _processKeyList = new List<string> ();
|
||||||
|
static List<string> _processHotKeyList = new List<string> ();
|
||||||
|
static List<string> _processColdKeyList = new List<string> ();
|
||||||
|
|
||||||
|
class TestWindow : Window {
|
||||||
|
public TestWindow (ustring title = null) : base (title)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestWindow (Rect frame, ustring title = null) : base (frame, title)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestWindow (ustring title = null, int padding = 0) : base (title, padding)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestWindow (Rect frame, ustring title = null, int padding = 0) : base (frame, title, padding)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ProcessKey (KeyEvent keyEvent)
|
||||||
|
{
|
||||||
|
_processKeyList.Add (keyEvent.ToString ());
|
||||||
|
return base.ProcessKey (keyEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ProcessHotKey (KeyEvent keyEvent)
|
||||||
|
{
|
||||||
|
_processHotKeyList.Add (keyEvent.ToString ());
|
||||||
|
return base.ProcessHotKey (keyEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ProcessColdKey (KeyEvent keyEvent)
|
||||||
|
{
|
||||||
|
_processColdKeyList.Add (keyEvent.ToString ());
|
||||||
|
return base.ProcessHotKey (keyEvent);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Init (Toplevel top)
|
||||||
|
{
|
||||||
|
Top = top;
|
||||||
|
|
||||||
|
Win = new TestWindow ($"CTRL-Q to Close - Scenario: {GetName ()}") {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
Top.Add (Win);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
// Type text here: ______
|
||||||
|
var editLabel = new Label ("Type text here:") {
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
};
|
||||||
|
Win.Add (editLabel);
|
||||||
|
var edit = new TextField ("") {
|
||||||
|
X = Pos.Right (editLabel) + 1,
|
||||||
|
Y = Pos.Top (editLabel),
|
||||||
|
Width = Dim.Fill (2),
|
||||||
|
};
|
||||||
|
Win.Add (edit);
|
||||||
|
|
||||||
|
// Last KeyPress: ______
|
||||||
|
var keyPressedLabel = new Label ("Last KeyPress:") {
|
||||||
|
X = Pos.Left (editLabel),
|
||||||
|
Y = Pos.Top (editLabel) + 2,
|
||||||
|
};
|
||||||
|
Win.Add (keyPressedLabel);
|
||||||
|
// BUGBUG: Label is not positioning right with Pos, so using TextField instead
|
||||||
|
var labelKeypress = new TextField ("") {
|
||||||
|
X = Pos.Right (keyPressedLabel) + 1,
|
||||||
|
Y = Pos.Top (keyPressedLabel),
|
||||||
|
Width = 20,
|
||||||
|
//TextAlignment = Terminal.Gui.TextAlignment.Left,
|
||||||
|
ColorScheme = Colors.Error,
|
||||||
|
};
|
||||||
|
Win.Add (labelKeypress);
|
||||||
|
|
||||||
|
Win.OnKeyPress += (KeyEvent keyEvent) => labelKeypress.Text = keyEvent.ToString ();
|
||||||
|
|
||||||
|
// Key stroke log:
|
||||||
|
var keyLogLabel = new Label ("Key stroke log:") {
|
||||||
|
X = Pos.Left (editLabel),
|
||||||
|
Y = Pos.Top (editLabel) + 4,
|
||||||
|
};
|
||||||
|
Win.Add (keyLogLabel);
|
||||||
|
|
||||||
|
var yOffset = (Top == Application.Top ? 1 : 6);
|
||||||
|
var keyStrokelist = new List<string> ();
|
||||||
|
var keyStrokeListView = new ListView (keyStrokelist) {
|
||||||
|
X = 0,
|
||||||
|
Y = Pos.Top (keyLogLabel) + yOffset,
|
||||||
|
Width = 25,
|
||||||
|
Height = Dim.Fill (),
|
||||||
|
};
|
||||||
|
keyStrokeListView.ColorScheme = Colors.TopLevel;
|
||||||
|
Win.Add (keyStrokeListView);
|
||||||
|
|
||||||
|
void KeyDownPressUp (KeyEvent keyEvent, string updown)
|
||||||
|
{
|
||||||
|
var msg = $"Key{updown,-5}: {keyEvent.ToString ()}";
|
||||||
|
keyStrokelist.Add (msg);
|
||||||
|
keyStrokeListView.MoveDown ();
|
||||||
|
}
|
||||||
|
|
||||||
|
Win.OnKeyDown += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Down");
|
||||||
|
Win.OnKeyPress += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Press");
|
||||||
|
Win.OnKeyUp += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Up");
|
||||||
|
|
||||||
|
// ProcessKey log:
|
||||||
|
// BUGBUG: Label is not positioning right with Pos, so using TextField instead
|
||||||
|
var processKeyLogLabel = new Label ("ProcessKey log:") {
|
||||||
|
X = Pos.Right (keyStrokeListView) + 1,
|
||||||
|
Y = Pos.Top (editLabel) + 4,
|
||||||
|
};
|
||||||
|
Win.Add (processKeyLogLabel);
|
||||||
|
|
||||||
|
yOffset = (Top == Application.Top ? 1 : 6);
|
||||||
|
var processKeyListView = new ListView (_processKeyList) {
|
||||||
|
X = Pos.Left (processKeyLogLabel),
|
||||||
|
Y = Pos.Top (processKeyLogLabel) + yOffset,
|
||||||
|
Width = 25,
|
||||||
|
Height = Dim.Fill (),
|
||||||
|
};
|
||||||
|
processKeyListView.ColorScheme = Colors.TopLevel;
|
||||||
|
Win.Add (processKeyListView);
|
||||||
|
|
||||||
|
// ProcessHotKey log:
|
||||||
|
// BUGBUG: Label is not positioning right with Pos, so using TextField instead
|
||||||
|
var processHotKeyLogLabel = new Label ("ProcessHotKey log:") {
|
||||||
|
X = Pos.Right (processKeyListView) + 1,
|
||||||
|
Y = Pos.Top (editLabel) + 4,
|
||||||
|
};
|
||||||
|
Win.Add (processHotKeyLogLabel);
|
||||||
|
|
||||||
|
yOffset = (Top == Application.Top ? 1 : 6);
|
||||||
|
var processHotKeyListView = new ListView (_processHotKeyList) {
|
||||||
|
X = Pos.Left (processHotKeyLogLabel),
|
||||||
|
Y = Pos.Top (processHotKeyLogLabel) + yOffset,
|
||||||
|
Width = 25,
|
||||||
|
Height = Dim.Fill (),
|
||||||
|
};
|
||||||
|
processHotKeyListView.ColorScheme = Colors.TopLevel;
|
||||||
|
Win.Add (processHotKeyListView);
|
||||||
|
|
||||||
|
// ProcessColdKey log:
|
||||||
|
// BUGBUG: Label is not positioning right with Pos, so using TextField instead
|
||||||
|
var processColdKeyLogLabel = new Label ("ProcessColdKey log:") {
|
||||||
|
X = Pos.Right (processHotKeyListView) + 1,
|
||||||
|
Y = Pos.Top (editLabel) + 4,
|
||||||
|
};
|
||||||
|
Win.Add (processColdKeyLogLabel);
|
||||||
|
|
||||||
|
yOffset = (Top == Application.Top ? 1 : 6);
|
||||||
|
var processColdKeyListView = new ListView (_processColdKeyList) {
|
||||||
|
X = Pos.Left (processColdKeyLogLabel),
|
||||||
|
Y = Pos.Top (processColdKeyLogLabel) + yOffset,
|
||||||
|
Width = 25,
|
||||||
|
Height = Dim.Fill (),
|
||||||
|
};
|
||||||
|
processColdKeyListView.ColorScheme = Colors.TopLevel;
|
||||||
|
Win.Add (processColdKeyListView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
UICatalog/Scenarios/MessageBoxes.cs
Normal file
42
UICatalog/Scenarios/MessageBoxes.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
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 ()
|
||||||
|
{
|
||||||
|
Top = new Toplevel ();
|
||||||
|
|
||||||
|
var menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_File", new MenuItem [] {
|
||||||
|
new MenuItem ("_Quit", "", () => Application.RequestStop() )
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_Simple Query...", "A simple query message box", () => MessageBox.Query (0, 6, "MessageBox.Query", "Minimum size was specified", "Ok")),
|
||||||
|
new MenuBarItem ("_Error Query...", "A error query message box", () => MessageBox.ErrorQuery (0, 6, "MessageBox.Query", "Minimum size was specified", "Ok")),
|
||||||
|
// BUGBUG: Illustrates MessageBoxes do not deal with long text gracefully. Issue #432
|
||||||
|
new MenuBarItem ("_Long Text...", "Demo long text", () => MessageBox.Query (0, 6, "About UI Catalog", "This is a very long title. It is longer than the width of the screen. Will it Wrap? I bet it will not wrap", "Ok")),
|
||||||
|
});
|
||||||
|
Top.Add (menu);
|
||||||
|
|
||||||
|
Win = new Window ($"Scenario: {GetName ()}") {
|
||||||
|
X = 0,
|
||||||
|
Y = 1,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
Top.Add (Win);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Run ()
|
||||||
|
{
|
||||||
|
Application.Run (Top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
UICatalog/Scenarios/Mouse.cs
Normal file
34
UICatalog/Scenarios/Mouse.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Mouse", Description: "Demonstrates how to capture mouse events")]
|
||||||
|
[ScenarioCategory ("Input")]
|
||||||
|
class Mouse : Scenario {
|
||||||
|
public override void Setup () {
|
||||||
|
Label ml;
|
||||||
|
int count = 0;
|
||||||
|
ml = new Label (new Rect (1, 1, 50, 1), "Mouse: ");
|
||||||
|
Application.RootMouseEvent += delegate (MouseEvent me) {
|
||||||
|
ml.TextColor = Colors.TopLevel.Normal;
|
||||||
|
ml.Text = $"Mouse: ({me.X},{me.Y}) - {me.Flags} {count++}";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var test = new Label (1, 2, "Se iniciará el análisis");
|
||||||
|
Win.Add (test);
|
||||||
|
Win.Add (ml);
|
||||||
|
|
||||||
|
// I have no idea what this was intended to show off in demo.c
|
||||||
|
var drag = new Label ("Drag: ") { X = 1, Y = 4 };
|
||||||
|
var dragText = new TextField ("") {
|
||||||
|
X = Pos.Right (drag),
|
||||||
|
Y = Pos.Top (drag),
|
||||||
|
Width = 40
|
||||||
|
};
|
||||||
|
Win.Add (drag, dragText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
UICatalog/Scenarios/TextAlignment.cs
Normal file
26
UICatalog/Scenarios/TextAlignment.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Text Alignment", Description: "Demonstrates text alignment")]
|
||||||
|
[ScenarioCategory ("Text")]
|
||||||
|
class TextAlignment : Scenario {
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
string txt = "Hello world, how are you doing today";
|
||||||
|
var labelList = new List<Label> ();
|
||||||
|
labelList.Add (new Label ($"Label:"));
|
||||||
|
labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Left, Width = Dim.Fill (1), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()) + 1 });
|
||||||
|
labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Right, Width = Dim.Fill (1), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()) + 1 });
|
||||||
|
labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Centered, Width = Dim.Fill (1), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()) + 1 });
|
||||||
|
labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Justified, Width = Dim.Fill (1), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()) + 1 });
|
||||||
|
txt += "\nSecond line";
|
||||||
|
labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Left, Width = Dim.Fill (1), Height = 4, X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()) + 1 });
|
||||||
|
|
||||||
|
Win.Add (labelList.ToArray ());
|
||||||
|
Win.LayoutSubviews ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
UICatalog/Scenarios/TopLevelNoWindowBug.cs
Normal file
40
UICatalog/Scenarios/TopLevelNoWindowBug.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "TopLevelNoWindowBug", Description: "Illustrates that not having a Window causes MenuBar to misbehave. #437")]
|
||||||
|
[ScenarioCategory ("Bug Repro")]
|
||||||
|
|
||||||
|
class TopLevelNoWindowBug : Scenario {
|
||||||
|
|
||||||
|
public override void Run ()
|
||||||
|
{
|
||||||
|
var ntop = new Toplevel (new Rect (0, 0, Application.Driver.Cols, Application.Driver.Rows));
|
||||||
|
|
||||||
|
var menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_Файл", new MenuItem [] {
|
||||||
|
new MenuItem ("_Создать", "Creates new file", null),
|
||||||
|
new MenuItem ("_Открыть", "", null),
|
||||||
|
new MenuItem ("Со_хранить", "", null),
|
||||||
|
new MenuItem ("_Выход", "", () => ntop.Running = false )
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_Edit", new MenuItem [] {
|
||||||
|
new MenuItem ("_Copy", "", null),
|
||||||
|
new MenuItem ("C_ut", "", null),
|
||||||
|
new MenuItem ("_Paste", "", null)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
ntop.Add (menu);
|
||||||
|
|
||||||
|
// BUGBUG: #437 This being commmented out causes menu to mis-behave
|
||||||
|
var win = new Window ($"Scenario: {GetName ()}") {
|
||||||
|
X = 0,
|
||||||
|
Y = 1,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
ntop.Add (win);
|
||||||
|
|
||||||
|
Application.Run (ntop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
UICatalog/Scenarios/UnicodeInMenu.cs
Normal file
35
UICatalog/Scenarios/UnicodeInMenu.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using Terminal.Gui;
|
||||||
|
|
||||||
|
namespace UICatalog {
|
||||||
|
[ScenarioMetadata (Name: "Unicode In Menu", Description: "Unicode menus per PR #204")]
|
||||||
|
[ScenarioCategory ("Text")]
|
||||||
|
[ScenarioCategory ("Controls")]
|
||||||
|
class UnicodeInMenu : Scenario {
|
||||||
|
public override void Setup ()
|
||||||
|
{
|
||||||
|
Top = new Toplevel (new Rect (0, 0, Application.Driver.Cols, Application.Driver.Rows));
|
||||||
|
var menu = new MenuBar (new MenuBarItem [] {
|
||||||
|
new MenuBarItem ("_Файл", new MenuItem [] {
|
||||||
|
new MenuItem ("_Создать", "Creates new file", null),
|
||||||
|
new MenuItem ("_Открыть", "", null),
|
||||||
|
new MenuItem ("Со_хранить", "", null),
|
||||||
|
new MenuItem ("_Выход", "", () => Application.RequestStop() )
|
||||||
|
}),
|
||||||
|
new MenuBarItem ("_Edit", new MenuItem [] {
|
||||||
|
new MenuItem ("_Copy", "", null),
|
||||||
|
new MenuItem ("C_ut", "", null),
|
||||||
|
new MenuItem ("_Paste", "", null)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
Top.Add (menu);
|
||||||
|
|
||||||
|
Win = new Window ($"Scenario: {GetName ()}") {
|
||||||
|
X = 0,
|
||||||
|
Y = 1,
|
||||||
|
Width = Dim.Fill (),
|
||||||
|
Height = Dim.Fill ()
|
||||||
|
};
|
||||||
|
Top.Add (Win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
UICatalog/UICatalog.csproj
Normal file
13
UICatalog/UICatalog.csproj
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<StartupObject>UICatalog.Program</StartupObject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Terminal.Gui\Terminal.Gui.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
BIN
UICatalog/generic_screenshot.png
Normal file
BIN
UICatalog/generic_screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
UICatalog/screenshot.png
Normal file
BIN
UICatalog/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Reference in New Issue
Block a user