/// <summary> /// Check if the path thickness, the selection state and the arrows of this instance /// are equal to another <see cref="RenderDataCache"/>'s properties. /// </summary> public bool StateEquals(RenderDataCache other) { return(other.PathThickness == PathThickness && other.Selected == Selected && Equals(other.Arrows, Arrows) && //////////////// New in this sample //////////////// other.obstacleHash == obstacleHash); //////////////////////////////////////////////////// }
/// <summary> /// Creates the visual appearance of an edge /// </summary> private void Render(IRenderContext context, IEdge edge, VisualGroup container, RenderDataCache cache) { // store information with the visual on how we created it container.SetRenderDataCache(cache); GeneralPath gp = cache.GeneralPath; Path path = new Path { // convince WPF to render the path even if all coordinates are negative Stretch = Stretch.None, MinWidth = 1, MinHeight = 1, Data = CreateGeometry(gp) }; if (cache.Selected) { // Fill for selected state path.Stroke = animatedPathStroke; } else { // Fill for non-selected state path.Stroke = pathStroke; } path.StrokeThickness = cache.PathThickness; path.StrokeLineJoin = PenLineJoin.Round; container.Add(path); // add the arrows to the container base.AddArrows(context, container, edge, gp, cache.Arrows, cache.Arrows); }
/// <summary> /// Creates the visual for an edge. /// </summary> protected override VisualGroup CreateVisual(IRenderContext context, IEdge edge) { // This implementation creates a VisualGroup and uses it for the rendering of the edge. var visual = new VisualGroup(); // Get the necessary data for rendering of the edge RenderDataCache cache = CreateRenderDataCache(context, edge); // Render the edge Render(context, edge, visual, cache); return visual; }
/// <summary> /// Creates the visual for a node. /// </summary> protected override VisualGroup CreateVisual(IRenderContext context, INode node) { // This implementation creates a VisualGroup and uses it for the rendering of the node. var visual = new VisualGroup(); // Get the necessary data for rendering of the edge RenderDataCache cache = CreateRenderDataCache(context, node); // Render the node Render(context, node, visual, cache); // set the location visual.SetCanvasArrangeRect(node.Layout.ToRectD()); return(visual); }
/// <summary> /// Creates the visual for a label to be drawn /// </summary> protected override VisualGroup CreateVisual(IRenderContext context, ILabel label) { // This implementation creates a VisualGroup and uses it for the rendering of the label. var container = new VisualGroup(); // Get the necessary data for rendering of the label RenderDataCache cache = CreateRenderDataCache(context, label, Typeface); // Render the label var labelLayout = label.GetLayout(); Render(context, label, container, labelLayout, cache); // move container to correct location ArrangeByLayout(context, container, labelLayout, true); return(container); }
/// <summary> /// Creates the visual for a label to be drawn /// </summary> protected override VisualGroup CreateVisual(IRenderContext context, ILabel label) { // This implementation creates a VisualGroup and uses it for the rendering of the label. var container = new VisualGroup(); // Get the necessary data for rendering of the label RenderDataCache cache = CreateRenderDataCache(context, label, Typeface); // Render the label var labelLayout = label.GetLayout(); Render(context, label, container, labelLayout, cache); // move container to correct location // We delegate to LabelStyleBase's ArrangeByLayout method to position the container. // This method sets the layout properly and applies auto flipping to the text if necessary. ArrangeByLayout(context, container, labelLayout, true); return(container); }
/// <summary> /// Creates the visual for the label. /// </summary> /// <remarks> /// Implementation of LabelStyleBase.CreateVisual. /// </remarks> /// <param name="context">The render context.</param> /// <param name="label">The label to which this style instance is assigned.</param> /// <returns>The visual as required by the <see cref="IVisualCreator.CreateVisual"/> interface.</returns> protected override VisualGroup CreateVisual(IRenderContext context, ILabel label) { // Updates the dummy label which is internally used for rendering with the properties of the given label. UpdateDummyLabel(context, label); // creates the container for the visual and sets a transform for view coordinates var container = new VisualGroup(); // ReSharper disable once PossibleUnintendedReferenceComparison if (container.Transform != context.IntermediateTransform) { container.Transform = context.IntermediateTransform; } RenderDataCache cache = CreateRenderDataCache(context, label); container.SetRenderDataCache(cache); var creator = InnerLabelStyle.Renderer.GetVisualCreator(dummyLabel, InnerLabelStyle); // create a new IRenderContext with a zoom of 1 var cc = new ContextConfigurator(context.CanvasControl.ContentRect); var innerContext = cc.CreateRenderContext(context.CanvasControl); //The wrapped style should always think it's rendering with zoom level 1 var visual = creator.CreateVisual(innerContext); if (visual == null) { return(container); } // add the created visual to the container container.Children.Add(visual); // if the label is selected, add the selection visualization, too. if (cache.Selected) { UIElement selectionVisual = CreateSelectionVisual(innerContext, dummyLabel.GetLayout()) as UIElement; if (selectionVisual != null) { selectionVisual.IsHitTestVisible = false; } container.Children.Add(selectionVisual); } return(container); }
/// <summary> /// Re-renders the node using the old visual for performance reasons. /// </summary> protected override VisualGroup UpdateVisual(IRenderContext context, VisualGroup oldVisual, INode node) { // get the data with which the old visual was created RenderDataCache oldCache = oldVisual.GetRenderDataCache <RenderDataCache>(); // get the data for the new visual RenderDataCache newCache = CreateRenderDataCache(context, node); // check if something changed except for the location of the node if (!newCache.Equals(oldCache)) { // something changed - re-render the visual oldVisual.Children.Clear(); Render(context, node, oldVisual, newCache); } // make sure that the location is up to date oldVisual.SetCanvasArrangeRect(node.Layout.ToRectD()); return(oldVisual); }
/// <summary> /// Re-renders the label using the old visual for performance reasons. /// </summary> protected override VisualGroup UpdateVisual(IRenderContext context, VisualGroup oldVisual, ILabel label) { // get the data with which the old visual was created RenderDataCache oldCache = oldVisual.GetRenderDataCache <RenderDataCache>(); // get the data for the new visual RenderDataCache newCache = CreateRenderDataCache(context, label, Typeface); var labelLayout = label.GetLayout(); if (!oldCache.Equals(newCache)) { // something changed - re-render the visual oldVisual.Children.Clear(); Render(context, label, oldVisual, labelLayout, newCache); } // nothing changed, return the old visual // arrange because the layout might have changed ArrangeByLayout(context, oldVisual, labelLayout, true); return(oldVisual); }
/// <summary> /// Re-renders the edge using the old visual for performance reasons. /// </summary> protected override VisualGroup UpdateVisual(IRenderContext context, VisualGroup oldVisual, IEdge edge) { // get the data with which the old visual was created RenderDataCache oldCache = oldVisual.GetRenderDataCache<RenderDataCache>(); // get the data for the new visual RenderDataCache newCache = CreateRenderDataCache(context, edge); // check if something changed if (!newCache.StateEquals(oldCache)) { // more than only the path changed - re-render the visual oldVisual.Children.Clear(); Render(context, edge, oldVisual, newCache); return oldVisual; } if (!newCache.PathEquals(oldCache)) { // only the path changed - update the old visual UpdatePath(context, edge, oldVisual, newCache); } return oldVisual; }
/// <summary> /// Check if the path thickness is equal to another <see cref="RenderDataCache"/>'s path thickness. /// </summary> public bool StateEquals(RenderDataCache other) { return(other.PathThickness == PathThickness); }
public bool Equals(RenderDataCache other) { return(other.Color == Color && other.Size.Equals(Size)); }
/// <summary> /// Check if the path of this instance is equals to another <see cref="RenderDataCache"/>'s path. /// </summary> public bool PathEquals(RenderDataCache other) { return(other.GeneralPath.IsEquivalentTo(GeneralPath)); }
/// <summary> /// Check if the path thickness, the selection state and the arrows of this instance /// are equal to another <see cref="RenderDataCache"/>'s properties. /// </summary> public bool StateEquals(RenderDataCache other) { return(other.PathThickness == PathThickness && other.Selected == Selected && Equals(other.Arrows, Arrows)); }
/// <summary> /// Updates the edge path data as well as the arrow positions of the visuals stored in <param name="container" />. /// </summary> private void UpdatePath(IRenderContext context, IEdge edge, VisualGroup container, RenderDataCache cache) { // The first child must be a path - else re-create the container from scratch if (container.Children.Count == 0 || !(container.Children[0] is Path)) { container.Children.Clear(); Render(context, edge, container, cache); return; } // store information with the visual on how we created it container.SetRenderDataCache(cache); // update the path GeneralPath gp = cache.GeneralPath; Path path = (Path)container.Children[0]; path.Data = CreateGeometry(gp); // update the arrows base.UpdateArrows(context, container, edge, gp, cache.Arrows, cache.Arrows); }
public bool Equals(RenderDataCache other) { return(other.Color == Color && other.Size.Equals(Size) && other.DrawPrerenderedShadow == DrawPrerenderedShadow); }
/// <summary> /// Creates the visual appearance of a label /// </summary> private void Render(IRenderContext context, ILabel label, VisualGroup container, IOrientedRectangle labelLayout, RenderDataCache cache) { // store information with the visual on how we created it container.SetRenderDataCache(cache); // background rectangle System.Windows.Shapes.Rectangle rect = new System.Windows.Shapes.Rectangle { Width = labelLayout.Width, Height = labelLayout.Height, RadiusX = labelLayout.Width / 10, RadiusY = labelLayout.Height / 10, Stroke = Brushes.SkyBlue, Fill = fillBrush, StrokeThickness = 1 }; container.Add(rect); // TextBlock with label text TextBlock textBlock = new TextBlock { Text = cache.LabelText, FontFamily = cache.Typeface.FontFamily, FontStretch = cache.Typeface.Stretch, FontStyle = cache.Typeface.Style, FontWeight = cache.Typeface.Weight, Foreground = Brushes.Black, }; textBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); // if edit button is visible align left, otherwise center double textPositionLeft = cache.ButtonVisibility == Visibility.Visible ? HorizontalInset : (labelLayout.Width - textBlock.DesiredSize.Width) / 2; textBlock.SetCanvasArrangeRect(new Rect(textPositionLeft, (labelLayout.Height - textBlock.DesiredSize.Height) / 2, textBlock.DesiredSize.Width, textBlock.DesiredSize.Height )); container.Add(textBlock); //////////////////////////////////////////////////// //////////////// New in this sample //////////////// //////////////////////////////////////////////////// if (cache.ButtonVisibility == Visibility.Visible) { // get style for edit button from XAML resources // create edit button Button editLabelButton = new Button { Style = editButtonStyle }; editLabelButton.SetCanvasArrangeRect(new Rect(labelLayout.Width - HorizontalInset - ButtonSize, VerticalInset, ButtonSize, ButtonSize)); // set button command editLabelButton.Command = GraphCommands.EditLabel; editLabelButton.CommandParameter = label; editLabelButton.CommandTarget = context.CanvasControl; container.Add(editLabelButton); } //////////////////////////////////////////////////// }
/// <summary> /// Draws the edge-like connectors from a node to its labels /// </summary> private void RenderLabelEdges(IRenderContext context, INode node, VisualGroup container, RenderDataCache cache) { if (node.Labels.Count > 0) { // Create a SimpleEdge which will be used as a dummy for the rendering SimpleEdge simpleEdge = new SimpleEdge(null, null); // Assign the style simpleEdge.Style = new PolylineEdgeStyle(); // Create a SimpleNode which provides the sourceport for the edge but won't be drawn itself SimpleNode sourceDummyNode = new SimpleNode { Layout = new RectD(0, 0, node.Layout.Width, node.Layout.Height), Style = node.Style }; // Set sourceport to the port of the node using a dummy node that is located at the origin. simpleEdge.SourcePort = new SimplePort(sourceDummyNode, FreeNodePortLocationModel.NodeCenterAnchored); // Create a SimpleNode which provides the targetport for the edge but won't be drawn itself SimpleNode targetDummyNode = new SimpleNode(); // Create port on targetDummynode for the label target targetDummyNode.Ports = new ListEnumerable <IPort>(new[] { new SimplePort(targetDummyNode, FreeNodePortLocationModel.NodeCenterAnchored) }); simpleEdge.TargetPort = new SimplePort(targetDummyNode, FreeNodePortLocationModel.NodeCenterAnchored); // Render one edge for each label foreach (PointD labelLocation in cache.LabelLocations) { // move the dummy node to the location of the label targetDummyNode.Layout = new MutableRectangle(labelLocation, SizeD.Zero); // now create the visual using the style interface: IEdgeStyleRenderer renderer = simpleEdge.Style.Renderer; IVisualCreator creator = renderer.GetVisualCreator(simpleEdge, simpleEdge.Style); Visual element = creator.CreateVisual(context); if (element != null) { container.Add(element); } } } }
protected override VisualGroup UpdateVisual(IRenderContext context, VisualGroup oldVisual, IStripe stripe) { var layout = stripe.Layout.ToRectD(); Thickness stripeInsets; //Check if values have changed - then update everything StripeDescriptor descriptor; if (stripe is IColumn) { var col = (IColumn)stripe; stripeInsets = new Thickness(0, col.GetActualInsets().Top, 0, col.GetActualInsets().Bottom); } else { var row = (IRow)stripe; stripeInsets = new Thickness(row.GetActualInsets().Left, 0, row.GetActualInsets().Right, 0); } Thickness actualBorderThickness; if (stripe.GetChildStripes().Any()) { descriptor = ParentDescriptor; actualBorderThickness = descriptor.BorderThickness; } else { int index; if (stripe is IColumn) { var col = (IColumn)stripe; var leafs = col.Table.RootColumn.GetLeaves().ToList(); index = leafs.FindIndex((curr) => col == curr); descriptor = index % 2 == 0 ? EvenLeafDescriptor : OddLeafDescriptor; actualBorderThickness = descriptor.BorderThickness; } else { var row = (IRow)stripe; var leafs = row.Table.RootRow.GetLeaves().ToList(); index = leafs.FindIndex((curr) => row == curr); descriptor = index % 2 == 0 ? EvenLeafDescriptor : OddLeafDescriptor; actualBorderThickness = descriptor.BorderThickness; } } // get the data with which the oldvisual was created var oldCache = oldVisual.GetRenderDataCache <RenderDataCache>(); // get the data for the new visual RenderDataCache newCache = CreateRenderDataCache(context, descriptor, stripe, stripeInsets); // check if something changed except for the location of the node if (!newCache.Equals(oldCache)) { // something changed - just re-render the visual return(CreateVisual(context, stripe)); } Border borderVisual = (Border)oldVisual.Children[0]; borderVisual.Width = layout.Width; borderVisual.Height = layout.Height; borderVisual.BorderThickness = stripeInsets; Border stripeVisual = (Border)oldVisual.Children[1]; stripeVisual.Width = layout.Width; stripeVisual.Height = layout.Height; stripeVisual.BorderThickness = actualBorderThickness; oldVisual.SetCanvasArrangeRect(layout.ToRectD()); return(oldVisual); }
/// <summary> /// Check if this instance is equals to another <see cref="RenderDataCache"/> object /// </summary> public bool Equals(RenderDataCache other) { return(other.Selected == Selected); }
/// <summary> /// Update the visual previously created by <see cref="CreateVisual"/>. /// </summary> /// <remarks> /// Implementation of LabelStyleBase.UpdateVisual. /// </remarks> /// <param name="context">The render context.</param> /// <param name="oldVisual">The visual that has been created in the call to <see cref="CreateVisual"/>.</param> /// <param name="label">The label to which this style instance is assigned.</param> /// <returns>The visual as required by the <see cref="IVisualCreator.CreateVisual"/> interface.</returns> /// <seealso cref="CreateVisual"/> protected override VisualGroup UpdateVisual(IRenderContext context, VisualGroup oldVisual, ILabel label) { // get the data with which the old visual was created RenderDataCache oldCache = oldVisual.GetRenderDataCache <RenderDataCache>(); // get the data for the new visual RenderDataCache newCache = CreateRenderDataCache(context, label); oldVisual.SetRenderDataCache(newCache); // create a new visual if the cache has been changed or the container's contents seem to be wrong bool cacheChanged = !newCache.Equals(oldCache); if (cacheChanged) { return(CreateVisual(context, label)); } if (oldVisual == null || oldVisual.Children.Count != (newCache.Selected?2:1)) { return(CreateVisual(context, label)); } var visual = oldVisual.Children[0]; if (visual == null) { return(CreateVisual(context, label)); } // Updates the dummy label which is internally used for rendering with the properties of the given label. UpdateDummyLabel(context, label); // create a new IRenderContext with a zoom of 1 var cc = new ContextConfigurator(context.CanvasControl.ContentRect); var innerContext = cc.CreateRenderContext(context.CanvasControl); // ReSharper disable once PossibleUnintendedReferenceComparison if (oldVisual.Transform != context.IntermediateTransform) { oldVisual.Transform = context.IntermediateTransform; } // update the visual created by the inner style renderer var creator = InnerLabelStyle.Renderer.GetVisualCreator(dummyLabel, InnerLabelStyle); var updatedVisual = creator.UpdateVisual(innerContext, visual); if (updatedVisual == null) { // nothing to display -> return nothing return(null); } // ReSharper disable once PossibleUnintendedReferenceComparison if (updatedVisual != visual) { oldVisual.Remove(visual); oldVisual.Add(updatedVisual); } // if selected: update the selection visual, too. if (newCache.Selected) { var oldSelectionVisual = oldVisual.Children[1]; Visual selectionVisual = UpdateSelectionVisual(innerContext, oldSelectionVisual, dummyLabel.GetLayout()); // ReSharper disable once PossibleUnintendedReferenceComparison if (oldSelectionVisual != selectionVisual) { oldVisual.Children.Remove(oldSelectionVisual); oldVisual.Children.Add(selectionVisual); } } return(oldVisual); }
/// <summary> /// Check if this instance is equal to another RenderDataCache object /// </summary> public bool Equals(RenderDataCache other) { return(other.LabelText.Equals(LabelText) && other.ButtonVisibility == ButtonVisibility && other.Typeface.Equals(Typeface)); }
/// <summary> /// Creates the visual appearance of a label /// </summary> private void Render(IRenderContext context, ILabel label, VisualGroup container, IOrientedRectangle labelLayout, RenderDataCache cache) { // store information with the visual on how we created it container.SetRenderDataCache(cache); // background rectangle System.Windows.Shapes.Rectangle rect = new System.Windows.Shapes.Rectangle { Width = labelLayout.Width, Height = labelLayout.Height, RadiusX = labelLayout.Width / 10, RadiusY = labelLayout.Height / 10, Stroke = Brushes.SkyBlue, Fill = fillBrush, StrokeThickness = 1 }; container.Add(rect); // TextBlock with label text TextBlock textBlock = new TextBlock { Text = cache.LabelText, FontFamily = cache.Typeface.FontFamily, FontStretch = cache.Typeface.Stretch, FontStyle = cache.Typeface.Style, FontWeight = cache.Typeface.Weight, Foreground = Brushes.Black, }; textBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); // text is left aligned double textPositionLeft = HorizontalInset; textBlock.SetCanvasArrangeRect(new Rect(textPositionLeft, (labelLayout.Height - textBlock.DesiredSize.Height) / 2, textBlock.DesiredSize.Width, textBlock.DesiredSize.Height )); container.Add(textBlock); //////////////////////////////////////////////////// //////////////// New in this sample //////////////// //////////////////////////////////////////////////// // create edit button Button editLabelButton = new Button { Style = editButtonStyle }; editLabelButton.SetCanvasArrangeRect(new Rect(labelLayout.Width - HorizontalInset - ButtonSize, VerticalInset, ButtonSize, ButtonSize)); // let the button edit the label editLabelButton.Click += (sender, args) => ((GraphEditorInputMode)context.CanvasControl.InputMode).EditLabel(label); container.Add(editLabelButton); //////////////////////////////////////////////////// }
public bool Equals(RenderDataCache other) { return(other.Descriptor == Descriptor && other.Insets == Insets && other.Stripe == Stripe); }
/// <summary> /// Check if this instance is equal to another RenderDataCache object /// </summary> public bool Equals(RenderDataCache other) { return(other.LabelText.Equals(LabelText) && other.Typeface.Equals(Typeface)); }
/// <summary> /// Actually creates the visual appearance of a node given the values provided by <see cref="RenderDataCache"/>. /// </summary> /// <remarks> /// This renders the node and the edges to the labels and adds the visuals to the <paramref name="container"/>. /// All items are arranged as if the node was located at (0,0). <see cref="CreateVisual"/> and <see cref="UpdateVisual"/> /// finally arrange the container so that the drawing is translated into the final position. /// </remarks> private void Render(IRenderContext context, INode node, VisualGroup container, RenderDataCache cache) { // store information with the visual on how we created it container.SetRenderDataCache(cache); // draw the drop shadow DrawShadow(container, cache.Size); // draw edges to node labels RenderLabelEdges(context, node, container, cache); // determine the color to use for the rendering Color color = GetNodeColor(node); // the size of node SizeD nodeSize = cache.Size; Ellipse shape = new Ellipse { Width = nodeSize.Width, Height = nodeSize.Height }; // max and min needed for reflection effect calculation double max = Math.Max(nodeSize.Width, nodeSize.Height); double min = Math.Min(nodeSize.Width, nodeSize.Height); // Create Background gradient from specified background color shape.Fill = new LinearGradientBrush() { GradientStops = { new GradientStop { Color = Color.FromArgb((byte)Math.Max(0, color.A - 50), (byte)Math.Min(255, color.R * 1.7), (byte)Math.Min(255, color.G * 1.7), (byte)Math.Min(255, color.B * 1.7)), Offset = 1 }, new GradientStop { Color = color, Offset = 0.5 }, new GradientStop { Color = Color.FromArgb((byte)Math.Max(0, color.A - 50), (byte)Math.Min(255, color.R * 1.4), (byte)Math.Min(255, color.G * 1.4), (byte)Math.Min(255, color.B * 1.4)), Offset = 0 } }, StartPoint = new Point(0, 0), EndPoint = new Point(0.5 / (nodeSize.Width / max), 1 / (nodeSize.Height / max)), SpreadMethod = GradientSpreadMethod.Pad }; // Create light reflection effects Ellipse reflection1 = new Ellipse { Width = min / 10, Height = min / 10, Fill = Brushes.White }; Ellipse reflection2 = new Ellipse { Width = min / 7, Height = min / 7, Fill = Brushes.AliceBlue }; PathGeometry reflection3 = new PathGeometry(); PathFigure figure = new PathFigure(); Point startPoint = new Point(nodeSize.Width / 2.5, nodeSize.Height / 10 * 9); Point endPoint = new Point(nodeSize.Width / 10 * 9, nodeSize.Height / 2.5); Point ctrlPoint1 = new Point(startPoint.X + (endPoint.X - startPoint.X) / 2, nodeSize.Height); Point ctrlPoint2 = new Point(nodeSize.Width, startPoint.Y + (endPoint.Y - startPoint.Y) / 2); Point ctrlPoint3 = new Point(ctrlPoint1.X, ctrlPoint1.Y - nodeSize.Height / 10); Point ctrlPoint4 = new Point(ctrlPoint2.X - nodeSize.Width / 10, ctrlPoint2.Y); figure.StartPoint = startPoint; reflection3.Figures.Add(figure); figure.Segments.Add(new BezierSegment { Point1 = ctrlPoint1, Point2 = ctrlPoint2, Point3 = endPoint }); figure.Segments.Add(new BezierSegment { Point1 = ctrlPoint4, Point2 = ctrlPoint3, Point3 = startPoint }); figure.IsFilled = true; Path p = new Path(); p.Data = reflection3; p.Fill = Brushes.AliceBlue; figure.Freeze(); // place the reflections reflection1.SetCanvasArrangeRect(new Rect(nodeSize.Width / 5, nodeSize.Height / 5, min / 10, min / 10)); reflection2.SetCanvasArrangeRect(new Rect(nodeSize.Width / 4.9, nodeSize.Height / 4.9, min / 7, min / 7)); // and add all to the container for the node container.Children.Add(shape); container.Children.Add(reflection2); container.Children.Add(reflection1); container.Children.Add(p); }
/// <summary> /// Creates the visual appearance of a label /// </summary> private void Render(IRenderContext context, ILabel label, VisualGroup container, IOrientedRectangle labelLayout, RenderDataCache cache) { // store information with the visual on how we created it container.SetRenderDataCache(cache); // background rectangle System.Windows.Shapes.Rectangle rect = new System.Windows.Shapes.Rectangle { Width = labelLayout.Width, Height = labelLayout.Height, RadiusX = labelLayout.Width / 10, RadiusY = labelLayout.Height / 10, Stroke = Brushes.SkyBlue, Fill = fillBrush, StrokeThickness = 1 }; container.Add(rect); // TextBlock with label text TextBlock textBlock = new TextBlock { Text = cache.LabelText, FontFamily = cache.Typeface.FontFamily, FontStretch = cache.Typeface.Stretch, FontStyle = cache.Typeface.Style, FontWeight = cache.Typeface.Weight, Foreground = Brushes.Black, }; textBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); double textPositionLeft = (labelLayout.Width - textBlock.DesiredSize.Width) / 2; textBlock.SetCanvasArrangeRect(new Rect(textPositionLeft, (labelLayout.Height - textBlock.DesiredSize.Height) / 2, textBlock.DesiredSize.Width, textBlock.DesiredSize.Height )); container.Add(textBlock); }
public bool Equals(RenderDataCache other) { return(other.Color == Color && other.Size.Equals(Size) && ListsAreEqual(LabelLocations, other.LabelLocations)); }
public bool Equals(RenderDataCache other) { return(ListsAreEqual(LabelLocations, other.LabelLocations)); }