Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
2 using System.Collections.Generic;
3 using System.Collections.ObjectModel;
4 using System.ComponentModel;
6 using System.Security.Permissions;
7 using System.Threading;
8 using System.Windows.Forms;
9 using System.Collections;
11 using Aga.Controls.Tree.NodeControls;
12 using Aga.Controls.Threading;
15 namespace Aga.Controls.Tree
18 /// Extensible advanced <see cref="TreeView"/> implemented in 100% managed C# code.
19 /// Features: Model/View architecture. Multiple column per node. Ability to select
20 /// multiple tree nodes. Different types of controls for each node column:
21 /// <see cref="CheckBox"/>, Icon, Label... Drag and Drop highlighting. Load on
22 /// demand of nodes. Incremental search of nodes.
24 public partial class TreeViewAdv : Control
26 private const int LeftMargin = 7;
27 internal const int ItemDragSensivity = 4;
28 private readonly int _columnHeaderHeight;
29 private const int DividerWidth = 9;
30 private const int DividerCorrectionGap = -2;
34 private bool _suspendUpdate;
35 private bool _needFullUpdate;
36 private bool _fireSelectionEvent;
37 private NodePlusMinus _plusMinus;
38 private ToolTip _toolTip;
39 private DrawContext _measureContext;
40 private TreeColumn _hotColumn;
41 private IncrementalSearch _search;
42 private List<TreeNodeAdv> _expandingNodes = new List<TreeNodeAdv>();
43 private AbortableThreadPool _threadPool = new AbortableThreadPool();
48 public event ItemDragEventHandler ItemDrag;
49 private void OnItemDrag(MouseButtons buttons, object item)
52 ItemDrag(this, new ItemDragEventArgs(buttons, item));
55 [Category("Behavior")]
56 public event EventHandler<TreeNodeAdvMouseEventArgs> NodeMouseClick;
57 private void OnNodeMouseClick(TreeNodeAdvMouseEventArgs args)
59 if (NodeMouseClick != null)
60 NodeMouseClick(this, args);
63 [Category("Behavior")]
64 public event EventHandler<TreeNodeAdvMouseEventArgs> NodeMouseDoubleClick;
65 private void OnNodeMouseDoubleClick(TreeNodeAdvMouseEventArgs args)
67 if (NodeMouseDoubleClick != null)
68 NodeMouseDoubleClick(this, args);
71 [Category("Behavior")]
72 public event EventHandler<TreeColumnEventArgs> ColumnWidthChanged;
73 internal void OnColumnWidthChanged(TreeColumn column)
75 if (ColumnWidthChanged != null)
76 ColumnWidthChanged(this, new TreeColumnEventArgs(column));
79 [Category("Behavior")]
80 public event EventHandler<TreeColumnEventArgs> ColumnReordered;
81 internal void OnColumnReordered(TreeColumn column)
83 if (ColumnReordered != null)
84 ColumnReordered(this, new TreeColumnEventArgs(column));
87 [Category("Behavior")]
88 public event EventHandler<TreeColumnEventArgs> ColumnClicked;
89 internal void OnColumnClicked(TreeColumn column)
91 if (ColumnClicked != null)
92 ColumnClicked(this, new TreeColumnEventArgs(column));
95 [Category("Behavior")]
96 public event EventHandler SelectionChanged;
97 internal void OnSelectionChanged()
99 if (SuspendSelectionEvent)
100 _fireSelectionEvent = true;
103 _fireSelectionEvent = false;
104 if (SelectionChanged != null)
105 SelectionChanged(this, EventArgs.Empty);
109 [Category("Behavior")]
110 public event EventHandler<TreeViewAdvEventArgs> Collapsing;
111 private void OnCollapsing(TreeNodeAdv node)
113 if (Collapsing != null)
114 Collapsing(this, new TreeViewAdvEventArgs(node));
117 [Category("Behavior")]
118 public event EventHandler<TreeViewAdvEventArgs> Collapsed;
119 private void OnCollapsed(TreeNodeAdv node)
121 if (Collapsed != null)
122 Collapsed(this, new TreeViewAdvEventArgs(node));
125 [Category("Behavior")]
126 public event EventHandler<TreeViewAdvEventArgs> Expanding;
127 private void OnExpanding(TreeNodeAdv node)
129 if (Expanding != null)
130 Expanding(this, new TreeViewAdvEventArgs(node));
133 [Category("Behavior")]
134 public event EventHandler<TreeViewAdvEventArgs> Expanded;
135 private void OnExpanded(TreeNodeAdv node)
137 if (Expanded != null)
138 Expanded(this, new TreeViewAdvEventArgs(node));
141 [Category("Behavior")]
142 public event EventHandler GridLineStyleChanged;
143 private void OnGridLineStyleChanged()
145 if (GridLineStyleChanged != null)
146 GridLineStyleChanged(this, EventArgs.Empty);
149 [Category("Behavior")]
150 public event ScrollEventHandler Scroll;
151 protected virtual void OnScroll(ScrollEventArgs e)
157 [Category("Behavior")]
158 public event EventHandler<TreeViewRowDrawEventArgs> RowDraw;
159 protected virtual void OnRowDraw(PaintEventArgs e, TreeNodeAdv node, DrawContext context, int row, Rectangle rowRect)
163 TreeViewRowDrawEventArgs args = new TreeViewRowDrawEventArgs(e.Graphics, e.ClipRectangle, node, context, row, rowRect);
169 /// Fires when control is going to draw. Can be used to change text or back color
171 [Category("Behavior")]
172 public event EventHandler<DrawEventArgs> DrawControl;
174 internal bool DrawControlMustBeFired()
176 return DrawControl != null;
179 internal void FireDrawControl(DrawEventArgs args)
184 protected virtual void OnDrawControl(DrawEventArgs args)
186 if (DrawControl != null)
187 DrawControl(this, args);
191 [Category("Drag Drop")]
192 public event EventHandler<DropNodeValidatingEventArgs> DropNodeValidating;
193 protected virtual void OnDropNodeValidating(Point point, ref TreeNodeAdv node)
195 if (DropNodeValidating != null)
197 DropNodeValidatingEventArgs args = new DropNodeValidatingEventArgs(point, node);
198 DropNodeValidating(this, args);
206 InitializeComponent();
207 SetStyle(ControlStyles.AllPaintingInWmPaint
208 | ControlStyles.UserPaint
209 | ControlStyles.OptimizedDoubleBuffer
210 | ControlStyles.ResizeRedraw
211 | ControlStyles.Selectable
215 if (Application.RenderWithVisualStyles)
216 _columnHeaderHeight = 20;
218 _columnHeaderHeight = 17;
220 //BorderStyle = BorderStyle.Fixed3D;
221 _hScrollBar.Height = SystemInformation.HorizontalScrollBarHeight;
222 _vScrollBar.Width = SystemInformation.VerticalScrollBarWidth;
223 _rowLayout = new FixedRowHeightLayout(this, RowHeight);
224 _rowMap = new List<TreeNodeAdv>();
225 _selection = new List<TreeNodeAdv>();
226 _readonlySelection = new ReadOnlyCollection<TreeNodeAdv>(_selection);
227 _columns = new TreeColumnCollection(this);
228 _toolTip = new ToolTip();
230 _measureContext = new DrawContext();
231 _measureContext.Font = Font;
232 _measureContext.Graphics = Graphics.FromImage(new Bitmap(1, 1));
234 Input = new NormalInputState(this);
235 _search = new IncrementalSearch(this);
241 _plusMinus = new NodePlusMinus();
242 _controls = new NodeControlsCollection(this);
245 ExpandingIcon.IconChanged += ExpandingIconChanged;
248 void ExpandingIconChanged(object sender, EventArgs e)
250 if (IsHandleCreated && !IsDisposed)
251 BeginInvoke(new MethodInvoker(DrawIcons));
254 private void DrawIcons()
256 using (Graphics gr = Graphics.FromHwnd(this.Handle))
258 //Apply the same Graphics Transform logic as used in OnPaint.
262 y += ColumnHeaderHeight;
263 if (Columns.Count == 0)
266 int firstRowY = _rowLayout.GetRowBounds(FirstVisibleRow).Y;
269 gr.TranslateTransform(-OffsetX, y);
271 DrawContext context = new DrawContext();
272 context.Graphics = gr;
273 for (int i = 0; i < _expandingNodes.Count; i++)
275 foreach (NodeControlInfo item in GetNodeControls(_expandingNodes[i]))
277 if (item.Control is ExpandingIcon)
279 Rectangle bounds = item.Bounds;
280 if (item.Node.Parent == null && UseColumns)
281 bounds.Location = Point.Empty; // display root expanding icon at 0,0
283 context.Bounds = bounds;
284 item.Control.Draw(item.Node, context);
291 #region Public Methods
293 public TreePath GetPath(TreeNodeAdv node)
296 return TreePath.Empty;
299 Stack<object> stack = new Stack<object>();
300 while (node != _root && node != null)
302 stack.Push(node.Tag);
305 return new TreePath(stack.ToArray());
309 public TreeNodeAdv GetNodeAt(Point point)
311 NodeControlInfo info = GetNodeControlInfoAt(point);
315 public NodeControlInfo GetNodeControlInfoAt(Point point)
317 if (point.X < 0 || point.Y < 0)
318 return NodeControlInfo.Empty;
320 int row = _rowLayout.GetRowAt(point);
321 if (row < RowCount && row >= 0)
322 return GetNodeControlInfoAt(RowMap[row], point);
324 return NodeControlInfo.Empty;
327 private NodeControlInfo GetNodeControlInfoAt(TreeNodeAdv node, Point point)
329 Rectangle rect = _rowLayout.GetRowBounds(FirstVisibleRow);
330 point.Y += (rect.Y - ColumnHeaderHeight);
332 foreach (NodeControlInfo info in GetNodeControls(node))
333 if (info.Bounds.Contains(point))
337 return new NodeControlInfo(null, Rectangle.Empty, node);
339 return NodeControlInfo.Empty;
342 public void BeginUpdate()
344 _suspendUpdate = true;
345 SuspendSelectionEvent = true;
348 public void EndUpdate()
350 _suspendUpdate = false;
355 SuspendSelectionEvent = false;
358 public void ExpandAll()
363 public void CollapseAll()
369 /// Expand all parent nodes, andd scroll to the specified node
371 public void EnsureVisible(TreeNodeAdv node)
374 throw new ArgumentNullException("node");
377 throw new ArgumentException();
379 TreeNodeAdv parent = node.Parent;
380 while (parent != _root)
382 parent.IsExpanded = true;
383 parent = parent.Parent;
389 /// Make node visible, scroll if needed. All parent nodes of the specified node must be expanded
391 /// <param name="node"></param>
392 public void ScrollTo(TreeNodeAdv node)
395 throw new ArgumentNullException("node");
398 throw new ArgumentException();
405 if (node.Row < FirstVisibleRow)
409 int pageStart = _rowLayout.GetRowBounds(FirstVisibleRow).Top;
410 int rowBottom = _rowLayout.GetRowBounds(node.Row).Bottom;
411 if (rowBottom > pageStart + DisplayRectangle.Height - ColumnHeaderHeight)
412 row = _rowLayout.GetFirstRow(node.Row);
415 if (row >= _vScrollBar.Minimum && row <= _vScrollBar.Maximum)
416 _vScrollBar.Value = row;
419 public void ClearSelection()
424 ClearSelectionInternal();
432 internal void ClearSelectionInternal()
434 while (Selection.Count > 0)
436 var t = Selection[0];
437 t.IsSelected = false;
438 Selection.Remove(t); //hack
444 protected override void OnSizeChanged(EventArgs e)
447 SafeUpdateScrollBars();
448 base.OnSizeChanged(e);
451 private void ArrangeControls()
453 int hBarSize = _hScrollBar.Height;
454 int vBarSize = _vScrollBar.Width;
455 Rectangle clientRect = ClientRectangle;
457 _hScrollBar.SetBounds(clientRect.X, clientRect.Bottom - hBarSize,
458 clientRect.Width - vBarSize, hBarSize);
460 _vScrollBar.SetBounds(clientRect.Right - vBarSize, clientRect.Y,
461 vBarSize, clientRect.Height - hBarSize);
464 private void SafeUpdateScrollBars()
467 BeginInvoke(new MethodInvoker(UpdateScrollBars));
472 private void UpdateScrollBars()
478 _hScrollBar.Width = DisplayRectangle.Width;
479 _vScrollBar.Height = DisplayRectangle.Height;
482 private void UpdateHScrollBar()
484 _hScrollBar.Maximum = ContentWidth;
485 _hScrollBar.LargeChange = Math.Max(DisplayRectangle.Width, 0);
486 _hScrollBar.SmallChange = 5;
487 _hScrollBar.Visible = _hScrollBar.LargeChange < _hScrollBar.Maximum;
488 _hScrollBar.Value = Math.Min(_hScrollBar.Value, _hScrollBar.Maximum - _hScrollBar.LargeChange + 1);
491 private void UpdateVScrollBar()
493 _vScrollBar.Maximum = Math.Max(RowCount - 1, 0);
494 _vScrollBar.LargeChange = _rowLayout.PageRowCount;
495 _vScrollBar.Visible = (RowCount > 0) && (_vScrollBar.LargeChange <= _vScrollBar.Maximum);
496 _vScrollBar.Value = Math.Min(_vScrollBar.Value, _vScrollBar.Maximum - _vScrollBar.LargeChange + 1);
499 protected override CreateParams CreateParams
501 [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
504 CreateParams res = base.CreateParams;
507 case BorderStyle.FixedSingle:
508 res.Style |= 0x800000;
510 case BorderStyle.Fixed3D:
511 res.ExStyle |= 0x200;
518 protected override void OnGotFocus(EventArgs e)
525 protected override void OnFontChanged(EventArgs e)
527 base.OnFontChanged(e);
528 _measureContext.Font = Font;
532 internal IEnumerable<NodeControlInfo> GetNodeControls(TreeNodeAdv node)
536 Rectangle rowRect = _rowLayout.GetRowBounds(node.Row);
537 foreach (NodeControlInfo n in GetNodeControls(node, rowRect))
541 internal IEnumerable<NodeControlInfo> GetNodeControls(TreeNodeAdv node, Rectangle rowRect)
547 int x = (node.Level - 1) * _indent + LeftMargin;
549 if (node.Row == 0 && ShiftFirstNode)
551 Rectangle rect = Rectangle.Empty;
555 width = _plusMinus.GetActualSize(node, _measureContext).Width;
556 rect = new Rectangle(x, y, width, rowRect.Height);
557 if (UseColumns && Columns.Count > 0 && Columns[0].Width < rect.Right)
558 rect.Width = Columns[0].Width - x;
560 yield return new NodeControlInfo(_plusMinus, rect, node);
566 foreach (NodeControl c in NodeControls)
568 Size s = c.GetActualSize(node, _measureContext);
572 rect = new Rectangle(x, y, width, rowRect.Height);
574 yield return new NodeControlInfo(c, rect, node);
581 foreach (TreeColumn col in Columns)
583 if (col.IsVisible && col.Width > 0)
586 for (int i = 0; i < NodeControls.Count; i++)
588 NodeControl nc = NodeControls[i];
589 if (nc.ParentColumn == col)
591 Size s = nc.GetActualSize(node, _measureContext);
594 bool isLastControl = true;
595 for (int k = i + 1; k < NodeControls.Count; k++)
596 if (NodeControls[k].ParentColumn == col)
598 isLastControl = false;
605 int maxWidth = Math.Max(0, right - x);
606 rect = new Rectangle(x, y, Math.Min(maxWidth, width), rowRect.Height);
608 yield return new NodeControlInfo(nc, rect, node);
618 internal static double Dist(Point p1, Point p2)
620 return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
623 public void FullUpdate()
627 BeginInvoke(new MethodInvoker(UnsafeFullUpdate));
632 private void UnsafeFullUpdate()
634 _rowLayout.ClearCache();
636 SafeUpdateScrollBars();
638 _needFullUpdate = false;
641 internal void UpdateView()
647 internal void UpdateHeaders()
649 Invalidate(new Rectangle(0, 0, Width, ColumnHeaderHeight));
652 internal void UpdateColumns()
657 private void CreateNodes()
660 SelectionStart = null;
661 _root = new TreeNodeAdv(this, null);
662 _root.IsExpanded = true;
663 if (_root.Nodes.Count > 0)
664 CurrentNode = _root.Nodes[0];
669 internal void ReadChilds(TreeNodeAdv parentNode)
671 ReadChilds(parentNode, false);
674 internal void ReadChilds(TreeNodeAdv parentNode, bool performFullUpdate)
676 if (!parentNode.IsLeaf)
678 parentNode.IsExpandedOnce = true;
679 parentNode.Nodes.Clear();
683 IEnumerable items = Model.GetChildren(GetPath(parentNode));
685 foreach (object obj in items)
687 AddNewNode(parentNode, obj, -1);
688 if (performFullUpdate)
693 if (parentNode.AutoExpandOnStructureChanged)
694 parentNode.ExpandAll();
698 private void AddNewNode(TreeNodeAdv parent, object tag, int index)
700 TreeNodeAdv node = new TreeNodeAdv(this, tag);
701 AddNode(parent, index, node);
704 private void AddNode(TreeNodeAdv parent, int index, TreeNodeAdv node)
706 if (index >= 0 && index < parent.Nodes.Count)
707 parent.Nodes.Insert(index, node);
709 parent.Nodes.Add(node);
711 node.IsLeaf = Model.IsLeaf(GetPath(node));
714 if (!LoadOnDemand || node.IsExpandedOnce)
718 private struct ExpandArgs
720 public TreeNodeAdv Node;
722 public bool IgnoreChildren;
725 public void AbortBackgroundExpandingThreads()
727 _threadPool.CancelAll(true);
728 for (int i = 0; i < _expandingNodes.Count; i++)
729 _expandingNodes[i].IsExpandingNow = false;
730 _expandingNodes.Clear();
734 internal void SetIsExpanded(TreeNodeAdv node, bool value, bool ignoreChildren)
736 ExpandArgs eargs = new ExpandArgs();
739 eargs.IgnoreChildren = ignoreChildren;
741 if (AsyncExpanding && LoadOnDemand && !_threadPool.IsMyThread(Thread.CurrentThread))
743 WaitCallback wc = delegate(object argument) { SetIsExpanded((ExpandArgs)argument); };
744 _threadPool.QueueUserWorkItem(wc, eargs);
747 SetIsExpanded(eargs);
750 private void SetIsExpanded(ExpandArgs eargs)
752 bool update = !eargs.IgnoreChildren && !AsyncExpanding;
757 if (IsMyNode(eargs.Node) && eargs.Node.IsExpanded != eargs.Value)
758 SetIsExpanded(eargs.Node, eargs.Value);
760 if (!eargs.IgnoreChildren)
761 SetIsExpandedRecursive(eargs.Node, eargs.Value);
770 internal void SetIsExpanded(TreeNodeAdv node, bool value)
772 if (Root == node && !value)
773 return; //Can't collapse root node
786 if (value && !node.IsExpandedOnce)
788 if (AsyncExpanding && LoadOnDemand)
790 AddExpandingNode(node);
791 node.AssignIsExpanded(true);
794 ReadChilds(node, AsyncExpanding);
795 RemoveExpandingNode(node);
797 node.AssignIsExpanded(value);
812 private void RemoveExpandingNode(TreeNodeAdv node)
814 node.IsExpandingNow = false;
815 _expandingNodes.Remove(node);
816 if (_expandingNodes.Count <= 0)
817 ExpandingIcon.Stop();
820 private void AddExpandingNode(TreeNodeAdv node)
822 node.IsExpandingNow = true;
823 _expandingNodes.Add(node);
824 ExpandingIcon.Start();
827 internal void SetIsExpandedRecursive(TreeNodeAdv root, bool value)
829 for (int i = 0; i < root.Nodes.Count; i++)
831 TreeNodeAdv node = root.Nodes[i];
832 node.IsExpanded = value;
833 SetIsExpandedRecursive(node, value);
837 private void CreateRowMap()
842 foreach (TreeNodeAdv node in VisibleNodes)
848 _contentWidth = Math.Max(_contentWidth, GetNodeWidth(node));
855 foreach (TreeColumn col in _columns)
857 _contentWidth += col.Width;
861 private int GetNodeWidth(TreeNodeAdv node)
863 if (node.RightBounds == null)
865 Rectangle res = GetNodeBounds(GetNodeControls(node, Rectangle.Empty));
866 node.RightBounds = res.Right;
868 return node.RightBounds.Value;
871 internal Rectangle GetNodeBounds(TreeNodeAdv node)
873 return GetNodeBounds(GetNodeControls(node));
876 private Rectangle GetNodeBounds(IEnumerable<NodeControlInfo> nodeControls)
878 Rectangle res = Rectangle.Empty;
879 foreach (NodeControlInfo info in nodeControls)
881 if (res == Rectangle.Empty)
884 res = Rectangle.Union(res, info.Bounds);
889 private void _vScrollBar_ValueChanged(object sender, EventArgs e)
891 FirstVisibleRow = _vScrollBar.Value;
894 private void _hScrollBar_ValueChanged(object sender, EventArgs e)
896 OffsetX = _hScrollBar.Value;
899 private void _vScrollBar_Scroll(object sender, ScrollEventArgs e)
904 private void _hScrollBar_Scroll(object sender, ScrollEventArgs e)
909 internal void SmartFullUpdate()
912 _needFullUpdate = true;
917 internal bool IsMyNode(TreeNodeAdv node)
922 if (node.Tree != this)
925 while (node.Parent != null)
928 return node == _root;
931 internal void UpdateSelection()
935 if (!IsMyNode(CurrentNode))
937 if (!IsMyNode(_selectionStart))
938 _selectionStart = null;
940 for (int i = Selection.Count - 1; i >= 0; i--)
941 if (!IsMyNode(Selection[i]))
944 Selection.RemoveAt(i);
948 OnSelectionChanged();
951 internal void ChangeColumnWidth(TreeColumn column)
953 if (!(_input is ResizeColumnState))
956 OnColumnWidthChanged(column);
960 public TreeNodeAdv FindNode(TreePath path)
962 return FindNode(path, false);
965 public TreeNodeAdv FindNode(TreePath path, bool readChilds)
970 return FindNode(_root, path, 0, readChilds);
973 private TreeNodeAdv FindNode(TreeNodeAdv root, TreePath path, int level, bool readChilds)
975 if (!root.IsExpandedOnce && readChilds)
978 for (int i = 0; i < root.Nodes.Count; i++)
980 TreeNodeAdv node = root.Nodes[i];
981 if (node.Tag == path.FullPath[level])
983 if (level == path.FullPath.Length - 1)
986 return FindNode(node, path, level + 1, readChilds);
992 public TreeNodeAdv FindNodeByTag(object tag)
994 return FindNodeByTag(_root, tag);
997 private TreeNodeAdv FindNodeByTag(TreeNodeAdv root, object tag)
999 foreach (TreeNodeAdv node in root.Nodes)
1001 if (node.Tag == tag)
1003 TreeNodeAdv res = FindNodeByTag(node, tag);
1010 public void SelectAllNodes()
1012 SuspendSelectionEvent = true;
1015 if (SelectionMode == TreeSelectionMode.MultiSameParent)
1017 if (CurrentNode != null)
1019 foreach (TreeNodeAdv n in CurrentNode.Parent.Nodes)
1020 n.IsSelected = true;
1023 else if (SelectionMode == TreeSelectionMode.Multi)
1025 SelectNodes(Root.Nodes);
1030 SuspendSelectionEvent = false;
1034 private void SelectNodes(Collection<TreeNodeAdv> nodes)
1036 foreach (TreeNodeAdv n in nodes)
1038 n.IsSelected = true;
1040 SelectNodes(n.Nodes);
1045 private void BindModelEvents()
1047 _model.NodesChanged += new EventHandler<TreeModelEventArgs>(_model_NodesChanged);
1048 _model.NodesInserted += new EventHandler<TreeModelEventArgs>(_model_NodesInserted);
1049 _model.NodesRemoved += new EventHandler<TreeModelEventArgs>(_model_NodesRemoved);
1050 _model.StructureChanged += new EventHandler<TreePathEventArgs>(_model_StructureChanged);
1053 private void UnbindModelEvents()
1055 _model.NodesChanged -= new EventHandler<TreeModelEventArgs>(_model_NodesChanged);
1056 _model.NodesInserted -= new EventHandler<TreeModelEventArgs>(_model_NodesInserted);
1057 _model.NodesRemoved -= new EventHandler<TreeModelEventArgs>(_model_NodesRemoved);
1058 _model.StructureChanged -= new EventHandler<TreePathEventArgs>(_model_StructureChanged);
1061 private void _model_StructureChanged(object sender, TreePathEventArgs e)
1064 throw new ArgumentNullException();
1066 TreeNodeAdv node = FindNode(e.Path);
1070 node.IsLeaf = Model.IsLeaf(GetPath(node));
1072 var list = new Dictionary<object, object>();
1073 SaveExpandedNodes(node, list);
1075 RestoreExpandedNodes(node, list);
1081 // throw new ArgumentException("Path not found");
1084 private void RestoreExpandedNodes(TreeNodeAdv node, Dictionary<object, object> list)
1086 if (node.Tag != null && list.ContainsKey(node.Tag))
1088 node.IsExpanded = true;
1089 foreach (var child in node.Children)
1090 RestoreExpandedNodes(child, list);
1094 private void SaveExpandedNodes(TreeNodeAdv node, Dictionary<object, object> list)
1096 if (node.IsExpanded && node.Tag != null)
1098 list.Add(node.Tag, null);
1099 foreach (var child in node.Children)
1100 SaveExpandedNodes(child, list);
1104 private void _model_NodesRemoved(object sender, TreeModelEventArgs e)
1106 TreeNodeAdv parent = FindNode(e.Path);
1109 if (e.Indices != null)
1111 List<int> list = new List<int>(e.Indices);
1113 for (int n = list.Count - 1; n >= 0; n--)
1115 int index = list[n];
1116 if (index >= 0 && index <= parent.Nodes.Count)
1117 parent.Nodes.RemoveAt(index);
1119 throw new ArgumentOutOfRangeException("Index out of range");
1124 for (int i = parent.Nodes.Count - 1; i >= 0; i--)
1126 for (int n = 0; n < e.Children.Length; n++)
1127 if (parent.Nodes[i].Tag == e.Children[n])
1129 parent.Nodes.RemoveAt(i);
1139 private void _model_NodesInserted(object sender, TreeModelEventArgs e)
1141 if (e.Indices == null)
1142 throw new ArgumentNullException("Indices");
1144 TreeNodeAdv parent = FindNode(e.Path);
1147 for (int i = 0; i < e.Children.Length; i++)
1148 AddNewNode(parent, e.Children[i], e.Indices[i]);
1153 private void _model_NodesChanged(object sender, TreeModelEventArgs e)
1155 TreeNodeAdv parent = FindNode(e.Path);
1156 if (parent != null && parent.IsVisible && parent.IsExpanded)
1159 BeginInvoke(new UpdateContentWidthDelegate(ClearNodesSize), e, parent);
1161 ClearNodesSize(e, parent);
1166 private delegate void UpdateContentWidthDelegate(TreeModelEventArgs e, TreeNodeAdv parent);
1167 private void ClearNodesSize(TreeModelEventArgs e, TreeNodeAdv parent)
1169 if (e.Indices != null)
1171 foreach (int index in e.Indices)
1173 if (index >= 0 && index < parent.Nodes.Count)
1175 TreeNodeAdv node = parent.Nodes[index];
1176 node.Height = node.RightBounds = null;
1179 throw new ArgumentOutOfRangeException("Index out of range");
1184 foreach (TreeNodeAdv node in parent.Nodes)
1186 foreach (object obj in e.Children)
1187 if (node.Tag == obj)
1189 node.Height = node.RightBounds = null;