Toolbars are by now a staple of modern GUI design. An unobtrusive list of small icons enables easy access to multiple application actions without requiring large space for textual descriptions. Unfortunately, the built-in documented support for the Matlab toolbars is limited to adding icon buttons via the uipushtool and uitoggletool functions, and new toolbars containing them via the uitoolbar function. In this post I will introduce several additional customizations that rely on undocumented features.
This article will only describe figure toolbars. However, much of the discussion is also relevant to the desktop (Comand Window) toolbars and interested users can adapt it accordingly.
Accessing toolbar buttons - undo/redo
Let’s start by adding undo/redo buttons to the existing figure toolbar. I am unclear why such an elementary feature was not included in the default figure toolbar, but this is a fact that can easily be remedied. In a future post I will describe uiundo, Matlab’s semi-documented support for undo/redo functionality, but for the present let’s assume we already have this functionality set up.
First, let’s prepare our icons, which are basically a green-filled triangle icon and its mirror image:
% Load the Redo icon icon = fullfile(matlabroot,'/toolbox/matlab/icons/greenarrowicon.gif'); [cdata,map] = imread(icon); % Convert white pixels into a transparent background map(find(map(:,1)+map(:,2)+map(:,3)==3)) = NaN; % Convert into 3D RGB-space cdataRedo = ind2rgb(cdata,map); cdataUndo = cdataRedo(:,[16:-1:1],:);
Now let’s add these icons to the default figure toolbar:
% Add the icon (and its mirror image = undo) to the latest toolbar hUndo = uipushtool('cdata',cdataUndo, 'tooltip','undo', 'ClickedCallback','uiundo(gcbf,''execUndo'')'); hRedo = uipushtool('cdata',cdataRedo, 'tooltip','redo', 'ClickedCallback','uiundo(gcbf,''execRedo'')');

Undo/redo buttons
In the preceding screenshot, since no figure toolbar was previously shown, uipushtool added the undo and redo buttons to a new toolbar. Had the figure toolbar been visible, then the buttons would have been added to its right end. Since undo/redo buttons are normally requested near the left end of toolbars, we need to rearrange the toolbar buttons:
hToolbar = findall(hFig,'tag','FigureToolBar'); %hToolbar = get(hUndo,'Parent'); % an alternative hButtons = findall(hToolbar); set(hToolbar,'children',hButtons([4:end-4,2,3,end-3:end])); set(hUndo,'Separator','on');

Undo/redo buttons in their expected positions
We would normally preserve hUndo and hRedo, and modify their Tooltip and Visible/Enable properties in run-time, based on the availability and name of the latest undo/redo actions:
% Retrieve redo/undo object undoObj = getappdata(hFig,'uitools_FigureToolManager'); if isempty(undoObj) undoObj = uitools.FigureToolManager(hFig); setappdata(hFig,'uitools_FigureToolManager',undoObj); end % Customize the toolbar buttons latestUndoAction = undoObj.CommandManager.peekundo; if isempty(latestUndoAction) set(hUndo, 'Tooltip','', 'Enable','off'); else tooltipStr = ['undo' latestUndoAction.Name]; set(hUndo, 'Tooltip',tooltipStr, 'Enable','on'); end
We can easily adapt the method I have just shown to modify/update existing toolbar icons: hiding/disabling them etc. based on the application needs at run-time.
Adding non-button toolbar components - undo dropdown
A more advanced customization is required if we wish to present the undo/redo actions in a drop-down (combo-box). Unfortunately, since Matlab only enables adding uipushtools and uitoggletools to toolbars, we need to use a Java component. The drawback of using such a component is that it is inaccessible via the toolbar’s Children property (implementation of the drop-down callback function is left as an exercise to the reader):
% Add undo dropdown list to the toolbar jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer'); if ~isempty(jToolbar) undoActions = get(undoObj.CommandManager.UndoStack,'Name'); jCombo = javax.swing.JComboBox(undoActions(end:-1:1)); set(jCombo, 'ActionPerformedCallback', @myUndoCallbackFcn); jToolbar(1).add(jCombo,5); %5th position, after printer icon jToolbar(1).repaint; jToolbar(1).revalidate; end % Drop-down (combo-box) callback function function myUndoCallbackFcn(hCombo,hEvent) itemIndex = get(hCombo,'SelectedIndex'); % 0=topmost item itemName = get(hCombo,'SelectedItem'); % user processing needs to be placed here end

