protected static new void DrawDecorator(DiagramPaintEventArgs e, IGeometryHost geometryHost, float rotation, PointD centerRight, LinkDecorator decorator) { SizeD size = LinkShapeGeometry.SizeDecorator; #endif double offsetBy = 0d; bool doOffset = false; ILinkDecoratorSettings settings = decorator as ILinkDecoratorSettings; if (settings != null) { size = settings.DecoratorSize; offsetBy = settings.OffsetBy; doOffset = !VGConstants.FuzzZero(offsetBy, VGConstants.FuzzDistance); } Graphics g = e.Graphics; RectangleD boundingRect = new RectangleD(centerRight.X - size.Width, centerRight.Y - (size.Height / 2), size.Width, size.Height); Matrix rotationMatrix = g.Transform; float offsetX = 0f; float offsetY = 0f; if (doOffset) { double rotationRadians = rotation * Math.PI / 180; offsetX = (float)(offsetBy * Math.Cos(rotationRadians)); offsetY = (float)(offsetBy * Math.Sin(rotationRadians)); rotationMatrix.Translate(offsetX, offsetY); } rotationMatrix.RotateAt(rotation, PointD.ToPointF(centerRight)); g.Transform = rotationMatrix; decorator.DoPaintShape(boundingRect, geometryHost, e); rotationMatrix.RotateAt(-rotation, PointD.ToPointF(centerRight)); if (doOffset) { rotationMatrix.Translate(-offsetX, -offsetY); } g.Transform = rotationMatrix; }
/// <summary> /// Maintain center position on resize /// </summary> public override void AutoResize() { SizeD contentSize = ContentSize; if (!contentSize.IsEmpty) { RectangleD oldBounds = (RectangleD)AbsoluteBounds; if (!(oldBounds.IsEmpty || Store.TransactionManager.CurrentTransaction.TopLevelTransaction.Context.ContextInfo.ContainsKey(ORMBaseShape.PlaceAllChildShapes))) { SizeD oldSize = oldBounds.Size; double xDelta = contentSize.Width - oldSize.Width; double yDelta = contentSize.Height - oldSize.Height; bool xChanged = !VGConstants.FuzzZero(xDelta, VGConstants.FuzzDistance); bool yChanged = !VGConstants.FuzzZero(yDelta, VGConstants.FuzzDistance); if (xChanged || yChanged) { PointD location = oldBounds.Location; location.Offset(xChanged ? -xDelta / 2 : 0d, yChanged ? -yDelta / 2 : 0d); AbsoluteBounds = new RectangleD(location, contentSize); return; } } Size = contentSize; } }
/// <summary> /// Replacement for LinkShapeGeometry.CalculateRotationAngle /// </summary> /// <param name="pt1">From point</param> /// <param name="pt2">To point</param> /// <returns>Rotation angle in degrees</returns> public new virtual float CalculateRotationAngle(PointD pt1, PointD pt2) { if (VGConstants.FuzzEqual(pt1.X, pt2.X, VGConstants.FuzzDistance)) { // Vertical line, get angle by comparing y return((pt1.Y > pt2.Y) ? 90f : 270f); } else { double retVal; double xDif = pt2.X - pt1.X; retVal = Math.Atan((pt2.Y - pt1.Y) / xDif); if (xDif > 0d) { retVal += Math.PI; } return((float)(retVal / Math.PI * 180d)); } }
private static void ExcludeDecorator(Graphics g, ObliqueBinaryLinkShapeGeometry geometry, LinkDecorator decorator, PointD fromPoint, PointD toPoint) { SizeD size = LinkShapeGeometry.SizeDecorator; #endif ILinkDecoratorSettings settings = decorator as ILinkDecoratorSettings; double offsetBy = double.NaN; if (settings != null) { size = settings.DecoratorSize; offsetBy = settings.OffsetBy; if (VGConstants.FuzzZero(offsetBy, VGConstants.FuzzDistance)) { offsetBy = double.NaN; } } RectangleD bounds = new RectangleD(fromPoint.X - size.Width, fromPoint.Y - (size.Height / 2), size.Width, size.Height); float rotationAngle = geometry.CalculateRotationAngle(fromPoint, toPoint); ExcludeDecorator(g, bounds, rotationAngle, offsetBy, fromPoint); }
/// <summary> /// Calculcate the distance from a point to a line /// </summary> /// <param name="point">The point to test distance from.</param> /// <param name="lineStart">The starting point for the line</param> /// <param name="lineEnd">The end point for the line</param> /// <param name="enforceSeqment">True to only return a number if the shortest /// distance is within the specified line segment</param> /// <returns>A distance, or NaN if enforceSeqment is true and the point misses</returns> private static double DistanceFromPointToLine(PointD point, PointD lineStart, PointD lineEnd, bool enforceSeqment) { double segmentLength = Magnitude(lineStart, lineEnd); if (VGConstants.FuzzZero(segmentLength, VGConstants.FuzzDistance)) { return(Magnitude(point, lineStart)); } double u = (((point.X - lineStart.X) * (lineEnd.X - lineStart.X)) + ((point.Y - lineStart.Y) * (lineEnd.Y - lineStart.Y))) / (segmentLength * segmentLength); if (enforceSeqment && (u < 0d || u > 1d)) { // closest point does not fall within the line segment return(double.NaN); } // Return the distance from the point to the intersection return(Magnitude(point, new PointD(lineStart.X + u * (lineEnd.X - lineStart.X), lineStart.Y + u * (lineEnd.Y - lineStart.Y)))); }
/// <summary> /// Helper function to keep all relative shapes equidistant from /// a shape when the shape bounds change. /// </summary> /// <param name="e">ElementPropertyChangedEventArgs</param> protected static void MaintainRelativeShapeOffsetsForBoundsChange(ElementPropertyChangedEventArgs e) { Guid attributeId = e.DomainProperty.Id; if (attributeId == ORMBaseShape.AbsoluteBoundsDomainPropertyId) { ORMBaseShape parentShape = e.ModelElement as ORMBaseShape; RectangleD oldBounds = (RectangleD)e.OldValue; if (oldBounds.IsEmpty || oldBounds.Size == parentShape.DefaultSize || e.ModelElement.Store.TransactionManager.CurrentTransaction.TopLevelTransaction.Context.ContextInfo.ContainsKey(ORMBaseShape.PlaceAllChildShapes)) { // Initializing, let normal placement win return; } RectangleD newBounds = (RectangleD)e.NewValue; SizeD oldSize = oldBounds.Size; SizeD newSize = newBounds.Size; double xChange = newSize.Width - oldSize.Width; double yChange = newSize.Height - oldSize.Height; bool checkX = !VGConstants.FuzzZero(xChange, VGConstants.FuzzDistance); bool checkY = !VGConstants.FuzzZero(yChange, VGConstants.FuzzDistance); if (checkX || checkY) { LinkedElementCollection <ShapeElement> childShapes = parentShape.RelativeChildShapes; int childCount = childShapes.Count; if (childCount != 0) { for (int i = 0; i < childCount; ++i) { bool changeBounds = false; PointD change = default(PointD); NodeShape childShape = childShapes[i] as NodeShape; if (childShape != null) { RectangleD childBounds = childShape.AbsoluteBounds; if (checkX) { double newRight = newBounds.Right - xChange; double childLeft = childBounds.Left; if (childLeft > newRight || // Completely to the right (childBounds.Right > newRight && childLeft > newBounds.Left)) // Straddles right edge { change.X = xChange; changeBounds = true; } } if (checkY) { double newBottom = newBounds.Bottom - yChange; double childTop = childBounds.Top; if (childTop > newBottom || // Completely below (childBounds.Bottom > newBottom && childTop > newBounds.Top)) // Straddles bottom edge { change.Y = yChange; changeBounds = true; } } if (changeBounds) { childBounds.Offset(change); childShape.AbsoluteBounds = childBounds; } } } } } } }