// determines whether the button has been hit
            public bool IsHit(IInputModeContext context, PointD location)
            {
                // see if the button is visible at all
                IOrientedRectangle orientedRectangle = label.GetLayout();

                if (orientedRectangle.Contains(location, context.HitTestRadius))
                {
                    location = location - orientedRectangle.GetAnchorLocation();

                    double upX = orientedRectangle.UpX;
                    double upY = orientedRectangle.UpY;

                    double tx = location.X * -upY + location.Y * upX;
                    double ty = location.X * upX + location.Y * upY;

                    // consider auto flipping of the label contents
                    if (upY > 0)
                    {
                        return
                            (new RectD(inset, inset, 20, orientedRectangle.Height - 2 * inset).Contains(new PointD(tx, ty),
                                                                                                        context.HitTestRadius));
                    }
                    else
                    {
                        return
                            (new RectD(orientedRectangle.Width - (inset + buttonWidth), inset, buttonWidth,
                                       orientedRectangle.Height - 2 * inset).Contains(new PointD(tx, ty),
                                                                                      context.HitTestRadius));
                    }
                }
                else
                {
                    return(false);
                }
            }
예제 #2
0
        /// <summary>
        ///   Creates the geometry for the label's path.
        /// </summary>
        /// <param name="layout">The label's layout.</param>
        /// <param name="text">The label text.</param>
        /// <returns>The label path's geometry.</returns>
        /// <remarks>
        ///   The label's visualization is an approximation of its text where each word is represented by a line with a length
        ///   proportional to the word's length. In the vast majority of cases this approximates the position of spaces in the line
        ///   accurately enough that the switch from a text label to a fast label is almost imperceptible.
        /// </remarks>
        private StreamGeometry CreateGeometry(IOrientedRectangle layout, string text)
        {
            var origin = layout.GetAnchorLocation();
            var up     = layout.GetUp();
            var right  = new PointD(-up.Y, up.X);

            if (AutoFlip && up.Y > 0)
            {
                origin = origin + up * layout.Height + right * layout.Width;
                up     = -up;
                right  = -right;
            }

            var upperLeft = origin + up * layout.Height;

            // This part could be optimized a bit by not allocating new objects and thus reduce pressure on the garbage
            // collector. However, in practice it made not much of an impact.
            var lines             = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            var longestLineLength = lines.Max(l => l.Length);
            var sizePerLetter     = layout.Width / longestLineLength;

            var geometry = new StreamGeometry();

            using (var ctx = geometry.Open()) {
                // Fill – only drawn when a brush was set
                if (BackgroundBrush != null)
                {
                    ctx.BeginFigure(origin, true, false);
                    ctx.PolyLineTo(new Point[]
                    {
                        origin + right * layout.Width,
                        origin + right * layout.Width + up * layout.Height,
                        origin + up * layout.Height
                    }, false, false);
                }

                // Lines
                for (int i = 0; i < lines.Length; i++)
                {
                    var line         = lines[i];
                    var words        = line.Split(' ', ' ');
                    var currentPoint = upperLeft - up * layout.Height / lines.Length * (i + 0.6);
                    // Words
                    foreach (var word in words)
                    {
                        var wordLength  = word.Length * sizePerLetter;
                        var targetPoint = currentPoint + right * wordLength;

                        ctx.BeginFigure(currentPoint, false, false);
                        ctx.LineTo(targetPoint, true, false);

                        currentPoint = targetPoint + right * sizePerLetter;
                    }
                }
            }
            return(geometry);
        }
예제 #3
0
        /// <summary>
        ///   Creates the geometry for the selection rectangle.
        /// </summary>
        /// <param name="layout">The label's layout.</param>
        /// <returns>The selection rectangle geometry.</returns>
        private Geometry CreateGeometry(IOrientedRectangle layout)
        {
            var up     = layout.GetUp();
            var anchor = layout.GetAnchorLocation();
            var right  = new PointD(-up.Y, up.X);

            var g = new StreamGeometry();

            using (var ctx = g.Open()) {
                ctx.BeginFigure(anchor, Fill != null, true);
                ctx.LineTo(anchor + right * layout.Width, true, false);
                ctx.LineTo(anchor + right * layout.Width + up * layout.Height, true, false);
                ctx.LineTo(anchor + up * layout.Height, true, false);
                ctx.LineTo(anchor, true, false);
            }
            return(g);
        }
예제 #4
0
        /// <summary>
        /// Returns the location of the specified position on the border of the oriented rectangle.
        /// </summary>
        private PointD GetLocation(IOrientedRectangle layout, HandlePositions position)
        {
            if (layout == null)
            {
                return(node.Layout.ToPointD());
            }
            switch (position)
            {
            case HandlePositions.NorthWest:
                return(GetLocation(layout, 0.0, 1.0));

            case HandlePositions.North:
                return(GetLocation(layout, 0.5, 1.0));

            case HandlePositions.NorthEast:
                return(GetLocation(layout, 1.0, 1.0));

            case HandlePositions.East:
                return(GetLocation(layout, 1.0, 0.5));

            case HandlePositions.SouthEast:
                return(GetLocation(layout, 1.0, 0.0));

            case HandlePositions.South:
                return(GetLocation(layout, 0.5, 0.0));

            case HandlePositions.SouthWest:
                return(layout.GetAnchorLocation());

            case HandlePositions.West:
                return(GetLocation(layout, 0.0, 0.5));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #5
0
        public Visual UpdateSelectionVisual(IRenderContext context, Visual oldVisual, IOrientedRectangle layout)
        {
            var container = oldVisual as VisualGroup;

            if (container != null && container.Children.Count == 1)
            {
                var visual = container.Children[0] as FrameworkElement;
                if (visual != null)
                {
                    Transform transform = context.IntermediateTransform;
                    container.Transform = transform;
                    var anchor      = layout.GetAnchorLocation();
                    var anchorAndUp = anchor + layout.GetUp();
                    anchor      = context.WorldToIntermediateCoordinates(anchor);
                    anchorAndUp = context.WorldToIntermediateCoordinates(anchorAndUp);

                    var or = new OrientedRectangle();
                    or.SetUpVector((anchorAndUp - anchor).Normalized);
                    or.SetAnchor(anchor);
                    or.Width      = layout.Width * context.Zoom;
                    or.Height     = layout.Height * context.Zoom;
                    visual.Width  = or.Width;
                    visual.Height = or.Height;
                    visual.SetCanvasArrangeRect(new Rect(0, 0, or.Width, or.Height));
                    ArrangeByLayout(context, visual, or, false);

                    if (!container.IsMeasureValid)
                    {
                        container.Arrange(new Rect(0, 0, or.Width, or.Height));
                    }

                    return(container);
                }
            }
            return(CreateSelectionVisual(context, layout));
        }