Add Tooltip for Chart Objects

Created at 01 May 2019, 08:56
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
afhacker's avatar

afhacker

Joined 15.10.2015

Add Tooltip for Chart Objects
01 May 2019, 08:56


All chart objects must have a tooltip property, so whenever the user moves the mouse over the object it should show that tooltip which is provided programmatically.

It's a very important and easy to implement feature please add it ASAP.


cTrader Automate
@afhacker
Replies

PanagiotisCharalampous
04 Nov 2019, 15:54

Hi AlgoDeveloper,

You might find the below example useful

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class CustomTooltip : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        private Tooltip Tooltip;
        private double LastMouseX;
        private double LastMouseY;

        protected override void OnStart()
        {
            Tooltip = new Tooltip 
            {
                VerticalAlignment = VerticalAlignment.Top,
                HorizontalAlignment = HorizontalAlignment.Left,
                IsVisible = false,
                Width = 120,
                Height = 40
            };
            Chart.AddControl(Tooltip);

            Chart.ObjectHoverChanged += Chart_ObjectHoverChanged;
            Chart.MouseMove += Chart_MouseMove;
        }

        private void Chart_MouseMove(ChartMouseEventArgs obj)
        {
            LastMouseX = obj.MouseX;
            LastMouseY = obj.MouseY;

            if (Tooltip.IsVisible)
                UpdateTooltipCoorinates();
        }

        private void Chart_ObjectHoverChanged(ChartObjectHoverChangedEventArgs obj)
        {
            if (obj.IsObjectHovered)
                ShowTooltip(obj.ChartObject.Name);
            else
                HideTooltip();
        }

        private void ShowTooltip(string text)
        {
            Tooltip.IsVisible = true;
            Tooltip.Text = text;
            UpdateTooltipCoorinates();
        }

        private void UpdateTooltipCoorinates()
        {

            var extraDelta = 10;
            var width = Tooltip.Width;
            var height = Tooltip.Height;
            var left = Chart.Width - LastMouseX > width + extraDelta ? LastMouseX + extraDelta : LastMouseX - width - extraDelta;
            var right = Chart.Height - LastMouseY > height + extraDelta ? LastMouseY + extraDelta : LastMouseY - height - extraDelta;

            Tooltip.Margin = new Thickness(left, right, 0, 0);
        }

        private void HideTooltip()
        {
            Tooltip.IsVisible = false;
        }

        protected override void OnTick()
        {
            // Put your core logic here
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }

    public class Tooltip : CustomControl
    {
        public Tooltip()
        {
            var border = new Border 
            {
                BackgroundColor = "#3F3F3F",
                BorderColor = "#969696",
                BorderThickness = 1,
                CornerRadius = 5
            };

            ContentLabel = new TextBlock 
            {
                Margin = 5
            };

            border.Child = ContentLabel;
            AddChild(border);
        }

        private TextBlock ContentLabel { get; set; }

        public string Text
        {
            get { return ContentLabel.Text; }
            set { ContentLabel.Text = value; }
        }


    }
}

Best Regards,

Panagiotis


@PanagiotisCharalampous

afhacker
04 Nov 2019, 20:09

That's awesome! and very helpful.


@afhacker

afhacker
05 Nov 2019, 12:16

Production-ready tooltip control for chart objects (Not controls and for now, it only works if the chart object is interactive):

namespace cAlgo.API.Extensions.Controls
{
    public class ChartObjectTooltip : CustomControl
    {
        #region Fields

        private readonly Border _border;

        private readonly Chart _chart;

        private readonly ChartObject _chartObject;

        private double _lastMouseX, _lastMouseY;

        #endregion Fields

        public ChartObjectTooltip(Chart chart, ChartObject chartObject)
        {
            _chart = chart;
            _chartObject = chartObject;

            _border = new Border
            {
                BackgroundColor = "#3F3F3F",
                BorderColor = "#969696",
                BorderThickness = 1,
                CornerRadius = 5
            };

            AddChild(_border);

            _chart.ObjectHoverChanged += Chart_ObjectHoverChanged;
            _chart.MouseMove += Chart_MouseMove;
        }

        #region Properties

