/// <summary> /// Get point representing given connector. /// </summary> /// <param name="connector">Connector which point is requested.</param> /// <returns>Point representing given connector if available, <c>null</c> otherwise.</returns> private GraphPoint getPoint(ConnectorDrawing connector) { GraphPoint connectorPoint; _connectorPoints.TryGetValue(connector, out connectorPoint); return(connectorPoint); }
/// <summary> /// Attach behaviour to given connector /// </summary> /// <param name="connector">Attached connector</param> /// <param name="engine">Engine using attached behaviour</param> /// <param name="moveHandler">Handler used for move events</param> internal static void Attach(ConnectorDrawing connector, DisplayEngine engine, OnConnectorMove moveHandler) { var item = connector.OwningItem; UpdateGlobalPosition.WidthChange.AddValueChanged(item, (e, args) => { moveHandler(connector); }); UpdateGlobalPosition.HeightChange.AddValueChanged(item, (e, args) => { moveHandler(connector); }); }
internal static void SetProperties(ConnectorDrawing connector, string heading, IEnumerable <KeyValuePair <string, string> > mapping) { var definition = connector.Definition; var propertiesText = new StringBuilder(); foreach (var map in mapping) { var property = definition.GetProperty(map.Key); if (property == null || property.Value == null) { continue; } propertiesText.AppendFormat("{0}: {1}\n", map.Value, property.Value); } var metaText = new StringBuilder(); foreach (var property in definition.Properties) { var prefix = "$Meta"; var propertyName = property.Name; if (!propertyName.StartsWith(prefix)) { continue; } var name = propertyName.Substring(propertyName.IndexOf('-') + 1); metaText.AppendFormat("{0}: {1}\n", name, property.Value); } var tooltip = DrawingTools.GetHeadingText(heading, propertiesText.ToString()); if (metaText.Length > 0) { DrawingTools.AppendHeadingText("Metadata", metaText.ToString(), tooltip); } DrawingTools.SetToolTip(connector, tooltip); }
/// <summary> /// Run exploration of path between given connectors /// <remarks>Exploration should be runned before path finding</remarks>. /// </summary> /// <param name="from">Connector from which path is explored.</param> /// <param name="to">Connector to which path is explored.</param> public void Explore(ConnectorDrawing from, ConnectorDrawing to) { //initialize global buffers _processed.Clear(); _fromCandidates.Clear(); //get point representation of source connector var fromPoint = getPoint(from); if (fromPoint == null) { return; } //all points on desired component are possible targets (they all are connected with self) var toItem = to.OwningItem; var toCandidates = _itemPoints.Get(toItem); //run exploration tryEnqueue(fromPoint); while (_fromCandidates.Count > 0) { var fromCandidate = _fromCandidates.Dequeue(); foreach (var toCandidate in toCandidates) { DiagramItem obstacle; tryAddEdge(fromCandidate, toCandidate, toItem, out obstacle); enqueueWithObstacleEdges(fromCandidate, obstacle); } foreach (var neighbour in fromCandidate.ExploredNeighbours) { tryEnqueue(neighbour); } } }
/// <summary> /// Create point for given connector with given view angle. /// </summary> /// <param name="connector">Connector which point is created.</param> /// <param name="view">View angle of created point.</param> /// <returns>Created point.</returns> private GraphPoint createPoint(ConnectorDrawing connector, ViewAngle view) { var position = connector.GlobalConnectPoint; return(new GraphPoint(position, view, connector.OwningItem)); }
/// <summary> /// Gets the input slots. /// </summary> /// <param name="connectorIndex">Index of the connector.</param> /// <param name="connectorsCount">The connectors count.</param> /// <param name="connector">The connector.</param> /// <param name="item">The item.</param> /// <param name="contactPoints">The contact points.</param> /// <returns>GraphPoint[].</returns> /// <exception cref="System.NotSupportedException">Connector align + connectorAlign</exception> private GraphPoint[] getInputSlots(int connectorIndex, int connectorsCount, ConnectorDrawing connector, DiagramItem item, List <GraphPoint> contactPoints) { var connectorAlign = connector.Align; var span = _navigator.GetSpan(item); //find positions of slots for inputs according to connector align Point slot1End, slot1Start; Point slot2End; ViewAngle slot1View; ViewAngle slot2View; GraphPoint slot1Contact; GraphPoint slot2Contact; //slots has to be parallel with same length switch (connectorAlign) { case ConnectorAlign.Top: slot1Contact = contactPoints[2]; slot2Contact = contactPoints[3]; slot1View = TopLeftCorner; slot2View = TopRightCorner; slot1End = span.TopLeft; slot2End = span.TopRight; slot1Start = new Point(slot1End.X, slot1End.Y + item.TopConnectors.DesiredSize.Height); break; case ConnectorAlign.Bottom: slot1Contact = contactPoints[0]; slot2Contact = contactPoints[1]; slot1View = BottomLeftCorner; slot2View = BottomRightCorner; slot1End = span.BottomLeft; slot2End = span.BottomRight; slot1Start = new Point(slot1End.X, slot1End.Y - item.BottomConnectors.DesiredSize.Height); break; case ConnectorAlign.Left: slot1Contact = contactPoints[1]; slot2Contact = contactPoints[3]; slot1View = TopLeftCorner; slot2View = BottomLeftCorner; slot1End = span.TopLeft; slot2End = span.BottomLeft; slot1Start = new Point(slot1End.X + item.LeftConnectors.DesiredSize.Width, slot1End.Y); break; case ConnectorAlign.Right: slot1Contact = contactPoints[0]; slot2Contact = contactPoints[2]; slot1View = TopRightCorner; slot2View = BottomRightCorner; slot1End = span.TopRight; slot2End = span.BottomRight; slot1Start = new Point(slot1End.X - item.RightConnectors.DesiredSize.Width, slot1End.Y); break; default: throw new NotSupportedException("Connector align " + connectorAlign); } var slotVector = (slot1Start - slot1End) / (connectorsCount + 2); var slot1 = new GraphPoint(slot1End + slotVector * connectorIndex, slot1View, item); var slot2 = new GraphPoint(slot2End + slotVector * (connectorsCount - connectorIndex), slot2View, item); slot1.SetEdgeStatus(slot1Contact); slot2.SetEdgeStatus(slot2Contact); return(new[] { slot1, slot2 }); }
/// <summary> /// Find path beween from and to connectors. /// <remarks>Path finding is processed on current explored state of graph</remarks>. /// </summary> /// <param name="from">Start of desired path.</param> /// <param name="to">End of desired path.</param> /// <returns>Path if available, <c>null</c> otherwise.</returns> /// <exception cref="System.NotSupportedException"></exception> public Point[] FindPath(ConnectorDrawing from, ConnectorDrawing to) { //get connector representation on graph var fromPoint = getPoint(from); var toPoint = getPoint(to); //if there is no connector representation we //cannot construct path if (fromPoint == null || toPoint == null) { return(null); } //store points that has been already reached var reachedPoints = new Dictionary <GraphPoint, GraphPoint>(); reachedPoints.Add(fromPoint, null); //queue where are stored relaxed graph nodes var toRelax = new Dictionary <GraphPoint, double>(); toRelax.Add(fromPoint, 0); while (toRelax.Count > 0) { var currentPair = extractMin(toRelax); var current = currentPair.Key; var currentDistance = currentPair.Value; //relax all neigbours of current node foreach (var neighbour in current.ExploredNeighbours) { if (reachedPoints.ContainsKey(neighbour)) { continue; } var fromCurrentDistance = current.DistanceTo(neighbour); var toNeighbourDistance = currentDistance + fromCurrentDistance; double previousNeighbourDistance; if (!toRelax.TryGetValue(neighbour, out previousNeighbourDistance)) { toRelax[neighbour] = previousNeighbourDistance = double.MaxValue; } if (previousNeighbourDistance <= toNeighbourDistance) { //we have already a better path continue; } if (neighbour == current) { throw new NotSupportedException(); } //relax path reachedPoints[neighbour] = current; toRelax[neighbour] = toNeighbourDistance; } } //get representation of path that has been found var reconstructed = reconstructPath(toPoint, reachedPoints); var simplified = simplifyPath(reconstructed); return(simplified); }