mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Merge pull request #1706 from tznind/tree-view-context
Tree view context
This commit is contained in:
@@ -609,6 +609,29 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Returns the Y coordinate within the <see cref="View.Bounds"/> of the
|
||||
/// tree at which <paramref name="toFind"/> would be displayed or null if
|
||||
/// it is not currently exposed (e.g. its parent is collapsed).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note that the returned value can be negative if the TreeView is scrolled
|
||||
/// down and the <paramref name="toFind"/> object is off the top of the view.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="toFind"></param>
|
||||
/// <returns></returns>
|
||||
public int? GetObjectRow(T toFind)
|
||||
{
|
||||
var idx = BuildLineMap ().IndexOf (o => o.Model.Equals (toFind));
|
||||
|
||||
if (idx == -1)
|
||||
return null;
|
||||
|
||||
return idx - ScrollOffsetVertical;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Moves the <see cref="SelectedObject"/> to the next item that begins with <paramref name="character"/></para>
|
||||
/// <para>This method will loop back to the start of the tree if reaching the end without finding a match</para>
|
||||
@@ -671,6 +694,21 @@ namespace Terminal.Gui {
|
||||
ObjectActivated?.Invoke (e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the object in the tree list that is currently visible
|
||||
/// at the provided row. Returns null if no object is at that location.
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
/// If you have screen coordinates then use <see cref="View.ScreenToView(int, int)"/>
|
||||
/// to translate these into the client area of the <see cref="TreeView{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="row">The row of the <see cref="View.Bounds"/> of the <see cref="TreeView{T}"/></param>
|
||||
/// <returns>The object currently displayed on this row or null</returns>
|
||||
public T GetObjectOnRow (int row)
|
||||
{
|
||||
return HitTest (row)?.Model;
|
||||
}
|
||||
|
||||
///<inheritdoc/>
|
||||
public override bool MouseEvent (MouseEvent me)
|
||||
{
|
||||
|
||||
@@ -77,6 +77,8 @@ namespace UICatalog.Scenarios {
|
||||
};
|
||||
|
||||
treeViewFiles.ObjectActivated += TreeViewFiles_ObjectActivated;
|
||||
treeViewFiles.MouseClick += TreeViewFiles_MouseClick;
|
||||
treeViewFiles.KeyPress += TreeViewFiles_KeyPress;
|
||||
|
||||
SetupFileTree ();
|
||||
|
||||
@@ -88,6 +90,80 @@ namespace UICatalog.Scenarios {
|
||||
red = Application.Driver.MakeAttribute (Color.Red, Color.Blue);
|
||||
}
|
||||
|
||||
private void TreeViewFiles_KeyPress (View.KeyEventEventArgs obj)
|
||||
{
|
||||
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
|
||||
if (location == null || location < 0 || location > treeViewFiles.Frame.Height)
|
||||
return;
|
||||
|
||||
ShowContextMenu (new Point (
|
||||
5 + treeViewFiles.Frame.X,
|
||||
location.Value + treeViewFiles.Frame.Y + 2),
|
||||
selected);
|
||||
}
|
||||
}
|
||||
|
||||
private void TreeViewFiles_MouseClick (View.MouseEventArgs obj)
|
||||
{
|
||||
// if user right clicks
|
||||
if (obj.MouseEvent.Flags.HasFlag(MouseFlags.Button3Clicked)) {
|
||||
|
||||
var rightClicked = treeViewFiles.GetObjectOnRow ( obj.MouseEvent.Y);
|
||||
|
||||
// nothing was clicked
|
||||
if (rightClicked == null)
|
||||
return;
|
||||
|
||||
ShowContextMenu (new Point (
|
||||
obj.MouseEvent.X + treeViewFiles.Frame.X,
|
||||
obj.MouseEvent.Y + treeViewFiles.Frame.Y + 2),
|
||||
rightClicked);
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowContextMenu (Point screenPoint, FileSystemInfo forObject)
|
||||
{
|
||||
var menu = new ContextMenu ();
|
||||
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");
|
||||
}
|
||||
|
||||
if (fileSystemInfo is DirectoryInfo dir) {
|
||||
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder ();
|
||||
sb.AppendLine ($"Path:{dir.Parent?.FullName}");
|
||||
sb.AppendLine ($"Modified:{ dir.LastWriteTime}");
|
||||
sb.AppendLine ($"Created:{ dir.CreationTime}");
|
||||
|
||||
MessageBox.Query (dir.Name, sb.ToString (), "Close");
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupScrollBar ()
|
||||
{
|
||||
// When using scroll bar leave the last row of the control free (for over-rendering with scroll bar)
|
||||
@@ -140,25 +216,7 @@ namespace UICatalog.Scenarios {
|
||||
|
||||
private void TreeViewFiles_ObjectActivated (ObjectActivatedEventArgs<FileSystemInfo> obj)
|
||||
{
|
||||
if (obj.ActivatedObject 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");
|
||||
}
|
||||
|
||||
if (obj.ActivatedObject is DirectoryInfo dir) {
|
||||
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder ();
|
||||
sb.AppendLine ($"Path:{dir.Parent?.FullName}");
|
||||
sb.AppendLine ($"Modified:{ dir.LastWriteTime}");
|
||||
sb.AppendLine ($"Created:{ dir.CreationTime}");
|
||||
|
||||
MessageBox.Query (dir.Name, sb.ToString (), "Close");
|
||||
}
|
||||
ShowPropertiesOf (obj.ActivatedObject);
|
||||
}
|
||||
|
||||
private void ShowLines ()
|
||||
|
||||
@@ -720,7 +720,115 @@ namespace Terminal.Gui.Views {
|
||||
Assert.Equal (1, tree.GetChildren (root).Count (child => ReferenceEquals (obj2, child)));
|
||||
|
||||
}
|
||||
[Fact, AutoInitShutdown]
|
||||
public void TestGetObjectOnRow ()
|
||||
{
|
||||
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.GetObjectOnRow (0));
|
||||
Assert.Same (n1_1, tv.GetObjectOnRow (1));
|
||||
Assert.Same (n1_2, tv.GetObjectOnRow (2));
|
||||
Assert.Same (n2, tv.GetObjectOnRow (3));
|
||||
Assert.Null (tv.GetObjectOnRow (4));
|
||||
|
||||
tv.Collapse (n1);
|
||||
|
||||
tv.Redraw (tv.Bounds);
|
||||
|
||||
|
||||
GraphViewTests.AssertDriverContentsAre (
|
||||
@"├+normal
|
||||
└─pink
|
||||
", output);
|
||||
|
||||
Assert.Same (n1, tv.GetObjectOnRow (0));
|
||||
Assert.Same (n2, tv.GetObjectOnRow (1));
|
||||
Assert.Null (tv.GetObjectOnRow (2));
|
||||
Assert.Null (tv.GetObjectOnRow (3));
|
||||
Assert.Null (tv.GetObjectOnRow (4));
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
public void TestGetObjectRow ()
|
||||
{
|
||||
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.Equal (0, tv.GetObjectRow (n1));
|
||||
Assert.Equal (1, tv.GetObjectRow (n1_1));
|
||||
Assert.Equal (2, tv.GetObjectRow (n1_2));
|
||||
Assert.Equal (3, tv.GetObjectRow (n2));
|
||||
|
||||
tv.Collapse (n1);
|
||||
|
||||
tv.Redraw (tv.Bounds);
|
||||
|
||||
|
||||
GraphViewTests.AssertDriverContentsAre (
|
||||
@"├+normal
|
||||
└─pink
|
||||
", output);
|
||||
Assert.Equal (0, tv.GetObjectRow (n1));
|
||||
Assert.Null (tv.GetObjectRow (n1_1));
|
||||
Assert.Null (tv.GetObjectRow (n1_2));
|
||||
Assert.Equal (1, tv.GetObjectRow (n2));
|
||||
|
||||
|
||||
// scroll down 1
|
||||
tv.ScrollOffsetVertical = 1;
|
||||
|
||||
tv.Redraw (tv.Bounds);
|
||||
|
||||
|
||||
GraphViewTests.AssertDriverContentsAre (
|
||||
@"└─pink
|
||||
", output);
|
||||
Assert.Equal (-1, tv.GetObjectRow (n1));
|
||||
Assert.Null (tv.GetObjectRow (n1_1));
|
||||
Assert.Null (tv.GetObjectRow (n1_2));
|
||||
Assert.Equal (0, tv.GetObjectRow (n2));
|
||||
}
|
||||
[Fact, AutoInitShutdown]
|
||||
public void TestTreeViewColor()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user