        public Color BackgroundColor
        {
            get
            {
                return _border.BackgroundColor;
            }
            set
            {
                _border.BackgroundColor = value;
            }
        }

        public Color BorderColor
        {
            get
            {
                return _border.BorderColor;
            }
            set
            {
                _border.BorderColor = value;
            }
        }

        public Thickness BorderThickness
        {
            get
            {
                return _border.BorderThickness;
            }
            set
            {
                _border.BorderThickness = value;
            }
        }

        public CornerRadius CornerRadius
        {
            get
            {
                return _border.CornerRadius;
            }
            set
            {
                _border.CornerRadius = value;
            }
        }

        public ControlBase Content
        {
            get
            {
                return _border.Child;
            }
            set
            {
                _border.Child = value;
            }
        }

        #endregion Properties

        #region Methods

        private void Chart_ObjectHoverChanged(ChartObjectHoverChangedEventArgs obj)
        {
            if (obj.IsObjectHovered && obj.ChartObject == _chartObject)
            {
                UpdateCoorinates();

                IsVisible = true;
            }
            else
            {
                IsVisible = false;
            }
        }

        private void Chart_MouseMove(ChartMouseEventArgs obj)
        {
            _lastMouseX = obj.MouseX;
            _lastMouseY = obj.MouseY;

            if (IsVisible)
            {
                UpdateCoorinates();
            }
        }

        private void UpdateCoorinates()
        {
            var extraDelta = 10;
            var width = Width;
            var height = Height;
            var left = _chart.Width - _lastMouseX > width + extraDelta ? _lastMouseX + extraDelta : _lastMouseX - width - extraDelta;
            var right = _chart.Height - _lastMouseY > height + extraDelta ? _lastMouseY + extraDelta : _lastMouseY - height - extraDelta;

            Margin = new Thickness(left, right, 0, 0);
        }

        #endregion Methods
    }
}

 


@afhacker

snowchilli
13 Nov 2019, 02:55

RE:

Panagiotis Charalampous said:

Hi AlgoDeveloper,

You might find the below example useful

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class CustomTooltip : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        private Tooltip Tooltip;
        private double LastMouseX;
        private double LastMouseY;

        protected override void OnStart()
        {
            Tooltip = new Tooltip 
            {
                VerticalAlignment = VerticalAlignment.Top,
                HorizontalAlignment = HorizontalAlignment.Left,
                IsVisible = false,
                Width = 120,
                Height = 40
            };
            Chart.AddControl(Tooltip);

            Chart.ObjectHoverChanged += Chart_ObjectHoverChanged;
            Chart.MouseMove += Chart_MouseMove;
        }

        private void Chart_MouseMove(ChartMouseEventArgs obj)
        {
            LastMouseX = obj.MouseX;
            LastMouseY = obj.MouseY;

            if (Tooltip.IsVisible)
                UpdateTooltipCoorinates();
        }

        private void Chart_ObjectHoverChanged(ChartObjectHoverChangedEventArgs obj)
        {
            if (obj.IsObjectHovered)
                ShowTooltip(obj.ChartObject.Name);
            else
                HideTooltip();
        }

        private void ShowTooltip(string text)
        {
            Tooltip.IsVisible = true;
            Tooltip.Text = text;
            UpdateTooltipCoorinates();
        }

        private void UpdateTooltipCoorinates()
        {

            var extraDelta = 10;
            var width = Tooltip.Width;
            var height = Tooltip.Height;
            var left = Chart.Width - LastMouseX > width + extraDelta ? LastMouseX + extraDelta : LastMouseX - width - extraDelta;
            var right = Chart.Height - LastMouseY > height + extraDelta ? LastMouseY + extraDelta : LastMouseY - height - extraDelta;

            Tooltip.Margin = new Thickness(left, right, 0, 0);
        }

        private void HideTooltip()
        {
            Tooltip.IsVisible = false;
        }

        protected override void OnTick()
        {
            // Put your core logic here
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }

    public class Tooltip : CustomControl
    {
        public Tooltip()
        {
            var border = new Border 
            {
                BackgroundColor = "#3F3F3F",
                BorderColor = "#969696",
                BorderThickness = 1,
                CornerRadius = 5
            };

            ContentLabel = new TextBlock 
            {
                Margin = 5
            };

            border.Child = ContentLabel;
            AddChild(border);
        }

        private TextBlock ContentLabel { get; set; }

        public string Text
        {
            get { return ContentLabel.Text; }
            set { ContentLabel.Text = value; }
        }


    }
}

