Can I format text in tooltips / render my own tooltip?


https://www.nevron.com/Forum/Topic12343.aspx
Print Topic | Close Window

By Kevin Harrison - 6 Years Ago
Hi

We have a new requirement to create formatted tooltips rather than simple multi-line unformatted text.
Is this possible? It looks like the current tooltip can only be plain text.

Can I hook into a Mouse Hover event somehow and render my own tooltip with formatted text, configurable borders, drop shadow, background colour etc.?

Thanks
Kevin
By Nevron Support - 6 Years Ago
Hi Kevin,

In this case you'll need to implement your own custom tooltip tool. Following is the source code of the standard build in tool for reference:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Xml.Serialization;
using Nevron.GraphicsCore;
using Nevron.Reflection;
using Nevron.Chart.View;

namespace Nevron.Chart.Windows
{
 /// <summary>
 /// When present in the Tools collection instructs the
 /// control to display tooltips for the chart elements that have an
 /// assigned tooltip.
 /// </summary>
 [Serializable]
 [ClassInterface(ClassInterfaceType.AutoDual)]
 [NIcon("Resources.Icons.Tools.Tooltip.png")]
 public partial class NTooltipTool : NInteractivityTool,
        IDisposable
 {
  #region Constructors

  /// <summary>
  /// Creates a new NTooltipTool object with default settings.
  /// </summary>
  /// <remarks>
  /// This constructor sets AutoPopDelay to 5000ms, InitialDelay to 500ms
  /// and Reshow delay to 100ms.
  /// </remarks>
  public NTooltipTool()
  {
   m_nAutoPopDelay = defaultAutoPopDelay;
   m_nInitialDelay = defaultInitialDelay;
   m_nReshowDelay = defaultReshowDelay;
  }

  #endregion

  #region Properties

  /// <summary>
  /// Controls the period of time the tooltips remain visible if the
  /// mouse pointer is stationary within the chart.
  /// </summary>
  /// <remarks>
  /// This property enables you to shorten or lengthen the time that the
  /// tooltip window is displayed when the mouse pointer is over a control.
  /// For example, if you display extensive help in a tooltip window, you
  /// can increase the value of this property to ensure that the user has
  /// sufficient time to read the text.
  /// </remarks>
  [Category("Tooltips"), Description("Controls the period of time the tooltips remain visible if the mouse pointer is stationary within the chart.")]
  [DefaultValue(defaultAutoPopDelay)]
  [XmlAttribute]
  public int AutoPopDelay
  {
   get
   {
    return m_nAutoPopDelay;
   }
   set
   {
    m_nAutoPopDelay = value;
   }
  }
  /// <summary>
  /// Gets or sets the time that passes before the tooltip appears.
  /// </summary>
  /// <remarks>
  /// This property enables you to shorten or lengthen the time that the
  /// chart control waits before displaying a tooltip window. If the value
  /// of the InitialDelay property is set to a value that is too long
  /// in duration, the user of your application may not know that your
  /// application provides tooltip help. You can use this property to
  /// ensure that the user has tooltips displayed quickly by shortening
  /// the time specified.
  /// </remarks>
  [Category("Tooltips"), Description("Gets or sets the time that passes before the tooltip appears.")]
  [DefaultValue(defaultInitialDelay)]
  [XmlAttribute]
  public int InitialDelay
  {
   get
   {
    return m_nInitialDelay;
   }
   set
   {
    m_nInitialDelay = value;
   }
  }
  /// <summary>
  /// Gets or sets the length of time that must transpire before subsequent
  /// tooltip windows appear as the mouse pointer moves from one chart
  /// element to another.
  /// </summary>
  /// <remarks>
  /// This property enables you to shorten or lengthen the time that the
  /// tooltip waits before displaying a tooltip window after a previous
  /// tooltip window is displayed. The first time a tooltip window is
  /// displayed the value of the InitialDelay property is used to determine
  /// the delay to apply before initially showing the tooltip window. When
  /// a tooltip window is currently being displayed and the user moves the
  /// cursor to another chart element or control that displays a tooltip
  /// window, the value of the ReshowDelay property is used before showing
  /// the tooltip for the new control. The tooltip window from the previous
  /// control must still be displayed in order for the delay specified in
  /// the ReshowDelay property to be used; otherwise the InitialDelay
  /// property value is used.
  /// </remarks>
  [Category("Tooltips"), Description("Gets or sets the time that must transpire before subsequent tooltip windows appear.")]
  [DefaultValue(defaultReshowDelay)]
  [XmlAttribute]
  public int ReshowDelay
  {
   get
   {
    return m_nReshowDelay;
   }
   set
   {
    m_nReshowDelay = value;
   }
  }

  #endregion

  #region Overrides

  public override void OnMouseMove(object sender, NMouseEventArgs e)
  {
            NPointF mousePosition = new NPointF(e.X, e.Y);
            SetTooltip(mousePosition, GetTooltipFromPoint(mousePosition));
  }

  #endregion

        #region Interface implementations

        #region IDisposable

        public void Dispose()
  {
   ClearTooltip();
  }

  #endregion

  #region INReferenceHolder

  [EditorBrowsable(EditorBrowsableState.Never)]
  public override void UpdateReferences(INReferenceProvider provider)
  {
   // when removed from the collection clear the tooltip
            if (m_Provider != null)
            {
                ClearTooltip();
            }

   base.UpdateReferences(provider);
  }

  #endregion

  #endregion

  #region Implementation

  /// <summary>
  /// Gets the tooltip from the specified mouse position
  /// </summary>
  /// <param name="mousePosition"></param>
  /// <returns></returns>
  public virtual string GetTooltipFromPoint(NPointF mousePosition)
  {
   NInteractivityStyle interactivityStyle = GetInteractivityStyleFromPoint(mousePosition);
 
   if (interactivityStyle == null)
    return "";

   NTooltipAttribute tooltipAttribute = (NTooltipAttribute)interactivityStyle.FindAttributeOfType(typeof(NTooltipAttribute));

   if (tooltipAttribute == null)
    return "";

   NHitTestCacheService hitTestService = GetView().GetServiceOfType(typeof(NHitTestCacheService)) as NHitTestCacheService;

   if (hitTestService == null)
   {
    Debug.Assert(false);
    return "";
   }

   INTooltipFormatter tooltipFormatter = hitTestService.HitTest(mousePosition) as INTooltipFormatter;

   if (tooltipFormatter == null)
   {
    return tooltipAttribute.Text;
   }

   return tooltipFormatter.FormatTooltip(tooltipAttribute.Text);
  }

  protected virtual void SetTooltip(NPointF mousePosition, string tooltip)
  {
            GetView().SetTooltip(mousePosition, tooltip, this);
  }

        protected virtual void ClearTooltip()
  {
   NView view = GetView();

   if (view != null)
   {
    view.ClearTooltip();
   }
  }

  #endregion

  #region Fields

  protected int m_nAutoPopDelay;
  protected int m_nInitialDelay;
  protected int m_nReshowDelay;

  #endregion

  #region Default values

  protected const int defaultAutoPopDelay = 5000;
  protected const int defaultInitialDelay = 500;
  protected const int defaultReshowDelay = 100;

  #endregion
 }
}

