External/Aga.Controls/Tree/TreeViewAdv.cs
author StephaneLenclud
Thu, 18 Apr 2013 23:25:10 +0200
branchMiniDisplay
changeset 444 9b09e2ee0968
permissions -rw-r--r--
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.
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
}