External/Aga.Controls/Tree/NodeControls/BaseTextControl.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.
moel@345
     1
using System;
moel@345
     2
using System.Collections.Generic;
moel@345
     3
using System.Text;
moel@345
     4
using System.Drawing;
moel@345
     5
using System.Windows.Forms;
moel@345
     6
using System.Reflection;
moel@345
     7
using System.ComponentModel;
moel@345
     8
moel@345
     9
namespace Aga.Controls.Tree.NodeControls
moel@345
    10
{
moel@345
    11
	public abstract class BaseTextControl : EditableControl
moel@345
    12
	{
moel@345
    13
		private TextFormatFlags _baseFormatFlags;
moel@345
    14
        private TextFormatFlags _formatFlags;
moel@345
    15
        private Pen _focusPen;
moel@345
    16
		private StringFormat _format;
moel@345
    17
moel@345
    18
		#region Properties
moel@345
    19
moel@345
    20
		private Font _font = null;
moel@345
    21
		public Font Font
moel@345
    22
		{
moel@345
    23
			get
moel@345
    24
			{
moel@345
    25
				if (_font == null)
moel@345
    26
					return Control.DefaultFont;
moel@345
    27
				else
moel@345
    28
					return _font;
moel@345
    29
			}
moel@345
    30
			set
moel@345
    31
			{
moel@345
    32
				if (value == Control.DefaultFont)
moel@345
    33
					_font = null;
moel@345
    34
				else
moel@345
    35
					_font = value;
moel@345
    36
			}
moel@345
    37
		}
moel@345
    38
moel@345
    39
		protected bool ShouldSerializeFont()
moel@345
    40
		{
moel@345
    41
			return (_font != null);
moel@345
    42
		}
moel@345
    43
moel@345
    44
		private HorizontalAlignment _textAlign = HorizontalAlignment.Left;
moel@345
    45
		[DefaultValue(HorizontalAlignment.Left)]
moel@345
    46
		public HorizontalAlignment TextAlign
moel@345
    47
		{
moel@345
    48
			get { return _textAlign; }
moel@345
    49
			set 
moel@345
    50
			{ 
moel@345
    51
				_textAlign = value;
moel@345
    52
				SetFormatFlags();
moel@345
    53
			}
moel@345
    54
		}
moel@345
    55
moel@345
    56
		private StringTrimming _trimming = StringTrimming.None;
moel@345
    57
		[DefaultValue(StringTrimming.None)]
moel@345
    58
		public StringTrimming Trimming
moel@345
    59
		{
moel@345
    60
			get { return _trimming; }
moel@345
    61
			set 
moel@345
    62
			{ 
moel@345
    63
				_trimming = value;
moel@345
    64
				SetFormatFlags();
moel@345
    65
			}
moel@345
    66
		}
moel@345
    67
moel@345
    68
		private bool _displayHiddenContentInToolTip = true;
moel@345
    69
		[DefaultValue(true)]
moel@345
    70
		public bool DisplayHiddenContentInToolTip
moel@345
    71
		{
moel@345
    72
			get { return _displayHiddenContentInToolTip; }
moel@345
    73
			set { _displayHiddenContentInToolTip = value; }
moel@345
    74
		}
moel@345
    75
moel@345
    76
		private bool _useCompatibleTextRendering = false;
moel@345
    77
		[DefaultValue(false)]
moel@345
    78
		public bool UseCompatibleTextRendering
moel@345
    79
		{
moel@345
    80
			get { return _useCompatibleTextRendering; }
moel@345
    81
			set { _useCompatibleTextRendering = value; }
moel@345
    82
		}
moel@345
    83
moel@345
    84
		[DefaultValue(false)]
moel@345
    85
		public bool TrimMultiLine
moel@345
    86
		{
moel@345
    87
			get;
moel@345
    88
			set;
moel@345
    89
		}
moel@345
    90
moel@345
    91
		#endregion
moel@345
    92
moel@345
    93
		protected BaseTextControl()
moel@345
    94
		{
moel@345
    95
			IncrementalSearchEnabled = true;
moel@345
    96
			_focusPen = new Pen(Color.Black);
moel@345
    97
			_focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
moel@345
    98
moel@345
    99
			_format = new StringFormat(StringFormatFlags.LineLimit | StringFormatFlags.NoClip | StringFormatFlags.FitBlackBox | StringFormatFlags.MeasureTrailingSpaces);
moel@345
   100
			_baseFormatFlags = TextFormatFlags.PreserveGraphicsClipping |
moel@345
   101
						   TextFormatFlags.PreserveGraphicsTranslateTransform;
moel@345
   102
			SetFormatFlags();
moel@345
   103
			LeftMargin = 3;
moel@345
   104
		}
moel@345
   105
moel@345
   106
		private void SetFormatFlags()
moel@345
   107
		{
moel@345
   108
			_format.Alignment = TextHelper.TranslateAligment(TextAlign);
moel@345
   109
			_format.Trimming = Trimming;
moel@345
   110
moel@345
   111
			_formatFlags = _baseFormatFlags | TextHelper.TranslateAligmentToFlag(TextAlign)
moel@345
   112
				| TextHelper.TranslateTrimmingToFlag(Trimming);
moel@345
   113
		}
moel@345
   114
moel@345
   115
		public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
moel@345
   116
		{
moel@345
   117
			return GetLabelSize(node, context);
moel@345
   118
		}
moel@345
   119
moel@345
   120
		protected Size GetLabelSize(TreeNodeAdv node, DrawContext context)
moel@345
   121
		{
moel@345
   122
			return GetLabelSize(node, context, GetLabel(node));
moel@345
   123
		}
moel@345
   124
moel@345
   125
		protected Size GetLabelSize(TreeNodeAdv node, DrawContext context, string label)
moel@345
   126
		{
moel@345
   127
			PerformanceAnalyzer.Start("GetLabelSize");
moel@345
   128
			CheckThread();
moel@345
   129
			Font font = GetDrawingFont(node, context, label);
moel@345
   130
			Size s = Size.Empty;
moel@345
   131
			if (UseCompatibleTextRendering)
moel@345
   132
				s = TextRenderer.MeasureText(label, font);
moel@345
   133
			else
moel@345
   134
			{
moel@345
   135
				SizeF sf = context.Graphics.MeasureString(label, font);
moel@345
   136
				s = new Size((int)Math.Ceiling(sf.Width), (int)Math.Ceiling(sf.Height));
moel@345
   137
			}
moel@345
   138
			PerformanceAnalyzer.Finish("GetLabelSize");
moel@345
   139
moel@345
   140
			if (!s.IsEmpty)
moel@345
   141
				return s;
moel@345
   142
			else
moel@345
   143
				return new Size(10, Font.Height);
moel@345
   144
		}
moel@345
   145
moel@345
   146
		protected Font GetDrawingFont(TreeNodeAdv node, DrawContext context, string label)
moel@345
   147
		{
moel@345
   148
			Font font = context.Font;
moel@345
   149
			if (DrawTextMustBeFired(node))
moel@345
   150
			{
moel@345
   151
				DrawEventArgs args = new DrawEventArgs(node, this, context, label);
moel@345
   152
				args.Font = context.Font;
moel@345
   153
				OnDrawText(args);
moel@345
   154
				font = args.Font;
moel@345
   155
			}
moel@345
   156
			return font;
moel@345
   157
		}
moel@345
   158
moel@345
   159
		protected void SetEditControlProperties(Control control, TreeNodeAdv node)
moel@345
   160
		{
moel@345
   161
			string label = GetLabel(node);
moel@345
   162
			DrawContext context = new DrawContext();
moel@345
   163
			context.Font = control.Font;
moel@345
   164
			control.Font = GetDrawingFont(node, context, label);
moel@345
   165
		}
moel@345
   166
moel@345
   167
		public override void Draw(TreeNodeAdv node, DrawContext context)
moel@345
   168
		{
moel@345
   169
			if (context.CurrentEditorOwner == this && node == Parent.CurrentNode)
moel@345
   170
				return;
moel@345
   171
moel@345
   172
			PerformanceAnalyzer.Start("BaseTextControl.Draw");
moel@345
   173
			string label = GetLabel(node);
moel@345
   174
			Rectangle bounds = GetBounds(node, context);
moel@345
   175
			Rectangle focusRect = new Rectangle(bounds.X, context.Bounds.Y,	
moel@345
   176
				bounds.Width, context.Bounds.Height);
moel@345
   177
moel@345
   178
			Brush backgroundBrush;
moel@345
   179
			Color textColor;
moel@345
   180
			Font font;
moel@345
   181
			CreateBrushes(node, context, label, out backgroundBrush, out textColor, out font, ref label);
moel@345
   182
moel@345
   183
			if (backgroundBrush != null)
moel@345
   184
				context.Graphics.FillRectangle(backgroundBrush, focusRect);
moel@345
   185
			if (context.DrawFocus)
moel@345
   186
			{
moel@345
   187
				focusRect.Width--;
moel@345
   188
				focusRect.Height--;
moel@345
   189
				if (context.DrawSelection == DrawSelectionMode.None)
moel@345
   190
					_focusPen.Color = SystemColors.ControlText;
moel@345
   191
				else
moel@345
   192
					_focusPen.Color = SystemColors.InactiveCaption;
moel@345
   193
				context.Graphics.DrawRectangle(_focusPen, focusRect);
moel@345
   194
			}
moel@345
   195
			
moel@345
   196
			PerformanceAnalyzer.Start("BaseTextControl.DrawText");
moel@345
   197
			if (UseCompatibleTextRendering)
moel@345
   198
				TextRenderer.DrawText(context.Graphics, label, font, bounds, textColor, _formatFlags);
moel@345
   199
			else
moel@345
   200
				context.Graphics.DrawString(label, font, GetFrush(textColor), bounds, _format);
moel@345
   201
			PerformanceAnalyzer.Finish("BaseTextControl.DrawText");
moel@345
   202
moel@345
   203
			PerformanceAnalyzer.Finish("BaseTextControl.Draw");
moel@345
   204
		}
moel@345
   205
moel@345
   206
		private static Dictionary<Color, Brush> _brushes = new Dictionary<Color,Brush>();
moel@345
   207
		private static Brush GetFrush(Color color)
moel@345
   208
		{
moel@345
   209
			Brush br;
moel@345
   210
			if (_brushes.ContainsKey(color))
moel@345
   211
				br = _brushes[color];
moel@345
   212
			else
moel@345
   213
			{
moel@345
   214
				br = new SolidBrush(color);
moel@345
   215
				_brushes.Add(color, br);
moel@345
   216
			}
moel@345
   217
			return br;
moel@345
   218
		}
moel@345
   219
moel@345
   220
		private void CreateBrushes(TreeNodeAdv node, DrawContext context, string text, out Brush backgroundBrush, out Color textColor, out Font font, ref string label)
moel@345
   221
		{
moel@345
   222
			textColor = SystemColors.ControlText;
moel@345
   223
			backgroundBrush = null;
moel@345
   224
			font = context.Font;
moel@345
   225
			if (context.DrawSelection == DrawSelectionMode.Active)
moel@345
   226
			{
moel@345
   227
				textColor = SystemColors.HighlightText;
moel@345
   228
                backgroundBrush = SystemBrushes.Highlight;
moel@345
   229
			}
moel@345
   230
			else if (context.DrawSelection == DrawSelectionMode.Inactive)
moel@345
   231
			{
moel@345
   232
				textColor = SystemColors.ControlText;
moel@345
   233
                backgroundBrush = SystemBrushes.InactiveBorder;
moel@345
   234
			}
moel@345
   235
			else if (context.DrawSelection == DrawSelectionMode.FullRowSelect)
moel@346
   236
				textColor = SystemColors.ControlText;
moel@345
   237
moel@345
   238
			if (!context.Enabled)
moel@345
   239
				textColor = SystemColors.GrayText;
moel@345
   240
moel@345
   241
			if (DrawTextMustBeFired(node))
moel@345
   242
			{
moel@345
   243
				DrawEventArgs args = new DrawEventArgs(node, this, context, text);
moel@345
   244
				args.Text = label;
moel@345
   245
				args.TextColor = textColor;
moel@345
   246
				args.BackgroundBrush = backgroundBrush;
moel@345
   247
				args.Font = font;
moel@345
   248
moel@345
   249
				OnDrawText(args);
moel@345
   250
moel@345
   251
				textColor = args.TextColor;
moel@345
   252
				backgroundBrush = args.BackgroundBrush;
moel@345
   253
				font = args.Font;
moel@345
   254
				label = args.Text;
moel@345
   255
			}
moel@345
   256
		}
moel@345
   257
moel@345
   258
		public string GetLabel(TreeNodeAdv node)
moel@345
   259
		{
moel@345
   260
			if (node != null && node.Tag != null)
moel@345
   261
			{
moel@345
   262
				object obj = GetValue(node);
moel@345
   263
				if (obj != null)
moel@345
   264
					return FormatLabel(obj);
moel@345
   265
			}
moel@345
   266
			return string.Empty;
moel@345
   267
		}
moel@345
   268
moel@345
   269
		protected virtual string FormatLabel(object obj)
moel@345
   270
		{
moel@345
   271
			var res = obj.ToString();
moel@345
   272
			if (TrimMultiLine && res != null)
moel@345
   273
			{
moel@345
   274
				string[] parts = res.Split('\n');
moel@345
   275
				if (parts.Length > 1)
moel@345
   276
					return parts[0] + "...";
moel@345
   277
			}
moel@345
   278
			return res;
moel@345
   279
		}
moel@345
   280
moel@345
   281
		public void SetLabel(TreeNodeAdv node, string value)
moel@345
   282
		{
moel@345
   283
			SetValue(node, value);
moel@345
   284
		}
moel@345
   285
moel@345
   286
		protected override void Dispose(bool disposing)
moel@345
   287
		{
moel@345
   288
			base.Dispose(disposing);
moel@345
   289
			if (disposing)
moel@345
   290
			{
moel@345
   291
				_focusPen.Dispose();
moel@345
   292
				_format.Dispose();
moel@345
   293
			}
moel@345
   294
		}
moel@345
   295
moel@345
   296
		/// <summary>
moel@345
   297
		/// Fires when control is going to draw a text. Can be used to change text or back color
moel@345
   298
		/// </summary>
moel@345
   299
		public event EventHandler<DrawEventArgs> DrawText;
moel@345
   300
		protected virtual void OnDrawText(DrawEventArgs args)
moel@345
   301
		{
moel@345
   302
			TreeViewAdv tree = args.Node.Tree;
moel@345
   303
			if (tree != null)
moel@345
   304
				tree.FireDrawControl(args);
moel@345
   305
			if (DrawText != null)
moel@345
   306
				DrawText(this, args);
moel@345
   307
		}
moel@345
   308
moel@345
   309
		protected virtual bool DrawTextMustBeFired(TreeNodeAdv node)
moel@345
   310
		{
moel@345
   311
			return DrawText != null || (node.Tree != null && node.Tree.DrawControlMustBeFired());
moel@345
   312
		}
moel@345
   313
	}
moel@345
   314
}