Watermark

Modified on Fri, 04 Aug 2023 at 01:59 PM

Sample of indicator which shows watermark on the chart


Image 13521

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

Let us know how can we improve this article!

Select atleast one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article