예제 #1
0
        private Rectangle GetLabelBounds(TEdge edge, D2dGraphics g)
        {
            Vec2F   startPoint  = new Vec2F();
            Vec2F   endPoint    = new Vec2F();
            CircleF c           = new CircleF();
            bool    moreThan180 = false;
            Vec2F   textPoint;

            if (GetEdgeGeometry(edge, edge.FromRoute.Index, ref startPoint, ref endPoint, ref c, ref moreThan180))
            {
                textPoint = (endPoint + startPoint) * 0.5f;
            }
            else
            {
                textPoint = (endPoint + startPoint) * 0.5f;
                CircleF.Project(textPoint, c, ref textPoint);
                if (moreThan180)
                {
                    textPoint -= 2 * (textPoint - c.Center);
                }
            }

            float height = m_theme.TextFormat.FontHeight;
            float width  = 32;

            if (!string.IsNullOrEmpty(edge.Label))
            {
                SizeF size = g.MeasureText(edge.Label, m_theme.TextFormat);
                width  = size.Width;
                height = size.Height;
            }
            return(new Rectangle((int)(textPoint.X - width * 0.5f), (int)textPoint.Y, (int)width, (int)height));
        }
예제 #2
0
        /// <summary>
        /// Draws floating group pin</summary>
        /// <param name="grpPin">Group pin</param>
        /// <param name="inputSide">True for input pin, false for output pin</param>
        /// <param name="style">DiagramDrawingStyle</param>
        /// <param name="g">Graphics object</param>
        public void DrawFloatingGroupPin(ICircuitGroupPin <TElement> grpPin, bool inputSide, DiagramDrawingStyle style, D2dGraphics g)
        {
            SizeF  pinNameSize = g.MeasureText(grpPin.Name, Theme.TextFormat);
            PointF p;

            if (inputSide)
            {
                p = GetGroupPinLocation(grpPin, true);

                RectangleF pinRect = new RectangleF(p.X + CircuitGroupPinInfo.FloatingPinBoxWidth - Theme.PinSize,
                                                    grpPin.Bounds.Location.Y + Theme.PinMargin + Theme.PinOffset,
                                                    Theme.PinSize, Theme.PinSize);
                // draw output pin for input floating pins
                g.DrawRectangle(pinRect, m_subGraphPinPen);
                if (grpPin.Info.Pinned)
                {
                    D2dUtil.DrawPin((int)(p.X + CircuitGroupPinInfo.FloatingPinBoxWidth), (int)p.Y, true, true, m_pinBrush, g);
                }
                else
                {
                    D2dUtil.DrawPin((int)(p.X + CircuitGroupPinInfo.FloatingPinBoxWidth), (int)p.Y + Theme.PinSize / 2, false, true, m_pinBrush, g);
                }

                RectangleF bounds    = new RectangleF(p.X, p.Y, CircuitGroupPinInfo.FloatingPinBoxWidth, CircuitGroupPinInfo.FloatingPinBoxHeight);
                RectangleF alignRect = new RectangleF(
                    bounds.Left, bounds.Bottom + Theme.PinMargin, pinNameSize.Width, Theme.RowSpacing);
                var textAlignment = Theme.TextFormat.TextAlignment;
                Theme.TextFormat.TextAlignment = D2dTextAlignment.Leading;
                g.DrawText(grpPin.Name, Theme.TextFormat, alignRect.Location, Theme.TextBrush);
                Theme.TextFormat.TextAlignment = textAlignment;
            }
            else
            {
                // assume vertical scroll bar width = 16
                p = GetGroupPinLocation(grpPin, false);

                RectangleF pinRect = new RectangleF(p.X + 1, grpPin.Bounds.Location.Y + Theme.PinMargin + Theme.PinOffset,
                                                    Theme.PinSize, Theme.PinSize);
                // draw input pin for output floating pins
                g.DrawRectangle(pinRect, m_subGraphPinPen);
                // draw pin icon
                if (grpPin.Info.Pinned)
                {
                    D2dUtil.DrawPin((int)p.X, (int)p.Y, true, false, m_pinBrush, g);
                }
                else
                {
                    D2dUtil.DrawPin((int)p.X, (int)p.Y + Theme.PinSize / 2, false, false, m_pinBrush, g);
                }

                // draw label
                RectangleF bounds     = new RectangleF(p.X, p.Y, CircuitGroupPinInfo.FloatingPinBoxWidth, CircuitGroupPinInfo.FloatingPinBoxHeight);
                RectangleF alignRectF = new RectangleF(bounds.Right - pinNameSize.Width, bounds.Bottom + Theme.PinMargin,
                                                       pinNameSize.Width, Theme.RowSpacing);

                var textAlignment = Theme.TextFormat.TextAlignment;
                Theme.TextFormat.TextAlignment = D2dTextAlignment.Trailing;
                g.DrawText(grpPin.Name, Theme.TextFormat, alignRectF, Theme.TextBrush);
                Theme.TextFormat.TextAlignment = textAlignment;
            }

            // draw the fake pin node itself
            float savedStrokeWidth = Theme.StrokeWidth;

            Theme.StrokeWidth = 2.0f;
            if (style == DiagramDrawingStyle.Normal)
            {
                g.DrawRectangle(new RectangleF(p.X, p.Y, CircuitGroupPinInfo.FloatingPinBoxWidth, CircuitGroupPinInfo.FloatingPinBoxHeight), m_subGraphPinNodePen);
            }
            else
            {
                g.DrawRectangle(new RectangleF(p.X, p.Y, CircuitGroupPinInfo.FloatingPinBoxWidth, CircuitGroupPinInfo.FloatingPinBoxHeight), Theme.HotBrush);
            }
            Theme.StrokeWidth = savedStrokeWidth;


            if (!grpPin.Info.ExternalConnected)
            {
                RectangleF eyeRect = GetVisibilityCheckRect(grpPin, inputSide);
                g.DrawEyeIcon(eyeRect, grpPin.Info.Visible ? m_visiblePinBrush : m_hiddrenPinBrush, 1.0f);
            }

            // draw fake edge that connects group pin fake node
            DrawGroupPinNodeFakeEdge(grpPin, p, inputSide, style, g);
        }
