Browse Source

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

Charlie Kindel 5 years ago
parent
commit
6f10a051d1

+ 23 - 17
Terminal.Gui/Core.cs

@@ -1545,12 +1545,12 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// Check id current toplevel has menu bar
 		/// Check id current toplevel has menu bar
 		/// </summary>
 		/// </summary>
-		public bool HasMenuBar { get; set; }
+		public MenuBar MenuBar { get; set; }
 
 
 		/// <summary>
 		/// <summary>
 		/// Check id current toplevel has status bar
 		/// Check id current toplevel has status bar
 		/// </summary>
 		/// </summary>
-		public bool HasStatusBar { get; set; }
+		public StatusBar StatusBar { get; set; }
 
 
 		///<inheritdoc cref="ProcessKey"/>
 		///<inheritdoc cref="ProcessKey"/>
 		public override bool ProcessKey (KeyEvent keyEvent)
 		public override bool ProcessKey (KeyEvent keyEvent)
@@ -1609,9 +1609,9 @@ namespace Terminal.Gui {
 		{
 		{
 			if (this == Application.Top) {
 			if (this == Application.Top) {
 				if (view is MenuBar)
 				if (view is MenuBar)
-					HasMenuBar = true;
+					MenuBar = view as MenuBar;
 				if (view is StatusBar)
 				if (view is StatusBar)
-					HasStatusBar = true;
+					StatusBar = view as StatusBar;
 			}
 			}
 			base.Add (view);
 			base.Add (view);
 		}
 		}
@@ -1621,9 +1621,9 @@ namespace Terminal.Gui {
 		{
 		{
 			if (this == Application.Top) {
 			if (this == Application.Top) {
 				if (view is MenuBar)
 				if (view is MenuBar)
-					HasMenuBar = true;
+					MenuBar = null;
 				if (view is StatusBar)
 				if (view is StatusBar)
-					HasStatusBar = true;
+					StatusBar = null;
 			}
 			}
 			base.Remove (view);
 			base.Remove (view);
 		}
 		}
@@ -1632,8 +1632,8 @@ namespace Terminal.Gui {
 		public override void RemoveAll ()
 		public override void RemoveAll ()
 		{
 		{
 			if (this == Application.Top) {
 			if (this == Application.Top) {
-				HasMenuBar = false;
-				HasStatusBar = false;
+				MenuBar = null;
+				StatusBar = null;
 			}
 			}
 			base.RemoveAll ();
 			base.RemoveAll ();
 		}
 		}
@@ -1643,16 +1643,16 @@ namespace Terminal.Gui {
 			nx = Math.Max (x, 0);
 			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;
 			bool m, s;
-			if (SuperView == null || SuperView.GetType() != typeof(Toplevel))
-				m = Application.Top.HasMenuBar;
+			if (SuperView == null)
+				m = Application.Top.MenuBar != null;
 			else
 			else
-				m = ((Toplevel)SuperView).HasMenuBar;
+				m = ((Toplevel)SuperView).MenuBar != null;
 			int l = m ? 1 : 0;
 			int l = m ? 1 : 0;
 			ny = Math.Max (y, l);
 			ny = Math.Max (y, l);
 			if (SuperView == null)
 			if (SuperView == null)
-				s = Application.Top.HasStatusBar;
+				s = Application.Top.StatusBar != null;
 			else
 			else
-				s = ((Toplevel)SuperView).HasStatusBar;
+				s = ((Toplevel)SuperView).StatusBar != null;
 			l = s ? Driver.Rows - 1 : Driver.Rows;
 			l = s ? Driver.Rows - 1 : Driver.Rows;
 			ny = Math.Min (ny, l);
 			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;
@@ -1674,9 +1674,15 @@ namespace Terminal.Gui {
 							top.X = nx;
 							top.X = nx;
 							top.Y = ny;
 							top.Y = ny;
 						}
 						}
-						if (HasStatusBar && ny + top.Frame.Height > Driver.Rows - 1) {
-							if (top.Height is Dim.DimFill)
-								top.Height = Dim.Fill () - 1;
+						if (StatusBar != null) {
+							if (ny + top.Frame.Height > Driver.Rows - 1) {
+								if (top.Height is Dim.DimFill)
+									top.Height = Dim.Fill () - 1;
+							}
+							if (StatusBar.Frame.Y != Driver.Rows - 1) {
+								StatusBar.Y = Driver.Rows - 1;
+								SetNeedsDisplay ();
+							}
 						}
 						}
 					}
 					}
 				}
 				}
