internal override void ArrangeLabel(FrameworkElement visual, ChartSeriesLabelUpdateContext context) { RadSize size = MeasureVisual(visual); PieDataPoint piePoint = context.Point as PieDataPoint; double radius = this.updateContext.Radius; double offsetFromCenter = radius * piePoint.OffsetFromCenter; double offset = context.Definition.Margin.Left; // calculate the position of the label, depending on its size this.updateContext.Radius = radius - offset + offsetFromCenter; this.updateContext.StartAngle = piePoint.startAngle; double angle = piePoint.startAngle; if (this.AngleRange.SweepDirection == ChartSweepDirection.Clockwise) { angle += piePoint.sweepAngle / 2; } else { angle -= piePoint.sweepAngle / 2; } Point middlePoint = this.updateContext.CalculateArcPoint(angle); middlePoint.X += size.Width * Math.Cos(angle * RadMath.DegToRadFactor) / 2; middlePoint.Y += size.Height * Math.Sin(angle * RadMath.DegToRadFactor) / 2; RadRect labelRect = RadRect.Round(new RadRect(middlePoint.X - (size.Width / 2), middlePoint.Y - (size.Height / 2), size.Width, size.Height)); this.ArrangeUIElement(visual, labelRect); this.updateContext.Radius = radius; }
internal virtual void SetLabelContent(FrameworkElement visual, ChartSeriesLabelUpdateContext context) { if (context.Definition.Strategy != null) { if ((context.Definition.Strategy.Options & LabelStrategyOptions.DefaultVisual) == LabelStrategyOptions.DefaultVisual) { context.Definition.Strategy.SetLabelContent(context.Point, visual, context.DefinitionIndex); } } }
internal virtual RadSize MeasureLabel(FrameworkElement visual, ChartSeriesLabelUpdateContext context) { if (context.Definition.Strategy != null) { if ((context.Definition.Strategy.Options & LabelStrategyOptions.Measure) == LabelStrategyOptions.Measure) { return(context.Definition.Strategy.GetLabelDesiredSize(context.Point, visual, context.DefinitionIndex)); } } return(PresenterBase.MeasureVisual(visual)); }
internal virtual DataTemplate GetLabelTemplate(ChartSeriesLabelUpdateContext context) { DataTemplate template = null; if (context.Definition.Template != null) { template = context.Definition.Template; } else if (context.Definition.TemplateSelector != null) { template = context.Definition.TemplateSelector.SelectTemplate(context.Point, this); } return(template); }
internal virtual FrameworkElement CreateDefaultLabelVisual(ChartSeriesLabelUpdateContext context) { if (context.Definition.Strategy != null) { if ((context.Definition.Strategy.Options & LabelStrategyOptions.DefaultVisual) == LabelStrategyOptions.DefaultVisual) { return(context.Definition.Strategy.CreateDefaultVisual(context.Point, context.DefinitionIndex)); } } TextBlock block = new TextBlock(); block.Style = context.Definition.DefaultVisualStyle; return(block); }
private void ProcessDataPointLabels(ChartSeriesLabelUpdateContext context) { // we have user-defined definition(s) if (this.labelDefinitions.Count > 0) { int index = 0; foreach (ChartSeriesLabelDefinition definition in this.labelDefinitions) { context.Definition = definition; context.DefinitionIndex = index; this.ProcessLabelDefinition(context); index++; } } else { context.Definition = CreateDefaultLabelDefinition(context.PlotDirection); this.ProcessLabelDefinition(context); } }
internal virtual object GetLabelContent(ChartSeriesLabelUpdateContext context) { // we have a custom strategy that will provide a label content if (context.Definition.Strategy != null) { if ((context.Definition.Strategy.Options & LabelStrategyOptions.Content) == LabelStrategyOptions.Content) { return(context.Definition.Strategy.GetLabelContent(context.Point, context.DefinitionIndex)); } } object label = null; // we have a label binding - it will work if we are data-bound (run-time only) if (context.Definition.Binding != null && !DesignMode.DesignModeEnabled) { if (!this.Model.isDataBound) { throw new ArgumentException("ChartSeriesLabelDefinition.Binding is valid when owning series is data-bound."); } object dataItem = context.Point.dataItem; if (dataItem == null) { Debug.Assert(false, string.Format("Failed to retrieve data item for data point at index {0}", context.Point.CollectionIndex)); return(null); } label = context.Definition.Binding.GetValue(dataItem); } else { label = context.Point.Label; } if (label != null && !string.IsNullOrEmpty(context.Definition.Format)) { return(string.Format(CultureInfo.CurrentUICulture, context.Definition.Format, label)); } return(label); }
private void ProcessLabelDefinition(ChartSeriesLabelUpdateContext context) { FrameworkElement visual = this.GetLabelVisual(context); if (visual == null) { Debug.Assert(false, "No label visual created."); return; } if (context.Definition.Strategy != null) { if ((context.Definition.Strategy.Options & LabelStrategyOptions.Arrange) == LabelStrategyOptions.Arrange) { RadRect labelSlot = context.Definition.Strategy.GetLabelLayoutSlot(context.Point, visual, context.DefinitionIndex); this.ArrangeUIElement(visual, labelSlot); return; } } this.ArrangeLabel(visual, context); }
private FrameworkElement CreateLabelVisual(ChartSeriesLabelUpdateContext context) { FrameworkElement visual; DataTemplate template = this.GetLabelTemplate(context); if (template != null) { visual = new ContentPresenter(); } else { visual = this.CreateDefaultLabelVisual(context); if (visual == null) { throw new ArgumentNullException("Label default visual cannot be null."); } } this.labelLayer.Children.Add(visual); return(visual); }
private void UpdateLabels(ChartLayoutContext context) { int index = 0; ChartSeriesModel series = this.Model; ChartSeriesLabelUpdateContext labelContext = new ChartSeriesLabelUpdateContext(); labelContext.PlotDirection = this.Model.GetTypedValue <AxisPlotDirection>(AxisModel.PlotDirectionPropertyKey, AxisPlotDirection.Vertical); labelContext.IsPlotInverse = this.Model.GetIsPlotInverse(labelContext.PlotDirection); if (this.showLabelsCache) { foreach (DataPoint point in series.DataPointsInternal) { // point is empty or is laid-out outside the clip area, skip it from visualization. if (point.isEmpty || !context.ClipRect.IntersectsWith(point.layoutSlot)) { continue; } labelContext.Point = point; labelContext.PointVirtualIndex = index; this.ProcessDataPointLabels(labelContext); index++; } } while (index < this.labels.Count) { List <FrameworkElement> pointLabels = this.labels[index].Value; foreach (FrameworkElement label in pointLabels) { label.Visibility = Visibility.Collapsed; } index++; } }
private FrameworkElement GetLabelVisual(ChartSeriesLabelUpdateContext context) { FrameworkElement element; List <FrameworkElement> pointLabels; if (context.PointVirtualIndex < this.labels.Count) { pointLabels = this.labels[context.PointVirtualIndex].Value; if (pointLabels == null) { Debug.Assert(false, "Must have list of label visuals created at this point"); return(null); } if (pointLabels.Count > context.DefinitionIndex) { element = pointLabels[context.DefinitionIndex]; element.Visibility = Visibility.Visible; } else { element = this.CreateLabelVisual(context); pointLabels.Add(element); } if (IsDefaultLabelVisual(element)) { element.Style = context.Definition.DefaultVisualStyle; } } else { element = this.CreateLabelVisual(context); pointLabels = new List <FrameworkElement>(); pointLabels.Add(element); this.labels.Add(new KeyValuePair <DataPoint, List <FrameworkElement> >(context.Point, pointLabels)); } DataTemplate labelTemplate = this.GetLabelTemplate(context); // NOTE: When Template or TemplateSelector is defined, the DataContext of the item labels' DataTemplate // should be the respective DataPoint and not just calculated value. if (labelTemplate != null) { // Assumes ContentPresenter has been created to handle this case. // NOTE: this will override any ChartSeriesLabelDefinition.Binding logic now (if both Binding and Template/TemplateSelector are set) ContentPresenter presenter = element as ContentPresenter; presenter.Content = context.Point; presenter.ContentTemplate = labelTemplate; } else { TextBlock textblock = element as TextBlock; if (textblock != null) { // Assumes TextBlock has been created to handle the default case. object label = this.GetLabelContent(context); textblock.Text = label == null ? string.Empty : label.ToString(); } else { // Assumes if user-defined label strategy is involved in visual creation (even if the strategy creates ContentPresenters), // the strategy should be responsible for setting its content (via ChartSeriesLabelStrategy.SetLabelContent(...) method override) this.SetLabelContent(element, context); } } return(element); }
private static RadRect GetLabelSlot(RadSize labelSize, ChartSeriesLabelUpdateContext context) { double x = double.NaN; double y = double.NaN; Thickness margin = context.Definition.Margin; RadRect pointSlot = context.Point.layoutSlot; switch (context.Definition.HorizontalAlignment) { case HorizontalAlignment.Center: x = pointSlot.X + ((pointSlot.Width - labelSize.Width) / 2) + margin.Left - margin.Right; break; case HorizontalAlignment.Stretch: x = pointSlot.X + ((pointSlot.Width - labelSize.Width) / 2); break; case HorizontalAlignment.Left: // positive point with regular axis is equivalent to negative point with inverse axis if (context.PlotDirection == AxisPlotDirection.Horizontal && !(context.Point.isPositive ^ context.IsPlotInverse)) { // swap Left with Right due to negative values x = pointSlot.Right - margin.Left + margin.Right; } else { x = pointSlot.X - labelSize.Width - margin.Right + margin.Left; } break; case HorizontalAlignment.Right: // positive point with regular axis is equivalent to negative point with inverse axis if (context.PlotDirection == AxisPlotDirection.Horizontal && !(context.Point.isPositive ^ context.IsPlotInverse)) { // swap Left with Right due to negative values x = pointSlot.X - labelSize.Width - margin.Left + margin.Right; } else { x = pointSlot.Right + margin.Left - margin.Right; } break; } switch (context.Definition.VerticalAlignment) { case VerticalAlignment.Center: y = pointSlot.Y + ((pointSlot.Height - labelSize.Height) / 2) + margin.Top - margin.Bottom; break; case VerticalAlignment.Stretch: y = pointSlot.Y + ((pointSlot.Height - labelSize.Height) / 2); break; case VerticalAlignment.Bottom: // positive point with regular axis is equivalent to negative point with inverse axis if (context.PlotDirection == AxisPlotDirection.Vertical && !(context.Point.isPositive ^ context.IsPlotInverse)) { // swap Bottom with Top due to negative values y = pointSlot.Y - labelSize.Height - margin.Top + margin.Bottom; } else { y = pointSlot.Bottom + margin.Top - margin.Bottom; } break; case VerticalAlignment.Top: // positive point with regular axis is equivalent to negative point with inverse axis if (context.PlotDirection == AxisPlotDirection.Vertical && !(context.Point.isPositive ^ context.IsPlotInverse)) { // swap Top with Bottom due to negative values y = pointSlot.Bottom + margin.Bottom - margin.Top; } else { y = pointSlot.Y - labelSize.Height - margin.Bottom + margin.Top; } break; } return(new RadRect(x, y, labelSize.Width, labelSize.Height)); }
internal virtual void ArrangeLabel(FrameworkElement visual, ChartSeriesLabelUpdateContext context) { RadSize size = this.MeasureLabel(visual, context); this.ArrangeUIElement(visual, GetLabelSlot(size, context)); }