Undo dropdown list
Note that the javax.swing.JComboBox constructor accepts a cell-array of strings (undoActions in the snippet above). A user-defined dropdownlist might be constructed as follows (also see a related CSSM thread):
... dropdownStrings = {'here', 'there', 'everywhere'}; jCombo = javax.swing.JComboBox(dropdownStrings); set(jCombo, 'ActionPerformedCallback', @myUndoCallbackFcn); jToolbar(1).addSeparator; jToolbar(1).add(jCombo); % at end, following a separator mark jToolbar(1).repaint; jToolbar(1).revalidate; ...
A similar approach can be used to add checkboxes, radio-buttons and other non-button controls.
In next week’s post I will describe how the toolbar can be customized using undocumented functionality to achieve a non-default background, a floating toolbar (”palette”) effect and other interesting customizations. If you have any specific toolbar-related request, I’ll be happy to hear in the comments section below.
Related posts:
- Figure toolbar customizations Matlab's toolbars can be customized using a combination of undocumented Matlab and Java hacks. This article describes how to customize the Matlab figure toolbar....
- uicontrol side-effect: removing figure toolbar Matlab's built-in uicontrol function has a side-effect of removing the figure toolbar. This was undocumented until lately. This article describes the side-effect behavior and how to fix it....
- Setting status-bar components Matlab status-bars are Java containers in which we can add GUI controls such as progress-bars, not just simple text labels...
- uiundo - Matlab’s undocumented undo/redo manager The built-in uiundo function provides easy yet undocumented access to Matlab's powerful undo/redo functionality. This article explains its usage....
- Context-Sensitive Help Matlab has a hidden/unsupported built-in mechanism for easy implementation of context-sensitive help...
- Customizing uiundo This article describes how Matlab's undocumented uiundo undo/redo manager can be customized...
Tags: GUI, Icons, Java, Semi-documented function, Toolbar, uiundo
Print
|


