Figure toolbar customizations

Last week, I described how to access existing Matlab figure toolbar icons and how to add non-button toolbar components. Today, I describe how the toolbar itself can be customized using undocumented functionality and properties.

All the important undocumented customizations can only be accessed via the toolbar’s Java handle, which is retrieved so:

hToolbar = findall(hFig,'tag','FigureToolBar');
jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer');

One interesting functionality is enabling a floating toolbar, via jToolbar.setFloatable(1). The toolbar can then be dragged from its docked position at the top of the figure menu, becoming enclosed in an independent floating window (a non-modal javax.swing.JDialog child of the parent figure, to be exact). Since this toolbar window has a very small initial size and no name, a simple immediate fix is required:

% Modify Java toolbar properties
jToolbar.setFloatable(1);
hjToolbar = handle(jToolbar,'CallbackProperties');
set(hjToolbar,'AncestorAddedCallback',@dockUndockCallbackFcn);
 
% Sample dockUndockCallbackFcn function
function dockUndockCallbackFcn(hjToolbar, eventdata)
   if hjToolbar.isFloating
      jToolbarWin = hjToolbar.getTopLevelAncestor;
      jToolbarWin.setTitle('Toolbar');
      %jToolbarWin.setResizable(1); %if you wish manual resize
      jToolbarWin.setPreferredSize(java.awt.Dimension(380,57));
      jToolbarWin.setSize(java.awt.Dimension(380,57));
      jToolbar.revalidate;  %repaint toolbar
      jToolbarWin.getParent.validate; %repaint parent figure
   end
end

Floating toolbar   ...and after minor fixes

Floating toolbar                 ...and after minor fixes        

Re-docking a floating toolbar can be done by simply closing the floating window – the toolbar then reappears in its default (top) position within the parent figure window.

There are other interesting functions/properties available via the Java interface – readers are encouraged to explore via the methods, methodsview, inspect functions, or my uiinspect utility.

For example, addGap() can be used to add a transparent gap between the rightmost toolbar component and the window border: this gap is kept even if the window is shrunk to a smaller width – the rightmost components disappear, maintaining the requested gap.

setBackground() sets the background color that is seen beneath transparent pixels of button images and gaps. Non-transparent (opaque or colored) pixels are not modified. If the button icons are improperly created, the result looks bad:

jToolbar.setBackground(java.awt.Color.cyan); %or: Color(0,1,1)

Default figure toolbar with cyan background

Default figure toolbar with cyan background

This problem can be fixed by looping over the toolbar icons and modifying the pixel values from their default gray background to transparent. An example for this practice was given at the beginning of last week’s article.

setMorePopupEnabled() is used to specify the behavior when the window resizes to such a small width that one or more toolbar buttons need to disappear – by default (=1 or true) the chevron (>>) mark appears on the toolbar’s right, enabling display of the missing buttons, but this behavior can be overridden (0 or false) to simply crop the extra buttons.

setRollover() controls the behavior when the mouse passes (“rolls”) over toolbar buttons. The default parameter (1 or true), displays a 3-dimensional button border, creating an embossing effect; this can be overridden (0 or false) to use a different 3D effect:

% Set non-default Rollover, MorePopupEnabled
jToolbar.setRollover(0);         % or: set(jToolbar,'Rollover','off');
jToolbar.setMorePopupEnabled(0); % or: set(jToolbar,'MorePopupEnabled','off');

default Rollover & MorePopupEnabled properties

non-default Rollover & MorePopupEnabled properties

default (top) and non-default (bottom)
Rollover & MorePopupEnabled properties

Remember that toolbars are simply containers for internal components, generally buttons and separators. These components may be accessed individually and manipulated. An example of such manipulation can be found in my FindJObj utility on the File Exchange, that lists the individual figure components: whenever the user selects a toolbar button (or any other Java component for that matter), its border is temporarily modified to a flashing red rectangle helping users understand the component’s location. Here’s the relevant code snip and screenshot (readers are encouraged to look at the actual code, which is more complex – FindJObj sub-function flashComponent()):

% Prepare the red border panel
oldBorder = jComponent.getBorder;
redBorder = javax.swing.border.LineBorder(java.awt.Color.red,2,0);
redBorderPanel = javax.swing.JPanel;
redBorderPanel.setBorder(redBorder);
redBorderPanel.setOpaque(0);  % transparent interior, red border
redBorderPanel.setBounds(jComponent.getBounds);
isSettable(compIdx) = ismethod(jComponent,'setBorder');
 
