Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Draggable plot data-tips

October 23, 2013 6 Comments

A couple of years ago, I was asked by a client to figure out a way to make Matlab plot data-tips movable. The problem was that he had a very crowded plot and Matlab’s standard data-tips are displayed immediately adjacent to the data, thereby overlapping the plot parts. Matlab’s standard data-tips enable dragging to a very limited extent (only to the 4 corners of the data-point), and in any case the displayed textbox remains directly attached to the data point.
So I developed a small utility for my client that solves this problem. I then forgot all about it until a few days ago when I came across it again. Yesterday I uploaded this draggableDataTips utility to the File Exchange, where you can download it.
draggableDataTips enables the user to interactively drag any newly-created data-tip, anywhere in the Matlab figure. A dashed line connects the dragged data-tip with the original data point. Simple, intuitive, and effective. At 300 lines, the draggableDataTips.m source code is compact and easy to follow, and you’re welcome to take a look and further customize this utility for your specific needs.

draggableDataTips utility in action
draggableDataTips utility in action

Technical implementation

The implementation of draggableDataTips relies on undocumented aspects of the data-cursor object exposed via the datacursormode function. I have already shown how these can be used to customize and control data-tips programmatically (rather than interactively). For draggableDataTips, we first get the cursor object’s meta-data classhandle (a schema.class object), then use it to find the meta-data for its hidden CurrentDataCursor property (a schema.prop object). There is also a more direct approach, using the findprop function.
Whichever alternative we choose, we finally use this object to set the property’s SetFunction meta-property. Quite straight-forward, I should say:

% Get the cursor-mode object
cursorObj = datacursormode(hFig);
% Alternative #1: the indirect route to the meta-property
ch = classhandle(cursorObj);
hPropIdx = strcmpi(get(ch.Properties,'Name'), 'CurrentDataCursor');
hProp = ch.Properties(hPropIdx);
% Alternative #2: the direct approach
hProp = findprop(cursorObj, 'CurrentDataCursor');
% Update the meta-property to use a custom function whenever new data-tips are created
hProp.SetFunction = @installNewMoveFcn;

% Get the cursor-mode object cursorObj = datacursormode(hFig); % Alternative #1: the indirect route to the meta-property ch = classhandle(cursorObj); hPropIdx = strcmpi(get(ch.Properties,'Name'), 'CurrentDataCursor'); hProp = ch.Properties(hPropIdx); % Alternative #2: the direct approach hProp = findprop(cursorObj, 'CurrentDataCursor'); % Update the meta-property to use a custom function whenever new data-tips are created hProp.SetFunction = @installNewMoveFcn;

This has the effect that all new data-tips that will be created from then on will call our custom installNewMoveFcn function when the data-tip object is created. This installNewMoveFcn function, in turn, simply replaces the data-tips standard default callback for mouse movement (which is used while dragging), to a new custom function textBoxUpdateFcn:

% Install a replacement callback function for datatip textbox mouse movement
function hDataTip = installNewMoveFcn(cursorObj, hDataTip)
    srcObjs = get(hDataTip.SelfListenerHandles,'SourceObject');
    for srcIdx = 1 : length(srcObjs)
        if strcmpi(srcObjs{srcIdx}.Name,'Orientation')
            hDataTip.SelfListenerHandles(srcIdx).Callback = @textBoxUpdateFcn;
            hDataTip.MarkerHandle.Marker = 'none';
            break;
        end
    end
end

% Install a replacement callback function for datatip textbox mouse movement function hDataTip = installNewMoveFcn(cursorObj, hDataTip) srcObjs = get(hDataTip.SelfListenerHandles,'SourceObject'); for srcIdx = 1 : length(srcObjs) if strcmpi(srcObjs{srcIdx}.Name,'Orientation') hDataTip.SelfListenerHandles(srcIdx).Callback = @textBoxUpdateFcn; hDataTip.MarkerHandle.Marker = 'none'; break; end end end

