protected override void OnRender(DrawingContext drawingContext) { //TODO potential rendering loop. if (FilteredData.Count < 1) { FilteredData = DataFilter.Filter(DataSorter.Sort(Data)); base.OnRender(drawingContext); return; } visualContext = new NestedArcChartVisualContext(); PART_segments.Children.Clear(); PART_inactivesegments.Children.Clear(); PART_categorylabels.Children.Clear(); var context = new ProviderContext(FilteredData.Count); MaterialProvider.Reset(context); var fullArcDiameter = PART_main.RenderSize.Height - TopRingPadding; var fullArcWidth = fullArcDiameter - BottomRingPadding; var subArcAvailableWidth = fullArcWidth / FilteredData.Count; var subArcActualWidth = subArcAvailableWidth * SegmentWidthPercentage; var subRingOffset = (subArcAvailableWidth - subArcActualWidth) / 2; var fullRadius = PART_main.RenderSize.Width / 2; var centerPoint = new Point(0, fullRadius); if (FilteredData.Count < 1) { base.OnRender(drawingContext); return; } var max = FilteredData.MaxValue(); var trace = 0; foreach (var d in FilteredData) { var categoryVisualContext = new NestedArcCategoryVisualContext(); var materialSet = MaterialProvider.ProvideNext(context); categoryVisualContext.CategoryDataPoint = d; var arcDiameter = BottomRingPadding + (subArcAvailableWidth * trace) + subRingOffset; var inactiveArcPath = CalculatePath(centerPoint, arcDiameter, subArcActualWidth); inactiveArcPath.Fill = SegmentSpaceBackground.GetMaterial(materialSet); //BindingOperations.SetBinding(inactiveArcPath, Shape.FillProperty, new Binding("SegmentSpaceBackground") { Source = this }); categoryVisualContext.InactiveArcVisual = inactiveArcPath; PART_inactivesegments.Children.Add(inactiveArcPath); var activeArcAngle = d.Value.Map(0, max, 0, MaxArcAngle); var activeArcPath = CalculateActiveArcPath(centerPoint, arcDiameter, subArcActualWidth, activeArcAngle); categoryVisualContext.CategoryMaterialSet = materialSet; activeArcPath.Fill = SegmentForeground.GetMaterial(materialSet); activeArcPath.MouseOverFill = materialSet.GetMaterial(Luminosity.P700); activeArcPath.RenderTransformOrigin = new Point(.5, 1); activeArcPath.RenderTransform = new RotateTransform((IsLoaded ? 0 : 180), .5, .5); d.RenderedVisual = activeArcPath; categoryVisualContext.ActiveArcVisual = activeArcPath; PART_segments.Children.Add(activeArcPath); visualContext.CategoryVisuals.Add(categoryVisualContext); trace++; } var ltrace = 0; for (var x = FilteredData.Count - 1; x >= 0; x--) { var d = FilteredData[x]; var currentCategoryVisualContext = visualContext.CategoryVisuals[x]; var shape = (Shape)d.RenderedVisual; //.ShouldBeCastable<Shape>(); var renderedFill = (SolidColorBrush)shape.Fill; //.ShouldBeType<SolidColorBrush>(); var arcLabelMarginLeft = fullRadius + LeftArcLabelSpacing; var categoryLabel = new Label { Width = ValueLabelHorizontalSpacing, VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Left, Margin = new Thickness(arcLabelMarginLeft, (ltrace * subArcAvailableWidth) + subRingOffset + 6, 0, 0), //Foreground = renderedFill.Lighten(.2), Foreground = ValueForeground.GetMaterial(currentCategoryVisualContext.CategoryMaterialSet), Content = d.CategoryName.ToUpper(), Height = subArcAvailableWidth, Padding = new Thickness(0), Opacity = IsLoaded ? 1 : 0, // TODO isloaded DataContext = this }; currentCategoryVisualContext.CategoryLabel = categoryLabel; //BindingOperations.SetBinding(categoryLabel, FontFamilyProperty, new Binding("ValueFontFamily") { Source = this }); //BindingOperations.SetBinding(categoryLabel, FontStyleProperty, new Binding("ValueFontStyle") { Source = this }); //BindingOperations.SetBinding(categoryLabel, FontWeightProperty, new Binding("ValueFontWeight") { Source = this }); //BindingOperations.SetBinding(categoryLabel, FontSizeProperty, new Binding("ValueFontSize") { Source = this }); categoryLabel.BindTextualPrimitive <ValuePrimitive>(this); var valuePercentLabel = new Label { Width = ValueLabelHorizontalSpacing, VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Right, Margin = new Thickness(arcLabelMarginLeft, (ltrace * subArcAvailableWidth) + subRingOffset + 6, 0, 0), //Foreground = renderedFill.Lighten(.2), Foreground = ValueForeground.GetMaterial(currentCategoryVisualContext.CategoryMaterialSet), Content = d.Value + " Minutes", Height = subArcAvailableWidth, Padding = new Thickness(0), Opacity = IsLoaded ? 1 : 0, DataContext = this }; currentCategoryVisualContext.ValuePercentLabel = valuePercentLabel; valuePercentLabel.BindTextualPrimitive <ValuePrimitive>(this); var valueLabelLeftSpace = arcLabelMarginLeft + ValueLabelHorizontalSpacing; var valueLabelWidth = PART_main.RenderSize.Width - valueLabelLeftSpace; if (valueLabelWidth < 0) { valueLabelWidth = 0; } var valueLabel = new Label() { Width = valueLabelWidth, VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center, HorizontalContentAlignment = HorizontalAlignment.Left, Foreground = SecondaryValueForeground.GetMaterial(currentCategoryVisualContext.CategoryMaterialSet), Margin = new Thickness(arcLabelMarginLeft + ValueLabelHorizontalSpacing, (ltrace * subArcAvailableWidth) + subRingOffset + 6, 0, 0), Content = $" = {Math.Round(d.Value / 60, 2)} Hours", //{Math.Round(d.Value * 48):n0} Height = subArcAvailableWidth, Opacity = IsLoaded ? 1 : 0, // TODO isloaded Padding = new Thickness(0), }; currentCategoryVisualContext.ValueLabel = valueLabel; valueLabel.BindTextualPrimitive <SecondaryValuePrimitive>(this); PART_categorylabels.Children.Add(categoryLabel); PART_categorylabels.Children.Add(valuePercentLabel); PART_categorylabels.Children.Add(valueLabel); ltrace++; } base.OnRender(drawingContext); }
protected override void OnRender(DrawingContext drawingContext) { PART_focusedsegmentlabel.Foreground = SecondaryValueForeground.GetMaterial(FallbackMaterialSet); PART_segments.Children.Clear(); var context = new ProviderContext(FilteredData.Count); MaterialProvider.Reset(context); var radius = (PART_segments.RenderSize.Smallest() * CircleScale) / 2; var total = Data.SumValue(); var angleTrace = 0d; var actualRingWidth = radius * RingWidthPercentage; foreach (var d in FilteredData) { var materialSet = MaterialProvider.ProvideNext(context); var degrees = (d.Value / total) * 360; var activePath = new ArcPath(degrees, angleTrace, actualRingWidth, CircleScale, radius, PART_segments.RenderSize, d) { Fill = SegmentForeground.GetMaterial(materialSet), MouseOverFill = materialSet.GetMaterial(Luminosity.P700), DataContext = this }; activePath.Click += segmentClicked; PART_segments.Children.Add(activePath); d.RenderedVisual = activePath; angleTrace += degrees; } if (FocusedSegment == null) { return; } PART_categorylabels.Children.Clear(); var diameter = PART_segments.RenderSize.Smallest() * CircleScale; var outerLabelRadius = (diameter / 2) * OuterLabelPositionScale; var overlayedLabelRadius = (diameter / 2) - (actualRingWidth / 2); var targetAngularOffset = FocusedSegment.RequireType <ArcPath>().CalculateAngularOffset(); MaterialProvider.Reset(context); foreach (var d in FilteredData) { var materialSet = MaterialProvider.ProvideNext(context); var categoryNameLabel = positionLabel(d, outerLabelRadius, targetAngularOffset, true); categoryNameLabel.Content = d.CategoryName; categoryNameLabel.BindTextualPrimitive <BarTotalPrimitive>(this); categoryNameLabel.Foreground = BarTotalForeground.GetMaterial(materialSet); PART_categorylabels.Children.Add(categoryNameLabel); var valueLabel = positionLabel(d, overlayedLabelRadius, targetAngularOffset); valueLabel.Content = d.Value; valueLabel.BindTextualPrimitive <ValuePrimitive>(this); valueLabel.Foreground = ValueForeground.GetMaterial(materialSet); PART_categorylabels.Children.Add(valueLabel); } base.OnRender(drawingContext); }