% flash by periodically displaying/hiding the panel
for idx = 1 : 2*numTimes
   if idx>1,  pause(delaySecs);  end  % don't pause at start
   visible = mod(idx,2);
   jParent = jComponent.getParent;
 
   % Most Java components allow modifying their borders
   if isSettable
      if visible
         % Set a red border
         jComp.setBorder(redBorder);
         try jComponent.setBorderPainted(1); catch, end
      else %if ~isempty(oldorder)
         % Remove red border by restoring the original border
         jComp.setBorder(oldBorder);
      end
      jComp.repaint;
 
   % Other Java components are highlighted by a transparent red-
   % border panel, placed on top of them in their parent's space
   elseif ~isempty(jParent)
      if visible
         % place the transparent red-border panel on top
         jParent.add(redBorderPanel);
         jParent.setComponentZOrder(redBorderPanel,0);
      else
         jParent.remove(redBorderPanel);
      end
      jParent.repaint;
   end
end  % idx flash loop

FindJObj - flashing red border around a toolbar icon

FindJObj - flashing red border around a toolbar icon

Related posts:

  1. Customizing figure toolbar background Setting the figure toolbar's background color can easily be done using just a tiny bit of Java magic powder. This article explains how. ...
  2. Figure toolbar components Matlab's toolbars can be customized using a combination of undocumented Matlab and Java hacks. This article describes how to access existing toolbar icons and how to add non-button toolbar components....
  3. Customizing the standard figure toolbar, menubar The standard figure toolbar and menubar can easily be modified to include a list of recently-used files....
  4. Uitab customizations This article shows several customizations that can be done to Matlab's undocumented tab-panels functionality...
  5. 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....
  6. Blurred Matlab figure window Matlab figure windows can be blurred using a semi-transparent overlaid window - this article explains how...

Categories: Figure window, GUI, Java, Medium risk of breaking in future versions

Tags: , , , ,

Bookmark and SharePrint Print

