mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-29 01:07:58 +01:00
Added interactive scenario (create and delete tree nodes on demand). Added Tag and Text to interface for ITreeNode
This commit is contained in:
@@ -12,11 +12,21 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
public interface ITreeNode
|
||||
{
|
||||
/// <summary>
|
||||
/// Text to display when rendering the node
|
||||
/// </summary>
|
||||
string Text {get;set;}
|
||||
|
||||
/// <summary>
|
||||
/// The children of your class which should be rendered underneath it when expanded
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IList<ITreeNode> Children {get;}
|
||||
|
||||
/// <summary>
|
||||
/// Optionally allows you to store some custom data/class here.
|
||||
/// </summary>
|
||||
object Tag {get;set;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -36,6 +46,11 @@ namespace Terminal.Gui {
|
||||
/// <value></value>
|
||||
public string Text {get;set;}
|
||||
|
||||
/// <summary>
|
||||
/// Optionally allows you to store some custom data/class here.
|
||||
/// </summary>
|
||||
public object Tag {get;set;}
|
||||
|
||||
/// <summary>
|
||||
/// returns <see cref="Text"/>
|
||||
/// </summary>
|
||||
@@ -228,6 +243,7 @@ namespace Terminal.Gui {
|
||||
public TreeView ()
|
||||
{
|
||||
TreeBuilder = new TreeNodeBuilder();
|
||||
AspectGetter = o=>o == null ? "Null" : (o.Text ?? o?.ToString() ?? "Unamed Node");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
150
UICatalog/Scenarios/InteractiveTree.cs
Normal file
150
UICatalog/Scenarios/InteractiveTree.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Terminal.Gui;
|
||||
using static UICatalog.Scenario;
|
||||
|
||||
namespace UICatalog.Scenarios {
|
||||
|
||||
[ScenarioMetadata (Name: "Interactive Tree", Description: "Create nodes and child nodes in TreeView")]
|
||||
[ScenarioCategory ("Controls")]
|
||||
class InteractiveTree : Scenario{
|
||||
|
||||
TreeView treeView;
|
||||
|
||||
public override void Setup ()
|
||||
{
|
||||
Win.Title = this.GetName();
|
||||
Win.Y = 1; // menu
|
||||
Win.Height = Dim.Fill (1); // status bar
|
||||
Top.LayoutSubviews ();
|
||||
|
||||
var menu = new MenuBar (new MenuBarItem [] {
|
||||
new MenuBarItem ("_File", new MenuItem [] {
|
||||
new MenuItem ("_Quit", "", () => Quit()),
|
||||
})
|
||||
});
|
||||
|
||||
treeView = new TreeView() {
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Width = Dim.Fill(),
|
||||
Height = Dim.Fill(1),
|
||||
};
|
||||
treeView.KeyPress += TreeView_KeyPress;
|
||||
|
||||
Win.Add(treeView);
|
||||
|
||||
var statusBar = new StatusBar (new StatusItem [] {
|
||||
new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
|
||||
new StatusItem(Key.CtrlMask | Key.C, "~^C~ Add Child", () => AddChildNode()),
|
||||
new StatusItem(Key.CtrlMask | Key.T, "~^T~ Add Root", () => AddRootNode()),
|
||||
new StatusItem(Key.CtrlMask | Key.R, "~^R~ Rename Node", () => RenameNode()),
|
||||
});
|
||||
Top.Add (statusBar);
|
||||
|
||||
}
|
||||
|
||||
private void TreeView_KeyPress (View.KeyEventEventArgs obj)
|
||||
{
|
||||
if(obj.KeyEvent.Key == Key.DeleteChar) {
|
||||
|
||||
var toDelete = treeView.SelectedObject;
|
||||
|
||||
if(toDelete == null)
|
||||
return;
|
||||
|
||||
obj.Handled = true;
|
||||
|
||||
// if it is a root object remove it
|
||||
if(treeView.Objects.Contains(toDelete)) {
|
||||
treeView.Remove(toDelete);
|
||||
}
|
||||
else {
|
||||
var parent = treeView.GetParent(toDelete);
|
||||
|
||||
if(parent == null)
|
||||
MessageBox.ErrorQuery("Could not delete",$"Parent of '{toDelete}' was unexpectedly null","Ok");
|
||||
else {
|
||||
//update the model
|
||||
parent.Children.Remove(toDelete);
|
||||
|
||||
//refresh the tree
|
||||
treeView.RefreshObject(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RenameNode ()
|
||||
{
|
||||
var node = treeView.SelectedObject;
|
||||
|
||||
if(node != null) {
|
||||
if(GetText("Text","Enter text for node:",node.Text,out string entered)) {
|
||||
node.Text = entered;
|
||||
treeView.RefreshObject(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRootNode ()
|
||||
{
|
||||
if(GetText("Text","Enter text for node:","",out string entered)) {
|
||||
treeView.AddObject(new TreeNode(entered));
|
||||
}
|
||||
}
|
||||
|
||||
private void AddChildNode()
|
||||
{
|
||||
var node = treeView.SelectedObject;
|
||||
|
||||
if(node != null) {
|
||||
if(GetText("Text","Enter text for node:","",out string entered)) {
|
||||
node.Children.Add(new TreeNode(entered));
|
||||
treeView.RefreshObject(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool GetText(string title, string label, string initialText, out string enteredText)
|
||||
{
|
||||
bool okPressed = false;
|
||||
|
||||
var ok = new Button ("Ok", is_default: true);
|
||||
ok.Clicked += () => { okPressed = true; Application.RequestStop (); };
|
||||
var cancel = new Button ("Cancel");
|
||||
cancel.Clicked += () => { Application.RequestStop (); };
|
||||
var d = new Dialog (title, 60, 20, ok, cancel);
|
||||
|
||||
var lbl = new Label() {
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Text = label
|
||||
};
|
||||
|
||||
var tf = new TextField()
|
||||
{
|
||||
Text = initialText,
|
||||
X = 0,
|
||||
Y = 2,
|
||||
Width = Dim.Fill()
|
||||
};
|
||||
|
||||
d.Add (lbl,tf);
|
||||
tf.SetFocus();
|
||||
|
||||
Application.Run (d);
|
||||
|
||||
enteredText = okPressed? tf.Text.ToString() : null;
|
||||
return okPressed;
|
||||
}
|
||||
|
||||
private void Quit ()
|
||||
{
|
||||
Application.RequestStop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace UICatalog.Scenarios {
|
||||
}
|
||||
|
||||
// Your data class
|
||||
private class House : ITreeNode {
|
||||
private class House : TreeNode {
|
||||
|
||||
|
||||
// Your properties
|
||||
@@ -59,14 +59,10 @@ namespace UICatalog.Scenarios {
|
||||
return Address;
|
||||
}
|
||||
}
|
||||
private class Room : ITreeNode{
|
||||
private class Room : TreeNode{
|
||||
|
||||
public string Name {get;set;}
|
||||
|
||||
|
||||
// Rooms have no sub objects
|
||||
public IList<ITreeNode> Children => new List<ITreeNode>();
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return Name;
|
||||
|
||||
@@ -34,7 +34,7 @@ Having to create a bunch of TreeNode objects can be a pain especially if you alr
|
||||
|
||||
```csharp
|
||||
// Your data class
|
||||
private class House : ITreeNode {
|
||||
private class House : TreeNode {
|
||||
|
||||
|
||||
// Your properties
|
||||
@@ -52,7 +52,7 @@ private class House : ITreeNode {
|
||||
}
|
||||
|
||||
// Your other data class
|
||||
private class Room : ITreeNode{
|
||||
private class Room : TreeNode{
|
||||
|
||||
public string Name {get;set;}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user