Let us know if you meet any problems.
By Eli Gazit - 6 Years Ago
Hi,
I am trying to do a similar thing - show HTML tooltip instead of plain text.
I could not understand from your sample above how to obtain the user-control that hosts the tooltip and replace it with my own control.
please advise.

By Nevron Support - 6 Years Ago
Hi Eli,
The following code shows how to override the standard tooltip tool so that it shows a formatted label dynamically. In the next version we'll extend the control to support this as a build in feature:
using Nevron.Chart;
using Nevron.Chart.Windows;
using Nevron.Chart.WinForm;
using Nevron.GraphicsCore;
using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

[Serializable]
class NCustomTooltipTool : NTooltipTool
{
public NCustomTooltipTool(NChartControl chartControl)
{
m_ChartControl = chartControl;

m_TimerHide = new Timer();
m_TimerHide.Tick += OnTimerHideTick;
m_TimerHide.Interval = 2000;

m_TimerShow = new Timer();
m_TimerShow.Tick += OnTimerShowTick;
m_TimerShow.Interval = 1000;
}

private void OnTimerHideTick(object sender, EventArgs e)
{
m_TimerHide.Stop();
ClearTooltip();
}

private void OnTimerShowTick(object sender, EventArgs e)
{
if (m_Label == null)
{
m_Label = new NLabel();
m_Label.TextStyle.TextFormat = TextFormat.XML;
m_Label.UseAutomaticSize = true;
m_ChartControl.Panels.Add(m_Label);
}

m_Label.Text = m_RequestTooltip;
m_PrevShownTooltip = m_RequestTooltip;
m_Label.Location = new NPointL(new NLength((int)m_MousePosition.X, NGraphicsUnit.Pixel), new NLength((int)m_MousePosition.Y, NGraphicsUnit.Pixel));
m_ChartControl.Refresh();
m_TimerHide.Start();
}

protected override void SetTooltip(NPointF mousePosition, string tooltip)
{
if (m_PrevShownTooltip == tooltip)
{
return;
}

if (m_RequestTooltip == tooltip)
{
m_TimerShow.Stop();
m_TimerShow.Start();
m_MousePosition = mousePosition;
return;
}

m_RequestTooltip = tooltip;
}

protected override void ClearTooltip()
{
if (m_Label != null)
{
m_TimerShow.Stop();

m_Label.ParentPanel.ChildPanels.Remove(m_Label);
m_Label = null;
m_ChartControl.Refresh();
}
}

NChartControl m_ChartControl;
NLabel m_Label;
Timer m_TimerShow;
Timer m_TimerHide;
string m_PrevShownTooltip;
string m_RequestTooltip;
NPointF m_MousePosition;
}

private void Form1_Load(object sender, EventArgs e)
{
NCartesianChart chart = (NCartesianChart)nChartControl1.Charts[0];
NBarSeries bar = new NBarSeries();

bar.Values.Add(10);
bar.InteractivityStyles.Add(0, new NInteractivityStyle("Bar <b>1</b>"));
bar.Values.Add(20);
bar.InteractivityStyles.Add(1, new NInteractivityStyle("Bar <b>2</b>"));
bar.Values.Add(30);
bar.InteractivityStyles.Add(2, new NInteractivityStyle("Bar <b>3</b>"));

chart.Series.Add(bar);

nChartControl1.Controller.Tools.Add(new NCustomTooltipTool(nChartControl1));
}
}
}
Hope this helps - let us know if you meet any problems or have any questions.
By Eli Gazit - 6 Years Ago
Hello, any news?
By Nevron Support - 6 Years Ago
Hello Eli,
We still haven't released the new version. This will most likely happen at the end of August...