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