moel@345: using System; moel@345: using System.Collections.Generic; moel@345: using System.Text; moel@345: using System.Drawing; moel@345: using System.Windows.Forms; moel@345: using System.Reflection; moel@345: using System.ComponentModel; moel@345: moel@345: namespace Aga.Controls.Tree.NodeControls moel@345: { moel@345: public abstract class BaseTextControl : EditableControl moel@345: { moel@345: private TextFormatFlags _baseFormatFlags; moel@345: private TextFormatFlags _formatFlags; moel@345: private Pen _focusPen; moel@345: private StringFormat _format; moel@345: moel@345: #region Properties moel@345: moel@345: private Font _font = null; moel@345: public Font Font moel@345: { moel@345: get moel@345: { moel@345: if (_font == null) moel@345: return Control.DefaultFont; moel@345: else moel@345: return _font; moel@345: } moel@345: set moel@345: { moel@345: if (value == Control.DefaultFont) moel@345: _font = null; moel@345: else moel@345: _font = value; moel@345: } moel@345: } moel@345: moel@345: protected bool ShouldSerializeFont() moel@345: { moel@345: return (_font != null); moel@345: } moel@345: moel@345: private HorizontalAlignment _textAlign = HorizontalAlignment.Left; moel@345: [DefaultValue(HorizontalAlignment.Left)] moel@345: public HorizontalAlignment TextAlign moel@345: { moel@345: get { return _textAlign; } moel@345: set moel@345: { moel@345: _textAlign = value; moel@345: SetFormatFlags(); moel@345: } moel@345: } moel@345: moel@345: private StringTrimming _trimming = StringTrimming.None; moel@345: [DefaultValue(StringTrimming.None)] moel@345: public StringTrimming Trimming moel@345: { moel@345: get { return _trimming; } moel@345: set moel@345: { moel@345: _trimming = value; moel@345: SetFormatFlags(); moel@345: } moel@345: } moel@345: moel@345: private bool _displayHiddenContentInToolTip = true; moel@345: [DefaultValue(true)] moel@345: public bool DisplayHiddenContentInToolTip moel@345: { moel@345: get { return _displayHiddenContentInToolTip; } moel@345: set { _displayHiddenContentInToolTip = value; } moel@345: } moel@345: moel@345: private bool _useCompatibleTextRendering = false; moel@345: [DefaultValue(false)] moel@345: public bool UseCompatibleTextRendering moel@345: { moel@345: get { return _useCompatibleTextRendering; } moel@345: set { _useCompatibleTextRendering = value; } moel@345: } moel@345: moel@345: [DefaultValue(false)] moel@345: public bool TrimMultiLine moel@345: { moel@345: get; moel@345: set; moel@345: } moel@345: moel@345: #endregion moel@345: moel@345: protected BaseTextControl() moel@345: { moel@345: IncrementalSearchEnabled = true; moel@345: _focusPen = new Pen(Color.Black); moel@345: _focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot; moel@345: moel@345: _format = new StringFormat(StringFormatFlags.LineLimit | StringFormatFlags.NoClip | StringFormatFlags.FitBlackBox | StringFormatFlags.MeasureTrailingSpaces); moel@345: _baseFormatFlags = TextFormatFlags.PreserveGraphicsClipping | moel@345: TextFormatFlags.PreserveGraphicsTranslateTransform; moel@345: SetFormatFlags(); moel@345: LeftMargin = 3; moel@345: } moel@345: moel@345: private void SetFormatFlags() moel@345: { moel@345: _format.Alignment = TextHelper.TranslateAligment(TextAlign); moel@345: _format.Trimming = Trimming; moel@345: moel@345: _formatFlags = _baseFormatFlags | TextHelper.TranslateAligmentToFlag(TextAlign) moel@345: | TextHelper.TranslateTrimmingToFlag(Trimming); moel@345: } moel@345: moel@345: public override Size MeasureSize(TreeNodeAdv node, DrawContext context) moel@345: { moel@345: return GetLabelSize(node, context); moel@345: } moel@345: moel@345: protected Size GetLabelSize(TreeNodeAdv node, DrawContext context) moel@345: { moel@345: return GetLabelSize(node, context, GetLabel(node)); moel@345: } moel@345: moel@345: protected Size GetLabelSize(TreeNodeAdv node, DrawContext context, string label) moel@345: { moel@345: PerformanceAnalyzer.Start("GetLabelSize"); moel@345: CheckThread(); moel@345: Font font = GetDrawingFont(node, context, label); moel@345: Size s = Size.Empty; moel@345: if (UseCompatibleTextRendering) moel@345: s = TextRenderer.MeasureText(label, font); moel@345: else moel@345: { moel@345: SizeF sf = context.Graphics.MeasureString(label, font); moel@345: s = new Size((int)Math.Ceiling(sf.Width), (int)Math.Ceiling(sf.Height)); moel@345: } moel@345: PerformanceAnalyzer.Finish("GetLabelSize"); moel@345: moel@345: if (!s.IsEmpty) moel@345: return s; moel@345: else moel@345: return new Size(10, Font.Height); moel@345: } moel@345: moel@345: protected Font GetDrawingFont(TreeNodeAdv node, DrawContext context, string label) moel@345: { moel@345: Font font = context.Font; moel@345: if (DrawTextMustBeFired(node)) moel@345: { moel@345: DrawEventArgs args = new DrawEventArgs(node, this, context, label); moel@345: args.Font = context.Font; moel@345: OnDrawText(args); moel@345: font = args.Font; moel@345: } moel@345: return font; moel@345: } moel@345: moel@345: protected void SetEditControlProperties(Control control, TreeNodeAdv node) moel@345: { moel@345: string label = GetLabel(node); moel@345: DrawContext context = new DrawContext(); moel@345: context.Font = control.Font; moel@345: control.Font = GetDrawingFont(node, context, label); moel@345: } moel@345: moel@345: public override void Draw(TreeNodeAdv node, DrawContext context) moel@345: { moel@345: if (context.CurrentEditorOwner == this && node == Parent.CurrentNode) moel@345: return; moel@345: moel@345: PerformanceAnalyzer.Start("BaseTextControl.Draw"); moel@345: string label = GetLabel(node); moel@345: Rectangle bounds = GetBounds(node, context); moel@345: Rectangle focusRect = new Rectangle(bounds.X, context.Bounds.Y, moel@345: bounds.Width, context.Bounds.Height); moel@345: moel@345: Brush backgroundBrush; moel@345: Color textColor; moel@345: Font font; moel@345: CreateBrushes(node, context, label, out backgroundBrush, out textColor, out font, ref label); moel@345: moel@345: if (backgroundBrush != null) moel@345: context.Graphics.FillRectangle(backgroundBrush, focusRect); moel@345: if (context.DrawFocus) moel@345: { moel@345: focusRect.Width--; moel@345: focusRect.Height--; moel@345: if (context.DrawSelection == DrawSelectionMode.None) moel@345: _focusPen.Color = SystemColors.ControlText; moel@345: else moel@345: _focusPen.Color = SystemColors.InactiveCaption; moel@345: context.Graphics.DrawRectangle(_focusPen, focusRect); moel@345: } moel@345: moel@345: PerformanceAnalyzer.Start("BaseTextControl.DrawText"); moel@345: if (UseCompatibleTextRendering) moel@345: TextRenderer.DrawText(context.Graphics, label, font, bounds, textColor, _formatFlags); moel@345: else moel@345: context.Graphics.DrawString(label, font, GetFrush(textColor), bounds, _format); moel@345: PerformanceAnalyzer.Finish("BaseTextControl.DrawText"); moel@345: moel@345: PerformanceAnalyzer.Finish("BaseTextControl.Draw"); moel@345: } moel@345: moel@345: private static Dictionary _brushes = new Dictionary(); moel@345: private static Brush GetFrush(Color color) moel@345: { moel@345: Brush br; moel@345: if (_brushes.ContainsKey(color)) moel@345: br = _brushes[color]; moel@345: else moel@345: { moel@345: br = new SolidBrush(color); moel@345: _brushes.Add(color, br); moel@345: } moel@345: return br; moel@345: } moel@345: moel@345: private void CreateBrushes(TreeNodeAdv node, DrawContext context, string text, out Brush backgroundBrush, out Color textColor, out Font font, ref string label) moel@345: { moel@345: textColor = SystemColors.ControlText; moel@345: backgroundBrush = null; moel@345: font = context.Font; moel@345: if (context.DrawSelection == DrawSelectionMode.Active) moel@345: { moel@345: textColor = SystemColors.HighlightText; moel@345: backgroundBrush = SystemBrushes.Highlight; moel@345: } moel@345: else if (context.DrawSelection == DrawSelectionMode.Inactive) moel@345: { moel@345: textColor = SystemColors.ControlText; moel@345: backgroundBrush = SystemBrushes.InactiveBorder; moel@345: } moel@345: else if (context.DrawSelection == DrawSelectionMode.FullRowSelect) moel@345: textColor = SystemColors.HighlightText; moel@345: moel@345: if (!context.Enabled) moel@345: textColor = SystemColors.GrayText; moel@345: moel@345: if (DrawTextMustBeFired(node)) moel@345: { moel@345: DrawEventArgs args = new DrawEventArgs(node, this, context, text); moel@345: args.Text = label; moel@345: args.TextColor = textColor; moel@345: args.BackgroundBrush = backgroundBrush; moel@345: args.Font = font; moel@345: moel@345: OnDrawText(args); moel@345: moel@345: textColor = args.TextColor; moel@345: backgroundBrush = args.BackgroundBrush; moel@345: font = args.Font; moel@345: label = args.Text; moel@345: } moel@345: } moel@345: moel@345: public string GetLabel(TreeNodeAdv node) moel@345: { moel@345: if (node != null && node.Tag != null) moel@345: { moel@345: object obj = GetValue(node); moel@345: if (obj != null) moel@345: return FormatLabel(obj); moel@345: } moel@345: return string.Empty; moel@345: } moel@345: moel@345: protected virtual string FormatLabel(object obj) moel@345: { moel@345: var res = obj.ToString(); moel@345: if (TrimMultiLine && res != null) moel@345: { moel@345: string[] parts = res.Split('\n'); moel@345: if (parts.Length > 1) moel@345: return parts[0] + "..."; moel@345: } moel@345: return res; moel@345: } moel@345: moel@345: public void SetLabel(TreeNodeAdv node, string value) moel@345: { moel@345: SetValue(node, value); moel@345: } moel@345: moel@345: protected override void Dispose(bool disposing) moel@345: { moel@345: base.Dispose(disposing); moel@345: if (disposing) moel@345: { moel@345: _focusPen.Dispose(); moel@345: _format.Dispose(); moel@345: } moel@345: } moel@345: moel@345: /// moel@345: /// Fires when control is going to draw a text. Can be used to change text or back color moel@345: /// moel@345: public event EventHandler DrawText; moel@345: protected virtual void OnDrawText(DrawEventArgs args) moel@345: { moel@345: TreeViewAdv tree = args.Node.Tree; moel@345: if (tree != null) moel@345: tree.FireDrawControl(args); moel@345: if (DrawText != null) moel@345: DrawText(this, args); moel@345: } moel@345: moel@345: protected virtual bool DrawTextMustBeFired(TreeNodeAdv node) moel@345: { moel@345: return DrawText != null || (node.Tree != null && node.Tree.DrawControlMustBeFired()); moel@345: } moel@345: } moel@345: }