External/Aga.Controls/Tree/TreeViewAdv.cs
author moel.mich
Sun, 27 May 2012 15:16:19 +0000
changeset 345 0c551e8818e0
permissions -rw-r--r--
Added the source code of Aga.Controls (TreeViewAdv for .Net) version 1.7.0.0.
moel@345
     1
using System;
moel@345
     2
using System.Collections.Generic;
moel@345
     3
using System.Collections.ObjectModel;
moel@345
     4
using System.ComponentModel;
moel@345
     5
using System.Drawing;
moel@345
     6
using System.Security.Permissions;
moel@345
     7
using System.Threading;
moel@345
     8
using System.Windows.Forms;
moel@345
     9
using System.Collections;
moel@345
    10
moel@345
    11
using Aga.Controls.Tree.NodeControls;
moel@345
    12
using Aga.Controls.Threading;
moel@345
    13
moel@345
    14
moel@345
    15
namespace Aga.Controls.Tree
moel@345
    16
{
moel@345
    17
	/// <summary>
moel@345
    18
	/// Extensible advanced <see cref="TreeView"/> implemented in 100% managed C# code.
moel@345
    19
	/// Features: Model/View architecture. Multiple column per node. Ability to select
moel@345
    20
	/// multiple tree nodes. Different types of controls for each node column: 
moel@345
    21
	/// <see cref="CheckBox"/>, Icon, Label... Drag and Drop highlighting. Load on
moel@345
    22
	/// demand of nodes. Incremental search of nodes.
moel@345
    23
	/// </summary>
moel@345
    24
	public partial class TreeViewAdv : Control
moel@345
    25
	{
moel@345
    26
		private const int LeftMargin = 7;
moel@345
    27
		internal const int ItemDragSensivity = 4;
moel@345
    28
		private readonly int _columnHeaderHeight;
moel@345
    29
		private const int DividerWidth = 9;
moel@345
    30
		private const int DividerCorrectionGap = -2;
moel@345
    31
moel@345
    32
		private Pen _linePen;
moel@345
    33
		private Pen _markPen;
moel@345
    34
		private bool _suspendUpdate;
moel@345
    35
		private bool _needFullUpdate;
moel@345
    36
		private bool _fireSelectionEvent;
moel@345
    37
		private NodePlusMinus _plusMinus;
moel@345
    38
		private ToolTip _toolTip;
moel@345
    39
		private DrawContext _measureContext;
moel@345
    40
		private TreeColumn _hotColumn;
moel@345
    41
		private IncrementalSearch _search;
moel@345
    42
		private List<TreeNodeAdv> _expandingNodes = new List<TreeNodeAdv>();
moel@345
    43
		private AbortableThreadPool _threadPool = new AbortableThreadPool();
moel@345
    44
moel@345
    45
		#region Public Events
moel@345
    46
moel@345
    47
		[Category("Action")]
moel@345
    48
		public event ItemDragEventHandler ItemDrag;
moel@345
    49
		private void OnItemDrag(MouseButtons buttons, object item)
moel@345
    50
		{
moel@345
    51
			if (ItemDrag != null)
moel@345
    52
				ItemDrag(this, new ItemDragEventArgs(buttons, item));
moel@345
    53
		}
moel@345
    54
moel@345
    55
		[Category("Behavior")]
moel@345
    56
		public event EventHandler<TreeNodeAdvMouseEventArgs> NodeMouseClick;
moel@345
    57
		private void OnNodeMouseClick(TreeNodeAdvMouseEventArgs args)
moel@345
    58
		{
moel@345
    59
			if (NodeMouseClick != null)
moel@345
    60
				NodeMouseClick(this, args);
moel@345
    61
		}
moel@345
    62
moel@345
    63
		[Category("Behavior")]
moel@345
    64
		public event EventHandler<TreeNodeAdvMouseEventArgs> NodeMouseDoubleClick;
moel@345
    65
		private void OnNodeMouseDoubleClick(TreeNodeAdvMouseEventArgs args)
moel@345
    66
		{
moel@345
    67
			if (NodeMouseDoubleClick != null)
moel@345
    68
				NodeMouseDoubleClick(this, args);
moel@345
    69
		}
moel@345
    70
moel@345
    71
		[Category("Behavior")]
moel@345
    72
		public event EventHandler<TreeColumnEventArgs> ColumnWidthChanged;
moel@345
    73
		internal void OnColumnWidthChanged(TreeColumn column)
moel@345
    74
		{
moel@345
    75
			if (ColumnWidthChanged != null)
moel@345
    76
				ColumnWidthChanged(this, new TreeColumnEventArgs(column));
moel@345
    77
		}
moel@345
    78
moel@345
    79
		[Category("Behavior")]
moel@345
    80
		public event EventHandler<TreeColumnEventArgs> ColumnReordered;
moel@345
    81
		internal void OnColumnReordered(TreeColumn column)
moel@345
    82
		{
moel@345
    83
			if (ColumnReordered != null)
moel@345
    84
				ColumnReordered(this, new TreeColumnEventArgs(column));
moel@345
    85
		}
moel@345
    86
moel@345
    87
		[Category("Behavior")]
moel@345
    88
		public event EventHandler<TreeColumnEventArgs> ColumnClicked;
moel@345
    89
		internal void OnColumnClicked(TreeColumn column)
moel@345
    90
		{
moel@345
    91
			if (ColumnClicked != null)
moel@345
    92
				ColumnClicked(this, new TreeColumnEventArgs(column));
moel@345
    93
		}
moel@345
    94
moel@345
    95
		[Category("Behavior")]
moel@345
    96
		public event EventHandler SelectionChanged;
moel@345
    97
		internal void OnSelectionChanged()
moel@345
    98
		{
moel@345
    99
			if (SuspendSelectionEvent)
moel@345
   100
				_fireSelectionEvent = true;
moel@345
   101
			else
moel@345
   102
			{
moel@345
   103
				_fireSelectionEvent = false;
moel@345
   104
				if (SelectionChanged != null)
moel@345
   105
					SelectionChanged(this, EventArgs.Empty);
moel@345
   106
			}
moel@345
   107
		}
moel@345
   108
moel@345
   109
		[Category("Behavior")]
moel@345
   110
		public event EventHandler<TreeViewAdvEventArgs> Collapsing;
moel@345
   111
		private void OnCollapsing(TreeNodeAdv node)
moel@345
   112
		{
moel@345
   113
			if (Collapsing != null)
moel@345
   114
				Collapsing(this, new TreeViewAdvEventArgs(node));
moel@345
   115
		}
moel@345
   116
moel@345
   117
		[Category("Behavior")]
moel@345
   118
		public event EventHandler<TreeViewAdvEventArgs> Collapsed;
moel@345
   119
		private void OnCollapsed(TreeNodeAdv node)
moel@345
   120
		{
moel@345
   121
			if (Collapsed != null)
moel@345
   122
				Collapsed(this, new TreeViewAdvEventArgs(node));
moel@345
   123
		}
moel@345
   124
moel@345
   125
		[Category("Behavior")]
moel@345
   126
		public event EventHandler<TreeViewAdvEventArgs> Expanding;
moel@345
   127
		private void OnExpanding(TreeNodeAdv node)
moel@345
   128
		{
moel@345
   129
			if (Expanding != null)
moel@345
   130
				Expanding(this, new TreeViewAdvEventArgs(node));
moel@345
   131
		}
moel@345
   132
moel@345
   133
		[Category("Behavior")]
moel@345
   134
		public event EventHandler<TreeViewAdvEventArgs> Expanded;
moel@345
   135
		private void OnExpanded(TreeNodeAdv node)
moel@345
   136
		{
moel@345
   137
			if (Expanded != null)
moel@345
   138
				Expanded(this, new TreeViewAdvEventArgs(node));
moel@345
   139
		}
moel@345
   140
moel@345
   141
		[Category("Behavior")]
moel@345
   142
		public event EventHandler GridLineStyleChanged;
moel@345
   143
		private void OnGridLineStyleChanged()
moel@345
   144
		{
moel@345
   145
			if (GridLineStyleChanged != null)
moel@345
   146
				GridLineStyleChanged(this, EventArgs.Empty);
moel@345
   147
		}
moel@345
   148
moel@345
   149
		[Category("Behavior")]
moel@345
   150
		public event ScrollEventHandler Scroll;
moel@345
   151
		protected virtual void OnScroll(ScrollEventArgs e)
moel@345
   152
		{
moel@345
   153
			if (Scroll != null)
moel@345
   154
				Scroll(this, e);
moel@345
   155
		}
moel@345
   156
moel@345
   157
		[Category("Behavior")]
moel@345
   158
		public event EventHandler<TreeViewRowDrawEventArgs> RowDraw;
moel@345
   159
		protected virtual void OnRowDraw(PaintEventArgs e, TreeNodeAdv node, DrawContext context, int row, Rectangle rowRect)
moel@345
   160
		{
moel@345
   161
			if (RowDraw != null)
moel@345
   162
			{
moel@345
   163
				TreeViewRowDrawEventArgs args = new TreeViewRowDrawEventArgs(e.Graphics, e.ClipRectangle, node, context, row, rowRect);
moel@345
   164
				RowDraw(this, args);
moel@345
   165
			}
moel@345
   166
		}
moel@345
   167
moel@345
   168
		/// <summary>
moel@345
   169
		/// Fires when control is going to draw. Can be used to change text or back color
moel@345
   170
		/// </summary>
moel@345
   171
		[Category("Behavior")]
moel@345
   172
		public event EventHandler<DrawEventArgs> DrawControl;
moel@345
   173
moel@345
   174
		internal bool DrawControlMustBeFired()
moel@345
   175
		{
moel@345
   176
			return DrawControl != null;
moel@345
   177
		}
moel@345
   178
moel@345
   179
		internal void FireDrawControl(DrawEventArgs args)
moel@345
   180
		{
moel@345
   181
			OnDrawControl(args);
moel@345
   182
		}
moel@345
   183
moel@345
   184
		protected virtual void OnDrawControl(DrawEventArgs args)
moel@345
   185
		{
moel@345
   186
			if (DrawControl != null)
moel@345
   187
				DrawControl(this, args);
moel@345
   188
		}
moel@345
   189
moel@345
   190
moel@345
   191
		[Category("Drag Drop")]
moel@345
   192
		public event EventHandler<DropNodeValidatingEventArgs> DropNodeValidating;
moel@345
   193
		protected virtual void OnDropNodeValidating(Point point, ref TreeNodeAdv node)
moel@345
   194
		{
moel@345
   195
			if (DropNodeValidating != null)
moel@345
   196
			{
moel@345
   197
				DropNodeValidatingEventArgs args = new DropNodeValidatingEventArgs(point, node);
moel@345
   198
				DropNodeValidating(this, args);
moel@345
   199
				node = args.Node;
moel@345
   200
			}
moel@345
   201
		}
moel@345
   202
		#endregion
moel@345
   203
moel@345
   204
		public TreeViewAdv()
moel@345
   205
		{
moel@345
   206
			InitializeComponent();
moel@345
   207
			SetStyle(ControlStyles.AllPaintingInWmPaint
moel@345
   208
				| ControlStyles.UserPaint
moel@345
   209
				| ControlStyles.OptimizedDoubleBuffer
moel@345
   210
				| ControlStyles.ResizeRedraw
moel@345
   211
				| ControlStyles.Selectable
moel@345
   212
				, true);
moel@345
   213
moel@345
   214
moel@345
   215
			if (Application.RenderWithVisualStyles)
moel@345
   216
				_columnHeaderHeight = 20;
moel@345
   217
			else
moel@345
   218
				_columnHeaderHeight = 17;
moel@345
   219
moel@345
   220
			//BorderStyle = BorderStyle.Fixed3D;
moel@345
   221
			_hScrollBar.Height = SystemInformation.HorizontalScrollBarHeight;
moel@345
   222
			_vScrollBar.Width = SystemInformation.VerticalScrollBarWidth;
moel@345
   223
			_rowLayout = new FixedRowHeightLayout(this, RowHeight);
moel@345
   224
			_rowMap = new List<TreeNodeAdv>();
moel@345
   225
			_selection = new List<TreeNodeAdv>();
moel@345
   226
			_readonlySelection = new ReadOnlyCollection<TreeNodeAdv>(_selection);
moel@345
   227
			_columns = new TreeColumnCollection(this);
moel@345
   228
			_toolTip = new ToolTip();
moel@345
   229
moel@345
   230
			_measureContext = new DrawContext();
moel@345
   231
			_measureContext.Font = Font;
moel@345
   232
			_measureContext.Graphics = Graphics.FromImage(new Bitmap(1, 1));
moel@345
   233
moel@345
   234
			Input = new NormalInputState(this);
moel@345
   235
			_search = new IncrementalSearch(this);
moel@345
   236
			CreateNodes();
moel@345
   237
			CreatePens();
moel@345
   238
moel@345
   239
			ArrangeControls();
moel@345
   240
moel@345
   241
			_plusMinus = new NodePlusMinus();
moel@345
   242
			_controls = new NodeControlsCollection(this);
moel@345
   243
moel@345
   244
			Font = _font;
moel@345
   245
			ExpandingIcon.IconChanged += ExpandingIconChanged;
moel@345
   246
		}
moel@345
   247
moel@345
   248
		void ExpandingIconChanged(object sender, EventArgs e)
moel@345
   249
		{
moel@345
   250
			if (IsHandleCreated && !IsDisposed)
moel@345
   251
				BeginInvoke(new MethodInvoker(DrawIcons));
moel@345
   252
		}
moel@345
   253
moel@345
   254
		private void DrawIcons()
moel@345
   255
		{
moel@345
   256
			using (Graphics gr = Graphics.FromHwnd(this.Handle))
moel@345
   257
			{
moel@345
   258
				//Apply the same Graphics Transform logic as used in OnPaint.
moel@345
   259
				int y = 0;
moel@345
   260
				if (UseColumns)
moel@345
   261
				{
moel@345
   262
					y += ColumnHeaderHeight;
moel@345
   263
					if (Columns.Count == 0)
moel@345
   264
						return;
moel@345
   265
				}
moel@345
   266
				int firstRowY = _rowLayout.GetRowBounds(FirstVisibleRow).Y;
moel@345
   267
				y -= firstRowY;
moel@345
   268
				gr.ResetTransform();
moel@345
   269
				gr.TranslateTransform(-OffsetX, y);
moel@345
   270
moel@345
   271
				DrawContext context = new DrawContext();
moel@345
   272
				context.Graphics = gr;
moel@345
   273
				for (int i = 0; i < _expandingNodes.Count; i++)
moel@345
   274
				{
moel@345
   275
					foreach (NodeControlInfo item in GetNodeControls(_expandingNodes[i]))
moel@345
   276
					{
moel@345
   277
						if (item.Control is ExpandingIcon)
moel@345
   278
						{
moel@345
   279
							Rectangle bounds = item.Bounds;
moel@345
   280
							if (item.Node.Parent == null && UseColumns)
moel@345
   281
								bounds.Location = Point.Empty; // display root expanding icon at 0,0
moel@345
   282
moel@345
   283
							context.Bounds = bounds;
moel@345
   284
							item.Control.Draw(item.Node, context);
moel@345
   285
						}
moel@345
   286
					}
moel@345
   287
				}
moel@345
   288
			}
moel@345
   289
		}
moel@345
   290
moel@345
   291
		#region Public Methods
moel@345
   292
moel@345
   293
		public TreePath GetPath(TreeNodeAdv node)
moel@345
   294
		{
moel@345
   295
			if (node == _root)
moel@345
   296
				return TreePath.Empty;
moel@345
   297
			else
moel@345
   298
			{
moel@345
   299
				Stack<object> stack = new Stack<object>();
moel@345
   300
				while (node != _root && node != null)
moel@345
   301
				{
moel@345
   302
					stack.Push(node.Tag);
moel@345
   303
					node = node.Parent;
moel@345
   304
				}
moel@345
   305
				return new TreePath(stack.ToArray());
moel@345
   306
			}
moel@345
   307
		}
moel@345
   308
moel@345
   309
		public TreeNodeAdv GetNodeAt(Point point)
moel@345
   310
		{
moel@345
   311
			NodeControlInfo info = GetNodeControlInfoAt(point);
moel@345
   312
			return info.Node;
moel@345
   313
		}
moel@345
   314
moel@345
   315
		public NodeControlInfo GetNodeControlInfoAt(Point point)
moel@345
   316
		{
moel@345
   317
			if (point.X < 0 || point.Y < 0)
moel@345
   318
				return NodeControlInfo.Empty;
moel@345
   319
moel@345
   320
			int row = _rowLayout.GetRowAt(point);
moel@345
   321
			if (row < RowCount && row >= 0)
moel@345
   322
				return GetNodeControlInfoAt(RowMap[row], point);
moel@345
   323
			else
moel@345
   324
				return NodeControlInfo.Empty;
moel@345
   325
		}
moel@345
   326
moel@345
   327
		private NodeControlInfo GetNodeControlInfoAt(TreeNodeAdv node, Point point)
moel@345
   328
		{
moel@345
   329
			Rectangle rect = _rowLayout.GetRowBounds(FirstVisibleRow);
moel@345
   330
			point.Y += (rect.Y - ColumnHeaderHeight);
moel@345
   331
			point.X += OffsetX;
moel@345
   332
			foreach (NodeControlInfo info in GetNodeControls(node))
moel@345
   333
				if (info.Bounds.Contains(point))
moel@345
   334
					return info;
moel@345
   335
moel@345
   336
			if (FullRowSelect)
moel@345
   337
				return new NodeControlInfo(null, Rectangle.Empty, node);
moel@345
   338
			else
moel@345
   339
				return NodeControlInfo.Empty;
moel@345
   340
		}
moel@345
   341
moel@345
   342
		public void BeginUpdate()
moel@345
   343
		{
moel@345
   344
			_suspendUpdate = true;
moel@345
   345
			SuspendSelectionEvent = true;
moel@345
   346
		}
moel@345
   347
moel@345
   348
		public void EndUpdate()
moel@345
   349
		{
moel@345
   350
			_suspendUpdate = false;
moel@345
   351
			if (_needFullUpdate)
moel@345
   352
				FullUpdate();
moel@345
   353
			else
moel@345
   354
				UpdateView();
moel@345
   355
			SuspendSelectionEvent = false;
moel@345
   356
		}
moel@345
   357
moel@345
   358
		public void ExpandAll()
moel@345
   359
		{
moel@345
   360
			_root.ExpandAll();
moel@345
   361
		}
moel@345
   362
moel@345
   363
		public void CollapseAll()
moel@345
   364
		{
moel@345
   365
			_root.CollapseAll();
moel@345
   366
		}
moel@345
   367
moel@345
   368
		/// <summary>
moel@345
   369
		/// Expand all parent nodes, andd scroll to the specified node
moel@345
   370
		/// </summary>
moel@345
   371
		public void EnsureVisible(TreeNodeAdv node)
moel@345
   372
		{
moel@345
   373
			if (node == null)
moel@345
   374
				throw new ArgumentNullException("node");
moel@345
   375
moel@345
   376
			if (!IsMyNode(node))
moel@345
   377
				throw new ArgumentException();
moel@345
   378
moel@345
   379
			TreeNodeAdv parent = node.Parent;
moel@345
   380
			while (parent != _root)
moel@345
   381
			{
moel@345
   382
				parent.IsExpanded = true;
moel@345
   383
				parent = parent.Parent;
moel@345
   384
			}
moel@345
   385
			ScrollTo(node);
moel@345
   386
		}
moel@345
   387
moel@345
   388
		/// <summary>
moel@345
   389
		/// Make node visible, scroll if needed. All parent nodes of the specified node must be expanded
moel@345
   390
		/// </summary>
moel@345
   391
		/// <param name="node"></param>
moel@345
   392
		public void ScrollTo(TreeNodeAdv node)
moel@345
   393
		{
moel@345
   394
			if (node == null)
moel@345
   395
				throw new ArgumentNullException("node");
moel@345
   396
moel@345
   397
			if (!IsMyNode(node))
moel@345
   398
				throw new ArgumentException();
moel@345
   399
moel@345
   400
			if (node.Row < 0)
moel@345
   401
				CreateRowMap();
moel@345
   402
moel@345
   403
			int row = -1;
moel@345
   404
moel@345
   405
			if (node.Row < FirstVisibleRow)
moel@345
   406
				row = node.Row;
moel@345
   407
			else
moel@345
   408
			{
moel@345
   409
				int pageStart = _rowLayout.GetRowBounds(FirstVisibleRow).Top;
moel@345
   410
				int rowBottom = _rowLayout.GetRowBounds(node.Row).Bottom;
moel@345
   411
				if (rowBottom > pageStart + DisplayRectangle.Height - ColumnHeaderHeight)
moel@345
   412
					row = _rowLayout.GetFirstRow(node.Row);
moel@345
   413
			}
moel@345
   414
moel@345
   415
			if (row >= _vScrollBar.Minimum && row <= _vScrollBar.Maximum)
moel@345
   416
				_vScrollBar.Value = row;
moel@345
   417
		}
moel@345
   418
moel@345
   419
		public void ClearSelection()
moel@345
   420
		{
moel@345
   421
			BeginUpdate();
moel@345
   422
			try
moel@345
   423
			{
moel@345
   424
				ClearSelectionInternal();
moel@345
   425
			}
moel@345
   426
			finally
moel@345
   427
			{
moel@345
   428
				EndUpdate();
moel@345
   429
			}
moel@345
   430
		}
moel@345
   431
moel@345
   432
		internal void ClearSelectionInternal()
moel@345
   433
		{
moel@345
   434
			while (Selection.Count > 0)
moel@345
   435
			{
moel@345
   436
				var t = Selection[0];
moel@345
   437
				t.IsSelected = false;
moel@345
   438
				Selection.Remove(t); //hack
moel@345
   439
			}
moel@345
   440
		}
moel@345
   441
moel@345
   442
		#endregion
moel@345
   443
moel@345
   444
		protected override void OnSizeChanged(EventArgs e)
moel@345
   445
		{
moel@345
   446
			ArrangeControls();
moel@345
   447
			SafeUpdateScrollBars();
moel@345
   448
			base.OnSizeChanged(e);
moel@345
   449
		}
moel@345
   450
moel@345
   451
		private void ArrangeControls()
moel@345
   452
		{
moel@345
   453
			int hBarSize = _hScrollBar.Height;
moel@345
   454
			int vBarSize = _vScrollBar.Width;
moel@345
   455
			Rectangle clientRect = ClientRectangle;
moel@345
   456
moel@345
   457
			_hScrollBar.SetBounds(clientRect.X, clientRect.Bottom - hBarSize,
moel@345
   458
				clientRect.Width - vBarSize, hBarSize);
moel@345
   459
moel@345
   460
			_vScrollBar.SetBounds(clientRect.Right - vBarSize, clientRect.Y,
moel@345
   461
				vBarSize, clientRect.Height - hBarSize);
moel@345
   462
		}
moel@345
   463
moel@345
   464
		private void SafeUpdateScrollBars()
moel@345
   465
		{
moel@345
   466
			if (InvokeRequired)
moel@345
   467
				BeginInvoke(new MethodInvoker(UpdateScrollBars));
moel@345
   468
			else
moel@345
   469
				UpdateScrollBars();
moel@345
   470
		}
moel@345
   471
moel@345
   472
		private void UpdateScrollBars()
moel@345
   473
		{
moel@345
   474
			UpdateVScrollBar();
moel@345
   475
			UpdateHScrollBar();
moel@345
   476
			UpdateVScrollBar();
moel@345
   477
			UpdateHScrollBar();
moel@345
   478
			_hScrollBar.Width = DisplayRectangle.Width;
moel@345
   479
			_vScrollBar.Height = DisplayRectangle.Height;
moel@345
   480
		}
moel@345
   481
moel@345
   482
		private void UpdateHScrollBar()
moel@345
   483
		{
moel@345
   484
			_hScrollBar.Maximum = ContentWidth;
moel@345
   485
			_hScrollBar.LargeChange = Math.Max(DisplayRectangle.Width, 0);
moel@345
   486
			_hScrollBar.SmallChange = 5;
moel@345
   487
			_hScrollBar.Visible = _hScrollBar.LargeChange < _hScrollBar.Maximum;
moel@345
   488
			_hScrollBar.Value = Math.Min(_hScrollBar.Value, _hScrollBar.Maximum - _hScrollBar.LargeChange + 1);
moel@345
   489
		}
moel@345
   490
moel@345
   491
		private void UpdateVScrollBar()
moel@345
   492
		{
moel@345
   493
			_vScrollBar.Maximum = Math.Max(RowCount - 1, 0);
moel@345
   494
			_vScrollBar.LargeChange = _rowLayout.PageRowCount;
moel@345
   495
			_vScrollBar.Visible = (RowCount > 0) && (_vScrollBar.LargeChange <= _vScrollBar.Maximum);
moel@345
   496
			_vScrollBar.Value = Math.Min(_vScrollBar.Value, _vScrollBar.Maximum - _vScrollBar.LargeChange + 1);
moel@345
   497
		}
moel@345
   498
moel@345
   499
		protected override CreateParams CreateParams
moel@345
   500
		{
moel@345
   501
			[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
moel@345
   502
			get
moel@345
   503
			{
moel@345
   504
				CreateParams res = base.CreateParams;
moel@345
   505
				switch (BorderStyle)
moel@345
   506
				{
moel@345
   507
					case BorderStyle.FixedSingle:
moel@345
   508
						res.Style |= 0x800000;
moel@345
   509
						break;
moel@345
   510
					case BorderStyle.Fixed3D:
moel@345
   511
						res.ExStyle |= 0x200;
moel@345
   512
						break;
moel@345
   513
				}
moel@345
   514
				return res;
moel@345
   515
			}
moel@345
   516
		}
moel@345
   517
moel@345
   518
		protected override void OnGotFocus(EventArgs e)
moel@345
   519
		{
moel@345
   520
			UpdateView();
moel@345
   521
			ChangeInput();
moel@345
   522
			base.OnGotFocus(e);
moel@345
   523
		}
moel@345
   524
moel@345
   525
		protected override void OnFontChanged(EventArgs e)
moel@345
   526
		{
moel@345
   527
			base.OnFontChanged(e);
moel@345
   528
			_measureContext.Font = Font;
moel@345
   529
			FullUpdate();
moel@345
   530
		}
moel@345
   531
moel@345
   532
		internal IEnumerable<NodeControlInfo> GetNodeControls(TreeNodeAdv node)
moel@345
   533
		{
moel@345
   534
			if (node == null)
moel@345
   535
				yield break;
moel@345
   536
			Rectangle rowRect = _rowLayout.GetRowBounds(node.Row);
moel@345
   537
			foreach (NodeControlInfo n in GetNodeControls(node, rowRect))
moel@345
   538
				yield return n;
moel@345
   539
		}
moel@345
   540
moel@345
   541
		internal IEnumerable<NodeControlInfo> GetNodeControls(TreeNodeAdv node, Rectangle rowRect)
moel@345
   542
		{
moel@345
   543
			if (node == null)
moel@345
   544
				yield break;
moel@345
   545
moel@345
   546
			int y = rowRect.Y;
moel@345
   547
			int x = (node.Level - 1) * _indent + LeftMargin;
moel@345
   548
			int width = 0;
moel@345
   549
			if (node.Row == 0 && ShiftFirstNode)
moel@345
   550
				x -= _indent;
moel@345
   551
			Rectangle rect = Rectangle.Empty;
moel@345
   552
moel@345
   553
			if (ShowPlusMinus)
moel@345
   554
			{
moel@345
   555
				width = _plusMinus.GetActualSize(node, _measureContext).Width;
moel@345
   556
				rect = new Rectangle(x, y, width, rowRect.Height);
moel@345
   557
				if (UseColumns && Columns.Count > 0 && Columns[0].Width < rect.Right)
moel@345
   558
					rect.Width = Columns[0].Width - x;
moel@345
   559
moel@345
   560
				yield return new NodeControlInfo(_plusMinus, rect, node);
moel@345
   561
				x += width;
moel@345
   562
			}
moel@345
   563
moel@345
   564
			if (!UseColumns)
moel@345
   565
			{
moel@345
   566
				foreach (NodeControl c in NodeControls)
moel@345
   567
				{
moel@345
   568
					Size s = c.GetActualSize(node, _measureContext);
moel@345
   569
					if (!s.IsEmpty)
moel@345
   570
					{
moel@345
   571
						width = s.Width;
moel@345
   572
						rect = new Rectangle(x, y, width, rowRect.Height);
moel@345
   573
						x += rect.Width;
moel@345
   574
						yield return new NodeControlInfo(c, rect, node);
moel@345
   575
					}
moel@345
   576
				}
moel@345
   577
			}
moel@345
   578
			else
moel@345
   579
			{
moel@345
   580
				int right = 0;
moel@345
   581
				foreach (TreeColumn col in Columns)
moel@345
   582
				{
moel@345
   583
					if (col.IsVisible && col.Width > 0)
moel@345
   584
					{
moel@345
   585
						right += col.Width;
moel@345
   586
						for (int i = 0; i < NodeControls.Count; i++)
moel@345
   587
						{
moel@345
   588
							NodeControl nc = NodeControls[i];
moel@345
   589
							if (nc.ParentColumn == col)
moel@345
   590
							{
moel@345
   591
								Size s = nc.GetActualSize(node, _measureContext);
moel@345
   592
								if (!s.IsEmpty)
moel@345
   593
								{
moel@345
   594
									bool isLastControl = true;
moel@345
   595
									for (int k = i + 1; k < NodeControls.Count; k++)
moel@345
   596
										if (NodeControls[k].ParentColumn == col)
moel@345
   597
										{
moel@345
   598
											isLastControl = false;
moel@345
   599
											break;
moel@345
   600
										}
moel@345
   601
moel@345
   602
									width = right - x;
moel@345
   603
									if (!isLastControl)
moel@345
   604
										width = s.Width;
moel@345
   605
									int maxWidth = Math.Max(0, right - x);
moel@345
   606
									rect = new Rectangle(x, y, Math.Min(maxWidth, width), rowRect.Height);
moel@345
   607
									x += width;
moel@345
   608
									yield return new NodeControlInfo(nc, rect, node);
moel@345
   609
								}
moel@345
   610
							}
moel@345
   611
						}
moel@345
   612
						x = right;
moel@345
   613
					}
moel@345
   614
				}
moel@345
   615
			}
moel@345
   616
		}
moel@345
   617
moel@345
   618
		internal static double Dist(Point p1, Point p2)
moel@345
   619
		{
moel@345
   620
			return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
moel@345
   621
		}
moel@345
   622
moel@345
   623
		public void FullUpdate()
moel@345
   624
		{
moel@345
   625
			HideEditor();
moel@345
   626
			if (InvokeRequired)
moel@345
   627
				BeginInvoke(new MethodInvoker(UnsafeFullUpdate));
moel@345
   628
			else
moel@345
   629
				UnsafeFullUpdate();
moel@345
   630
		}
moel@345
   631
moel@345
   632
		private void UnsafeFullUpdate()
moel@345
   633
		{
moel@345
   634
			_rowLayout.ClearCache();
moel@345
   635
			CreateRowMap();
moel@345
   636
			SafeUpdateScrollBars();
moel@345
   637
			UpdateView();
moel@345
   638
			_needFullUpdate = false;
moel@345
   639
		}
moel@345
   640
moel@345
   641
		internal void UpdateView()
moel@345
   642
		{
moel@345
   643
			if (!_suspendUpdate)
moel@345
   644
				Invalidate(false);
moel@345
   645
		}
moel@345
   646
moel@345
   647
		internal void UpdateHeaders()
moel@345
   648
		{
moel@345
   649
			Invalidate(new Rectangle(0, 0, Width, ColumnHeaderHeight));
moel@345
   650
		}
moel@345
   651
moel@345
   652
		internal void UpdateColumns()
moel@345
   653
		{
moel@345
   654
			FullUpdate();
moel@345
   655
		}
moel@345
   656
moel@345
   657
		private void CreateNodes()
moel@345
   658
		{
moel@345
   659
			Selection.Clear();
moel@345
   660
			SelectionStart = null;
moel@345
   661
			_root = new TreeNodeAdv(this, null);
moel@345
   662
			_root.IsExpanded = true;
moel@345
   663
			if (_root.Nodes.Count > 0)
moel@345
   664
				CurrentNode = _root.Nodes[0];
moel@345
   665
			else
moel@345
   666
				CurrentNode = null;
moel@345
   667
		}
moel@345
   668
moel@345
   669
		internal void ReadChilds(TreeNodeAdv parentNode)
moel@345
   670
		{
moel@345
   671
			ReadChilds(parentNode, false);
moel@345
   672
		}
moel@345
   673
moel@345
   674
		internal void ReadChilds(TreeNodeAdv parentNode, bool performFullUpdate)
moel@345
   675
		{
moel@345
   676
			if (!parentNode.IsLeaf)
moel@345
   677
			{
moel@345
   678
				parentNode.IsExpandedOnce = true;
moel@345
   679
				parentNode.Nodes.Clear();
moel@345
   680
moel@345
   681
				if (Model != null)
moel@345
   682
				{
moel@345
   683
					IEnumerable items = Model.GetChildren(GetPath(parentNode));
moel@345
   684
					if (items != null)
moel@345
   685
						foreach (object obj in items)
moel@345
   686
						{
moel@345
   687
							AddNewNode(parentNode, obj, -1);
moel@345
   688
							if (performFullUpdate)
moel@345
   689
								FullUpdate();
moel@345
   690
						}
moel@345
   691
				}
moel@345
   692
moel@345
   693
				if (parentNode.AutoExpandOnStructureChanged)
moel@345
   694
					parentNode.ExpandAll();
moel@345
   695
			}
moel@345
   696
		}
moel@345
   697
moel@345
   698
		private void AddNewNode(TreeNodeAdv parent, object tag, int index)
moel@345
   699
		{
moel@345
   700
			TreeNodeAdv node = new TreeNodeAdv(this, tag);
moel@345
   701
			AddNode(parent, index, node);
moel@345
   702
		}
moel@345
   703
moel@345
   704
		private void AddNode(TreeNodeAdv parent, int index, TreeNodeAdv node)
moel@345
   705
		{
moel@345
   706
			if (index >= 0 && index < parent.Nodes.Count)
moel@345
   707
				parent.Nodes.Insert(index, node);
moel@345
   708
			else
moel@345
   709
				parent.Nodes.Add(node);
moel@345
   710
moel@345
   711
			node.IsLeaf = Model.IsLeaf(GetPath(node));
moel@345
   712
			if (node.IsLeaf)
moel@345
   713
				node.Nodes.Clear();
moel@345
   714
			if (!LoadOnDemand || node.IsExpandedOnce)
moel@345
   715
				ReadChilds(node);
moel@345
   716
		}
moel@345
   717
moel@345
   718
		private struct ExpandArgs
moel@345
   719
		{
moel@345
   720
			public TreeNodeAdv Node;
moel@345
   721
			public bool Value;
moel@345
   722
			public bool IgnoreChildren;
moel@345
   723
		}
moel@345
   724
moel@345
   725
		public void AbortBackgroundExpandingThreads()
moel@345
   726
		{
moel@345
   727
			_threadPool.CancelAll(true);
moel@345
   728
			for (int i = 0; i < _expandingNodes.Count; i++)
moel@345
   729
				_expandingNodes[i].IsExpandingNow = false;
moel@345
   730
			_expandingNodes.Clear();
moel@345
   731
			Invalidate();
moel@345
   732
		}
moel@345
   733
moel@345
   734
		internal void SetIsExpanded(TreeNodeAdv node, bool value, bool ignoreChildren)
moel@345
   735
		{
moel@345
   736
			ExpandArgs eargs = new ExpandArgs();
moel@345
   737
			eargs.Node = node;
moel@345
   738
			eargs.Value = value;
moel@345
   739
			eargs.IgnoreChildren = ignoreChildren;
moel@345
   740
moel@345
   741
			if (AsyncExpanding && LoadOnDemand && !_threadPool.IsMyThread(Thread.CurrentThread))
moel@345
   742
			{
moel@345
   743
				WaitCallback wc = delegate(object argument) { SetIsExpanded((ExpandArgs)argument); };
moel@345
   744
				_threadPool.QueueUserWorkItem(wc, eargs);
moel@345
   745
			}
moel@345
   746
			else
moel@345
   747
				SetIsExpanded(eargs);
moel@345
   748
		}
moel@345
   749
moel@345
   750
		private void SetIsExpanded(ExpandArgs eargs)
moel@345
   751
		{
moel@345
   752
			bool update = !eargs.IgnoreChildren && !AsyncExpanding;
moel@345
   753
			if (update)
moel@345
   754
				BeginUpdate();
moel@345
   755
			try
moel@345
   756
			{
moel@345
   757
				if (IsMyNode(eargs.Node) && eargs.Node.IsExpanded != eargs.Value)
moel@345
   758
					SetIsExpanded(eargs.Node, eargs.Value);
moel@345
   759
moel@345
   760
				if (!eargs.IgnoreChildren)
moel@345
   761
					SetIsExpandedRecursive(eargs.Node, eargs.Value);
moel@345
   762
			}
moel@345
   763
			finally
moel@345
   764
			{
moel@345
   765
				if (update)
moel@345
   766
					EndUpdate();
moel@345
   767
			}
moel@345
   768
		}
moel@345
   769
moel@345
   770
		internal void SetIsExpanded(TreeNodeAdv node, bool value)
moel@345
   771
		{
moel@345
   772
			if (Root == node && !value)
moel@345
   773
				return; //Can't collapse root node
moel@345
   774
moel@345
   775
			if (value)
moel@345
   776
			{
moel@345
   777
				OnExpanding(node);
moel@345
   778
				node.OnExpanding();
moel@345
   779
			}
moel@345
   780
			else
moel@345
   781
			{
moel@345
   782
				OnCollapsing(node);
moel@345
   783
				node.OnCollapsing();
moel@345
   784
			}
moel@345
   785
moel@345
   786
			if (value && !node.IsExpandedOnce)
moel@345
   787
			{
moel@345
   788
				if (AsyncExpanding && LoadOnDemand)
moel@345
   789
				{
moel@345
   790
					AddExpandingNode(node);
moel@345
   791
					node.AssignIsExpanded(true);
moel@345
   792
					Invalidate();
moel@345
   793
				}
moel@345
   794
				ReadChilds(node, AsyncExpanding);
moel@345
   795
				RemoveExpandingNode(node);
moel@345
   796
			}
moel@345
   797
			node.AssignIsExpanded(value);
moel@345
   798
			SmartFullUpdate();
moel@345
   799
moel@345
   800
			if (value)
moel@345
   801
			{
moel@345
   802
				OnExpanded(node);
moel@345
   803
				node.OnExpanded();
moel@345
   804
			}
moel@345
   805
			else
moel@345
   806
			{
moel@345
   807
				OnCollapsed(node);
moel@345
   808
				node.OnCollapsed();
moel@345
   809
			}
moel@345
   810
		}
moel@345
   811
moel@345
   812
		private void RemoveExpandingNode(TreeNodeAdv node)
moel@345
   813
		{
moel@345
   814
			node.IsExpandingNow = false;
moel@345
   815
			_expandingNodes.Remove(node);
moel@345
   816
			if (_expandingNodes.Count <= 0)
moel@345
   817
				ExpandingIcon.Stop();
moel@345
   818
		}
moel@345
   819
moel@345
   820
		private void AddExpandingNode(TreeNodeAdv node)
moel@345
   821
		{
moel@345
   822
			node.IsExpandingNow = true;
moel@345
   823
			_expandingNodes.Add(node);
moel@345
   824
			ExpandingIcon.Start();
moel@345
   825
		}
moel@345
   826
moel@345
   827
		internal void SetIsExpandedRecursive(TreeNodeAdv root, bool value)
moel@345
   828
		{
moel@345
   829
			for (int i = 0; i < root.Nodes.Count; i++)
moel@345
   830
			{
moel@345
   831
				TreeNodeAdv node = root.Nodes[i];
moel@345
   832
				node.IsExpanded = value;
moel@345
   833
				SetIsExpandedRecursive(node, value);
moel@345
   834
			}
moel@345
   835
		}
moel@345
   836
moel@345
   837
		private void CreateRowMap()
moel@345
   838
		{
moel@345
   839
			RowMap.Clear();
moel@345
   840
			int row = 0;
moel@345
   841
			_contentWidth = 0;
moel@345
   842
			foreach (TreeNodeAdv node in VisibleNodes)
moel@345
   843
			{
moel@345
   844
				node.Row = row;
moel@345
   845
				RowMap.Add(node);
moel@345
   846
				if (!UseColumns)
moel@345
   847
				{
moel@345
   848
					_contentWidth = Math.Max(_contentWidth, GetNodeWidth(node));
moel@345
   849
				}
moel@345
   850
				row++;
moel@345
   851
			}
moel@345
   852
			if (UseColumns)
moel@345
   853
			{
moel@345
   854
				_contentWidth = 0;
moel@345
   855
				foreach (TreeColumn col in _columns)
moel@345
   856
					if (col.IsVisible)
moel@345
   857
						_contentWidth += col.Width;
moel@345
   858
			}
moel@345
   859
		}
moel@345
   860
moel@345
   861
		private int GetNodeWidth(TreeNodeAdv node)
moel@345
   862
		{
moel@345
   863
			if (node.RightBounds == null)
moel@345
   864
			{
moel@345
   865
				Rectangle res = GetNodeBounds(GetNodeControls(node, Rectangle.Empty));
moel@345
   866
				node.RightBounds = res.Right;
moel@345
   867
			}
moel@345
   868
			return node.RightBounds.Value;
moel@345
   869
		}
moel@345
   870
moel@345
   871
		internal Rectangle GetNodeBounds(TreeNodeAdv node)
moel@345
   872
		{
moel@345
   873
			return GetNodeBounds(GetNodeControls(node));
moel@345
   874
		}
moel@345
   875
moel@345
   876
		private Rectangle GetNodeBounds(IEnumerable<NodeControlInfo> nodeControls)
moel@345
   877
		{
moel@345
   878
			Rectangle res = Rectangle.Empty;
moel@345
   879
			foreach (NodeControlInfo info in nodeControls)
moel@345
   880
			{
moel@345
   881
				if (res == Rectangle.Empty)
moel@345
   882
					res = info.Bounds;
moel@345
   883
				else
moel@345
   884
					res = Rectangle.Union(res, info.Bounds);
moel@345
   885
			}
moel@345
   886
			return res;
moel@345
   887
		}
moel@345
   888
moel@345
   889
		private void _vScrollBar_ValueChanged(object sender, EventArgs e)
moel@345
   890
		{
moel@345
   891
			FirstVisibleRow = _vScrollBar.Value;
moel@345
   892
		}
moel@345
   893
moel@345
   894
		private void _hScrollBar_ValueChanged(object sender, EventArgs e)
moel@345
   895
		{
moel@345
   896
			OffsetX = _hScrollBar.Value;
moel@345
   897
		}
moel@345
   898
moel@345
   899
		private void _vScrollBar_Scroll(object sender, ScrollEventArgs e)
moel@345
   900
		{
moel@345
   901
			OnScroll(e);
moel@345
   902
		}
moel@345
   903
moel@345
   904
		private void _hScrollBar_Scroll(object sender, ScrollEventArgs e)
moel@345
   905
		{
moel@345
   906
			OnScroll(e);
moel@345
   907
		}
moel@345
   908
moel@345
   909
		internal void SmartFullUpdate()
moel@345
   910
		{
moel@345
   911
			if (_suspendUpdate)
moel@345
   912
				_needFullUpdate = true;
moel@345
   913
			else
moel@345
   914
				FullUpdate();
moel@345
   915
		}
moel@345
   916
moel@345
   917
		internal bool IsMyNode(TreeNodeAdv node)
moel@345
   918
		{
moel@345
   919
			if (node == null)
moel@345
   920
				return false;
moel@345
   921
moel@345
   922
			if (node.Tree != this)
moel@345
   923
				return false;
moel@345
   924
moel@345
   925
			while (node.Parent != null)
moel@345
   926
				node = node.Parent;
moel@345
   927
moel@345
   928
			return node == _root;
moel@345
   929
		}
moel@345
   930
moel@345
   931
		internal void UpdateSelection()
moel@345
   932
		{
moel@345
   933
			bool flag = false;
moel@345
   934
moel@345
   935
			if (!IsMyNode(CurrentNode))
moel@345
   936
				CurrentNode = null;
moel@345
   937
			if (!IsMyNode(_selectionStart))
moel@345
   938
				_selectionStart = null;
moel@345
   939
moel@345
   940
			for (int i = Selection.Count - 1; i >= 0; i--)
moel@345
   941
				if (!IsMyNode(Selection[i]))
moel@345
   942
				{
moel@345
   943
					flag = true;
moel@345
   944
					Selection.RemoveAt(i);
moel@345
   945
				}
moel@345
   946
moel@345
   947
			if (flag)
moel@345
   948
				OnSelectionChanged();
moel@345
   949
		}
moel@345
   950
moel@345
   951
		internal void ChangeColumnWidth(TreeColumn column)
moel@345
   952
		{
moel@345
   953
			if (!(_input is ResizeColumnState))
moel@345
   954
			{
moel@345
   955
				FullUpdate();
moel@345
   956
				OnColumnWidthChanged(column);
moel@345
   957
			}
moel@345
   958
		}
moel@345
   959
moel@345
   960
		public TreeNodeAdv FindNode(TreePath path)
moel@345
   961
		{
moel@345
   962
			return FindNode(path, false);
moel@345
   963
		}
moel@345
   964
moel@345
   965
		public TreeNodeAdv FindNode(TreePath path, bool readChilds)
moel@345
   966
		{
moel@345
   967
			if (path.IsEmpty())
moel@345
   968
				return _root;
moel@345
   969
			else
moel@345
   970
				return FindNode(_root, path, 0, readChilds);
moel@345
   971
		}
moel@345
   972
moel@345
   973
		private TreeNodeAdv FindNode(TreeNodeAdv root, TreePath path, int level, bool readChilds)
moel@345
   974
		{
moel@345
   975
			if (!root.IsExpandedOnce && readChilds)
moel@345
   976
				ReadChilds(root);
moel@345
   977
moel@345
   978
			for (int i = 0; i < root.Nodes.Count; i++)
moel@345
   979
			{
moel@345
   980
				TreeNodeAdv node = root.Nodes[i];
moel@345
   981
				if (node.Tag == path.FullPath[level])
moel@345
   982
				{
moel@345
   983
					if (level == path.FullPath.Length - 1)
moel@345
   984
						return node;
moel@345
   985
					else
moel@345
   986
						return FindNode(node, path, level + 1, readChilds);
moel@345
   987
				}
moel@345
   988
			}
moel@345
   989
			return null;
moel@345
   990
		}
moel@345
   991
moel@345
   992
		public TreeNodeAdv FindNodeByTag(object tag)
moel@345
   993
		{
moel@345
   994
			return FindNodeByTag(_root, tag);
moel@345
   995
		}
moel@345
   996
moel@345
   997
		private TreeNodeAdv FindNodeByTag(TreeNodeAdv root, object tag)
moel@345
   998
		{
moel@345
   999
			foreach (TreeNodeAdv node in root.Nodes)
moel@345
  1000
			{
moel@345
  1001
				if (node.Tag == tag)
moel@345
  1002
					return node;
moel@345
  1003
				TreeNodeAdv res = FindNodeByTag(node, tag);
moel@345
  1004
				if (res != null)
moel@345
  1005
					return res;
moel@345
  1006
			}
moel@345
  1007
			return null;
moel@345
  1008
		}
moel@345
  1009
moel@345
  1010
		public void SelectAllNodes()
moel@345
  1011
		{
moel@345
  1012
			SuspendSelectionEvent = true;
moel@345
  1013
			try
moel@345
  1014
			{
moel@345
  1015
				if (SelectionMode == TreeSelectionMode.MultiSameParent)
moel@345
  1016
				{
moel@345
  1017
					if (CurrentNode != null)
moel@345
  1018
					{
moel@345
  1019
						foreach (TreeNodeAdv n in CurrentNode.Parent.Nodes)
moel@345
  1020
							n.IsSelected = true;
moel@345
  1021
					}
moel@345
  1022
				}
moel@345
  1023
				else if (SelectionMode == TreeSelectionMode.Multi)
moel@345
  1024
				{
moel@345
  1025
					SelectNodes(Root.Nodes);
moel@345
  1026
				}
moel@345
  1027
			}
moel@345
  1028
			finally
moel@345
  1029
			{
moel@345
  1030
				SuspendSelectionEvent = false;
moel@345
  1031
			}
moel@345
  1032
		}
moel@345
  1033
moel@345
  1034
		private void SelectNodes(Collection<TreeNodeAdv> nodes)
moel@345
  1035
		{
moel@345
  1036
			foreach (TreeNodeAdv n in nodes)
moel@345
  1037
			{
moel@345
  1038
				n.IsSelected = true;
moel@345
  1039
				if (n.IsExpanded)
moel@345
  1040
					SelectNodes(n.Nodes);
moel@345
  1041
			}
moel@345
  1042
		}
moel@345
  1043
moel@345
  1044
		#region ModelEvents
moel@345
  1045
		private void BindModelEvents()
moel@345
  1046
		{
moel@345
  1047
			_model.NodesChanged += new EventHandler<TreeModelEventArgs>(_model_NodesChanged);
moel@345
  1048
			_model.NodesInserted += new EventHandler<TreeModelEventArgs>(_model_NodesInserted);
moel@345
  1049
			_model.NodesRemoved += new EventHandler<TreeModelEventArgs>(_model_NodesRemoved);
moel@345
  1050
			_model.StructureChanged += new EventHandler<TreePathEventArgs>(_model_StructureChanged);
moel@345
  1051
		}
moel@345
  1052
moel@345
  1053
		private void UnbindModelEvents()
moel@345
  1054
		{
moel@345
  1055
			_model.NodesChanged -= new EventHandler<TreeModelEventArgs>(_model_NodesChanged);
moel@345
  1056
			_model.NodesInserted -= new EventHandler<TreeModelEventArgs>(_model_NodesInserted);
moel@345
  1057
			_model.NodesRemoved -= new EventHandler<TreeModelEventArgs>(_model_NodesRemoved);
moel@345
  1058
			_model.StructureChanged -= new EventHandler<TreePathEventArgs>(_model_StructureChanged);
moel@345
  1059
		}
moel@345
  1060
moel@345
  1061
		private void _model_StructureChanged(object sender, TreePathEventArgs e)
moel@345
  1062
		{
moel@345
  1063
			if (e.Path == null)
moel@345
  1064
				throw new ArgumentNullException();
moel@345
  1065
moel@345
  1066
			TreeNodeAdv node = FindNode(e.Path);
moel@345
  1067
			if (node != null)
moel@345
  1068
			{
moel@345
  1069
				if (node != Root)
moel@345
  1070
					node.IsLeaf = Model.IsLeaf(GetPath(node));
moel@345
  1071
moel@345
  1072
				var list = new Dictionary<object, object>();
moel@345
  1073
				SaveExpandedNodes(node, list);
moel@345
  1074
				ReadChilds(node);
moel@345
  1075
				RestoreExpandedNodes(node, list);
moel@345
  1076
moel@345
  1077
				UpdateSelection();
moel@345
  1078
				SmartFullUpdate();
moel@345
  1079
			}
moel@345
  1080
			//else 
moel@345
  1081
			//	throw new ArgumentException("Path not found");
moel@345
  1082
		}
moel@345
  1083
moel@345
  1084
		private void RestoreExpandedNodes(TreeNodeAdv node, Dictionary<object, object> list)
moel@345
  1085
		{
moel@345
  1086
			if (node.Tag != null && list.ContainsKey(node.Tag))
moel@345
  1087
			{
moel@345
  1088
				node.IsExpanded = true;
moel@345
  1089
				foreach (var child in node.Children)
moel@345
  1090
					RestoreExpandedNodes(child, list);
moel@345
  1091
			}
moel@345
  1092
		}
moel@345
  1093
moel@345
  1094
		private void SaveExpandedNodes(TreeNodeAdv node, Dictionary<object, object> list)
moel@345
  1095
		{
moel@345
  1096
			if (node.IsExpanded && node.Tag != null)
moel@345
  1097
			{
moel@345
  1098
				list.Add(node.Tag, null);
moel@345
  1099
				foreach (var child in node.Children)
moel@345
  1100
					SaveExpandedNodes(child, list);
moel@345
  1101
			}
moel@345
  1102
		}
moel@345
  1103
moel@345
  1104
		private void _model_NodesRemoved(object sender, TreeModelEventArgs e)
moel@345
  1105
		{
moel@345
  1106
			TreeNodeAdv parent = FindNode(e.Path);
moel@345
  1107
			if (parent != null)
moel@345
  1108
			{
moel@345
  1109
				if (e.Indices != null)
moel@345
  1110
				{
moel@345
  1111
					List<int> list = new List<int>(e.Indices);
moel@345
  1112
					list.Sort();
moel@345
  1113
					for (int n = list.Count - 1; n >= 0; n--)
moel@345
  1114
					{
moel@345
  1115
						int index = list[n];
moel@345
  1116
						if (index >= 0 && index <= parent.Nodes.Count)
moel@345
  1117
							parent.Nodes.RemoveAt(index);
moel@345
  1118
						else
moel@345
  1119
							throw new ArgumentOutOfRangeException("Index out of range");
moel@345
  1120
					}
moel@345
  1121
				}
moel@345
  1122
				else
moel@345
  1123
				{
moel@345
  1124
					for (int i = parent.Nodes.Count - 1; i >= 0; i--)
moel@345
  1125
					{
moel@345
  1126
						for (int n = 0; n < e.Children.Length; n++)
moel@345
  1127
							if (parent.Nodes[i].Tag == e.Children[n])
moel@345
  1128
							{
moel@345
  1129
								parent.Nodes.RemoveAt(i);
moel@345
  1130
								break;
moel@345
  1131
							}
moel@345
  1132
					}
moel@345
  1133
				}
moel@345
  1134
			}
moel@345
  1135
			UpdateSelection();
moel@345
  1136
			SmartFullUpdate();
moel@345
  1137
		}
moel@345
  1138
moel@345
  1139
		private void _model_NodesInserted(object sender, TreeModelEventArgs e)
moel@345
  1140
		{
moel@345
  1141
			if (e.Indices == null)
moel@345
  1142
				throw new ArgumentNullException("Indices");
moel@345
  1143
moel@345
  1144
			TreeNodeAdv parent = FindNode(e.Path);
moel@345
  1145
			if (parent != null)
moel@345
  1146
			{
moel@345
  1147
				for (int i = 0; i < e.Children.Length; i++)
moel@345
  1148
					AddNewNode(parent, e.Children[i], e.Indices[i]);
moel@345
  1149
			}
moel@345
  1150
			SmartFullUpdate();
moel@345
  1151
		}
moel@345
  1152
moel@345
  1153
		private void _model_NodesChanged(object sender, TreeModelEventArgs e)
moel@345
  1154
		{
moel@345
  1155
			TreeNodeAdv parent = FindNode(e.Path);
moel@345
  1156
			if (parent != null && parent.IsVisible && parent.IsExpanded)
moel@345
  1157
			{
moel@345
  1158
				if (InvokeRequired)
moel@345
  1159
					BeginInvoke(new UpdateContentWidthDelegate(ClearNodesSize), e, parent);
moel@345
  1160
				else
moel@345
  1161
					ClearNodesSize(e, parent);
moel@345
  1162
				SmartFullUpdate();
moel@345
  1163
			}
moel@345
  1164
		}
moel@345
  1165
moel@345
  1166
		private delegate void UpdateContentWidthDelegate(TreeModelEventArgs e, TreeNodeAdv parent);
moel@345
  1167
		private void ClearNodesSize(TreeModelEventArgs e, TreeNodeAdv parent)
moel@345
  1168
		{
moel@345
  1169
			if (e.Indices != null)
moel@345
  1170
			{
moel@345
  1171
				foreach (int index in e.Indices)
moel@345
  1172
				{
moel@345
  1173
					if (index >= 0 && index < parent.Nodes.Count)
moel@345
  1174
					{
moel@345
  1175
						TreeNodeAdv node = parent.Nodes[index];
moel@345
  1176
						node.Height = node.RightBounds = null;
moel@345
  1177
					}
moel@345
  1178
					else
moel@345
  1179
						throw new ArgumentOutOfRangeException("Index out of range");
moel@345
  1180
				}
moel@345
  1181
			}
moel@345
  1182
			else
moel@345
  1183
			{
moel@345
  1184
				foreach (TreeNodeAdv node in parent.Nodes)
moel@345
  1185
				{
moel@345
  1186
					foreach (object obj in e.Children)
moel@345
  1187
						if (node.Tag == obj)
moel@345
  1188
						{
moel@345
  1189
							node.Height = node.RightBounds = null;
moel@345
  1190
						}
moel@345
  1191
				}
moel@345
  1192
			}
moel@345
  1193
		}
moel@345
  1194
		#endregion
moel@345
  1195
	}
moel@345
  1196
}