Adding a context-menu to a uitree

A CSSM poster asked a few days ago whether it was possible to add a context (right-click) menu to uitree nodes. Uitree is an internal, undocumented and unsupported Matlab function, which does not enable easy setting of a uicontextmenu like its uicontrol relatives.

However, using some undocumented Java magic, it is possible to do so. Being undocumented and unsupported, this solution might break in future releases, although this is unlikely since it relies on some very basic Java functionality that is unlikely to be broken soon.

Note that the context-menu in the following example uses HTML formatting. As explained in an earlier post, all Swing components (and by extension, most Matlab uicontrols) support HTML formatting.

% Prepare the context menu (note the use of HTML labels)
menuItem1 = javax.swing.JMenuItem('action #1');
menuItem2 = javax.swing.JMenuItem('<html><b>action #2');
menuItem3 = javax.swing.JMenuItem('<html><i>action #3');

% Set the menu items' callbacks
set(menuItem1,'ActionPerformedCallback',@myFunc1);
set(menuItem2,'ActionPerformedCallback',{@myfunc2,data1,data2});
set(menuItem3,'ActionPerformedCallback','disp ''action #3...'' ');

% Add all menu items to the context menu (with internal separator)
jmenu = javax.swing.JPopupMenu;
jmenu.add(menuItem1);
jmenu.add(menuItem2);
jmenu.addSeparator;
jmenu.add(menuItem3);

% Set the tree mouse-click callback
% Note: MousePressedCallback is better than MouseClickedCallback
%       since it fires immediately when mouse button is pressed,
%       without waiting for its release, as MouseClickedCallback does
set(jtree, 'MousePressedCallback', {@mousePressedCallback,jmenu});

% Set the mouse-press callback
function mousePressedCallback(hTree, eventData, jmenu)
   if eventData.isMetaDown  % right-click is like a Meta-button
      % Get the clicked node
      clickX = eventData.getX;
      clickY = eventData.getY;
      jtree = eventData.getSource;
      treePath = jtree.getPathForLocation(clickX, clickY);
      try
         % Modify the context menu or some other element
         % based on the clicked node. Here is an example:
         node = treePath.getLastPathComponent;
         nodeName = ['Current node: ' char(node.getName)];
         item = jmenu.add(nodeName);

         % remember to call jmenu.remove(item) in item callback
         % or use the timer hack shown here to remove the item:
         timerFcn = {@removeItem,jmenu,item};
         start(timer('TimerFcn',timerFcn,'StartDelay',0.2));
      catch
         % clicked location is NOT on top of any node
         % Note: can also be tested by isempty(treePath)
      end

      % Display the (possibly-modified) context menu
      jmenu.show(jtree, clickX, clickY);
      jmenu.repaint;
   end
end

% Remove the extra context menu item after display
function removeItem(hObj,eventData,jmenu,item)
   jmenu.remove(item);
end

% Menu items callbacks must receive at least 2 args:
% hObject and eventData – user-defined args follow after these two
function myfunc1(hObject, eventData)
   % ... 

function myFunc2(hObject, eventData, myData1, myData2)
    % ... 

uitree node-specific context-menu

uitree node-specific context-menu
(note the HTML formatting of menu items)

If the issue of undocumented Matlab interests you, please review the list of future post topics and let me know if you have any preference, or would like to see some other (unlisted) topics.

Yair

Related posts:

  1. Customizing Workspace context-menu Matlab's Workspace table context-menu can be configured with user-defined actions - this article explains how....
  2. Customizing menu items part 2 Matlab menu items can be customized in a variety of useful ways using their underlying Java object. ...
  3. uitree This article describes the undocumented Matlab uitree function, which displays data in a GUI tree component...
  4. Customizing uitree nodes – part 2 This article shows how Matlab GUI tree nodes can be customized with checkboxes and similar controls...
  5. Customizing menu items part 3 Matlab menu items can easily display custom icons, using just a tiny bit of Java magic powder. ...
  6. Customizing uitree nodes – part 1 This article describes how to customize specific nodes of Matlab GUI tree controls created using the undocumented uitree function...