I’m still a little fuzzy on the idea of “memory leaks” so this may be unneccessary, but I usually modify your code like this:
not sure that getting the handle is necessary to prevent memory leakage, it doesn’t seem to hurt anything though.
Also I have a few figures that use swing objects, and occasionally doing a uistack or reordering the children of the figure will remove the swing objects in the toolbar. I have done a few work arounds, mostly just avoiding the reorg at all. Just thought I would post that as an issue along with this post so people know about it.
Thanks Yair as always
Jason
Fascinating - I wish Matlab would natively give us access to toolbars and status bars the same way it possible with your “hacks”. I have a question though. If I add a jButton to the toolbar and the status bar they look very different, i.e. the status bar button looks like a nice button but the one in the toolbar lacks the 3D effects. This can be reproduced with the following code:
How can I make the button in the toolbar look ‘nice’ too?
Another problem is that I have to use your statusbar function since none of the methods described in your status bar post on this site seem to work on my 2009b Matlab, i.e.
gives
in
The strange thing is that if I execute line by line in the command window it does work fine….
Collecting most of the pieces of code above I get:
which runs nicely, and adds the two new buttons at the end of the toolbar. However, doing the following:
I get the error:
Inspecting “hButtons”, it contains 19 handles, but looking at:
it only contains 2 (!!!) handles, namely the two buttons that I just added.
I use MATLAB R2009b, and since I don’t have other versions of MATLAB installed, I don’t know if the is a “new feature” of the latest MATLAB release. I have tried setting “Toolbar” to both “figure” and “auto” but it doesn’t makes any difference.
Thanks for some inspiring reading
Henrik
@Henrik - You got this odd error because the toolbar buttons have hidden handles, which are only exposed to findall but not to findobj or get/set(hToolbar,’Children’). To solve this, temporarily set the desktop to show hidden handles, as follows:
- this is actually what findall does, if you look at its source with
Yair
@Dani -
1. The toolbar button actually behaves consistently with the other buttons on the toolbar (and your windowing system, for that matter), namely that its border is painted only when you hover your mouse over the button. This is controlled by the JButton’s RolloverEnabled property (which is true by default, and can be turned off if you wish):
To always display a border, you need to override the JButton’s default Border property. Here’s a link to get you started and also sample code: http://java.sun.com/docs/books/tutorial/uiswing/components/border.html
2. Yes I know - this issue also occurred in earlier Matlab releases: there’s is a delicate timing issue involved here, which is solved in the statusbar utility but for space considerations was left out of the short code snippets in my posts. When you run the commands in the Command Window one at a time, there is enough delay between commands to solve this problem. Well - that’s what we have utilities for, right?
Yair
@Yair
this
helps, but the status bar button is still a lot ‘nicer’, e.g. rounded corners, 3D color transition effect, larger button relative to text size - what else do I have to invoke to get this effect in the toolbar?
Dani
@Henrik
@Yair
I have another question reqgarding access to the toolbar. If I replace access to the standard figure toolbar
with a new toolbar through
then the java access to hToolbar2 does not work, i.e.
returns empty and I can consequently not add ojects such as jButton to it.
What is the reason for this?
@Dani - read my response above - the answers to your 2 questions are exactly the same answers I gave above:
1. You need to play around with the Border property. Search the web - there are numerous resources about this issue.
2. This is a timing issue again. Place a short delay/drawnow between your toolbar creation, your get(…,’JavaContainer’) and your get(…,’ComponentPeer’) to let everything render.
Yair
@Yair
@Henrik
In order for the rearrangement of the buttons to work, in R2009b, it is better to do:
rather than:
Since in the first case, only the buttons are found (length(hButtonsChildren) == 18) whereas in the second case also the the handle to the figure toolbar is included AND the undocumented “uitogglesplittool” is divided into two handle elements (length(hButtonsFindall) == 20)!
Another interesting (although irretating) feature is, that if the following is performed:
the undocumented “uitogglesplittool” which used to the 11th element has now forcefully placed itself as the first element!!! And there it insist on remaining even if I do the following (with “ShowHiddenHandles” = ‘on’):
I don’t konw if “interesting” is the right word
Henrik
Hi,
I’d like to add a button to the default “figure” Matlab toolbar and have it become part of the button group that contains the zoom/pan etc. buttons. In particular, when the user clicks my button, i want the other buttons in the group to be deselected (btnup function). However, the btnup function requires the “groupid” of the button group; I cannot seem to find this default “id” that Matlab is using for this button group (the group that contains the zoom, pan, etc. buttons).
Any help would be appreciated, thanks!
@Danny - the btn* set of functions (btnup, btndown, btnpress, btnstate, btnresize and btnicon) work with btngroup. Specifically, you can use btngroup to define the group ID, which is stored in the buttons’ Tag property.
These functions are obsolete and are not supported (they have a valid help section but no doc page), although for some unknown reason they do not issue an obsolescence warning.
Although in this blog I frequently advocate the use of undocumented functions, this is NOT the case here. My advise: don’t use btn* functions.
Nowadays, Matlab uses an altogether different approach to toolbar buttons. There are actually two grouping levels: Low-level grouping logic (zoom in/zoom-out) is done programmatically in zoom.m (near the end of the file), whereas high-level grouping (zoom/pan modes) is done using a ModeManager (which will be described in a dedicated article sometime in the future). This mode-manager object can be gotten via the following code:
Thanks for the advice! I’m trying your code and I got this output (below). Any ideas why it’s returning a null cbScribe value?
@danny - this could be because of a different Matlab version/platform than mine, or because your figure toolbar is hidden.
Try to simply display getappdata(gcf), to check maybe the data is named something other than ‘ScribeClearModeCallback’ on your system.
Otherwise, tell me your Matlab version and platform and I’ll see if I have anything intelligent to say about this…
Here’s the output of this command on my version (7.9.0 R2009b):
@danny - you need to enable one of the modes before this appdata property becomes available. For example, by clicking on one of the buttons or programmatically (e.g., zoom(’on’) or pan(’on’)).
OK, I got it to work, but I don’t see any information that corresponds to a “button group”. I was able to copy and paste some code from a GUIDE output file that works as far as creating a “group” of two buttons that are mutually exclusive (a previously selected button will become deselected if the other button becomes selected). However, I’m unable to add my own “custom” button to this group! Any tips? In the example code snippet below, I’m trying to add a third button “select region” to a group of two other buttons. The first two buttons seem to know about each other but don’t see the third button… I think it has something to do with the “createfcn” called “local_CreateFcn” that I copied from the GUIDE output. Any help is MUCH appreciated!!!!!!!!!
Thanks!!
Your first two buttons are zoom and pan, which know of each other and have internal code to handle mutual exclusivity. Your third button is different, so you need to let them know of each other.
This is more than the space here allows, so if you want to continue discussion, please contact me offline using the email link on the top-right of this page.