Browse Source

Messagebox

Miguel de Icaza 7 years ago
parent
commit
fb70b45e58
6 changed files with 103 additions and 16 deletions
  1. 2 2
      Core.cs
  2. 1 0
      Terminal.csproj
  3. 22 1
      Views/Dialog.cs
  4. 30 12
      Views/Label.cs
  5. 41 0
      Views/MessageBox.cs
  6. 7 1
      demo.cs

+ 2 - 2
Core.cs

@@ -800,8 +800,8 @@ namespace Terminal {
 		public Window (Rect frame, string title = null) : base (frame)
 		{
 			this.Title = title;
-			frame.Inflate (-1, -1);
-			contentView = new ContentView (frame);
+			var cFrame = new Rect (1, 1, frame.Width - 2, frame.Height - 2);
+			contentView = new ContentView (cFrame);
 			base.Add (contentView);
 		}
 

+ 1 - 0
Terminal.csproj

@@ -47,6 +47,7 @@
     <Compile Include="Views\ScrollView.cs" />
     <Compile Include="Views\Dialog.cs" />
     <Compile Include="Views\RadioGroup.cs" />
+    <Compile Include="Views\MessageBox.cs" />
   </ItemGroup>
   <ItemGroup>
    <Reference Include="mono-curses.dll">

+ 22 - 1
Views/Dialog.cs

@@ -16,6 +16,13 @@ namespace Terminal {
 	public class Dialog : Window {
 		List<Button> buttons = new List<Button> ();
 
+		/// <summary>
+		/// Initializes a new instance of the <see cref="T:Terminal.Dialog"/> class with an optional set of buttons to display
+		/// </summary>
+		/// <param name="title">Title for the dialog.</param>
+		/// <param name="width">Width for the dialog.</param>
+		/// <param name="height">Height for the dialog.</param>
+		/// <param name="buttons">Optional buttons to lay out at the bottom of the dialog.</param>
 		public Dialog (string title, int width, int height, params Button [] buttons) : base (Application.MakeCenteredRect (new Size (width, height)), title)
 		{
 			foreach (var b in buttons) {
@@ -24,6 +31,20 @@ namespace Terminal {
 			}
 		}
 
+		/// <summary>
+		/// Adds a button to the dialog, its layout will be controled by the dialog
+		/// </summary>
+		/// <param name="button">Button to add.</param>
+		public void AddButton (Button button)
+		{
+			if (button == null)
+				return;
+
+			buttons.Add (button);
+			Add (button);
+		}
+
+
 		public override void LayoutSubviews ()
 		{
 			base.LayoutSubviews ();
@@ -38,7 +59,7 @@ namespace Terminal {
 			const int borderWidth = 2;
 			var start = (Frame.Width-borderWidth - buttonSpace) / 2;
 
-			var y = Frame.Height - borderWidth - 2 - maxHeight;
+			var y = Frame.Height - borderWidth  - maxHeight;
 			foreach (var b in buttons) {
 				var bf = b.Frame;
 

+ 30 - 12
Views/Label.cs

@@ -63,18 +63,18 @@ namespace Terminal {
 
 		static char [] whitespace = new char [] { ' ', '\t' };
 
-		string ClipAndJustify (string str)
+		static string ClipAndJustify (string str, int width, TextAlignment talign)
 		{
 			int slen = str.Length;
-			if (slen > Frame.Width)
-				return str.Substring (0, Frame.Width);
+			if (slen > width)
+				return str.Substring (0, width);
 			else {
-				if (textAlignment == TextAlignment.Justified) {
+				if (talign == TextAlignment.Justified) {
 					var words = str.Split (whitespace, StringSplitOptions.RemoveEmptyEntries);
 					int textCount = words.Sum ((arg) => arg.Length);
 
-					var spaces = (Frame.Width - textCount) / (words.Length - 1);
-					var extras = (Frame.Width - textCount) % words.Length;
+					var spaces = (width- textCount) / (words.Length - 1);
+					var extras = (width - textCount) % words.Length;
 					var s = new System.Text.StringBuilder ();
 					//s.Append ($"tc={textCount} sp={spaces},x={extras} - ");
 					for (int w = 0; w < words.Length; w++) {
@@ -97,18 +97,23 @@ namespace Terminal {
 		void Recalc ()
 		{
 			recalcPending = false;
-			lines.Clear ();
-			if (text.IndexOf ('\n') == -1) {
-				lines.Add (ClipAndJustify (text));
+			Recalc (text, lines, Frame.Width, textAlignment);
+		}
+
+		static void Recalc (string textStr, List<string> lineResult, int width, TextAlignment talign)
+		{
+			lineResult.Clear ();
+			if (textStr.IndexOf ('\n') == -1) {
+				lineResult.Add (ClipAndJustify (textStr, width, talign));
 				return;
 			}
-			int textLen = text.Length;
+			int textLen = textStr.Length;
 			int lp = 0;
 			for (int i = 0; i < textLen; i++) {
-				char c = text [i];
+				char c = textStr [i];
 
 				if (c == '\n') {
-					lines.Add (ClipAndJustify (text.Substring (lp, i - lp)));
+					lineResult.Add (ClipAndJustify (textStr.Substring (lp, i - lp), width, talign));
 					lp = i + 1;
 				}
 			}
@@ -150,6 +155,19 @@ namespace Terminal {
 			}
 		}
 
+		/// <summary>
+		/// Computes the number of lines needed to render the specified text by the Label control
+		/// </summary>
+		/// <returns>Number of lines.</returns>
+		/// <param name="text">Text, may contain newlines.</param>
+		/// <param name="width">The width for the text.</param>
+		public static int MeasureLines (string text, int width)
+		{
+			var result = new List<string> ();
+			Recalc (text, result, width, TextAlignment.Left);
+			return result.Count ();
+		}
+
 		/// <summary>
 		///   The text displayed by this widget.
 		/// </summary>

+ 41 - 0
Views/MessageBox.cs

@@ -0,0 +1,41 @@
+using System;
+namespace Terminal {
+
+	/// <summary>
+	/// Message box displays a modal message to the user, with a title, a message and a series of options that the user can choose from.
+	/// </summary>
+	public class MessageBox {
+		/// <summary>
+		/// Runs the dialog bo 
+		/// </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="buttons">Array of buttons to add.</param>
+		public static int Query (int width, int height, string title, string message, params string [] buttons)
+		{
+			int lines = Label.MeasureLines (message, width);
+			int clicked = -1, count = 0;
+
+			var d = new Dialog (title, width, height);
+			foreach (var s in buttons) {
+				int n = count++;
+				var b = new Button (s);
+				b.Clicked += delegate {
+					clicked = n;
+					d.Running = false;
+				};
+				d.AddButton (b);
+			}
+			if (message != null) {
+				var l = new Label ((width - 4 - message.Length) / 2, 0, message);
+				d.Add (l);
+			}
+
+			Application.Run (d);
+			return clicked;
+		}
+	}
+}

+ 7 - 1
demo.cs

@@ -38,6 +38,12 @@ class Demo {
 		Application.Run (d);
 	}
 
+	static bool Quit ()
+	{
+		var n = MessageBox.Query (50, 5, "Quit Demo", "Are you sure you want to quit this demo?", "Yes", "No");
+		return n == 0;
+	}
+
 	public static Label ml;
 	static void Main ()
 	{
@@ -51,7 +57,7 @@ class Demo {
 				new MenuItem ("_New", "Creates new file", NewFile),
 				new MenuItem ("_Open", "", null),
 				new MenuItem ("_Close", "", null),
-				new MenuItem ("_Quit", "", () => { top.Running = false; })
+				new MenuItem ("_Quit", "", () => { if (Quit ()) top.Running = false; })
 			}),
 			new MenuBarItem ("_Edit", new MenuItem [] {
 				new MenuItem ("_Copy", "", null),