The textBoxUpdateFcn function basically moves the datatip textbox to the new mouse location, without limiting its positions as Matlab’s standard default callback function did. A dashed connector line is then drawn to connect the center of the textbox with the data-point. It’s a bit long to include here, but interested readers are welcome to look at the code (lines #99 onward in draggableDataTips.m).
As can be seen from the screenshot above, standard and draggable data-tips can be used in the same plot. This is done by simply turning the draggability functionality on and off by draggableDataTips before creating a new data-tip (using either alt-click or programmatically):

draggableDataTips on    % or: draggableDataTips('on')  or: draggableDataTips(true)
draggableDataTips off   % or: draggableDataTips('off') or: draggableDataTips(false)

draggableDataTips on % or: draggableDataTips('on') or: draggableDataTips(true) draggableDataTips off % or: draggableDataTips('off') or: draggableDataTips(false)

Notes:

  1. The actual code of draggableDataTips naturally contains more sanity checks, exception handling etc. I have only presented the core code in the snippets above, but you should always include such extra checks in any real-life program.
  2. There is a minor bug that causes the connector line to be on top of the box rather than beneath it, but aside from this all works ok. For some reason, uistack did not work. If anyone has a fix for this bug, please let me know.
  3. Did you notice that Java was not mentioned anywhere above? Mode managers, such as the data-cursor mode, use pure-Matlab functionality.

HG2

Unfortunately, when I tested draggableDataTips on HG2, Matlab’s upcoming new graphics engine, the utility failed. Data-cursors have undergone a significant reengineering in HG2 (about time!), causing multiple properties and methods to change names and functionality. But this could be overcome (see lines #43-53 in draggableDataTips.m).
However, I could not overcome the apparent fact that unlike HG1 (or more specifically, schema objects, that HG1 uses for its data-tips functionality), in HG2 (or rather, MCOS class objects) we cannot override an object’s meta-properties, specifically its SetMethod (which is the MCOS equivalent of schema.prop‘s SetFunction meta-property).
So for the moment, draggableDataTips does not work on HG2. I hope to find a solution for this by the time HG2 launches. If anyone finds a fix for the problem, please let me know. If I ever find or receive a fix, I will update this post with the relevant technical details.
For the moment there is no rush, since HG2 is still relatively far away in the distant future, and draggableDataTips works splendidly in the current HG1.
Have you used plot data-tips in some nifty way? If so, please share your experience in a comment below.

Related posts:

  1. Controlling plot data-tips – Data-tips are an extremely useful plotting tool that can easily be controlled programmatically....
  2. Accessing plot brushed data – Plot data brushing can be accessed programmatically using very simple pure-Matlab code...
  3. Undocumented scatter plot jitter – Matlab's scatter plot can automatically jitter data to enable better visualization of distribution density. ...
  4. Plot LimInclude properties – The plot objects' XLimInclude, YLimInclude, ZLimInclude, ALimInclude and CLimInclude properties are an important feature, that has both functional and performance implications....
  5. Plot markers transparency and color gradient – Matlab plot-line markers can be customized to have transparency and color gradients. ...
  6. Undocumented plot marker types – Undocumented plot marker styles can easily be accesses using a hidden plot-line property. ...
Handle graphics HG2 Hidden property Pure Matlab schema.class schema.prop Undocumented feature
Print Print
« Previous
Next »
6 Responses
  1. Werner October 23, 2013 at 20:40 Reply

    You are amazing… as soon as I finish my master and hopefully start earning some money, I will gladly buy you some cups of coffee. xD

    And yes, I had the same issue when using customized datatips with HG2 (I used your older post information on this topic available here).

  2. Ortmann February 24, 2015 at 07:13 Reply

    Wow…it just works.

    Thank you so much!

  3. Patricio September 10, 2015 at 13:10 Reply

    worked like magic. Thanks a lot!

  4. Simon September 23, 2015 at 01:12 Reply

    Hi Yair!

    Thanks for this great piece of code! It works perfectly.

    I have a question concerning the customization of the data-tips: I’d like to give the user the ability to define the line style and the marker at the data-point position. I know I can change it in the code directly. But I’d rather like to give both settings as additional inputs to draggableDataTips. The only thing is I don’t know where to store this information in order to access it in functions installNewMoveFcn and updateConnectorLine. Do you have a hint?

    Thanks in advance!

    Best regards, Simon

  5. SVee August 5, 2016 at 20:33 Reply

    Hi,

    Nice tricks.
    Any chance it could work on HG2 by using the method described in http://undocumentedmatlab.com/blog/accessing-private-object-properties or am I wasting my time trying?

    Cheers,

    • Yair Altman August 6, 2016 at 20:40 Reply

      @SVee – it’s definitely worth a shot, you’re not wasting your time. Let us all know if you discover anything useful.

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitable (6) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top