Browse Source

merge with latest master

Charlie Kindel 5 years ago
parent
commit
7c23c5ab21

+ 0 - 25
.github/workflows/dotnetcore.yml

@@ -1,25 +0,0 @@
-name: .NET Core
-
-on:
-  push:
-    branches: [ master ]
-  pull_request:
-    branches: [ master ]
-
-jobs:
-  build:
-
-    runs-on: ubuntu-latest
-
-    steps:
-    - uses: actions/checkout@v2
-    - name: Setup .NET Core
-      uses: actions/setup-dotnet@v1
-      with:
-        dotnet-version: 3.1.101
-    - name: Install dependencies
-      run: dotnet restore
-    - name: Build
-      run: dotnet build --configuration Release --no-restore
-    - name: Test
-      run: dotnet test --no-restore --verbosity normal

+ 8 - 8
Example/demo.cs

@@ -90,8 +90,8 @@ static class Demo {
 			Width = Dim.Fill (),
 			Height = Dim.Fill ()
 		};
-		container.OnKeyUp += (KeyEvent ke) => {
-			if (ke.Key == Key.Esc)
+		container.KeyUp += (sender, e) => {
+			if (e.KeyEvent.Key == Key.Esc)
 				container.Running = false;
 		};
 
@@ -413,11 +413,11 @@ static class Demo {
 	#endregion
 
 
-	#region OnKeyDown / OnKeyPress / OnKeyUp Demo
+	#region KeyDown / KeyPress / KeyUp Demo
 	private static void OnKeyDownPressUpDemo ()
 	{
 		var container = new Dialog (
-			"OnKeyDown & OnKeyPress & OnKeyUp demo", 80, 20,
+			"KeyDown & KeyPress & KeyUp demo", 80, 20,
 			new Button ("Close") { Clicked = () => { Application.RequestStop (); } }) {
 			Width = Dim.Fill (),
 			Height = Dim.Fill (),
@@ -469,9 +469,9 @@ static class Demo {
 		}
 
 
-		container.OnKeyDown += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Down");
-		container.OnKeyPress += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Press");
-		container.OnKeyUp += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Up");
+		container.KeyDown += (o, e) => KeyDownPressUp (e.KeyEvent, "Down");
+		container.KeyPress += (o, e) => KeyDownPressUp (e.KeyEvent, "Press");
+		container.KeyUp += (o, e) => KeyDownPressUp (e.KeyEvent, "Up");
 		Application.Run (container);
 	}
 	#endregion
@@ -604,7 +604,7 @@ static class Demo {
 		var bottom2 = new Label ("This should go on the bottom of another top-level!");
 		top.Add (bottom2);
 
-		Application.OnLoad = () => {
+		Application.Loaded += (sender, e) => {
 			bottom.X = win.X;
 			bottom.Y = Pos.Bottom (win) - Pos.Top (win) - margin;
 			bottom2.X = Pos.Left (win);

+ 0 - 611
Example/demo.cs.orig

@@ -1,611 +0,0 @@
-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 ();
-	}
-}

+ 82 - 52
Terminal.Gui/Core.cs

@@ -126,7 +126,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
 		/// <returns>true if the event was handled</returns>
-		public virtual bool KeyDown (KeyEvent keyEvent)
+		public virtual bool OnKeyDown (KeyEvent keyEvent)
 		{
 			return false;
 		}
@@ -136,7 +136,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
 		/// <returns>true if the event was handled</returns>
-		public virtual bool KeyUp (KeyEvent keyEvent)
+		public virtual bool OnKeyUp (KeyEvent keyEvent)
 		{
 			return false;
 		}
@@ -607,7 +607,7 @@ namespace Terminal.Gui {
 				return;
 
 			while (subviews.Count > 0) {
-				Remove (subviews[0]);
+				Remove (subviews [0]);
 			}
 		}
 
@@ -705,9 +705,9 @@ namespace Terminal.Gui {
 		{
 			PerformActionForSubview (subview, x => {
 				var idx = subviews.IndexOf (x);
-				if (idx+1 < subviews.Count) {
+				if (idx + 1 < subviews.Count) {
 					subviews.Remove (x);
-					subviews.Insert (idx+1, x);
+					subviews.Insert (idx + 1, x);
 				}
 			});
 		}
@@ -910,7 +910,7 @@ namespace Terminal.Gui {
 						OnEnter ();
 					else
 						OnLeave ();
-					SetNeedsDisplay ();
+				SetNeedsDisplay ();
 				base.HasFocus = value;
 
 				// Remove focus down the chain of subviews if focus is removed
@@ -1062,18 +1062,23 @@ namespace Terminal.Gui {
 			focused.EnsureFocus ();
 
 			// Send focus upwards
-			SuperView?.SetFocus(this);
+			SuperView?.SetFocus (this);
+		}
+
+		public class KeyEventEventArgs : EventArgs {
+			public KeyEventEventArgs(KeyEvent ke) => KeyEvent = ke;
+			public KeyEvent KeyEvent { get; set; }
 		}
 
 		/// <summary>
 		/// Invoked when a character key is pressed and occurs after the key up event.
 		/// </summary>
-		public Action<KeyEvent> OnKeyPress;
+		public event EventHandler<KeyEventEventArgs> KeyPress;
 
 		/// <inheritdoc cref="ProcessKey"/>
 		public override bool ProcessKey (KeyEvent keyEvent)
 		{
-			OnKeyPress?.Invoke (keyEvent);
+			KeyPress?.Invoke (this, new KeyEventEventArgs(keyEvent));
 			if (Focused?.ProcessKey (keyEvent) == true)
 				return true;
 
@@ -1083,6 +1088,7 @@ namespace Terminal.Gui {
 		/// <inheritdoc cref="ProcessHotKey"/>
 		public override bool ProcessHotKey (KeyEvent keyEvent)
 		{
+			KeyPress?.Invoke (this, new KeyEventEventArgs (keyEvent));
 			if (subviews == null || subviews.Count == 0)
 				return false;
 			foreach (var view in subviews)
@@ -1094,6 +1100,7 @@ namespace Terminal.Gui {
 		/// <inheritdoc cref="ProcessColdKey"/>
 		public override bool ProcessColdKey (KeyEvent keyEvent)
 		{
+			KeyPress?.Invoke (this, new KeyEventEventArgs(keyEvent));
 			if (subviews == null || subviews.Count == 0)
 				return false;
 			foreach (var view in subviews)
@@ -1105,16 +1112,16 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Invoked when a key is pressed
 		/// </summary>
-		public Action<KeyEvent> OnKeyDown;
+		public event EventHandler<KeyEventEventArgs> KeyDown;
 
-		/// <inheritdoc cref="KeyDown"/>
-		public override bool KeyDown (KeyEvent keyEvent)
+		/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
+		public override bool OnKeyDown (KeyEvent keyEvent)
 		{
-			OnKeyDown?.Invoke (keyEvent);
+			KeyDown?.Invoke (this, new KeyEventEventArgs (keyEvent));
 			if (subviews == null || subviews.Count == 0)
 				return false;
 			foreach (var view in subviews)
-				if (view.KeyDown (keyEvent))
+				if (view.OnKeyDown (keyEvent))
 					return true;
 
 			return false;
@@ -1123,16 +1130,16 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Invoked when a key is released
 		/// </summary>
-		public Action<KeyEvent> OnKeyUp;
+		public event EventHandler<KeyEventEventArgs> KeyUp;
 
-		/// <inheritdoc cref="KeyUp"/>
-		public override bool KeyUp (KeyEvent keyEvent)
+		/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
+		public override bool OnKeyUp (KeyEvent keyEvent)
 		{
-			OnKeyUp?.Invoke (keyEvent);
+			KeyUp?.Invoke (this, new KeyEventEventArgs (keyEvent));
 			if (subviews == null || subviews.Count == 0)
 				return false;
 			foreach (var view in subviews)
-				if (view.KeyUp (keyEvent))
+				if (view.OnKeyUp (keyEvent))
 					return true;
 
 			return false;
@@ -1174,7 +1181,7 @@ namespace Terminal.Gui {
 		public void FocusLast ()
 		{
 			if (subviews == null) {
-				SuperView?.SetFocus(this);
+				SuperView?.SetFocus (this);
 				return;
 			}
 
@@ -1221,7 +1228,7 @@ namespace Terminal.Gui {
 						w.FocusLast ();
 
 					SetFocus (w);
-				return true;
+					return true;
 				}
 			}
 			if (focused != null) {
@@ -1634,9 +1641,9 @@ namespace Terminal.Gui {
 		internal void EnsureVisibleBounds (Toplevel top, int x, int y, out int nx, out int ny)
 		{
 			nx = Math.Max (x, 0);
-			nx = nx + top.Frame.Width > Driver.Cols ? Math.Max(Driver.Cols - top.Frame.Width, 0) : nx;
+			nx = nx + top.Frame.Width > Driver.Cols ? Math.Max (Driver.Cols - top.Frame.Width, 0) : nx;
 			bool m, s;
-			if (SuperView == null)
+			if (SuperView == null || SuperView.GetType() != typeof(Toplevel))
 				m = Application.Top.HasMenuBar;
 			else
 				m = ((Toplevel)SuperView).HasMenuBar;
@@ -1648,7 +1655,7 @@ namespace Terminal.Gui {
 				s = ((Toplevel)SuperView).HasStatusBar;
 			l = s ? Driver.Rows - 1 : Driver.Rows;
 			ny = Math.Min (ny, l);
-			ny = ny + top.Frame.Height > l ? Math.Max(l - top.Frame.Height, m ? 1 : 0) : ny;
+			ny = ny + top.Frame.Height > l ? Math.Max (l - top.Frame.Height, m ? 1 : 0) : ny;
 		}
 
 		internal void PositionToplevels ()
@@ -1796,7 +1803,7 @@ namespace Terminal.Gui {
 			this.Title = title;
 			int wb = 1 + padding;
 			this.padding = padding;
- 			contentView = new ContentView () {
+			contentView = new ContentView () {
 				X = wb,
 				Y = wb,
 				Width = Dim.Fill (wb),
@@ -2008,7 +2015,7 @@ namespace Terminal.Gui {
 		/// <remarks>
 		///   See also <see cref="Timeout"/>
 		/// </remarks>
-		static public event EventHandler Iteration;
+		public static event EventHandler Iteration;
 
 		/// <summary>
 		/// Returns a rectangle that is centered in the screen for the provided size.
@@ -2079,7 +2086,7 @@ namespace Terminal.Gui {
 			if (UseSystemConsole) {
 				mainLoopDriver = new Mono.Terminal.NetMainLoop ();
 				Driver = new NetDriver ();
-			} else if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows){
+			} else if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows) {
 				var windowsDriver = new WindowsDriver ();
 				mainLoopDriver = windowsDriver;
 				Driver = windowsDriver;
@@ -2137,7 +2144,7 @@ namespace Terminal.Gui {
 		static void ProcessKeyEvent (KeyEvent ke)
 		{
 
-			var chain = toplevels.ToList();
+			var chain = toplevels.ToList ();
 			foreach (var topLevel in chain) {
 				if (topLevel.ProcessHotKey (ke))
 					return;
@@ -2165,7 +2172,7 @@ namespace Terminal.Gui {
 		{
 			var chain = toplevels.ToList ();
 			foreach (var topLevel in chain) {
-				if (topLevel.KeyDown (ke))
+				if (topLevel.OnKeyDown (ke))
 					return;
 				if (topLevel.Modal)
 					break;
@@ -2177,7 +2184,7 @@ namespace Terminal.Gui {
 		{
 			var chain = toplevels.ToList ();
 			foreach (var topLevel in chain) {
-				if (topLevel.KeyUp (ke))
+				if (topLevel.OnKeyUp (ke))
 					return;
 				if (topLevel.Modal)
 					break;
@@ -2194,7 +2201,7 @@ namespace Terminal.Gui {
 				return null;
 			}
 
-			if (start.InternalSubviews != null){
+			if (start.InternalSubviews != null) {
 				int count = start.InternalSubviews.Count;
 				if (count > 0) {
 					var rx = x - startFrame.X;
@@ -2210,8 +2217,8 @@ namespace Terminal.Gui {
 					}
 				}
 			}
-			resx = x-startFrame.X;
-			resy = y-startFrame.Y;
+			resx = x - startFrame.X;
+			resy = y - startFrame.Y;
 			return start;
 		}
 
@@ -2242,7 +2249,7 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Merely a debugging aid to see the raw mouse events
 		/// </summary>
-		static public Action<MouseEvent> RootMouseEvent;
+		public static Action<MouseEvent> RootMouseEvent;
 
 		internal static View wantContinuousButtonPressedView;
 		static View lastMouseOwnerView;
@@ -2267,8 +2274,12 @@ namespace Terminal.Gui {
 					OfY = me.Y - newxy.Y,
 					View = view
 				};
-				mouseGrabView.MouseEvent (nme);
-				return;
+				if (OutsideFrame (new Point (nme.X, nme.Y), mouseGrabView.Frame))
+					lastMouseOwnerView.OnMouseLeave (me);
+				if (mouseGrabView != null) {
+					mouseGrabView.MouseEvent (nme);
+					return;
+				}
 			}
 
 			if (view != null) {
@@ -2303,10 +2314,16 @@ namespace Terminal.Gui {
 			}
 		}
 
+		static bool OutsideFrame (Point p, Rect r)
+		{
+			return p.X < 0 || p.X > r.Width - 1 || p.Y < 0 || p.Y > r.Height - 1;
+		}
+
 		/// <summary>
-		/// Action that is invoked once at beginning.
+		/// This event is fired once when the application is first loaded. The dimensions of the
+		/// terminal are provided.
 		/// </summary>
-		static public Action OnLoad;
+		public static event EventHandler<ResizedEventArgs> Loaded;
 
 		/// <summary>
 		/// Building block API: Prepares the provided toplevel for execution.
@@ -2321,7 +2338,7 @@ namespace Terminal.Gui {
 		///  the <see cref="RunLoop"/> method, and then the <see cref="End(RunState)"/> method upon termination which will
 		///   undo these changes.
 		/// </remarks>
-		static public RunState Begin (Toplevel toplevel)
+		public static RunState Begin (Toplevel toplevel)
 		{
 			if (toplevel == null)
 				throw new ArgumentNullException (nameof (toplevel));
@@ -2330,11 +2347,11 @@ namespace Terminal.Gui {
 			Init ();
 			if (toplevel is ISupportInitializeNotification initializableNotification &&
 			    !initializableNotification.IsInitialized) {
-				initializableNotification.BeginInit();
-				initializableNotification.EndInit();
+				initializableNotification.BeginInit ();
+				initializableNotification.EndInit ();
 			} else if (toplevel is ISupportInitialize initializable) {
-				initializable.BeginInit();
-				initializable.EndInit();
+				initializable.BeginInit ();
+				initializable.EndInit ();
 			}
 			toplevels.Push (toplevel);
 			Current = toplevel;
@@ -2342,7 +2359,7 @@ namespace Terminal.Gui {
 			if (toplevel.LayoutStyle == LayoutStyle.Computed)
 				toplevel.RelativeLayout (new Rect (0, 0, Driver.Cols, Driver.Rows));
 			toplevel.LayoutSubviews ();
-			OnLoad?.Invoke ();
+			Loaded?.Invoke (null, new ResizedEventArgs () { Rows = Driver.Rows, Cols = Driver.Cols } );
 			toplevel.WillPresent ();
 			Redraw (toplevel);
 			toplevel.PositionCursor ();
@@ -2355,7 +2372,7 @@ namespace Terminal.Gui {
 		/// Building block API: completes the execution of a Toplevel that was started with Begin.
 		/// </summary>
 		/// <param name="runState">The runstate returned by the <see cref="Begin(Toplevel)"/> method.</param>
-		static public void End (RunState runState)
+		public static void End (RunState runState)
 		{
 			if (runState == null)
 				throw new ArgumentNullException (nameof (runState));
@@ -2409,9 +2426,8 @@ namespace Terminal.Gui {
 			toplevels.Pop ();
 			if (toplevels.Count == 0)
 				Shutdown ();
-			else
-			{
-				Current = toplevels.Peek();
+			else {
+				Current = toplevels.Peek ();
 				Refresh ();
 			}
 		}
@@ -2480,7 +2496,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		public static void Run<T> () where T : Toplevel, new()
 		{
-			Init (() => new T());
+			Init (() => new T ());
 			Run (Top);
 		}
 
@@ -2525,14 +2541,28 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// Invoked when the terminal was resized.
+		/// Event arguments for the <see cref="T:Terminal.Gui.Application.Resized"/> event.
+		/// </summary>
+		public class ResizedEventArgs : EventArgs {
+			/// <summary>
+			/// The number of rows in the resized terminal.
+			/// </summary>
+			public int Rows { get; set; }
+			/// <summary>
+			/// The number of columns in the resized terminal.
+			/// </summary>
+			public int Cols { get; set; }
+		}
+
+		/// <summary>
+		/// Invoked when the terminal was resized. The new size of the terminal is provided.
 		/// </summary>
-		static public Action OnResized;
+		public static event EventHandler<ResizedEventArgs> Resized;
 
 		static void TerminalResized ()
 		{
-			OnResized?.Invoke ();
 			var full = new Rect (0, 0, Driver.Cols, Driver.Rows);
+			Resized?.Invoke (null, new ResizedEventArgs () { Cols = full.Width, Rows = full.Height });
 			Driver.Clip = full;
 			foreach (var t in toplevels) {
 				t.PositionToplevels ();

+ 2 - 2
Terminal.Gui/Drivers/WindowsDriver.cs

@@ -673,10 +673,10 @@ namespace Terminal.Gui {
 						keyUpHandler (key);
 				} else {
 					if (inputEvent.KeyEvent.bKeyDown) {
+						// Key Down - Fire KeyDown Event and KeyStroke (ProcessKey) Event
+						keyHandler (new KeyEvent (map));
 						keyDownHandler (new KeyEvent (map));
 					} else {
-						// Key Up - Fire KeyDown Event and KeyStroke (ProcessKey) Event
-						keyHandler (new KeyEvent (map));
 						keyUpHandler (new KeyEvent (map));
 					}
 				}

+ 10 - 16
Terminal.Gui/Views/Menu.cs

@@ -347,7 +347,7 @@ namespace Terminal.Gui {
 			});
 		}
 
-		public override bool KeyDown (KeyEvent keyEvent)
+		public override bool OnKeyDown (KeyEvent keyEvent)
 		{
 			if (keyEvent.IsAlt) {
 				host.CloseAllMenus ();
@@ -360,9 +360,9 @@ namespace Terminal.Gui {
 		public override bool ProcessHotKey (KeyEvent keyEvent)
 		{
 			// To ncurses simulate a AltMask key pressing Alt+Space because
-			// it can´t detect an alone special key down was pressed.
+			// it can�t detect an alone special key down was pressed.
 			if (keyEvent.IsAlt && keyEvent.Key == Key.AltMask) {
-				KeyDown (keyEvent);
+				OnKeyDown (keyEvent);
 				return true;
 			}
 
@@ -562,9 +562,8 @@ namespace Terminal.Gui {
 		}
 
 		bool openedByAltKey;
-
-		///<inheritdoc cref="KeyDown"/>
-		public override bool KeyDown (KeyEvent keyEvent)
+		///<inheritdoc cref="OnKeyDown"/>
+		public override bool OnKeyDown (KeyEvent keyEvent)
 		{
 			if (keyEvent.IsAlt) {
 				openedByAltKey = true;
@@ -574,13 +573,8 @@ namespace Terminal.Gui {
 			return false;
 		}
 
-		/// <summary>
-		/// Track Alt key-up events. On Windows, when a user releases Alt (without another key), the menu gets focus but doesn't open.
-		/// We mimic that behavior here.
-		/// </summary>
-		/// <param name="keyEvent"></param>
-		/// <returns></returns>
-		public override bool KeyUp (KeyEvent keyEvent)
+		///<inheritdoc cref="OnKeyUp"/>
+		public override bool OnKeyUp (KeyEvent keyEvent)
 		{
 			if (keyEvent.IsAlt) {
 				// User pressed Alt - this may be a precursor to a menu accelerator (e.g. Alt-F)
@@ -1001,10 +995,10 @@ namespace Terminal.Gui {
 			}
 
 			// To ncurses simulate a AltMask key pressing Alt+Space because
-			// it can´t detect an alone special key down was pressed.
+			// it can�t detect an alone special key down was pressed.
 			if (kb.IsAlt && kb.Key == Key.AltMask && openMenu == null) {
-				KeyDown (kb);
-				KeyUp (kb);
+				OnKeyDown (kb);
+				OnKeyUp (kb);
 				return true;
 			} else if (kb.IsAlt) {
 				if (FindAndOpenMenuByHotkey (kb)) return true;

+ 43 - 2
Terminal.Gui/Views/ScrollView.cs

@@ -14,6 +14,8 @@
 // - Perhaps allow an option to not display the scrollbar arrow indicators?
 
 using System;
+using System.Reflection;
+
 namespace Terminal.Gui {
 	/// <summary>
 	/// ScrollBarViews are views that display a 1-character scrollbar, either horizontal or vertical
@@ -73,7 +75,7 @@ namespace Terminal.Gui {
 		/// <param name="rect">Frame for the scrollbar.</param>
 		/// <param name="size">The size that this scrollbar represents.</param>
 		/// <param name="position">The position within this scrollbar.</param>
-		/// <param name="isVertical">If set to <c>true</c> this is a vertical scrollbar, otherwize, the scrollbar is horizontal.</param>
+		/// <param name="isVertical">If set to <c>true</c> this is a vertical scrollbar, otherwise, the scrollbar is horizontal.</param>
 		public ScrollBarView (Rect rect, int size, int position, bool isVertical) : base (rect)
 		{
 			vertical = isVertical;
@@ -314,9 +316,35 @@ namespace Terminal.Gui {
 		/// <param name="view">The view to add to the scrollview.</param>
 		public override void Add (View view)
 		{
+			if (!IsOverridden (view)) {
+				view.MouseEnter += View_MouseEnter;
+				view.MouseLeave += View_MouseLeave;
+				vertical.MouseEnter += View_MouseEnter;
+				vertical.MouseLeave += View_MouseLeave;
+				horizontal.MouseEnter += View_MouseEnter;
+				horizontal.MouseLeave += View_MouseLeave;
+			}
 			contentView.Add (view);
 		}
 
+		void View_MouseLeave (object sender, MouseEvent e)
+		{
+			Application.UngrabMouse ();
+		}
+
+		void View_MouseEnter (object sender, MouseEvent e)
+		{
+			Application.GrabMouse (this);
+		}
+
+		bool IsOverridden (View view)
+		{
+			Type t = view.GetType ();
+			MethodInfo m = t.GetMethod ("MouseEvent");
+
+			return m.DeclaringType == t && m.GetBaseDefinition ().DeclaringType == typeof (Responder);
+		}
+
 		/// <summary>
 		/// Gets or sets the visibility for the horizontal scroll indicator.
 		/// </summary>
@@ -463,7 +491,7 @@ namespace Terminal.Gui {
 			switch (kb.Key) {
 			case Key.CursorUp:
 				return ScrollUp (1);
-			case (Key) 'v' | Key.AltMask:
+			case (Key)'v' | Key.AltMask:
 			case Key.PageUp:
 				return ScrollUp (Bounds.Height);
 
@@ -489,5 +517,18 @@ namespace Terminal.Gui {
 			}
 			return false;
 		}
+
+		public override bool MouseEvent (MouseEvent me)
+		{
+			if (me.Flags != MouseFlags.WheeledDown && me.Flags != MouseFlags.WheeledUp)
+				return false;
+
+			if (me.Flags == MouseFlags.WheeledDown)
+				ScrollDown (1);
+			else if (me.Flags == MouseFlags.WheeledUp)
+				ScrollUp (1);
+
+			return true;
+		}
 	}
 }

+ 2 - 2
Terminal.Gui/Views/StatusBar.cs

@@ -108,7 +108,7 @@ namespace Terminal.Gui {
 			CanFocus = false;
 			ColorScheme = Colors.Menu;
 
-			Application.OnLoad += () => {
+			Application.Loaded += (sender, e) => {
 				X = 0;
 				Height = 1;
 #if SNAP_TO_TOP
@@ -120,7 +120,7 @@ namespace Terminal.Gui {
 				case StatusBarStyle.SnapToBottom:
 #endif
 					if (Parent == null) {
-						Y = Application.Driver.Rows - 1; // TODO: using internals of Application
+						Y = e.Rows - 1; 
 					} else {
 						Y = Pos.Bottom (Parent);
 					}

+ 11 - 8
Terminal.sln

@@ -1,13 +1,14 @@
-
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.128
+MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{B0A602CD-E176-449D-8663-64238D54F857}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Terminal.Gui", "Terminal.Gui\Terminal.Gui.csproj", "{00F366F8-DEE4-482C-B9FD-6DB0200B79E5}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Terminal.Gui", "Terminal.Gui\Terminal.Gui.csproj", "{00F366F8-DEE4-482C-B9FD-6DB0200B79E5}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Designer", "Designer\Designer.csproj", "{1228D992-C801-49BB-839A-7BD28A3FFF0A}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UICatalog", "UICatalog\UICatalog.csproj", "{88979F89-9A42-448F-AE3E-3060145F6375}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UICatalog", "UICatalog\UICatalog.csproj", "{88979F89-9A42-448F-AE3E-3060145F6375}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -27,15 +28,17 @@ Global
 		{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.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
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {9F8F8A4D-7B8D-4C2A-AC5E-CD7117F74C03}
+	EndGlobalSection
 	GlobalSection(MonoDevelopProperties) = preSolution
 		Policies = $0
 		$0.TextStylePolicy = $1

+ 3 - 3
UICatalog/Program.cs

@@ -148,7 +148,7 @@ namespace UICatalog {
 			}
 
 			_top = Application.Top;
-			_top.OnKeyUp += KeyUpHandler;
+			_top.KeyUp += KeyUpHandler;
 			_top.Add (_menu);
 			_top.Add (_leftPane);
 			_top.Add (_rightPane);
@@ -235,7 +235,7 @@ namespace UICatalog {
 		/// to not be impacted. Same as for tabs.
 		/// </summary>
 		/// <param name="ke"></param>
-		private static void KeyUpHandler (KeyEvent ke)
+		private static void KeyUpHandler (object sender, View.KeyEventEventArgs a)
 		{
 			if (_runningScenario != null) {
 				//switch (ke.Key) {
@@ -245,7 +245,7 @@ namespace UICatalog {
 				//case Key.Enter:
 				//	break;
 				//}
-			} else if (ke.Key == Key.Tab || ke.Key == Key.BackTab) {
+			} else if (a.KeyEvent.Key == Key.Tab || a.KeyEvent.Key == Key.BackTab) {
 				// BUGBUG: Work around Issue #434 by implementing our own TAB navigation
 				if (_top.MostFocused == _categoryListView)
 					_top.SetFocus (_rightPane);

+ 0 - 1
UICatalog/Properties/launchSettings.json

@@ -2,7 +2,6 @@
   "profiles": {
     "UICatalog": {
       "commandName": "Project"
-
     }
   }
 }

+ 125 - 0
UICatalog/Scenarios/ComputedLayout.cs

@@ -0,0 +1,125 @@
+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: "Computed Layout", Description: "Demonstrates using the Computed (Dim and Pos) Layout System")]
+	[ScenarioCategory ("Layout")]
+	class ComputedLayout : Scenario {
+
+		public override void Setup ()
+		{
+			//Top.LayoutStyle = LayoutStyle.Computed;
+			// Demonstrate using Dim to create a horizontal ruler that always measures the parent window's width
+			// BUGBUG: Dim.Fill returns too big a value sometimes.
+			const string rule = "|123456789";
+			var horizontalRuler = new Label ("") {
+				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 += () => {
+				horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)];
+			};
+
+			Win.Add (horizontalRuler);
+
+			// Demonstrate using Dim to create a vertical ruler that always measures the parent window's height
+			// TODO: Either build a custom control for this or implement linewrap in Label #352
+			//var verticalRuler = new Label ("") {
+			//	X = 0,
+			//	Y = 0,
+			//	Width = 1,
+			//	Height = Dim.Fill (),
+			//	ColorScheme = Colors.Error
+			//};
+
+			//Application.OnResized += () => {
+			//	verticalRuler.Text = rule.Repeat ((int)Math.Ceiling ((double)(verticalRuler.Bounds.Height) / (double)rule.Length)) [0..(verticalRuler.Bounds.Height)];
+			//};
+
+			//Win.Add (verticalRuler);
+
+
+			// Demonstrate using Dim to create a window that fills the parent with a margin
+			int margin = 10;
+			var subWin = new Window ($"Centered Sub Window with {margin} character margin") {
+				X = Pos.Center(),
+				Y = 2,
+				Width = Dim.Fill (margin),
+				Height = 7
+			};
+			Win.Add (subWin);
+
+			int i = 1;
+			string txt = "Resize the terminal to see computed layout in action.";
+			var labelList = new List<Label> ();
+			labelList.Add (new Label ($"The lines below show different TextAlignments"));
+			labelList.Add (new Label ($"{i++}-{txt}") { TextAlignment = Terminal.Gui.TextAlignment.Left, Width = Dim.Fill (1), X = 0, Y = Pos.Bottom (labelList.LastOrDefault ()), 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 ()), 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 ()), 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 ()), ColorScheme = Colors.Dialog });
+
+			subWin.Add (labelList.ToArray ());
+
+			// Demonstrate Dim & Pos using percentages - a TextField that is 20% height and 80% wide
+			var textView= new TextView () {
+				X = Pos.Center (),
+				Y = Pos.Percent (50),
+				Width = Dim.Percent (80),
+				Height = Dim.Percent (20),
+				ColorScheme = Colors.TopLevel,
+			};
+			textView.Text = "This text view should be half-way down the terminal,\n20% of its height, and 80% of its width.";
+			Win.Add (textView);
+
+			//// Demonstrate AnchorEnd - Button anchored to bottom of textView
+			//var clearButton = new Button ("Clear") {
+			//	X = Pos.AnchorEnd (),
+			//	Y = Pos.AnchorEnd (),
+			//	Width = 15,
+			//	Height = 1
+			//};
+			//Win.Add (clearButton);
+
+			// Demonstrate At - Absolute Layout using Pos
+			var absoluteButton = new Button ("At(10,10)") {
+				X = Pos.At(10),
+				Y = Pos.At(10)
+			};
+			Win.Add (absoluteButton);
+		}
+
+		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 ();
+		}
+	}
+}

+ 0 - 82
UICatalog/Scenarios/DimAndPosLayout.cs

@@ -1,82 +0,0 @@
-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 ();
-		}
-	}
-}

+ 5 - 5
UICatalog/Scenarios/Keys.cs

@@ -43,7 +43,7 @@ namespace UICatalog {
 			public override bool ProcessColdKey (KeyEvent keyEvent)
 			{
 				_processColdKeyList.Add (keyEvent.ToString ());
-				return base.ProcessHotKey (keyEvent);
+				return base.ProcessColdKey (keyEvent);
 
 			}
 		}
@@ -92,7 +92,7 @@ namespace UICatalog {
 			};
 			Win.Add (labelKeypress);
 
-			Win.OnKeyPress += (KeyEvent keyEvent) => labelKeypress.Text = keyEvent.ToString ();
+			Win.KeyPress += (sender, a) => labelKeypress.Text = a.KeyEvent.ToString ();
 
 			// Key stroke log:
 			var keyLogLabel = new Label ("Key stroke log:") {
@@ -119,9 +119,9 @@ namespace UICatalog {
 				keyStrokeListView.MoveDown ();
 			}
 
-			Win.OnKeyDown += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Down");
-			Win.OnKeyPress += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Press");
-			Win.OnKeyUp += (KeyEvent keyEvent) => KeyDownPressUp (keyEvent, "Up");
+			Win.KeyDown += (sender, a) => KeyDownPressUp (a.KeyEvent, "Down");
+			Win.KeyPress += (sender, a) => KeyDownPressUp (a.KeyEvent, "Press");
+			Win.KeyUp += (sender, a) => KeyDownPressUp (a.KeyEvent, "Up");
 
 			// ProcessKey log:
 			// BUGBUG: Label is not positioning right with Pos, so using TextField instead

+ 75 - 0
UICatalog/Scenarios/Progress.cs

@@ -0,0 +1,75 @@
+using System;
+using Terminal.Gui;
+
+namespace UICatalog {
+	// 
+	// This would be a great scenario to show of threading (Issue #471)
+	//
+	[ScenarioMetadata (Name: "Progress", Description: "Shows off ProgressBar.")]
+	[ScenarioCategory ("Controls")]
+	class Progress : Scenario {
+
+		private ProgressBar _activityProgressBar;
+		private ProgressBar _pulseProgressBar;
+		public override void Setup ()
+		{
+			Win.Add (new Button ("Start") {
+				X = Pos.Center () - 20,
+				Y = Pos.Center () - 5,
+				Clicked = () => Start ()
+			});
+
+			Win.Add (new Button ("Pulse") {
+				X = Pos.Center () - 5,
+				Y = Pos.Center () - 5,
+				Clicked = () => Pulse ()
+			}); 
+
+
+			Win.Add (new Button ("Stop") {
+				X = Pos.Center () + 10,
+				Y = Pos.Center () - 5,
+				Clicked = () => Stop()
+			});
+
+			_activityProgressBar = new ProgressBar () {
+				X = Pos.Center (),
+				// BUGBUG: If you remove the +1 below the control is drawn at top?!?!
+				Y = Pos.Center ()+1,
+				Width = 30,
+				Fraction = 0.25F,
+			};
+			Win.Add (_activityProgressBar);
+
+			_pulseProgressBar = new ProgressBar () {
+				X = Pos.Center (),
+				// BUGBUG: If you remove the +1 below the control is drawn at top?!?!
+				Y = Pos.Center () + 3,
+				Width = 30,
+			};
+			Win.Add (_pulseProgressBar);
+		}
+
+		private void Pulse ()
+		{
+			if (_activityProgressBar.Fraction + 0.1F >= 1) {
+				_activityProgressBar.Fraction = 0F;
+			} else {
+				_activityProgressBar.Fraction += 0.1F;
+			}
+			_pulseProgressBar.Pulse ();
+		}
+
+		private void Start ()
+		{
+			_activityProgressBar.Fraction = 0F;
+			_pulseProgressBar.Fraction = 0F;
+		}
+
+		private void Stop ()
+		{
+			_activityProgressBar.Fraction = 1F;
+			_pulseProgressBar.Fraction = 1F;
+		}
+	}
+}

+ 30 - 0
UICatalog/Scenarios/TimeAndDate.cs

@@ -0,0 +1,30 @@
+using System;
+using Terminal.Gui;
+
+namespace UICatalog {
+	[ScenarioMetadata (Name: "Time And Date", Description: "Illustrates TimeField and time & date handling")]
+	[ScenarioCategory ("Controls")]
+	[ScenarioCategory ("Bug Repro")] // Issue #246
+	class TimeAndDate : Scenario {
+		public override void Setup ()
+		{
+			// NOTE: The TimeField control is not ready for prime-time.
+
+			Win.Add (new TimeField (0, 0, DateTime.Now, isShort: false) {
+				// BUGBUG: TimeField does not support Computed Layout
+				//X = Pos.Center (),
+				//Y = Pos.Center () - 1,
+				X = 10,
+				Y = 2,
+			});
+
+			Win.Add (new TimeField (0, 2, DateTime.Now, isShort: true) {
+				// BUGBUG: TimeField does not support Computed Layout
+				//X = Pos.Center (),
+				//Y = Pos.Center () + 1,
+				X = 10,
+				Y = 3,
+			});
+		}
+	}
+}