22 Responses to Figure toolbar customizations

  1. Jason McMains says:

    @Yair,
    There are 3 features of this toolbar window that really interest me:

    1) only the close button is shown in the top bar, not the minimize or restore button, does this mean it is possible to modify that top bar as well? (add and remove buttons there, or change callbacks)

    2) when the toolbar is undocked, the figure name does not show up in the windows start bar. Does this mean we could have other “child” figures, that dont show up in the start bar?

    3) the tool bar window stays on top of the figure, but not on top of any others.

    I’m really interested to hear your thoughts

    Jason

  2. Tim says:

    Any idea how to make changes to the default figure toolbar that apply for *all* figures, including new ones that have yet to be created?

  3. Yair Altman says:

    @Jason – the top (detached) toolbar is customizable just like a docked toolbar. I’m afraid I don’t know how to modify Matlab windows to have similar decoration effects (no resize/minimize buttons), nor how to create other child windows. If and when I learn more, I’ll post updates here.

    @Tim – place your customization code in figureToolbarCreateFcn.m. This is an internal Matlab function (in the %matlabroot%\toolbox\matlab\graphics\ folder) that is called whenever the default figure toolbar is created. Depending on your Matlab release version, you may need to update a different internal function.

    • Stupidfrog says:

      Excellent!
      However, if I have correctly understood, modifying figureToolbarCreateFcn.m is no longer possible in recent versions (I am using 2012a). Is there a new workaround?
      Thanks

  4. Tim says:

    Yair: Fantastic, that worked like a charm. I’ve used it to add a ‘Protect figure’ toggle to the standard toolbar. Here’s the code. Edit the file %matlabroot%\toolbox\matlab\graphics\figureToolbarCreateFcn.m and go to the line before this one:

    function localAddInfoBar(es,ed,fig)

    and add the following code:

    % Modifications to add a 'protect' toggle.
     
    % Shield icon:
    sh(:, :, 1) = [240 232 228 223 219 214 209 203 197 191 185 179 173 167 240 240;240 226 97 97 97 97 97 97 97 97 111 132 155 158 240 240;240 219 97 33 33 33 33 33 58 179 201 207 214 149 240 240;240 211 97 33 33 33 33 58 180 227 218 203 214 140 240 240;240 203 97 33 33 33 58 180 227 255 255 227 214 131 240 240;240 194 97 33 33 59 180 227 255 255 255 186 214 123 240 240;240 185 106 33 59 180 227 255 255 255 206 100 214 116 240 240;240 176 117 59 180 227 255 255 255 206 96 33 214 109 240 240;240 179 129 184 227 255 255 255 206 96 33 49 204 114 240 240;240 180 140 186 253 255 255 206 96 32 32 65 193 121 240 240;240 192 144 191 229 255 206 96 32 32 31 93 172 141 240 240;240 221 149 209 179 204 96 31 35 31 30 157 127 193 240 240;240 240 172 175 201 111 30 36 30 90 165 176 130 240 240 240;240 240 238 163 130 181 214 214 214 185 120 132 232 240 240 240;240 237 229 218 176 102 65 64 62 84 144 188 203 217 228 236;240 230 207 192 175 158 143 134 131 134 145 158 172 186 200 224];
    sh(:, :, 2) = [240 235 231 227 223 218 214 209 204 199 193 188 183 177 240 240;240 229 116 116 116 116 116 116 116 116 129 148 169 169 240 240;240 223 116 113 113 113 113 113 87 194 212 217 223 162 240 240;240 216 116 113 113 113 113 87 195 233 225 213 223 154 240 240;240 209 116 113 113 113 87 195 233 255 255 233 223 146 240 240;240 202 116 113 113 89 195 233 255 255 255 196 223 139 240 240;240 192 124 113 89 195 233 255 255 255 212 120 223 132 240 240;240 185 134 89 195 233 255 255 255 212 117 113 223 126 240 240;240 187 145 200 233 255 255 255 212 117 112 122 214 130 240 240;240 188 155 201 253 255 255 212 117 108 108 128 204 137 240 240;240 199 158 205 234 255 212 117 103 103 102 142 185 155 240 240;240 223 163 219 195 211 117 97 99 96 95 183 144 199 240 240;240 240 182 187 212 132 91 94 89 132 187 188 144 240 240 240;240 240 238 174 145 193 223 223 223 197 137 146 233 240 240 240;240 237 230 220 181 112 78 77 76 95 151 192 206 218 229 237;240 230 210 196 180 165 151 142 139 142 152 164 177 190 203 225];
    sh(:, :, 3) = [240 236 232 229 225 221 217 213 209 204 199 194 189 184 240 240;240 231 131 131 131 131 131 131 131 131 143 160 179 177 240 240;240 225 131 208 208 208 208 208 164 207 219 223 228 170 240 240;240 219 131 208 208 208 208 164 208 237 230 221 228 163 240 240;240 213 131 208 208 208 164 208 237 255 255 237 228 156 240 240;240 206 131 208 208 165 208 237 255 255 255 204 228 150 240 240;240 199 138 208 165 208 237 255 255 255 217 171 228 144 240 240;240 192 148 165 208 237 255 255 255 217 170 208 228 138 240 240;240 193 157 211 237 255 255 255 217 170 207 209 220 142 240 240;240 194 166 211 253 255 255 217 170 204 204 208 211 148 240 240;240 203 169 214 238 255 217 170 200 199 197 208 193 163 240 240;240 225 171 225 206 216 170 193 193 192 191 217 155 203 240 240;240 240 188 194 219 180 188 188 186 200 217 196 154 240 240 240;240 240 238 181 156 201 228 228 228 205 148 156 234 240 240 240;240 238 230 221 185 120 88 87 86 104 157 195 208 220 230 237;240 231 212 199 184 170 157 149 147 149 158 169 182 194 205 226];
    sh = sh ./ 255;
     
    fh = ancestor(tb,'figure');
    tbh = findall(fh, 'Type', 'uitoolbar');
    uitoggletool(tbh, 'CData', sh, 'TooltipString', 'Protect figure from modifications',...
                      'OnCallback',  @(obj, eventData) ProtectCallback(fh, true), ...
                      'OffCallback', @(obj, eventData) ProtectCallback(fh, false));
     
    function ProtectCallback(fig, protect)
        if protect
            set(fig, 'HandleVisibility', 'off');
        else
            set(fig, 'HandleVisibility', 'on');
        end

    Thanks again!

  5. Jason McMains says:

    Yair,
    I’ve just run across one more question on this topic, and I cant seem to find an answer in the java forums. Do you know of a way to make the toolbar float by default, I would expect some command along the lines of setFloating, but it doesnt exist.

    Thanks again
    Jason

    • Jason – odd as this may sound, it appears that the default Swing JToolBar object (from which Matlab’s MJToolBar inherits) does not enable setting the ‘Floating’ property programmatically. See here, for example: http://java.sun.com/docs/books/tutorial/uiswing/components/toolbar.html#more

      Matlab’s MJToolBar extends JToolBar with a getter method (isFloating()), but not with a corresponding setter method. Doing the following throws no exception/error, but also has no visible effect:

      set(jToolbar,'Floating','on');  % works but no visible effect
      jToolbar.setFloating(1);  % Error: no such method
    • Jason McMains says:

      Yair,
      Weird, it seems like something relatively fundamental that was left out. Thanks for checking on it though!
      Jason

  6. Daniel says:

    Yair
    I can’t find the AncestorAddedCallback. I’ve inspected the MJToolbar object with the uiinspect utility and it seems to be not accesible. am i doing something wrong?

    Thanks
    Daniel

    • Daniel – which Matlab release and platform are you using? Also, what commands do you use to get the toolbar object and its callbacks? – The following should work:

      hToolbar = findall(hFig,'tag','FigureToolBar');
      jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer');
      jToolbar = handle(jToolbar, 'CallbackProperties');
      set(jToolbar,'AncestorAddedCallback',@myCallbackFunction);
    • Daniel says:

      Yair
      i`ve just resolved my problem.
      jToolbar = handle(jToolbar, ‘CallbackProperties’); is missing in the example on the top of the page.
      Thanks for the new example.

      Daniel

    • oops… my bad – sometimes a simple handle(obj) is enough to expose the callbacks, but sometimes not, so it is always advisable to use handle(obj,’CallbackProperties’).

      Even MathWorks programmers encounter this limitation, as attested by the following internal comment within the built-in javacomponent.m function:
      Promote the component to a handle object first. It seems once a java object is cast to a handle, you cannot get another handle with ‘callbackproperties’.

      Anyway, I fixed the post accordingly.

  7. Kris says:

    Yair:

    I was curious if you might know how to create a vertically oriented figure toolbar. I am not wise in the ways of java, and thus, I am not certain about how to go about relocating the figure toolbar from the top of the figure window to, say, the left hand side of the figure window. I am interested in designing a GUI, such that the user may elect to place my customized toolbar icons and associated functions somewhere else in the figure window besides the top.

    I appreciate any feedback you might have. Thanks.

    -Kris

    • @Kris – interesting question! Standard Java JToolBars (which the Matlab toolbar extends) allow floating toolbars to be manually dragged and pinned to the sides, but apparently the Matlab extension prevents it.

      Here is how to programmatically place the toolbar on the bottom:

      jPanel = jToolbar.getParent.getParent;
      jPanel.add(jToolbar.getParent,java.awt.BorderLayout.SOUTH);
      jPanel.revalidate;

      Unfortunately, when we try to use the same method for placing the toolbar on the left/right sides, the figure gets “frozen” and unresponsive. Perhaps someone can enlighten us what needs to be changed in the following code:

      jToolbar.setOrientation(jToolbar.VERTICAL);
      jPanel = jToolbar.getParent.getParent;
      jPanel.add(jToolbar.getParent,java.awt.BorderLayout.WEST);
      jPanel.revalidate;

      Yair

  8. Pingback: Modifying default toolbar/menubar actions | Undocumented Matlab

  9. JP says:

    Yair,
    thanks for this, it is extremely helpful. Playing around with the jToolbar properties, I was wondering if there is a way to make the toolbar width less than the width of the window? I can adjust the height using preferred size, but adjusting the width does nothing.

    Also, when adding matlab toolbars, it adds the dock button to the right of the toolbar. Is there a way to remove that. It shows up in the list of jToolbar components, but removing it does not seem to work.

    Thanks,
    JP

    • @JP – I don’t know of an easy way to reduce the toolbar’s width. Why do you wish to do this?

      To remove the docking icon, simply use the fully-documented DockControls property of the figure:

      set(gcf,'DockControls','off')
    • JP says:

      I have a GUI that has an axes that fills the bottom left 1/4 of the window. I would like the toolbar to be directly above the axes, but not spill over into the content on the right half of the window.

    • Aris says:

      @JP
      How exactly do you adjust the height?
      Did you by any chance find a solution for the width?
      Thanks!

  10. Yasser says:

    Hi Yair,

    I am trying to build a GUI on Matlab 2012b that has a main toolbar with only three Icons, and other optional tool bars.
    the point is, i need the main toolbar width to be only for the three icons, and when i select one of the optional toolbars it should come to right side of the main toolbar NOT under it.

    Thanks
    Yasser

    • @Yasser – you would need to play around at the Java level. It is possible, but there is no two-liner solution I’m afraid. Send me an offline email if you’d like my consulting help in this.

  11. Daniel says:

    Hi all,

    would there be posibility to doch a toolbar on the left side (or the right side) of a gui?

    Thanks for all your help!
    Daniel.

Leave a Reply

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

*

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