mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Merge branch 'v2_develop' of tig:gui-cs/Terminal.Gui into v2_develop
This commit is contained in:
@@ -65,11 +65,10 @@ namespace Terminal.Gui {
|
||||
|
||||
if (Depth >= tree.MaxDepth) {
|
||||
children = Enumerable.Empty<T> ();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
children = tree.TreeBuilder.GetChildren (this.Model) ?? Enumerable.Empty<T> ();
|
||||
}
|
||||
|
||||
|
||||
this.ChildBranches = children.ToDictionary (k => k, val => new Branch<T> (tree, this, val));
|
||||
}
|
||||
|
||||
@@ -95,6 +94,11 @@ namespace Terminal.Gui {
|
||||
/// <param name="availableWidth"></param>
|
||||
public virtual void Draw (ConsoleDriver driver, ColorScheme colorScheme, int y, int availableWidth)
|
||||
{
|
||||
var cells = new List<RuneCell> ();
|
||||
int? indexOfExpandCollapseSymbol = null;
|
||||
int indexOfModelText;
|
||||
|
||||
|
||||
// true if the current line of the tree is the selected one and control has focus
|
||||
bool isSelected = tree.IsSelected (Model);
|
||||
|
||||
@@ -110,15 +114,15 @@ namespace Terminal.Gui {
|
||||
|
||||
// if we have scrolled to the right then bits of the prefix will have dispeared off the screen
|
||||
int toSkip = tree.ScrollOffsetHorizontal;
|
||||
var attr = symbolColor;
|
||||
|
||||
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) {
|
||||
toSkip--;
|
||||
} else {
|
||||
driver.AddRune (r);
|
||||
cells.Add (NewRuneCell (attr, r));
|
||||
availableWidth -= r.GetColumns ();
|
||||
}
|
||||
}
|
||||
@@ -141,23 +145,31 @@ namespace Terminal.Gui {
|
||||
color = new Attribute (color.Background, color.Foreground);
|
||||
}
|
||||
|
||||
driver.SetAttribute (color);
|
||||
attr = color;
|
||||
}
|
||||
|
||||
if (toSkip > 0) {
|
||||
toSkip--;
|
||||
} else {
|
||||
driver.AddRune (expansion);
|
||||
indexOfExpandCollapseSymbol = cells.Count;
|
||||
cells.Add (NewRuneCell (attr, expansion));
|
||||
availableWidth -= expansion.GetColumns ();
|
||||
}
|
||||
|
||||
// horizontal scrolling has already skipped the prefix but now must also skip some of the line body
|
||||
if (toSkip > 0) {
|
||||
|
||||
// For the event record a negative location for where model text starts since it
|
||||
// is pushed off to the left because of scrolling
|
||||
indexOfModelText = -toSkip;
|
||||
|
||||
if (toSkip > lineBody.Length) {
|
||||
lineBody = "";
|
||||
} else {
|
||||
lineBody = lineBody.Substring (toSkip);
|
||||
}
|
||||
} else {
|
||||
indexOfModelText = cells.Count;
|
||||
}
|
||||
|
||||
// If body of line is too long
|
||||
@@ -186,16 +198,47 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
driver.SetAttribute (modelColor);
|
||||
driver.AddStr (lineBody);
|
||||
attr = modelColor;
|
||||
cells.AddRange (lineBody.Select (r => NewRuneCell (attr, new Rune (r))));
|
||||
|
||||
if (availableWidth > 0) {
|
||||
driver.SetAttribute (symbolColor);
|
||||
driver.AddStr (new string (' ', availableWidth));
|
||||
attr = symbolColor;
|
||||
cells.AddRange (
|
||||
Enumerable.Repeat (
|
||||
NewRuneCell (attr, new Rune (' ')),
|
||||
availableWidth
|
||||
));
|
||||
}
|
||||
|
||||
var e = new DrawTreeViewLineEventArgs<T> {
|
||||
Model = Model,
|
||||
Y = y,
|
||||
RuneCells = cells,
|
||||
Tree = tree,
|
||||
IndexOfExpandCollapseSymbol = indexOfExpandCollapseSymbol,
|
||||
IndexOfModelText = indexOfModelText,
|
||||
};
|
||||
tree.OnDrawLine (e);
|
||||
|
||||
if (!e.Handled) {
|
||||
foreach (var cell in cells) {
|
||||
driver.SetAttribute (cell.ColorScheme.Normal);
|
||||
driver.AddRune (cell.Rune);
|
||||
}
|
||||
}
|
||||
|
||||
driver.SetAttribute (colorScheme.Normal);
|
||||
}
|
||||
|
||||
private static RuneCell NewRuneCell (Attribute attr, Rune r)
|
||||
{
|
||||
return new RuneCell {
|
||||
Rune = r,
|
||||
ColorScheme = new ColorScheme (attr)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets all characters to render prior to the current branches line. This includes indentation
|
||||
/// whitespace and any tree branches (if enabled).
|
||||
|
||||
66
Terminal.Gui/Views/TreeView/DrawTreeViewLineEventArgs.cs
Normal file
66
Terminal.Gui/Views/TreeView/DrawTreeViewLineEventArgs.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
// This code is based on http://objectlistview.sourceforge.net (GPLv3 tree/list controls
|
||||
// by phillip.piper@gmail.com). Phillip has explicitly granted permission for his design
|
||||
// and code to be used in this library under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// Event args for the <see cref="TreeView{T}.DrawLine"/> event
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class DrawTreeViewLineEventArgs<T> where T : class {
|
||||
|
||||
/// <summary>
|
||||
/// The object at this line in the tree
|
||||
/// </summary>
|
||||
public T Model { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TreeView{T}"/> that is performing the
|
||||
/// rendering.
|
||||
/// </summary>
|
||||
public TreeView<T> Tree { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The line within tree view bounds that is being rendered
|
||||
/// </summary>
|
||||
public int Y { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Set to true to cancel drawing (e.g. if you have already manually
|
||||
/// drawn content).
|
||||
/// </summary>
|
||||
public bool Handled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The rune and color of each symbol that will be rendered. Note
|
||||
/// that only <see cref="ColorScheme.Normal"/> is respected. You
|
||||
/// can modify these to change what is rendered.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Changing the length of this collection may result in corrupt rendering
|
||||
/// </remarks>
|
||||
public List<RuneCell> RuneCells { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The notional index in <see cref="RuneCells"/> which contains the first
|
||||
/// character of the <see cref="TreeView{T}.AspectGetter"/> text (i.e.
|
||||
/// after all branch lines and expansion/collapse sybmols).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// May be negative or outside of bounds of <see cref="RuneCells"/> if the view
|
||||
/// has been scrolled horizontally.
|
||||
/// </remarks>
|
||||
|
||||
public int IndexOfModelText { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// If line contains a branch that can be expanded/collapsed then this is
|
||||
/// the index in <see cref="RuneCells"/> at which the symbol is (or null for
|
||||
/// leaf elements).
|
||||
/// </summary>
|
||||
public int? IndexOfExpandCollapseSymbol { get; init; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -169,6 +169,12 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
public event EventHandler<SelectionChangedEventArgs<T>> SelectionChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Called once for each visible row during rendering. Can be used
|
||||
/// to make last minute changes to color or text rendered
|
||||
/// </summary>
|
||||
public event EventHandler<DrawTreeViewLineEventArgs<T>> DrawLine;
|
||||
|
||||
/// <summary>
|
||||
/// The root objects in the tree, note that this collection is of root objects only.
|
||||
/// </summary>
|
||||
@@ -557,10 +563,9 @@ namespace Terminal.Gui {
|
||||
List<Branch<T>> toReturn = new List<Branch<T>> ();
|
||||
|
||||
foreach (var root in roots.Values) {
|
||||
|
||||
|
||||
var toAdd = AddToLineMap (root, false, out var isMatch);
|
||||
if(isMatch)
|
||||
{
|
||||
if (isMatch) {
|
||||
toReturn.AddRange (toAdd);
|
||||
}
|
||||
}
|
||||
@@ -574,41 +579,38 @@ namespace Terminal.Gui {
|
||||
|
||||
private bool IsFilterMatch (Branch<T> branch)
|
||||
{
|
||||
return Filter?.IsMatch(branch.Model) ?? true;
|
||||
return Filter?.IsMatch (branch.Model) ?? true;
|
||||
}
|
||||
|
||||
private IEnumerable<Branch<T>> AddToLineMap (Branch<T> currentBranch,bool parentMatches, out bool match)
|
||||
private IEnumerable<Branch<T>> AddToLineMap (Branch<T> currentBranch, bool parentMatches, out bool match)
|
||||
{
|
||||
bool weMatch = IsFilterMatch(currentBranch);
|
||||
bool weMatch = IsFilterMatch (currentBranch);
|
||||
bool anyChildMatches = false;
|
||||
|
||||
var toReturn = new List<Branch<T>>();
|
||||
var children = new List<Branch<T>>();
|
||||
|
||||
var toReturn = new List<Branch<T>> ();
|
||||
var children = new List<Branch<T>> ();
|
||||
|
||||
if (currentBranch.IsExpanded) {
|
||||
foreach (var subBranch in currentBranch.ChildBranches.Values) {
|
||||
|
||||
foreach (var sub in AddToLineMap (subBranch, weMatch, out var childMatch)) {
|
||||
|
||||
if(childMatch)
|
||||
{
|
||||
children.Add(sub);
|
||||
|
||||
if (childMatch) {
|
||||
children.Add (sub);
|
||||
anyChildMatches = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(parentMatches || weMatch || anyChildMatches)
|
||||
{
|
||||
if (parentMatches || weMatch || anyChildMatches) {
|
||||
match = true;
|
||||
toReturn.Add(currentBranch);
|
||||
}
|
||||
else{
|
||||
toReturn.Add (currentBranch);
|
||||
} else {
|
||||
match = false;
|
||||
}
|
||||
|
||||
toReturn.AddRange(children);
|
||||
|
||||
toReturn.AddRange (children);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -1421,8 +1423,17 @@ namespace Terminal.Gui {
|
||||
{
|
||||
SelectionChanged?.Invoke (this, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the DrawLine event
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
internal void OnDrawLine (DrawTreeViewLineEventArgs<T> e)
|
||||
{
|
||||
DrawLine?.Invoke (this, e);
|
||||
}
|
||||
|
||||
}
|
||||
class TreeSelection<T> where T : class {
|
||||
|
||||
public Branch<T> Origin { get; }
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace UICatalog.Scenarios {
|
||||
Width = Dim.Percent (50),
|
||||
Height = Dim.Fill (),
|
||||
};
|
||||
treeViewFiles.DrawLine += TreeViewFiles_DrawLine;
|
||||
|
||||
_detailsFrame = new DetailsFrame (_iconProvider) {
|
||||
X = Pos.Right (treeViewFiles),
|
||||
@@ -106,7 +107,7 @@ namespace UICatalog.Scenarios {
|
||||
SetupScrollBar ();
|
||||
|
||||
treeViewFiles.SetFocus ();
|
||||
|
||||
|
||||
UpdateIconCheckedness ();
|
||||
}
|
||||
|
||||
@@ -140,6 +141,23 @@ namespace UICatalog.Scenarios {
|
||||
ShowPropertiesOf (e.NewValue);
|
||||
}
|
||||
|
||||
private void TreeViewFiles_DrawLine (object sender, DrawTreeViewLineEventArgs<IFileSystemInfo> e)
|
||||
{
|
||||
// Render directory icons in yellow
|
||||
if (e.Model is IDirectoryInfo d) {
|
||||
if (_iconProvider.UseNerdIcons || _iconProvider.UseUnicodeCharacters) {
|
||||
if (e.IndexOfModelText > 0 && e.IndexOfModelText < e.RuneCells.Count) {
|
||||
var cell = e.RuneCells [e.IndexOfModelText];
|
||||
cell.ColorScheme = new ColorScheme (
|
||||
new Terminal.Gui.Attribute (
|
||||
Color.BrightYellow,
|
||||
cell.ColorScheme.Normal.Background)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TreeViewFiles_KeyPress (object sender, KeyEventEventArgs obj)
|
||||
{
|
||||
if (obj.KeyEvent.Key == (Key.R | Key.CtrlMask)) {
|
||||
@@ -195,7 +213,7 @@ namespace UICatalog.Scenarios {
|
||||
private IFileSystemInfo fileInfo;
|
||||
private FileSystemIconProvider _iconProvider;
|
||||
|
||||
public DetailsFrame (FileSystemIconProvider iconProvider)
|
||||
public DetailsFrame (FileSystemIconProvider iconProvider)
|
||||
{
|
||||
Title = "Details";
|
||||
Visible = true;
|
||||
@@ -209,7 +227,7 @@ namespace UICatalog.Scenarios {
|
||||
System.Text.StringBuilder sb = null;
|
||||
|
||||
if (fileInfo is IFileInfo f) {
|
||||
Title = $"{_iconProvider.GetIconWithOptionalSpace(f)}{f.Name}".Trim();
|
||||
Title = $"{_iconProvider.GetIconWithOptionalSpace (f)}{f.Name}".Trim ();
|
||||
sb = new System.Text.StringBuilder ();
|
||||
sb.AppendLine ($"Path:\n {f.FullName}\n");
|
||||
sb.AppendLine ($"Size:\n {f.Length:N0} bytes\n");
|
||||
@@ -218,7 +236,7 @@ namespace UICatalog.Scenarios {
|
||||
}
|
||||
|
||||
if (fileInfo is IDirectoryInfo dir) {
|
||||
Title = $"{_iconProvider.GetIconWithOptionalSpace(dir)}{dir.Name}".Trim();
|
||||
Title = $"{_iconProvider.GetIconWithOptionalSpace (dir)}{dir.Name}".Trim ();
|
||||
sb = new System.Text.StringBuilder ();
|
||||
sb.AppendLine ($"Path:\n {dir?.FullName}\n");
|
||||
sb.AppendLine ($"Modified:\n {dir.LastWriteTime}\n");
|
||||
@@ -241,7 +259,7 @@ namespace UICatalog.Scenarios {
|
||||
|
||||
var scrollBar = new ScrollBarView (treeViewFiles, true);
|
||||
|
||||
scrollBar.ChangedPosition += (s,e) => {
|
||||
scrollBar.ChangedPosition += (s, e) => {
|
||||
treeViewFiles.ScrollOffsetVertical = scrollBar.Position;
|
||||
if (treeViewFiles.ScrollOffsetVertical != scrollBar.Position) {
|
||||
scrollBar.Position = treeViewFiles.ScrollOffsetVertical;
|
||||
@@ -249,7 +267,7 @@ namespace UICatalog.Scenarios {
|
||||
treeViewFiles.SetNeedsDisplay ();
|
||||
};
|
||||
|
||||
scrollBar.OtherScrollBarView.ChangedPosition += (s,e) => {
|
||||
scrollBar.OtherScrollBarView.ChangedPosition += (s, e) => {
|
||||
treeViewFiles.ScrollOffsetHorizontal = scrollBar.OtherScrollBarView.Position;
|
||||
if (treeViewFiles.ScrollOffsetHorizontal != scrollBar.OtherScrollBarView.Position) {
|
||||
scrollBar.OtherScrollBarView.Position = treeViewFiles.ScrollOffsetHorizontal;
|
||||
@@ -257,7 +275,7 @@ namespace UICatalog.Scenarios {
|
||||
treeViewFiles.SetNeedsDisplay ();
|
||||
};
|
||||
|
||||
treeViewFiles.DrawContent += (s,e) => {
|
||||
treeViewFiles.DrawContent += (s, e) => {
|
||||
scrollBar.Size = treeViewFiles.ContentHeight;
|
||||
scrollBar.Position = treeViewFiles.ScrollOffsetVertical;
|
||||
scrollBar.OtherScrollBarView.Size = treeViewFiles.GetContentWidth (true);
|
||||
@@ -269,20 +287,20 @@ namespace UICatalog.Scenarios {
|
||||
private void SetupFileTree ()
|
||||
{
|
||||
// setup how to build tree
|
||||
var fs = new FileSystem();
|
||||
var rootDirs = DriveInfo.GetDrives ().Select (d=>fs.DirectoryInfo.New(d.RootDirectory.FullName));
|
||||
var fs = new FileSystem ();
|
||||
var rootDirs = DriveInfo.GetDrives ().Select (d => fs.DirectoryInfo.New (d.RootDirectory.FullName));
|
||||
treeViewFiles.TreeBuilder = new FileSystemTreeBuilder ();
|
||||
treeViewFiles.AddObjects (rootDirs);
|
||||
|
||||
// Determines how to represent objects as strings on the screen
|
||||
treeViewFiles.AspectGetter = AspectGetter;
|
||||
|
||||
|
||||
_iconProvider.IsOpenGetter = treeViewFiles.IsExpanded;
|
||||
}
|
||||
|
||||
private string AspectGetter (IFileSystemInfo f)
|
||||
{
|
||||
return (_iconProvider.GetIconWithOptionalSpace(f) + f.Name).Trim();
|
||||
return (_iconProvider.GetIconWithOptionalSpace (f) + f.Name).Trim ();
|
||||
}
|
||||
|
||||
private void ShowLines ()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
@@ -939,7 +940,7 @@ namespace Terminal.Gui.ViewsTests {
|
||||
Assert.False (tv.CanExpand ("6"));
|
||||
Assert.False (tv.IsExpanded ("6"));
|
||||
|
||||
tv.Collapse("6");
|
||||
tv.Collapse ("6");
|
||||
|
||||
Assert.False (tv.CanExpand ("6"));
|
||||
Assert.False (tv.IsExpanded ("6"));
|
||||
@@ -992,6 +993,174 @@ namespace Terminal.Gui.ViewsTests {
|
||||
└-2
|
||||
└-3
|
||||
└─4
|
||||
", output);
|
||||
}
|
||||
[Fact, AutoInitShutdown]
|
||||
public void TestTreeView_DrawLineEvent ()
|
||||
{
|
||||
var tv = new TreeView { Width = 20, Height = 10 };
|
||||
|
||||
var eventArgs = new List<DrawTreeViewLineEventArgs<ITreeNode>> ();
|
||||
|
||||
tv.DrawLine += (s, e) => {
|
||||
eventArgs.Add (e);
|
||||
};
|
||||
|
||||
var n1 = new TreeNode ("root one");
|
||||
var n1_1 = new TreeNode ("leaf 1");
|
||||
var n1_2 = new TreeNode ("leaf 2");
|
||||
n1.Children.Add (n1_1);
|
||||
n1.Children.Add (n1_2);
|
||||
|
||||
var n2 = new TreeNode ("root two");
|
||||
tv.AddObject (n1);
|
||||
tv.AddObject (n2);
|
||||
tv.Expand (n1);
|
||||
|
||||
tv.ColorScheme = new ColorScheme ();
|
||||
tv.LayoutSubviews ();
|
||||
tv.Draw ();
|
||||
|
||||
// Normal drawing of the tree view
|
||||
TestHelpers.AssertDriverContentsAre (
|
||||
@"
|
||||
├-root one
|
||||
│ ├─leaf 1
|
||||
│ └─leaf 2
|
||||
└─root two
|
||||
", output);
|
||||
Assert.Equal (4, eventArgs.Count ());
|
||||
|
||||
Assert.Equal (0, eventArgs [0].Y);
|
||||
Assert.Equal (1, eventArgs [1].Y);
|
||||
Assert.Equal (2, eventArgs [2].Y);
|
||||
Assert.Equal (3, eventArgs [3].Y);
|
||||
|
||||
Assert.All (eventArgs, ea => Assert.Equal (ea.Tree, tv));
|
||||
Assert.All (eventArgs, ea => Assert.False (ea.Handled));
|
||||
|
||||
Assert.Equal ("├-root one", eventArgs [0].RuneCells.Aggregate ("", (s, n) => s += n.Rune).TrimEnd ());
|
||||
Assert.Equal ("│ ├─leaf 1", eventArgs [1].RuneCells.Aggregate ("", (s, n) => s += n.Rune).TrimEnd ());
|
||||
Assert.Equal ("│ └─leaf 2", eventArgs [2].RuneCells.Aggregate ("", (s, n) => s += n.Rune).TrimEnd ());
|
||||
Assert.Equal ("└─root two", eventArgs [3].RuneCells.Aggregate ("", (s, n) => s += n.Rune).TrimEnd ());
|
||||
|
||||
Assert.Equal (1, eventArgs [0].IndexOfExpandCollapseSymbol);
|
||||
Assert.Equal (3, eventArgs [1].IndexOfExpandCollapseSymbol);
|
||||
Assert.Equal (3, eventArgs [2].IndexOfExpandCollapseSymbol);
|
||||
Assert.Equal (1, eventArgs [3].IndexOfExpandCollapseSymbol);
|
||||
|
||||
Assert.Equal (2, eventArgs [0].IndexOfModelText);
|
||||
Assert.Equal (4, eventArgs [1].IndexOfModelText);
|
||||
Assert.Equal (4, eventArgs [2].IndexOfModelText);
|
||||
Assert.Equal (2, eventArgs [3].IndexOfModelText);
|
||||
|
||||
|
||||
Assert.Equal ("root one", eventArgs [0].Model.Text);
|
||||
Assert.Equal ("leaf 1", eventArgs [1].Model.Text);
|
||||
Assert.Equal ("leaf 2", eventArgs [2].Model.Text);
|
||||
Assert.Equal ("root two", eventArgs [3].Model.Text);
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
public void TestTreeView_DrawLineEvent_WithScrolling ()
|
||||
{
|
||||
var tv = new TreeView { Width = 20, Height = 10 };
|
||||
|
||||
var eventArgs = new List<DrawTreeViewLineEventArgs<ITreeNode>> ();
|
||||
|
||||
tv.DrawLine += (s, e) => {
|
||||
eventArgs.Add (e);
|
||||
};
|
||||
|
||||
tv.ScrollOffsetHorizontal = 3;
|
||||
tv.ScrollOffsetVertical = 1;
|
||||
|
||||
var n1 = new TreeNode ("root one");
|
||||
var n1_1 = new TreeNode ("leaf 1");
|
||||
var n1_2 = new TreeNode ("leaf 2");
|
||||
n1.Children.Add (n1_1);
|
||||
n1.Children.Add (n1_2);
|
||||
|
||||
var n2 = new TreeNode ("root two");
|
||||
tv.AddObject (n1);
|
||||
tv.AddObject (n2);
|
||||
tv.Expand (n1);
|
||||
|
||||
tv.ColorScheme = new ColorScheme ();
|
||||
tv.LayoutSubviews ();
|
||||
tv.Draw ();
|
||||
|
||||
// Normal drawing of the tree view
|
||||
TestHelpers.AssertDriverContentsAre (
|
||||
@"
|
||||
─leaf 1
|
||||
─leaf 2
|
||||
oot two
|
||||
", output);
|
||||
Assert.Equal (3, eventArgs.Count ());
|
||||
|
||||
Assert.Equal (0, eventArgs [0].Y);
|
||||
Assert.Equal (1, eventArgs [1].Y);
|
||||
Assert.Equal (2, eventArgs [2].Y);
|
||||
|
||||
Assert.All (eventArgs, ea => Assert.Equal (ea.Tree, tv));
|
||||
Assert.All (eventArgs, ea => Assert.False (ea.Handled));
|
||||
|
||||
Assert.Equal ("─leaf 1", eventArgs [0].RuneCells.Aggregate ("", (s, n) => s += n.Rune).TrimEnd ());
|
||||
Assert.Equal ("─leaf 2", eventArgs [1].RuneCells.Aggregate ("", (s, n) => s += n.Rune).TrimEnd ());
|
||||
Assert.Equal ("oot two", eventArgs [2].RuneCells.Aggregate ("", (s, n) => s += n.Rune).TrimEnd ());
|
||||
|
||||
Assert.Equal (0, eventArgs [0].IndexOfExpandCollapseSymbol);
|
||||
Assert.Equal (0, eventArgs [1].IndexOfExpandCollapseSymbol);
|
||||
Assert.Null (eventArgs [2].IndexOfExpandCollapseSymbol);
|
||||
|
||||
Assert.Equal (1, eventArgs [0].IndexOfModelText);
|
||||
Assert.Equal (1, eventArgs [1].IndexOfModelText);
|
||||
Assert.Equal (-1, eventArgs [2].IndexOfModelText);
|
||||
|
||||
Assert.Equal ("leaf 1", eventArgs [0].Model.Text);
|
||||
Assert.Equal ("leaf 2", eventArgs [1].Model.Text);
|
||||
Assert.Equal ("root two", eventArgs [2].Model.Text);
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
public void TestTreeView_DrawLineEvent_Handled ()
|
||||
{
|
||||
var tv = new TreeView { Width = 20, Height = 10 };
|
||||
|
||||
tv.DrawLine += (s, e) => {
|
||||
if(e.Model.Text.Equals("leaf 1")) {
|
||||
e.Handled = true;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
|
||||
e.Tree.AddRune (i,e.Y,new System.Text.Rune('F'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var n1 = new TreeNode ("root one");
|
||||
var n1_1 = new TreeNode ("leaf 1");
|
||||
var n1_2 = new TreeNode ("leaf 2");
|
||||
n1.Children.Add (n1_1);
|
||||
n1.Children.Add (n1_2);
|
||||
|
||||
var n2 = new TreeNode ("root two");
|
||||
tv.AddObject (n1);
|
||||
tv.AddObject (n2);
|
||||
tv.Expand (n1);
|
||||
|
||||
tv.ColorScheme = new ColorScheme ();
|
||||
tv.LayoutSubviews ();
|
||||
tv.Draw ();
|
||||
|
||||
// Normal drawing of the tree view
|
||||
TestHelpers.AssertDriverContentsAre (
|
||||
@"
|
||||
├-root one
|
||||
FFFFFFFFFF
|
||||
│ └─leaf 2
|
||||
└─root two
|
||||
", output);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user