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