Browse Source

Merge branch 'master' of tig:migueldeicaza/gui.cs

Charlie Kindel 4 years ago
parent
commit
7ad87af5f7

+ 5 - 9
Terminal.Gui/Core/Application.cs

@@ -700,19 +700,15 @@ namespace Terminal.Gui {
 		public static void Run (Toplevel view, Func<Exception, bool> errorHandler = null)
 		public static void Run (Toplevel view, Func<Exception, bool> errorHandler = null)
 		{
 		{
 			var resume = true;
 			var resume = true;
-			while (resume)
-			{
-#if DEBUG
+			while (resume) {
+#if !DEBUG
+				try {
+#endif
 				resume = false;
 				resume = false;
 				var runToken = Begin (view);
 				var runToken = Begin (view);
 				RunLoop (runToken);
 				RunLoop (runToken);
 				End (runToken);
 				End (runToken);
-#else
-				try {
-					resume = false;
-					var runToken = Begin (view);
-					RunLoop (runToken);
-					End (runToken);
+#if !DEBUG
 				}
 				}
 				catch (Exception error)
 				catch (Exception error)
 				{
 				{

+ 3 - 3
Terminal.Gui/Windows/Dialog.cs

@@ -34,7 +34,7 @@ namespace Terminal.Gui {
 		/// <remarks>
 		/// <remarks>
 		/// if <c>width</c> and <c>height</c> are both 0, the Dialog will be vertically and horizontally centered in the
 		/// if <c>width</c> and <c>height</c> are both 0, the Dialog will be vertically and horizontally centered in the
 		/// container and the size will be 85% of the container. 
 		/// container and the size will be 85% of the container. 
-		/// After initialzation use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> to override this with a location or size.
+		/// After initialization use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> to override this with a location or size.
 		/// </remarks>
 		/// </remarks>
 		/// <remarks>
 		/// <remarks>
 		/// Use the constructor that does not take a <c>width</c> and <c>height</c> instead.
 		/// Use the constructor that does not take a <c>width</c> and <c>height</c> instead.
@@ -73,7 +73,7 @@ namespace Terminal.Gui {
 		/// <remarks>
 		/// <remarks>
 		/// <para>
 		/// <para>
 		/// Te Dialog will be vertically and horizontally centered in the container and the size will be 85% of the container. 
 		/// Te Dialog will be vertically and horizontally centered in the container and the size will be 85% of the container. 
-		/// After initialzation use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> to override this with a location or size.
+		/// After initialization use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> to override this with a location or size.
 		/// </para>
 		/// </para>
 		/// <para>
 		/// <para>
 		/// Use <see cref="AddButton(Button)"/> to add buttons to the dialog.
 		/// Use <see cref="AddButton(Button)"/> to add buttons to the dialog.
@@ -89,7 +89,7 @@ namespace Terminal.Gui {
 		/// <param name="buttons">Optional buttons to lay out at the bottom of the dialog.</param>
 		/// <param name="buttons">Optional buttons to lay out at the bottom of the dialog.</param>
 		/// <remarks>
 		/// <remarks>
 		/// Te Dialog will be vertically and horizontally centered in the container and the size will be 85% of the container. 
 		/// Te Dialog will be vertically and horizontally centered in the container and the size will be 85% of the container. 
-		/// After initialzation use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> to override this with a location or size.
+		/// After initialization use <c>X</c>, <c>Y</c>, <c>Width</c>, and <c>Height</c> to override this with a location or size.
 		/// </remarks>
 		/// </remarks>
 		public Dialog (ustring title, params Button [] buttons) : this (title: title, width: 0, height: 0, buttons: buttons) { }
 		public Dialog (ustring title, params Button [] buttons) : this (title: title, width: 0, height: 0, buttons: buttons) { }
 
 

+ 19 - 6
Terminal.Gui/Windows/FileDialog.cs

@@ -480,7 +480,7 @@ namespace Terminal.Gui {
 	/// </summary>
 	/// </summary>
 	public class FileDialog : Dialog {
 	public class FileDialog : Dialog {
 		Button prompt, cancel;
 		Button prompt, cancel;
-		Label nameFieldLabel, message, dirLabel;
+		Label nameFieldLabel, message, nameDirLabel;
 		TextField dirEntry, nameEntry;
 		TextField dirEntry, nameEntry;
 		internal DirListView dirListView;
 		internal DirListView dirListView;
 
 
@@ -525,13 +525,14 @@ namespace Terminal.Gui {
 			Add (this.message);
 			Add (this.message);
 			var msgLines = TextFormatter.MaxLines (message, Driver.Cols - 20);
 			var msgLines = TextFormatter.MaxLines (message, Driver.Cols - 20);
 
 
-			dirLabel = new Label (nameDirLabel.IsEmpty ? "Directory: " : $"{nameDirLabel}: ") {
+			this.nameDirLabel = new Label (nameDirLabel.IsEmpty ? "Directory: " : $"{nameDirLabel}: ") {
 				X = 1,
 				X = 1,
-				Y = 1 + msgLines
+				Y = 1 + msgLines,
+				AutoSize = true
 			};
 			};
 
 
 			dirEntry = new TextField ("") {
 			dirEntry = new TextField ("") {
-				X = Pos.Right (dirLabel),
+				X = Pos.Right (this.nameDirLabel),
 				Y = 1 + msgLines,
 				Y = 1 + msgLines,
 				Width = Dim.Fill () - 1,
 				Width = Dim.Fill () - 1,
 			};
 			};
@@ -539,11 +540,12 @@ namespace Terminal.Gui {
 				DirectoryPath = dirEntry.Text;
 				DirectoryPath = dirEntry.Text;
 				nameEntry.Text = ustring.Empty;
 				nameEntry.Text = ustring.Empty;
 			};
 			};
-			Add (dirLabel, dirEntry);
+			Add (this.nameDirLabel, dirEntry);
 
 
 			this.nameFieldLabel = new Label (nameFieldLabel.IsEmpty ? "File: " : $"{nameFieldLabel}: ") {
 			this.nameFieldLabel = new Label (nameFieldLabel.IsEmpty ? "File: " : $"{nameFieldLabel}: ") {
 				X = 1,
 				X = 1,
 				Y = 3 + msgLines,
 				Y = 3 + msgLines,
+				AutoSize = true
 			};
 			};
 			nameEntry = new TextField ("") {
 			nameEntry = new TextField ("") {
 				X = Pos.Left (dirEntry),
 				X = Pos.Left (dirEntry),
@@ -621,6 +623,17 @@ namespace Terminal.Gui {
 			}
 			}
 		}
 		}
 
 
+		/// <summary>
+		/// Gets or sets the name of the directory field label.
+		/// </summary>
+		/// <value>The name of the directory field label.</value>
+		public ustring NameDirLabel {
+			get => nameDirLabel.Text;
+			set {
+				nameDirLabel.Text = $"{value}: ";
+			}
+		}
+
 		/// <summary>
 		/// <summary>
 		/// Gets or sets the name field label.
 		/// Gets or sets the name field label.
 		/// </summary>
 		/// </summary>
@@ -628,7 +641,7 @@ namespace Terminal.Gui {
 		public ustring NameFieldLabel {
 		public ustring NameFieldLabel {
 			get => nameFieldLabel.Text;
 			get => nameFieldLabel.Text;
 			set {
 			set {
-				nameFieldLabel.Text = value;
+				nameFieldLabel.Text = $"{value}: ";
 			}
 			}
 		}
 		}
 
 

+ 85 - 8
Terminal.Gui/Windows/MessageBox.cs

@@ -39,7 +39,7 @@ namespace Terminal.Gui {
 		/// </remarks>
 		/// </remarks>
 		public static int Query (int width, int height, ustring title, ustring message, params ustring [] buttons)
 		public static int Query (int width, int height, ustring title, ustring message, params ustring [] buttons)
 		{
 		{
-			return QueryFull (false, width, height, title, message, buttons);
+			return QueryFull (false, width, height, title, message, 0, buttons);
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -55,7 +55,7 @@ namespace Terminal.Gui {
 		/// </remarks>
 		/// </remarks>
 		public static int Query (ustring title, ustring message, params ustring [] buttons)
 		public static int Query (ustring title, ustring message, params ustring [] buttons)
 		{
 		{
-			return QueryFull (false, 0, 0, title, message, buttons);
+			return QueryFull (false, 0, 0, title, message, 0, buttons);
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -72,7 +72,7 @@ namespace Terminal.Gui {
 		/// </remarks>
 		/// </remarks>
 		public static int ErrorQuery (int width, int height, ustring title, ustring message, params ustring [] buttons)
 		public static int ErrorQuery (int width, int height, ustring title, ustring message, params ustring [] buttons)
 		{
 		{
-			return QueryFull (true, width, height, title, message, buttons);
+			return QueryFull (true, width, height, title, message, 0, buttons);
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -88,10 +88,80 @@ namespace Terminal.Gui {
 		/// </remarks>
 		/// </remarks>
 		public static int ErrorQuery (ustring title, ustring message, params ustring [] buttons)
 		public static int ErrorQuery (ustring title, ustring message, params ustring [] buttons)
 		{
 		{
-			return QueryFull (true, 0, 0, title, message, buttons);
+			return QueryFull (true, 0, 0, title, message, 0, buttons);
 		}
 		}
 
 
-		static int QueryFull (bool useErrorColors, int width, int height, ustring title, ustring message, params ustring [] buttons)
+		/// <summary>
+		/// Presents a normal <see cref="MessageBox"/> with the specified title and message and a list of buttons to show to the user.
+		/// </summary>
+		/// <returns>The index of the selected button, or -1 if the user pressed ESC to close the dialog.</returns>
+		/// <param name="width">Width for the window.</param>
+		/// <param name="height">Height for the window.</param>
+		/// <param name="title">Title for the query.</param>
+		/// <param name="message">Message to display, might contain multiple lines.</param>
+		/// <param name="defaultButton">Index of the default button.</param>
+		/// <param name="buttons">Array of buttons to add.</param>
+		/// <remarks>
+		/// Use <see cref="Query(ustring, ustring, ustring[])"/> instead; it automatically sizes the MessageBox based on the contents.
+		/// </remarks>
+		public static int Query (int width, int height, ustring title, ustring message, int defaultButton = 0, params ustring [] buttons)
+		{
+			return QueryFull (false, width, height, title, message, defaultButton, buttons);
+		}
+
+		/// <summary>
+		/// Presents an error <see cref="MessageBox"/> with the specified title and message and a list of buttons to show to the user.
+		/// </summary>
+		/// <returns>The index of the selected button, or -1 if the user pressed ESC to close the dialog.</returns>
+		/// <param name="title">Title for the query.</param>
+		/// <param name="message">Message to display, might contain multiple lines.</param>
+		/// <param name="defaultButton">Index of the default button.</param>
+		/// <param name="buttons">Array of buttons to add.</param>
+		/// <remarks>
+		/// The message box will be vertically and horizontally centered in the container and the size will be automatically determined
+		/// from the size of the message and buttons.
+		/// </remarks>
+		public static int Query (ustring title, ustring message, int defaultButton = 0, params ustring [] buttons)
+		{
+			return QueryFull (false, 0, 0, title, message, defaultButton, buttons);
+		}
+
+		/// <summary>
+		/// Presents an error <see cref="MessageBox"/> with the specified title and message and a list of buttons to show to the user.
+		/// </summary>
+		/// <returns>The index of the selected button, or -1 if the user pressed ESC to close the dialog.</returns>
+		/// <param name="width">Width for the window.</param>
+		/// <param name="height">Height for the window.</param>
+		/// <param name="title">Title for the query.</param>
+		/// <param name="message">Message to display, might contain multiple lines.</param>
+		/// <param name="defaultButton">Index of the default button.</param>
+		/// <param name="buttons">Array of buttons to add.</param>
+		/// <remarks>
+		/// Use <see cref="ErrorQuery(ustring, ustring, ustring[])"/> instead; it automatically sizes the MessageBox based on the contents.
+		/// </remarks>
+		public static int ErrorQuery (int width, int height, ustring title, ustring message, int defaultButton = 0, params ustring [] buttons)
+		{
+			return QueryFull (true, width, height, title, message, defaultButton, buttons);
+		}
+
+		/// <summary>
+		/// Presents an error <see cref="MessageBox"/> with the specified title and message and a list of buttons to show to the user.
+		/// </summary>
+		/// <returns>The index of the selected button, or -1 if the user pressed ESC to close the dialog.</returns>
+		/// <param name="title">Title for the query.</param>
+		/// <param name="message">Message to display, might contain multiple lines.</param>
+		/// <param name="defaultButton">Index of the default button.</param>
+		/// <param name="buttons">Array of buttons to add.</param>
+		/// <remarks>
+		/// The message box will be vertically and horizontally centered in the container and the size will be automatically determined
+		/// from the size of the title, message. and buttons.
+		/// </remarks>
+		public static int ErrorQuery (ustring title, ustring message, int defaultButton = 0, params ustring [] buttons)
+		{
+			return QueryFull (true, 0, 0, title, message, defaultButton, buttons);
+		}
+
+		static int QueryFull (bool useErrorColors, int width, int height, ustring title, ustring message, int defaultButton = 0, params ustring [] buttons)
 		{
 		{
 			const int defaultWidth = 50;
 			const int defaultWidth = 50;
 			int textWidth = TextFormatter.MaxWidth (message, width == 0 ? defaultWidth : width);
 			int textWidth = TextFormatter.MaxWidth (message, width == 0 ? defaultWidth : width);
@@ -101,9 +171,12 @@ namespace Terminal.Gui {
 			// Create button array for Dialog
 			// Create button array for Dialog
 			int count = 0;
 			int count = 0;
 			List<Button> buttonList = new List<Button> ();
 			List<Button> buttonList = new List<Button> ();
+			if (buttons != null && defaultButton > buttons.Length - 1) {
+				defaultButton = buttons.Length - 1;
+			}
 			foreach (var s in buttons) {
 			foreach (var s in buttons) {
 				var b = new Button (s);
 				var b = new Button (s);
-				if (count == 0) {
+				if (count == defaultButton) {
 					b.IsDefault = true;
 					b.IsDefault = true;
 				}
 				}
 				buttonList.Add (b);
 				buttonList.Add (b);
@@ -142,13 +215,17 @@ namespace Terminal.Gui {
 			int clicked = -1;
 			int clicked = -1;
 			for (int n = 0; n < buttonList.Count; n++) {
 			for (int n = 0; n < buttonList.Count; n++) {
 				int buttonId = n;
 				int buttonId = n;
-				buttonList [n].Clicked += () => {
+				var b = buttonList [n];
+				b.Clicked += () => {
 					clicked = buttonId;
 					clicked = buttonId;
 					Application.RequestStop ();
 					Application.RequestStop ();
 				};
 				};
+				if (b.IsDefault) {
+					b.SetFocus ();
+				}
 			}
 			}
 
 
-			// Rin the modal; do not shutdown the mainloop driver when done
+			// Run the modal; do not shutdown the mainloop driver when done
 			Application.Run (d);
 			Application.Run (d);
 			return clicked;
 			return clicked;
 		}
 		}

+ 21 - 3
UICatalog/Scenarios/MessageBoxes.cs

@@ -110,6 +110,22 @@ namespace UICatalog {
 			};
 			};
 			frame.Add (numButtonsEdit);
 			frame.Add (numButtonsEdit);
 
 
+			label = new Label ("Default Button:") {
+				X = 0,
+				Y = Pos.Bottom (label),
+				Width = Dim.Width (label),
+				Height = 1,
+				TextAlignment = Terminal.Gui.TextAlignment.Right,
+			};
+			frame.Add (label);
+			var defaultButtonEdit = new TextField ("0") {
+				X = Pos.Right (label) + 1,
+				Y = Pos.Top (label),
+				Width = 5,
+				Height = 1
+			};
+			frame.Add (defaultButtonEdit);
+
 			label = new Label ("Style:") {
 			label = new Label ("Style:") {
 				X = 0,
 				X = 0,
 				Y = Pos.Bottom (label),
 				Y = Pos.Bottom (label),
@@ -127,7 +143,7 @@ namespace UICatalog {
 			void Top_Loaded ()
 			void Top_Loaded ()
 			{
 			{
 				frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + Dim.Height (messageEdit)
 				frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + Dim.Height (messageEdit)
-					+ Dim.Height (numButtonsEdit) + Dim.Height (styleRadioGroup) + 2;
+					+ Dim.Height (numButtonsEdit) + Dim.Height (defaultButtonEdit) + Dim.Height (styleRadioGroup) + 2;
 				Top.Loaded -= Top_Loaded;
 				Top.Loaded -= Top_Loaded;
 			}
 			}
 			Top.Loaded += Top_Loaded;
 			Top.Loaded += Top_Loaded;
@@ -145,6 +161,7 @@ namespace UICatalog {
 				Width = 25,
 				Width = 25,
 				Height = 1,
 				Height = 1,
 				ColorScheme = Colors.Error,
 				ColorScheme = Colors.Error,
+				TextAlignment = Terminal.Gui.TextAlignment.Centered
 			};
 			};
 
 
 			//var btnText = new [] { "_Zero", "_One", "T_wo", "_Three", "_Four", "Fi_ve", "Si_x", "_Seven", "_Eight", "_Nine" };
 			//var btnText = new [] { "_Zero", "_One", "T_wo", "_Three", "_Four", "Fi_ve", "Si_x", "_Seven", "_Eight", "_Nine" };
@@ -159,6 +176,7 @@ namespace UICatalog {
 					int width = int.Parse (widthEdit.Text.ToString ());
 					int width = int.Parse (widthEdit.Text.ToString ());
 					int height = int.Parse (heightEdit.Text.ToString ());
 					int height = int.Parse (heightEdit.Text.ToString ());
 					int numButtons = int.Parse (numButtonsEdit.Text.ToString ());
 					int numButtons = int.Parse (numButtonsEdit.Text.ToString ());
+					int defaultButton = int.Parse (defaultButtonEdit.Text.ToString ());
 
 
 					var btns = new List<ustring> ();
 					var btns = new List<ustring> ();
 					for (int i = 0; i < numButtons; i++) {
 					for (int i = 0; i < numButtons; i++) {
@@ -166,9 +184,9 @@ namespace UICatalog {
 						btns.Add (NumberToWords.Convert (i));
 						btns.Add (NumberToWords.Convert (i));
 					}
 					}
 					if (styleRadioGroup.SelectedItem == 0) {
 					if (styleRadioGroup.SelectedItem == 0) {
-						buttonPressedLabel.Text = $"{MessageBox.Query (width, height, titleEdit.Text.ToString (), messageEdit.Text.ToString (), btns.ToArray ())}";
+						buttonPressedLabel.Text = $"{MessageBox.Query (width, height, titleEdit.Text.ToString (), messageEdit.Text.ToString (), defaultButton, btns.ToArray ())}";
 					} else {
 					} else {
-						buttonPressedLabel.Text = $"{MessageBox.ErrorQuery (width, height, titleEdit.Text.ToString (), messageEdit.Text.ToString (), btns.ToArray ())}";
+						buttonPressedLabel.Text = $"{MessageBox.ErrorQuery (width, height, titleEdit.Text.ToString (), messageEdit.Text.ToString (), defaultButton, btns.ToArray ())}";
 					}
 					}
 				} catch (FormatException) {
 				} catch (FormatException) {
 					buttonPressedLabel.Text = "Invalid Options";
 					buttonPressedLabel.Text = "Invalid Options";