Vertical Line

//------------------------------------------------------------------------------
//
// Графический объект VerticalLine. Copyright (c) 2023 Tiger Trade Capital AG. All rights reserved.
//
//------------------------------------------------------------------------------
 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.Serialization;
using System.Windows;
using System.Windows.Media;
using TigerTrade.Chart.Alerts;
using TigerTrade.Chart.Base;
using TigerTrade.Chart.Base.Enums;
using TigerTrade.Chart.Indicators.Common;
using TigerTrade.Chart.Objects.Common;
using TigerTrade.Core.Utils.Logging;
using TigerTrade.Dx;
using TigerTrade.Dx.Enums;
 
namespace TigerTrade.Chart.Objects.Custom
{
    [DataContract(Name = "VerticalLineObject", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Objects.Custom")]
    [ChartObject("X_VerticalLine", "Вертикальная линия", 1, Type = typeof(VerticalLineObject))]
    public sealed class VerticalLineObject : ObjectBase
    {
        private ChartAlertSettings _alert;
 
        [DataMember(Name = "Alert")]
        [Category("Оповещение"), DisplayName("Оповещение")]
        public ChartAlertSettings Alert
        {
            get => _alert ?? (_alert = new ChartAlertSettings());
            set
            {
                if (Equals(value, _alert))
                {
                    return;
                }
 
                _alert = value;
 
                OnPropertyChanged();
            }
        }
 
        private XBrush _lineBrush;
 
        private XPen _linePen;
 
        private XColor _lineColor;
 
        [DataMember(Name = "LineColor")]
        [Category("Линия"), DisplayName("Цвет линии")]
        public XColor LineColor
        {
            get => _lineColor;
            set
            {
                if (value == _lineColor)
                {
                    return;
                }
 
                _lineColor = value;
 
                _lineBrush = new XBrush(_lineColor);
                _linePen = new XPen(_lineBrush, LineWidth, LineStyle);
 
                OnPropertyChanged();
            }
        }
 
        private int _lineWidth;
 
        [DataMember(Name = "LineWidth")]
        [Category("Линия"), DisplayName("Толщина линии")]
        public int LineWidth
        {
            get => _lineWidth;
            set
            {
                value = Math.Max(1, Math.Min(10, value));
 
                if (value == _lineWidth)
                {
                    return;
                }
 
                _lineWidth = value;
 
                _linePen = new XPen(_lineBrush, _lineWidth, LineStyle);
 
                OnPropertyChanged();
            }
        }
 
        private XDashStyle _lineStyle;
 
        [DataMember(Name = "LineStyle")]
        [Category("Линия"), DisplayName("Стиль линии")]
        public XDashStyle LineStyle
        {
            get => _lineStyle;
            set
            {
                if (value == _lineStyle)
                {
                    return;
                }
 
                _lineStyle = value;
 
                _linePen = new XPen(_lineBrush, LineWidth, _lineStyle);
 
                OnPropertyChanged();
            }
        }
 
        protected override int PenWidth => LineWidth;
 
        private Rect _lineRect;
 
        public VerticalLineObject()
        {
            LineColor = Colors.Black;
            LineWidth = 1;
            LineStyle = XDashStyle.Solid;
        }
 
        protected override void Draw(DxVisualQueue visual, ref List<ObjectLabelInfo> labels)
        {
            if (Canvas == null)
            {
                return;
            }
 
            var point = ToPoint(ControlPoints[0]);
 
            var startPoint = new Point(point.X, Canvas.Rect.Top);
            var endPoint = new Point(point.X, Canvas.Rect.Bottom);
 
            _lineRect = new Rect(startPoint, endPoint);
 
            if (Settings.TransformVertLines && Canvas.IsStock &&
                Canvas.StockType == ChartStockType.Clusters)
            {
                var brush = new XBrush(_lineBrush.Color, _lineBrush.Color.Alpha > 127 ? 127 : 255);
 
                var x = point.X;
 
                var x1 = x - Canvas.ColumnWidth / 2.0;
                var x2 = x + Canvas.ColumnWidth / 2.0;
 
                if (x2 - x1 > LineWidth + 2)
                {
                    _lineRect = new Rect(new Point(x1, startPoint.Y), new Point(x2, endPoint.Y));
 
                    visual.FillRectangle(brush, _lineRect);
 
                    return;
                }
            }
 
            visual.DrawLine(_linePen, startPoint, endPoint);
        }
 
        public override void DrawControlPoints(DxVisualQueue visual)
        {
            if (_lineRect == Rect.Empty)
            {
                return;
            }
 
            var width = LineWidth / 2 + 4;
 
            var center = new Point((_lineRect.Left + _lineRect.Right) / 2.0, (_lineRect.Top + _lineRect.Bottom) / 2.0);
 
            var rect = new Rect(center, center);
 
            rect.Inflate(new Size(width, width));
 
            visual.FillRectangle(Theme.ChartCpFillBrush, rect);
            visual.DrawRectangle(Theme.ChartCpLinePen, rect);
        }
 
        protected override bool InObject(int x, int y)
        {
            if (_lineRect == Rect.Empty)
            {
                return false;
            }
 
            var r = Rect.Inflate(_lineRect, new Size(2, 0));
 
            return r.Contains(x, y);
        }
 
        public override void ApplyTheme(IChartTheme theme)
        {
            base.ApplyTheme(theme);
 
            LineColor = theme.ChartObjectLineColor;
        }
 
        public override void CopyTemplate(ObjectBase objectBase, bool style)
        {
            if (objectBase is VerticalLineObject obj)
            {
                Alert.Copy(obj.Alert, !style);
 
                OnPropertyChanged(nameof(Alert));
 
                LineColor = obj.LineColor;
                LineWidth = obj.LineWidth;
                LineStyle = obj.LineStyle;
            }
 
            base.CopyTemplate(objectBase, style);
        }
 
        private int _lastAlertIndex;
        private DateTime _lastLineTime;
 
        public override void CheckAlert(List<IndicatorBase> indicators)
        {
            if (!Alert.IsActive)
            {
                return;
            }
 
            try
            {
                var dp = DataProvider;
 
                var lineTime = DateTime.FromOADate(ControlPoints[0].X);
 
                var last = dp.GetCluster(dp.Count - 1);
 
                if (lineTime != _lastLineTime)
                {
                    if (lineTime > last?.CloseTime)
                    {
                        _lastAlertIndex = -1;
 
                        _lastLineTime = lineTime;
                    }
                }
 
                if (last?.CloseTime > lineTime && _lastAlertIndex == -1)
                {
                    _lastAlertIndex = dp.Count;
 
                    var message =
                        $"График пересёк вертикальную линию, время: {DateTime.FromOADate(ControlPoints[0].X).ToString(CultureInfo.CurrentCulture)}.";
 
                    AddAlert(Alert, message);
                }
            }
            catch (Exception e)
            {
                LogManager.WriteError(e);
            }
        }
    }
}

Last updated