/* Copyright (C) 2008 Webyog Softworks Private Limited This file is a part of Visifire Charts. Visifire is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with Visifire Charts. If not, see . If GPL is not suitable for your products or company, Webyog provides Visifire under a flexible commercial license designed to meet your specific usage and distribution requirements. If you have already obtained a commercial license from Webyog, you can use this file under those license terms. */ #if WPF using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; using System.Windows.Markup; using System.IO; using System.Xml; #else using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; using System.Windows.Browser; #endif using Visifire.Charts; namespace Visifire.Commons { /// /// Visifire.Commons.Marker class /// public class Marker : IComparable { #region Public Methods /// /// Initializes a new instance of the Visifire.Commons.Marker class /// public Marker(MarkerTypes markerType, Double scaleFactor, Size markerSize, Boolean markerBevel, Brush markerColor, String markerLabelText) { MarkerType = markerType; MarkerFillColor = markerColor; Text = markerLabelText; TextOrientation = Orientation.Horizontal; TextAlignmentX = AlignmentX.Right; TextAlignmentY = AlignmentY.Center; ScaleFactor = scaleFactor; MarkerSize = markerSize; BorderThickness = 1; TextBackground = new SolidColorBrush(Colors.Transparent); Bevel = markerBevel; Opacity = 1; LabelAngle = Double.NaN; } /// /// Initializes a new instance of the Visifire.Commons.Marker class /// public Marker() { } /// /// Compare two Markers /// /// Object /// int public int CompareTo(Object o) { Marker dataPoint = (Marker)o; return this.Position.X.CompareTo(dataPoint.Position.X); } /// /// Add elements to parent panel /// /// ParentCanvas /// x position value /// y position value /// AnchorPoint public void AddToParent(Canvas parentCanvas, Double xPosition, Double yPosition, Point anchorPoint) { Position = new Point(xPosition, yPosition); parentCanvas.Children.Add(Visual); Double visualHeight; Double visualWidth; #if WPF Visual.Measure(new Size(Double.MaxValue, Double.MaxValue)); visualHeight = Visual.DesiredSize.Height; visualWidth = Visual.DesiredSize.Width; #else visualHeight = Visual.ActualHeight; visualWidth = Visual.ActualWidth; #endif if (anchorPoint.X == 0.5) xPosition -= (MarkerShape.Width / 2 + ((TextAlignmentX == AlignmentX.Left) ? _markerShapePosition.X : 0)); else if (anchorPoint.X == 1) xPosition -= (MarkerShape.Width + ((TextAlignmentX == AlignmentX.Left) ? _markerShapePosition.X : 0)); if (anchorPoint.Y == 0.5) yPosition -= (MarkerShape.Height / 2 + ((TextAlignmentY == AlignmentY.Top) ? _markerShapePosition.Y : 0)); else if (anchorPoint.Y == 1) yPosition -= (MarkerShape.Height + ((TextAlignmentY == AlignmentY.Top) ? _markerShapePosition.Y : 0)); if (Double.IsNaN(LabelAngle)) { if (TextAlignmentX == AlignmentX.Center) if (TextBlockSize.Width > MarkerShape.Width) xPosition -= (TextBlockSize.Width - MarkerShape.Width) / 2; if (TextAlignmentY == AlignmentY.Center) if (TextBlockSize.Height > MarkerShape.Height) yPosition -= (TextBlockSize.Height - MarkerShape.Height) / 2; } Visual.SetValue(Canvas.TopProperty, yPosition); Visual.SetValue(Canvas.LeftProperty, xPosition); } /// /// Add elements to parent panel /// /// Panel public void AddToParent(Panel parent) { parent.Children.Add(Visual); } /// /// Create visual for Marker /// public void CreateVisual() { // Create Visual as Grid Visual = new Grid(); // Create Shape for Marker MarkerShape = GetShape(); if (MarkerShape != null) MarkerShape.Tag = Tag; MarkerShape.SetValue(Grid.RowProperty, 1); MarkerShape.SetValue(Grid.ColumnProperty, 1); if (ShadowEnabled) { MarkerShadow = GetShape(); if (MarkerShadow != null) MarkerShadow.Tag = Tag; // Set shadow properties MarkerShadow.Fill = GetMarkerShadowColor(); TranslateTransform tt = new TranslateTransform() { X = 1, Y = 1 }; MarkerShadow.RenderTransform = tt; // display or hide the shadow //MarkerShadow.Visibility = (ShadowEnabled ? Visibility.Visible : Visibility.Collapsed); // Set properties MarkerShadow.SetValue(Grid.RowProperty, 1); MarkerShadow.SetValue(Grid.ColumnProperty, 1); // Add Shape for Marker into Visual Visual.Children.Add(MarkerShadow); } Visual.Children.Add(MarkerShape); UpdateMarker(); if (!String.IsNullOrEmpty(Text)) { // Define row and columns Visual.RowDefinitions.Add(new RowDefinition()); Visual.RowDefinitions.Add(new RowDefinition()); Visual.RowDefinitions.Add(new RowDefinition()); Visual.ColumnDefinitions.Add(new ColumnDefinition()); Visual.ColumnDefinitions.Add(new ColumnDefinition()); Visual.ColumnDefinitions.Add(new ColumnDefinition()); // Create TextBlock for Label of the Marker TextBlock = new TextBlock() { Tag = this.Tag }; // Apply TextBlock Properties ApplyTextBlockProperties(); if (!Double.IsNaN(LabelAngle)) { // Create Canvas for TextBlock LabelCanvas = new Canvas(); TextBackgroundCanvas = new Canvas(); TextBackgroundCanvas.Background = TextBackground; TextBackgroundCanvas.Children.Add(TextBlock); // Add TextBackgroundCanvas to LabelCanvas LabelCanvas.Children.Add(TextBackgroundCanvas); // Set Alignment SetAlignment4Label(); if (TextAlignmentX == AlignmentX.Left) { LabelCanvas.SetValue(Grid.ColumnProperty, 0); } else if (TextAlignmentX == AlignmentX.Right) { LabelCanvas.SetValue(Grid.ColumnProperty, 2); } else { LabelCanvas.SetValue(Grid.ColumnProperty, 1); LabelCanvas.HorizontalAlignment = HorizontalAlignment.Center; } if (TextAlignmentY == AlignmentY.Top) { LabelCanvas.SetValue(Grid.RowProperty, 0); LabelCanvas.VerticalAlignment = VerticalAlignment.Top; } else if (TextAlignmentY == AlignmentY.Bottom) { LabelCanvas.SetValue(Grid.RowProperty, 2); LabelCanvas.VerticalAlignment = VerticalAlignment.Top; } else { LabelCanvas.SetValue(Grid.RowProperty, 1); LabelCanvas.VerticalAlignment = VerticalAlignment.Top; } // Add LabelCanvas into Visual Visual.Children.Add(LabelCanvas); } else { if (TextBackground != null) { TextBackgroundCanvas = new Canvas(); TextBackgroundCanvas.Background = TextBackground; Visual.Children.Add(TextBackgroundCanvas); } // Set Alignment SetAlignment4Label(); Visual.Children.Add(TextBlock); } TextBlock.Margin = new Thickness(LabelMargin, 0, 0, 0); Visual.Margin = new Thickness(Margin, Margin, Margin, Margin); } MarkerShape.Opacity = Opacity; MarkerActualSize = Graphics.CalculateVisualSize(Visual); } /// /// Update Marker with new properties /// public void UpdateMarker() { if (BevelLayer != null) Visual.Children.Remove(BevelLayer); if (Bevel) { BevelLayer = GetBevelLayer(); BevelLayer.IsHitTestVisible = false; BevelLayer.SetValue(Grid.RowProperty, 1); BevelLayer.SetValue(Grid.ColumnProperty, 1); BevelLayer.SetValue(Grid.RowProperty, 1); BevelLayer.SetValue(Grid.ColumnProperty, 1); Visual.Children.Add(BevelLayer); } ApplyMarkerShapeProperties(); } #endregion #region Public Properties /// /// Tag property /// public Object Tag { get; set; } /// /// Get or set the Marker Visual /// public Grid Visual { get; set; } /// /// Whether the Bevel effect is applied on Marker /// public Boolean Bevel { get; set; } /// /// Get or set scale factor of Marker symbol /// public Double ScaleFactor { get { return _scaleFactor; } set { // System.Diagnostics.Debug.Assert(value < 1, "ScaleFactor can not be less than 1.."); if (value >= 1) _scaleFactor = value; } } /// /// Get or set padding for label of a Marker /// public Double LabelPadding { get; set; } /// /// Get or set Position of the Marker /// public Point Position { get; set; } /// /// Get or set the Actual Size of Marker /// public Size MarkerSize { get; set; } /// /// Get or set the Text orientation of Marker label /// public Orientation TextOrientation { get; set; } /// /// Get or set the HorizontalAlignment of Marker label /// public AlignmentX TextAlignmentX { get { return _textAlignmentX; } set { _textAlignmentX = value; } } /// /// Get or set the VerticalAlignment of Marker label /// public AlignmentY TextAlignmentY { get { return _textAlignmentY; } set { _textAlignmentY = value; } } /// /// Get or set the Shape type of a Marker /// public MarkerTypes MarkerType { get; set; } public Double Opacity { get; set; } /// /// Get or set the Margin of Marker /// public Double Margin { get; set; } /// /// Get or set the LabelMargin of the label of Marker /// public Double LabelMargin { get; set; } #region Font Properties /// /// Get or set the marker label FontFamily /// public FontFamily FontFamily { get { if (_fontFamily == null) return new FontFamily("Arial"); else return _fontFamily; } set { _fontFamily = value; } } /// /// Get or set the marker label FontSize /// public Double FontSize { get { if (_fontSize == 0) _fontSize = 10; return _fontSize; } set { _fontSize = value; } } /// /// Get or set the marker label FontColor /// public Brush FontColor { get { return (_fontColor == null) ? (new SolidColorBrush(Colors.Black)) : _fontColor; } set { _fontColor = value; } } /// /// Get or set the marker label FontStyle /// public FontStyle FontStyle { get { return _fontStyle; } set { _fontStyle = value; } } /// /// Get or set the marker label FontWeight /// public FontWeight FontWeight { get { return _fontWeight; } set { _fontWeight = value; } } /// /// Get or set the marker label Text /// public String Text { get { return (_text == null) ? "" : _text; } set { _text = value; } } /// /// Get or set the background of marker label text /// public Brush TextBackground { get; set; } #endregion #region Border Properties /// /// Get or set the BorderColor /// public Brush BorderColor { get { if (_borderColor == null) _borderColor = MarkerFillColor; return _borderColor; } set { _borderColor = value; } } /// /// Get or set the BorderThickness /// public Double BorderThickness { get { return _borderThickness; } set { _borderThickness = value; } } /// /// Get or set the Marker fill color /// public Brush MarkerFillColor { get; set; } #endregion #endregion #region Public Events And Delegates #endregion #region Protected Methods #endregion #region Internal Properties /// /// Marker shape reference /// internal Shape MarkerShape { get; set; } /// /// BevelLayer of the Marker shape /// internal FrameworkElement BevelLayer { get; set; } internal Point MarkerPosition { get; set; } /// /// MarkerShadow of the Marker shape /// internal Shape MarkerShadow { get; set; } /// /// Control reference /// internal VisifireControl Control { get; set; } /// /// TextBlock for Marker /// internal TextBlock TextBlock { get; set; } internal Canvas LabelCanvas { get; set; } /// /// Angle for Marker labels /// internal Double LabelAngle { get; set; } internal LabelStyles LabelStyle { get; set; } /// /// Actual Size of Marker /// internal Size MarkerActualSize { get; private set; } /// /// Size of the TextBlock /// internal Size TextBlockSize { get; set; } /// /// Background of the label of the Marker /// internal Canvas TextBackgroundCanvas { get; set; } /// /// This property applies only for Bubble and Point charts /// internal bool ShadowEnabled { get; set; } /// /// DataSeries used in Legend for line chart /// internal DataSeries DataSeriesOfLegendMarker { get; set; } #endregion #region Private Properties #endregion #region Private Delegates #endregion #region Private Methods /// /// Apply all style properties of the Marker text /// private void ApplyMarkerShapeProperties() { // Set Border Properties if (MarkerShape != null) { MarkerShape.Stroke = BorderColor; MarkerShape.Fill = MarkerFillColor; MarkerShape.StrokeThickness = BorderThickness; MarkerShape.Height = MarkerSize.Height * ScaleFactor; MarkerShape.Width = MarkerSize.Width * ScaleFactor; if (MarkerShadow != null) { MarkerShadow.Height = MarkerSize.Height * ScaleFactor; MarkerShadow.Width = MarkerSize.Width * ScaleFactor; MarkerShadow.Stroke = null; } } if (BevelLayer != null) { BevelLayer.Height = MarkerSize.Height * ScaleFactor; BevelLayer.Width = MarkerSize.Width * ScaleFactor; if ((BevelLayer as Shape) != null) (BevelLayer as Shape).StrokeThickness = BorderThickness; } } /// /// Apply all style properties of the Marker text /// private void ApplyTextBlockProperties() { if (TextBlock != null) { // Set TextElement properties #if WPF TextBlock.FlowDirection = FlowDirection.LeftToRight; #endif TextBlock.FontFamily = FontFamily; TextBlock.FontSize = FontSize; TextBlock.FontStyle = FontStyle; TextBlock.FontWeight = FontWeight; TextBlock.Text = Text; TextBlock.Foreground = FontColor; TextBlock.VerticalAlignment = VerticalAlignment.Top; } } /// /// Create shape for Marker /// /// Shape private Shape GetShape() { String xaml = null; switch (MarkerType) { case MarkerTypes.Circle: //Ellipse ellipse = new Ellipse() { Height = 6, Width = 6 }; //GradientStopCollection gsc = new GradientStopCollection(); //gsc.Add(new GradientStop() { Offset = 0, Color = Colors.White }); //gsc.Add(new GradientStop() { Offset = 1, Color = Colors.Gray }); //ellipse.Fill = new LinearGradientBrush() { GradientStops = gsc, StartPoint = new Point(0.5, 1), EndPoint = new Point(0.5, 0) }; //return ellipse; return new Ellipse() { Height = 6, Width = 6, Stroke = new SolidColorBrush(Colors.Transparent) }; case MarkerTypes.Cross: xaml = String.Format(@""); break; case MarkerTypes.Diamond: xaml = String.Format(@""); break; case MarkerTypes.Square: xaml = String.Format(@""); break; case MarkerTypes.Triangle: xaml = String.Format(@""); break; case MarkerTypes.Line: xaml = String.Format(@""); break; } #if WPF return (Shape)XamlReader.Load(new XmlTextReader(new StringReader(xaml))); #else return System.Windows.Markup.XamlReader.Load(xaml) as Shape; #endif } /// /// Create shape for Marker /// /// FrameworkElement private FrameworkElement GetBevelLayer() { String xaml = null; Brush topBrush = Graphics.GetBevelTopBrush(MarkerFillColor); String color; switch (MarkerType) { case MarkerTypes.Circle: Ellipse ellipse = new Ellipse() { Height = 6, Width = 6 }; GradientStopCollection gsc = new GradientStopCollection(); gsc.Add(new GradientStop() { Offset = 0, Color = Graphics.GetDarkerColor((topBrush as LinearGradientBrush).GradientStops[1].Color, .8) }); gsc.Add(new GradientStop() { Offset = 0.6, Color = Graphics.GetDarkerColor((topBrush as LinearGradientBrush).GradientStops[1].Color, .8) }); gsc.Add(new GradientStop() { Offset = 0.8, Color = (topBrush as LinearGradientBrush).GradientStops[1].Color }); gsc.Add(new GradientStop() { Offset = 1, Color = (topBrush as LinearGradientBrush).GradientStops[1].Color }); ellipse.Fill = new LinearGradientBrush() { GradientStops = gsc, StartPoint = new Point(0.5, 1), EndPoint = new Point(0.5, 0) }; return ellipse; case MarkerTypes.Cross: topBrush = Graphics.GetBevelTopBrush(BorderColor); color = (topBrush as LinearGradientBrush).GradientStops[2].Color.ToString(); xaml = String.Format(@" ", Graphics.GetDarkerColor((topBrush as LinearGradientBrush).GradientStops[2].Color, .8).ToString(), color); break; case MarkerTypes.Diamond: color = (topBrush as LinearGradientBrush).GradientStops[2].Color.ToString(); xaml = String.Format(@" ", Graphics.GetDarkerColor((topBrush as LinearGradientBrush).GradientStops[2].Color, .8).ToString(), color); break; case MarkerTypes.Square: Double height = MarkerSize.Height * ScaleFactor; Double width = MarkerSize.Width * ScaleFactor; Canvas bevelCanvas = Visifire.Charts.ExtendedGraphics.Get2DRectangleBevel(this.Tag as FrameworkElement, width, height, 3, 3, topBrush, Graphics.GetBevelSideBrush(0, MarkerFillColor), Graphics.GetBevelSideBrush(120, MarkerFillColor), Graphics.GetBevelSideBrush(100, MarkerFillColor) ); return bevelCanvas; case MarkerTypes.Triangle: color = (topBrush as LinearGradientBrush).GradientStops[1].Color.ToString(); xaml = String.Format(@" ", Graphics.GetDarkerColor((topBrush as LinearGradientBrush).GradientStops[1].Color, .8).ToString(), color); break; case MarkerTypes.Line: color = (topBrush as LinearGradientBrush).GradientStops[1].Color.ToString(); xaml = String.Format(@" ", Graphics.GetDarkerColor((topBrush as LinearGradientBrush).GradientStops[1].Color, .8).ToString(), color); break; } #if WPF return (Shape)XamlReader.Load(new XmlTextReader(new StringReader(xaml))); #else return System.Windows.Markup.XamlReader.Load(xaml) as Shape; #endif } /// /// Sets values for rotate transform /// /// Ref RotateTransform /// CenterX /// CenterY /// Angle private void SetRotateTransformValues(ref RotateTransform rotateTransform, Double centerX, Double centerY, Double angle) { rotateTransform.CenterX = centerX; rotateTransform.CenterY = centerY; rotateTransform.Angle = angle; } private void SetRotation(Double radius, Double angle, Double angleInRadian, Point centerOfRotation) { Double left = centerOfRotation.X + radius * Math.Cos(angleInRadian); Double top = centerOfRotation.Y + radius * Math.Sin(angleInRadian); top -= TextBlockSize.Height / 2; if (TextBackgroundCanvas != null) { TextBackgroundCanvas.SetValue(Canvas.LeftProperty, left); TextBackgroundCanvas.SetValue(Canvas.TopProperty, top); TextBackgroundCanvas.Width = TextBlockSize.Width; TextBackgroundCanvas.Height = TextBlockSize.Height; TextBlock.SetValue(Canvas.TopProperty, -(Double)2); TextBackgroundCanvas.RenderTransformOrigin = new Point(0, 0.5); TextBackgroundCanvas.RenderTransform = new RotateTransform() { CenterX = 0, CenterY = 0, Angle = angle }; } } /// /// Set alignment for the Marker label /// private void SetAlignment4Label() { if (TextBlock != null) { #if WPF TextBlockSize = Graphics.CalculateVisualSize(TextBlock); #else TextBlockSize = new Size(TextBlock.ActualWidth, TextBlock.ActualHeight); #endif if (TextOrientation == Orientation.Vertical) { TransformGroup tg = new TransformGroup(); RotateTransform rt = new RotateTransform(); TranslateTransform tt = new TranslateTransform(); tg.Children.Add(rt); tg.Children.Add(tt); switch (TextAlignmentY) { case AlignmentY.Top: switch (TextAlignmentX) { case AlignmentX.Left: TextBlock.RenderTransformOrigin = new Point(0, 1); SetRotateTransformValues(ref rt, 0, 0, -90); tt.X = TextBlockSize.Width; break; case AlignmentX.Center: if (Double.IsNaN(LabelAngle)) { SetRotateTransformValues(ref rt, TextBlockSize.Width / 2, TextBlockSize.Height / 2, -90); tt.Y = -TextBlockSize.Width / 2 + TextBlockSize.Height / 2 - 5; tt.X = -1; } else { Point centerOfRotation = new Point(Position.X, Position.Y); Double radius = MarkerSize.Height / 2 * ScaleFactor; Double angle = 0; Double angleInRadian = 0; if (LabelStyle == LabelStyles.OutSide) { if (LabelAngle > 0 && LabelAngle <= 90) { angle = LabelAngle - 180; angleInRadian = (Math.PI / 180) * angle; radius += TextBlockSize.Width; angle = (angleInRadian - Math.PI) * (180 / Math.PI); SetRotation(radius, angle, angleInRadian, centerOfRotation); } else if (LabelAngle >= -90 && LabelAngle < 0) { angle = LabelAngle; angleInRadian = (Math.PI / 180) * angle; SetRotation(radius, angle, angleInRadian, centerOfRotation); } } else { centerOfRotation = new Point(Position.X, Position.Y + MarkerSize.Height / 2); if (LabelAngle >= -90 && LabelAngle < 0) { angle = 180 + LabelAngle; angleInRadian = (Math.PI / 180) * angle; radius += TextBlockSize.Width + 3; angle = (angleInRadian - Math.PI) * (180 / Math.PI); SetRotation(radius, angle, angleInRadian, centerOfRotation); } else if (LabelAngle > 0 && LabelAngle <= 90) { radius += 3; angle = LabelAngle; angleInRadian = (Math.PI / 180) * angle; SetRotation(radius, angle, angleInRadian, centerOfRotation); } } } break; case AlignmentX.Right: TextBlock.RenderTransformOrigin = new Point(0, 1); SetRotateTransformValues(ref rt, 0, 0, -90); tt.X = TextBlockSize.Height; break; } break; case AlignmentY.Center: switch (TextAlignmentX) { case AlignmentX.Left: if (Double.IsNaN(LabelAngle)) { SetRotateTransformValues(ref rt, TextBlockSize.Width, TextBlockSize.Height / 2, 90); tt.Y = TextBlockSize.Width / 2; tt.X = -TextBlockSize.Height / 2; } else { Point centerOfRotation = new Point(Position.X + MarkerSize.Width / 2, Position.Y + MarkerSize.Height / 2); Double radius = MarkerSize.Width / 2 * ScaleFactor; Double angle = 0; Double angleInRadian = 0; if (LabelStyle == LabelStyles.OutSide) { if (LabelAngle > 0 && LabelAngle <= 90) { angle = LabelAngle - 180; angleInRadian = (Math.PI / 180) * angle; radius += TextBlockSize.Width + 3; angle = (angleInRadian - Math.PI) * (180 / Math.PI); SetRotation(radius, angle, angleInRadian, centerOfRotation); } else if (LabelAngle >= -90 && LabelAngle < 0) { angle = LabelAngle - 180; angleInRadian = (Math.PI / 180) * angle; radius += TextBlockSize.Width + 3; angle = (angleInRadian - Math.PI) * (180 / Math.PI); SetRotation(radius, angle, angleInRadian, centerOfRotation); } } else { if (LabelAngle <= 90 && LabelAngle >= -90) { angle = LabelAngle; radius += 3; angleInRadian = (Math.PI / 180) * angle; SetRotation(radius, angle, angleInRadian, centerOfRotation); } } } break; case AlignmentX.Center: if (Double.IsNaN(LabelAngle)) { TextBlock.RenderTransformOrigin = new Point(0.5, 0.5); rt.Angle = 90; } else { Point centerOfRotation = new Point(Position.X, Position.Y + MarkerShape.Height / 2); Double radius = 4; Double angle = 0; Double angleInRadian = 0; if (LabelAngle > 0 && LabelAngle <= 90) { angle = LabelAngle - 180; angleInRadian = (Math.PI / 180) * angle; radius += TextBlockSize.Width; angle = (angleInRadian - Math.PI) * (180 / Math.PI); SetRotation(radius, angle, angleInRadian, centerOfRotation); } else if (LabelAngle >= -90 && LabelAngle < 0) { angle = LabelAngle; angleInRadian = (Math.PI / 180) * angle; SetRotation(radius, angle, angleInRadian, centerOfRotation); } } break; case AlignmentX.Right: if (Double.IsNaN(LabelAngle)) { SetRotateTransformValues(ref rt, 0, TextBlockSize.Height / 2, -90); tt.Y = TextBlockSize.Width / 2; tt.X = TextBlockSize.Height / 2; } else { Point centerOfRotation = new Point(Position.X - MarkerSize.Width / 2, Position.Y + MarkerSize.Height / 2); Double radius = MarkerSize.Width / 2 * ScaleFactor; Double angle = 0; Double angleInRadian = 0; if (LabelStyle == LabelStyles.OutSide) { if (LabelAngle <= 90 && LabelAngle >= -90) { angle = LabelAngle; radius += 3; angleInRadian = (Math.PI / 180) * angle; SetRotation(radius, angle, angleInRadian, centerOfRotation); } } else { if (LabelAngle > 0 && LabelAngle <= 90) { angle = LabelAngle - 180; angleInRadian = (Math.PI / 180) * angle; radius += TextBlockSize.Width + 3; angle = (angleInRadian - Math.PI) * (180 / Math.PI); SetRotation(radius, angle, angleInRadian, centerOfRotation); } else if (LabelAngle >= -90 && LabelAngle < 0) { angle = LabelAngle - 180; angleInRadian = (Math.PI / 180) * angle; radius += TextBlockSize.Width + 3; angle = (angleInRadian - Math.PI) * (180 / Math.PI); SetRotation(radius, angle, angleInRadian, centerOfRotation); } } } break; } break; case AlignmentY.Bottom: switch (TextAlignmentX) { case AlignmentX.Left: SetRotateTransformValues(ref rt, TextBlockSize.Width / 2, TextBlockSize.Height / 2, -90); tt.Y = TextBlockSize.Width / 2 - TextBlockSize.Height / 2; tt.X = TextBlockSize.Width / 2 - TextBlockSize.Height / 2; break; case AlignmentX.Center: if (Double.IsNaN(LabelAngle)) { SetRotateTransformValues(ref rt, TextBlockSize.Width / 2, TextBlockSize.Height / 2, -90); //tt.Y = TextBlockSize.Height + MarkerSize.Height * ScaleFactor; tt.Y = TextBlockSize.Width / 2; tt.X = -1; } else { Point centerOfRotation = new Point(); Double radius = MarkerSize.Height / 2 * ScaleFactor; Double angle = 0; Double angleInRadian = 0; if (LabelStyle == LabelStyles.OutSide) { centerOfRotation = new Point(Position.X, Position.Y); if (LabelAngle >= -90 && LabelAngle < 0) { angle = 180 + LabelAngle; angleInRadian = (Math.PI / 180) * angle; radius += TextBlockSize.Width; angle = (angleInRadian - Math.PI) * (180 / Math.PI); SetRotation(radius, angle, angleInRadian, centerOfRotation); } else if (LabelAngle > 0 && LabelAngle <= 90) { angle = LabelAngle; angleInRadian = (Math.PI / 180) * angle; SetRotation(radius, angle, angleInRadian, centerOfRotation); } } else { centerOfRotation = new Point(Position.X, Position.Y - MarkerSize.Height / 2); if (LabelAngle > 0 && LabelAngle <= 90) { angle = LabelAngle - 180; angleInRadian = (Math.PI / 180) * angle; radius += TextBlockSize.Width + 3; angle = (angleInRadian - Math.PI) * (180 / Math.PI); SetRotation(radius, angle, angleInRadian, centerOfRotation); } else if (LabelAngle >= -90 && LabelAngle < 0) { radius += 3; angle = LabelAngle; angleInRadian = (Math.PI / 180) * angle; SetRotation(radius, angle, angleInRadian, centerOfRotation); } } } break; case AlignmentX.Right: SetRotateTransformValues(ref rt, 0, 0, -90); tt.Y = TextBlockSize.Width; break; } break; } if (Double.IsNaN(LabelAngle)) { TextBlock.RenderTransform = tg; if (TextBackgroundCanvas != null) { TextBackgroundCanvas.RenderTransformOrigin = TextBlock.RenderTransformOrigin; TextBackgroundCanvas.RenderTransform = tg; TextBackgroundCanvas.Height = TextBlockSize.Height; TextBackgroundCanvas.Width = TextBlockSize.Width; } } } else { if (DataSeriesOfLegendMarker == null) { TransformGroup tg = new TransformGroup(); RotateTransform rt = new RotateTransform(); TranslateTransform tt = new TranslateTransform(); tg.Children.Add(rt); tg.Children.Add(tt); switch (TextAlignmentY) { case AlignmentY.Top: switch (TextAlignmentX) { case AlignmentX.Center: if (Double.IsNaN(LabelAngle)) { SetRotateTransformValues(ref rt, 0, 0, 0); tt.Y = -3; } break; } break; case AlignmentY.Bottom: switch (TextAlignmentX) { case AlignmentX.Center: if (Double.IsNaN(LabelAngle)) { SetRotateTransformValues(ref rt, 0, 0, 0); tt.Y = 1; } break; } break; case AlignmentY.Center: switch (TextAlignmentX) { case AlignmentX.Left: if (Double.IsNaN(LabelAngle)) { SetRotateTransformValues(ref rt, 0, 0, 0); tt.X = -5; tt.Y = -1; } break; case AlignmentX.Center: if (Double.IsNaN(LabelAngle)) { SetRotateTransformValues(ref rt, 0, 0, 0); tt.Y = -1; } break; case AlignmentX.Right: if (Double.IsNaN(LabelAngle)) { SetRotateTransformValues(ref rt, 0, 0, 0); tt.X = 4; tt.Y = -1; } break; } break; } if (Double.IsNaN(LabelAngle)) { TextBlock.RenderTransform = tg; if (TextBackgroundCanvas != null) { TextBackgroundCanvas.RenderTransformOrigin = TextBlock.RenderTransformOrigin; TextBackgroundCanvas.RenderTransform = tg; TextBackgroundCanvas.Height = TextBlockSize.Height; TextBackgroundCanvas.Width = TextBlockSize.Width; } } } } SetLabelBackgroundAndSymbolPosition(); } } /// /// Set background of label and position of symbol /// private void SetLabelBackgroundAndSymbolPosition() { if (Double.IsNaN(LabelAngle)) { if (TextBackgroundCanvas != null) { TextBackgroundCanvas.Height = TextBlockSize.Height; TextBackgroundCanvas.Width = TextBlockSize.Width; } if (TextAlignmentX == AlignmentX.Left) { TextBlock.SetValue(Grid.ColumnProperty, 0); _markerShapePosition.X = TextBlockSize.Width; if (TextBackgroundCanvas != null) { TextBackgroundCanvas.SetValue(Grid.ColumnProperty, 0); } } else if (TextAlignmentX == AlignmentX.Right) { TextBlock.SetValue(Grid.ColumnProperty, 2); if (TextBackgroundCanvas != null) { TextBackgroundCanvas.SetValue(Grid.ColumnProperty, 2); } } else { TextBlock.SetValue(Grid.ColumnProperty, 1); TextBlock.HorizontalAlignment = HorizontalAlignment.Center; if (TextBackgroundCanvas != null) { TextBackgroundCanvas.SetValue(Grid.ColumnProperty, 1); TextBackgroundCanvas.HorizontalAlignment = HorizontalAlignment.Center; } } if (TextAlignmentY == AlignmentY.Top) { TextBlock.SetValue(Grid.RowProperty, 0); _markerShapePosition.Y = TextBlockSize.Height; if (TextBackgroundCanvas != null) { TextBackgroundCanvas.SetValue(Grid.RowProperty, 0); } } else if (TextAlignmentY == AlignmentY.Bottom) { TextBlock.SetValue(Grid.RowProperty, 2); if (TextBackgroundCanvas != null) { TextBackgroundCanvas.SetValue(Grid.RowProperty, 2); } } else { TextBlock.SetValue(Grid.RowProperty, 1); TextBlock.VerticalAlignment = VerticalAlignment.Center; if (TextBackgroundCanvas != null) { TextBackgroundCanvas.SetValue(Grid.RowProperty, 1); TextBackgroundCanvas.VerticalAlignment = VerticalAlignment.Center; } } } if (TextAlignmentX == AlignmentX.Center) _markerShapePosition.X += Math.Abs((TextBlockSize.Width - MarkerShape.Width) / 2); if (TextAlignmentY == AlignmentY.Center) _markerShapePosition.Y += Math.Abs((TextBlockSize.Height - MarkerShape.Height) / 2); } /// /// Get shadow color of the Marker shape /// /// private Brush GetMarkerShadowColor() { // String xaml = String.Format(@" // // // "); LinearGradientBrush brush = new LinearGradientBrush(); brush.StartPoint = new Point(0.497000008821487, 1.00100004673004); brush.EndPoint = new Point(0.503000020980835, -0.00100000004749745); brush.GradientStops.Add(new GradientStop() { Color = Color.FromArgb(180, 108, 108, 108), Offset = 1 }); brush.GradientStops.Add(new GradientStop() { Color = Color.FromArgb(00, 255, 255, 255), Offset = 1 }); return brush; #if WPF //return (Brush)XamlReader.Load(new XmlTextReader(new StringReader(xaml))); #else //return System.Windows.Markup.XamlReader.Load(xaml) as Brush; #endif } #endregion #region Internal Methods #endregion #region Internal Events And Delegates #endregion #region Data /// /// The identifier for property FontSize /// private Double _fontSize; /// /// The identifier for property FontFamily /// private FontFamily _fontFamily; /// /// The identifier for property FontStyle /// private FontStyle _fontStyle; /// /// The identifier for property FontWeight /// private FontWeight _fontWeight; /// /// The identifier for property FontColor /// private Brush _fontColor; /// /// The identifier for property BorderThickness /// private Double _borderThickness; /// /// The identifier for property BorderColor /// private Brush _borderColor; /// /// HorizontalAlignment of Marker label /// private AlignmentX _textAlignmentX; /// /// VerticalAlignment of Marker label /// private AlignmentY _textAlignmentY; /// /// The identifier for property Text /// private String _text; /// /// The identifier for ScaleFactor property /// private Double _scaleFactor = 1; /// /// Actual position of the Marker shape inside Marker grid /// private Point _markerShapePosition; #endregion } }