External/Aga.Controls/Tree/TreeViewAdv.Draw.cs
author StephaneLenclud
Sun, 03 Feb 2013 18:01:50 +0100
branchMiniDisplay
changeset 433 090259cfd699
parent 345 0c551e8818e0
permissions -rw-r--r--
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
moel@345
     1
using System;
moel@345
     2
using System.Drawing;
moel@345
     3
using System.Diagnostics;
moel@345
     4
using System.Drawing.Drawing2D;
moel@345
     5
using System.Windows.Forms;
moel@345
     6
using Aga.Controls.Tree.NodeControls;
moel@345
     7
moel@345
     8
namespace Aga.Controls.Tree
moel@345
     9
{
moel@345
    10
	public partial class TreeViewAdv
moel@345
    11
	{
moel@345
    12
		public void AutoSizeColumn(TreeColumn column)
moel@345
    13
		{
moel@345
    14
			if (!Columns.Contains(column))
moel@345
    15
				throw new ArgumentException("column");
moel@345
    16
moel@345
    17
			DrawContext context = new DrawContext();
moel@345
    18
			context.Graphics = Graphics.FromImage(new Bitmap(1, 1));
moel@345
    19
			context.Font = this.Font;
moel@345
    20
			int res = 0;
moel@345
    21
			for (int row = 0; row < RowCount; row++)
moel@345
    22
			{
moel@345
    23
				if (row < RowMap.Count)
moel@345
    24
				{
moel@345
    25
					int w = 0;
moel@345
    26
					TreeNodeAdv node = RowMap[row];
moel@345
    27
					foreach (NodeControl nc in NodeControls)
moel@345
    28
					{
moel@345
    29
						if (nc.ParentColumn == column)
moel@345
    30
							w += nc.GetActualSize(node, _measureContext).Width;
moel@345
    31
					}
moel@345
    32
					res = Math.Max(res, w);
moel@345
    33
				}
moel@345
    34
			}
moel@345
    35
moel@345
    36
			if (res > 0)
moel@345
    37
				column.Width = res;
moel@345
    38
		}
moel@345
    39
moel@345
    40
		private void CreatePens()
moel@345
    41
		{
moel@345
    42
			CreateLinePen();
moel@345
    43
			CreateMarkPen();
moel@345
    44
		}
moel@345
    45
moel@345
    46
		private void CreateMarkPen()
moel@345
    47
		{
moel@345
    48
			GraphicsPath path = new GraphicsPath();
moel@345
    49
			path.AddLines(new Point[] { new Point(0, 0), new Point(1, 1), new Point(-1, 1), new Point(0, 0) });
moel@345
    50
			CustomLineCap cap = new CustomLineCap(null, path);
moel@345
    51
			cap.WidthScale = 1.0f;
moel@345
    52
moel@345
    53
			_markPen = new Pen(_dragDropMarkColor, _dragDropMarkWidth);
moel@345
    54
			_markPen.CustomStartCap = cap;
moel@345
    55
			_markPen.CustomEndCap = cap;
moel@345
    56
		}
moel@345
    57
moel@345
    58
		private void CreateLinePen()
moel@345
    59
		{
moel@345
    60
			_linePen = new Pen(_lineColor);
moel@345
    61
			_linePen.DashStyle = DashStyle.Dot;
moel@345
    62
		}
moel@345
    63
moel@345
    64
        protected override void OnPaint(PaintEventArgs e)
moel@345
    65
        {
moel@345
    66
            BeginPerformanceCount();
moel@345
    67
			PerformanceAnalyzer.Start("OnPaint");
moel@345
    68
moel@345
    69
            DrawContext context = new DrawContext();
moel@345
    70
            context.Graphics = e.Graphics;
moel@345
    71
            context.Font = this.Font;
moel@345
    72
            context.Enabled = Enabled;
moel@345
    73
moel@345
    74
            int y = 0;
moel@345
    75
            int gridHeight = 0;
moel@345
    76
moel@345
    77
            if (UseColumns)
moel@345
    78
            {
moel@345
    79
				DrawColumnHeaders(e.Graphics);
moel@345
    80
				y += ColumnHeaderHeight;
moel@345
    81
                if (Columns.Count == 0 || e.ClipRectangle.Height <= y)
moel@345
    82
                    return;
moel@345
    83
            }
moel@345
    84
moel@345
    85
			int firstRowY = _rowLayout.GetRowBounds(FirstVisibleRow).Y;
moel@345
    86
            y -= firstRowY;
moel@345
    87
moel@345
    88
            e.Graphics.ResetTransform();
moel@345
    89
            e.Graphics.TranslateTransform(-OffsetX, y);
moel@345
    90
            Rectangle displayRect = DisplayRectangle;
moel@345
    91
            for (int row = FirstVisibleRow; row < RowCount; row++)
moel@345
    92
            {
moel@345
    93
                Rectangle rowRect = _rowLayout.GetRowBounds(row);
moel@345
    94
                gridHeight += rowRect.Height;
moel@345
    95
                if (rowRect.Y + y > displayRect.Bottom)
moel@345
    96
                    break;
moel@345
    97
                else
moel@345
    98
                    DrawRow(e, ref context, row, rowRect);
moel@345
    99
            }
moel@345
   100
moel@345
   101
			if ((GridLineStyle & GridLineStyle.Vertical) == GridLineStyle.Vertical && UseColumns)
moel@345
   102
				DrawVerticalGridLines(e.Graphics, firstRowY);
moel@345
   103
moel@345
   104
			if (_dropPosition.Node != null && DragMode && HighlightDropPosition)
moel@345
   105
                DrawDropMark(e.Graphics);
moel@345
   106
moel@345
   107
            e.Graphics.ResetTransform();
moel@345
   108
            DrawScrollBarsBox(e.Graphics);
moel@345
   109
moel@345
   110
            if (DragMode && _dragBitmap != null)
moel@345
   111
                e.Graphics.DrawImage(_dragBitmap, PointToClient(MousePosition));
moel@345
   112
moel@345
   113
			PerformanceAnalyzer.Finish("OnPaint");
moel@345
   114
			EndPerformanceCount(e);
moel@345
   115
        }
moel@345
   116
moel@345
   117
		private void DrawRow(PaintEventArgs e, ref DrawContext context, int row, Rectangle rowRect)
moel@345
   118
		{
moel@345
   119
			TreeNodeAdv node = RowMap[row];
moel@345
   120
			context.DrawSelection = DrawSelectionMode.None;
moel@345
   121
			context.CurrentEditorOwner = CurrentEditorOwner;
moel@345
   122
			if (DragMode)
moel@345
   123
			{
moel@345
   124
				if ((_dropPosition.Node == node) && _dropPosition.Position == NodePosition.Inside && HighlightDropPosition)
moel@345
   125
					context.DrawSelection = DrawSelectionMode.Active;
moel@345
   126
			}
moel@345
   127
			else
moel@345
   128
			{
moel@345
   129
				if (node.IsSelected && Focused)
moel@345
   130
					context.DrawSelection = DrawSelectionMode.Active;
moel@345
   131
				else if (node.IsSelected && !Focused && !HideSelection)
moel@345
   132
					context.DrawSelection = DrawSelectionMode.Inactive;
moel@345
   133
			}
moel@345
   134
			context.DrawFocus = Focused && CurrentNode == node;
moel@345
   135
			
moel@345
   136
			OnRowDraw(e, node, context, row, rowRect);
moel@345
   137
moel@346
   138
			if ((GridLineStyle & GridLineStyle.Horizontal) == GridLineStyle.Horizontal) {
moel@346
   139
				e.Graphics.DrawLine(LightGrayPen, 0, rowRect.Bottom, e.Graphics.ClipBounds.Right, rowRect.Bottom);
moel@346
   140
      }
moel@346
   141
moel@345
   142
			if (FullRowSelect)
moel@345
   143
			{
moel@345
   144
				context.DrawFocus = false;
moel@345
   145
				if (context.DrawSelection == DrawSelectionMode.Active || context.DrawSelection == DrawSelectionMode.Inactive)
moel@345
   146
				{
moel@345
   147
					Rectangle focusRect = new Rectangle(OffsetX, rowRect.Y, ClientRectangle.Width, rowRect.Height);
moel@345
   148
					if (context.DrawSelection == DrawSelectionMode.Active)
moel@345
   149
					{
moel@346
   150
						e.Graphics.FillRectangle(GrayBrush, focusRect);
moel@345
   151
						context.DrawSelection = DrawSelectionMode.FullRowSelect;
moel@345
   152
					}
moel@345
   153
					else
moel@345
   154
					{
moel@346
   155
						e.Graphics.FillRectangle(GrayBrush, focusRect);
moel@345
   156
						context.DrawSelection = DrawSelectionMode.None;
moel@345
   157
					}
moel@345
   158
				}
moel@345
   159
			}
moel@345
   160
moel@345
   161
			if (ShowLines)
moel@345
   162
				DrawLines(e.Graphics, node, rowRect);
moel@345
   163
moel@345
   164
			DrawNode(node, context);
moel@345
   165
		}
moel@345
   166
moel@346
   167
		private Brush GrayBrush = new SolidBrush(Color.FromArgb(240, 240, 240));
moel@346
   168
		private Pen LightGrayPen = new Pen(Color.FromArgb(247, 247, 247));
moel@346
   169
moel@345
   170
		private void DrawVerticalGridLines(Graphics gr, int y)
moel@345
   171
		{
moel@345
   172
			int x = 0;
moel@345
   173
			foreach (TreeColumn c in Columns)
moel@345
   174
			{
moel@345
   175
				if (c.IsVisible)
moel@345
   176
				{
moel@345
   177
					x += c.Width;
moel@345
   178
					gr.DrawLine(SystemPens.InactiveBorder, x - 1, y, x - 1, gr.ClipBounds.Bottom);
moel@345
   179
				}
moel@345
   180
			}
moel@345
   181
		}
moel@345
   182
moel@345
   183
		private void DrawColumnHeaders(Graphics gr)
moel@345
   184
		{
moel@345
   185
			PerformanceAnalyzer.Start("DrawColumnHeaders");
moel@345
   186
			ReorderColumnState reorder = Input as ReorderColumnState;
moel@345
   187
			int x = 0;
moel@345
   188
			TreeColumn.DrawBackground(gr, new Rectangle(0, 0, ClientRectangle.Width + 2, ColumnHeaderHeight - 1), false, false);
moel@345
   189
			gr.TranslateTransform(-OffsetX, 0);
moel@345
   190
			foreach (TreeColumn c in Columns)
moel@345
   191
			{
moel@345
   192
				if (c.IsVisible)
moel@345
   193
				{
moel@345
   194
					if (x >= OffsetX && x - OffsetX < this.Bounds.Width)// skip invisible columns
moel@345
   195
					{
moel@345
   196
						Rectangle rect = new Rectangle(x, 0, c.Width, ColumnHeaderHeight - 1);
moel@345
   197
						gr.SetClip(rect);
moel@345
   198
						bool pressed = ((Input is ClickColumnState || reorder != null) && ((Input as ColumnState).Column == c));
moel@345
   199
						c.Draw(gr, rect, Font, pressed, _hotColumn == c);
moel@345
   200
						gr.ResetClip();
moel@345
   201
moel@345
   202
						if (reorder != null && reorder.DropColumn == c)
moel@345
   203
							TreeColumn.DrawDropMark(gr, rect);
moel@345
   204
					}
moel@345
   205
					x += c.Width;
moel@345
   206
				}
moel@345
   207
			}
moel@345
   208
moel@345
   209
			if (reorder != null)
moel@345
   210
			{
moel@345
   211
				if (reorder.DropColumn == null)
moel@345
   212
					TreeColumn.DrawDropMark(gr, new Rectangle(x, 0, 0, ColumnHeaderHeight));
moel@345
   213
				gr.DrawImage(reorder.GhostImage, new Point(reorder.Location.X +  + reorder.DragOffset, reorder.Location.Y));
moel@345
   214
			}
moel@345
   215
			PerformanceAnalyzer.Finish("DrawColumnHeaders");
moel@345
   216
		}
moel@345
   217
moel@345
   218
		public void DrawNode(TreeNodeAdv node, DrawContext context)
moel@345
   219
		{
moel@345
   220
			foreach (NodeControlInfo item in GetNodeControls(node))
moel@345
   221
			{
moel@345
   222
				if (item.Bounds.Right >= OffsetX && item.Bounds.X - OffsetX < this.Bounds.Width)// skip invisible nodes
moel@345
   223
				{
moel@345
   224
					context.Bounds = item.Bounds;
moel@345
   225
					context.Graphics.SetClip(context.Bounds);
moel@345
   226
					item.Control.Draw(node, context);
moel@345
   227
					context.Graphics.ResetClip();
moel@345
   228
				}
moel@345
   229
			}
moel@345
   230
		}
moel@345
   231
moel@345
   232
		private void DrawScrollBarsBox(Graphics gr)
moel@345
   233
		{
moel@345
   234
			Rectangle r1 = DisplayRectangle;
moel@345
   235
			Rectangle r2 = ClientRectangle;
moel@345
   236
			gr.FillRectangle(SystemBrushes.Control,
moel@345
   237
				new Rectangle(r1.Right, r1.Bottom, r2.Width - r1.Width, r2.Height - r1.Height));
moel@345
   238
		}
moel@345
   239
moel@345
   240
		private void DrawDropMark(Graphics gr)
moel@345
   241
		{
moel@345
   242
			if (_dropPosition.Position == NodePosition.Inside)
moel@345
   243
				return;
moel@345
   244
moel@345
   245
			Rectangle rect = GetNodeBounds(_dropPosition.Node);
moel@345
   246
			int right = DisplayRectangle.Right - LeftMargin + OffsetX;
moel@345
   247
			int y = rect.Y;
moel@345
   248
			if (_dropPosition.Position == NodePosition.After)
moel@345
   249
				y = rect.Bottom;
moel@345
   250
			gr.DrawLine(_markPen, rect.X, y, right, y);
moel@345
   251
		}
moel@345
   252
moel@345
   253
		private void DrawLines(Graphics gr, TreeNodeAdv node, Rectangle rowRect)
moel@345
   254
		{
moel@345
   255
			if (UseColumns && Columns.Count > 0)
moel@345
   256
				gr.SetClip(new Rectangle(0, rowRect.Y, Columns[0].Width, rowRect.Bottom));
moel@345
   257
moel@345
   258
			TreeNodeAdv curNode = node;
moel@345
   259
			while (curNode != _root && curNode != null)
moel@345
   260
			{
moel@345
   261
				int level = curNode.Level;
moel@345
   262
				int x = (level - 1) * _indent + NodePlusMinus.ImageSize / 2 + LeftMargin;
moel@345
   263
				int width = NodePlusMinus.Width - NodePlusMinus.ImageSize / 2;
moel@345
   264
				int y = rowRect.Y;
moel@345
   265
				int y2 = y + rowRect.Height;
moel@345
   266
moel@345
   267
				if (curNode == node)
moel@345
   268
				{
moel@345
   269
					int midy = y + rowRect.Height / 2;
moel@345
   270
					gr.DrawLine(_linePen, x, midy, x + width, midy);
moel@345
   271
					if (curNode.NextNode == null)
moel@345
   272
						y2 = y + rowRect.Height / 2;
moel@345
   273
				}
moel@345
   274
moel@345
   275
				if (node.Row == 0)
moel@345
   276
					y = rowRect.Height / 2;
moel@345
   277
				if (curNode.NextNode != null || curNode == node)
moel@345
   278
					gr.DrawLine(_linePen, x, y, x, y2);
moel@345
   279
moel@345
   280
				curNode = curNode.Parent;
moel@345
   281
			}
moel@345
   282
moel@345
   283
			gr.ResetClip();
moel@345
   284
		}
moel@345
   285
moel@345
   286
		#region Performance
moel@345
   287
moel@345
   288
		private double _totalTime;
moel@345
   289
		private int _paintCount;
moel@345
   290
moel@345
   291
		[Conditional("PERF_TEST")]
moel@345
   292
		private void BeginPerformanceCount()
moel@345
   293
		{
moel@345
   294
			_paintCount++;
moel@345
   295
			TimeCounter.Start();
moel@345
   296
		}
moel@345
   297
moel@345
   298
		[Conditional("PERF_TEST")]
moel@345
   299
		private void EndPerformanceCount(PaintEventArgs e)
moel@345
   300
		{
moel@345
   301
			double time = TimeCounter.Finish();
moel@345
   302
			_totalTime += time;
moel@345
   303
			string debugText = string.Format("FPS {0:0.0}; Avg. FPS {1:0.0}",
moel@345
   304
				1 / time, 1 / (_totalTime / _paintCount));
moel@345
   305
			e.Graphics.FillRectangle(Brushes.White, new Rectangle(DisplayRectangle.Width - 150, DisplayRectangle.Height - 20, 150, 20));
moel@345
   306
			e.Graphics.DrawString(debugText, Control.DefaultFont, Brushes.Gray,
moel@345
   307
				new PointF(DisplayRectangle.Width - 150, DisplayRectangle.Height - 20));
moel@345
   308
		}
moel@345
   309
		#endregion
moel@345
   310
moel@345
   311
	}
moel@345
   312
}