using System;
using System.Linq;
using Gwen.ControlInternal;
namespace Gwen.Control
{
///
/// Tree control node.
///
public class TreeNode : Base
{
public const int TreeIndentation = 14;
protected TreeControl m_TreeControl;
protected Button m_ToggleButton;
protected Button m_Title;
private bool m_Root;
private bool m_Selected;
private bool m_Selectable;
///
/// Indicates whether this is a root node.
///
public bool IsRoot { get { return m_Root; } set { m_Root = value; } }
///
/// Parent tree control.
///
public TreeControl TreeControl { get { return m_TreeControl; } set { m_TreeControl = value; } }
///
/// Determines whether the node is selectable.
///
public bool IsSelectable { get { return m_Selectable; } set { m_Selectable = value; } }
///
/// Indicates whether the node is selected.
///
public bool IsSelected
{
get { return m_Selected; }
set
{
if (!IsSelectable)
return;
if (IsSelected == value)
return;
m_Selected = value;
if (m_Title != null)
m_Title.ToggleState = value;
if (SelectionChanged != null)
SelectionChanged.Invoke(this);
// propagate to root parent (tree)
if (m_TreeControl != null && m_TreeControl.SelectionChanged != null)
m_TreeControl.SelectionChanged.Invoke(this);
if (value)
{
if (Selected != null)
Selected.Invoke(this);
if (m_TreeControl != null && m_TreeControl.Selected != null)
m_TreeControl.Selected.Invoke(this);
}
else
{
if (Unselected != null)
Unselected.Invoke(this);
if (m_TreeControl != null && m_TreeControl.Unselected != null)
m_TreeControl.Unselected.Invoke(this);
}
}
}
///
/// Node's label.
///
public String Text { get { return m_Title.Text; } set { m_Title.Text = value; } }
///
/// Invoked when the node label has been pressed.
///
public event GwenEventHandler LabelPressed;
///
/// Invoked when the node's selected state has changed.
///
public event GwenEventHandler SelectionChanged;
///
/// Invoked when the node has been selected.
///
public event GwenEventHandler Selected;
///
/// Invoked when the node has been unselected.
///
public event GwenEventHandler Unselected;
///
/// Invoked when the node has been expanded.
///
public event GwenEventHandler Expanded;
///
/// Invoked when the node has been collapsed.
///
public event GwenEventHandler Collapsed;
///
/// Initializes a new instance of the class.
///
/// Parent control.
public TreeNode(Base parent)
: base(parent)
{
m_ToggleButton = new TreeToggleButton(this);
m_ToggleButton.SetBounds(0, 0, 15, 15);
m_ToggleButton.Toggled += OnToggleButtonPress;
m_Title = new TreeNodeLabel(this);
m_Title.Dock = Pos.Top;
m_Title.Margin = new Margin(16, 0, 0, 0);
m_Title.DoubleClickedLeft += OnDoubleClickName;
m_Title.Clicked += OnClickName;
m_InnerPanel = new Base(this);
m_InnerPanel.Dock = Pos.Top;
m_InnerPanel.Height = 100;
m_InnerPanel.Margin = new Margin(TreeIndentation, 1, 0, 0);
m_InnerPanel.Hide();
m_Root = false;
m_Selected = false;
m_Selectable = true;
}
///
/// Renders the control using specified skin.
///
/// Skin to use.
protected override void Render(Skin.Base skin)
{
int bottom = 0;
if (m_InnerPanel.Children.Count > 0)
{
bottom = m_InnerPanel.Children.Last().Y + m_InnerPanel.Y;
}
skin.DrawTreeNode(this, m_InnerPanel.IsVisible, IsSelected, m_Title.Height, m_Title.TextRight,
(int)(m_ToggleButton.Y + m_ToggleButton.Height * 0.5f), bottom, m_TreeControl == Parent); // IsRoot
}
///
/// Lays out the control's interior according to alignment, padding, dock etc.
///
/// Skin to use.
protected override void Layout(Skin.Base skin)
{
if (m_ToggleButton != null)
{
if (m_Title != null)
{
m_ToggleButton.SetPosition(0, (m_Title.Height - m_ToggleButton.Height)*0.5f);
}
if (m_InnerPanel.Children.Count == 0)
{
m_ToggleButton.Hide();
m_ToggleButton.ToggleState = false;
m_InnerPanel.Hide();
}
else
{
m_ToggleButton.Show();
m_InnerPanel.SizeToChildren(false, true);
}
}
base.Layout(skin);
}
///
/// Function invoked after layout.
///
/// Skin to use.
protected override void PostLayout(Skin.Base skin)
{
if (SizeToChildren(false, true))
{
InvalidateParent();
}
}
///
/// Adds a new child node.
///
/// Node's label.
/// Newly created control.
public TreeNode AddNode(string label)
{
TreeNode node = new TreeNode(this);
node.Text = label;
node.Dock = Pos.Top;
node.IsRoot = this is TreeControl;
node.TreeControl = m_TreeControl;
if (m_TreeControl != null)
{
m_TreeControl.OnNodeAdded(node);
}
return node;
}
///
/// Opens the node.
///
public void Open()
{
m_InnerPanel.Show();
if (m_ToggleButton != null)
m_ToggleButton.ToggleState = true;
if (Expanded != null)
Expanded.Invoke(this);
if (m_TreeControl != null && m_TreeControl.Expanded != null)
m_TreeControl.Expanded.Invoke(this);
Invalidate();
}
///
/// Closes the node.
///
public void Close()
{
m_InnerPanel.Hide();
if (m_ToggleButton != null)
m_ToggleButton.ToggleState = false;
if (Collapsed != null)
Collapsed.Invoke(this);
if (m_TreeControl != null && m_TreeControl.Collapsed != null)
m_TreeControl.Collapsed.Invoke(this);
Invalidate();
}
///
/// Opens the node and all child nodes.
///
public void ExpandAll()
{
Open();
foreach (Base child in Children)
{
TreeNode node = child as TreeNode;
if (node == null)
continue;
node.ExpandAll();
}
}
///
/// Clears the selection on the node and all child nodes.
///
public void UnselectAll()
{
IsSelected = false;
if (m_Title != null)
m_Title.ToggleState = false;
foreach (Base child in Children)
{
TreeNode node = child as TreeNode;
if (node == null)
continue;
node.UnselectAll();
}
}
///
/// Handler for the toggle button.
///
/// Event source.
protected virtual void OnToggleButtonPress(Base control)
{
if (m_ToggleButton.ToggleState)
{
Open();
}
else
{
Close();
}
}
///
/// Handler for label double click.
///
/// Event source.
protected virtual void OnDoubleClickName(Base control)
{
if (!m_ToggleButton.IsVisible)
return;
m_ToggleButton.Toggle();
}
///
/// Handler for label click.
///
/// Event source.
protected virtual void OnClickName(Base control)
{
if (LabelPressed != null)
LabelPressed.Invoke(this);
IsSelected = !IsSelected;
}
}
}