/// <summary> /// Compares two nodes and returns a value indicating whether the first node's /// distance to the point is less than, equal to or greater than the second /// node's distance to the specified point. /// </summary> /// <param name="o1">The first node to compare.</param> /// <param name="o2">The second node to compare.</param> /// <returns> /// Less than 0, if o1's distance to the point is less than o2's distance to the /// point; 0 if o1's distance to the point equals 02's distance to the point; /// greater than 0 if o1's distance to the point is greater than o2's distance to /// the point. /// </returns> public int Compare(object o1, object o2) { PNode each1 = (PNode)o1; PNode each2 = (PNode)o2; PointF each1Center = PUtil.CenterOfRectangle(each1.GlobalFullBounds); PointF each2Center = PUtil.CenterOfRectangle(each2.GlobalFullBounds); if (!NODE_TO_GLOBAL_NODE_CENTER_MAPPING.Contains(each1)) { NODE_TO_GLOBAL_NODE_CENTER_MAPPING.Add(each1, each1Center); } if (!NODE_TO_GLOBAL_NODE_CENTER_MAPPING.Contains(each2)) { NODE_TO_GLOBAL_NODE_CENTER_MAPPING.Add(each2, each2Center); } float distance1 = PUtil.DistanceBetweenPoints(point, each1Center); float distance2 = PUtil.DistanceBetweenPoints(point, each2Center); if (distance1 < distance2) { return(-1); } else if (distance1 == distance2) { return(0); } else { return(1); } }
/// <summary> /// Force this handle to relocate itself using its locator. /// </summary> public virtual void RelocateHandle() { if (locator != null) { RectangleFx b = Bounds; PointFx aPoint = locator.LocatePoint; if (locator is PNodeLocator) { PNode located = ((PNodeLocator)locator).Node; PNode parent = Parent; aPoint = located.LocalToGlobal(aPoint); aPoint = GlobalToLocal(aPoint); if (parent != located && parent is PCamera) { aPoint = ((PCamera)parent).ViewToLocal(aPoint); } } float newCenterX = aPoint.X; float newCenterY = aPoint.Y; PointFx bCenter = PUtil.CenterOfRectangle(b); if (newCenterX != bCenter.X || newCenterY != bCenter.Y) { CenterBoundsOnPoint(newCenterX, newCenterY); } } }
/// <summary> /// Animates the camera's view to keep the focus node on the screen and at 100 /// percent scale with minimal view movement. /// </summary> /// <param name="aCamera">The camera whose view will be animated.</param> /// <param name="aFocusNode">The focus node to animate to.</param> /// <param name="duration">The length of the animation.</param> /// <returns> /// The activity that animates the camera's view to the focus node. /// </returns> public virtual PActivity DirectCameraViewToFocus(PCamera aCamera, PNode aFocusNode, int duration) { PMatrix originalViewMatrix = aCamera.ViewMatrix; // Scale the canvas to include SizeF s = new SizeF(1, 0); s = focusNode.GlobalToLocal(s); float scaleFactor = s.Width / aCamera.ViewScale; PointF scalePoint = PUtil.CenterOfRectangle(focusNode.GlobalFullBounds); if (scaleFactor != 1) { aCamera.ScaleViewBy(scaleFactor, scalePoint.X, scalePoint.Y); } // Pan the canvas to include the view bounds with minimal canvas // movement. aCamera.AnimateViewToPanToBounds(focusNode.GlobalFullBounds, 0); // Get rid of any white space. The canvas may be panned and // zoomed in to do this. But make sure not stay constrained by max // magnification. //FillViewWhiteSpace(aCamera); PMatrix resultingMatrix = aCamera.ViewMatrix; aCamera.ViewMatrix = originalViewMatrix; // Animate the canvas so that it ends up with the given // view transform. return(AnimateCameraViewMatrixTo(aCamera, resultingMatrix, duration)); }
/// <summary> /// Applies a previously set constraint to the camera's view matrix. /// </summary> public virtual void ApplyViewConstraints() { if (viewConstraint == CameraViewConstraint.None) { return; } RectangleF layerBounds = GlobalToLocal(UnionOfLayerFullBounds); SizeF constraintDelta = new SizeF(0, 0); switch (viewConstraint) { case CameraViewConstraint.All: constraintDelta = PUtil.DeltaRequiredToContain(ViewBounds, layerBounds); break; case CameraViewConstraint.Center: layerBounds.Location = PUtil.CenterOfRectangle(layerBounds); layerBounds.Width = 0; layerBounds.Height = 0; constraintDelta = PUtil.DeltaRequiredToContain(ViewBounds, layerBounds); break; } viewMatrix.TranslateBy(-constraintDelta.Width, -constraintDelta.Height); }
/// <summary> /// Gets the nearest neighbor in the specified direction. /// </summary> /// <param name="aDirection"> /// The direction in which to find the nearest neighbor. /// </param> /// <returns>The nearest neighbor in the specified direction.</returns> public virtual PNode GetNeighborInDirection(Direction aDirection) { if (focusNode == null) { return(null); } NODE_TO_GLOBAL_NODE_CENTER_MAPPING.Clear(); PointF highlightCenter = PUtil.CenterOfRectangle(focusNode.GlobalFullBounds); NODE_TO_GLOBAL_NODE_CENTER_MAPPING.Add(focusNode, highlightCenter); PNodeList l = GetNeighbors(); SortNodesByDistanceFromPoint(l, highlightCenter); foreach (PNode each in l) { if (NodeIsNeighborInDirection(each, aDirection)) { return(each); } } return(null); }
/// <summary> /// Applies a previously set constraint to the camera's view matrix. /// </summary> public virtual void ApplyViewConstraints() { if (viewConstraint == CameraViewConstraint.None) { return; } RectangleFx layerBounds = GlobalToLocal(UnionOfLayerFullBounds); SizeFx constraintDelta = new SizeFx(0, 0); switch (viewConstraint) { case CameraViewConstraint.All: constraintDelta = PUtil.DeltaRequiredToContain(ViewBounds, layerBounds); break; case CameraViewConstraint.Center: PointFx layerLocation = PUtil.CenterOfRectangle(layerBounds); //layerBounds.Width = 0; //layerBounds.Height = 0; layerBounds = new RectangleFx(layerLocation.X, layerLocation.Y, 0, 0); constraintDelta = PUtil.DeltaRequiredToContain(ViewBounds, layerBounds); break; } this.viewMatrix = MatrixExtensions.TranslateBy(viewMatrix, -constraintDelta.Width, -constraintDelta.Height); }
public void UpdateLink() { PointFx p1 = PUtil.CenterOfRectangle(node1.FullBounds); PointFx p2 = PUtil.CenterOfRectangle(node2.FullBounds); link.Reset(); link.AddLine(p1.X, p1.Y, p2.X, p2.Y); }
public override void OnMouseUp(object sender, PInputEventArgs e) { newP = PUtil.CenterOfRectangle(target.Camera.ViewBounds); colBarLayer.TranslateBy(0, (oldP.Y - newP.Y) / target.Layer.Scale); rowBarLayer.TranslateBy((oldP.X - newP.X) / target.Layer.Scale, 0); }
//! Создает линии - связи между узлами на графе диалогов public static void updateEdge(PPath edge) { // Note that the node's "FullBounds" must be used (instead of just the "Bound") // because the nodes have non-identity transforms which must be included when // determining their position. ArrayList nodes = (ArrayList)edge.Tag; PNode node1 = (PNode)nodes[0]; PNode node2 = (PNode)nodes[1]; PointF start = PUtil.CenterOfRectangle(node1.FullBounds); PointF end = PUtil.CenterOfRectangle(node2.FullBounds); edge.Reset(); edge.AddLine(start.X, start.Y, end.X, end.Y); }
/// <summary> /// Animates the camera's view to keep the control node on the screen and at 100 /// percent scale with minimal view movement. /// </summary> /// <param name="aCamera">The camera whose view will be animated.</param> /// <param name="aControlNode">The control node to animate to.</param> /// <param name="path">The pick path through which the control node was picked.</param> /// <param name="duration">The length of the animation.</param> /// <returns> /// The activity that animates the camera's view to the control node. /// </returns> public virtual PActivity DirectCameraViewToControl(PCamera aCamera, PControl aControlNode, PPickPath path, int duration) { Matrix originalViewMatrix = aCamera.ViewMatrix; // Scale the canvas to include SizeFx s = new SizeFx(1, 0); s = aControlNode.GlobalToLocal(s); float scaleFactor = s.Width / aCamera.ViewScale; PointFx scalePoint = PUtil.CenterOfRectangle(aControlNode.GlobalFullBounds); if (scaleFactor != 1) { aCamera.ScaleViewBy(scaleFactor, scalePoint.X, scalePoint.Y); } // Pan the canvas to include the view bounds with minimal canvas // movement. aCamera.AnimateViewToPanToBounds(aControlNode.GlobalFullBounds, 0); // Get rid of any white space. The canvas may be panned and // zoomed in to do this. But make sure not stay constrained by max // magnification. //FillViewWhiteSpace(aCamera); Matrix resultingMatrix = aCamera.ViewMatrix; aCamera.ViewMatrix = originalViewMatrix; PControl controlNode = (PControl)aControlNode; // Animate the canvas so that it ends up with the given // view transform. PActivity animateCameraViewActivity = AnimateCameraViewMatrixTo(aCamera, resultingMatrix, duration); aCamera.Root.WaitForActivities(); Matrix pathTransform = path.GetPathTransformTo(controlNode); PointFx point = new PointFx(controlNode.X, controlNode.Y); PointFx pf = MatrixExtensions.Transform(pathTransform, point); controlNode.ControlLocation = new System.Drawing.Point((int)pf.X, (int)pf.Y); controlNode.CurrentCanvas = path.TopCamera.Canvas; controlNode.Editing = true; return(animateCameraViewActivity); }
//**************************************************************** // Animation - Methods to animate the camera's view. //**************************************************************** /// <summary> /// Animate the camera's view from its current matrix when the activity starts /// to a new matrix that centers the given bounds in the camera layers' coordinate /// system into the camera's view bounds. /// </summary> /// <param name="centerBounds">The bounds to center the view on.</param> /// <param name="shouldScaleToFit"> /// Indicates whether the camera should scale it's view when necessary to fully fit /// the given bounds within the camera's view bounds. /// </param> /// <param name="duration">The amount of time that the animation should take.</param> /// <returns> /// The newly scheduled activity, if the duration is greater than 0; else null. /// </returns> /// <remarks> /// If the duration is 0 then the view will be transformed immediately, and null will /// be returned. Else a new PTransformActivity will get returned that is set to /// animate the camera’s view matrix to the new bounds. If shouldScaleToFit is true, /// then the camera will also scale its view so that the given bounds fit fully within /// the camera's view bounds, else the camera will maintain its original scale. /// </remarks> public virtual PTransformActivity AnimateViewToCenterBounds(RectangleF centerBounds, bool shouldScaleToFit, long duration) { SizeF delta = PUtil.DeltaRequiredToCenter(ViewBounds, centerBounds); PMatrix newMatrix = ViewMatrix; newMatrix.TranslateBy(delta.Width, delta.Height); if (shouldScaleToFit) { float s = Math.Min(ViewBounds.Width / centerBounds.Width, ViewBounds.Height / centerBounds.Height); PointF c = PUtil.CenterOfRectangle(centerBounds); newMatrix.ScaleBy(s, c.X, c.Y); } return(AnimateViewToMatrix(newMatrix, duration)); }
/// <summary> /// Caches the information necessary to animate from the current view bounds to the /// specified centerBounds /// </summary> /// <param name="centerBounds">The bounds to center the view on.</param> /// <param name="scaleToFit"> /// Indicates whether the camera should scale it's view when necessary to fully fit /// the given bounds within the camera's view bounds. /// </param> /// <returns>The new view matrix to center the specified bounds.</returns> private Matrix CacheViewBounds(RectangleFx centerBounds, bool scaleToFit) { RectangleFx viewBounds = ViewBounds; // Initialize the image to the union of the current and destination bounds RectangleFx imageBounds = viewBounds; imageBounds = RectangleFxtensions.Union(imageBounds, centerBounds); AnimateViewToCenterBounds(imageBounds, scaleToFit, 0); imageAnimateBounds = ViewBounds; // Now create the actual cache image that we will use to animate fast System.Drawing.Image buffer = PaintBuffer; Color fBrush = Color.White; if (Brush != Color.Transparent) { fBrush = Brush; } ToImage(buffer, fBrush); // Do this after the painting above! imageAnimate = true; // Return the bounds to the previous viewbounds AnimateViewToCenterBounds(viewBounds, scaleToFit, 0); // The code below is just copied from animateViewToCenterBounds to create the // correct transform to center the specified bounds SizeFx delta = PUtil.DeltaRequiredToCenter(viewBounds, centerBounds); Matrix newMatrix = ViewMatrix; newMatrix = MatrixExtensions.TranslateBy(newMatrix, delta.Width, delta.Height); if (scaleToFit) { float s = Math.Min(viewBounds.Width / centerBounds.Width, viewBounds.Height / centerBounds.Height); PointFx center = PUtil.CenterOfRectangle(centerBounds); newMatrix = MatrixExtensions.ScaleBy(newMatrix, s, center.X, center.Y); } return(newMatrix); }
//**************************************************************** // Animation - Methods to animate the camera's view. //**************************************************************** /// <summary> /// Animate the camera's view from its current matrix when the activity starts /// to a new matrix that centers the given bounds in the camera layers' coordinate /// system into the camera's view bounds. /// </summary> /// <param name="centerBounds">The bounds to center the view on.</param> /// <param name="shouldScaleToFit"> /// Indicates whether the camera should scale it's view when necessary to fully fit /// the given bounds within the camera's view bounds. /// </param> /// <param name="duration">The amount of time that the animation should take.</param> /// <returns> /// The newly scheduled activity, if the duration is greater than 0; else null. /// </returns> /// <remarks> /// If the duration is 0 then the view will be transformed immediately, and null will /// be returned. Else a new PTransformActivity will get returned that is set to /// animate the camera’s view matrix to the new bounds. If shouldScaleToFit is true, /// then the camera will also scale its view so that the given bounds fit fully within /// the camera's view bounds, else the camera will maintain its original scale. /// </remarks> public virtual PTransformActivity AnimateViewToCenterBounds(RectangleFx centerBounds, bool shouldScaleToFit, long duration) { SizeFx delta = PUtil.DeltaRequiredToCenter(ViewBounds, centerBounds); Matrix newMatrix = ViewMatrix; newMatrix = MatrixExtensions.TranslateBy(newMatrix, delta.Width, delta.Height); if (shouldScaleToFit) { float s = Math.Min(ViewBounds.Width / centerBounds.Width, ViewBounds.Height / centerBounds.Height); if (s != float.PositiveInfinity && s != 0) { PointFx c = PUtil.CenterOfRectangle(centerBounds); MatrixExtensions.ScaleBy(newMatrix, s, c.X, c.Y); } } return(AnimateViewToMatrix(newMatrix, duration)); }
protected void CreatePath(Random rnd) { PTransformActivity rotActivity; // Create a path P3Path path = P3Path.CreateEllipse(0, 0, 100, 100); path.Brush = Brushes.Red; path.AddLine(0, 0, 20, 20); path.AddLine(20, 20, 34, 67); path.AddArc(0, 30, 30, 30, 30, 30); path.Tolerance = .002f; canvas.Layer.AddChild(path); PMatrix rMatrix = new PMatrix(); PointF center = PUtil.CenterOfRectangle(path.Bounds); rMatrix.RotateBy(90, center.X, center.Y); rotActivity = path.AnimateToMatrix(rMatrix, 2000 + (long)(2000 * rnd.NextDouble())); rotActivity.LoopCount = 1000; rotActivity.Mode = ActivityMode.SourceToDestinationToSource; }
public override void OnMouseDown(object sender, PInputEventArgs e) { oldP = PUtil.CenterOfRectangle(target.Camera.ViewBounds); }