External/Aga.Controls/Tree/TreeColumn.cs
author StephaneLenclud
Thu, 18 Apr 2013 23:25:10 +0200
branchMiniDisplay
changeset 444 9b09e2ee0968
permissions -rw-r--r--
Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
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
}