Categories: GUI, Java, Low risk of breaking in future versions, UI controls

Tags: , ,

Bookmark and Share Print Print

12 Responses to Adding a context-menu to a uitree

  1. Darik Gamble says:

    Yair,

    I’m glad to see you’ve got a blog — I remember learning from your newsgroup posts a couple years ago that I could add custom properties and event listeners to handle graphics objects, and both features have helped me immensely (and made it into the Matlab documention!)

    My votes on your to do list include customizing menus and the two schema topics.

    Cheers,

    dg

  2. Venky says:

    Yair,
    It’s interesting to know that it is possible to add uicontextmenus to uitree.
    Your post saved my time.
    Thanks a lot

  3. Scott Koch says:

    If you have access to the figure handle (stored as User Data for instance) you could also use the click event coordinates to display a GUIDE created context menu:

    ...
    if eventData.isMetaDown
      fh = get(hTree,'UserData');%Get figure handle
      cm = findobj(fh,'tag','mycontextmenu');%Get context menu handle.
      tpos = get(hTree,'PixelPosition');
     
      set(cm,'position',[eventData.getX()+tpos(1) (tpos(4)-eventData.getY)+tpos(2)],'Visible','on');
     
    ...
  4. Pingback: Setting listbox mouse actions | Undocumented Matlab

  5. Bass says:

    Awesome article.

    I was looking for something that would allow me to create a right click context menu for any figure or uitable.

    When I use similar code (see below for example with a figure) I don’t get any context window displayed (although the mousePressedCallback is called). The same code using the handle of juitable, doesn’t even result in the mousePressCallback being called

    Am I doing something wrong or is this

    h = figure;
    juit = findjobj(h);
     
    % Prepare the context menu (note the use of HTML labels)
    menuItem1 = javax.swing.JMenuItem('action #1');
     
    % Set the menu items' callbacks
    set(menuItem1,'ActionPerformedCallback',@myFunc1);
     
    % Add all menu items to the context menu (with internal separator)
    jmenu = javax.swing.JPopupMenu;
    jmenu.add(menuItem1);
     
    set(juit, 'MousePressedCallback', {@mousePressedCallback,jmenu});
     
    function mousePressedCallback(hTree, eventData, jmenu)
       display('here')
       jmenu.repaint;
    end
    • Yair Altman says:

      @Bassam – you forgot the all-important display of the jmenu:

      jmenu.show(jComponent, jEventData.getX, jEventData.getY)

      (jComponent can be real or [])

  6. Pingback: Customizing uitree | Undocumented Matlab

  7. Yan says:

    Hi Yair,

    Good work, very useful post. I was wondering if you can also add specific Tool Tip on nodes (not for the entire tree) possibly different ones depending on node hierarchy.

    Thanks!

  8. Nuno Benavente says:

    Hello Yair,
    First of all, congratulations for your book and excellent blog.
    I’ve been trying to implement a context menu to my needs but I’m stuck.
    Say my uitree displays a list of text file names (e.g. image1.txt, image2.txt, …)
    I want my context menu’s first option to be something like ‘visualize matrix’ of the image I right click in…
    How do I pass that information to my 1st context menu option’s callback function?

    Thank you very much in advance!
    Nuno

  9. Nuno Benavente says:

    Well, now I have another problem and I suck at java; perhaps you can help?
    One of my mtree’s context menu options is ‘delete file’ so, in my callback, after I delete the file, I’d like my tree to be ‘refreshed’ (I’m displaying it in a GUI, with a uipanel as parent).
    My approach to create the original nodes was through a for cycle, reading all the files in a given folder and creating the nodes one by one. That works fine, but after I delete one file is there a simple way to ‘redraw’ my mtree inside the same uipanel?

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

<pre lang="matlab">
a = magic(3);
sum(a)
</pre>