Best Regards,

Panagiotis

Building the above code (as is) gives me 3 errors
Error CS0246: The type or namespace name 'CustomControl' could not be found (are you missing a using directive or an assembly reference?)

Error CS0122: 'cAlgo.API.TextBlock' is inaccessible due to its protection level

Error CS0053: Inconsistent accessibility: property type 'cAlgo.API.TextBlock' is less accessible than property 'cAlgo.Robots.Tooltip.ContentLabel'

Am I missing references? What else am I missing?


@snowchilli

PanagiotisCharalampous
13 Nov 2019, 09:05

Hi snowchilli,

Thank you for posting in our forum. Do you use v3.6 to build this cBot?

Best Regards,

Panagiotis


@PanagiotisCharalampous

noppanon
09 Apr 2021, 11:46

RE:

PanagiotisCharalampous said:

Hi AlgoDeveloper,

You might find the below example useful

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class CustomTooltip : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        private Tooltip Tooltip;
        private double LastMouseX;
        private double LastMouseY;

        protected override void OnStart()
        {
            Tooltip = new Tooltip 
            {
                VerticalAlignment = VerticalAlignment.Top,
                HorizontalAlignment = HorizontalAlignment.Left,
                IsVisible = false,
                Width = 120,
                Height = 40
            };
            Chart.AddControl(Tooltip);

            Chart.ObjectHoverChanged += Chart_ObjectHoverChanged;
            Chart.MouseMove += Chart_MouseMove;
        }

        private void Chart_MouseMove(ChartMouseEventArgs obj)
        {
            LastMouseX = obj.MouseX;
            LastMouseY = obj.MouseY;

            if (Tooltip.IsVisible)
                UpdateTooltipCoorinates();
        }

        private void Chart_ObjectHoverChanged(ChartObjectHoverChangedEventArgs obj)
        {
            if (obj.IsObjectHovered)
                ShowTooltip(obj.ChartObject.Name);
            else
                HideTooltip();
        }

        private void ShowTooltip(string text)
        {
            Tooltip.IsVisible = true;
            Tooltip.Text = text;
            UpdateTooltipCoorinates();
        }

        private void UpdateTooltipCoorinates()
        {

            var extraDelta = 10;
            var width = Tooltip.Width;
            var height = Tooltip.Height;
            var left = Chart.Width - LastMouseX > width + extraDelta ? LastMouseX + extraDelta : LastMouseX - width - extraDelta;
            var right = Chart.Height - LastMouseY > height + extraDelta ? LastMouseY + extraDelta : LastMouseY - height - extraDelta;

            Tooltip.Margin = new Thickness(left, right, 0, 0);
        }

        private void HideTooltip()
        {
            Tooltip.IsVisible = false;
        }

        protected override void OnTick()
        {
            // Put your core logic here
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }

    public class Tooltip : CustomControl
    {
        public Tooltip()
        {
            var border = new Border 
            {
                BackgroundColor = "#3F3F3F",
                BorderColor = "#969696",
                BorderThickness = 1,
                CornerRadius = 5
            };

            ContentLabel = new TextBlock 
            {
                Margin = 5
            };

            border.Child = ContentLabel;
            AddChild(border);
        }

        private TextBlock ContentLabel { get; set; }

        public string Text
        {
            get { return ContentLabel.Text; }
            set { ContentLabel.Text = value; }
        }


    }
}

Best Regards,

Panagiotis

 

Hi Panagiotis,

   I'm using the latest cTrader 4.0.   On your sample, I found that event ObjectHoverChanged does not fired, but MouseMove does fired. Is there anything missing?

Regards,

Noppanon

 


@noppanon

PanagiotisCharalampous
09 Apr 2021, 11:59

Hi Noppanon,

How did you come to this conclusion? It works fine for me.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous