/// <summary> /// Converts the given <see cref="OrientedRectangle"/> from the world into the view coordinate space. /// </summary> internal static void WorldToIntermediateCoordinates(ICanvasContext context, OrientedRectangle rect) { var anchor = new PointD(rect.Anchor); var anchorAndUp = anchor + rect.GetUp(); var renderContext = context as IRenderContext ?? context.Lookup(typeof(IRenderContext)) as IRenderContext; if (renderContext != null) { anchor = renderContext.WorldToIntermediateCoordinates(anchor); anchorAndUp = renderContext.WorldToIntermediateCoordinates(anchorAndUp); } else { var cc = context.Lookup(typeof(CanvasControl)) as CanvasControl; if (cc != null) { anchor = cc.WorldToIntermediateCoordinates(anchor); anchorAndUp = cc.WorldToIntermediateCoordinates(anchorAndUp); } else { // too bad - infer trivial scale matrix anchor *= context.Zoom; anchorAndUp *= context.Zoom; } } rect.SetUpVector((anchorAndUp - anchor).Normalized); rect.SetAnchor(anchor); rect.Width *= context.Zoom; rect.Height *= context.Zoom; }
/// <summary> /// Updates the layout in the cache. /// </summary> public void UpdateCache(RectD layout) { if (layout.Equals(cachedLayout) && upVector.Equals(cachedOrientedRect.GetUp())) { return; } cachedLayout = layout; cachedOrientedRect.SetUpVector(upVector.X, upVector.Y); cachedOrientedRect.Width = Width; cachedOrientedRect.Height = Height; cachedOrientedRect.SetCenter(cachedLayout.Center); }
/// <summary> /// Adjusts the node location and size according to the new handle location. /// </summary> public void HandleMove(IInputModeContext inputModeContext, PointD originalLocation, PointD newLocation) { // calculate how much the handle was moved var upNormal = new PointD(-initialLayout.UpY, initialLayout.UpX); var deltaW = GetWidthDelta(originalLocation, newLocation, upNormal); var up = initialLayout.GetUp(); var deltaH = GetHeightDelta(originalLocation, newLocation, up); // add one or two times delta to the width to expand the node right and left dummySize = new SizeD( initialLayout.Width + deltaW * (symmetricResize ? 2 : 1), initialLayout.Height + deltaH * (symmetricResize ? 2 : 1)); // Calculate the new location. // Depending on our handle position, a different corner of the node should stay fixed. if (symmetricResize) { var dx = upNormal.X * deltaW + up.X * deltaH; var dy = upNormal.Y * deltaW + up.Y * deltaH; dummyLocation = initialLayout.GetAnchorLocation() - new PointD(dx, dy); } else { var w = dummySize.Width - initialLayout.Width; var h = dummySize.Height - initialLayout.Height; switch (position) { case HandlePositions.NorthWest: dummyLocation = initialLayout.GetAnchorLocation() - new PointD(-up.Y * w, up.X * w); break; case HandlePositions.South: case HandlePositions.SouthWest: case HandlePositions.West: dummyLocation = initialLayout.GetAnchorLocation() - new PointD(up.X * h - up.Y * w, up.Y * h + up.X * w); break; case HandlePositions.SouthEast: dummyLocation = initialLayout.GetAnchorLocation() - new PointD(up.X * h, up.Y * h); break; // case HandlePositions.North: // case HandlePositions.NorthEast: // case HandlePositions.East: default: dummyLocation = initialLayout.GetAnchorLocation(); break; } } var newLayout = SetNodeLocationAndSize(inputModeContext, dummyLocation, dummySize); var portContext = new DelegatingContext(inputModeContext); foreach (var portHandle in portHandles) { portHandle.HandleMove(portContext, dummyLocation, newLocation); } if (reshapeHandler != null) { // if there is a reshape handler: // ensure proper handling of a parent group node reshapeHandler.HandleReshape(inputModeContext, initialRect, newLayout); } }