Added new method HitTest to TreeView to allow for better context menus

This commit is contained in:
Thomas Nind
2022-05-10 15:39:15 +01:00
parent 736d10598b
commit 5c39f6af48
3 changed files with 110 additions and 1 deletions

View File

@@ -671,6 +671,21 @@ namespace Terminal.Gui {
ObjectActivated?.Invoke (e);
}
/// <summary>
/// Returns the object in the tree list that is currently visible
/// at the provided point. Returns null if no object is at that location.
/// <remarks>
/// </remarks>
/// If you have screen cordinates then use <see cref="View.ScreenToView(int, int)"/>
/// to translate these into the client area of the <see cref="TreeView{T}"/>.
/// </summary>
/// <param name="point">Point with the <see cref="View.Bounds"/> of the <see cref="TreeView{T}"/></param>
/// <returns></returns>
public T HitTest (Point point)
{
return HitTest (point.Y)?.Model;
}
///<inheritdoc/>
public override bool MouseEvent (MouseEvent me)
{

View File

@@ -77,6 +77,7 @@ namespace UICatalog.Scenarios {
};
treeViewFiles.ObjectActivated += TreeViewFiles_ObjectActivated;
treeViewFiles.MouseClick += TreeViewFiles_MouseClick;
SetupFileTree ();
@@ -88,6 +89,52 @@ namespace UICatalog.Scenarios {
red = Application.Driver.MakeAttribute (Color.Red, Color.Blue);
}
private void TreeViewFiles_MouseClick (View.MouseEventArgs obj)
{
// if user right clicks
if (obj.MouseEvent.Flags.HasFlag(MouseFlags.Button3Clicked)) {
var rightClicked = treeViewFiles.HitTest (new Point (obj.MouseEvent.X, obj.MouseEvent.Y));
// nothing was clicked
if (rightClicked == null)
return;
var menu = new ContextMenu ();
menu.Position = new Point(
obj.MouseEvent.X + treeViewFiles.Frame.X,
obj.MouseEvent.Y + treeViewFiles.Frame.Y +1);
menu.MenuItems = new MenuBarItem (new [] { new MenuItem ("Properties",null,()=> {
MessageBox.Query($"{rightClicked.Name}({rightClicked.GetType().Name})",Describe(rightClicked),"Ok");
}
) });
menu.Show ();
}
}
private string Describe (FileSystemInfo f)
{
try {
if (f is FileInfo fi) {
return "Size:" + fi.Length;
}
if (f is DirectoryInfo d) {
return $@"Parent:{d.Parent}
Attributes:{d.Attributes}";
}
} catch (Exception) {
return "Could not get properties";
}
return null;
}
private void SetupScrollBar ()
{
// When using scroll bar leave the last row of the control free (for over-rendering with scroll bar)

View File

@@ -720,8 +720,55 @@ namespace Terminal.Gui.Views {
Assert.Equal (1, tree.GetChildren (root).Count (child => ReferenceEquals (obj2, child)));
}
[Fact, AutoInitShutdown]
public void TestTreeHitTest ()
{
var tv = new TreeView { Width = 20, Height = 10 };
var n1 = new TreeNode ("normal");
var n1_1 = new TreeNode ("pink");
var n1_2 = new TreeNode ("normal");
n1.Children.Add (n1_1);
n1.Children.Add (n1_2);
var n2 = new TreeNode ("pink");
tv.AddObject (n1);
tv.AddObject (n2);
tv.Expand (n1);
tv.ColorScheme = new ColorScheme ();
tv.Redraw (tv.Bounds);
GraphViewTests.AssertDriverContentsAre (
@"├-normal
│ ├─pink
│ └─normal
└─pink
", output);
Assert.Same (n1, tv.HitTest (new Point (0, 0)));
Assert.Same (n1_1, tv.HitTest (new Point (0, 1)));
Assert.Same (n1_2, tv.HitTest (new Point (0, 2)));
Assert.Same (n2, tv.HitTest (new Point (0, 3)));
Assert.Null (tv.HitTest (new Point (0, 4)));
tv.Collapse (n1);
tv.Redraw (tv.Bounds);
GraphViewTests.AssertDriverContentsAre (
@"├+normal
└─pink
", output);
Assert.Same (n1, tv.HitTest (new Point (0, 0)));
Assert.Same (n2, tv.HitTest (new Point (0, 1)));
Assert.Null (tv.HitTest (new Point (0, 2)));
Assert.Null (tv.HitTest (new Point (0, 3)));
Assert.Null (tv.HitTest (new Point (0, 4)));
}
[Fact, AutoInitShutdown]
public void TestTreeViewColor()
{
var tv = new TreeView{Width = 20,Height = 10};