예제 #3
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 <TElement, TWire, TPin> Pick(
            IGraph <TElement, TWire, TPin> graph, TWire priorityEdge, PointF p, D2dGraphics g)
        {
            var hitRecord = base.Pick(graph, priorityEdge, p, g);

            if (hitRecord.Node != null || hitRecord.Edge != null || hitRecord.Part != null)
            {
                return(hitRecord);
            }

            // check whether hits virtual parts of group pin
            var group = graph.Cast <ICircuitGroupType <TElement, TWire, TPin> >();

            foreach (var pin in group.Inputs.Concat(group.Info.HiddenInputPins))
            {
                var grpPin = pin.Cast <ICircuitGroupPin <TElement> >();
                // check whether hit the thumbtack of a floating pin
                var pinRect = GetThumbtackRect(grpPin, true);
                if (pinRect.Contains(p))
                {
                    var pinPart = new DiagramPin(pinRect);
                    return(new GraphHitRecord <TElement, TWire, TPin>((TPin)grpPin, pinPart));
                }

                // check whether hit the visibility check(eye icon)
                var eyeRect = GetVisibilityCheckRect(grpPin, true);
                if (eyeRect.Contains(p))
                {
                    var eyePart = new DiagramVisibilityCheck(eyeRect);
                    return(new GraphHitRecord <TElement, TWire, TPin>((TPin)grpPin, eyePart));
                }


                // check whether hit the floating pin label-part
                PointF     grpPos      = GetGroupPinLocation(grpPin, true);
                RectangleF bounds      = new RectangleF(grpPos.X, grpPos.Y, CircuitGroupPinInfo.FloatingPinBoxWidth, CircuitGroupPinInfo.FloatingPinBoxHeight);
                SizeF      nameSize    = g.MeasureText(grpPin.Name, Theme.TextFormat);
                RectangleF labelBounds = new RectangleF(bounds.Left, bounds.Bottom + Theme.PinMargin, (int)nameSize.Width, Theme.RowSpacing);
                //labelBounds = GdiUtil.Transform(g.Transform, labelBounds);
                var labelPart = new DiagramLabel(
                    new Rectangle((int)labelBounds.Left, (int)labelBounds.Top, (int)labelBounds.Width, (int)labelBounds.Height),
                    TextFormatFlags.SingleLine | TextFormatFlags.Left);

                if (labelBounds.Contains(p))
                {
                    return(new GraphHitRecord <TElement, TWire, TPin>((TPin)grpPin, labelPart));
                }

                // check whether hit the floating pin node
                if (bounds.Contains(p))
                {
                    var result = new GraphHitRecord <TElement, TWire, TPin>((TPin)grpPin, null);
                    result.DefaultPart = labelPart;
                    return(result);
                }
            }

            foreach (var pin in group.Outputs.Concat(group.Info.HiddenOutputPins))
            {
                var grpPin = pin.Cast <ICircuitGroupPin <TElement> >();
                // check whether hit the thumbtack of a floating pin
                var pinRect = GetThumbtackRect(grpPin, false);
                if (pinRect.Contains(p))
                {
                    var pinPart = new DiagramPin(pinRect);
                    return(new GraphHitRecord <TElement, TWire, TPin>((TPin)grpPin, pinPart));
                }

                // check whether hit the visibility check(eye icon)
                var eyeRect = GetVisibilityCheckRect(grpPin, false);
                if (eyeRect.Contains(p))
                {
                    var eyePart = new DiagramVisibilityCheck(eyeRect);
                    return(new GraphHitRecord <TElement, TWire, TPin>((TPin)grpPin, eyePart));
                }

                // check whether hit the floating pin label-part
                PointF     grpPos      = GetGroupPinLocation(grpPin, false);
                RectangleF bounds      = new RectangleF(grpPos.X, grpPos.Y, CircuitGroupPinInfo.FloatingPinBoxWidth, CircuitGroupPinInfo.FloatingPinBoxHeight);
                SizeF      nameSize    = g.MeasureText(grpPin.Name, Theme.TextFormat);
                RectangleF labelBounds = new RectangleF(bounds.Right - (int)nameSize.Width, bounds.Bottom + Theme.PinMargin, (int)nameSize.Width, Theme.RowSpacing);
                //labelBounds = GdiUtil.Transform(g.Transform, labelBounds);
                var labelPart = new DiagramLabel(
                    new Rectangle((int)labelBounds.Left, (int)labelBounds.Top, (int)labelBounds.Width, (int)labelBounds.Height),
                    TextFormatFlags.SingleLine | TextFormatFlags.Right);

                if (labelBounds.Contains(p))
                {
                    return(new GraphHitRecord <TElement, TWire, TPin>((TPin)grpPin, labelPart));
                }

                // check whether hit the floating pin node
                if (bounds.Contains(p))
                {
                    var result = new GraphHitRecord <TElement, TWire, TPin>((TPin)grpPin, null);
                    result.DefaultPart = labelPart;
                    return(result);
                }
            }

            return(hitRecord);
        }
