private void AdjustDealCommentArrowAngle(ChartComment comment, MarketOrder order)
        {
            if (!order.TimeExit.HasValue) return;
            // получить основное направление
            // (продолжение линии open - close)
            var ptE = Conversion.WorldToScreen(
                    new PointD(owner.StockSeries.GetDoubleIndexByTime(order.TimeEnter), order.PriceEnter),
                    owner.StockPane.WorldRect, owner.StockPane.CanvasRect);
            var ptQ = Conversion.WorldToScreen(
                    // ReSharper disable PossibleInvalidOperationException
                    new PointD(owner.StockSeries.GetDoubleIndexByTime(order.TimeExit.Value), order.PriceExit.Value),
                    // ReSharper restore PossibleInvalidOperationException
                    owner.StockPane.WorldRect, owner.StockPane.CanvasRect);
            var ptPivot = Conversion.WorldToScreen(new PointD(comment.PivotIndex, comment.PivotPrice),
                    owner.StockPane.WorldRect, owner.StockPane.CanvasRect);
            var ptStart = (Math.Abs(ptPivot.X - ptE.X) < Math.Abs(ptPivot.X - ptQ.X)) ? ptQ : ptE;
            var mainAngle = Math.Atan2(ptPivot.Y - ptStart.Y, ptPivot.X - ptStart.X) * 180 / Math.PI;

            // "округлить" угол
            mainAngle = Math.Round(mainAngle/15) * 15;

            // расставить направления по приоритету
            const int numAngles = 8;
            var angles = new double[numAngles];
            angles[0] = mainAngle;
            for (var i = 0; i < numAngles / 2 - 1; i++)
            {
                var delta = (i + 1) * 360 / numAngles;
                angles[i * 2 + 1] = mainAngle + delta;
                angles[i * 2 + 2] = mainAngle - delta;
            }
            angles[numAngles - 1] = -mainAngle;

            // выбрать направление, для которого комментарий не вылезает за рамки экрана
            var foundAngle = false;
            var screenRect = seriesComment.Owner.CanvasRect;
            using (var gr = owner.CreateGraphics())
            foreach (var angle in angles)
            {
                comment.ArrowAngle = angle;
                var commentRect = comment.GetCommentRectangle(gr,
                    owner.StockPane.WorldRect,
                    owner.StockPane.CanvasRect);
                // не вылез ли комментарий за пределы экрана?
                if (commentRect.Left < screenRect.Left || commentRect.Top < screenRect.Top ||
                    commentRect.Right > screenRect.Right || commentRect.Bottom > screenRect.Bottom)
                    continue;
                foundAngle = true;
                break;
            }

            // угол поворота по-умолчанию
            if (!foundAngle)
                comment.ArrowAngle = angles[0];
        }
Esempio n. 2
0
        private void DrawCommentForSelected(Graphics g,
            RectangleD worldRect, Rectangle canvasRect,
            PenStorage pens, BrushesStorage brushes)
        {
            if (string.IsNullOrEmpty(Comment)) return;

            var commentBox = new ChartComment
                {
                    Color = LineColor,
                    ColorFill = ShapeFillColor,
                    Text = Comment,
                    HideArrow = true,
                    FillTransparency = 160
                };
            var textRect = commentBox.GetCommentRectangle(g, worldRect, canvasRect);

            // прикинуть, куда лучше захреначить комментарий - в центр или в конец
            // спроецировать координаты курсора на линию
            var cursorPoint = Owner.Owner.PointToClient(Control.MousePosition);
            var screenPoints = linePoints.Select(p => Conversion.WorldToScreenF(p, worldRect, canvasRect)).ToList();
            var pivot = Geometry.GetProjectionPointOnLine(cursorPoint, screenPoints[0], screenPoints[1]);

            // пробуем два варианта размещения - привязываем левый верхний или
            // правый нижний углы комментария, смотрим, какой вариант ближе к центру экрана
            var potentialPivots = new []
                {
                    new PointF(pivot.X,
                               pivot.Y + textRect.Height/2),
                    new PointF(pivot.X - textRect.Width,
                               pivot.Y - textRect.Height/2)
                };
            var cx = canvasRect.Left + canvasRect.Width / 2;
            var cy = canvasRect.Top + canvasRect.Height / 2;
            var bestPivotIndex = potentialPivots.IndexOfMin(p => (p.X - cx)*(p.X - cx) + (p.Y - cy)*(p.Y - cy));
            pivot = potentialPivots[bestPivotIndex];
            var worldPivotPoint = Conversion.ScreenToWorld(pivot, worldRect, canvasRect);

            commentBox.PivotPrice = worldPivotPoint.Y;
            commentBox.PivotIndex = worldPivotPoint.X;

            // таки нарисовать
            using (var fonts = new FontStorage(Owner.Owner.Owner.Font))
                commentBox.DrawComment(g, fonts, worldRect, canvasRect, pens, brushes,
                    new List<Rectangle>());
        }