@@ -1688,7 +1694,7 @@ namespace Terminal.Gui {
 		{
 		{
 			Application.CurrentView = this;
 			Application.CurrentView = this;
 
 
-			if (this == Application.Top) {
+			if (this == Application.Top || this == Application.Current) {
 				if (!NeedDisplay.IsEmpty) {
 				if (!NeedDisplay.IsEmpty) {
 					Driver.SetAttribute (Colors.TopLevel.Normal);
 					Driver.SetAttribute (Colors.TopLevel.Normal);
 					Clear (region);
 					Clear (region);

+ 141 - 61
Terminal.Gui/Views/ListView.cs

@@ -63,6 +63,12 @@ namespace Terminal.Gui {
 		/// <param name="item">Item index.</param>
 		/// <param name="item">Item index.</param>
 		/// <param name="value">If set to <c>true</c> value.</param>
 		/// <param name="value">If set to <c>true</c> value.</param>
 		void SetMark (int item, bool value);
 		void SetMark (int item, bool value);
+
+		/// <summary>
+		/// Return the source as IList.
+		/// </summary>
+		/// <returns></returns>
+		IList ToList ();
 	}
 	}
 
 
 	/// <summary>
 	/// <summary>
@@ -257,7 +263,7 @@ namespace Terminal.Gui {
 		/// Redraws the ListView
 		/// Redraws the ListView
 		/// </summary>
 		/// </summary>
 		/// <param name="region">Region.</param>
 		/// <param name="region">Region.</param>
-		public override void Redraw(Rect region)
+		public override void Redraw (Rect region)
 		{
 		{
 			var current = ColorScheme.Focus;
 			var current = ColorScheme.Focus;
 			Driver.SetAttribute (current);
 			Driver.SetAttribute (current);
@@ -279,12 +285,12 @@ namespace Terminal.Gui {
 				Move (0, row);
 				Move (0, row);
 				if (source == null || item >= source.Count) {
 				if (source == null || item >= source.Count) {
 					for (int c = 0; c < f.Width; c++)
 					for (int c = 0; c < f.Width; c++)
-						Driver.AddRune(' ');
+						Driver.AddRune (' ');
 				} else {
 				} else {
 					if (allowsMarking) {
 					if (allowsMarking) {
 						Driver.AddStr (source.IsMarked (item) ? (AllowsMultipleSelection ? "[x] " : "(o)") : (AllowsMultipleSelection ? "[ ] " : "( )"));
 						Driver.AddStr (source.IsMarked (item) ? (AllowsMultipleSelection ? "[x] " : "(o)") : (AllowsMultipleSelection ? "[ ] " : "( )"));
 					}
 					}
-					Source.Render(this, Driver, isSelected, item, col, row, f.Width-col);
+					Source.Render (this, Driver, isSelected, item, col, row, f.Width - col);
 				}
 				}
 			}
 			}
 		}
 		}
@@ -292,12 +298,12 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// This event is raised when the cursor selection has changed.
 		/// This event is raised when the cursor selection has changed.
 		/// </summary>
 		/// </summary>
-		public event Action SelectedChanged;
+		public event EventHandler<ListViewItemEventArgs> SelectedChanged;
 
 
 		/// <summary>
 		/// <summary>
 		/// This event is raised on Enter key or Double Click to open the selected item.
 		/// This event is raised on Enter key or Double Click to open the selected item.
 		/// </summary>
 		/// </summary>
-		public event EventHandler OpenSelectedItem;
+		public event EventHandler<ListViewItemEventArgs> OpenSelectedItem;
 
 
 		/// <summary>
 		/// <summary>
 		/// Handles cursor movement for this view, passes all other events.
 		/// Handles cursor movement for this view, passes all other events.
@@ -312,27 +318,27 @@ namespace Terminal.Gui {
 			switch (kb.Key) {
 			switch (kb.Key) {
 			case Key.CursorUp:
 			case Key.CursorUp:
 			case Key.ControlP:
 			case Key.ControlP:
-				return MoveUp();
+				return MoveUp ();
 
 
 			case Key.CursorDown:
 			case Key.CursorDown:
 			case Key.ControlN:
 			case Key.ControlN:
-				return MoveDown();
+				return MoveDown ();
 
 
 			case Key.ControlV:
 			case Key.ControlV:
 			case Key.PageDown:
 			case Key.PageDown:
-				return MovePageDown();
+				return MovePageDown ();
 
 
 			case Key.PageUp:
 			case Key.PageUp:
-				return MovePageUp();
+				return MovePageUp ();
 
 
 			case Key.Space:
 			case Key.Space:
-				if (MarkUnmarkRow())
+				if (MarkUnmarkRow ())
 					return true;
 					return true;
 				else
 				else
 					break;
 					break;
 
 
 			case Key.Enter:
 			case Key.Enter:
-				OpenSelectedItem?.Invoke (this, new EventArgs ());
+				OnOpenSelectedItem ();
 				break;
 				break;
 
 
 			}
 			}
@@ -340,7 +346,7 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// 
+		/// Prevents marking if it's not allowed mark and if it's not allows multiple selection.
 		/// </summary>
 		/// </summary>
 		/// <returns></returns>
 		/// <returns></returns>
 		public virtual bool AllowsAll ()
 		public virtual bool AllowsAll ()
@@ -359,13 +365,14 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// 
+		/// Marks an unmarked row.
 		/// </summary>
 		/// </summary>
 		/// <returns></returns>
 		/// <returns></returns>
-		public virtual bool MarkUnmarkRow(){
+		public virtual bool MarkUnmarkRow ()
+		{
 			if (AllowsAll ()) {
 			if (AllowsAll ()) {
-				Source.SetMark(SelectedItem, !Source.IsMarked(SelectedItem));
-				SetNeedsDisplay();
+				Source.SetMark (SelectedItem, !Source.IsMarked (SelectedItem));
+				SetNeedsDisplay ();
 				return true;
 				return true;
 			}
 			}
 
 
@@ -373,84 +380,114 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// 
+		/// Moves to the next page.
 		/// </summary>
 		/// </summary>
 		/// <returns></returns>
 		/// <returns></returns>
-		public virtual bool MovePageUp(){
+		public virtual bool MovePageUp ()
+		{
 			int n = (selected - Frame.Height);
 			int n = (selected - Frame.Height);
 			if (n < 0)
 			if (n < 0)
 				n = 0;
 				n = 0;
-			if (n != selected){
+			if (n != selected) {
 				selected = n;
 				selected = n;
 				top = selected;
 				top = selected;
-				if (SelectedChanged != null)
-					SelectedChanged();
-				SetNeedsDisplay();
+				OnSelectedChanged ();
+				SetNeedsDisplay ();
 			}
 			}
 
 
 			return true;
 			return true;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// 
+		/// Moves to the previous page.
 		/// </summary>
 		/// </summary>
 		/// <returns></returns>
 		/// <returns></returns>
-		public virtual bool MovePageDown(){
+		public virtual bool MovePageDown ()
+		{
 			var n = (selected + Frame.Height);
 			var n = (selected + Frame.Height);
 			if (n > source.Count)
 			if (n > source.Count)
 				n = source.Count - 1;
 				n = source.Count - 1;
-			if (n != selected){
+			if (n != selected) {
 				selected = n;
 				selected = n;
 				if (source.Count >= Frame.Height)
 				if (source.Count >= Frame.Height)
 					top = selected;
 					top = selected;
 				else
 				else
 					top = 0;
 					top = 0;
-				if (SelectedChanged != null)
-					SelectedChanged();
-				SetNeedsDisplay();
+				OnSelectedChanged ();
+				SetNeedsDisplay ();
 			}
 			}
 
 
 			return true;
 			return true;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// 
+		/// Moves to the next row.
 		/// </summary>
 		/// </summary>
 		/// <returns></returns>
 		/// <returns></returns>
-		public virtual bool MoveDown(){
-			if (selected + 1 < source.Count){
+		public virtual bool MoveDown ()
+		{
+			if (selected + 1 < source.Count) {
 				selected++;
 				selected++;
 				if (selected >= top + Frame.Height)
 				if (selected >= top + Frame.Height)
 					top++;
 					top++;
-				if (SelectedChanged != null)
-					SelectedChanged();
-				SetNeedsDisplay();
+				OnSelectedChanged ();
+				SetNeedsDisplay ();
 			}
 			}
 
 
 			return true;
 			return true;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// 
+		/// Moves to the previous row.
 		/// </summary>
 		/// </summary>
 		/// <returns></returns>
 		/// <returns></returns>
-		public virtual bool MoveUp(){
-			if (selected > 0){
+		public virtual bool MoveUp ()
+		{
+			if (selected > 0) {
 				selected--;
 				selected--;
 				if (selected < top)
 				if (selected < top)
 					top = selected;
 					top = selected;
-				if (SelectedChanged != null)
-					SelectedChanged();
-				SetNeedsDisplay();
+				OnSelectedChanged ();
+				SetNeedsDisplay ();
 			}
 			}
 
 
 			return true;
 			return true;
 		}
 		}
 
 
+		int lastSelectedItem = -1;
+
+		/// <summary>
+		/// Invokes the SelectedChanged event if it is defined.
+		/// </summary>
+		/// <returns></returns>
+		public virtual bool OnSelectedChanged ()
+		{
+			if (selected != lastSelectedItem) {
+				var value = source.ToList () [selected];
+				SelectedChanged?.Invoke (this, new ListViewItemEventArgs (selected, value));
+				lastSelectedItem = selected;
+				return true;
+			}
+
+			return false;
+		}
+
+		/// <summary>
+		/// Invokes the OnOpenSelectedItem event if it is defined.
+		/// </summary>
+		/// <returns></returns>
+		public virtual bool OnOpenSelectedItem ()
+		{
+			var value = source.ToList () [selected];
+			OpenSelectedItem?.Invoke (this, new ListViewItemEventArgs (selected, value));
+
+			return true;
+		}
+
 		/// <summary>
 		/// <summary>
 		/// Positions the cursor in this view
 		/// Positions the cursor in this view
 		/// </summary>
 		/// </summary>
-		public override void PositionCursor()
+		public override void PositionCursor ()
 		{
 		{
 			if (allowsMarking)
 			if (allowsMarking)
 				Move (1, selected - top);
 				Move (1, selected - top);
@@ -461,7 +498,8 @@ 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) && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
+			if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked) &&
+				me.Flags != MouseFlags.WheeledDown && me.Flags != MouseFlags.WheeledUp)
 				return false;
 				return false;
 
 
 			if (!HasFocus)
 			if (!HasFocus)
@@ -470,6 +508,14 @@ namespace Terminal.Gui {
 			if (source == null)
 			if (source == null)
 				return false;
 				return false;
 
 
+			if (me.Flags == MouseFlags.WheeledDown) {
+				MoveDown ();
+				return true;
+			} else if (me.Flags == MouseFlags.WheeledUp) {
+				MoveUp ();
+				return true;
+			}
+
 			if (me.Y + top >= source.Count)
 			if (me.Y + top >= source.Count)
 				return true;
 				return true;
 
 
@@ -479,10 +525,10 @@ namespace Terminal.Gui {
 				SetNeedsDisplay ();
 				SetNeedsDisplay ();
 				return true;
 				return true;
 			}
 			}
-			SelectedChanged?.Invoke ();
+			OnSelectedChanged ();
 			SetNeedsDisplay ();
 			SetNeedsDisplay ();
 			if (me.Flags == MouseFlags.Button1DoubleClicked)
 			if (me.Flags == MouseFlags.Button1DoubleClicked)
-				OpenSelectedItem?.Invoke (this, new EventArgs ());
+				OnOpenSelectedItem ();
 			return true;
 			return true;
 		}
 		}
 	}
 	}
@@ -497,7 +543,7 @@ namespace Terminal.Gui {
 		int count;
 		int count;
 
 
 		/// <summary>
 		/// <summary>
-		/// constructor
+		/// Constructor based on a source.
 		/// </summary>
 		/// </summary>
 		/// <param name="source"></param>
 		/// <param name="source"></param>
 		public ListWrapper (IList source)
 		public ListWrapper (IList source)
@@ -508,7 +554,7 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// Count of items.
+		/// Returns the amount of items in the source.
 		/// </summary>
 		/// </summary>
 		public int Count => src.Count;
 		public int Count => src.Count;
 
 
@@ -519,7 +565,7 @@ namespace Terminal.Gui {
 			for (int i = 0; i < byteLen;) {
 			for (int i = 0; i < byteLen;) {
 				(var rune, var size) = Utf8.DecodeRune (ustr, i, i - byteLen);
 				(var rune, var size) = Utf8.DecodeRune (ustr, i, i - byteLen);
 				var count = Rune.ColumnWidth (rune);
 				var count = Rune.ColumnWidth (rune);
-				if (used+count >= width)
+				if (used + count >= width)
 					break;
 					break;
 				driver.AddRune (rune);
 				driver.AddRune (rune);
 				used += count;
 				used += count;
@@ -531,15 +577,15 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// Renders an item in the the list.
+		/// Method that render to the appropriate type based on the type of the item passed to it.
 		/// </summary>
 		/// </summary>
-		/// <param name="container"></param>
-		/// <param name="driver"></param>
-		/// <param name="marked"></param>
-		/// <param name="item"></param>
-		/// <param name="col"></param>
-		/// <param name="line"></param>
-		/// <param name="width"></param>
+		/// <param name="container">The ListView.</param>
+		/// <param name="driver">The driver used by the caller.</param>
+		/// <param name="marked">Informs if it's marked or not.</param>
+		/// <param name="item">The item.</param>
+		/// <param name="col">The col where to move.</param>
+		/// <param name="line">The line where to move.</param>
+		/// <param name="width">The item width.</param>
 		public void Render (ListView container, ConsoleDriver driver, bool marked, int item, int col, int line, int width)
 		public void Render (ListView container, ConsoleDriver driver, bool marked, int item, int col, int line, int width)
 		{
 		{
 			container.Move (col, line);
 			container.Move (col, line);
@@ -553,10 +599,10 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// Returns true of the item is marked. false if not.
+		/// Returns true if the item is marked, false otherwise.
 		/// </summary>
 		/// </summary>
-		/// <param name="item"></param>
-		/// <returns></returns>
+		/// <param name="item">The item.</param>
+		/// <returns><c>true</c>If is marked.<c>false</c>otherwise.</returns>
 		public bool IsMarked (int item)
 		public bool IsMarked (int item)
 		{
 		{
 			if (item >= 0 && item < count)
 			if (item >= 0 && item < count)
@@ -565,14 +611,48 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// Sets the marked state of an item.
+		/// Sets the item as marked or unmarked based on the value is true or false, respectively.
 		/// </summary>
 		/// </summary>
-		/// <param name="item"></param>
-		/// <param name="value"></param>
+		/// <param name="item">The item</param>
+		/// <param name="value"><true>Marks the item.</true><false>Unmarked the item.</false>The value.</param>
 		public void SetMark (int item, bool value)
 		public void SetMark (int item, bool value)
 		{
 		{
 			if (item >= 0 && item < count)
 			if (item >= 0 && item < count)
 				marks [item] = value;
 				marks [item] = value;
 		}
 		}
+
+		/// <summary>
+		/// Returns the source as IList.
+		/// </summary>
+		/// <returns></returns>
+		public IList ToList ()
+		{
+			return src;
+		}
+	}
+
+	/// <summary>
+	/// Gets the item and value to use in an event handler.
+	/// </summary>
+	public class ListViewItemEventArgs : EventArgs {
+		/// <summary>
+		/// The item.
+		/// </summary>
+		public int Item { get; }
+		/// <summary>
+		/// The item value.
+		/// </summary>
+		public object Value { get; }
+
+		/// <summary>
+		/// Constructor to sets the item and value passed from.
+		/// </summary>
+		/// <param name="item">The item.</param>
+		/// <param name="value">The item value</param>
+		public ListViewItemEventArgs (int item, object value)
+		{
+			Item = item;
+			Value = value;
+		}
 	}
 	}
 }
 }

+ 9 - 5
Terminal.Gui/Views/StatusBar.cs

@@ -107,6 +107,10 @@ namespace Terminal.Gui {
 			Items = items;
 			Items = items;
 			CanFocus = false;
 			CanFocus = false;
 			ColorScheme = Colors.Menu;
 			ColorScheme = Colors.Menu;
+			X = 0;
+			Y = Driver.Rows - 1;
+			Width = Dim.Fill ();
+			Height = 1;
 
 
 			Application.Loaded += (sender, e) => {
 			Application.Loaded += (sender, e) => {
 				X = 0;
 				X = 0;
@@ -141,11 +145,11 @@ namespace Terminal.Gui {
 		///<inheritdoc cref="Redraw"/>
 		///<inheritdoc cref="Redraw"/>
 		public override void Redraw (Rect region)
 		public override void Redraw (Rect region)
 		{
 		{
-			if (Frame.Y != Driver.Rows - 1) {
-				Frame = new Rect (Frame.X, Driver.Rows - 1, Frame.Width, Frame.Height);
-				Y = Driver.Rows - 1;
-				SetNeedsDisplay ();
-			}
+			//if (Frame.Y != Driver.Rows - 1) {
+			//	Frame = new Rect (Frame.X, Driver.Rows - 1, Frame.Width, Frame.Height);
+			//	Y = Driver.Rows - 1;
+			//	SetNeedsDisplay ();
+			//}
 
 
 			Move (0, 0);
 			Move (0, 0);
 			Driver.SetAttribute (ColorScheme.Normal);
 			Driver.SetAttribute (ColorScheme.Normal);

+ 44 - 6
Terminal.Gui/Views/TextField.cs

@@ -28,6 +28,11 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// </summary>
 		public bool Used { get => used; set { used = value; } }
 		public bool Used { get => used; set { used = value; } }
 
 
+		/// <summary>
+		/// If set to true its not allow any changes in the text.
+		/// </summary>
+		public bool ReadOnly { get; set; } = false;
+
 		/// <summary>
 		/// <summary>
 		///   Changed event, raised when the text has clicked.
 		///   Changed event, raised when the text has clicked.
 		/// </summary>
 		/// </summary>
@@ -95,7 +100,7 @@ namespace Terminal.Gui {
 			set {
 			set {
 				base.Frame = value;
 				base.Frame = value;
 				var w = base.Frame.Width;
 				var w = base.Frame.Width;
-				//first = point > w ? point - w : 0;
+				first = point > w ? point - w : 0;
 				Adjust ();
 				Adjust ();
 			}
 			}
 		}
 		}
@@ -115,6 +120,9 @@ namespace Terminal.Gui {
 			}
 			}
 
 
 			set {
 			set {
+				if (ReadOnly)
+					return;
+
 				var oldText = ustring.Make (text);
 				var oldText = ustring.Make (text);
 				text = TextModel.ToRunes (value);
 				text = TextModel.ToRunes (value);
 				if (!Secret && !isFromHistory) {
 				if (!Secret && !isFromHistory) {
@@ -184,13 +192,16 @@ namespace Terminal.Gui {
 			int col = 0;
 			int col = 0;
 			int width = Frame.Width;
 			int width = Frame.Width;
 			var tcount = text.Count;
 			var tcount = text.Count;
+			var roc = new Attribute (Color.DarkGray, Color.Gray);
 			for (int idx = 0; idx < tcount; idx++){
 			for (int idx = 0; idx < tcount; idx++){
 				var rune = text [idx];
 				var rune = text [idx];
 				if (idx < p)
 				if (idx < p)
 					continue;
 					continue;
 				var cols = Rune.ColumnWidth (rune);
 				var cols = Rune.ColumnWidth (rune);
-				if (col == point && HasFocus && !Used && SelectedLength == 0)
+				if (col == point && HasFocus && !Used && SelectedLength == 0 && !ReadOnly)
 					Driver.SetAttribute (Colors.Menu.HotFocus);
 					Driver.SetAttribute (Colors.Menu.HotFocus);
+				else if (ReadOnly)
+					Driver.SetAttribute (idx >= start && length > 0 && idx < start + length ? color.Focus : roc);
 				else
 				else
 					Driver.SetAttribute (idx >= start && length > 0 && idx < start + length ? color.Focus : ColorScheme.Focus);
 					Driver.SetAttribute (idx >= start && length > 0 && idx < start + length ? color.Focus : ColorScheme.Focus);
 				if (col + cols <= width)
 				if (col + cols <= width)
@@ -261,6 +272,9 @@ namespace Terminal.Gui {
 			switch (kb.Key) {
 			switch (kb.Key) {
 			case Key.DeleteChar:
 			case Key.DeleteChar:
 			case Key.ControlD:
 			case Key.ControlD:
+				if (ReadOnly)
+					return true;
+
 				if (SelectedLength == 0) {
 				if (SelectedLength == 0) {
 					if (text.Count == 0 || text.Count == point)
 					if (text.Count == 0 || text.Count == point)
 						return true;
 						return true;
@@ -275,6 +289,9 @@ namespace Terminal.Gui {
 
 
 			case Key.Delete:
 			case Key.Delete:
 			case Key.Backspace:
 			case Key.Backspace:
+				if (ReadOnly)
+					return true;
+
 				if (SelectedLength == 0) {
 				if (SelectedLength == 0) {
 					if (point == 0)
 					if (point == 0)
 						return true;
 						return true;
@@ -373,6 +390,9 @@ namespace Terminal.Gui {
 				break;
 				break;
 
 
 			case Key.ControlK: // kill-to-end
 			case Key.ControlK: // kill-to-end
+				if (ReadOnly)
+					return true;
+
 				ClearAllSelection ();
 				ClearAllSelection ();
 				if (point >= text.Count)
 				if (point >= text.Count)
 					return true;
 					return true;
@@ -383,6 +403,9 @@ namespace Terminal.Gui {
 
 
 			// Undo
 			// Undo
 			case Key.ControlZ:
 			case Key.ControlZ:
+				if (ReadOnly)
+					return true;
+
 				if (historyText != null && historyText.Count > 0) {
 				if (historyText != null && historyText.Count > 0) {
 					isFromHistory = true;
 					isFromHistory = true;
 					if (idxhistoryText > 0)
 					if (idxhistoryText > 0)
@@ -396,6 +419,9 @@ namespace Terminal.Gui {
 
 
 			//Redo
 			//Redo
 			case Key.ControlY: // Control-y, yank
 			case Key.ControlY: // Control-y, yank
+				if (ReadOnly)
+					return true;
+
 				if (historyText != null && historyText.Count > 0) {
 				if (historyText != null && historyText.Count > 0) {
 					isFromHistory = true;
 					isFromHistory = true;
 					if (idxhistoryText < historyText.Count - 1) {
 					if (idxhistoryText < historyText.Count - 1) {
@@ -455,6 +481,9 @@ namespace Terminal.Gui {
 				break;
 				break;
 
 
 			case Key.ControlX:
 			case Key.ControlX:
+				if (ReadOnly)
+					return true;
+
 				Cut ();
 				Cut ();
 				break;
 				break;
 
 
@@ -472,6 +501,9 @@ namespace Terminal.Gui {
 				if (kb.Key < Key.Space || kb.Key > Key.CharMask)
 				if (kb.Key < Key.Space || kb.Key > Key.CharMask)
 					return false;
 					return false;
 
 
+				if (ReadOnly)
+					return true;
+
 				if (SelectedLength != 0) {
 				if (SelectedLength != 0) {
 					DeleteSelectedText ();
 					DeleteSelectedText ();
 					oldCursorPos = point;
 					oldCursorPos = point;
@@ -639,7 +671,7 @@ namespace Terminal.Gui {
 				point = text.Count;
 				point = text.Count;
 			if (point < first)
 			if (point < first)
 				point = 0;
 				point = 0;
-			return x;
+			return point;
 		}
 		}
 
 
 		void PrepareSelection (int x, int direction = 0)
 		void PrepareSelection (int x, int direction = 0)
@@ -682,8 +714,11 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// Copy the selected text to the clipboard.
 		/// Copy the selected text to the clipboard.
 		/// </summary>
 		/// </summary>
-		public void Copy ()
+		public virtual void Copy ()
 		{
 		{
+			if (Secret)
+				return;
+
 			if (SelectedLength != 0) {
 			if (SelectedLength != 0) {
 				Clipboard.Contents = SelectedText;
 				Clipboard.Contents = SelectedText;
 			}
 			}
@@ -692,7 +727,7 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// Cut the selected text to the clipboard.
 		/// Cut the selected text to the clipboard.
 		/// </summary>
 		/// </summary>
-		public void Cut ()
+		public virtual void Cut ()
 		{
 		{
 			if (SelectedLength != 0) {
 			if (SelectedLength != 0) {
 				Clipboard.Contents = SelectedText;
 				Clipboard.Contents = SelectedText;
@@ -715,8 +750,11 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// Paste the selected text from the clipboard.
 		/// Paste the selected text from the clipboard.
 		/// </summary>
 		/// </summary>
-		public void Paste ()
+		public virtual void Paste ()
 		{
 		{
+			if (ReadOnly)
+				return;
+
 			string actualText = Text.ToString ();
 			string actualText = Text.ToString ();
 			int start = SelectedStart == -1 ? CursorPosition : SelectedStart;
 			int start = SelectedStart == -1 ? CursorPosition : SelectedStart;
 			ustring cbTxt = Clipboard.Contents?.ToString () ?? "";
 			ustring cbTxt = Clipboard.Contents?.ToString () ?? "";

+ 28 - 0
Terminal.Gui/Views/TextView.cs

@@ -39,6 +39,7 @@ namespace Terminal.Gui {
 			if (file == null)
 			if (file == null)
 				throw new ArgumentNullException (nameof (file));
 				throw new ArgumentNullException (nameof (file));
 			try {
 			try {
+				FilePath = file;
 				var stream = File.OpenRead (file);
 				var stream = File.OpenRead (file);
 			} catch {
 			} catch {
 				return false;
 				return false;
@@ -47,6 +48,19 @@ namespace Terminal.Gui {
 			return true;
 			return true;
 		}
 		}
 
 
+		public bool CloseFile ()
+		{
+			if (FilePath == null)
+				throw new ArgumentNullException (nameof (FilePath));
+			try {
+				FilePath = null;
+				lines = new List<List<Rune>> ();
+			} catch {
+				return false;
+			}
+			return true;
+		}
+
 		// Turns the ustring into runes, this does not split the 
 		// Turns the ustring into runes, this does not split the 
 		// contents on a newline if it is present.
 		// contents on a newline if it is present.
 		internal static List<Rune> ToRunes (ustring str)
 		internal static List<Rune> ToRunes (ustring str)
@@ -120,6 +134,8 @@ namespace Terminal.Gui {
 			return sb.ToString ();
 			return sb.ToString ();
 		}
 		}
 
 
+		public string FilePath { get; set; }
+
 		/// <summary>
 		/// <summary>
 		/// The number of text lines in the model
 		/// The number of text lines in the model
 		/// </summary>
 		/// </summary>
@@ -351,6 +367,18 @@ namespace Terminal.Gui {
 			SetNeedsDisplay ();
 			SetNeedsDisplay ();
 		}
 		}
 
 
+		/// <summary>
+		/// Closes the contents of the stream into the TextView.
+		/// </summary>
+		/// <returns><c>true</c>, if stream was closed, <c>false</c> otherwise.</returns>
+		public bool CloseFile()
+		{
+			ResetPosition ();
+			var res = model.CloseFile ();
+			SetNeedsDisplay ();
+			return res;
+		}
+
 		/// <summary>
 		/// <summary>
 		///    The current cursor row.
 		///    The current cursor row.
 		/// </summary>
 		/// </summary>

+ 11 - 3
UICatalog/Program.cs

@@ -1,5 +1,6 @@
 using NStack;
 using NStack;
 using System;
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Globalization;
 using System.Globalization;
@@ -119,7 +120,7 @@ namespace UICatalog {
 			_rightPane.Add (_scenarioListView);
 			_rightPane.Add (_scenarioListView);
 
 
 			_categoryListView.SelectedItem = 0;
 			_categoryListView.SelectedItem = 0;
-			CategoryListView_SelectedChanged ();
+			_categoryListView.OnSelectedChanged ();
 
 
 			_statusBar = new StatusBar (new StatusItem [] {
 			_statusBar = new StatusBar (new StatusItem [] {
 				//new StatusItem(Key.F1, "~F1~ Help", () => Help()),
 				//new StatusItem(Key.F1, "~F1~ Help", () => Help()),
@@ -150,6 +151,7 @@ namespace UICatalog {
 			_top = Application.Top;
 			_top = Application.Top;
 
 
 			_top.KeyUp += KeyUpHandler;
 			_top.KeyUp += KeyUpHandler;
+
 			_top.Add (_menu);
 			_top.Add (_menu);
 			_top.Add (_leftPane);
 			_top.Add (_leftPane);
 			_top.Add (_rightPane);
 			_top.Add (_rightPane);
@@ -228,6 +230,12 @@ namespace UICatalog {
 					used++;
 					used++;
 				}
 				}
 			}
 			}
+
+			public IList ToList ()
+			{
+				return Scenarios;
+			}
+
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -245,7 +253,7 @@ namespace UICatalog {
 				//	break;
 				//	break;
 				//case Key.Enter:
 				//case Key.Enter:
 				//	break;
 				//	break;
-				//}
+				//}<
 			} else if (a.KeyEvent.Key == Key.Tab || a.KeyEvent.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
 				// BUGBUG: Work around Issue #434 by implementing our own TAB navigation
 				if (_top.MostFocused == _categoryListView)
 				if (_top.MostFocused == _categoryListView)
@@ -255,7 +263,7 @@ namespace UICatalog {
 			}
 			}
 		}
 		}
 
 
-		private static void CategoryListView_SelectedChanged ()
+		private static void CategoryListView_SelectedChanged (object sender, ListViewItemEventArgs e)
 		{
 		{
 			var item = _categories [_categoryListView.SelectedItem];
 			var item = _categories [_categoryListView.SelectedItem];
 			List<Type> newlist;
 			List<Type> newlist;