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;
 }
Example #2
0
 public static int GetConnectorIndex(FlowElement el, FlowConnector fl)
 {
     if (fl.IsInput)
     {
         return(el.InputConnectors.IndexOf(fl));
     }
     return(el.OutputConnectors.IndexOf(fl));
 }
Example #3
0
        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);
            }
        }
Example #4
0
        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;
            }
        }
Example #6
0
 public virtual bool CanConnectTo(FlowConnector connector)
 {
     return(true);
 }
Example #7
0
        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);
        }
Example #8
0
        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);
 }
Example #10
0
        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;
 }