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