External/Aga.Controls/Tree/TreeViewAdv.Draw.cs
author Stephane Lenclud
Sat, 30 Jan 2016 23:01:51 +0100
branchMiniDisplay
changeset 454 f84878f52cd9
parent 345 0c551e8818e0
permissions -rw-r--r--
Disabling Nuvoton NCT6791D because of fan full speed bug on Asus Z97 WS.
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
}