예제 #4
0
파일: D2dUtil.cs 프로젝트: blue3k/ATFClone
        /// <summary>
        /// Draws a horizontal chart scale</summary>
        /// <param name="g">The Direct2D graphics object</param>
        /// <param name="transform">Graph (world) to window's client (screen) transform</param>
        /// <param name="graphRect">Graph rectangle</param>
        /// <param name="top">Whether or not the scale should be aligned along the top of the rectangle</param>
        /// <param name="majorSpacing">Spacing, in pixels, between major tick marks</param>
        /// <param name="minimumGraphStep">Minimum spacing, in graph (world) space, between ticks.
        /// For example, 1.0 would limit ticks to being drawn on whole integers.</param>
        /// <param name="lineBrush">Scale line pen</param>
        /// <param name="textFormat">Text format</param>
        /// <param name="textBrush">Text brush</param>
        public static void DrawHorizontalScale(
            this D2dGraphics g,
            Matrix transform,
            RectangleF graphRect,
            bool top,
            int majorSpacing,
            float minimumGraphStep,
            D2dBrush lineBrush,
            D2dTextFormat textFormat,
            D2dBrush textBrush)
        {
            double     xScale     = transform.Elements[0];
            RectangleF clientRect = Transform(transform, graphRect);

            double tickEnd, majorTickStart, minorTickStart, textStart;

            if (top)
            {
                tickEnd        = clientRect.Top + 1;
                majorTickStart = tickEnd + 12;
                minorTickStart = tickEnd + 6;
                textStart      = tickEnd + 8;
            }
            else
            {
                tickEnd        = clientRect.Bottom - 1;
                majorTickStart = tickEnd - 12;
                minorTickStart = tickEnd - 6;
                textStart      = tickEnd - 19;
            }

            double min = Math.Min(graphRect.Left, graphRect.Right);
            double max = Math.Max(graphRect.Left, graphRect.Right);

            double tickAnchor     = CalculateTickAnchor(min, max);
            double majorGraphStep = CalculateStep(
                min, max, Math.Abs(clientRect.Right - clientRect.Left), majorSpacing, minimumGraphStep);
            int    numMinorTicks = CalculateNumMinorTicks(majorGraphStep, minimumGraphStep, 5);
            double cMinorStep    = (majorGraphStep / numMinorTicks) * xScale;

            if (majorGraphStep > 0)
            {
                double offset = tickAnchor - min;
                offset = offset - MathUtil.Remainder(offset, majorGraphStep);

                // draw leading minor ticks
                double cmx;
                cmx = ((tickAnchor - (offset + majorGraphStep)) - min) * xScale + clientRect.Left + cMinorStep;
                for (int i = 0; i < numMinorTicks - 1 && cmx < clientRect.Right; i++)
                {
                    // cull minor ticks outside of the view
                    if (cmx > clientRect.Left)
                    {
                        g.DrawLine((float)cmx, (float)minorTickStart, (float)cmx, (float)tickEnd, lineBrush);
                    }
                    cmx += cMinorStep;
                }

                for (double x = tickAnchor - offset; x < max; x += majorGraphStep)
                {
                    double cx = (x - min) * xScale + clientRect.Left;
                    g.DrawLine((float)cx, (float)majorTickStart, (float)cx, (float)tickEnd, lineBrush);
                    string xString  = String.Format("{0:G8}", Math.Round(x, 6));
                    SizeF  textSize = g.MeasureText(xString, textFormat);
                    var    textRect = new RectangleF(new PointF((float)cx + 1, (float)textStart), textSize);
                    g.DrawText(xString, textFormat, textRect, textBrush);

                    // draw minor ticks
                    cmx = cx + cMinorStep;
                    for (int i = 0; i < numMinorTicks - 1 && cmx < clientRect.Right; i++)
                    {
                        g.DrawLine((float)cmx, (float)minorTickStart, (float)cmx, (float)tickEnd, lineBrush);
                        cmx += cMinorStep;
                    }
                }
            }
        }
