예제 #1
0
        /// <summary>
        /// Finds node and/or edge hit by the given point</summary>
        /// <param name="graph">Graph to test</param>
        /// <param name="priorityEdge">Graph edge to test before others</param>
        /// <param name="p">Point to test</param>
        /// <param name="g">Graphics object</param>
        /// <returns>Hit record containing node and/or edge hit by the given point</returns>
        public override GraphHitRecord <TNode, TEdge, BoundaryRoute> Pick(
            IGraph <TNode, TEdge, BoundaryRoute> graph,
            TEdge priorityEdge,
            Point p,
            Graphics g)
        {
            int tolerance = m_theme.PickTolerance;

            TNode         pickedNode = null;
            TEdge         pickedEdge = null;
            BoundaryRoute fromRoute  = null;
            BoundaryRoute toRoute    = null;

            Vec2F v = new Vec2F(p.X, p.Y);

            if (priorityEdge != null &&
                Pick(priorityEdge, v))
            {
                pickedEdge = priorityEdge;
            }
            else
            {
                foreach (TEdge edge in graph.Edges.Reverse())
                {
                    if (Pick(edge, v))
                    {
                        pickedEdge = edge;
                        break;
                    }
                }
            }

            foreach (TNode state in graph.Nodes.Reverse())
            {
                Rectangle bounds = state.Bounds;
                bounds.Inflate(tolerance, tolerance);

                if (bounds.Contains(p))
                {
                    pickedNode = state;

                    float position = PointToParameter(bounds, p);

                    bounds.Inflate(-2 * tolerance, -2 * tolerance);
                    bool onEdge = !bounds.Contains(p);

                    if (pickedEdge == null)
                    {
                        if (onEdge)
                        {
                            // edge of node can be source or destination
                            fromRoute = new BoundaryRoute(position);
                            toRoute   = new BoundaryRoute(position);
                        }
                    }
                    else // hit on edge and node
                    {
                        if (onEdge)
                        {
                            if (pickedEdge.FromNode == pickedNode)
                            {
                                fromRoute = new BoundaryRoute(position);
                            }
                            else if (pickedEdge.ToNode == pickedNode)
                            {
                                toRoute = new BoundaryRoute(position);
                            }
                        }
                    }
                    break;
                }
            }

            IComplexState <TNode, TEdge> complexState = pickedNode as IComplexState <TNode, TEdge>;

            if (complexState != null && pickedEdge == null)
            {
                Rectangle bounds      = pickedNode.Bounds;
                Rectangle labelBounds = new Rectangle(
                    bounds.X + CornerRadius,
                    bounds.Y + Margin,
                    bounds.Width - 2 * CornerRadius,
                    m_theme.Font.Height);

                if (labelBounds.Contains(p))
                {
                    DiagramLabel label = new DiagramLabel(labelBounds, TextFormatFlags.SingleLine);
                    return
                        (new GraphHitRecord <TNode, TEdge, BoundaryRoute>(pickedNode, label));
                }
            }

            return
                (new GraphHitRecord <TNode, TEdge, BoundaryRoute>(pickedNode, pickedEdge, fromRoute, toRoute));
        }
