Over the past years, I have not posted articles dealing with menu items. I have shown how to directly access menu items’ hidden handles, but not much more than that. A year ago I promised a mini-series on menu customizations, and it’s time to keep my promise. In today’s article, the first in the mini-series, I will present several undocumented menu customization topics that rely on pure-Matlab (i.e, no Java today). The next article in this series will focus on Java-based customizations.
Invoking menu item callbacks
As noted above, a figure window’s menu items can be directly accessed. Once we access a menu item’s handle, we can extract its Callback property and directly invoke it (for example, using the semi-documented hgfeval function). Note that menu callbacks are kept in Callback, while toolbar callbacks are kept in ClickedCallback.
Menu callbacks generally use internal semi-documented functions (i.e., having a readable help section but no doc, online help, or official support), which are part of Matlab’s uitools folder. These functions are specific to each top-level menu tree: filemenufcn, editmenufcn, viewmenufcn, insertmenufcn, toolsmenufcn, desktopmenufcn, winmenu, and helpmenufcn implement the figure’s eight respective top-level menu trees’ callbacks. These functions accept an optional figure handle (otherwise, gcbf is assumed), followed by a string specifying the specific menu item whose action needs to be run. webmenufcn implements the Help menu’s Web Resources sub-menu callbacks in a similar manner.
Use of these functions makes it easy to invoke a menu action directly from our Matlab code: instead of accessing the relevant menu item and invoking its Callback, we simply find out the menu item string in advance and use it directly. For example,
filemenufcn FileClose; editmenufcn(hFig,'EditPaste'); |
uimenufcn is a related fully-undocumented (built-in) function, available since Matlab R11 (late 1990s). It accepts a figure handle (or the zero [0] handle to indicate the desktop) and action name. For example, the fully-documented commandwindow function uses the following code to bring the Command Window into focus:
uimenufcn(0, 'WindowCommandWindow'); |
Customizing menus via uitools
makemenu is another semi-documented uitool function that enables easy creation of hierarchical menu trees with separators and accelerators. It is a simple and effective wrapper for uimenu. makemenu is a useful function that has been made obsolete (grandfathered) without any known replacement.
makemenu accepts four parameters: a figure handle, a char matrix of labels (‘>’ indicating sub item, ‘>>’ indicating sub-sub items etc.; ‘&’ indicating keyboard shortcut; ‘^x’ indicating an accelerator key; ‘-‘ indicating a separator line), a char matrix of callbacks, and an optional char matrix of tags (empty by default). makemenu makes use of another semi-documented grandfathered function, menulabel, to parse the specified label components. makemenu returns an array of handles of the created uimenu items:
labels = str2mat('&File', ... % File top menu '>&New^n', ... % File=>New '>&Open', ... % File=>Open '>>Open &document^d', ... % File=>Open=>doc '>>Open &graph^g', ... % File=>Open=>graph '>-------', ... % File=>separator line '>&Save^s', ... % File=>Save '&Edit', ... % Edit top menu '&View', ... % View top menu '>&Axis^a', ... % View=>Axis '>&Selection region^r'); % View=>Selection calls = str2mat('', ... % no action: File top menu 'disp(''New'')', ... '', ... % no action: Open sub-menu 'disp(''Open doc'')', ... 'disp(''Open graph'')', ... '', ... % no action: Separator 'disp(''Save'')', ... '', ... % no action: Edit top menu '', ... % no action: View top menu 'disp(''View axis'')', ... 'disp(''View selection region'')'); handles = makemenu(hFig, labels, calls); set(hFig,'menuBar','none'); |
Customizing menus via HTML
Since menu items share the same HTML/CSS support feature as all Java Swing labels, we can specify font size/face/color, bold, italic, underline, superscript/subscript, and practically any HTML formatting.
Note that some features, such as the font or foreground/background colors, have specific properties that we can set using the Java handle, instead of using HTML. The benefit of using HTML is that it enables setting all the formatting in a single property. HTML does not require using Java – just pure Matlab (see the following example).
Multi-line menu items can easily be done with HTML: simply include a <br>
element in the label – the menu item will split into two lines and automatically resize vertically when displayed:
txt1 = '<html><b><u><i>Save</i></u>'; txt2 = '<font color="red"><sup>this file</sup></font></b></html>'; txt3 = '<br />this file as...'; set(findall(hFig,'tag','figMenuFileSave'), 'Label',[txt1,txt2]); set(findall(hFig,'tag','figMenuFileSaveAs'), 'Label',[txt1,txt3]); |
set(hMenuItem, 'Label',['<html>&2: C:\My Documents\doc.txt<br />' '<font size="-1" face="Courier New" color="red"> ' 'Date: 15-Jun-2011 13:23:45<br /> Size: 123 KB</font></html>']); |
Much more complex customizations can be achieved using Java. So stay tuned to part 2 of this mini-series…
Note: Menu customization is explored in depth in section 4.6 of my book.
HI Yair,
not related to this post, but was curious if you
Have you ever worked on the solution to this :
http://stackoverflow.com/questions/5554518/can-matlab-not-read-back-a-double-array-from-java
no…
It is not a bug, it is expected behaviour
firstfunction accepts a copy of a MATLAB double array, modifies that copy and returns without altering anything in the MyClass instance.
secondfunction gets a reference to a java.lang.Double array as input- so MATLAB sees the changes made to that object
@Malcolm, I believe the OP does not dispute the fact that this is the expected behavior, he/she was simply asking whether there is any way to circumvent or modify this behavior. I do not know of any, but this is not saying that there isn’t any…
[…] Last week I explained how to customize Matlab’s menu items using some undocumented tricks that do not need Java […]
[…] We can take this idea even further by employing HTML formatting, as I have shown in my first article of the menubar mini-series: HTML-rendered menu items […]
Hi Yair,
Do you know how to add a separator to a pop-up control (combo box)? I tried:
But, alas, it didn’t work as expected (it added
jSeparator.toString()
instead). Where did I go wrong?Kindest regards, Yaroslav
@Yaroslav – instead of customizing the built-in Matlab uicontrol, create a standard
javax.swing.JComboBox
(where adding aJSeparator
is easy), then add it to your figure window using javacomponent.Hi Yair,
Unfortunately, javacomponent did not solve the problem. The culprit is actually the renderer, as suggested here. After installing the java classes
SeparatorComboBoxRenderer
andSeparatorComboBoxListener
therein (with slight adjustments), the following modification worked:A similar version with
javax.swing.JComboBox
and javacomponent also worked.In any case, I thank you for the prompt response and the recommendation to work directly with java. It gave me the motivation to dig into some java code and find the solution.
Kindest regards, Yaroslav
A simple alternative that does not require any Java is to use simple HTML. For example: