public void UnExecute() { StageView stage = MainForm.CurrentStage; InstanceGroup sel = MainForm.CurrentStage.Selection; uint[] ids = sel.SelectedIds; foreach (Bond b in addedBonds) { stage.CurrentEditItem.BondStore.RemoveBond(b); } for (int i = 0; i < ids.Length; i++) { DesignInstance di = MainForm.CurrentInstanceManager[ids[i]]; Vex.Matrix m = di.GetMatrix(); Vex.Point offset = new Vex.Point(-offsets[i].X, -offsets[i].Y); m.Translate(offset); stage.SetDesignInstanceMatrix(di, m); } if (useSmartBonds) { foreach (Bond b in previousBonds) { stage.CurrentEditItem.BondStore.AddBond(b); } } sel.Update(); MainForm.CurrentStage.ResetTransformHandles(); MainForm.CurrentStage.InvalidateTransformedSelection(); }
public static Vex.Point GetTransformedPoint(Vex.Point pt, Vex.Matrix m, bool invert) { PointF[] pts = new PointF[] { pt.SysPointF() }; using (Matrix ms = m.SysMatrix()) { TransformPoints(pts, ms, invert); } return(pts[0].VexPoint()); }
public void Align(uint[] instanceIds, ChainType chainType, Vex.Point target, List <Bond> addedBonds, List <Bond> previousBonds) { BondAttachment bt = chainType.GetAttachment(); BondType bondType = chainType.IsAligned() ? BondType.Anchor : BondType.Spring; Bond b; Bond prev = null; for (int i = 0; i < instanceIds.Length - 1; i++) { uint id = instanceIds[i]; if (chainType.IsDistributed()) { if (i > 0) { RemoveCollidingBond(id, bt, previousBonds, BondType.Anchor); } if (i < instanceIds.Length - 1) { BondAttachment btOpp = chainType.GetOppositeAttachment(); RemoveCollidingBond(id, btOpp, previousBonds, BondType.Anchor); } } else { RemoveCollidingBond(id, bt, previousBonds, BondType.Anchor); } b = new Bond(id, bt, bondType); b.ChainType = chainType; b.TargetLocation = target; AddBond(b); addedBonds.Add(b); b.Previous = prev; if (prev != null) { prev.Next = b; } prev = b; } int lastIndex = instanceIds.Length - 1; uint lastId = instanceIds[lastIndex]; RemoveCollidingBond(lastId, bt, previousBonds, BondType.Anchor); b = new Bond(lastId, bt, bondType); b.ChainType = chainType; b.TargetLocation = target; AddBond(b); addedBonds.Add(b); b.Previous = prev; prev.Next = b; }
public void ConstrainOffset(IEnumerable <uint> sourceIds, ref Vex.Point offset) { HashSet <uint> tested = new HashSet <uint>(); HashSet <uint> alreadyDiscovered = new HashSet <uint>(); List <Bond> guideBonds = new List <Bond>(); AppendJoinedRelations(sourceIds, tested, alreadyDiscovered, guideBonds); foreach (Bond b in guideBonds) { offset.X = b.Next.SourceAttachment.IsVGuide() ? 0 : offset.X; offset.Y = b.Next.SourceAttachment.IsHGuide() ? 0 : offset.Y; } }
private void GetRelatedObjectTransformsRec(IEnumerable <uint> ids, Dictionary <uint, Vex.Rectangle> alreadyDiscovered, Vex.Point offset, HashSet <Bond> starts) { List <Bond> externalBonds = new List <Bond>(); DesignTimeline designStage = MainForm.CurrentStage.CurrentEditItem; //alreadyDiscovered.UnionWith(ids); //foreach (uint id in ids) //{ // alreadyDiscovered.Add(id, designStage[id].StrokeBounds.TranslatedRectangle(tx, ty)); //} List <Bond> guideBonds = new List <Bond>(); HashSet <uint> joinedIds = new HashSet <uint>(); designStage.BondStore.AppendJoinedRelations(ids, joinedIds, alreadyDiscovered.Keys, guideBonds); foreach (Bond b in guideBonds) { if (b.Next.SourceAttachment.IsGuide()) { bool guideMoved = b.Next.GuideMoved; Vex.Point guideOffset = b.Next.GuideMoved ? offset : Vex.Point.Zero; offset.X = b.Next.SourceAttachment.IsVGuide() ? guideOffset.X : offset.X; offset.Y = b.Next.SourceAttachment.IsHGuide() ? guideOffset.Y : offset.Y; } } foreach (uint id in joinedIds) { if (!alreadyDiscovered.ContainsKey(id)) { alreadyDiscovered.Add(id, designStage[id].StrokeBounds.TranslatedRectangle(offset.X, offset.Y)); } externalBonds.AddRange(designStage.BondStore.GetExternalBondIds(alreadyDiscovered.Keys, id, starts)); } foreach (Bond b in externalBonds) { // todo: this algorithm ignores multiple chains on an object. // probably need to keep track of 'join islands' and their outward chains if (!alreadyDiscovered.ContainsKey(b.SourceInstanceId)) { float newTx = offset.X; float newTy = offset.Y; if (offset.X != 0 || offset.Y != 0) { designStage.BondStore.GetFinalOffset(b, ref newTx, ref newTy); } GetRelatedObjectTransformsRec(new uint[] { b.SourceInstanceId }, alreadyDiscovered, new Vex.Point(newTx, newTy), starts); } } }
public DesignInstance Add(uint definitionId, Vex.Point location) { DesignInstance si = stage.CreateInstance(definitionId, location); if (si != null) { timeline.AddInstance(si.Instance); si.ParentInstanceId = InstanceHash; selectedItems.Clear(); selectedItems.Add(si.InstanceHash); SnapStore.AddInstance(si); } return(si); }
public void UnExecute() { StageView stage = MainForm.CurrentStage; List <Bond> discardAddedBonds = new List <Bond>(); List <Bond> discardPreviousBonds = new List <Bond>(); foreach (Bond b in addedBonds) { stage.CurrentEditItem.BondStore.RemoveBond(b); } Vex.Point unOffset = new Vex.Point(-offset.X, -offset.Y); stage.TranslateSelection(unOffset, false, discardAddedBonds, discardPreviousBonds); foreach (Bond b in previousBonds) { stage.CurrentEditItem.BondStore.AddBond(b); } addedBonds.Clear(); previousBonds.Clear(); }
public void LockToGuide( uint srcId, BondAttachment srcHandle, uint targId, BondAttachment targHandle, Vex.Point targetLocation, List <Bond> addedBonds, List <Bond> previousBonds) { bool canAdd = RemoveCollidingBond(srcId, srcHandle, previousBonds, BondType.Lock); if (canAdd) { Bond src = new Bond(srcId, srcHandle, BondType.Lock); Bond targ = GetOrCreateGuideBond(targId, targHandle); src.TargetLocation = targetLocation; targ.TargetLocation = targetLocation; AddBond(src); src.Next = targ; addedBonds.Add(src); guideAttachments[targId].Add(src); } }
public void JoinHandles( uint srcId, BondAttachment srcHandle, uint targId, BondAttachment targHandle, Vex.Point targetLocation, List <Bond> addedBonds, List <Bond> previousBonds) { RemoveCollidingBond(srcId, srcHandle, previousBonds, BondType.Join); RemoveCollidingBond(targId, targHandle, previousBonds, BondType.Join); Bond src = new Bond(srcId, srcHandle, BondType.Join); Bond targ = new Bond(targId, targHandle, BondType.Join); AddBond(src); AddBond(targ); src.Next = targ; targ.Previous = src; src.TargetLocation = targetLocation; targ.TargetLocation = targetLocation; addedBonds.Add(src); addedBonds.Add(targ); }
public ICrossPoint[] GetCrossPoint(Vex.Point snapPoint, BondAttachment ba) { List <ICrossPoint> result = new List <ICrossPoint>(); if (ba.IsHandle()) { if (xStops.ContainsKey(snapPoint.X)) // will not contain point if snaping to original position { List <ICrossPoint> cps = xStops[snapPoint.X]; ICrossPoint cp = cps.Find(item => item.CrossStart == snapPoint.Y); if (cp != null) { result.Add(cp); } } } else { if (ba.IsVGuide()) { List <ICrossPoint> cps = xStops[snapPoint.X]; if (cps.Count > 0) { result.Add(cps[0]); } } if (ba.IsHGuide()) { List <ICrossPoint> cps = yStops[snapPoint.Y]; if (cps.Count > 0) { result.Add(cps[0]); } } } return(result.ToArray()); }
public MoveSelectionCommand(Vex.Point offset) { this.offset = offset; useSmartBonds = MainForm.CurrentStage.UseSmartBonds; }
public void GetRelatedObjectTransforms(IEnumerable <uint> ids, Dictionary <uint, Vex.Rectangle> alreadyDiscovered, Vex.Point offset) { HashSet <Bond> starts = new HashSet <Bond>(); GetRelatedObjectTransformsRec(ids, alreadyDiscovered, offset, starts); foreach (Bond start in starts) { SortBondChain(ids, start, alreadyDiscovered); } }
public Vex.Point LocalToContainer(Vex.Point pt) { Vex.Point result = Gdi.GdiRenderer.GetTransformedPoint(pt.SysPointF(), GetSysMatrix(), false).VexPoint(); return(result); }
public void Execute() { StageView stage = MainForm.CurrentStage; InstanceGroup sel = MainForm.CurrentStage.Selection; Vex.Rectangle bounds = sel.StrokeBounds; uint[] ids = sel.SelectedIds; offsets = new Vex.Point[ids.Length]; InstanceManager im = MainForm.CurrentInstanceManager; List <uint> sortIds = new List <uint>(ids); im.SortIndexesByLocation(sortIds, chainType); Vex.Point target = Vex.Point.Empty; if (chainType == ChainType.DistributedHorizontal) { float firstWidth = MainForm.CurrentInstanceManager[sortIds[0]].StrokeBounds.Width; float lastWidth = MainForm.CurrentInstanceManager[sortIds[sortIds.Count - 1]].StrokeBounds.Width; float fillWidth = bounds.Width - firstWidth - lastWidth; float remainingWidths = 0; for (int i = 1; i < sortIds.Count - 1; i++) { DesignInstance di = MainForm.CurrentInstanceManager[sortIds[i]]; remainingWidths += di.StrokeBounds.Width; } float spacing = (fillWidth - remainingWidths) / (sortIds.Count - 1); float curLoc = bounds.Left; for (int i = 0; i < sortIds.Count; i++) { DesignInstance di = MainForm.CurrentInstanceManager[sortIds[i]]; Vex.Point offset = new Vex.Point(curLoc - di.StrokeBounds.Left, 0); Vex.Matrix m = di.GetMatrix(); m.Translate(offset); stage.SetDesignInstanceMatrix(di, m); curLoc += spacing + di.StrokeBounds.Width; int realIndex = Array.IndexOf(ids, sortIds[i]); offsets[realIndex] = offset; } target = new Vex.Point(spacing, float.NaN); } else if (chainType == ChainType.DistributedVertical) { float firstHeight = MainForm.CurrentInstanceManager[sortIds[0]].StrokeBounds.Height; float lastHeight = MainForm.CurrentInstanceManager[sortIds[sortIds.Count - 1]].StrokeBounds.Height; float fillHeight = bounds.Height - firstHeight - lastHeight; float remainingHeights = 0; for (int i = 1; i < sortIds.Count - 1; i++) { DesignInstance di = MainForm.CurrentInstanceManager[sortIds[i]]; remainingHeights += di.StrokeBounds.Height; } float spacing = (fillHeight - remainingHeights) / (sortIds.Count - 1); float curLoc = bounds.Top; for (int i = 0; i < sortIds.Count; i++) { DesignInstance di = MainForm.CurrentInstanceManager[sortIds[i]]; Vex.Point offset = new Vex.Point(0, curLoc - di.StrokeBounds.Top); Vex.Matrix m = di.GetMatrix(); m.Translate(offset); stage.SetDesignInstanceMatrix(di, m); curLoc += spacing + di.StrokeBounds.Height; int realIndex = Array.IndexOf(ids, sortIds[i]); offsets[realIndex] = offset; } target = new Vex.Point(float.NaN, spacing); } else { Vex.Rectangle contrainedBounds = bounds.Clone(); stage.CurrentEditItem.BondStore.ConstrainBounds(sortIds, ref contrainedBounds, chainType); switch (chainType) { case ChainType.AlignedLeft: target = new Vex.Point(contrainedBounds.Left, float.NaN); break; case ChainType.AlignedCenterVertical: target = new Vex.Point(contrainedBounds.Center.X, float.NaN); break; case ChainType.AlignedRight: target = new Vex.Point(contrainedBounds.Right, float.NaN); break; case ChainType.AlignedTop: target = new Vex.Point(float.NaN, contrainedBounds.Top); break; case ChainType.AlignedCenterHorizontal: target = new Vex.Point(float.NaN, contrainedBounds.Center.Y); break; case ChainType.AlignedBottom: target = new Vex.Point(float.NaN, contrainedBounds.Bottom); break; } for (int i = 0; i < sortIds.Count; i++) { DesignInstance di = MainForm.CurrentInstanceManager[sortIds[i]]; Vex.Point offset = Vex.Point.Zero; switch (chainType) { case ChainType.AlignedLeft: offset.X = target.X - di.StrokeBounds.Left; break; case ChainType.AlignedCenterVertical: offset.X = target.X - (di.StrokeBounds.Left + di.StrokeBounds.Width / 2); break; case ChainType.AlignedRight: offset.X = target.X - (di.StrokeBounds.Left + di.StrokeBounds.Width); break; case ChainType.AlignedTop: offset.Y = target.Y - di.StrokeBounds.Top; break; case ChainType.AlignedCenterHorizontal: offset.Y = target.Y - (di.StrokeBounds.Top + di.StrokeBounds.Height / 2); break; case ChainType.AlignedBottom: offset.Y = target.Y - (di.StrokeBounds.Top + di.StrokeBounds.Height); break; } Vex.Matrix m = di.GetMatrix(); m.Translate(offset); stage.SetDesignInstanceMatrix(di, m); offsets[i] = offset; } } if (useSmartBonds) { stage.CurrentEditItem.BondStore.Align(sortIds.ToArray(), chainType, target, addedBonds, previousBonds); } sel.Update(); MainForm.CurrentStage.ResetTransformHandles(); MainForm.CurrentStage.InvalidateTransformedSelection(); }
public static Point SysPoint(this Vex.Point p) { return(new Point( (int)Math.Ceiling(p.X), (int)Math.Ceiling(p.Y))); }
public static PointF SysPointF(this Vex.Point p) { return(new PointF(p.X, p.Y)); }
public Vex.Point GetSnapPoints(PointF[] pts, ref Vex.Point[] snapPoints, ref BondAttachment[] snapTypes) { Vex.Point resultOffset = Vex.Point.Zero; // get first snap point for each handle point (based on top left) Vex.Point[] snapsXP = new Vex.Point[pts.Length]; Vex.Point[] snapsY = new Vex.Point[pts.Length]; for (int i = 0; i < pts.Length; i++) { snapsXP[i] = Vex.Point.Empty; snapsY[i] = Vex.Point.Empty; GetSnapPoint(xStops, pts[i].X, pts[i].Y, ref snapsXP[i].X, ref snapsXP[i].Y); GetSnapPoint(yStops, pts[i].Y, pts[i].X, ref snapsY[i].Y, ref snapsY[i].X, false); } // get closest X and Y float bestDist = float.MaxValue; float bestDistX = float.MaxValue; float bestDistY = float.MaxValue; Vex.Point bestPoint = Vex.Point.Empty; Dictionary <int, BondAttachment> bestIndexes = new Dictionary <int, BondAttachment>(); for (int i = 0; i < snapsXP.Length; i++) { // find the distance to the snap(s) for the given handle Vex.Point rp = snapsXP[i]; float difX = 0; float difY = 0; BondAttachment targ = BondAttachment.None; if (!float.IsNaN(rp.X) && !float.IsNaN(rp.Y)) // point { targ = BondAttachment.SymbolHandle; difX = rp.X - pts[i].X; difY = rp.Y - pts[i].Y; } else if (!float.IsNaN(rp.X)) // vertical guide { targ = BondAttachment.VGuide; difX = rp.X - pts[i].X; } rp = snapsY[i]; if (float.IsNaN(rp.X) && !float.IsNaN(rp.Y)) // horizontal guide { targ = (targ == BondAttachment.VGuide) ? BondAttachment.CornerGuide : BondAttachment.HGuide; difY = rp.Y - pts[i].Y; } // check if close enough to win or tie float distX = difX * difX; float distY = difY * difY; if (targ.IsHandle()) { float dist = distX + distY; if (dist <= bestDist + 0.001f) { if (dist + 0.001f < bestDist && (bestPoint.IsEmpty || Math.Abs(difX - bestPoint.X) < 0.001 || Math.Abs(difY - bestPoint.Y) < 0.001)) { bestIndexes.Clear(); bestDist = dist; bestPoint = new Vex.Point(difX, difY); bestDistX = distX; bestDistY = distY; bestIndexes.Add(i, targ); } else if (Math.Abs(distX - bestDistX) < 0.001 && Math.Abs(distY - bestDistY) < 0.001) { bestIndexes.Add(i, targ); } } } else if (targ != BondAttachment.None) // guides { float minXY = Math.Min(distX, distY); if (minXY < bestDist - 0.0001f) { foreach (var item in bestIndexes.Where(kpv => kpv.Value == BondAttachment.SymbolHandle).ToList()) { bestIndexes.Remove(item.Key); } bestDist = minXY; } if (targ == BondAttachment.CornerGuide) { if (distX - 0.0001f <= bestDistX || difY - 0.0001f <= bestDistY) { foreach (var item in bestIndexes.Where(kpv => ((kpv.Value == BondAttachment.VGuide && bestDistX > distX) || (kpv.Value == BondAttachment.HGuide && bestDistY > distY)) ).ToList()) { bestIndexes.Remove(item.Key); } bestDistX = Math.Min(bestDistX, distX); bestDistY = Math.Min(bestDistY, distY); bestIndexes.Add(i, targ); } } else if (targ == BondAttachment.VGuide) // clear non HGuides { if (distX - 0.0001f <= bestDistX) { foreach (var item in bestIndexes.Where(kpv => (kpv.Value.IsVGuide() && bestDistX > distX)).ToList()) { bestIndexes.Remove(item.Key); } bestDistX = distX; bestIndexes.Add(i, targ); } } else if (targ == BondAttachment.HGuide) // clear non VGuides { if (distY - 0.0001f <= bestDistY) { foreach (var item in bestIndexes.Where(kpv => (kpv.Value.IsHGuide() && bestDistY > distY)).ToList()) { bestIndexes.Remove(item.Key); } bestDistY = distY; bestIndexes.Add(i, targ); } } } } // find offset bool hasSnap = false; Vex.Point target = Vex.Point.Empty; foreach (int key in bestIndexes.Keys) { hasSnap = true; BondAttachment bt = bestIndexes[key]; PointF src = pts[key]; target = (bt == BondAttachment.HGuide) ? snapsY[key] : snapsXP[key]; if (bt.IsHandle()) { resultOffset = new Vex.Point(target.X - src.X, target.Y - src.Y); break; } else if (bt == BondAttachment.CornerGuide) { resultOffset = new Vex.Point(target.X - src.X, snapsY[key].Y - src.Y); break; } else if (bt == BondAttachment.HGuide) { if (resultOffset.X != 0) { resultOffset = new Vex.Point(resultOffset.X, target.Y - src.Y); break; } resultOffset = new Vex.Point(0, target.Y - src.Y); } else if (bt == BondAttachment.VGuide) { if (resultOffset.Y != 0) { resultOffset = new Vex.Point(target.X - src.X, resultOffset.Y); break; } resultOffset = new Vex.Point(target.X - src.X, 0); } } // set snap points if (hasSnap) { foreach (int key in bestIndexes.Keys) { BondAttachment bt = bestIndexes[key]; snapTypes[key] = bt; target = (bt == BondAttachment.HGuide) ? snapsY[key] : snapsXP[key]; if (bt.IsHandle()) { snapPoints[key] = new Vex.Point(target.X, target.Y); } else if (bt == BondAttachment.HGuide) { snapPoints[key] = new Vex.Point(pts[key].X + resultOffset.X, target.Y); } else if (bt == BondAttachment.VGuide) { snapPoints[key] = new Vex.Point(target.X, pts[key].Y + resultOffset.Y); } else if (bt == BondAttachment.CornerGuide) { snapPoints[key] = new Vex.Point(pts[key].X + resultOffset.X, pts[key].Y + resultOffset.Y); } } } return(resultOffset); }