uisplittool & uitogglesplittool callbacks

Last week, I presented the undocumented uisplittool and uitogglesplittool functions and showed how they can be added to a Matlab figure toolbar. Today I wish to conclude this topic by explaining how these controls can be customized with user-defined callbacks and pop-up menus.

Callback functionality

Both uisplittool and uitogglesplittool have a Callback property, in addition to the standard ClickedCallback property that is available in uipushtools and uitoggletools.

The standard ClickedCallback is invoked when the main button is clicked, while Callback is invoked when the narrow arrow button is clicked. uitogglesplittool, like uitoggletool, also has settable OnCallback and OffCallback callback properties.

The accepted convention is that ClickedCallback should invoke the default control action (in our case, an Undo/Redo of the topmost uiundo action stack), while Callback should display a drop-down of selectable actions.

While this can be done programmatically using the Callback property, this functionality is already pre-built into uisplittool and uitogglesplittool for our benefit. To access it, we need to get the control’s underlying Java component.

Accessing the underlying Java component is normally done using the findjobj utility, but in this case we have a shortcut: the control handle’s hidden JavaContainer property that holds the underlying com.mathworks.hg.peer.SplitButtonPeer (or .ToggleSplitButtonPeer) Java reference handle. This Java object’s MenuComponent property returns a reference to the control’s drop-down sub-component (which is a com.mathworks.mwswing.MJPopupMenu object):

>> jUndo = get(hUndo,'JavaContainer')
jUndo =
com.mathworks.hg.peer.SplitButtonPeer@f09ad5
 
>> jMenu = get(jUndo,'MenuComponent')  % or: =jUndo.getMenuComponent
jMenu =
com.mathworks.mwswing.MJPopupMenu[Dropdown Picker ButtonMenu,...]

Let’s add a few simple textual options:

jOption1 = jMenu.add('Option #1');
jOption1 = jMenu.add('Option #2');
set(jOption1, 'ActionPerformedCallback', 'disp(''option #1'')');
set(jOption2, 'ActionPerformedCallback', {@myCallbackFcn, extraData});

setting uisplittool & uitogglesplittool popup-menus

setting uisplittool & uitogglesplittool popup-menus

Popup-menus are described in more detail elsewhere (and in future articles). In the past I have already explained how icons and HTML markup can be added to menu items. Sub-menus can also be added.

A complete example

Let’s now use this information, together with last year’s set of articles about Matlab’s undocumented uiundo functionality, to generate a complete and more realistic example, of undo/redo toolbar buttons.

Undo and redo are actions that are particularly suited for uisplittool, since its main button enables us to easily undo/redo the latest action (like a simple toolbar button, by clicking the main uisplittool button) as well as select items from the actions drop-down (like a combo-box, by clicking the attached arrow button) – all this using a single component.

% Display our GUI
hEditbox = uicontrol('style','edit', 'position',[20,60,40,40]); 
set(hEditbox, 'Enable','off', 'string','0');
hSlider = uicontrol('style','slider','userdata',hEditbox);
set(hSlider,'Callback',@test_uiundo);  
 
% Display the figure toolbar that was hidden by the uicontrol function
set(gcf,'Toolbar','figure');
 
% Add the Undo/Redo buttons
hToolbar = findall(gcf,'tag','FigureToolBar');
hUndo = uisplittool('parent',hToolbar);
hRedo = uitogglesplittool('parent',hToolbar);
 
% 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],:);
 
% Add the icon (and its mirror image = undo) to latest toolbar
set(hUndo, 'cdata',cdataUndo, 'tooltip','undo','Separator','on', ...
           'ClickedCallback','uiundo(gcbf,''execUndo'')');
set(hRedo, 'cdata',cdataRedo, 'tooltip','redo', ...
           'ClickedCallback','uiundo(gcbf,''execRedo'')');
 
% Re-arrange the Undo/Redo buttons  
jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer');
jButtons = jToolbar.getComponents;
for buttonIdx = length(jButtons)-3 : -1 : 7  % end-to-front
   jToolbar.setComponentZOrder(jButtons(buttonIdx), buttonIdx+1);
end
jToolbar.setComponentZOrder(jButtons(end-2), 5);    % Separator
jToolbar.setComponentZOrder(jButtons(end-1), 6);    % Undo
jToolbar.setComponentZOrder(jButtons(end), 7);      % Redo
jToolbar.revalidate;
 
% Retrieve redo/undo object
undoObj = getappdata(gcf,'uitools_FigureToolManager');
if isempty(undoObj)
   undoObj = uitools.FigureToolManager(gcf);
   setappdata(gcf,'uitools_FigureToolManager',undoObj);
end
 
% Populate Undo actions drop-down list
jUndo = get(hUndo,'JavaContainer');
jMenu = get(jUndo,'MenuComponent');
undoActions = get(undoObj.CommandManager.UndoStack,'Name');
jMenu.removeAll;
for actionIdx = length(undoActions) : -1 : 1    % end-to-front
    jActionItem = jMenu.add(undoActions(actionIdx));
    set(jActionItem, 'ActionPerformedCallback', @myUndoCallbackFcn);
end
jToolbar.revalidate;
 
% Drop-down callback function
function myUndoCallbackFcn(jActionItem,hEvent)
    % user processing needs to be placed here
end  % myUndoCallbackFcn

undo/redo buttons implemented using uisplittool

undo/redo buttons implemented using uisplittool

In a real-world application, the code-segment above that populated the drop-down list would be placed within the slider’s test_uiundo() callback function, and we would set a similar drop-down for the hRedu button. In addition, we would dynamically modify the button tooltips. As a final customization, we could modify the figure’s main menu. Menu customization will be discussed in a future separate set of articles.

Have you used uisplittool or uitogglesplittool in your GUI? If so, please tell us what use you have made of them, in a comment below.

Categories: Figure window, Java, Medium risk of breaking in future versions, Stock Matlab function, Undocumented feature

Tags: , , , , , ,

Bookmark and SharePrint Print

3 Responses to uisplittool & uitogglesplittool callbacks

  1. Chris says:

    Hello Yair,

    this site is great!

    I am using the togglesplittool in my GUI. First I had problems, Matlab 2010a shutting down. I was able to solve this by putting a “pause(0.01)” before calling “get(hUndo,’JavaContainer’)”.

    You know a way to put a sign like you have on uimenus by setting the ‘checked’-property to ‘on’?

    Greetings Chris

  2. Chris says:

    Exactly, i give different options the user can choose from the togglesplittool associated drop-down-menu. After choosing one can click the togglebutton. Now it would be nice if the user can see the actually selected option. This i would like to do by putting a sign check to the last selected option from the drop-down-menu. I hope you got what i mean?

Leave a Reply


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