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; } } }