Sample of indicator which shows watermark on the chart
namespace ATAS.Indicators.Technical
{
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Drawing;
using ATAS.Indicators.Editors;
using ATAS.Indicators.Properties;
using OFT.Rendering.Context;
using OFT.Rendering.Tools;
using Color = System.Windows.Media.Color;
public class Watermark : Indicator
{
#region Nested types
public enum Location
{
[Display(Name = "Center")]
Center,
[Display(Name = "TopLeft")]
TopLeft,
[Display(Name = "TopRight")]
TopRight,
[Display(Name = "BottomLeft")]
BottomLeft,
[Display(Name = "BottomRight")]
BottomRight
}
#endregion
#region Properties
[Display(Name = "Color", GroupName = "Common", Order = 10)]
public Color TextColor { get; set; } = Color.FromArgb(255, 225, 225, 225);
[Display(Name = "TextLocation", GroupName = "Common", Order = 20)]
public Location TextLocation { get; set; }
[Display(Name = "HorizontalOffset", GroupName = "Common", Order = 30)]
public int HorizontalOffset { get; set; }
[Display(Name = "VerticalOffset", GroupName = "Common", Order = 40)]
public int VerticalOffset { get; set; }
[Display(Name = "ShowInstrument", GroupName = "FirstLine", Order = 50)]
public bool ShowInstrument { get; set; } = true;
[Display(Name = "ShowPeriod", GroupName = "FirstLine", Order = 60)]
public bool ShowPeriod { get; set; } = true;
[Display(Name = "Font", GroupName = "FirstLine", Order = 70)]
[Editor(typeof(FontEditor), typeof(FontEditor))]
public FontSetting Font { get; set; } = new FontSetting { Size = 60, Bold = true };
[Display(Name = "Text", GroupName = "SecondLine", Order = 80)]
public string AdditionalText { get; set; } = "";
[Display(Name = "Font", GroupName = "SecondLine", Order = 90)]
[Editor(typeof(FontEditor), typeof(FontEditor))]
public FontSetting AdditionalFont { get; set; } = new FontSetting { Size = 55 };
[Display(Name = "VerticalOffset", GroupName = "SecondLine", Order = 90)]
public int AdditionalTextYOffset { get; set; } = -40;
#endregion
#region ctor
public Watermark()
: base(true)
{
Font.PropertyChanged += (a, b) => RedrawChart();
AdditionalFont.PropertyChanged += (a, b) => RedrawChart();
DataSeries[0].IsHidden = true;
DenyToChangePanel = true;
EnableCustomDrawing = true;
SubscribeToDrawingEvents(DrawingLayouts.Historical);
DrawAbovePrice = false;
}
#endregion
#region Overrides of BaseIndicator
protected override void OnCalculate(int bar, decimal value)
{
}
protected override void OnRender(RenderContext context, DrawingLayouts layout)
{
var showSecondLine = !string.IsNullOrWhiteSpace(AdditionalText);
if (!showSecondLine && !ShowInstrument && !ShowPeriod)
return;
var textColor = TextColor.Convert();
var mainTextRectangle = new Rectangle();
var additionalTextRectangle = new Rectangle();
var firstLine = string.Empty;
if (showSecondLine && !string.IsNullOrEmpty(AdditionalText))
{
var size = context.MeasureString(AdditionalText, AdditionalFont.Font);
additionalTextRectangle = new Rectangle(0, 0, (int)size.Width, (int)size.Height);
}
if (ShowInstrument || ShowPeriod)
{
if (ShowInstrument)
firstLine = InstrumentInfo.Instrument;
if (ShowPeriod)
{
var period = ChartInfo.ChartType == "TimeFrame" ? ChartInfo.TimeFrame : $"{ChartInfo.ChartType} {ChartInfo.TimeFrame}";
if (ShowInstrument)
firstLine += $", {period}";
else
firstLine += $"{period}";
}
var size = context.MeasureString(firstLine, Font.Font);
mainTextRectangle = new Rectangle(0, 0, (int)size.Width, (int)size.Height);
}
if (mainTextRectangle.Height > 0 && additionalTextRectangle.Height > 0)
{
int firstLineX;
int secondLineX;
var y = 0;
var totalHeight = mainTextRectangle.Height + additionalTextRectangle.Height + AdditionalTextYOffset;
switch (TextLocation)
{
case Location.Center:
{
firstLineX = ChartInfo.PriceChartContainer.Region.Width / 2 - mainTextRectangle.Width / 2 + HorizontalOffset;
secondLineX = ChartInfo.PriceChartContainer.Region.Width / 2 - additionalTextRectangle.Width / 2 + HorizontalOffset;
y = ChartInfo.PriceChartContainer.Region.Height / 2 - totalHeight / 2 + VerticalOffset;
break;
}
case Location.TopLeft:
{
firstLineX = secondLineX = HorizontalOffset;
break;
}
case Location.TopRight:
{
firstLineX = ChartInfo.PriceChartContainer.Region.Width - mainTextRectangle.Width + HorizontalOffset;
secondLineX = ChartInfo.PriceChartContainer.Region.Width - additionalTextRectangle.Width + HorizontalOffset;
break;
}
case Location.BottomLeft:
{
firstLineX = secondLineX = HorizontalOffset;
y = ChartInfo.PriceChartContainer.Region.Height - totalHeight + VerticalOffset;
break;
}
case Location.BottomRight:
{
firstLineX = ChartInfo.PriceChartContainer.Region.Width - mainTextRectangle.Width + HorizontalOffset;
secondLineX = ChartInfo.PriceChartContainer.Region.Width - additionalTextRectangle.Width + HorizontalOffset;
y = ChartInfo.PriceChartContainer.Region.Height - totalHeight + VerticalOffset;
break;
}
default:
throw new ArgumentOutOfRangeException();
}
context.DrawString(firstLine, Font.Font, textColor, firstLineX, y);
context.DrawString(AdditionalText, AdditionalFont.Font, textColor, secondLineX, y + mainTextRectangle.Height + AdditionalTextYOffset);
}
else if (mainTextRectangle.Height > 0)
{
DrawString(context, firstLine, Font.Font, textColor, mainTextRectangle);
}
else if (additionalTextRectangle.Height > 0)
{
DrawString(context, AdditionalText, AdditionalFont.Font, textColor, additionalTextRectangle);
}
}
private void DrawString(RenderContext context, string text, RenderFont font, System.Drawing.Color color, Rectangle rectangle)
{
switch (TextLocation)
{
case Location.Center:
{
context.DrawString(text, font, color, ChartInfo.PriceChartContainer.Region.Width / 2 - rectangle.Width / 2 + HorizontalOffset,
ChartInfo.PriceChartContainer.Region.Height / 2 - rectangle.Height / 2 + VerticalOffset);
break;
}
case Location.TopLeft:
{
context.DrawString(text, font, color, HorizontalOffset, VerticalOffset);
break;
}
case Location.TopRight:
{
context.DrawString(text, font, color, ChartInfo.PriceChartContainer.Region.Width - rectangle.Width + HorizontalOffset, VerticalOffset);
break;
}
case Location.BottomLeft:
{
context.DrawString(text, font, color, HorizontalOffset, ChartInfo.PriceChartContainer.Region.Height - rectangle.Height + VerticalOffset);
break;
}
case Location.BottomRight:
{
context.DrawString(text, font, color, ChartInfo.PriceChartContainer.Region.Width - rectangle.Width + HorizontalOffset,
ChartInfo.PriceChartContainer.Region.Height - rectangle.Height + VerticalOffset);
break;
}
default:
throw new ArgumentOutOfRangeException();
}
}
#endregion
}
}
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article