Browse Source

Merge pull request #2161 from tig/newer_treeview_highlight_model_text

TreeView - (redo) Adds option to highlight only the model text of selected node
Tig 2 years ago
parent
commit
ab541ba1da

+ 42 - 40
Terminal.Gui/Core/Trees/Branch.cs

@@ -5,23 +5,23 @@ using System.Linq;
 namespace Terminal.Gui.Trees {
 	class Branch<T> where T : class {
 		/// <summary>
-		/// True if the branch is expanded to reveal child branches
+		/// True if the branch is expanded to reveal child branches.
 		/// </summary>
 		public bool IsExpanded { get; set; }
 
 		/// <summary>
-		/// The users object that is being displayed by this branch of the tree
+		/// The users object that is being displayed by this branch of the tree.
 		/// </summary>
 		public T Model { get; private set; }
 
 		/// <summary>
-		/// The depth of the current branch.  Depth of 0 indicates root level branches
+		/// The depth of the current branch.  Depth of 0 indicates root level branches.
 		/// </summary>
 		public int Depth { get; private set; } = 0;
 
 		/// <summary>
 		/// The children of the current branch.  This is null until the first call to 
-		/// <see cref="FetchChildren"/> to avoid enumerating the entire underlying hierarchy
+		/// <see cref="FetchChildren"/> to avoid enumerating the entire underlying hierarchy.
 		/// </summary>
 		public Dictionary<T, Branch<T>> ChildBranches { get; set; }
 
@@ -34,12 +34,12 @@ namespace Terminal.Gui.Trees {
 
 		/// <summary>
 		/// Declares a new branch of <paramref name="tree"/> in which the users object 
-		/// <paramref name="model"/> is presented
+		/// <paramref name="model"/> is presented.
 		/// </summary>
-		/// <param name="tree">The UI control in which the branch resides</param>
+		/// <param name="tree">The UI control in which the branch resides.</param>
 		/// <param name="parentBranchIfAny">Pass null for root level branches, otherwise
-		/// pass the parent</param>
-		/// <param name="model">The user's object that should be displayed</param>
+		/// pass the parent.</param>
+		/// <param name="model">The user's object that should be displayed.</param>
 		public Branch (TreeView<T> tree, Branch<T> parentBranchIfAny, T model)
 		{
 			this.tree = tree;
@@ -53,7 +53,7 @@ namespace Terminal.Gui.Trees {
 
 
 		/// <summary>
-		/// Fetch the children of this branch. This method populates <see cref="ChildBranches"/>
+		/// Fetch the children of this branch. This method populates <see cref="ChildBranches"/>.
 		/// </summary>
 		public virtual void FetchChildren ()
 		{
@@ -80,7 +80,7 @@ namespace Terminal.Gui.Trees {
 		}
 
 		/// <summary>
-		/// Renders the current <see cref="Model"/> on the specified line <paramref name="y"/>
+		/// Renders the current <see cref="Model"/> on the specified line <paramref name="y"/>.
 		/// </summary>
 		/// <param name="driver"></param>
 		/// <param name="colorScheme"></param>
@@ -89,10 +89,10 @@ namespace Terminal.Gui.Trees {
 		public virtual void Draw (ConsoleDriver driver, ColorScheme colorScheme, int y, int availableWidth)
 		{
 			// true if the current line of the tree is the selected one and control has focus
-			bool isSelected = tree.IsSelected (Model);// && tree.HasFocus;
-			Attribute lineColor = isSelected ? (tree.HasFocus ? colorScheme.HotFocus : colorScheme.HotNormal) : colorScheme.Normal ;
+			bool isSelected = tree.IsSelected (Model);
 
-			driver.SetAttribute (lineColor);
+			Attribute textColor = isSelected ? (tree.HasFocus ? colorScheme.Focus : colorScheme.HotNormal) : colorScheme.Normal;
+			Attribute symbolColor = tree.Style.HighlightModelTextOnly ? colorScheme.Normal : textColor;
 
 			// Everything on line before the expansion run and branch text
 			Rune [] prefix = GetLinePrefix (driver).ToArray ();
@@ -104,7 +104,8 @@ namespace Terminal.Gui.Trees {
 			// if we have scrolled to the right then bits of the prefix will have dispeared off the screen
 			int toSkip = tree.ScrollOffsetHorizontal;
 
-			// Draw the line prefix (all paralell lanes or whitespace and an expand/collapse/leaf symbol)
+			driver.SetAttribute (symbolColor);
+			// Draw the line prefix (all parallel lanes or whitespace and an expand/collapse/leaf symbol)
 			foreach (Rune r in prefix) {
 
 				if (toSkip > 0) {
@@ -117,12 +118,16 @@ namespace Terminal.Gui.Trees {
 
 			// pick color for expanded symbol
 			if (tree.Style.ColorExpandSymbol || tree.Style.InvertExpandSymbolColors) {
-				Attribute color;
+				Attribute color = symbolColor;
 
 				if (tree.Style.ColorExpandSymbol) {
-					color = isSelected ? tree.ColorScheme.HotFocus : tree.ColorScheme.HotNormal;
+					if (isSelected) {
+						color = tree.Style.HighlightModelTextOnly ? colorScheme.HotNormal : (tree.HasFocus ? tree.ColorScheme.HotFocus : tree.ColorScheme.HotNormal);
+					} else {
+						color = tree.ColorScheme.HotNormal;
+					}
 				} else {
-					color = lineColor;
+					color = symbolColor;
 				}
 
 				if (tree.Style.InvertExpandSymbolColors) {
@@ -162,16 +167,14 @@ namespace Terminal.Gui.Trees {
 
 			// default behaviour is for model to use the color scheme
 			// of the tree view
-			var modelColor = lineColor;
+			var modelColor = textColor;
 
 			// if custom color delegate invoke it
-			if(tree.ColorGetter != null)
-			{
-				var modelScheme = tree.ColorGetter(Model);
+			if (tree.ColorGetter != null) {
+				var modelScheme = tree.ColorGetter (Model);
 
 				// if custom color scheme is defined for this Model
-				if(modelScheme != null)
-				{
+				if (modelScheme != null) {
 					// use it
 					modelColor = isSelected ? modelScheme.Focus : modelScheme.Normal;
 				}
@@ -179,24 +182,23 @@ namespace Terminal.Gui.Trees {
 
 			driver.SetAttribute (modelColor);
 			driver.AddStr (lineBody);
-			driver.SetAttribute (lineColor);
 
 			if (availableWidth > 0) {
+				driver.SetAttribute (symbolColor);
 				driver.AddStr (new string (' ', availableWidth));
 			}
-
 			driver.SetAttribute (colorScheme.Normal);
 		}
 
 		/// <summary>
 		/// Gets all characters to render prior to the current branches line.  This includes indentation
-		/// whitespace and any tree branches (if enabled)
+		/// whitespace and any tree branches (if enabled).
 		/// </summary>
 		/// <param name="driver"></param>
 		/// <returns></returns>
 		private IEnumerable<Rune> GetLinePrefix (ConsoleDriver driver)
 		{
-			// If not showing line branches or this is a root object
+			// If not showing line branches or this is a root object.
 			if (!tree.Style.ShowBranchLines) {
 				for (int i = 0; i < Depth; i++) {
 					yield return new Rune (' ');
@@ -224,7 +226,7 @@ namespace Terminal.Gui.Trees {
 		}
 
 		/// <summary>
-		/// Returns all parents starting with the immediate parent and ending at the root
+		/// Returns all parents starting with the immediate parent and ending at the root.
 		/// </summary>
 		/// <returns></returns>
 		private IEnumerable<Branch<T>> GetParentBranches ()
@@ -240,7 +242,7 @@ namespace Terminal.Gui.Trees {
 		/// <summary>
 		/// Returns an appropriate symbol for displaying next to the string representation of 
 		/// the <see cref="Model"/> object to indicate whether it <see cref="IsExpanded"/> or
-		/// not (or it is a leaf)
+		/// not (or it is a leaf).
 		/// </summary>
 		/// <param name="driver"></param>
 		/// <returns></returns>
@@ -261,7 +263,7 @@ namespace Terminal.Gui.Trees {
 
 		/// <summary>
 		/// Returns true if the current branch can be expanded according to 
-		/// the <see cref="TreeBuilder{T}"/> or cached children already fetched
+		/// the <see cref="TreeBuilder{T}"/> or cached children already fetched.
 		/// </summary>
 		/// <returns></returns>
 		public bool CanExpand ()
@@ -283,7 +285,7 @@ namespace Terminal.Gui.Trees {
 		}
 
 		/// <summary>
-		/// Expands the current branch if possible
+		/// Expands the current branch if possible.
 		/// </summary>
 		public void Expand ()
 		{
@@ -297,7 +299,7 @@ namespace Terminal.Gui.Trees {
 		}
 
 		/// <summary>
-		/// Marks the branch as collapsed (<see cref="IsExpanded"/> false)
+		/// Marks the branch as collapsed (<see cref="IsExpanded"/> false).
 		/// </summary>
 		public void Collapse ()
 		{
@@ -305,10 +307,10 @@ namespace Terminal.Gui.Trees {
 		}
 
 		/// <summary>
-		/// Refreshes cached knowledge in this branch e.g. what children an object has
+		/// Refreshes cached knowledge in this branch e.g. what children an object has.
 		/// </summary>
 		/// <param name="startAtTop">True to also refresh all <see cref="Parent"/> 
-		/// branches (starting with the root)</param>
+		/// branches (starting with the root).</param>
 		public void Refresh (bool startAtTop)
 		{
 			// if we must go up and refresh from the top down
@@ -351,7 +353,7 @@ namespace Terminal.Gui.Trees {
 		}
 
 		/// <summary>
-		/// Calls <see cref="Refresh(bool)"/> on the current branch and all expanded children
+		/// Calls <see cref="Refresh(bool)"/> on the current branch and all expanded children.
 		/// </summary>
 		internal void Rebuild ()
 		{
@@ -375,7 +377,7 @@ namespace Terminal.Gui.Trees {
 
 		/// <summary>
 		/// Returns true if this branch has parents and it is the last node of it's parents 
-		/// branches (or last root of the tree)
+		/// branches (or last root of the tree).
 		/// </summary>
 		/// <returns></returns>
 		private bool IsLast ()
@@ -389,7 +391,7 @@ namespace Terminal.Gui.Trees {
 
 		/// <summary>
 		/// Returns true if the given x offset on the branch line is the +/- symbol.  Returns 
-		/// false if not showing expansion symbols or leaf node etc
+		/// false if not showing expansion symbols or leaf node etc.
 		/// </summary>
 		/// <param name="driver"></param>
 		/// <param name="x"></param>
@@ -415,10 +417,10 @@ namespace Terminal.Gui.Trees {
 		}
 
 		/// <summary>
-		/// Expands the current branch and all children branches
+		/// Expands the current branch and all children branches.
 		/// </summary>
 		internal void ExpandAll ()
-			{
+		{
 			Expand ();
 
 			if (ChildBranches != null) {
@@ -430,7 +432,7 @@ namespace Terminal.Gui.Trees {
 
 		/// <summary>
 		/// Collapses the current branch and all children branches (even though those branches are 
-		/// no longer visible they retain collapse/expansion state)
+		/// no longer visible they retain collapse/expansion state).
 		/// </summary>
 		internal void CollapseAll ()
 		{

+ 15 - 10
Terminal.Gui/Core/Trees/TreeStyle.cs

@@ -2,46 +2,51 @@
 
 namespace Terminal.Gui.Trees {
 	/// <summary>
-	/// Defines rendering options that affect how the tree is displayed
+	/// Defines rendering options that affect how the tree is displayed.
 	/// </summary>
 	public class TreeStyle {
 
 		/// <summary>
-		/// True to render vertical lines under expanded nodes to show which node belongs to which 
-		/// parent.  False to use only whitespace
+		/// <see langword="true"/> to render vertical lines under expanded nodes to show which node belongs to which 
+		/// parent. <see langword="false"/> to use only whitespace.
 		/// </summary>
 		/// <value></value>
 		public bool ShowBranchLines { get; set; } = true;
 
 		/// <summary>
-		/// Symbol to use for branch nodes that can be expanded to indicate this to the user.  
-		/// Defaults to '+'. Set to null to hide
+		/// Symbol to use for branch nodes that can be expanded to indicate this to the user. 
+		/// Defaults to '+'. Set to null to hide.
 		/// </summary>
 		public Rune? ExpandableSymbol { get; set; } = '+';
 
 		/// <summary>
 		/// Symbol to use for branch nodes that can be collapsed (are currently expanded).
-		/// Defaults to '-'.  Set to null to hide
+		/// Defaults to '-'. Set to null to hide.
 		/// </summary>
 		public Rune? CollapseableSymbol { get; set; } = '-';
 
 		/// <summary>
-		/// Set to true to highlight expand/collapse symbols in hot key color
+		/// Set to <see langword="true"/> to highlight expand/collapse symbols in hot key color.
 		/// </summary>
 		public bool ColorExpandSymbol { get; set; }
 
 		/// <summary>
-		/// Invert console colours used to render the expand symbol
+		/// Invert console colours used to render the expand symbol.
 		/// </summary>
 		public bool InvertExpandSymbolColors { get; set; }
 
 		/// <summary>
-		/// True to leave the last row of the control free for overwritting (e.g. by a scrollbar)
-		/// When True scrolling will be triggered on the second last row of the control rather than
+		/// <see langword="true"/> to leave the last row of the control free for overwritting (e.g. by a scrollbar)
+		/// When <see langword="true"/> scrolling will be triggered on the second last row of the control rather than.
 		/// the last.
 		/// </summary>
 		/// <value></value>
 		public bool LeaveLastRow { get; set; }
 
+		/// <summary>
+		/// Set to <see langword="true"/> to cause the selected item to be rendered with only the <see cref="Branch{T}.Model"/> text
+		/// to be highlighted. If <see langword="false"/> (the default), the entire row will be highlighted.
+		/// </summary>
+		public bool HighlightModelTextOnly { get; set; } = false;
 	}
 }

+ 8 - 4
Terminal.Gui/Views/TreeView.cs

@@ -689,8 +689,10 @@ namespace Terminal.Gui {
 		/// </summary>
 		public void ScrollDown ()
 		{
-			ScrollOffsetVertical++;
-			SetNeedsDisplay ();
+			if (ScrollOffsetVertical <= ContentHeight - 2) {
+				ScrollOffsetVertical++;
+				SetNeedsDisplay ();
+			}
 		}
 
 		/// <summary>
@@ -698,8 +700,10 @@ namespace Terminal.Gui {
 		/// </summary>
 		public void ScrollUp ()
 		{
-			ScrollOffsetVertical--;
-			SetNeedsDisplay ();
+			if (scrollOffsetVertical > 0) {
+				ScrollOffsetVertical--;
+				SetNeedsDisplay ();
+			}
 		}
 
 		/// <summary>

+ 18 - 5
UICatalog/Scenarios/ClassExplorer.cs

@@ -53,6 +53,8 @@ namespace UICatalog.Scenarios {
 			}
 		}
 
+		MenuItem highlightModelTextOnly;
+
 		public override void Setup ()
 		{
 			Win.Title = this.GetName ();
@@ -63,15 +65,20 @@ namespace UICatalog.Scenarios {
 			var menu = new MenuBar (new MenuBarItem [] {
 				new MenuBarItem ("_File", new MenuItem [] {
 					new MenuItem ("_Quit", "", () => Quit()),
-				})
-				,
+				}),
 				new MenuBarItem ("_View", new MenuItem [] {
 					miShowPrivate = new MenuItem ("_Include Private", "", () => ShowPrivate()){
 						Checked = false,
 						CheckType = MenuItemCheckStyle.Checked
 					},
-				new MenuItem ("_Expand All", "", () => treeView.ExpandAll()),
-				new MenuItem ("_Collapse All", "", () => treeView.CollapseAll()) }),
+					new MenuItem ("_Expand All", "", () => treeView.ExpandAll()),
+					new MenuItem ("_Collapse All", "", () => treeView.CollapseAll())
+				}),
+				new MenuBarItem ("_Style", new MenuItem [] {
+					highlightModelTextOnly = new MenuItem ("_Highlight Model Text Only", "", () => OnCheckHighlightModelTextOnly()) {
+						CheckType = MenuItemCheckStyle.Checked
+					},
+				}) 
 			});
 			Application.Top.Add (menu);
 
@@ -82,7 +89,6 @@ namespace UICatalog.Scenarios {
 				Height = Dim.Fill (),
 			};
 
-
 			treeView.AddObjects (AppDomain.CurrentDomain.GetAssemblies ());
 			treeView.AspectGetter = GetRepresentation;
 			treeView.TreeBuilder = new DelegateTreeBuilder<object> (ChildGetter, CanExpand);
@@ -100,6 +106,13 @@ namespace UICatalog.Scenarios {
 			Win.Add (textView);
 		}
 
+		private void OnCheckHighlightModelTextOnly ()
+		{
+			treeView.Style.HighlightModelTextOnly = !treeView.Style.HighlightModelTextOnly;
+			highlightModelTextOnly.Checked = treeView.Style.HighlightModelTextOnly;
+			treeView.SetNeedsDisplay ();
+		}
+
 		private void ShowPrivate ()
 		{
 			miShowPrivate.Checked = !miShowPrivate.Checked;

+ 3 - 4
UICatalog/Scenarios/CollectionNavigatorTester.cs

@@ -137,7 +137,6 @@ namespace UICatalog.Scenarios {
 				Height = Dim.Fill (),
 				AllowsMarking = false,
 				AllowsMultipleSelection = false,
-				ColorScheme = Colors.TopLevel
 			};
 			Application.Top.Add (_listView);
 
@@ -157,7 +156,7 @@ namespace UICatalog.Scenarios {
 				TextAlignment = TextAlignment.Centered,
 				X = Pos.Right (_listView) + 2,
 				Y = 1, // for menu
-				Width = Dim.Percent (50),
+				Width = Dim.Percent	 (50),
 				Height = 1,
 			};
 			Application.Top.Add (label);
@@ -166,9 +165,9 @@ namespace UICatalog.Scenarios {
 				X = Pos.Right (_listView) + 1,
 				Y = Pos.Bottom (label),
 				Width = Dim.Fill (),
-				Height = Dim.Fill (),
-				ColorScheme = Colors.TopLevel
+				Height = Dim.Fill ()
 			};
+			_treeView.Style.HighlightModelTextOnly = true;
 			Application.Top.Add (_treeView);
 
 			var root = new TreeNode ("IsLetterOrDigit examples");

+ 105 - 76
UICatalog/Scenarios/TreeViewFileSystem.cs

@@ -2,11 +2,12 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Reflection.PortableExecutable;
 using Terminal.Gui;
 using Terminal.Gui.Trees;
 
 namespace UICatalog.Scenarios {
-	[ScenarioMetadata (Name: "TreeViewFileSystem", Description: "Hierarchical file system explorer based on TreeView.")]
+	[ScenarioMetadata (Name: "File System Explorer", Description: "Hierarchical file system explorer demonstrating TreeView.")]
 	[ScenarioCategory ("Controls"), ScenarioCategory ("TreeView"), ScenarioCategory ("Files and IO")]
 	public class TreeViewFileSystem : Scenario {
 
@@ -24,86 +25,97 @@ namespace UICatalog.Scenarios {
 		private MenuItem miUnicodeSymbols;
 		private MenuItem miFullPaths;
 		private MenuItem miLeaveLastRow;
+		private MenuItem miHighlightModelTextOnly;
 		private MenuItem miCustomColors;
 		private MenuItem miCursor;
 		private MenuItem miMultiSelect;
-		private Terminal.Gui.Attribute green;
-		private Terminal.Gui.Attribute red;
+
+		private DetailsFrame detailsFrame;
 
 		public override void Setup ()
 		{
 			Win.Title = this.GetName ();
 			Win.Y = 1; // menu
-			Win.Height = Dim.Fill (1); // status bar
+			Win.Height = Dim.Fill ();
 			Application.Top.LayoutSubviews ();
 
 			var menu = new MenuBar (new MenuBarItem [] {
 				new MenuBarItem ("_File", new MenuItem [] {
-					new MenuItem ("_Quit", "", () => Quit()),
+					new MenuItem ("_Quit", "CTRL-Q", () => Quit()),
 				}),
 				new MenuBarItem ("_View", new MenuItem [] {
-					miShowLines = new MenuItem ("_ShowLines", "", () => ShowLines()){
+					miFullPaths = new MenuItem ("_Full Paths", "", () => SetFullName()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
+					miMultiSelect = new MenuItem ("_Multi Select", "", () => SetMultiSelect()){Checked = true, CheckType = MenuItemCheckStyle.Checked},
+				}),
+				new MenuBarItem ("_Style", new MenuItem [] {
+					miShowLines = new MenuItem ("_Show Lines", "", () => ShowLines()){
 					Checked = true, CheckType = MenuItemCheckStyle.Checked
 						},
 					null /*separator*/,
-					miPlusMinus = new MenuItem ("_PlusMinusSymbols", "", () => SetExpandableSymbols('+','-')){Checked = true, CheckType = MenuItemCheckStyle.Radio},
-					miArrowSymbols = new MenuItem ("_ArrowSymbols", "", () => SetExpandableSymbols('>','v')){Checked = false, CheckType = MenuItemCheckStyle.Radio},
-					miNoSymbols = new MenuItem ("_NoSymbols", "", () => SetExpandableSymbols(null,null)){Checked = false, CheckType = MenuItemCheckStyle.Radio},
-					miUnicodeSymbols = new MenuItem ("_Unicode", "", () => SetExpandableSymbols('ஹ','﷽')){Checked = false, CheckType = MenuItemCheckStyle.Radio},
+					miPlusMinus = new MenuItem ("_Plus Minus Symbols", "+ -", () => SetExpandableSymbols('+','-')){Checked = true, CheckType = MenuItemCheckStyle.Radio},
+					miArrowSymbols = new MenuItem ("_Arrow Symbols", "> v", () => SetExpandableSymbols('>','v')){Checked = false, CheckType = MenuItemCheckStyle.Radio},
+					miNoSymbols = new MenuItem ("_No Symbols", "", () => SetExpandableSymbols(null,null)){Checked = false, CheckType = MenuItemCheckStyle.Radio},
+					miUnicodeSymbols = new MenuItem ("_Unicode", "ஹ ﷽", () => SetExpandableSymbols('ஹ','﷽')){Checked = false, CheckType = MenuItemCheckStyle.Radio},
+					null /*separator*/,
+					miColoredSymbols = new MenuItem ("_Colored Symbols", "", () => ShowColoredExpandableSymbols()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
+					miInvertSymbols = new MenuItem ("_Invert Symbols", "", () => InvertExpandableSymbols()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
+					null /*separator*/,
+					miLeaveLastRow = new MenuItem ("_Leave Last Row", "", () => SetLeaveLastRow()){Checked = true, CheckType = MenuItemCheckStyle.Checked},
+					miHighlightModelTextOnly = new MenuItem ("_Highlight Model Text Only", "", () => SetCheckHighlightModelTextOnly()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
+					null /*separator*/,
+					miCustomColors = new MenuItem ("C_ustom Colors Hidden Files", "Yellow/Red", () => SetCustomColors()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
 					null /*separator*/,
-					miColoredSymbols = new MenuItem ("_ColoredSymbols", "", () => ShowColoredExpandableSymbols()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
-					miInvertSymbols = new MenuItem ("_InvertSymbols", "", () => InvertExpandableSymbols()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
-					miFullPaths = new MenuItem ("_FullPaths", "", () => SetFullName()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
-					miLeaveLastRow = new MenuItem ("_LeaveLastRow", "", () => SetLeaveLastRow()){Checked = true, CheckType = MenuItemCheckStyle.Checked},
-					miCustomColors = new MenuItem ("C_ustomColors", "", () => SetCustomColors()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
 					miCursor = new MenuItem ("Curs_or (MultiSelect only)", "", () => SetCursor()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
-					miMultiSelect = new MenuItem ("_MultiSelect", "", () => SetMultiSelect()){Checked = true, CheckType = MenuItemCheckStyle.Checked},
 				}),
 			});
 			Application.Top.Add (menu);
 
-			var statusBar = new StatusBar (new StatusItem [] {
-				new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
-			});
-			Application.Top.Add (statusBar);
-
-			var lblFiles = new Label ("File Tree:") {
+			treeViewFiles = new TreeView<FileSystemInfo> () {
 				X = 0,
-				Y = 1
+				Y = 0,
+				Width = Dim.Percent (50),
+				Height = Dim.Fill (),
 			};
-			Win.Add (lblFiles);
 
-			treeViewFiles = new TreeView<FileSystemInfo> () {
-				X = 0,
-				Y = Pos.Bottom (lblFiles),
+			detailsFrame = new DetailsFrame () {
+				X = Pos.Right (treeViewFiles),
+				Y = 0,
 				Width = Dim.Fill (),
 				Height = Dim.Fill (),
 			};
 
-			treeViewFiles.ObjectActivated += TreeViewFiles_ObjectActivated;
+			Win.Add (detailsFrame);
 			treeViewFiles.MouseClick += TreeViewFiles_MouseClick;
 			treeViewFiles.KeyPress += TreeViewFiles_KeyPress;
+			treeViewFiles.SelectionChanged += TreeViewFiles_SelectionChanged;
 
 			SetupFileTree ();
 
 			Win.Add (treeViewFiles);
+			treeViewFiles.GoToFirst ();
+			treeViewFiles.Expand ();
 
 			SetupScrollBar ();
 
-			green = Application.Driver.MakeAttribute (Color.Green, Color.Blue);
-			red = Application.Driver.MakeAttribute (Color.Red, Color.Blue);
+			treeViewFiles.SetFocus ();
+
+		}
+
+		private void TreeViewFiles_SelectionChanged (object sender, SelectionChangedEventArgs<FileSystemInfo> e)
+		{
+			ShowPropertiesOf (e.NewValue);
 		}
 
 		private void TreeViewFiles_KeyPress (View.KeyEventEventArgs obj)
 		{
-			if(obj.KeyEvent.Key == (Key.R | Key.CtrlMask)) {
+			if (obj.KeyEvent.Key == (Key.R | Key.CtrlMask)) {
 
 				var selected = treeViewFiles.SelectedObject;
-				
+
 				// nothing is selected
 				if (selected == null)
 					return;
-				
+
 				var location = treeViewFiles.GetObjectRow (selected);
 
 				//selected object is offscreen or somehow not found
@@ -120,9 +132,9 @@ namespace UICatalog.Scenarios {
 		private void TreeViewFiles_MouseClick (View.MouseEventArgs obj)
 		{
 			// if user right clicks
-			if (obj.MouseEvent.Flags.HasFlag(MouseFlags.Button3Clicked)) {
+			if (obj.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked)) {
 
-				var rightClicked = treeViewFiles.GetObjectOnRow ( obj.MouseEvent.Y);
+				var rightClicked = treeViewFiles.GetObjectOnRow (obj.MouseEvent.Y);
 
 				// nothing was clicked
 				if (rightClicked == null)
@@ -141,33 +153,50 @@ namespace UICatalog.Scenarios {
 			menu.Position = screenPoint;
 
 			menu.MenuItems = new MenuBarItem (new [] { new MenuItem ("Properties", null, () => ShowPropertiesOf (forObject)) });
-			
-			Application.MainLoop.Invoke(menu.Show);
-		}
 
-		private void ShowPropertiesOf (FileSystemInfo fileSystemInfo)
-		{
-			if (fileSystemInfo is FileInfo f) {
-				System.Text.StringBuilder sb = new System.Text.StringBuilder ();
-				sb.AppendLine ($"Path:{f.DirectoryName}");
-				sb.AppendLine ($"Size:{f.Length:N0} bytes");
-				sb.AppendLine ($"Modified:{ f.LastWriteTime}");
-				sb.AppendLine ($"Created:{ f.CreationTime}");
-
-				MessageBox.Query (f.Name, sb.ToString (), "Close");
-			}
+			Application.MainLoop.Invoke (menu.Show);
+		}
 
-			if (fileSystemInfo is DirectoryInfo dir) {
+		class DetailsFrame : FrameView {
+			private FileSystemInfo fileInfo;
 
-				System.Text.StringBuilder sb = new System.Text.StringBuilder ();
-				sb.AppendLine ($"Path:{dir.Parent?.FullName}");
-				sb.AppendLine ($"Modified:{ dir.LastWriteTime}");
-				sb.AppendLine ($"Created:{ dir.CreationTime}");
+			public DetailsFrame ()
+			{
+				Title = "Details";
+				Visible = true;
+				CanFocus = true;				
+			}
 
-				MessageBox.Query (dir.Name, sb.ToString (), "Close");
+			public FileSystemInfo FileInfo {
+				get => fileInfo; set {
+					fileInfo = value;
+					System.Text.StringBuilder sb = null;
+					if (fileInfo is FileInfo f) {
+						Title = $"File: {f.Name}";
+						sb = new System.Text.StringBuilder ();
+						sb.AppendLine ($"Path:\n {f.FullName}\n");
+						sb.AppendLine ($"Size:\n {f.Length:N0} bytes\n");
+						sb.AppendLine ($"Modified:\n {f.LastWriteTime}\n");
+						sb.AppendLine ($"Created:\n {f.CreationTime}");
+					}
+
+					if (fileInfo is DirectoryInfo dir) {
+						Title = $"Directory: {dir.Name}";
+						sb = new System.Text.StringBuilder ();
+						sb.AppendLine ($"Path:\n {dir?.FullName}\n");
+						sb.AppendLine ($"Modified:\n {dir.LastWriteTime}\n");
+						sb.AppendLine ($"Created:\n {dir.CreationTime}\n");
+					}
+					Text = sb.ToString ();
+				}
 			}
 		}
 
+		private void ShowPropertiesOf (FileSystemInfo fileSystemInfo)
+		{
+			detailsFrame.FileInfo = fileSystemInfo;
+		}
+
 		private void SetupScrollBar ()
 		{
 			// When using scroll bar leave the last row of the control free (for over-rendering with scroll bar)
@@ -218,11 +247,6 @@ namespace UICatalog.Scenarios {
 			treeViewFiles.AddObjects (DriveInfo.GetDrives ().Select (d => d.RootDirectory));
 		}
 
-		private void TreeViewFiles_ObjectActivated (ObjectActivatedEventArgs<FileSystemInfo> obj)
-		{
-			ShowPropertiesOf (obj.ActivatedObject);
-		}
-
 		private void ShowLines ()
 		{
 			miShowLines.Checked = !miShowLines.Checked;
@@ -266,6 +290,7 @@ namespace UICatalog.Scenarios {
 			} else {
 				treeViewFiles.AspectGetter = (f) => f.Name;
 			}
+			treeViewFiles.SetNeedsDisplay ();
 		}
 
 		private void SetLeaveLastRow ()
@@ -273,41 +298,45 @@ namespace UICatalog.Scenarios {
 			miLeaveLastRow.Checked = !miLeaveLastRow.Checked;
 			treeViewFiles.Style.LeaveLastRow = miLeaveLastRow.Checked;
 		}
-		private void SetCursor()
+		private void SetCursor ()
 		{
 			miCursor.Checked = !miCursor.Checked;
 			treeViewFiles.DesiredCursorVisibility = miCursor.Checked ? CursorVisibility.Default : CursorVisibility.Invisible;
 		}
-		private void SetMultiSelect()
+		private void SetMultiSelect ()
 		{
 			miMultiSelect.Checked = !miMultiSelect.Checked;
 			treeViewFiles.MultiSelect = miMultiSelect.Checked;
 		}
-		
 
-		private void SetCustomColors()
+
+		private void SetCustomColors ()
 		{
-			var yellow = new ColorScheme
-			{
-				Focus = new Terminal.Gui.Attribute(Color.BrightYellow,treeViewFiles.ColorScheme.Focus.Background),
-				Normal = new Terminal.Gui.Attribute (Color.BrightYellow,treeViewFiles.ColorScheme.Normal.Background),
+			var hidden = new ColorScheme {
+				Focus = new Terminal.Gui.Attribute (Color.BrightRed, treeViewFiles.ColorScheme.Focus.Background),
+				Normal = new Terminal.Gui.Attribute (Color.BrightYellow, treeViewFiles.ColorScheme.Normal.Background),
 			};
 
 			miCustomColors.Checked = !miCustomColors.Checked;
 
-			if(miCustomColors.Checked)
-			{
-				treeViewFiles.ColorGetter = (m)=>
-				{
-					return m is DirectoryInfo ? yellow : null;
+			if (miCustomColors.Checked) {
+				treeViewFiles.ColorGetter = (m) => {
+					if (m is DirectoryInfo && m.Attributes.HasFlag (FileAttributes.Hidden)) return hidden;
+					if (m is FileInfo && m.Attributes.HasFlag (FileAttributes.Hidden)) return hidden;
+					return null;
 				};
-			}
-			else
-			{
+			} else {
 				treeViewFiles.ColorGetter = null;
 			}
+			treeViewFiles.SetNeedsDisplay ();
 		}
 
+		private void SetCheckHighlightModelTextOnly ()
+		{
+			treeViewFiles.Style.HighlightModelTextOnly = !treeViewFiles.Style.HighlightModelTextOnly;
+			miHighlightModelTextOnly.Checked = treeViewFiles.Style.HighlightModelTextOnly;
+			treeViewFiles.SetNeedsDisplay ();
+		}
 
 		private IEnumerable<FileSystemInfo> GetChildren (FileSystemInfo model)
 		{