Код графического объекта Вертикальная линия
//------------------------------------------------------------------------------ // // Графический объект VerticalLine. Copyright (c) 2020 Ilya Smirnov. 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); } } } }