Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 39 additions & 36 deletions Terminal.Gui/Core/Trees/Branch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@
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; }

Expand All @@ -34,12 +34,12 @@ class Branch<T> where T : class {

/// <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;
Expand All @@ -53,7 +53,7 @@ public Branch (TreeView<T> tree, Branch<T> parentBranchIfAny, T model)


/// <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 ()
{
Expand All @@ -80,7 +80,7 @@ public virtual int GetWidth (ConsoleDriver driver)
}

/// <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>
Expand All @@ -89,9 +89,10 @@ public virtual int GetWidth (ConsoleDriver driver)
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);
Attribute textColor = isSelected ? (tree.HasFocus ? colorScheme.HotFocus : colorScheme.HotNormal) : colorScheme.Normal;
Attribute symbolColor = tree.Style.HighlightModelTextOnly ? colorScheme.Normal : textColor;
bool isSelected = tree.IsSelected (Model);// && tree.HasFocus;
Attribute lineColor = isSelected ? (tree.HasFocus ? colorScheme.HotFocus : colorScheme.HotNormal) : colorScheme.Normal ;

driver.SetAttribute (lineColor);

// Everything on line before the expansion run and branch text
Rune [] prefix = GetLinePrefix (driver).ToArray ();
Expand All @@ -103,8 +104,7 @@ public virtual void Draw (ConsoleDriver driver, ColorScheme colorScheme, int y,
// if we have scrolled to the right then bits of the prefix will have dispeared off the screen
int toSkip = tree.ScrollOffsetHorizontal;

driver.SetAttribute (symbolColor);
// Draw the line prefix (all parallel lanes or whitespace and an expand/collapse/leaf symbol)
// Draw the line prefix (all paralell lanes or whitespace and an expand/collapse/leaf symbol)
foreach (Rune r in prefix) {

if (toSkip > 0) {
Expand All @@ -117,12 +117,12 @@ public virtual void Draw (ConsoleDriver driver, ColorScheme colorScheme, int y,

// pick color for expanded symbol
if (tree.Style.ColorExpandSymbol || tree.Style.InvertExpandSymbolColors) {
Attribute color = symbolColor;
Attribute color;

if (tree.Style.ColorExpandSymbol) {
color = isSelected ? tree.ColorScheme.HotFocus : tree.ColorScheme.HotNormal;
} else {
color = symbolColor;
color = lineColor;
}

if (tree.Style.InvertExpandSymbolColors) {
Expand Down Expand Up @@ -162,38 +162,41 @@ public virtual void Draw (ConsoleDriver driver, ColorScheme colorScheme, int y,

// default behaviour is for model to use the color scheme
// of the tree view
var modelColor = textColor;
var modelColor = lineColor;

// 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;
}
}

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 (' ');
Expand Down Expand Up @@ -221,7 +224,7 @@ private IEnumerable<Rune> GetLinePrefix (ConsoleDriver driver)
}

/// <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 ()
Expand All @@ -237,7 +240,7 @@ private IEnumerable<Branch<T>> GetParentBranches ()
/// <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>
Expand All @@ -258,7 +261,7 @@ public Rune GetExpandableSymbol (ConsoleDriver driver)

/// <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 ()
Expand All @@ -280,7 +283,7 @@ public bool CanExpand ()
}

/// <summary>
/// Expands the current branch if possible.
/// Expands the current branch if possible
/// </summary>
public void Expand ()
{
Expand All @@ -294,18 +297,18 @@ public void Expand ()
}

/// <summary>
/// Marks the branch as collapsed (<see cref="IsExpanded"/> false).
/// Marks the branch as collapsed (<see cref="IsExpanded"/> false)
/// </summary>
public void Collapse ()
{
IsExpanded = false;
}

/// <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
Expand Down Expand Up @@ -348,7 +351,7 @@ public void Refresh (bool startAtTop)
}

/// <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 ()
{
Expand All @@ -372,7 +375,7 @@ internal void Rebuild ()

/// <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 ()
Expand All @@ -386,7 +389,7 @@ private bool IsLast ()

/// <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>
Expand All @@ -412,7 +415,7 @@ internal bool IsHitOnExpandableSymbol (ConsoleDriver driver, int x)
}

/// <summary>
/// Expands the current branch and all children branches.
/// Expands the current branch and all children branches
/// </summary>
internal void ExpandAll ()
{
Expand All @@ -427,7 +430,7 @@ internal void ExpandAll ()

/// <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 ()
{
Expand Down
25 changes: 10 additions & 15 deletions Terminal.Gui/Core/Trees/TreeStyle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,46 @@

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>
/// <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.
/// True to render vertical lines under expanded nodes to show which node belongs to which
/// parent. 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 <see langword="true"/> to highlight expand/collapse symbols in hot key color.
/// Set to 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>
/// <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.
/// 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
/// 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;
}
}
12 changes: 4 additions & 8 deletions Terminal.Gui/Views/TreeView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -689,21 +689,17 @@ public void MovePageDown (bool expandSelection = false)
/// </summary>
public void ScrollDown ()
{
if (ScrollOffsetVertical <= ContentHeight - 2) {
ScrollOffsetVertical++;
SetNeedsDisplay ();
}
ScrollOffsetVertical++;
SetNeedsDisplay ();
}

/// <summary>
/// Scrolls the view area up a single line without changing the current selection.
/// </summary>
public void ScrollUp ()
{
if (scrollOffsetVertical > 0) {
ScrollOffsetVertical--;
SetNeedsDisplay ();
}
ScrollOffsetVertical--;
SetNeedsDisplay ();
}

/// <summary>
Expand Down
23 changes: 5 additions & 18 deletions UICatalog/Scenarios/ClassExplorer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ public override string ToString ()
}
}

MenuItem highlightModelTextOnly;

public override void Setup ()
{
Win.Title = this.GetName ();
Expand All @@ -65,20 +63,15 @@ public override void Setup ()
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 MenuBarItem ("_Style", new MenuItem [] {
highlightModelTextOnly = new MenuItem ("_Highlight Model Text Only", "", () => OnCheckHighlightModelTextOnly()) {
CheckType = MenuItemCheckStyle.Checked
},
})
new MenuItem ("_Expand All", "", () => treeView.ExpandAll()),
new MenuItem ("_Collapse All", "", () => treeView.CollapseAll()) }),
});
Top.Add (menu);

Expand All @@ -89,6 +82,7 @@ public override void Setup ()
Height = Dim.Fill (),
};


treeView.AddObjects (AppDomain.CurrentDomain.GetAssemblies ());
treeView.AspectGetter = GetRepresentation;
treeView.TreeBuilder = new DelegateTreeBuilder<object> (ChildGetter, CanExpand);
Expand All @@ -106,13 +100,6 @@ public override void Setup ()
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;
Expand Down