External/Aga.Controls/Tree/TreeColumn.cs
author sl
Thu, 01 Jan 2015 23:35:49 +0100
changeset 405 5715aefd2bcc
permissions -rw-r--r--
SharpDisplay: Migrating to new robust client scheme.
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 using System.ComponentModel;
     5 using System.Windows.Forms;
     6 using System.Drawing;
     7 using System.Windows.Forms.VisualStyles;
     8 using System.Drawing.Imaging;
     9 
    10 namespace Aga.Controls.Tree
    11 {
    12 	[TypeConverter(typeof(TreeColumn.TreeColumnConverter)), DesignTimeVisible(false), ToolboxItem(false)]
    13 	public class TreeColumn : Component
    14 	{
    15 		private class TreeColumnConverter : ComponentConverter
    16 		{
    17 			public TreeColumnConverter()
    18 				: base(typeof(TreeColumn))
    19 			{
    20 			}
    21 
    22 			public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    23 			{
    24 				return false;
    25 			}
    26 		}
    27 
    28 		private const int HeaderLeftMargin = 5;
    29         private const int HeaderRightMargin = 5;   
    30 		private const int SortOrderMarkMargin = 8;
    31 
    32         private TextFormatFlags _headerFlags;
    33         private TextFormatFlags _baseHeaderFlags = TextFormatFlags.NoPadding | 
    34                                                    TextFormatFlags.EndEllipsis |
    35                                                    TextFormatFlags.VerticalCenter |
    36 												TextFormatFlags.PreserveGraphicsTranslateTransform;
    37 
    38 		#region Properties
    39 
    40         private TreeColumnCollection _owner;
    41 		internal TreeColumnCollection Owner
    42 		{
    43 			get { return _owner; }
    44 			set { _owner = value; }
    45 		}
    46 
    47 		[Browsable(false)]
    48 		public int Index
    49 		{
    50 			get 
    51 			{
    52 				if (Owner != null)
    53 					return Owner.IndexOf(this);
    54 				else
    55 					return -1;
    56 			}
    57 		}
    58 
    59 		private string _header;
    60 		[Localizable(true)]
    61 		public string Header
    62 		{
    63 			get { return _header; }
    64 			set 
    65 			{ 
    66 				_header = value;
    67 				OnHeaderChanged();
    68 			}
    69 		}
    70 
    71 		private string _tooltipText;
    72 		[Localizable(true)]
    73 		public string TooltipText
    74 		{
    75 			get { return _tooltipText; }
    76 			set { _tooltipText = value; }
    77 		}
    78 
    79 		private int _width;
    80 		[DefaultValue(50), Localizable(true)]
    81 		public int Width
    82 		{
    83 			get
    84             {
    85                 return _width;
    86             }
    87 			set 
    88 			{
    89 				if (_width != value)
    90 				{
    91                     _width = Math.Max(MinColumnWidth, value);
    92                     if (_maxColumnWidth > 0)
    93                     {
    94                         _width = Math.Min(_width, MaxColumnWidth);
    95                     }
    96 					OnWidthChanged();
    97 				}
    98 			}
    99 		}
   100 
   101         private int _minColumnWidth;
   102         [DefaultValue(0)]
   103         public int MinColumnWidth
   104         {
   105             get { return _minColumnWidth; }
   106             set
   107             {
   108 				if (value < 0)
   109 					throw new ArgumentOutOfRangeException("value");
   110 
   111 				_minColumnWidth = value;
   112                 Width = Math.Max(value, Width);
   113             }
   114         }
   115 
   116         private int _maxColumnWidth;
   117         [DefaultValue(0)]
   118         public int MaxColumnWidth
   119         {
   120             get { return _maxColumnWidth; }
   121             set
   122             {
   123 				if (value < 0)
   124 					throw new ArgumentOutOfRangeException("value");
   125 
   126 				_maxColumnWidth = value;
   127 				if (value > 0)
   128 					Width = Math.Min(value, _width);
   129             }
   130         }
   131 
   132 		private bool _visible = true;
   133 		[DefaultValue(true)]
   134 		public bool IsVisible
   135 		{
   136 			get { return _visible; }
   137 			set 
   138 			{ 
   139 				_visible = value;
   140 				OnIsVisibleChanged();
   141 			}
   142 		}
   143 
   144 		private HorizontalAlignment _textAlign = HorizontalAlignment.Left;
   145 		[DefaultValue(HorizontalAlignment.Left)]
   146 		public HorizontalAlignment TextAlign
   147 		{
   148 			get { return _textAlign; }
   149 			set 
   150 			{
   151 				if (value != _textAlign)
   152 				{
   153 					_textAlign = value;
   154                     _headerFlags = _baseHeaderFlags | TextHelper.TranslateAligmentToFlag(value);
   155 					OnHeaderChanged();
   156 				}
   157 			}
   158 		}
   159 
   160         private bool _sortable = false;
   161         [DefaultValue(false)]
   162         public bool Sortable
   163         {
   164             get { return _sortable; }
   165             set { _sortable = value; }
   166         }
   167 
   168 		private SortOrder _sort_order = SortOrder.None;
   169 		public SortOrder SortOrder
   170 		{
   171 			get { return _sort_order; }
   172 			set
   173 			{
   174 				if (value == _sort_order)
   175 					return;
   176 				_sort_order = value;
   177 				OnSortOrderChanged();
   178 			}
   179 		}
   180 
   181 		public Size SortMarkSize
   182 		{
   183 			get
   184 			{
   185 				if (Application.RenderWithVisualStyles)
   186 					return new Size(9, 5);
   187 				else
   188 					return new Size(7, 4);
   189 			}
   190 		}
   191 		#endregion
   192 
   193 		public TreeColumn(): 
   194 			this(string.Empty, 50)
   195 		{
   196 		}
   197 
   198         public TreeColumn(string header, int width)
   199 		{
   200 			_header = header;
   201 			_width = width;
   202             _headerFlags = _baseHeaderFlags | TextFormatFlags.Left;
   203 		}
   204 
   205 		public override string ToString()
   206 		{
   207 			if (string.IsNullOrEmpty(Header))
   208 				return GetType().Name;
   209 			else
   210 				return Header;
   211 		}
   212 
   213 		protected override void Dispose(bool disposing)
   214 		{
   215 			base.Dispose(disposing);
   216 		}
   217 
   218 		#region Draw
   219 
   220 		private static VisualStyleRenderer _normalRenderer;
   221 		private static VisualStyleRenderer _pressedRenderer;
   222 		private static VisualStyleRenderer _hotRenderer;
   223 
   224 		private static void CreateRenderers()
   225 		{
   226 			if (Application.RenderWithVisualStyles && _normalRenderer == null)
   227 			{
   228 				_normalRenderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Normal);
   229 				_pressedRenderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Pressed);
   230 				_hotRenderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Hot);
   231 			}
   232 		}
   233 
   234 		internal Bitmap CreateGhostImage(Rectangle bounds, Font font)
   235 		{
   236 			Bitmap b = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
   237 			Graphics gr = Graphics.FromImage(b);
   238 			gr.FillRectangle(SystemBrushes.ControlDark, bounds);
   239 			DrawContent(gr, bounds, font);
   240 			BitmapHelper.SetAlphaChanelValue(b, 150);
   241 			return b;
   242 		}
   243 
   244 		internal void Draw(Graphics gr, Rectangle bounds, Font font, bool pressed, bool hot)
   245 		{
   246 			DrawBackground(gr, bounds, pressed, hot);
   247 			DrawContent(gr, bounds, font);
   248 		}
   249 
   250         private void DrawContent(Graphics gr, Rectangle bounds, Font font)
   251         {
   252             Rectangle innerBounds = new Rectangle(bounds.X + HeaderLeftMargin, bounds.Y,
   253                                    bounds.Width - HeaderLeftMargin - HeaderRightMargin,
   254                                    bounds.Height);
   255 
   256             if (SortOrder != SortOrder.None)
   257 				innerBounds.Width -= (SortMarkSize.Width + SortOrderMarkMargin);
   258 
   259             Size maxTextSize = TextRenderer.MeasureText(gr, Header, font, innerBounds.Size, TextFormatFlags.NoPadding);
   260 			Size textSize = TextRenderer.MeasureText(gr, Header, font, innerBounds.Size, _baseHeaderFlags);
   261 
   262             if (SortOrder != SortOrder.None)
   263             {
   264 				int tw = Math.Min(textSize.Width, innerBounds.Size.Width);
   265 
   266                 int x = 0;
   267                 if (TextAlign == HorizontalAlignment.Left)
   268 					x = innerBounds.X + tw + SortOrderMarkMargin;
   269                 else if (TextAlign == HorizontalAlignment.Right)
   270 					x = innerBounds.Right + SortOrderMarkMargin;
   271                 else
   272 					x = innerBounds.X + tw + (innerBounds.Width - tw) / 2 + SortOrderMarkMargin;
   273                 DrawSortMark(gr, bounds, x);
   274 			}
   275 
   276 			if (textSize.Width < maxTextSize.Width)
   277 				TextRenderer.DrawText(gr, Header, font, innerBounds, SystemColors.ControlText, _baseHeaderFlags | TextFormatFlags.Left);
   278             else
   279 				TextRenderer.DrawText(gr, Header, font, innerBounds, SystemColors.ControlText, _headerFlags);
   280         }
   281 
   282 		private void DrawSortMark(Graphics gr, Rectangle bounds, int x)
   283 		{
   284 			int y = bounds.Y + bounds.Height / 2 - 2;
   285 			x = Math.Max(x, bounds.X + SortOrderMarkMargin);
   286 
   287             int w2 = SortMarkSize.Width / 2;
   288             if (SortOrder == SortOrder.Ascending)
   289             {
   290                 Point[] points = new Point[] { new Point(x, y), new Point(x + SortMarkSize.Width, y), new Point(x + w2, y + SortMarkSize.Height) };
   291                 gr.FillPolygon(SystemBrushes.ControlDark, points);
   292             }
   293             else if (SortOrder == SortOrder.Descending)
   294             {
   295                 Point[] points = new Point[] { new Point(x - 1, y + SortMarkSize.Height), new Point(x + SortMarkSize.Width, y + SortMarkSize.Height), new Point(x + w2, y - 1) };
   296                 gr.FillPolygon(SystemBrushes.ControlDark, points);
   297             }
   298 		}
   299 
   300 		internal static void DrawDropMark(Graphics gr, Rectangle rect)
   301 		{
   302 			gr.FillRectangle(SystemBrushes.HotTrack, rect.X-1, rect.Y, 2, rect.Height);
   303 		}
   304 
   305 		internal static void DrawBackground(Graphics gr, Rectangle bounds, bool pressed, bool hot)
   306 		{
   307 			if (Application.RenderWithVisualStyles)
   308 			{
   309 				CreateRenderers();
   310 				if (pressed)
   311 					_pressedRenderer.DrawBackground(gr, bounds);
   312 				else if (hot)
   313 					_hotRenderer.DrawBackground(gr, bounds);
   314 				else
   315 					_normalRenderer.DrawBackground(gr, bounds);
   316 			}
   317 			else
   318 			{
   319 				gr.FillRectangle(SystemBrushes.Control, bounds);
   320 				Pen p1 = SystemPens.ControlLightLight;
   321 				Pen p2 = SystemPens.ControlDark;
   322 				Pen p3 = SystemPens.ControlDarkDark;
   323 				if (pressed)
   324 					gr.DrawRectangle(p2, bounds.X, bounds.Y, bounds.Width, bounds.Height);
   325 				else
   326 				{
   327 					gr.DrawLine(p1, bounds.X, bounds.Y, bounds.Right, bounds.Y);
   328 					gr.DrawLine(p3, bounds.X, bounds.Bottom, bounds.Right, bounds.Bottom);
   329 					gr.DrawLine(p3, bounds.Right - 1, bounds.Y, bounds.Right - 1, bounds.Bottom - 1);
   330 					gr.DrawLine(p1, bounds.Left, bounds.Y + 1, bounds.Left, bounds.Bottom - 2);
   331 					gr.DrawLine(p2, bounds.Right - 2, bounds.Y + 1, bounds.Right - 2, bounds.Bottom - 2);
   332 					gr.DrawLine(p2, bounds.X, bounds.Bottom - 1, bounds.Right - 2, bounds.Bottom - 1);
   333 				}
   334 			}
   335 		}
   336 
   337 		#endregion
   338 
   339 		#region Events
   340 
   341 		public event EventHandler HeaderChanged;
   342 		private void OnHeaderChanged()
   343 		{
   344 			if (HeaderChanged != null)
   345 				HeaderChanged(this, EventArgs.Empty);
   346 		}
   347 
   348 		public event EventHandler SortOrderChanged;
   349 		private void OnSortOrderChanged()
   350 		{
   351 			if (SortOrderChanged != null)
   352 				SortOrderChanged(this, EventArgs.Empty);
   353 		}
   354 
   355 		public event EventHandler IsVisibleChanged;
   356 		private void OnIsVisibleChanged()
   357 		{
   358 			if (IsVisibleChanged != null)
   359 				IsVisibleChanged(this, EventArgs.Empty);
   360 		}
   361 
   362 		public event EventHandler WidthChanged;
   363 		private void OnWidthChanged()
   364 		{
   365 			if (WidthChanged != null)
   366 				WidthChanged(this, EventArgs.Empty);
   367 		}
   368 
   369 		#endregion
   370 	}
   371 }