using System; using System.Text; using System.Windows.Forms; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; namespace DevComponents.DotNetBar.Controls { /// /// Represents an single line of text label control with text-markup support and built-in reflection. /// [ToolboxItem(true), Designer("DevComponents.DotNetBar.Design.ReflectionLabelDesigner, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf"), ToolboxBitmap(typeof(LabelX), "Controls.ReflectionLabel.ico")] public class ReflectionLabel : ControlWithBackgroundStyle { #region Private Variables private TextMarkup.BodyElement _TextMarkup = null; private Bitmap _ReflectionBitmap = null; private float _ReflectionFactor = .52f; private Size _TextSize = Size.Empty; #endregion #region Events /// /// Occurs when text markup link is clicked. Markup links can be created using "a" tag, for example: /// Markup link /// public event MarkupLinkClickEventHandler MarkupLinkClick; #endregion #region Constructor #endregion #region Internal Implementation protected override void Dispose(bool disposing) { DisposeReflectionImage(); base.Dispose(disposing); } protected override void PaintContent(PaintEventArgs e) { Graphics g = e.Graphics; SmoothingMode sm = g.SmoothingMode; if (AntiAlias) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.TextRenderingHint = DisplayHelp.AntiAliasTextRenderingHint; } Rectangle r = GetContentRectangle(); Point reflectionLocation = r.Location; bool disposeStyle = false; ElementStyle style = this.GetBackgroundStyle(out disposeStyle); if (_TextMarkup != null) { TextMarkup.MarkupDrawContext d = new TextMarkup.MarkupDrawContext(g, this.Font, (style.TextColor.IsEmpty?this.ForeColor:style.TextColor), (this.RightToLeft == RightToLeft.Yes), Rectangle.Empty, true); if (!this.Enabled) { d.IgnoreFormattingColors = true; d.CurrentForeColor = SystemColors.ControlDark; } _TextMarkup.Render(d); reflectionLocation.Y = _TextMarkup.Bounds.Bottom; reflectionLocation.X = 0; } else { int totalHeight = (int)(_TextSize.Height * (1 + _ReflectionFactor)); int y = r.Y, x = r.X; if (style.TextLineAlignment == eStyleTextAlignment.Center) { y += (r.Height - totalHeight) / 2; } else if (style.TextLineAlignment == eStyleTextAlignment.Far) { y += (r.Height - totalHeight); } TextDrawing.DrawString(g, this.Text, this.Font, (style.TextColor.IsEmpty ? this.ForeColor : style.TextColor), new Rectangle(x, y, r.Width, r.Height), GetTextFormat(style)); reflectionLocation.Y = y + _TextSize.Height; } Rectangle rClip = new Rectangle(0, reflectionLocation.Y, this.Width, this.Height - reflectionLocation.Y); g.SetClip(rClip, CombineMode.Replace); int fontBaseOffset = (int)Math.Floor(Font.Size * Font.FontFamily.GetCellDescent(Font.Style) / Font.FontFamily.GetEmHeight(Font.Style)); reflectionLocation.Y -= fontBaseOffset; if (_ReflectionBitmap != null && _ReflectionEnabled) { g.DrawImage(_ReflectionBitmap, reflectionLocation); } g.ResetClip(); if (disposeStyle) style.Dispose(); if (AntiAlias) g.SmoothingMode = sm; } protected override void OnTextChanged(EventArgs e) { UpdateDisplay(); base.OnTextChanged(e); } protected override void OnFontChanged(EventArgs e) { UpdateDisplay(); base.OnFontChanged(e); } protected override void OnForeColorChanged(EventArgs e) { UpdateDisplay(); base.OnForeColorChanged(e); } protected override void OnVisualPropertyChanged() { UpdateDisplay(); base.OnVisualPropertyChanged(); } protected override void OnResize(EventArgs e) { UpdateDisplay(); base.OnResize(e); } private void UpdateDisplay() { string text = this.Text; if (_TextMarkup != null) { _TextMarkup.MouseLeave(this); _TextMarkup.HyperLinkClick -= new EventHandler(TextMarkupLinkClicked); _TextMarkup = null; } if (TextMarkup.MarkupParser.IsMarkup(ref text)) _TextMarkup = TextMarkup.MarkupParser.Parse(text); if (_TextMarkup != null) { _TextMarkup.HyperLinkClick += new EventHandler(TextMarkupLinkClicked); } CreateReflection(); this.Invalidate(); } private void CreateReflection() { DisposeReflectionImage(); if (Text.Length == 0 || this.Width <= 0 || this.Height <= 0 || this.Font == null) return; // Create image based on the control content Bitmap bmp = null; if (_TextMarkup == null) { using(Graphics g = this.CreateGraphics()) { if (AntiAlias) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.TextRenderingHint = DisplayHelp.AntiAliasTextRenderingHint; } Size s = TextDrawing.MeasureString(g, this.Text, this.Font); bmp = new Bitmap(this.Width, s.Height, PixelFormat.Format32bppArgb); _TextSize = s; } bmp.MakeTransparent(); Color transparentColor = Color.Empty; using (Graphics g = Graphics.FromImage(bmp)) { bool disposeStyle = false; ElementStyle style = this.GetBackgroundStyle(out disposeStyle); if (AntiAlias) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.TextRenderingHint = DisplayHelp.AntiAliasTextRenderingHint; transparentColor = style.BackColor.IsEmpty ? this.BackColor : style.BackColor; if (transparentColor.IsEmpty || transparentColor == Color.Transparent) transparentColor = Color.WhiteSmoke; DisplayHelp.FillRectangle(g, new Rectangle(0, 0, bmp.Width, bmp.Height), transparentColor); } TextDrawing.DrawString(g, this.Text, this.Font, (style.TextColor.IsEmpty ? this.ForeColor : style.TextColor), new Rectangle(0, 0, bmp.Width, bmp.Height), GetTextFormat(style)); if (disposeStyle) style.Dispose(); } if (!transparentColor.IsEmpty) bmp.MakeTransparent(transparentColor); } else { ResizeMarkup(); if (_TextMarkup.Bounds.Height > 0) { bmp = new Bitmap(this.Width, _TextMarkup.Bounds.Height, PixelFormat.Format32bppArgb); Color transparentColor = Color.Empty; using (Graphics g = Graphics.FromImage(bmp)) { bool disposeStyle = false; ElementStyle style = this.GetBackgroundStyle(out disposeStyle); if (AntiAlias) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.TextRenderingHint = DisplayHelp.AntiAliasTextRenderingHint; transparentColor = style.BackColor.IsEmpty ? this.BackColor : style.BackColor; if (transparentColor.IsEmpty || transparentColor == Color.Transparent) transparentColor = Color.WhiteSmoke; DisplayHelp.FillRectangle(g, new Rectangle(0, 0, bmp.Width, bmp.Height), transparentColor); } if (_TextMarkup.Bounds.Top > 0) g.TranslateTransform(0, -(_TextMarkup.Bounds.Top - GetContentRectangle().Y)); TextMarkup.MarkupDrawContext d = new TextMarkup.MarkupDrawContext(g, this.Font, (style.TextColor.IsEmpty ? this.ForeColor : style.TextColor), (this.RightToLeft == RightToLeft.Yes), Rectangle.Empty, true); if (!this.Enabled) { d.IgnoreFormattingColors = true; d.CurrentForeColor = SystemColors.ControlDark; } _TextMarkup.Render(d); if (disposeStyle) style.Dispose(); } if (!transparentColor.IsEmpty) bmp.MakeTransparent(transparentColor); } } if (bmp != null) { _ReflectionBitmap = ImageHelper.CreateReflectionImage(bmp); bmp.Dispose(); } } private eTextFormat GetTextFormat(ElementStyle style) { if (style.TextAlignment == eStyleTextAlignment.Center) return eTextFormat.HorizontalCenter; else if (style.TextAlignment == eStyleTextAlignment.Far) return eTextFormat.Right; return eTextFormat.Default; } private void DisposeReflectionImage() { if (_ReflectionBitmap != null) { _ReflectionBitmap.Dispose(); _ReflectionBitmap = null; } } private void TextMarkupLinkClicked(object sender, EventArgs e) { TextMarkup.HyperLink link = sender as TextMarkup.HyperLink; if (link != null) { OnMarkupLinkClick(new MarkupLinkClickEventArgs(link.Name, link.HRef)); } } protected virtual void OnMarkupLinkClick(MarkupLinkClickEventArgs e) { if (this.MarkupLinkClick != null) MarkupLinkClick(this, e); } protected virtual void ResizeMarkup() { if (_TextMarkup != null) { Rectangle r = this.GetContentRectangle(); if (r.Width <= 0 || r.Height <= 0) return; Graphics g = this.CreateGraphics(); try { if (AntiAlias) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.TextRenderingHint = DisplayHelp.AntiAliasTextRenderingHint; } TextMarkup.MarkupDrawContext d = new TextMarkup.MarkupDrawContext(g, this.Font, SystemColors.Control, (this.RightToLeft == RightToLeft.Yes)); Size measureSize = new Size(10000, r.Height); _TextMarkup.Measure(measureSize, d); bool disposeStyle = false; ElementStyle style = this.GetBackgroundStyle(out disposeStyle); int totalHeight = (int)(_TextMarkup.Bounds.Height * (1 + _ReflectionFactor)); if (totalHeight < r.Height) { if (style.TextLineAlignment == eStyleTextAlignment.Center) { r.Y += (r.Height - totalHeight) / 2; r.Height = _TextMarkup.Bounds.Height; } else if (style.TextLineAlignment == eStyleTextAlignment.Far) { r.Y = (r.Bottom - totalHeight); r.Height = _TextMarkup.Bounds.Height; } } if (_TextMarkup.Bounds.Width < r.Width) { if (style.TextAlignment == eStyleTextAlignment.Center) { r.X += (r.Width - _TextMarkup.Bounds.Width) / 2; r.Width = _TextMarkup.Bounds.Width; } else if (style.TextAlignment == eStyleTextAlignment.Far && this.RightToLeft == RightToLeft.No || style.TextAlignment == eStyleTextAlignment.Near && this.RightToLeft == RightToLeft.Yes) { r.X = (r.Right - _TextMarkup.Bounds.Width); r.Width = _TextMarkup.Bounds.Width; } } _TextMarkup.Arrange(r, d); if (disposeStyle) style.Dispose(); } finally { g.Dispose(); } } } protected override void OnEnabledChanged(EventArgs e) { CreateReflection(); this.Invalidate(); base.OnEnabledChanged(e); } protected override Size DefaultSize { get { return new Size(175, 70); } } private bool _ReflectionEnabled = true; /// /// Gets or sets whether reflection effect is enabled. Default value is true. /// [DefaultValue(true), Description("Indicates whether reflection effect is enabled.")] public bool ReflectionEnabled { get { return _ReflectionEnabled; } set { if (_ReflectionEnabled != value) { _ReflectionEnabled = value; this.Invalidate(); } } } #endregion #region Property hiding [Browsable(false)] public override Image BackgroundImage { get { return base.BackgroundImage; } set { base.BackgroundImage = value; } } #if FRAMEWORK20 [Browsable(false)] public override ImageLayout BackgroundImageLayout { get { return base.BackgroundImageLayout; } set { base.BackgroundImageLayout = value; } } [Browsable(false)] public new System.Windows.Forms.Padding Padding { get { return base.Padding; } set { base.Padding = value; } } #endif [Browsable(true), DefaultValue(""), Editor("DevComponents.DotNetBar.Design.TextMarkupUIEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor)), EditorBrowsable(EditorBrowsableState.Always), Category("Appearance"), Description("Gets or sets the text displayed on label.")] public override string Text { get { return base.Text; } set { base.Text = value; } } #endregion } }