1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/External/Aga.Controls/Tree/TreeViewAdv.cs Sun May 27 15:16:19 2012 +0000
1.3 @@ -0,0 +1,1196 @@
1.4 +using System;
1.5 +using System.Collections.Generic;
1.6 +using System.Collections.ObjectModel;
1.7 +using System.ComponentModel;
1.8 +using System.Drawing;
1.9 +using System.Security.Permissions;
1.10 +using System.Threading;
1.11 +using System.Windows.Forms;
1.12 +using System.Collections;
1.13 +
1.14 +using Aga.Controls.Tree.NodeControls;
1.15 +using Aga.Controls.Threading;
1.16 +
1.17 +
1.18 +namespace Aga.Controls.Tree
1.19 +{
1.20 + /// <summary>
1.21 + /// Extensible advanced <see cref="TreeView"/> implemented in 100% managed C# code.
1.22 + /// Features: Model/View architecture. Multiple column per node. Ability to select
1.23 + /// multiple tree nodes. Different types of controls for each node column:
1.24 + /// <see cref="CheckBox"/>, Icon, Label... Drag and Drop highlighting. Load on
1.25 + /// demand of nodes. Incremental search of nodes.
1.26 + /// </summary>
1.27 + public partial class TreeViewAdv : Control
1.28 + {
1.29 + private const int LeftMargin = 7;
1.30 + internal const int ItemDragSensivity = 4;
1.31 + private readonly int _columnHeaderHeight;
1.32 + private const int DividerWidth = 9;
1.33 + private const int DividerCorrectionGap = -2;
1.34 +
1.35 + private Pen _linePen;
1.36 + private Pen _markPen;
1.37 + private bool _suspendUpdate;
1.38 + private bool _needFullUpdate;
1.39 + private bool _fireSelectionEvent;
1.40 + private NodePlusMinus _plusMinus;
1.41 + private ToolTip _toolTip;
1.42 + private DrawContext _measureContext;
1.43 + private TreeColumn _hotColumn;
1.44 + private IncrementalSearch _search;
1.45 + private List<TreeNodeAdv> _expandingNodes = new List<TreeNodeAdv>();
1.46 + private AbortableThreadPool _threadPool = new AbortableThreadPool();
1.47 +
1.48 + #region Public Events
1.49 +
1.50 + [Category("Action")]
1.51 + public event ItemDragEventHandler ItemDrag;
1.52 + private void OnItemDrag(MouseButtons buttons, object item)
1.53 + {
1.54 + if (ItemDrag != null)
1.55 + ItemDrag(this, new ItemDragEventArgs(buttons, item));
1.56 + }
1.57 +
1.58 + [Category("Behavior")]
1.59 + public event EventHandler<TreeNodeAdvMouseEventArgs> NodeMouseClick;
1.60 + private void OnNodeMouseClick(TreeNodeAdvMouseEventArgs args)
1.61 + {
1.62 + if (NodeMouseClick != null)
1.63 + NodeMouseClick(this, args);
1.64 + }
1.65 +
1.66 + [Category("Behavior")]
1.67 + public event EventHandler<TreeNodeAdvMouseEventArgs> NodeMouseDoubleClick;
1.68 + private void OnNodeMouseDoubleClick(TreeNodeAdvMouseEventArgs args)
1.69 + {
1.70 + if (NodeMouseDoubleClick != null)
1.71 + NodeMouseDoubleClick(this, args);
1.72 + }
1.73 +
1.74 + [Category("Behavior")]
1.75 + public event EventHandler<TreeColumnEventArgs> ColumnWidthChanged;
1.76 + internal void OnColumnWidthChanged(TreeColumn column)
1.77 + {
1.78 + if (ColumnWidthChanged != null)
1.79 + ColumnWidthChanged(this, new TreeColumnEventArgs(column));
1.80 + }
1.81 +
1.82 + [Category("Behavior")]
1.83 + public event EventHandler<TreeColumnEventArgs> ColumnReordered;
1.84 + internal void OnColumnReordered(TreeColumn column)
1.85 + {
1.86 + if (ColumnReordered != null)
1.87 + ColumnReordered(this, new TreeColumnEventArgs(column));
1.88 + }
1.89 +
1.90 + [Category("Behavior")]
1.91 + public event EventHandler<TreeColumnEventArgs> ColumnClicked;
1.92 + internal void OnColumnClicked(TreeColumn column)
1.93 + {
1.94 + if (ColumnClicked != null)
1.95 + ColumnClicked(this, new TreeColumnEventArgs(column));
1.96 + }
1.97 +
1.98 + [Category("Behavior")]
1.99 + public event EventHandler SelectionChanged;
1.100 + internal void OnSelectionChanged()
1.101 + {
1.102 + if (SuspendSelectionEvent)
1.103 + _fireSelectionEvent = true;
1.104 + else
1.105 + {
1.106 + _fireSelectionEvent = false;
1.107 + if (SelectionChanged != null)
1.108 + SelectionChanged(this, EventArgs.Empty);
1.109 + }
1.110 + }
1.111 +
1.112 + [Category("Behavior")]
1.113 + public event EventHandler<TreeViewAdvEventArgs> Collapsing;
1.114 + private void OnCollapsing(TreeNodeAdv node)
1.115 + {
1.116 + if (Collapsing != null)
1.117 + Collapsing(this, new TreeViewAdvEventArgs(node));
1.118 + }
1.119 +
1.120 + [Category("Behavior")]
1.121 + public event EventHandler<TreeViewAdvEventArgs> Collapsed;
1.122 + private void OnCollapsed(TreeNodeAdv node)
1.123 + {
1.124 + if (Collapsed != null)
1.125 + Collapsed(this, new TreeViewAdvEventArgs(node));
1.126 + }
1.127 +
1.128 + [Category("Behavior")]
1.129 + public event EventHandler<TreeViewAdvEventArgs> Expanding;
1.130 + private void OnExpanding(TreeNodeAdv node)
1.131 + {
1.132 + if (Expanding != null)
1.133 + Expanding(this, new TreeViewAdvEventArgs(node));
1.134 + }
1.135 +
1.136 + [Category("Behavior")]
1.137 + public event EventHandler<TreeViewAdvEventArgs> Expanded;
1.138 + private void OnExpanded(TreeNodeAdv node)
1.139 + {
1.140 + if (Expanded != null)
1.141 + Expanded(this, new TreeViewAdvEventArgs(node));
1.142 + }
1.143 +
1.144 + [Category("Behavior")]
1.145 + public event EventHandler GridLineStyleChanged;
1.146 + private void OnGridLineStyleChanged()
1.147 + {
1.148 + if (GridLineStyleChanged != null)
1.149 + GridLineStyleChanged(this, EventArgs.Empty);
1.150 + }
1.151 +
1.152 + [Category("Behavior")]
1.153 + public event ScrollEventHandler Scroll;
1.154 + protected virtual void OnScroll(ScrollEventArgs e)
1.155 + {
1.156 + if (Scroll != null)
1.157 + Scroll(this, e);
1.158 + }
1.159 +
1.160 + [Category("Behavior")]
1.161 + public event EventHandler<TreeViewRowDrawEventArgs> RowDraw;
1.162 + protected virtual void OnRowDraw(PaintEventArgs e, TreeNodeAdv node, DrawContext context, int row, Rectangle rowRect)
1.163 + {
1.164 + if (RowDraw != null)
1.165 + {
1.166 + TreeViewRowDrawEventArgs args = new TreeViewRowDrawEventArgs(e.Graphics, e.ClipRectangle, node, context, row, rowRect);
1.167 + RowDraw(this, args);
1.168 + }
1.169 + }
1.170 +
1.171 + /// <summary>
1.172 + /// Fires when control is going to draw. Can be used to change text or back color
1.173 + /// </summary>
1.174 + [Category("Behavior")]
1.175 + public event EventHandler<DrawEventArgs> DrawControl;
1.176 +
1.177 + internal bool DrawControlMustBeFired()
1.178 + {
1.179 + return DrawControl != null;
1.180 + }
1.181 +
1.182 + internal void FireDrawControl(DrawEventArgs args)
1.183 + {
1.184 + OnDrawControl(args);
1.185 + }
1.186 +
1.187 + protected virtual void OnDrawControl(DrawEventArgs args)
1.188 + {
1.189 + if (DrawControl != null)
1.190 + DrawControl(this, args);
1.191 + }
1.192 +
1.193 +
1.194 + [Category("Drag Drop")]
1.195 + public event EventHandler<DropNodeValidatingEventArgs> DropNodeValidating;
1.196 + protected virtual void OnDropNodeValidating(Point point, ref TreeNodeAdv node)
1.197 + {
1.198 + if (DropNodeValidating != null)
1.199 + {
1.200 + DropNodeValidatingEventArgs args = new DropNodeValidatingEventArgs(point, node);
1.201 + DropNodeValidating(this, args);
1.202 + node = args.Node;
1.203 + }
1.204 + }
1.205 + #endregion
1.206 +
1.207 + public TreeViewAdv()
1.208 + {
1.209 + InitializeComponent();
1.210 + SetStyle(ControlStyles.AllPaintingInWmPaint
1.211 + | ControlStyles.UserPaint
1.212 + | ControlStyles.OptimizedDoubleBuffer
1.213 + | ControlStyles.ResizeRedraw
1.214 + | ControlStyles.Selectable
1.215 + , true);
1.216 +
1.217 +
1.218 + if (Application.RenderWithVisualStyles)
1.219 + _columnHeaderHeight = 20;
1.220 + else
1.221 + _columnHeaderHeight = 17;
1.222 +
1.223 + //BorderStyle = BorderStyle.Fixed3D;
1.224 + _hScrollBar.Height = SystemInformation.HorizontalScrollBarHeight;
1.225 + _vScrollBar.Width = SystemInformation.VerticalScrollBarWidth;
1.226 + _rowLayout = new FixedRowHeightLayout(this, RowHeight);
1.227 + _rowMap = new List<TreeNodeAdv>();
1.228 + _selection = new List<TreeNodeAdv>();
1.229 + _readonlySelection = new ReadOnlyCollection<TreeNodeAdv>(_selection);
1.230 + _columns = new TreeColumnCollection(this);
1.231 + _toolTip = new ToolTip();
1.232 +
1.233 + _measureContext = new DrawContext();
1.234 + _measureContext.Font = Font;
1.235 + _measureContext.Graphics = Graphics.FromImage(new Bitmap(1, 1));
1.236 +
1.237 + Input = new NormalInputState(this);
1.238 + _search = new IncrementalSearch(this);
1.239 + CreateNodes();
1.240 + CreatePens();
1.241 +
1.242 + ArrangeControls();
1.243 +
1.244 + _plusMinus = new NodePlusMinus();
1.245 + _controls = new NodeControlsCollection(this);
1.246 +
1.247 + Font = _font;
1.248 + ExpandingIcon.IconChanged += ExpandingIconChanged;
1.249 + }
1.250 +
1.251 + void ExpandingIconChanged(object sender, EventArgs e)
1.252 + {
1.253 + if (IsHandleCreated && !IsDisposed)
1.254 + BeginInvoke(new MethodInvoker(DrawIcons));
1.255 + }
1.256 +
1.257 + private void DrawIcons()
1.258 + {
1.259 + using (Graphics gr = Graphics.FromHwnd(this.Handle))
1.260 + {
1.261 + //Apply the same Graphics Transform logic as used in OnPaint.
1.262 + int y = 0;
1.263 + if (UseColumns)
1.264 + {
1.265 + y += ColumnHeaderHeight;
1.266 + if (Columns.Count == 0)
1.267 + return;
1.268 + }
1.269 + int firstRowY = _rowLayout.GetRowBounds(FirstVisibleRow).Y;
1.270 + y -= firstRowY;
1.271 + gr.ResetTransform();
1.272 + gr.TranslateTransform(-OffsetX, y);
1.273 +
1.274 + DrawContext context = new DrawContext();
1.275 + context.Graphics = gr;
1.276 + for (int i = 0; i < _expandingNodes.Count; i++)
1.277 + {
1.278 + foreach (NodeControlInfo item in GetNodeControls(_expandingNodes[i]))
1.279 + {
1.280 + if (item.Control is ExpandingIcon)
1.281 + {
1.282 + Rectangle bounds = item.Bounds;
1.283 + if (item.Node.Parent == null && UseColumns)
1.284 + bounds.Location = Point.Empty; // display root expanding icon at 0,0
1.285 +
1.286 + context.Bounds = bounds;
1.287 + item.Control.Draw(item.Node, context);
1.288 + }
1.289 + }
1.290 + }
1.291 + }
1.292 + }
1.293 +
1.294 + #region Public Methods
1.295 +
1.296 + public TreePath GetPath(TreeNodeAdv node)
1.297 + {
1.298 + if (node == _root)
1.299 + return TreePath.Empty;
1.300 + else
1.301 + {
1.302 + Stack<object> stack = new Stack<object>();
1.303 + while (node != _root && node != null)
1.304 + {
1.305 + stack.Push(node.Tag);
1.306 + node = node.Parent;
1.307 + }
1.308 + return new TreePath(stack.ToArray());
1.309 + }
1.310 + }
1.311 +
1.312 + public TreeNodeAdv GetNodeAt(Point point)
1.313 + {
1.314 + NodeControlInfo info = GetNodeControlInfoAt(point);
1.315 + return info.Node;
1.316 + }
1.317 +
1.318 + public NodeControlInfo GetNodeControlInfoAt(Point point)
1.319 + {
1.320 + if (point.X < 0 || point.Y < 0)
1.321 + return NodeControlInfo.Empty;
1.322 +
1.323 + int row = _rowLayout.GetRowAt(point);
1.324 + if (row < RowCount && row >= 0)
1.325 + return GetNodeControlInfoAt(RowMap[row], point);
1.326 + else
1.327 + return NodeControlInfo.Empty;
1.328 + }
1.329 +
1.330 + private NodeControlInfo GetNodeControlInfoAt(TreeNodeAdv node, Point point)
1.331 + {
1.332 + Rectangle rect = _rowLayout.GetRowBounds(FirstVisibleRow);
1.333 + point.Y += (rect.Y - ColumnHeaderHeight);
1.334 + point.X += OffsetX;
1.335 + foreach (NodeControlInfo info in GetNodeControls(node))
1.336 + if (info.Bounds.Contains(point))
1.337 + return info;
1.338 +
1.339 + if (FullRowSelect)
1.340 + return new NodeControlInfo(null, Rectangle.Empty, node);
1.341 + else
1.342 + return NodeControlInfo.Empty;
1.343 + }
1.344 +
1.345 + public void BeginUpdate()
1.346 + {
1.347 + _suspendUpdate = true;
1.348 + SuspendSelectionEvent = true;
1.349 + }
1.350 +
1.351 + public void EndUpdate()
1.352 + {
1.353 + _suspendUpdate = false;
1.354 + if (_needFullUpdate)
1.355 + FullUpdate();
1.356 + else
1.357 + UpdateView();
1.358 + SuspendSelectionEvent = false;
1.359 + }
1.360 +
1.361 + public void ExpandAll()
1.362 + {
1.363 + _root.ExpandAll();
1.364 + }
1.365 +
1.366 + public void CollapseAll()
1.367 + {
1.368 + _root.CollapseAll();
1.369 + }
1.370 +
1.371 + /// <summary>
1.372 + /// Expand all parent nodes, andd scroll to the specified node
1.373 + /// </summary>
1.374 + public void EnsureVisible(TreeNodeAdv node)
1.375 + {
1.376 + if (node == null)
1.377 + throw new ArgumentNullException("node");
1.378 +
1.379 + if (!IsMyNode(node))
1.380 + throw new ArgumentException();
1.381 +
1.382 + TreeNodeAdv parent = node.Parent;
1.383 + while (parent != _root)
1.384 + {
1.385 + parent.IsExpanded = true;
1.386 + parent = parent.Parent;
1.387 + }
1.388 + ScrollTo(node);
1.389 + }
1.390 +
1.391 + /// <summary>
1.392 + /// Make node visible, scroll if needed. All parent nodes of the specified node must be expanded
1.393 + /// </summary>
1.394 + /// <param name="node"></param>
1.395 + public void ScrollTo(TreeNodeAdv node)
1.396 + {
1.397 + if (node == null)
1.398 + throw new ArgumentNullException("node");
1.399 +
1.400 + if (!IsMyNode(node))
1.401 + throw new ArgumentException();
1.402 +
1.403 + if (node.Row < 0)
1.404 + CreateRowMap();
1.405 +
1.406 + int row = -1;
1.407 +
1.408 + if (node.Row < FirstVisibleRow)
1.409 + row = node.Row;
1.410 + else
1.411 + {
1.412 + int pageStart = _rowLayout.GetRowBounds(FirstVisibleRow).Top;
1.413 + int rowBottom = _rowLayout.GetRowBounds(node.Row).Bottom;
1.414 + if (rowBottom > pageStart + DisplayRectangle.Height - ColumnHeaderHeight)
1.415 + row = _rowLayout.GetFirstRow(node.Row);
1.416 + }
1.417 +
1.418 + if (row >= _vScrollBar.Minimum && row <= _vScrollBar.Maximum)
1.419 + _vScrollBar.Value = row;
1.420 + }
1.421 +
1.422 + public void ClearSelection()
1.423 + {
1.424 + BeginUpdate();
1.425 + try
1.426 + {
1.427 + ClearSelectionInternal();
1.428 + }
1.429 + finally
1.430 + {
1.431 + EndUpdate();
1.432 + }
1.433 + }
1.434 +
1.435 + internal void ClearSelectionInternal()
1.436 + {
1.437 + while (Selection.Count > 0)
1.438 + {
1.439 + var t = Selection[0];
1.440 + t.IsSelected = false;
1.441 + Selection.Remove(t); //hack
1.442 + }
1.443 + }
1.444 +
1.445 + #endregion
1.446 +
1.447 + protected override void OnSizeChanged(EventArgs e)
1.448 + {
1.449 + ArrangeControls();
1.450 + SafeUpdateScrollBars();
1.451 + base.OnSizeChanged(e);
1.452 + }
1.453 +
1.454 + private void ArrangeControls()
1.455 + {
1.456 + int hBarSize = _hScrollBar.Height;
1.457 + int vBarSize = _vScrollBar.Width;
1.458 + Rectangle clientRect = ClientRectangle;
1.459 +
1.460 + _hScrollBar.SetBounds(clientRect.X, clientRect.Bottom - hBarSize,
1.461 + clientRect.Width - vBarSize, hBarSize);
1.462 +
1.463 + _vScrollBar.SetBounds(clientRect.Right - vBarSize, clientRect.Y,
1.464 + vBarSize, clientRect.Height - hBarSize);
1.465 + }
1.466 +
1.467 + private void SafeUpdateScrollBars()
1.468 + {
1.469 + if (InvokeRequired)
1.470 + BeginInvoke(new MethodInvoker(UpdateScrollBars));
1.471 + else
1.472 + UpdateScrollBars();
1.473 + }
1.474 +
1.475 + private void UpdateScrollBars()
1.476 + {
1.477 + UpdateVScrollBar();
1.478 + UpdateHScrollBar();
1.479 + UpdateVScrollBar();
1.480 + UpdateHScrollBar();
1.481 + _hScrollBar.Width = DisplayRectangle.Width;
1.482 + _vScrollBar.Height = DisplayRectangle.Height;
1.483 + }
1.484 +
1.485 + private void UpdateHScrollBar()
1.486 + {
1.487 + _hScrollBar.Maximum = ContentWidth;
1.488 + _hScrollBar.LargeChange = Math.Max(DisplayRectangle.Width, 0);
1.489 + _hScrollBar.SmallChange = 5;
1.490 + _hScrollBar.Visible = _hScrollBar.LargeChange < _hScrollBar.Maximum;
1.491 + _hScrollBar.Value = Math.Min(_hScrollBar.Value, _hScrollBar.Maximum - _hScrollBar.LargeChange + 1);
1.492 + }
1.493 +
1.494 + private void UpdateVScrollBar()
1.495 + {
1.496 + _vScrollBar.Maximum = Math.Max(RowCount - 1, 0);
1.497 + _vScrollBar.LargeChange = _rowLayout.PageRowCount;
1.498 + _vScrollBar.Visible = (RowCount > 0) && (_vScrollBar.LargeChange <= _vScrollBar.Maximum);
1.499 + _vScrollBar.Value = Math.Min(_vScrollBar.Value, _vScrollBar.Maximum - _vScrollBar.LargeChange + 1);
1.500 + }
1.501 +
1.502 + protected override CreateParams CreateParams
1.503 + {
1.504 + [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
1.505 + get
1.506 + {
1.507 + CreateParams res = base.CreateParams;
1.508 + switch (BorderStyle)
1.509 + {
1.510 + case BorderStyle.FixedSingle:
1.511 + res.Style |= 0x800000;
1.512 + break;
1.513 + case BorderStyle.Fixed3D:
1.514 + res.ExStyle |= 0x200;
1.515 + break;
1.516 + }
1.517 + return res;
1.518 + }
1.519 + }
1.520 +
1.521 + protected override void OnGotFocus(EventArgs e)
1.522 + {
1.523 + UpdateView();
1.524 + ChangeInput();
1.525 + base.OnGotFocus(e);
1.526 + }
1.527 +
1.528 + protected override void OnFontChanged(EventArgs e)
1.529 + {
1.530 + base.OnFontChanged(e);
1.531 + _measureContext.Font = Font;
1.532 + FullUpdate();
1.533 + }
1.534 +
1.535 + internal IEnumerable<NodeControlInfo> GetNodeControls(TreeNodeAdv node)
1.536 + {
1.537 + if (node == null)
1.538 + yield break;
1.539 + Rectangle rowRect = _rowLayout.GetRowBounds(node.Row);
1.540 + foreach (NodeControlInfo n in GetNodeControls(node, rowRect))
1.541 + yield return n;
1.542 + }
1.543 +
1.544 + internal IEnumerable<NodeControlInfo> GetNodeControls(TreeNodeAdv node, Rectangle rowRect)
1.545 + {
1.546 + if (node == null)
1.547 + yield break;
1.548 +
1.549 + int y = rowRect.Y;
1.550 + int x = (node.Level - 1) * _indent + LeftMargin;
1.551 + int width = 0;
1.552 + if (node.Row == 0 && ShiftFirstNode)
1.553 + x -= _indent;
1.554 + Rectangle rect = Rectangle.Empty;
1.555 +
1.556 + if (ShowPlusMinus)
1.557 + {
1.558 + width = _plusMinus.GetActualSize(node, _measureContext).Width;
1.559 + rect = new Rectangle(x, y, width, rowRect.Height);
1.560 + if (UseColumns && Columns.Count > 0 && Columns[0].Width < rect.Right)
1.561 + rect.Width = Columns[0].Width - x;
1.562 +
1.563 + yield return new NodeControlInfo(_plusMinus, rect, node);
1.564 + x += width;
1.565 + }
1.566 +
1.567 + if (!UseColumns)
1.568 + {
1.569 + foreach (NodeControl c in NodeControls)
1.570 + {
1.571 + Size s = c.GetActualSize(node, _measureContext);
1.572 + if (!s.IsEmpty)
1.573 + {
1.574 + width = s.Width;
1.575 + rect = new Rectangle(x, y, width, rowRect.Height);
1.576 + x += rect.Width;
1.577 + yield return new NodeControlInfo(c, rect, node);
1.578 + }
1.579 + }
1.580 + }
1.581 + else
1.582 + {
1.583 + int right = 0;
1.584 + foreach (TreeColumn col in Columns)
1.585 + {
1.586 + if (col.IsVisible && col.Width > 0)
1.587 + {
1.588 + right += col.Width;
1.589 + for (int i = 0; i < NodeControls.Count; i++)
1.590 + {
1.591 + NodeControl nc = NodeControls[i];
1.592 + if (nc.ParentColumn == col)
1.593 + {
1.594 + Size s = nc.GetActualSize(node, _measureContext);
1.595 + if (!s.IsEmpty)
1.596 + {
1.597 + bool isLastControl = true;
1.598 + for (int k = i + 1; k < NodeControls.Count; k++)
1.599 + if (NodeControls[k].ParentColumn == col)
1.600 + {
1.601 + isLastControl = false;
1.602 + break;
1.603 + }
1.604 +
1.605 + width = right - x;
1.606 + if (!isLastControl)
1.607 + width = s.Width;
1.608 + int maxWidth = Math.Max(0, right - x);
1.609 + rect = new Rectangle(x, y, Math.Min(maxWidth, width), rowRect.Height);
1.610 + x += width;
1.611 + yield return new NodeControlInfo(nc, rect, node);
1.612 + }
1.613 + }
1.614 + }
1.615 + x = right;
1.616 + }
1.617 + }
1.618 + }
1.619 + }
1.620 +
1.621 + internal static double Dist(Point p1, Point p2)
1.622 + {
1.623 + return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
1.624 + }
1.625 +
1.626 + public void FullUpdate()
1.627 + {
1.628 + HideEditor();
1.629 + if (InvokeRequired)
1.630 + BeginInvoke(new MethodInvoker(UnsafeFullUpdate));
1.631 + else
1.632 + UnsafeFullUpdate();
1.633 + }
1.634 +
1.635 + private void UnsafeFullUpdate()
1.636 + {
1.637 + _rowLayout.ClearCache();
1.638 + CreateRowMap();
1.639 + SafeUpdateScrollBars();
1.640 + UpdateView();
1.641 + _needFullUpdate = false;
1.642 + }
1.643 +
1.644 + internal void UpdateView()
1.645 + {
1.646 + if (!_suspendUpdate)
1.647 + Invalidate(false);
1.648 + }
1.649 +
1.650 + internal void UpdateHeaders()
1.651 + {
1.652 + Invalidate(new Rectangle(0, 0, Width, ColumnHeaderHeight));
1.653 + }
1.654 +
1.655 + internal void UpdateColumns()
1.656 + {
1.657 + FullUpdate();
1.658 + }
1.659 +
1.660 + private void CreateNodes()
1.661 + {
1.662 + Selection.Clear();
1.663 + SelectionStart = null;
1.664 + _root = new TreeNodeAdv(this, null);
1.665 + _root.IsExpanded = true;
1.666 + if (_root.Nodes.Count > 0)
1.667 + CurrentNode = _root.Nodes[0];
1.668 + else
1.669 + CurrentNode = null;
1.670 + }
1.671 +
1.672 + internal void ReadChilds(TreeNodeAdv parentNode)
1.673 + {
1.674 + ReadChilds(parentNode, false);
1.675 + }
1.676 +
1.677 + internal void ReadChilds(TreeNodeAdv parentNode, bool performFullUpdate)
1.678 + {
1.679 + if (!parentNode.IsLeaf)
1.680 + {
1.681 + parentNode.IsExpandedOnce = true;
1.682 + parentNode.Nodes.Clear();
1.683 +
1.684 + if (Model != null)
1.685 + {
1.686 + IEnumerable items = Model.GetChildren(GetPath(parentNode));
1.687 + if (items != null)
1.688 + foreach (object obj in items)
1.689 + {
1.690 + AddNewNode(parentNode, obj, -1);
1.691 + if (performFullUpdate)
1.692 + FullUpdate();
1.693 + }
1.694 + }
1.695 +
1.696 + if (parentNode.AutoExpandOnStructureChanged)
1.697 + parentNode.ExpandAll();
1.698 + }
1.699 + }
1.700 +
1.701 + private void AddNewNode(TreeNodeAdv parent, object tag, int index)
1.702 + {
1.703 + TreeNodeAdv node = new TreeNodeAdv(this, tag);
1.704 + AddNode(parent, index, node);
1.705 + }
1.706 +
1.707 + private void AddNode(TreeNodeAdv parent, int index, TreeNodeAdv node)
1.708 + {
1.709 + if (index >= 0 && index < parent.Nodes.Count)
1.710 + parent.Nodes.Insert(index, node);
1.711 + else
1.712 + parent.Nodes.Add(node);
1.713 +
1.714 + node.IsLeaf = Model.IsLeaf(GetPath(node));
1.715 + if (node.IsLeaf)
1.716 + node.Nodes.Clear();
1.717 + if (!LoadOnDemand || node.IsExpandedOnce)
1.718 + ReadChilds(node);
1.719 + }
1.720 +
1.721 + private struct ExpandArgs
1.722 + {
1.723 + public TreeNodeAdv Node;
1.724 + public bool Value;
1.725 + public bool IgnoreChildren;
1.726 + }
1.727 +
1.728 + public void AbortBackgroundExpandingThreads()
1.729 + {
1.730 + _threadPool.CancelAll(true);
1.731 + for (int i = 0; i < _expandingNodes.Count; i++)
1.732 + _expandingNodes[i].IsExpandingNow = false;
1.733 + _expandingNodes.Clear();
1.734 + Invalidate();
1.735 + }
1.736 +
1.737 + internal void SetIsExpanded(TreeNodeAdv node, bool value, bool ignoreChildren)
1.738 + {
1.739 + ExpandArgs eargs = new ExpandArgs();
1.740 + eargs.Node = node;
1.741 + eargs.Value = value;
1.742 + eargs.IgnoreChildren = ignoreChildren;
1.743 +
1.744 + if (AsyncExpanding && LoadOnDemand && !_threadPool.IsMyThread(Thread.CurrentThread))
1.745 + {
1.746 + WaitCallback wc = delegate(object argument) { SetIsExpanded((ExpandArgs)argument); };
1.747 + _threadPool.QueueUserWorkItem(wc, eargs);
1.748 + }
1.749 + else
1.750 + SetIsExpanded(eargs);
1.751 + }
1.752 +
1.753 + private void SetIsExpanded(ExpandArgs eargs)
1.754 + {
1.755 + bool update = !eargs.IgnoreChildren && !AsyncExpanding;
1.756 + if (update)
1.757 + BeginUpdate();
1.758 + try
1.759 + {
1.760 + if (IsMyNode(eargs.Node) && eargs.Node.IsExpanded != eargs.Value)
1.761 + SetIsExpanded(eargs.Node, eargs.Value);
1.762 +
1.763 + if (!eargs.IgnoreChildren)
1.764 + SetIsExpandedRecursive(eargs.Node, eargs.Value);
1.765 + }
1.766 + finally
1.767 + {
1.768 + if (update)
1.769 + EndUpdate();
1.770 + }
1.771 + }
1.772 +
1.773 + internal void SetIsExpanded(TreeNodeAdv node, bool value)
1.774 + {
1.775 + if (Root == node && !value)
1.776 + return; //Can't collapse root node
1.777 +
1.778 + if (value)
1.779 + {
1.780 + OnExpanding(node);
1.781 + node.OnExpanding();
1.782 + }
1.783 + else
1.784 + {
1.785 + OnCollapsing(node);
1.786 + node.OnCollapsing();
1.787 + }
1.788 +
1.789 + if (value && !node.IsExpandedOnce)
1.790 + {
1.791 + if (AsyncExpanding && LoadOnDemand)
1.792 + {
1.793 + AddExpandingNode(node);
1.794 + node.AssignIsExpanded(true);
1.795 + Invalidate();
1.796 + }
1.797 + ReadChilds(node, AsyncExpanding);
1.798 + RemoveExpandingNode(node);
1.799 + }
1.800 + node.AssignIsExpanded(value);
1.801 + SmartFullUpdate();
1.802 +
1.803 + if (value)
1.804 + {
1.805 + OnExpanded(node);
1.806 + node.OnExpanded();
1.807 + }
1.808 + else
1.809 + {
1.810 + OnCollapsed(node);
1.811 + node.OnCollapsed();
1.812 + }
1.813 + }
1.814 +
1.815 + private void RemoveExpandingNode(TreeNodeAdv node)
1.816 + {
1.817 + node.IsExpandingNow = false;
1.818 + _expandingNodes.Remove(node);
1.819 + if (_expandingNodes.Count <= 0)
1.820 + ExpandingIcon.Stop();
1.821 + }
1.822 +
1.823 + private void AddExpandingNode(TreeNodeAdv node)
1.824 + {
1.825 + node.IsExpandingNow = true;
1.826 + _expandingNodes.Add(node);
1.827 + ExpandingIcon.Start();
1.828 + }
1.829 +
1.830 + internal void SetIsExpandedRecursive(TreeNodeAdv root, bool value)
1.831 + {
1.832 + for (int i = 0; i < root.Nodes.Count; i++)
1.833 + {
1.834 + TreeNodeAdv node = root.Nodes[i];
1.835 + node.IsExpanded = value;
1.836 + SetIsExpandedRecursive(node, value);
1.837 + }
1.838 + }
1.839 +
1.840 + private void CreateRowMap()
1.841 + {
1.842 + RowMap.Clear();
1.843 + int row = 0;
1.844 + _contentWidth = 0;
1.845 + foreach (TreeNodeAdv node in VisibleNodes)
1.846 + {
1.847 + node.Row = row;
1.848 + RowMap.Add(node);
1.849 + if (!UseColumns)
1.850 + {
1.851 + _contentWidth = Math.Max(_contentWidth, GetNodeWidth(node));
1.852 + }
1.853 + row++;
1.854 + }
1.855 + if (UseColumns)
1.856 + {
1.857 + _contentWidth = 0;
1.858 + foreach (TreeColumn col in _columns)
1.859 + if (col.IsVisible)
1.860 + _contentWidth += col.Width;
1.861 + }
1.862 + }
1.863 +
1.864 + private int GetNodeWidth(TreeNodeAdv node)
1.865 + {
1.866 + if (node.RightBounds == null)
1.867 + {
1.868 + Rectangle res = GetNodeBounds(GetNodeControls(node, Rectangle.Empty));
1.869 + node.RightBounds = res.Right;
1.870 + }
1.871 + return node.RightBounds.Value;
1.872 + }
1.873 +
1.874 + internal Rectangle GetNodeBounds(TreeNodeAdv node)
1.875 + {
1.876 + return GetNodeBounds(GetNodeControls(node));
1.877 + }
1.878 +
1.879 + private Rectangle GetNodeBounds(IEnumerable<NodeControlInfo> nodeControls)
1.880 + {
1.881 + Rectangle res = Rectangle.Empty;
1.882 + foreach (NodeControlInfo info in nodeControls)
1.883 + {
1.884 + if (res == Rectangle.Empty)
1.885 + res = info.Bounds;
1.886 + else
1.887 + res = Rectangle.Union(res, info.Bounds);
1.888 + }
1.889 + return res;
1.890 + }
1.891 +
1.892 + private void _vScrollBar_ValueChanged(object sender, EventArgs e)
1.893 + {
1.894 + FirstVisibleRow = _vScrollBar.Value;
1.895 + }
1.896 +
1.897 + private void _hScrollBar_ValueChanged(object sender, EventArgs e)
1.898 + {
1.899 + OffsetX = _hScrollBar.Value;
1.900 + }
1.901 +
1.902 + private void _vScrollBar_Scroll(object sender, ScrollEventArgs e)
1.903 + {
1.904 + OnScroll(e);
1.905 + }
1.906 +
1.907 + private void _hScrollBar_Scroll(object sender, ScrollEventArgs e)
1.908 + {
1.909 + OnScroll(e);
1.910 + }
1.911 +
1.912 + internal void SmartFullUpdate()
1.913 + {
1.914 + if (_suspendUpdate)
1.915 + _needFullUpdate = true;
1.916 + else
1.917 + FullUpdate();
1.918 + }
1.919 +
1.920 + internal bool IsMyNode(TreeNodeAdv node)
1.921 + {
1.922 + if (node == null)
1.923 + return false;
1.924 +
1.925 + if (node.Tree != this)
1.926 + return false;
1.927 +
1.928 + while (node.Parent != null)
1.929 + node = node.Parent;
1.930 +
1.931 + return node == _root;
1.932 + }
1.933 +
1.934 + internal void UpdateSelection()
1.935 + {
1.936 + bool flag = false;
1.937 +
1.938 + if (!IsMyNode(CurrentNode))
1.939 + CurrentNode = null;
1.940 + if (!IsMyNode(_selectionStart))
1.941 + _selectionStart = null;
1.942 +
1.943 + for (int i = Selection.Count - 1; i >= 0; i--)
1.944 + if (!IsMyNode(Selection[i]))
1.945 + {
1.946 + flag = true;
1.947 + Selection.RemoveAt(i);
1.948 + }
1.949 +
1.950 + if (flag)
1.951 + OnSelectionChanged();
1.952 + }
1.953 +
1.954 + internal void ChangeColumnWidth(TreeColumn column)
1.955 + {
1.956 + if (!(_input is ResizeColumnState))
1.957 + {
1.958 + FullUpdate();
1.959 + OnColumnWidthChanged(column);
1.960 + }
1.961 + }
1.962 +
1.963 + public TreeNodeAdv FindNode(TreePath path)
1.964 + {
1.965 + return FindNode(path, false);
1.966 + }
1.967 +
1.968 + public TreeNodeAdv FindNode(TreePath path, bool readChilds)
1.969 + {
1.970 + if (path.IsEmpty())
1.971 + return _root;
1.972 + else
1.973 + return FindNode(_root, path, 0, readChilds);
1.974 + }
1.975 +
1.976 + private TreeNodeAdv FindNode(TreeNodeAdv root, TreePath path, int level, bool readChilds)
1.977 + {
1.978 + if (!root.IsExpandedOnce && readChilds)
1.979 + ReadChilds(root);
1.980 +
1.981 + for (int i = 0; i < root.Nodes.Count; i++)
1.982 + {
1.983 + TreeNodeAdv node = root.Nodes[i];
1.984 + if (node.Tag == path.FullPath[level])
1.985 + {
1.986 + if (level == path.FullPath.Length - 1)
1.987 + return node;
1.988 + else
1.989 + return FindNode(node, path, level + 1, readChilds);
1.990 + }
1.991 + }
1.992 + return null;
1.993 + }
1.994 +
1.995 + public TreeNodeAdv FindNodeByTag(object tag)
1.996 + {
1.997 + return FindNodeByTag(_root, tag);
1.998 + }
1.999 +
1.1000 + private TreeNodeAdv FindNodeByTag(TreeNodeAdv root, object tag)
1.1001 + {
1.1002 + foreach (TreeNodeAdv node in root.Nodes)
1.1003 + {
1.1004 + if (node.Tag == tag)
1.1005 + return node;
1.1006 + TreeNodeAdv res = FindNodeByTag(node, tag);
1.1007 + if (res != null)
1.1008 + return res;
1.1009 + }
1.1010 + return null;
1.1011 + }
1.1012 +
1.1013 + public void SelectAllNodes()
1.1014 + {
1.1015 + SuspendSelectionEvent = true;
1.1016 + try
1.1017 + {
1.1018 + if (SelectionMode == TreeSelectionMode.MultiSameParent)
1.1019 + {
1.1020 + if (CurrentNode != null)
1.1021 + {
1.1022 + foreach (TreeNodeAdv n in CurrentNode.Parent.Nodes)
1.1023 + n.IsSelected = true;
1.1024 + }
1.1025 + }
1.1026 + else if (SelectionMode == TreeSelectionMode.Multi)
1.1027 + {
1.1028 + SelectNodes(Root.Nodes);
1.1029 + }
1.1030 + }
1.1031 + finally
1.1032 + {
1.1033 + SuspendSelectionEvent = false;
1.1034 + }
1.1035 + }
1.1036 +
1.1037 + private void SelectNodes(Collection<TreeNodeAdv> nodes)
1.1038 + {
1.1039 + foreach (TreeNodeAdv n in nodes)
1.1040 + {
1.1041 + n.IsSelected = true;
1.1042 + if (n.IsExpanded)
1.1043 + SelectNodes(n.Nodes);
1.1044 + }
1.1045 + }
1.1046 +
1.1047 + #region ModelEvents
1.1048 + private void BindModelEvents()
1.1049 + {
1.1050 + _model.NodesChanged += new EventHandler<TreeModelEventArgs>(_model_NodesChanged);
1.1051 + _model.NodesInserted += new EventHandler<TreeModelEventArgs>(_model_NodesInserted);
1.1052 + _model.NodesRemoved += new EventHandler<TreeModelEventArgs>(_model_NodesRemoved);
1.1053 + _model.StructureChanged += new EventHandler<TreePathEventArgs>(_model_StructureChanged);
1.1054 + }
1.1055 +
1.1056 + private void UnbindModelEvents()
1.1057 + {
1.1058 + _model.NodesChanged -= new EventHandler<TreeModelEventArgs>(_model_NodesChanged);
1.1059 + _model.NodesInserted -= new EventHandler<TreeModelEventArgs>(_model_NodesInserted);
1.1060 + _model.NodesRemoved -= new EventHandler<TreeModelEventArgs>(_model_NodesRemoved);
1.1061 + _model.StructureChanged -= new EventHandler<TreePathEventArgs>(_model_StructureChanged);
1.1062 + }
1.1063 +
1.1064 + private void _model_StructureChanged(object sender, TreePathEventArgs e)
1.1065 + {
1.1066 + if (e.Path == null)
1.1067 + throw new ArgumentNullException();
1.1068 +
1.1069 + TreeNodeAdv node = FindNode(e.Path);
1.1070 + if (node != null)
1.1071 + {
1.1072 + if (node != Root)
1.1073 + node.IsLeaf = Model.IsLeaf(GetPath(node));
1.1074 +
1.1075 + var list = new Dictionary<object, object>();
1.1076 + SaveExpandedNodes(node, list);
1.1077 + ReadChilds(node);
1.1078 + RestoreExpandedNodes(node, list);
1.1079 +
1.1080 + UpdateSelection();
1.1081 + SmartFullUpdate();
1.1082 + }
1.1083 + //else
1.1084 + // throw new ArgumentException("Path not found");
1.1085 + }
1.1086 +
1.1087 + private void RestoreExpandedNodes(TreeNodeAdv node, Dictionary<object, object> list)
1.1088 + {
1.1089 + if (node.Tag != null && list.ContainsKey(node.Tag))
1.1090 + {
1.1091 + node.IsExpanded = true;
1.1092 + foreach (var child in node.Children)
1.1093 + RestoreExpandedNodes(child, list);
1.1094 + }
1.1095 + }
1.1096 +
1.1097 + private void SaveExpandedNodes(TreeNodeAdv node, Dictionary<object, object> list)
1.1098 + {
1.1099 + if (node.IsExpanded && node.Tag != null)
1.1100 + {
1.1101 + list.Add(node.Tag, null);
1.1102 + foreach (var child in node.Children)
1.1103 + SaveExpandedNodes(child, list);
1.1104 + }
1.1105 + }
1.1106 +
1.1107 + private void _model_NodesRemoved(object sender, TreeModelEventArgs e)
1.1108 + {
1.1109 + TreeNodeAdv parent = FindNode(e.Path);
1.1110 + if (parent != null)
1.1111 + {
1.1112 + if (e.Indices != null)
1.1113 + {
1.1114 + List<int> list = new List<int>(e.Indices);
1.1115 + list.Sort();
1.1116 + for (int n = list.Count - 1; n >= 0; n--)
1.1117 + {
1.1118 + int index = list[n];
1.1119 + if (index >= 0 && index <= parent.Nodes.Count)
1.1120 + parent.Nodes.RemoveAt(index);
1.1121 + else
1.1122 + throw new ArgumentOutOfRangeException("Index out of range");
1.1123 + }
1.1124 + }
1.1125 + else
1.1126 + {
1.1127 + for (int i = parent.Nodes.Count - 1; i >= 0; i--)
1.1128 + {
1.1129 + for (int n = 0; n < e.Children.Length; n++)
1.1130 + if (parent.Nodes[i].Tag == e.Children[n])
1.1131 + {
1.1132 + parent.Nodes.RemoveAt(i);
1.1133 + break;
1.1134 + }
1.1135 + }
1.1136 + }
1.1137 + }
1.1138 + UpdateSelection();
1.1139 + SmartFullUpdate();
1.1140 + }
1.1141 +
1.1142 + private void _model_NodesInserted(object sender, TreeModelEventArgs e)
1.1143 + {
1.1144 + if (e.Indices == null)
1.1145 + throw new ArgumentNullException("Indices");
1.1146 +
1.1147 + TreeNodeAdv parent = FindNode(e.Path);
1.1148 + if (parent != null)
1.1149 + {
1.1150 + for (int i = 0; i < e.Children.Length; i++)
1.1151 + AddNewNode(parent, e.Children[i], e.Indices[i]);
1.1152 + }
1.1153 + SmartFullUpdate();
1.1154 + }
1.1155 +
1.1156 + private void _model_NodesChanged(object sender, TreeModelEventArgs e)
1.1157 + {
1.1158 + TreeNodeAdv parent = FindNode(e.Path);
1.1159 + if (parent != null && parent.IsVisible && parent.IsExpanded)
1.1160 + {
1.1161 + if (InvokeRequired)
1.1162 + BeginInvoke(new UpdateContentWidthDelegate(ClearNodesSize), e, parent);
1.1163 + else
1.1164 + ClearNodesSize(e, parent);
1.1165 + SmartFullUpdate();
1.1166 + }
1.1167 + }
1.1168 +
1.1169 + private delegate void UpdateContentWidthDelegate(TreeModelEventArgs e, TreeNodeAdv parent);
1.1170 + private void ClearNodesSize(TreeModelEventArgs e, TreeNodeAdv parent)
1.1171 + {
1.1172 + if (e.Indices != null)
1.1173 + {
1.1174 + foreach (int index in e.Indices)
1.1175 + {
1.1176 + if (index >= 0 && index < parent.Nodes.Count)
1.1177 + {
1.1178 + TreeNodeAdv node = parent.Nodes[index];
1.1179 + node.Height = node.RightBounds = null;
1.1180 + }
1.1181 + else
1.1182 + throw new ArgumentOutOfRangeException("Index out of range");
1.1183 + }
1.1184 + }
1.1185 + else
1.1186 + {
1.1187 + foreach (TreeNodeAdv node in parent.Nodes)
1.1188 + {
1.1189 + foreach (object obj in e.Children)
1.1190 + if (node.Tag == obj)
1.1191 + {
1.1192 + node.Height = node.RightBounds = null;
1.1193 + }
1.1194 + }
1.1195 + }
1.1196 + }
1.1197 + #endregion
1.1198 + }
1.1199 +}