예제 #2
0
        private void Draw(TNode state, Graphics g)
        {
            Rectangle bounds = state.Bounds;

            if (state.Type != StateType.Normal)
            {
                DrawPseudostate(bounds.Location, state.Type, m_theme.OutlinePen, g);
            }
            else
            {
                IComplexState <TNode, TEdge> complexState = state as IComplexState <TNode, TEdge>;

                // Prevent an exception being thrown by LinearGradientBrush.
                if (bounds.Width <= 0)
                {
                    bounds.Width = 1;
                }
                if (bounds.Height <= 0)
                {
                    bounds.Height = 1;
                }

                StateIndicators indicators = state.Indicators;
                if ((indicators & StateIndicators.Active) != 0)
                {
                    g.FillEllipse(
                        Brushes.SpringGreen,
                        bounds.X - CornerRadius,
                        bounds.Y - CornerRadius,
                        2 * CornerRadius,
                        2 * CornerRadius);
                }

                // draw state lozenge
                using (GraphicsPath gp = GetStatePath(bounds))
                {
                    if (!IsPrinting)
                    {
                        using (LinearGradientBrush interiorBrush =
                                   new LinearGradientBrush(
                                       bounds,
                                       Color.WhiteSmoke,
                                       Color.LightGray,
                                       LinearGradientMode.ForwardDiagonal))
                        {
                            g.FillPath(interiorBrush, gp);
                        }
                    }
                    else
                    {
                        g.FillPath(Brushes.White, gp);
                    }
                    g.DrawPath(m_theme.OutlinePen, gp);
                }

                g.DrawString(
                    complexState.Name,
                    m_theme.Font,
                    m_theme.TextBrush,
                    bounds.X + CornerRadius,
                    bounds.Y + Margin);

                g.DrawLine(
                    m_theme.OutlinePen,
                    bounds.Left, bounds.Top + m_fontHeight + Margin,
                    bounds.Right, bounds.Top + m_fontHeight + Margin);

                RectangleF textBounds = new RectangleF(
                    (float)(bounds.Left + 4),
                    (float)(bounds.Top + m_fontHeight + 2),
                    (float)(bounds.Width - 5),
                    (float)(bounds.Height - m_fontHeight - 4));

                g.DrawString(complexState.Text, m_theme.Font, m_theme.TextBrush, textBounds, s_stateTextFormat);

                //IList<int> partitionWidths = complexState.PartitionSizes;
                //if (partitionWidths.Count > 0)
                //{
                //    // draw AND-state dividers
                //    int lastDivider = bounds.Left;
                //    foreach (int width in partitionWidths)
                //    {
                //        g.DrawLine(
                //            m_dividerPen,
                //            lastDivider, bounds.Y + m_fontHeight + Margin,
                //            lastDivider, bounds.Y + bounds.Height);

                //        lastDivider += width;
                //    }
                //}
            }
        }
예제 #3
0
        private void Draw(TNode state, D2dGraphics g, bool outline)
        {
            RectangleF bounds = state.Bounds;

            if (state.Type != StateType.Normal)
            {
                DrawPseudostate(state, g, outline);
            }
            else
            {
                float scaleX     = g.Transform.M11; // assume no rotation.
                float radInPixel = scaleX * CornerRadius;

                IComplexState <TNode, TEdge> complexState = state as IComplexState <TNode, TEdge>;

                StateIndicators indicators = state.Indicators;
                if ((indicators & StateIndicators.Active) != 0)
                {
                    if (radInPixel > MinRadiusInPixel)
                    {
                        D2dEllipse ellipse = new D2dEllipse();
                        ellipse.RadiusX = CornerRadius;
                        ellipse.RadiusY = CornerRadius;
                        ellipse.Center  = bounds.Location;
                        g.FillEllipse(ellipse, Color.SpringGreen);
                    }
                }


                if (radInPixel > MinRadiusInPixel)
                {
                    m_stateRect.Rect = bounds;
                    D2dLinearGradientBrush gradbrush = m_theme.FillGradientBrush;
                    gradbrush.StartPoint = bounds.Location;
                    gradbrush.EndPoint   = new PointF(bounds.Right, bounds.Bottom);

                    g.FillRoundedRectangle(m_stateRect, gradbrush);
                    if (outline)
                    {
                        g.DrawRoundedRectangle(m_stateRect, m_theme.OutlineBrush);
                    }
                }
                else
                {
                    g.FillRectangle(bounds, m_theme.FillBrush);
                    if (outline)
                    {
                        g.DrawRectangle(bounds, m_theme.OutlineBrush);
                    }
                }
                g.DrawLine(bounds.Left, bounds.Top + m_fontHeight + Margin,
                           bounds.Right, bounds.Top + m_fontHeight + Margin, m_theme.OutlineBrush);

                if ((scaleX * m_fontHeight) > MinFontHeightInPixel)
                {
                    g.DrawText(complexState.TitleText, m_theme.TextFormat,
                               new PointF(bounds.X + CornerRadius, bounds.Y + Margin), m_theme.TextBrush);
                }



                //RectangleF textBounds = new RectangleF(
                //    (float)(bounds.Left + 4),
                //    (float)(bounds.Top + m_fontHeight + 2),
                //    (float)(bounds.Width - 5),
                //    (float)(bounds.Height - m_fontHeight - 4));

                //g.DrawString(complexState.Text, m_theme.Font, m_theme.TextBrush, textBounds, s_stateTextFormat);

                //IList<int> partitionWidths = complexState.PartitionSizes;
                //if (partitionWidths.Count > 0)
                //{
                //    // draw AND-state dividers
                //    int lastDivider = bounds.Left;
                //    foreach (int width in partitionWidths)
                //    {
                //        g.DrawLine(
                //            m_dividerPen,
                //            lastDivider, bounds.Y + m_fontHeight + Margin,
                //            lastDivider, bounds.Y + bounds.Height);

                //        lastDivider += width;
                //    }
                //}
            }
        }