public override bool CanConnectTo(FlowConnector connector) { if (!(connector is AlgorithmFlowConnector)) return false; var algorithmFlowConnector = connector as AlgorithmFlowConnector; AlgorithmFlowElement inputLayer, outputLayer; int inputIndex; if (this.IsOutput) { inputIndex = FlowElement.GetConnectorIndex(algorithmFlowConnector.Owner, algorithmFlowConnector); inputLayer = algorithmFlowConnector.m_LayerOwner; outputLayer = this.m_LayerOwner; } else if (this.IsInput) { inputIndex = FlowElement.GetConnectorIndex(this.Owner, this); inputLayer = this.m_LayerOwner; outputLayer = algorithmFlowConnector.m_LayerOwner; } else throw new NotSupportedException(); var inputType = inputLayer.Layer.Algorithm.InputTypes[inputIndex]; var outputType = outputLayer.Layer.Algorithm.OutputType; return inputType == outputType; }
public static int GetConnectorIndex(FlowElement el, FlowConnector fl) { if (fl.IsInput) { return(el.InputConnectors.IndexOf(fl)); } return(el.OutputConnectors.IndexOf(fl)); }
internal static void RenderTo(FlowElement el, RenderAttributes re, bool selected) { int ex = (int)(el.X * re.Zoom); int ey = (int)(el.Y * re.Zoom); int ew = (int)(el.Width * re.Zoom); int eh = (int)(el.Height * re.Zoom); int eiw = (int)Math.Floor(el.ImageWidth * re.Zoom); int eih = (int)Math.Floor(el.ImageHeight * re.Zoom); int etx = (int)((el.X + 4) * re.Zoom); int ety = (int)((el.Y + 4) * re.Zoom); int aiw = 0, aih = 0; if (el.m_AdditionalInformation != null) { aiw = (int)Math.Floor(el.m_AdditionalInformation.Width * re.Zoom); aih = (int)Math.Floor(el.m_AdditionalInformation.Height * re.Zoom); } re.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed; re.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; re.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; re.Graphics.FillRectangle(selected ? m_TitleHighlight : SystemBrushes.Control, ex, ey, ew - 1 * re.Zoom, eh - 1 * re.Zoom); re.Graphics.DrawRectangle(Pens.Black, ex, ey, ew - 1 * re.Zoom, eh - 1 * re.Zoom); re.Graphics.DrawString(el.Name, re.Font, SystemBrushes.ControlText, new PointF(etx, ety)); var image = el.Image; if (image != null && ex + 1 * re.Zoom + eiw > 0 && ey + 21 * re.Zoom + eih > 0) { re.Graphics.DrawImage(image, ex + 1 * re.Zoom, ey + 21 * re.Zoom, eiw, eih); } var additional = el.m_AdditionalInformation; if (additional != null && ex + 1 * re.Zoom + aiw > 0 && ey + 21 * re.Zoom + eih + aih > 0) { re.Graphics.DrawImage(additional, ex + 1 * re.Zoom, ey + 21 * re.Zoom + eih, aiw, aih); } foreach (FlowConnector fl in el.OutputConnectors) { FlowConnector.RenderTo(fl, re); } foreach (FlowConnector fl in el.InputConnectors) { FlowConnector.RenderTo(fl, re); } }
internal static void RenderTo(FlowConnector el, RenderAttributes re) { re.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; re.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; // If we are input, we draw on the left hand side of the flow element. int idx = FlowElement.GetConnectorIndex(el.Owner, el); int sx = (int)Math.Ceiling(re.Graphics.MeasureString(el.Name, re.Font).Width); float xx = (el.IsInput ? el.Owner.X - CONNECTOR_PADDING : el.Owner.X + el.Owner.Width + CONNECTOR_PADDING) * re.Zoom; float yy = (el.Owner.Y + idx * (CONNECTOR_SIZE + CONNECTOR_PADDING)) * re.Zoom; if (el.IsInput) { re.Graphics.DrawString(el.Name, re.Font, SystemBrushes.ControlText, new PointF(xx - sx + CONNECTOR_PADDING * re.Zoom, yy)); } else { re.Graphics.DrawString(el.Name, re.Font, SystemBrushes.ControlText, new PointF(xx, yy)); } el.InvalidationWidth = sx; el.m_CenterZoomAdjustment = re.Zoom; sx += CONNECTOR_PADDING; re.Graphics.DrawRectangle(Pens.Black, xx + (el.IsInput ? -sx : sx), yy, CONNECTOR_SIZE * re.Zoom, CONNECTOR_SIZE * re.Zoom); if (el.IsInput && el.ConnectedTo != null) { foreach (FlowConnector ct in el.ConnectedTo) { try { re.Graphics.DrawLine(Pens.Blue, el.Center.Apply(re.Zoom), ct.Center.Apply(re.Zoom)); } catch (OverflowException) { } } } }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); // Don't do anything on right-click. if (e.Button == System.Windows.Forms.MouseButtons.Right) { if (this.m_ActiveConnection != null) { this.m_ActiveConnection = null; this.Invalidate(); } else { this.SelectedElement = null; foreach (FlowElement el in this.m_Elements.Reverse<FlowElement>()) { if (el.Region.Contains(e.Location.Apply(1 / this.Zoom))) { this.SelectedElement = el; this.m_SelectedElementStillHeldDown = true; this.m_SelectedElementsDrag[el] = new Point( (int)(e.X / this.Zoom) - el.X, (int)(e.Y / this.Zoom) - el.Y); break; } } this.m_LastContextMenuOpenLocation = e.Location; } return; } // If we are currently dragging, ignore this logic. if (this.m_SelectedElementStillHeldDown || this.m_PanningStillHeldDown) return; // Check to see if the mouse is over an element during left press. if (e.Button == System.Windows.Forms.MouseButtons.Left) { if (this.m_WillMultiselect) { this.m_Multiselecting = true; this.m_MultiselectStartX = e.X; this.m_MultiselectStartY = e.Y; this.m_MultiselectEndX = e.X; this.m_MultiselectEndY = e.Y; this.m_MultiselectPreviousEndX = e.X; this.m_MultiselectPreviousEndY = e.Y; return; } if (this.SelectedElements.Count <= 1) { this.SelectedElement = null; } foreach (FlowElement el in this.m_Elements.Reverse<FlowElement>()) { if (el.Region.Contains(e.Location.Apply(1 / this.Zoom))) { if (this.SelectedElements.Count <= 1) { this.SelectedElement = el; } this.m_SelectedElementStillHeldDown = true; this.m_SelectedElementsDrag[el] = new Point( (int)(e.X / this.Zoom) - el.X, (int)(e.Y / this.Zoom) - el.Y); break; } } if (this.SelectedElements.Count > 1) { foreach (FlowElement el in this.m_Elements.Reverse<FlowElement>()) { if (this.SelectedElements.Contains(el)) { this.m_SelectedElementsDrag[el] = new Point( (int)(e.X / this.Zoom) - el.X, (int)(e.Y / this.Zoom) - el.Y); } } } if (this.SelectedElements.Count > 1 && !this.m_SelectedElementStillHeldDown) { this.SelectedElement = null; } // If we didn't select an element, see if we clicked on a flow // connector. if (this.SelectedElement == null && this.m_ActiveConnection == null) { var range = new Rectangle( e.X - FlowConnector.CONNECTOR_SIZE / 2, e.Y - FlowConnector.CONNECTOR_SIZE / 2, FlowConnector.CONNECTOR_SIZE * 2, FlowConnector.CONNECTOR_SIZE * 2); foreach (FlowElement el in this.m_Elements.Reverse<FlowElement>()) { // Check input connectors. foreach (FlowConnector ic in el.InputConnectors) { if (range.Contains(ic.Center)) { this.m_ActiveConnection = ic; return; } } // Check output connectors. foreach (FlowConnector ic in el.OutputConnectors) { if (range.Contains(ic.Center)) { this.m_ActiveConnection = ic; return; } } } } // Otherwise if we're clicking on a flow connector and there is an // active connection, we probably want to make the connection. else if (this.m_ActiveConnection != null) { var range = new Rectangle( e.X - FlowConnector.CONNECTOR_SIZE / 2, e.Y - FlowConnector.CONNECTOR_SIZE / 2, FlowConnector.CONNECTOR_SIZE * 2, FlowConnector.CONNECTOR_SIZE * 2); foreach (FlowElement el in this.m_Elements.Reverse<FlowElement>()) { // Check input connectors. foreach (FlowConnector ic in el.InputConnectors) { if (range.Contains(ic.Center)) { // The user wants to connect this up. Is it possible? if (this.m_ActiveConnection.IsInput || !this.m_ActiveConnection.CanConnectTo(ic) || !ic.CanConnectTo(this.m_ActiveConnection)) { // Can't connect an input to an input.. this.m_ActiveConnection = null; this.Invalidate(); return; } // Set the connection. var old = this.m_ActiveConnection.ConnectedTo; var newFC = new List<FlowConnector>(); foreach (FlowConnector fc in old) if (!newFC.Contains(fc)) newFC.Add(fc); if (!newFC.Contains(ic)) newFC.Add(ic); this.m_ActiveConnection.ConnectedTo = newFC.ToArray(); // Finish up by turning off connection mode. this.m_ActiveConnection = null; this.Invalidate(); return; } } // Check output connectors. foreach (FlowConnector ic in el.OutputConnectors) { if (range.Contains(ic.Center)) { // The user wants to connect this up. Is it possible? if (this.m_ActiveConnection.IsOutput || !this.m_ActiveConnection.CanConnectTo(ic) || !ic.CanConnectTo(this.m_ActiveConnection)) { // Can't connect an output to an output.. this.m_ActiveConnection = null; this.Invalidate(); return; } // Set the connection. var old = this.m_ActiveConnection.ConnectedTo; foreach (var fc in old) { var newFC = new List<FlowConnector>(); foreach (var ffc in fc.ConnectedTo) if (ffc != this.m_ActiveConnection) newFC.Add(ffc); fc.ConnectedTo = newFC.ToArray(); } this.m_ActiveConnection.ConnectedTo = new[] { ic }; // Finish up by turning off connection mode. this.m_ActiveConnection = null; this.Invalidate(); return; } } } } } // Pan on middle mouse button. if (e.Button == System.Windows.Forms.MouseButtons.Middle || e.Button == System.Windows.Forms.MouseButtons.Left) { this.m_PanningStillHeldDown = true; this.m_AllElementPanX = this.m_AllElementPanOldX = e.X; this.m_AllElementPanY = this.m_AllElementPanOldY = e.Y; } }
public virtual bool CanConnectTo(FlowConnector connector) { return(true); }
public void SetConnectorsForLayer(AlgorithmFlowConnector connector, FlowConnector[] targets, bool isInput) { if (isInput) { // We are an input connector, we must clear our layer's current // parent and set it to the new value. if (targets.Length != 1) throw new InvalidOperationException("An input can not be connected to more than one output."); if (this.m_Layer.Inputs == null) throw new InvalidOperationException("Input array for an algorithm can not be null."); this.m_Layer.Inputs[this.m_InputConnectors.IndexOf(connector)] = (targets[0].Owner as AlgorithmFlowElement).m_Layer; this.ObjectPropertyUpdated(); } else { // We are an output connector, we must add ourselves as the target's // parent. We can do this as a reverse operation on our targets. foreach (var t in targets) { (t.Owner as AlgorithmFlowElement).SetConnectorsForLayer( t as AlgorithmFlowConnector, new[] { connector }, true); } } // Invalidate the control area. foreach (Rectangle r in this.GetConnectorRegionsToInvalidate()) this.m_Control.Invalidate(r); }
public FlowConnector[] GetConnectorsForLayer(FlowConnector connector, bool isInput) { if (isInput) return this.m_Control.Elements .Where(v => v is AlgorithmFlowElement) .Select(v => v as AlgorithmFlowElement) .Where(v => this.m_Layer.Inputs == null ? false : this.m_Layer.Inputs.Contains(v.m_Layer)) .Where(v => this.ParentsIndexOf(v.m_Layer).Contains(this.m_InputConnectors.IndexOf(connector))) .Select(v => v.m_OutputConnectors[0]) .ToArray(); IEnumerable<AlgorithmFlowElement> lfe = this.m_Control.Elements .Where(v => v is AlgorithmFlowElement) .Select(v => v as AlgorithmFlowElement) .Where(v => v.m_Layer.Inputs == null ? false : v.m_Layer.Inputs.Contains(this.m_Layer)); // TODO: Probably can be moved into LINQ query above. var fll = new List<FlowConnector>(); foreach (var el in lfe) { for (var i = 0; i < el.m_InputConnectors.Count; i++) { if ( (el.m_InputConnectors[i] as AlgorithmFlowConnector).ConnectedTo.Contains( this.m_OutputConnectors[0])) { fll.Add(el.m_InputConnectors[i]); } } } return fll.ToArray(); }
public static int GetConnectorIndex(FlowElement el, FlowConnector fl) { if (fl.IsInput) return el.InputConnectors.IndexOf(fl); return el.OutputConnectors.IndexOf(fl); }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); // Don't do anything on right-click. if (e.Button == System.Windows.Forms.MouseButtons.Right) { if (this.m_ActiveConnection != null) { this.m_ActiveConnection = null; this.Invalidate(); } else { this.SelectedElement = null; foreach (FlowElement el in this.m_Elements.Reverse <FlowElement>()) { if (el.Region.Contains(e.Location.Apply(1 / this.Zoom))) { this.SelectedElement = el; this.m_SelectedElementStillHeldDown = true; this.m_SelectedElementsDrag[el] = new Point( (int)(e.X / this.Zoom) - el.X, (int)(e.Y / this.Zoom) - el.Y); break; } } this.m_LastContextMenuOpenLocation = e.Location; } return; } // If we are currently dragging, ignore this logic. if (this.m_SelectedElementStillHeldDown || this.m_PanningStillHeldDown) { return; } // Check to see if the mouse is over an element during left press. if (e.Button == System.Windows.Forms.MouseButtons.Left) { if (this.m_WillMultiselect) { this.m_Multiselecting = true; this.m_MultiselectStartX = e.X; this.m_MultiselectStartY = e.Y; this.m_MultiselectEndX = e.X; this.m_MultiselectEndY = e.Y; this.m_MultiselectPreviousEndX = e.X; this.m_MultiselectPreviousEndY = e.Y; return; } if (this.SelectedElements.Count <= 1) { this.SelectedElement = null; } foreach (FlowElement el in this.m_Elements.Reverse <FlowElement>()) { if (el.Region.Contains(e.Location.Apply(1 / this.Zoom))) { if (this.SelectedElements.Count <= 1) { this.SelectedElement = el; } this.m_SelectedElementStillHeldDown = true; this.m_SelectedElementsDrag[el] = new Point( (int)(e.X / this.Zoom) - el.X, (int)(e.Y / this.Zoom) - el.Y); break; } } if (this.SelectedElements.Count > 1) { foreach (FlowElement el in this.m_Elements.Reverse <FlowElement>()) { if (this.SelectedElements.Contains(el)) { this.m_SelectedElementsDrag[el] = new Point( (int)(e.X / this.Zoom) - el.X, (int)(e.Y / this.Zoom) - el.Y); } } } if (this.SelectedElements.Count > 1 && !this.m_SelectedElementStillHeldDown) { this.SelectedElement = null; } // If we didn't select an element, see if we clicked on a flow // connector. if (this.SelectedElement == null && this.m_ActiveConnection == null) { var range = new Rectangle( e.X - FlowConnector.CONNECTOR_SIZE / 2, e.Y - FlowConnector.CONNECTOR_SIZE / 2, FlowConnector.CONNECTOR_SIZE * 2, FlowConnector.CONNECTOR_SIZE * 2); foreach (FlowElement el in this.m_Elements.Reverse <FlowElement>()) { // Check input connectors. foreach (FlowConnector ic in el.InputConnectors) { if (range.Contains(ic.Center)) { this.m_ActiveConnection = ic; return; } } // Check output connectors. foreach (FlowConnector ic in el.OutputConnectors) { if (range.Contains(ic.Center)) { this.m_ActiveConnection = ic; return; } } } } // Otherwise if we're clicking on a flow connector and there is an // active connection, we probably want to make the connection. else if (this.m_ActiveConnection != null) { var range = new Rectangle( e.X - FlowConnector.CONNECTOR_SIZE / 2, e.Y - FlowConnector.CONNECTOR_SIZE / 2, FlowConnector.CONNECTOR_SIZE * 2, FlowConnector.CONNECTOR_SIZE * 2); foreach (FlowElement el in this.m_Elements.Reverse <FlowElement>()) { // Check input connectors. foreach (FlowConnector ic in el.InputConnectors) { if (range.Contains(ic.Center)) { // The user wants to connect this up. Is it possible? if (this.m_ActiveConnection.IsInput || !this.m_ActiveConnection.CanConnectTo(ic) || !ic.CanConnectTo(this.m_ActiveConnection)) { // Can't connect an input to an input.. this.m_ActiveConnection = null; this.Invalidate(); return; } // Set the connection. var old = this.m_ActiveConnection.ConnectedTo; var newFC = new List <FlowConnector>(); foreach (FlowConnector fc in old) { if (!newFC.Contains(fc)) { newFC.Add(fc); } } if (!newFC.Contains(ic)) { newFC.Add(ic); } this.m_ActiveConnection.ConnectedTo = newFC.ToArray(); // Finish up by turning off connection mode. this.m_ActiveConnection = null; this.Invalidate(); return; } } // Check output connectors. foreach (FlowConnector ic in el.OutputConnectors) { if (range.Contains(ic.Center)) { // The user wants to connect this up. Is it possible? if (this.m_ActiveConnection.IsOutput || !this.m_ActiveConnection.CanConnectTo(ic) || !ic.CanConnectTo(this.m_ActiveConnection)) { // Can't connect an output to an output.. this.m_ActiveConnection = null; this.Invalidate(); return; } // Set the connection. var old = this.m_ActiveConnection.ConnectedTo; foreach (var fc in old) { var newFC = new List <FlowConnector>(); foreach (var ffc in fc.ConnectedTo) { if (ffc != this.m_ActiveConnection) { newFC.Add(ffc); } } fc.ConnectedTo = newFC.ToArray(); } this.m_ActiveConnection.ConnectedTo = new[] { ic }; // Finish up by turning off connection mode. this.m_ActiveConnection = null; this.Invalidate(); return; } } } } } // Pan on middle mouse button. if (e.Button == System.Windows.Forms.MouseButtons.Middle || e.Button == System.Windows.Forms.MouseButtons.Left) { this.m_PanningStillHeldDown = true; this.m_AllElementPanX = this.m_AllElementPanOldX = e.X; this.m_AllElementPanY = this.m_AllElementPanOldY = e.Y; } }
internal static void RenderTo(FlowConnector el, RenderAttributes re) { re.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; re.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; // If we are input, we draw on the left hand side of the flow element. int idx = FlowElement.GetConnectorIndex(el.Owner, el); int sx = (int)Math.Ceiling(re.Graphics.MeasureString(el.Name, re.Font).Width); float xx = (el.IsInput ? el.Owner.X - CONNECTOR_PADDING : el.Owner.X + el.Owner.Width + CONNECTOR_PADDING) * re.Zoom; float yy = (el.Owner.Y + idx * (CONNECTOR_SIZE + CONNECTOR_PADDING)) * re.Zoom; if (el.IsInput) re.Graphics.DrawString(el.Name, re.Font, SystemBrushes.ControlText, new PointF(xx - sx + CONNECTOR_PADDING * re.Zoom, yy)); else re.Graphics.DrawString(el.Name, re.Font, SystemBrushes.ControlText, new PointF(xx, yy)); el.InvalidationWidth = sx; el.m_CenterZoomAdjustment = re.Zoom; sx += CONNECTOR_PADDING; re.Graphics.DrawRectangle(Pens.Black, xx + (el.IsInput ? -sx : sx), yy, CONNECTOR_SIZE * re.Zoom, CONNECTOR_SIZE * re.Zoom); if (el.IsInput && el.ConnectedTo != null) foreach (FlowConnector ct in el.ConnectedTo) { try { re.Graphics.DrawLine(Pens.Blue, el.Center.Apply(re.Zoom), ct.Center.Apply(re.Zoom)); } catch (OverflowException) { } } }
public virtual bool CanConnectTo(FlowConnector connector) { return true; }