/// <summary> /// Creates a <see cref="GeneralPath"/> that describes the face on the top of the block. /// </summary> /// <param name="corners">The coordinates of the corners of the block.</param> /// <returns>A <see cref="GeneralPath"/> that describes the face on the top of the block.</returns> static GeneralPath GetTopFacePath(double[] corners) { var path = new GeneralPath(); path.MoveTo( corners[UpTopLeftX], corners[UpTopLeftY] ); path.LineTo( corners[UpTopRightX], corners[UpTopRightY] ); path.LineTo( corners[UpBottomRightX], corners[UpBottomRightY] ); path.LineTo( corners[UpBottomLeftX], corners[UpBottomLeftY] ); path.Close(); return(path); }
public override IVisual CreateVisual(IRenderContext context) { var bounds = Bounds; var width = bounds.Width; var height = bounds.Height; var path = new GeneralPath(); path.MoveTo(0, TopLeftRadius); path.QuadTo(0, 0, TopLeftRadius, 0); path.LineTo(width - TopRightRadius, 0); path.QuadTo(width, 0, width, TopRightRadius); path.LineTo(width, height - BottomRightRadius); path.QuadTo(width, height, width - BottomRightRadius, height); path.LineTo(BottomLeftRadius, height); path.QuadTo(0, height, 0, height - BottomRightRadius); path.Close(); return(new GeneralPathVisual(path) { Brush = Brush, Pen = Pen, Transform = new Matrix(1, 0, 0, 1, (float)Bounds.X, (float)Bounds.Y) }); }
protected override GeneralPath GetOutline(INode node) { double width = Math.Min(node.Layout.Width, node.Layout.Height / BpmnConstants.ConversationWidthHeightRatio); double height = width * BpmnConstants.ConversationWidthHeightRatio; RectD bounds = new RectD(node.Layout.GetCenter().X - width / 2, node.Layout.GetCenter().Y - height / 2, width, height); var path = new GeneralPath(); path.MoveTo(0, 0.5); path.LineTo(0.25, 0); path.LineTo(0.75, 0); path.LineTo(1, 0.5); path.LineTo(0.75, 1); path.LineTo(0.25, 1); path.Close(); var transform = new Matrix2D(); transform.Translate(bounds.GetTopLeft()); transform.Scale(bounds.Width, bounds.Height); path.Transform(transform); return(path); }
/// <summary> /// Generates a path for the callout decoration, which is an isosceles triangle from the label's center pointing /// to the node. /// </summary> /// <param name="label">The label for which to create the path.</param> /// <returns>A path for the callout triangle.</returns> private static GeneralPath GenerateTrianglePath(ILabel label) { var node = (INode)label.Owner; var layout = label.GetLayout(); // Find the point where the triangle attaches to the outline shape var outlineShape = node.Style.Renderer.GetShapeGeometry(node, node.Style).GetOutline(); var nodeCenter = node.Layout.GetCenter(); var labelCenter = layout.GetCenter(); if (outlineShape == null) { outlineShape = new GeneralPath(4); outlineShape.AppendOrientedRectangle(layout, false); } var intersection = outlineShape.FindLineIntersection(nodeCenter, labelCenter); var intersectionPoint = nodeCenter + intersection * (labelCenter - nodeCenter); // Find the vector that is orthogonal to the line connecting the label and node centers var triangleVector = labelCenter - intersectionPoint; var orthoVector = OrthoNormal(triangleVector); // Construct the other points of the triangle var point2 = labelCenter + orthoVector * 20; var point3 = labelCenter - orthoVector * 20; // Create the path var p = new GeneralPath(); p.MoveTo(intersectionPoint); p.LineTo(point2); p.LineTo(point3); p.Close(); return(p); }
protected override VisualGroup CreateVisual(IRenderContext context, ILabel label) { var group = new VisualGroup(); bool enabled = false; if (Button != null) { enabled = Button.CanExecute((INode)label.Owner, context.CanvasControl); } var labelLayout = label.GetLayout(); var layout = new RectD(labelLayout.AnchorX, labelLayout.AnchorY - label.PreferredSize.Height, label.PreferredSize.Width, label.PreferredSize.Height); Brush backgroundBrush; Brush foregroundBrush; Pen foregroundPen; if (enabled) { // enabled style if (Icon != ButtonIcon.Increase) { backgroundBrush = new LinearGradientBrush(layout.TopLeft, layout.BottomLeft, BackgroundColor, Mix(Color.White, BackgroundColor, 0.5d)); } else { backgroundBrush = new LinearGradientBrush(layout.TopLeft, layout.BottomLeft, Mix(Color.White, BackgroundColor, 0.5d), BackgroundColor); } foregroundPen = new Pen(ForegroundColor); foregroundBrush = new SolidBrush(ForegroundColor); } else { // disabled style backgroundBrush = new LinearGradientBrush(layout.TopLeft, layout.BottomLeft, Mix(Color.White, BackgroundColor, 0.7), Mix(Color.White, BackgroundColor, 0.7)); foregroundPen = new Pen(Mix(Color.White, ForegroundColor, 0.7)); foregroundBrush = new SolidBrush(Mix(Color.White, ForegroundColor, 0.7)); } var backgroundRect = new RectangleVisual(layout) { Brush = backgroundBrush, Pen = BorderPen }; group.Add(backgroundRect); GeneralPath path; ShapeVisual pathPaintable; switch (Icon) { case ButtonIcon.Increase: // paint "up"-arrow path = new GeneralPath(); path.MoveTo(layout.TopLeft + new PointD(layout.Width * 0.3, layout.Height * 0.7)); path.LineTo(layout.TopLeft + new PointD(layout.Width * 0.7, layout.Height * 0.7)); path.LineTo(layout.TopLeft + new PointD(layout.Width * 0.5, layout.Height * 0.3)); path.Close(); pathPaintable = new GeneralPathVisual(path) { Brush = foregroundBrush }; group.Add(pathPaintable); break; case ButtonIcon.Decrease: // paint "down"-arrow path = new GeneralPath(); path.MoveTo(layout.TopLeft + new PointD(layout.Width * 0.3, layout.Height * 0.3)); path.LineTo(layout.TopLeft + new PointD(layout.Width * 0.7, layout.Height * 0.3)); path.LineTo(layout.TopLeft + new PointD(layout.Width * 0.5, layout.Height * 0.7)); path.Close(); pathPaintable = new GeneralPathVisual(path) { Brush = foregroundBrush }; group.Add(pathPaintable); break; case ButtonIcon.Toggle: // paint "check" path = new GeneralPath(); path.MoveTo(layout.TopLeft + new PointD(layout.Width * 0.3, layout.Height * 0.5)); path.LineTo(layout.TopLeft + new PointD(layout.Width * 0.5, layout.Height * 0.7)); path.LineTo(layout.TopLeft + new PointD(layout.Width * 0.7, layout.Height * 0.3));; pathPaintable = new GeneralPathVisual(path) { Pen = foregroundPen }; group.Add(pathPaintable); break; case ButtonIcon.None: // paint nothing break; default: // can't happen throw new ArgumentOutOfRangeException(); } return(group); }
protected override VisualGroup CreateVisual(IRenderContext context, INode node) { Color borderColor, backgroundColor1, backgroundColor2; if (((GraphControl)context.CanvasControl).CurrentItem == node) { borderColor = Color.Orange; backgroundColor1 = Color.White; backgroundColor2 = Color.Orange; } else { borderColor = Color.FromArgb(255, 24, 154, 231); backgroundColor1 = Color.FromArgb(255, 204, 255, 255); backgroundColor2 = Color.FromArgb(255, 24, 154, 231); } var layout = node.Layout; var employee = (Employee)node.Tag; var text = new TextVisual { Text = GetShortName(employee.Name), Font = new Font("Arial", 37, FontStyle.Regular, GraphicsUnit.Pixel), Brush = Brushes.Black, Location = new PointD(5, 5) }; double locationX = layout.Width / 2 - text.GetBounds(context).Width / 2; double locationY = layout.Height / 2 - text.GetBounds(context).Height / 2; string s1 = GetShortName(employee.Name); Font font1 = new Font("Arial", 37, FontStyle.Regular, GraphicsUnit.Pixel); Brush brush1 = Brushes.Black; IPoint location1 = new PointD(locationX, locationY); text = new TextVisual { Text = s1, Font = font1, Brush = brush1, Location = location1 }; var ribbonColor = Color.Green; if (employee.Status == EmployeeStatus.Travel) { ribbonColor = Color.Purple; } if (employee.Status == EmployeeStatus.Unavailable) { ribbonColor = Color.Red; } var border = new RectangleVisual(0, 0, layout.Width, layout.Height) { Pen = new Pen(borderColor) }; var background = new RectangleVisual(0, 0, layout.Width, layout.Height) { Brush = new LinearGradientBrush(new PointF(0, 0), new PointF((float)layout.Width, (float)layout.Height), backgroundColor1, backgroundColor2) }; var ribbonPath = new GeneralPath(); ribbonPath.MoveTo(0, 20); ribbonPath.LineTo(25, 0); ribbonPath.LineTo(40, 0); ribbonPath.LineTo(0, 35); ribbonPath.Close(); var ribbon = new GeneralPathVisual(ribbonPath) { Brush = new SolidBrush(ribbonColor) }; // Set a transform on the group, matching the node's location. // That way only the transform has to be updated instead of every single child visual. var transform = new Matrix(); transform.Translate((float)layout.X, (float)layout.Y); var group = new VisualGroup { Transform = transform, Children = { border, background, text, ribbon } }; return(group); }
/// <summary> /// Creates a visual representation of the constraint indicator. /// </summary> public GeneralPath CreateConstraintIndicator() { IPort port = sourceEnd ? bend.Owner.SourcePort : bend.Owner.TargetPort; var nodeLayout = ((INode)port.Owner).Layout.ToRectD(); PointD portLocation = nodeLayout.Center; double plX = portLocation.X, plY = portLocation.Y; PointD bendLocation = bend.Location.ToPointD(); PointD delta = bendLocation - portLocation; if (delta.VectorLength > MinDistance && !nodeLayout.Contains(bendLocation)) { PointD direction = delta.Normalized; GeneralPath path = new GeneralPath(20); path.MoveTo(-15, 0); path.LineTo(-5, 10); path.LineTo(-2, 7); path.LineTo(-5, 4); path.LineTo(8, 4); path.LineTo(8, -4); path.LineTo(-5, -4); path.LineTo(-2, -7); path.LineTo(-5, -10); path.Close(); // mirror at target end if (!sourceEnd) { path.Transform(new Matrix2D(-1, 0, 0, 1, 0, 0)); } // rotate and translate arrow const int ArrowOffset = 11; if (direction.IsHorizontalVector) { plY = nodeLayout.CenterY; if (direction.X > 0) { plX = nodeLayout.MaxX + ArrowOffset; path.Transform(new Matrix2D(-1, 0, 0, 1, plX, plY)); } else { plX = nodeLayout.X - ArrowOffset; path.Transform(new Matrix2D(1, 0, 0, 1, plX, plY)); } } else { plX = nodeLayout.CenterX; if (direction.Y < 0) { plY = nodeLayout.Y - ArrowOffset; path.Transform(new Matrix2D(0, 1, 1, 0, plX, plY)); } else { plY = nodeLayout.MaxY + ArrowOffset; path.Transform(new Matrix2D(0, 1, -1, 0, plX, plY)); } } return(path); } return(null); }
//////////////////////////////////////////////////// #region Visual /// <summary> /// Creates an <see cref="IVisual"/> which renders the label. /// </summary> /// <remarks> /// Adds separate visuals for background and text in a VisualGroup. /// Delegates to method <see cref="LabelStyleBase{TVisual}.GetTransform"/> /// to get a valid transform for the label. /// </remarks> /// <param name="context">The Render Context.</param> /// <param name="label">The label to render.</param> /// <returns>A visual which renders the label.</returns> protected override VisualGroup CreateVisual(IRenderContext context, ILabel label) { var layout = label.GetLayout(); // don't render invisible labels if (layout.Width < 0 || layout.Height < 0) { return(null); } var group = new VisualGroup(); // convert to convenient coordinate space group.Transform = GetTransform(context, layout, true); // Draw the label background as a rounded rectangle GeneralPath gp = new GeneralPath(10); double xRad = layout.Width / 4; double yRad = layout.Height / 10; gp.MoveTo(0, yRad); gp.QuadTo(0, 0, xRad, 0); gp.LineTo(layout.Width - xRad, 0); gp.QuadTo(layout.Width, 0, layout.Width, yRad); gp.LineTo(layout.Width, layout.Height - yRad); gp.QuadTo(layout.Width, layout.Height, layout.Width - xRad, layout.Height); gp.LineTo(xRad, layout.Height); gp.QuadTo(0, layout.Height, 0, layout.Height - yRad); gp.Close(); var pathVisual = new GeneralPathVisual(gp) { Brush = new SolidBrush(Color.FromArgb(255, 155, 226, 255)), Pen = Pens.SkyBlue }; group.Add(pathVisual); //////////////////////////////////////////////////// //////////////// New in this sample //////////////// //////////////////////////////////////////////////// // Draw the label's text if (context.Zoom >= buttonZoomThreshold) { // draw the action button group.Add(new ImageVisual { Image = Resources.edit_label, Rectangle = new RectD(layout.Width - (inset + buttonWidth), inset, buttonWidth, layout.Height - inset * 2) }); group.Add(new TextVisual { Text = label.Text, Font = Font, Brush = Brushes.Black, Location = PointD.Origin }); } else { group.Add(new TextVisual { Text = label.Text, Font = Font, Brush = Brushes.Black, Location = new PointD((buttonWidth + 2 * inset) * 0.5, 0) }); } //////////////////////////////////////////////////// return(group); }