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