예제 #5
0
        private Rectangle GetLabelBounds(TEdge edge, D2dGraphics g)
        {
            Vec2F   startPoint  = new Vec2F();
            Vec2F   endPoint    = new Vec2F();
            CircleF c           = new CircleF();
            bool    moreThan180 = false;
            Vec2F   textPoint;
            int     route = edge.FromRoute.Index;

            if (GetEdgeGeometry(edge, route, ref startPoint, ref endPoint, ref c, ref moreThan180))
            {
                textPoint = (endPoint + startPoint) * 0.5f;
            }
            else
            {
                // prepare to draw arc
                RectangleF rect = new RectangleF(c.Center.X - c.Radius, c.Center.Y - c.Radius, 2 * c.Radius, 2 * c.Radius);

                double       angle1 = Math.Atan2(startPoint.Y - c.Center.Y, startPoint.X - c.Center.X);
                double       angle2 = Math.Atan2(endPoint.Y - c.Center.Y, endPoint.X - c.Center.X);
                const double twoPi  = 2 * Math.PI;

                // swap so we always go clockwise
                if (angle1 > angle2)
                {
                    double temp = angle1;
                    angle1 = angle2;
                    angle2 = temp;
                }

                double startAngle = angle1;
                double sweepAngle = angle2 - angle1;

                if (moreThan180)
                {
                    if (sweepAngle < Math.PI)
                    {
                        sweepAngle = -(twoPi - sweepAngle);
                    }
                }
                else
                {
                    if (sweepAngle > Math.PI)
                    {
                        sweepAngle = -(twoPi - sweepAngle);
                    }
                }

                const double RadiansToDegrees = 360 / twoPi;
                startAngle *= RadiansToDegrees;
                sweepAngle *= RadiansToDegrees;

                textPoint = (endPoint + startPoint) * 0.5f;
                CircleF.Project(textPoint, c, ref textPoint);
                if (moreThan180)
                {
                    textPoint -= 2 * (textPoint - c.Center);
                }
            }

            float height = m_theme.TextFormat.FontHeight;
            float width  = 32;

            if (!string.IsNullOrEmpty(edge.Label))
            {
                SizeF size = g.MeasureText(edge.Label, m_theme.TextFormat);
                width  = size.Width;
                height = size.Height;
            }
            return(new Rectangle((int)(textPoint.X - width * 0.5f), (int)textPoint.Y, (int)width, (int)height));
        }