using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; namespace DevComponents.DotNetBar.Charts.Style { /// /// Represents the visual style. /// [ToolboxItem(false), DesignTimeVisible(false)] [TypeConverter(typeof(ExpandableObjectConverter))] public class VisualStyle : BaseVisualStyle { #region Private variables private Background _Background; private BorderColor _BorderColor; private BorderPattern _BorderPattern; private Thickness _BorderThickness; private Color _TextColor = Color.Empty; private Padding _Margin; private Padding _Padding; private Font _Font; #endregion #region Public properties #region Background /// /// Gets or sets the style background. /// [Description("Indicates the style background")] public Background Background { get { if (_Background == null) { _Background = Background.Empty; UpdateChangeHandler(null, _Background); } return (_Background); } set { if (_Background != value) { UpdateChangeHandler(_Background, value); _Background = value; OnPropertyChangedEx("Background", VisualChangeType.Render); } } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] private bool ShouldSerializeBackground() { return (_Background != null && _Background.IsEmpty == false); } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] private void ResetBackground() { Background = null; } #endregion #region BorderColor /// /// Gets or sets the style border color. /// [Description("Indicates the style Border Color")] public BorderColor BorderColor { get { if (_BorderColor == null) { _BorderColor = BorderColor.Empty; UpdateChangeHandler(null, _BorderColor); } return (_BorderColor); } set { if (_BorderColor != value) { UpdateChangeHandler(_BorderColor, value); _BorderColor = value; OnPropertyChangedEx("BorderColor", VisualChangeType.Render); } } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] private bool ShouldSerializeBorderColor() { return (_BorderColor != null && _BorderColor.IsEmpty == false); } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] private void ResetBorderColor() { BorderColor = null; } #endregion #region BorderPattern /// /// Gets or sets the style border pattern (Solid, Dash, ...) /// [Description("Indicates the style border pattern (Solid, Dash, ...)")] public BorderPattern BorderPattern { get { if (_BorderPattern == null) { _BorderPattern = BorderPattern.Empty; UpdateChangeHandler(null, _BorderPattern); } return (_BorderPattern); } set { if (_BorderPattern != value) { UpdateChangeHandler(_BorderPattern, value); _BorderPattern = value; OnPropertyChangedEx("BorderPattern", VisualChangeType.Render); } } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] private bool ShouldSerializeBorderPattern() { return (_BorderPattern != null && _BorderPattern.IsEmpty == false); } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] private void ResetBorderPattern() { BorderPattern = null; } #endregion #region BorderThickness /// /// Gets or sets the style border thickness. /// [Description("Indicates the style border thickness")] public Thickness BorderThickness { get { if (_BorderThickness == null) { _BorderThickness = Thickness.Empty; UpdateChangeHandler(null, _BorderThickness); } return (_BorderThickness); } set { if (_BorderThickness != value) { UpdateChangeHandler(_BorderThickness, value); _BorderThickness = value; OnPropertyChangedEx("BorderThickness", VisualChangeType.Layout); } } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] private bool ShouldSerializeBorderThickness() { return (_BorderThickness != null && _BorderThickness.IsEmpty == false); } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] private void ResetBorderThickness() { BorderThickness = null; } #endregion #region Font /// /// Gets or sets the style Font /// [DefaultValue(null)] [Description("Indicates the style Font")] public Font Font { get { return (_Font); } set { if (_Font != value) { _Font = value; OnPropertyChangedEx("Font", VisualChangeType.Layout); } } } #endregion #region Margin /// /// Gets or sets the spacing between the border and outside content. /// [Description("Indicates the spacing between the border and outside content")] public Padding Margin { get { if (_Margin == null) { _Margin = Padding.Empty; UpdateChangeHandler(null, _Margin); } return (_Margin); } set { if (_Margin != value) { UpdateChangeHandler(_Margin, value); _Margin = value; OnPropertyChangedEx("Margin", VisualChangeType.Layout); } } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] private bool ShouldSerializeMargin() { return (_Margin != null && _Margin.IsEmpty == false); } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] private void ResetMargin() { Margin = null; } #endregion #region Padding /// /// Gets or sets spacing between the content and edges of the element. /// [Description("Indicates the spacing between the content and edges of the element")] public Padding Padding { get { if (_Padding == null) { _Padding = Padding.Empty; UpdateChangeHandler(null, _Padding); } return (_Padding); } set { if (_Padding != value) { UpdateChangeHandler(_Padding, value); _Padding = value; OnPropertyChangedEx("Padding", VisualChangeType.Layout); } } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] private bool ShouldSerializePadding() { return (_Padding != null && _Padding.IsEmpty == false); } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] private void ResetPadding() { Padding = null; } #endregion #region TextColor /// /// Gets or sets the Text color /// [Description("Indicates the Text color")] public Color TextColor { get { return (_TextColor); } set { if (_TextColor != value) { _TextColor = value; OnPropertyChangedEx("TextColor", VisualChangeType.Render); } } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] private bool ShouldSerializeTextColor() { return (_TextColor.IsEmpty == false); } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] private void ResetTextColor() { TextColor = Color.Empty; } #endregion #region IsEmpty /// /// Gets whether the style is logically Empty. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Description("Gets whether the style is logically Empty.")] public override bool IsEmpty { get { return ((_Background == null || _Background.IsEmpty == true) && (_BorderColor == null || _BorderColor.IsEmpty == true) && (_BorderPattern == null || _BorderPattern.IsEmpty == true) && (_BorderThickness == null || _BorderThickness.IsEmpty == true) && (_Margin == null || _Margin.IsEmpty == true) && (_Padding == null || _Padding.IsEmpty == true) && (_Font == null) && (_TextColor.IsEmpty == true) && (base.IsEmpty == true)); } } #endregion #endregion #region RenderBackground internal void RenderBackground(Graphics g, Rectangle bounds) { if (bounds.Width > 1 && bounds.Height > 1) { using (Brush br = Background.GetBrush(bounds)) { if (br != null) g.FillRectangle(br, bounds); } } } #endregion #region RenderBorder internal void RenderBorder(Graphics g, Rectangle r) { RenderBorderEx(g, r, BorderPattern, BorderThickness, BorderColor); } internal void RenderBorderEx(Graphics g, Rectangle r, BorderPattern borderPattern, Thickness borderThickness, BorderColor borderColor) { if (r.Width > 2 && r.Height > 2) { if (borderPattern == null || borderThickness == null || borderColor == null) return; SmoothingMode sm = g.SmoothingMode; g.SmoothingMode = SmoothingMode.None; if (borderColor.IsUniform == true && borderThickness.IsUniform == true && borderPattern.IsUniform == true) { RenderUniformBorder(g, r, borderPattern, borderThickness, borderColor); } else { RenderVariableBorder(g, r, borderPattern, borderThickness, borderColor); } g.SmoothingMode = sm; } } #region RenderUniformBorder private void RenderUniformBorder(Graphics g, Rectangle r, BorderPattern borderPattern, Thickness borderThickness, BorderColor borderColor) { if (borderPattern.Top != LinePattern.None && (borderThickness.Top > 0 && borderColor.Top.IsEmpty == false)) { using (Pen pen = new Pen(borderColor.Top, Dpi.Width(borderThickness.Top))) { LinePattern pattern = (borderPattern.Top == LinePattern.NotSet) ? LinePattern.Solid : borderPattern.Top; if (borderThickness.Top > 1) { pen.Alignment = PenAlignment.Inset; } else { r.Width--; r.Height--; } pen.DashStyle = (DashStyle)pattern; g.DrawRectangle(pen, r); } } } #endregion #region RenderVariableBorder private void RenderVariableBorder(Graphics g, Rectangle r, BorderPattern borderPattern, Thickness borderThickness, BorderColor borderColor) { Pen[] pens = GetBorderPens(borderPattern, borderThickness, borderColor); if (pens[(int)BorderSide.Left] != null) { int n = (int)Math.Floor((double)borderThickness.Left / 2); int left = r.Left + n; g.DrawLine(pens[(int)BorderSide.Left], left, r.Top, left, r.Bottom - 1); } if (pens[(int)BorderSide.Right] != null) { int n = (int)Math.Ceiling((double)borderThickness.Right / 2); int right = r.Right - n; g.DrawLine(pens[(int)BorderSide.Right], right, r.Top, right, r.Bottom); } if (pens[(int)BorderSide.Top] != null) { int n = (int)Math.Floor((double)borderThickness.Top / 2); int top = r.Top + n; g.DrawLine(pens[(int)BorderSide.Top], r.X, top, r.Right - 1, top); } if (pens[(int)BorderSide.Bottom] != null) { int n = (int)Math.Ceiling((double)borderThickness.Bottom / 2); int bottom = r.Bottom - n; g.DrawLine(pens[(int)BorderSide.Bottom], r.X, bottom, r.Right, bottom); } foreach (Pen pen in pens) { if (pen != null) pen.Dispose(); } } #region GetBorderPens internal Pen[] GetBorderPens( BorderPattern borderPattern, Thickness borderThickness, BorderColor borderColor) { Pen[] pens = new Pen[4]; pens[(int)BorderSide.Top] = GetBorderPen(pens, borderColor.Top, borderThickness.Top, borderPattern.Top); pens[(int)BorderSide.Left] = GetBorderPen(pens, borderColor.Left, borderThickness.Left, borderPattern.Left); pens[(int)BorderSide.Bottom] = GetBorderPen(pens, borderColor.Bottom, borderThickness.Bottom, borderPattern.Bottom); pens[(int)BorderSide.Right] = GetBorderPen(pens, borderColor.Right, borderThickness.Right, borderPattern.Right); return (pens); } #region GetBorderPen private Pen GetBorderPen(IEnumerable pens, Color color, int width, LinePattern pattern) { if (color.IsEmpty == true || pattern == LinePattern.None || width <= 0) { return (null); } width = Dpi.Width(width); foreach (Pen pen in pens) { if (pen != null) { if (pen.Color == color && pen.Width == width && pen.DashStyle == (DashStyle)pattern) { return (pen); } } } Pen npen = new Pen(color, width); if (pattern == LinePattern.NotSet) pattern = LinePattern.Solid; npen.DashStyle = (DashStyle)pattern; return (npen); } #endregion #endregion #endregion #endregion #region GetBorderSize internal Size GetBorderSize(bool inclPadding) { Size size = Size.Empty; size.Width += (BorderThickness.Horizontal + Margin.Horizontal); size.Height += (BorderThickness.Vertical + Margin.Vertical); if (inclPadding == true) { size.Width += Padding.Horizontal; size.Height += Padding.Vertical; } return (size); } #endregion #region ApplyStyle /// /// Applies the style to instance of this style. /// /// Style to apply. public void ApplyStyle(VisualStyle style) { base.ApplyStyle(style); if (style != null) { if (style._Background != null && style._Background.IsEmpty == false) Background = style._Background.Copy(); if (style._BorderColor != null && style._BorderColor.IsEmpty == false) BorderColor = style._BorderColor.Copy(); if (style._BorderPattern != null && style._BorderPattern.IsEmpty == false) BorderPattern.ApplyPattern(style._BorderPattern); if (style._BorderThickness != null && style._BorderThickness.IsZero == false) BorderThickness = style._BorderThickness.Copy(); if (style.Font != null) Font = style.Font; if (style._Margin != null && style._Margin.IsEmpty == false) Margin = style.Margin.Copy(); if (style._Padding != null && style._Padding.IsEmpty == false) Padding = style.Padding.Copy(); if (style._TextColor.IsEmpty == false) TextColor = style._TextColor; } } #endregion #region ApplyDefaults private Background _DefaultBackground = new Background(Color.Transparent); public override void ApplyDefaults() { base.ApplyDefaults(); if (_TextColor.IsEmpty == true) TextColor = Color.Black; if (Font == null) Font = SystemFonts.DefaultFont; if (Background == null) Background = _DefaultBackground; } #endregion #region Copy /// /// Returns the copy of the style. /// /// Copy of the style. public new VisualStyle Copy() { VisualStyle style = new VisualStyle(); CopyTo(style); return (style); } #endregion #region CopyTo /// /// Returns the copy of the style. /// /// Copy of the style. public void CopyTo(VisualStyle style) { base.CopyTo(style); style.Background = (_Background == null) ? null : _Background.Copy(); style.BorderColor = (_BorderColor == null) ? null : _BorderColor.Copy(); style.BorderPattern = (_BorderPattern == null) ? null : _BorderPattern.Copy(); style.BorderThickness = (_BorderThickness == null) ? null : _BorderThickness.Copy(); style.Font = (_Font == null) ? null : (Font)_Font.Clone(); style.Margin = (_Margin == null) ? null : _Margin.Copy(); style.Padding = (_Padding == null) ? null : _Padding.Copy(); style.TextColor = _TextColor; } #endregion #region GetSerialData internal override SerialElementCollection GetSerialData(string serialName) { SerialElementCollection sec = new SerialElementCollection(); if (serialName != null) { if (serialName.Equals("") == true) serialName = "VisualStyle"; sec.AddStartElement(serialName); } if (_Background != null && _Background.IsEmpty == false) sec.AddElement(_Background.GetSerialData("Background")); if (_BorderColor != null && _BorderColor.IsEmpty == false) sec.AddElement(_BorderColor.GetSerialData("BorderColor")); if (_BorderPattern != null && _BorderPattern.IsEmpty == false) sec.AddElement(_BorderPattern.GetSerialData("BorderPattern")); if (_BorderThickness != null && _BorderThickness.IsEmpty == false) sec.AddElement(_BorderThickness.GetSerialData("BorderThickness")); if (_Font != null) sec.AddValue("Font", XmlSerializableFont.ConvertToString(_Font)); if (_Margin != null && _Margin.IsEmpty == false) sec.AddElement(_Margin.GetSerialData("Margin")); if (_Padding != null && _Padding.IsEmpty == false) sec.AddElement(_Padding.GetSerialData("Padding")); sec.AddValue("TextColor", TextColor, Color.Empty); sec.AddElement(base.GetSerialData(null)); if (serialName != null) sec.AddEndElement(serialName); return (sec); } #endregion #region PutSerialData #region ProcessValue internal override void ProcessValue(SerialElement se) { switch (se.Name) { case "TextColor": TextColor = se.GetValueColor(); break; case "Font": Font = XmlSerializableFont.ConvertFromString(se.StringValue); break; default: base.ProcessValue(se); break; } } #endregion #region ProcessCollection internal override void ProcessCollection(SerialElement se) { switch (se.Name) { case "Background": se.Sec.PutSerialData(Background); break; case "BorderColor": se.Sec.PutSerialData(BorderColor); break; case "BorderPattern": se.Sec.PutSerialData(BorderPattern); break; case "BorderThickness": se.Sec.PutSerialData(BorderThickness); break; case "Margin": se.Sec.PutSerialData(Margin); break; case "Padding": se.Sec.PutSerialData(Padding); break; default: base.ProcessCollection(se); break; } } #endregion #endregion #region IDisposable /// /// Dispose /// public override void Dispose() { Background = null; BorderColor = null; BorderPattern = null; BorderThickness = null; Margin = null; Padding = null; base.Dispose(); } #endregion } #region Alignment /// /// Alignment of the content /// public enum Alignment { /// /// NotSet = -1, /// /// TopLeft /// TopLeft, /// /// TopCenter /// TopCenter, /// /// TopRight /// TopRight, /// /// MiddleLeft /// MiddleLeft, /// /// MiddleCenter /// MiddleCenter, /// /// MiddleRight /// MiddleRight, /// /// BottomLeft /// BottomLeft, /// /// BottomCenter /// BottomCenter, /// /// BottomRight /// BottomRight, } #endregion #region LineAlignment /// /// LineAlignment of the content /// public enum LineAlignment { /// /// Not Set /// NotSet = -1, /// /// Near /// Near, /// /// Center /// Center, /// /// Far /// Far, } #endregion #region BorderSide internal enum BorderSide { Top, Left, Bottom, Right } #endregion }