Icons – Undocumented Matlab https://undocumentedmatlab.com/blog_old Charting Matlab's unsupported hidden underbelly Tue, 29 Oct 2019 15:26:09 +0000 en-US hourly 1 https://wordpress.org/?v=4.4.1 Toolbar button labelshttps://undocumentedmatlab.com/blog_old/toolbar-button-labels https://undocumentedmatlab.com/blog_old/toolbar-button-labels#respond Mon, 08 Jan 2018 17:34:17 +0000 https://undocumentedmatlab.com/?p=7270 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. Builtin PopupPanel widget We can use a built-in Matlab popup-panel widget control to display lightweight popups that are attached to a figure window. ...
  3. Matlab toolstrip – part 9 (popup figures) Custom popup figures can be attached to Matlab GUI toolstrip controls. ...
  4. FindJObj GUI – display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
]]>
I was recently asked by a client to add a few buttons labeled “1”-“4” to a GUI toolbar. I thought: How hard could that be? Simply get the toolbar’s handle from the figure, then use the builtin uipushtool function to add a new button, specifying the label in the String property, right?

Labeled toolbar buttons

Well, not so fast it seems:

hToolbar = findall(hFig, 'tag','FigureToolBar');  % get the figure's toolbar handle
uipushtool(hToolbar, 'String','1');               % add a pushbutton to the toolbar
Error using uipushtool
There is no String property on the PushTool class. 

Apparently, for some unknown reason, standard Matlab only enables us to set the icon (CData) of a toolbar control, but not a text label.

Once again, Java to the rescue:

We first get the Java toolbar reference handle, then add the button in standard Matlab (using uipushtool, uitoggletool and their kin). We can now access the Java toolbar’s last component, relying on the fact that Matlab always adds new buttons at the end of the toolbar. Note that we need to use a short drawnow to ensure that the toolbar is fully re-rendered, otherwise we’d get an invalid Java handle. Finally, once we have this reference handle to the underlying Java button component, we can set and customize its label text and appearance (font face, border, size, alignment etc.):

hToolbar = findall(hFig, 'tag','FigureToolBar');     % get the figure's toolbar handle
jToolbar = hToolbar.JavaContainer.getComponentPeer;  % get the toolbar's Java handle
for buttonIdx = 1 : 4
    % First create the toolbar button using standard Matlab code
    label = num2str(buttonIdx);  % create a string label
    uipushtool(hToolbar, 'ClickedCallback',{@myCallback,analysisIdx}, 'TooltipString',['Run analysis #' label]);
 
    % Get the Java reference handle to the newly-created button
    drawnow; pause(0.01);  % allow the GUI time to re-render the toolbar
    jButton = jToolbar.getComponent(jToolbar.getComponentCount-1);
 
    % Set the button's label
    jButton.setText(label)
end

The standard Matlab toolbar button size (23×23 pixels) is too small to display more than a few characters. To display a longer label, we need to widen the button:

% Make the button wider than the standard 23 pixels
newSize = java.awt.Dimension(50, jButton.getHeight);
jButton.setMaximumSize(newSize)
jButton.setPreferredSize(newSize)
jButton.setSize(newSize)

Using a text label does not prevent us from also displaying an icon: In addition to the text label, we can also display a standard icon (by setting the button’s CData property in standard Matlab). This icon will be displayed to the left of the text label. You can widen the button, as shown in the code snippet above, to make space for both the icon and the label. If you want to move the label to a different location relative to the icon, simply modify the Java component’s HorizontalTextPosition property:

jButton.setHorizontalTextPosition(jButton.RIGHT);   % label right of icon (=default)
jButton.setHorizontalTextPosition(jButton.CENTER);  % label on top of icon
jButton.setHorizontalTextPosition(jButton.LEFT);    % label left of icon

In summary, here’s the code snippet that generated the screenshot above:

% Get the Matlab & Java handles to the figure's toolbar
hToolbar = findall(hFig, 'tag','FigureToolBar');     % get the figure's toolbar handle
jToolbar = hToolbar.JavaContainer.getComponentPeer;  % get the toolbar's Java handle
 
% Button #1: label only, no icon, 23x23 pixels
h1 = uipushtool(hToolbar);
drawnow; pause(0.01);
jButton = jToolbar.getComponent(jToolbar.getComponentCount-1);
jButton.setText('1')
 
% Create the icon CData from an icon file
graphIcon = fullfile(matlabroot,'/toolbox/matlab/icons/plotpicker-plot.gif');
[graphImg,map] = imread(graphIcon);
map(map(:,1)+map(:,2)+map(:,3)==3) = NaN;  % Convert white pixels => transparent background
cdata = ind2rgb(graphImg,map);
 
% Button #2: label centered on top of icon, 23x23 pixels
h2 = uipushtool(hToolbar, 'CData',cdata);
drawnow; pause(0.01);
jButton = jToolbar.getComponent(jToolbar.getComponentCount-1);
jButton.setText('2')
jButton.setHorizontalTextPosition(jButton.CENTER)
 
% Button #3: label on right of icon, 50x23 pixels
h3 = uipushtool(hToolbar, 'CData',cdata);
drawnow; pause(0.01);
jButton = jToolbar.getComponent(jToolbar.getComponentCount-1);
jButton.setText('3...')
d = java.awt.Dimension(50, jButton.getHeight);
jButton.setMaximumSize(d); jButton.setPreferredSize(d); jButton.setSize(d)
 
% Button #4: label on left of icon, 70x23 pixels
h4 = uipushtool(hToolbar, 'CData',cdata);
drawnow; pause(0.01);
jButton = jToolbar.getComponent(jToolbar.getComponentCount-1);
jButton.setText('and 4:')
jButton.setHorizontalTextPosition(jButton.LEFT)
d = java.awt.Dimension(70, jButton.getHeight);
jButton.setMaximumSize(d); jButton.setPreferredSize(d); jButton.setSize(d)

Many additional toolbar customizations can be found here and in my book “Undocumented Secrets of MATLAB-Java Programming“. If you’d like me to design a professional-looking GUI for you, please contact me.

Caveat emptor: all this only works with the regular Java-based GUI figures, not web-based (“App-Designer”) uifigures.

]]>
https://undocumentedmatlab.com/blog_old/toolbar-button-labels/feed 0
Icon images & text in Matlab uicontrolshttps://undocumentedmatlab.com/blog_old/icon-images-in-matlab-uicontrols https://undocumentedmatlab.com/blog_old/icon-images-in-matlab-uicontrols#comments Wed, 28 Sep 2016 10:28:04 +0000 http://undocumentedmatlab.com/?p=6687 Related posts:
  1. Rich-contents log panel Matlab listboxes and editboxes can be used to display rich-contents HTML-formatted strings, which is ideal for log panels. ...
  2. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  3. Aligning uicontrol contents Matlab uicontrols can often be customized using plain HTML/CSS, without need for advanced Java. ...
  4. GUI integrated browser control A fully-capable browser component is included in Matlab and can easily be incorporated in regular Matlab GUI applications. This article shows how....
]]>
One of my consulting clients recently asked me if I knew any builtin Matlab GUI control that could display a list of colormap names alongside their respective image icons, in a listbox or popup menu (drop-down/combo-box):

Matlab listbox with icon images   Matlab popup menu (dropdown/combobox) with icon images

Matlab listbox (left) & popup menu (right) with icon images

My initial thought was that this should surely be possible, since Colormap is a documented figure property, that should therefore be listed inside the inspector window, and should therefore have an associated builtin Java control for the dropdown (just like other inspector controls, which are part of the com.mathworks.mlwidgets package, or possibly as a standalone control in the com.mathworks.mwswing package). To my surprise it turns out that for some unknown reason MathWorks neglected to add the Colormap property (and associated Java controls) to the inspector. This property is fully documented and all, just like Color and other standard figure properties, but unlike them Colormap can only be modified programmatically, not via the inspector window. Matlab does provide the related colormapeditor function and associated dialog window, but I would have expected a simple drop-down of the standard builtin colormaps to be available in the inspector. Anyway, this turned out to be a dead-end.

It turns out that we can relatively easily implement the requested listbox/combo-box using a bit of HTML magic, as I explained last week. The basic idea is for each of the listbox/combobox items to be an HTML string that contains both an <img> tag for the icon and the item label text. For example, such a string might contain something like this (parula is Matlab’s default colormap in HG2, starting in R2014b):

<html><img src="http://www.mathworks.com/help/matlab/ref/colormap_parula.png">parula

parula colormap image

parula colormap image

Of course, it would be a bit inefficient for each of the icons to be fetched from the internet. Luckily, the full set of Matlab documentation is typically installed on the local computer as part of the standard Matlab installation, beneath the docroot folder (e.g., C:\Program Files\Matlab\R2016b\help). In our specific case, the parula colormap image is located in:

imageFilename = [docroot, '/matlab/ref/colormap_parula.png']

Note that for a local image to be accepted by HTML, it needs to follow certain conventions. In our case, the HTML string for displaying the above image is:

<html><img src="file:///C:/Program%20Files/Matlab/R2016b/help/matlab/ref/colormap_parula.png">parula

Warning: it’s easy when dealing with HTML images in Matlab to get the format confused, resulting in a red-x icon. I discussed this issue some 4 years ago, which is still relevant.

How can we get the list of available builtin colormaps? The standard Matlab way of doing this would be something like this:

>> possibleColormaps = set(gcf,'Colormap')
possibleColormaps = 
     {}

but as we can see, for some unknown reason (probably another MathWorks omission), Matlab does not list the names of its available builtin colormaps.

Fortunately, all the builtin colormaps have image filenames that follow the same convention, which make it easy to get this list by simply listing the names of the relevant files, from which we can easily create the necessary HTML strings:

>> iconFiles = dir([docroot, '/matlab/ref/colormap_*.png']);
 
>> colormapNames = regexprep({iconFiles.name}, '.*_(.*).png', '$1')
colormapNames =  
  Columns 1 through 9
    'autumn'    'bone'    'colorcube'    'cool'    'copper'    'flag'    'gray'    'hot'    'hsv'
  Columns 10 through 18
    'jet'    'lines'    'parula'    'pink'    'prism'    'spring'    'summer'    'white'    'winter'
 
>> htmlStrings = strcat('<html><img width=200 height=10 src="file:///C:/Program%20Files/Matlab/R2016a/help/matlab/ref/colormap_', colormapNames', '.png">', colormapNames')
str = 
    '<html><img width=200 height=10 src="file:///C:/Program%20Files/Matlab/R2016a/help/matlab/ref/colormap_autumn.png">autumn'
    '<html><img width=200 height=10 src="file:///C:/Program%20Files/Matlab/R2016a/help/matlab/ref/colormap_bone.png">bone'
    '<html><img width=200 height=10 src="file:///C:/Program%20Files/Matlab/R2016a/help/matlab/ref/colormap_colorcube.png">colorcube'
    ...
 
>> hListbox = uicontrol(gcf, 'Style','listbox', 'Units','pixel', 'Pos',[10,10,270,200], 'String',htmlStrings);
>> hPopup   = uicontrol(gcf, 'Style','popup',   'Units','pixel', 'Pos',[10,500,270,20], 'String',htmlStrings);

…which results in the screenshots at the top of this post.

Note how I scaled the images to 10px high (so that the labels would be shown and not cropped vertically) and 200px wide (so that it becomes narrower than the default 434px). There’s really no need in this case for the full 434×27 image size – such flat images scale very nicely, even when their aspect ratio is not preserved. You can adjust the height and width values for a best fit with you GUI.

Unfortunately, it seems that HTML strings are not supported in the new web-based uifigure controls. This is not really Matlab’s fault because the way to customize labels in HTML controls is via CSS: directly embedding HTML code in labels does not work (it’s a Java-Swing feature, not a browser feature). I really hope that either HTML or CSS processing will be enabled for web-based uicontrol in a future Matlab release, because until that time uifigure uicontrols will remain seriously deficient compared to standard figure uicontrols. Until then, if we must use uifigures and wish to customize our labels or listbox items, we can directly access the underlying web controls, as Iliya explained here.


A blog reader recently complained that I’m abusing Swing and basically making Matlab work in unnatural ways, “something it was never meant to be“. I feel that using HTML as I’ve shown last week and in this post would fall under the same category in his eyes. To him and to others who complain I say that I have absolutely no remorse about doing this. When I purchase anything I have the full rights (within the scope of the license) to adapt it in whatever way fits my needs. As a software developer and manager for over 25 years, I’ve developed in dozens of programming languages and environments, and I still enjoy [ab]using Matlab. Matlab is a great environment to get things done quickly and if this sometimes requires a bit of HTML or Java hacks that make some people cringe, then that’s their problem, not mine – I’m content with being able to do in Matlab [nearly] everything I want, quickly, and move on to the next project. As long as it gets the job done, that’s fine by me. If this makes me more of an engineer than a computer scientist, then so be it.

On the flip side, I say to those who claim that Matlab is lacking in this or that aspect, that in most likelihood the limitation is only in their minds, not in Matlab – we can do amazing stuff with Matlab if we just open our minds, and possibly use some undocumented hacks. I’m not saying that Matlab has no limitations, I’m just saying that in most cases they can be overcome if we took the time and trouble to look for a solution. Matlab is a great tool and yet many people are not aware of its potential. Blaming Matlab for its failings is just an easy excuse in many cases. Of course, MathWorks could help my crusade on this subject by enabling useful features such as easy GUI component customizations…

On this sad day, I wish you all Shanah Tova!

]]>
https://undocumentedmatlab.com/blog_old/icon-images-in-matlab-uicontrols/feed 6
Programmatic shortcuts manipulation – part 1https://undocumentedmatlab.com/blog_old/programmatic-shortcuts-manipulation-part-1 https://undocumentedmatlab.com/blog_old/programmatic-shortcuts-manipulation-part-1#comments Wed, 23 Dec 2015 11:08:05 +0000 http://undocumentedmatlab.com/?p=6146 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. Variables Editor scrolling The Matlab Variables Editor can be accessed to provide immediate scrolling to a specified cell location. ...
  3. Programmatic shortcuts manipulation – part 2 Non-standard shortcut controls and customizations can easily be added to the Matlab desktop. ...
  4. Customizing help popup contents The built-in HelpPopup, available since Matlab R2007b, has a back-door that enables displaying arbitrary text, HTML and URL web-pages....
]]>
User-defined shortcuts can interactively be added to the Matlab Desktop to enable easy access to often-used scripts (e.g., clearing the console, running a certain program, initializing data etc.). Similarly, we can place shortcuts in the help browser to quickly access often-used pages. Unfortunately, both of these shortcut functionalities, like many other functionalities of the Matlab Desktop and related tools (Editor, Browser, Profiler etc.), have no documented programmatic access.

Such programmatic access is often useful. For example, a large company for which I consult is using centralized updates to users’ shortcuts, in order to manage and expose new features for all Matlab users from a central location. It is easy to send updates and manage a few users, but when your organization has dozens of Matlab users, centralized management becomes a necessity. It’s a pity that companies need to resort to external consultants and undocumented hacks to achieve this, but I’m not complaining since it keeps me occupied…

Shortcuts in Matlab R2012a and earlier

Shortcuts in Matlab R2012a and earlier


Shortcuts in Matlab R2012b and newer

Shortcuts in Matlab R2012b and newer


Today’s post will describe “regular” shortcuts – those that are simple clickable buttons. Next week I will show how we can extend this to incorporate other types of shortcut controls, as well as some advanced customizations.

The shortcuts.xml file

It turns out that the shortcults toolbar (on R2012a and earlier) or toolstrip group (on R2012b onward) is a reflection of the contents of the [prefdir ‘\shortcuts.xml’] file (depending on your version, the file might be named somewhat differently, i.e. shortcuts_2.xml). This file can be edited in any text editor, Matlab’s editor included. So a very easy way to programmatically affect the shortcuts is to update this file. Here is a sample of this file:

<?xml version="1.0" encoding="utf-8"?>
<FAVORITESROOT version="2">
   <title>My Shortcuts</title>
   <FAVORITECATEGORY>
      <name>Help Browser Favorites</name>
      <FAVORITE>
         <label>Help Using the Desktop</label>
         <icon>Help icon</icon>
         <callback>helpview([docroot '/mapfiles/matlab_env.map'], 'matlabenvironment_desktop');</callback>
         <editable>true</editable>
      </FAVORITE>
   </FAVORITECATEGORY>
   <FAVORITE>
      <label>CSSM</label>
      <icon>Help icon</icon>
      <callback>disp('No callback specified for this shortcut')</callback>
      <editable>true</editable>
   </FAVORITE>
   <FAVORITE>
      <label>UndocML</label>
      <icon>MATLAB icon</icon>
      <callback>web('undocumentedMatlab.com')</callback>
      <editable>true</editable>
   </FAVORITE>
   <FAVORITE>
      <label>My favorite program</label>
      <icon>C:\Yair\program\icon.gif</icon>
      <callback>cd('C:\Yair\program'); myProgram(123);</callback>
      <editable>true</editable>
   </FAVORITE>
   ...
</FAVORITESROOT>

The file is only loaded once during Matlab startup, so any changes made to it will only take effect after Matlab restarts.

Updating the shortcuts in the current Matlab session

We can update the shortcuts directly, in the current Matlab session, using the builtin com.mathworks.mlwidgets.shortcuts.­ShortcutUtils class. This class has existed largely unchanged for numerous releases (at least as far back as R2008b).

For example, to add a new shortcut to the toolbar:

name = 'My New Shortcut';
cbstr = 'disp(''My New Shortcut'')';  % will be eval'ed when clicked
iconfile = 'c:\path\to\icon.gif';  % default icon if it is not found
isEditable = 'true';
scUtils = com.mathworks.mlwidgets.shortcuts.ShortcutUtils;
category = scUtils.getDefaultToolbarCategoryName;
scUtils.addShortcutToBottom(name,cbstr,iconfile,category,isEditable);

The shortcut’s icon can either be set to a specific icon filepath (e.g., ‘C:\Yair\program\icon.jpg’), or to one of the predefined names: ‘Help icon’, ‘Standard icon’, ‘MATLAB icon’ or ‘Simulink icon’. The editable parameter does not seem to have a visible effect that I could see.

The category name can either be set to the default name using scUtils.getDefaultToolbarCategoryName (‘Shortcuts’ on English-based Matlab R2012b onward), or it can be set to any other name (e.g., ‘My programs’). To add a shortcut to the Help Browser (also known as a “Favorite”), simply set the category to scUtils.getDefaultHelpCategoryName (=’Help Browser Favorites’ on English-based Matlab installations); to add the shortcut to the ‘Start’ button, set the category to ‘Shortcuts’. When you use a non-default category name on R2012a and earlier, you will only see the shortcuts via Matlab’s “Start” button (as seen in the screenshot below); on R2012b onward you will see it as a new category group within the Shortcuts toolstrip (as seen in the screenshot above). For example:

scUtils = com.mathworks.mlwidgets.shortcuts.ShortcutUtils;
scUtils.addShortcutToBottom('clear', 'clear; clc', 'Standard icon', 'Special commands', 'true');

Custom category in Matlab R2010a

Custom category in Matlab R2010a

To remove a shortcut, use the removeShortcut(category,shortcutName) method (note: this method does not complain if the specified shortcut does not exist):

scUtils.removeShortcut('Shortcuts', 'My New Shortcut');

The addShortcutToBottom() method does not override existing shortcuts. Therefore, to ensure that we don’t add duplicate shortcuts, we must first remove the possibly-existing shortcut using removeShortcut() before adding it. Since removeShortcut() does not complain if the specific shortcut is not found, we can safely use it without having to loop over all the existing shortcuts. Alternately, we could loop over all existing category shortcuts checking their label, and adding a new shortcut only if it is not already found, as follows:

scUtils = com.mathworks.mlwidgets.shortcuts.ShortcutUtils;
category = scUtils.getDefaultToolbarCategoryName; 
scVector = scUtils.getShortcutsByCategory(category);
scArray = scVector.toArray;  % Java array
foundFlag = 0;
for scIdx = 1:length(scArray)
   scName = char(scArray(scIdx));
   if strcmp(scName, 'My New Shortcut')
      foundFlag = 1; break;
      % alternatively: scUtils.removeShortcut(category, scName);
   end
end
if ~foundFlag
   scUtils.addShortcutToBottom(scName, callbackString, iconString, category, 'true');
end

As noted above, we can add categories by simply specifying a new category name in the call to scUtils.addShortcutToBottom(). We can also add and remove categories directly, as follows (beware: when removing a category, it is removed together with all its contents):

scUtils.addNewCategory('category name');
scUtils.removeShortcut('category name', []);  % entire category will be deleted

Shortcut tools on the Matlab File Exchange

Following my advice on StackOverflow back in 2010, Richie Cotton wrapped the code snippets above in a user-friendly utility (set of independent Matlab functions) that can now be found on the Matlab File Exchange and on his blog. Richie tested his toolbox on Matlab releases as old as R2008b, but the functionality may also work on even older releases.

Shortcuts panel embedded in Matlab GUI

Shortcuts are normally visible in the toolbar and the Matlab start menu (R2012a and earlier) or the Matlab Desktop’s toolstrip (R2012b onward). However, using com.mathworks.mlwidgets.shortcuts.ShortcutTreePanel, the schortcuts can also be displayed in any user GUI, complete with right-click context-menu:

jShortcuts = com.mathworks.mlwidgets.shortcuts.ShortcutTreePanel;
[jhShortcuts,hPanel] = javacomponent(jShortcuts, [10,10,300,200], gcf);

Shortcuts panel in Matlab figure GUI

Shortcuts panel in Matlab figure GUI

Stay tuned…

Next week I will expand the discussion of Matlab shortcuts with the following improvements:

  1. Displaying non-standard controls as shortcuts: checkboxes, drop-downs (combo-boxes) and toggle-buttons
  2. Customizing the shortcut tooltip (replacing the default tooltip that simply repeats the callback string)
  3. Customizing the shortcut callback (rather than using an eval-ed callback string)
  4. Enabling/disabling shortcuts in run-time

Merry Christmas everyone!

]]>
https://undocumentedmatlab.com/blog_old/programmatic-shortcuts-manipulation-part-1/feed 5
Customizing Matlab uipanelshttps://undocumentedmatlab.com/blog_old/customizing-matlab-uipanels https://undocumentedmatlab.com/blog_old/customizing-matlab-uipanels#comments Wed, 25 Feb 2015 12:24:50 +0000 http://undocumentedmatlab.com/?p=5595 Related posts:
  1. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  2. Customizing Matlab labels Matlab's text uicontrol is not very customizable, and does not support HTML or Tex formatting. This article shows how to display HTML labels in Matlab and some undocumented customizations...
  3. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...
  4. Transparent Matlab figure window Matlab figure windows can be made fully or partially transparent/translucent or blurred - this article explains how...
]]>
The major innovation in Matlab release R2014b was the introduction of the new handle-based graphics system (HG2). However, this release also included a few other improvements to graphics/GUI that should not be overlooked. The most notable is that uitabs are finally officially documented/supported, following a decade or being undocumented (well, undocumented in the official sense, since I took the time to document this functionality in this blog and in my Matlab-Java book).

A less-visible improvement occurred with uipanels: Panels are very important containers when designing GUIs. They enable a visual grouping of related controls and introduce order to an otherwise complex GUI. Unfortunately, until R2014b panels were drawn at the canvas level, and did not use a standard Java Swing controls like other uicontrols. This made it impossible to customize uipanels in a similar manner to other GUI uicontrols (example).

In R2014b, uipanels have finally become standard Java Swing controls, a com.mathworks.hg.peer.ui.UIPanelPeer$UIPanelJPanel component that extends Swing’s standard javax.swing.JPanel and Matlab’s ubiquitous com.mathworks.mwswing.MJPanel. This means that we can finally customize it in various ways that are not available in plain Matlab.

We start the discussion with a simple Matlab code snippet. It is deliberately simple, since I wish to demonstrate only the panel aspects:

figure('Menubar','none', 'Color','w');
hPanel = uipanel('Title','Panel title', 'Units','norm', 'Pos',[.1,.1,.6,.7]);
hButton = uicontrol('String','Click!', 'Parent',hPanel);

Standard Matlab uipanel

Standard Matlab uipanel

Notice the default ‘etchedin’ panel border, which I hate (note the broken edges at the corners). Luckily, Swing includes a wide range of alternative borders that we can use. I’ve already demonstrated customizing Matlab uicontrols with Java borders back in 2010 (has it really been that long? wow!). In R2014b we can finally do something similar to uipanels:

The first step is to get the uipanel‘s underlying Java component’s reference. We can do this using my findjobj utility, but in the specific case of uipanel we are lucky to have a direct shortcut by using the panel’s undocumented hidden property JavaFrame and its PrintableComponent property:

>> jPanel = hPanel.JavaFrame.getPrintableComponent
jPanel =
com.mathworks.hg.peer.ui.UIPanelPeer$UIPanelJPanel[,0,0,97x74,...]

Let’s now take a look at the jPanel‘s border:

>> jPanel.getBorder
ans =
com.mathworks.hg.peer.ui.borders.TitledBorder@25cd9b97
 
>> jPanel.getBorder.get
                Border: [1x1 com.mathworks.hg.peer.ui.borders.EtchedBorderWithThickness]
          BorderOpaque: 0
                 Class: [1x1 java.lang.Class]
                 Title: 'Panel title'
            TitleColor: [1x1 java.awt.Color]
             TitleFont: [1x1 java.awt.Font]
    TitleJustification: 1
         TitlePosition: 2

Ok, simple enough. Let’s replace the border’s EtchedBorderWithThickness with something more appealing. We start with a simple red LineBorder having rounded corners and 1px width:

jColor = java.awt.Color.red;  % or: java.awt.Color(1,0,0)
jNewBorder = javax.swing.border.LineBorder(jColor, 1, true);  % red, 1px, rounded=true
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

Rounded-corners LineBorder

Rounded-corners LineBorder

Or maybe a thicker non-rounded orange border:

jColor = java.awt.Color(1,0.5,0);
jNewBorder = javax.swing.border.LineBorder(jColor, 3, false);  % orange, 3px, rounded=false
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

Another LineBorder example

Another LineBorder example

Or maybe a MatteBorder with colored insets:

jColor = java.awt.Color(0,0.3,0.8);  % light-blue
jNewBorder = javax.swing.border.MatteBorder(2,5,8,11,jColor)  % top,left,bottom,right, color
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

MatteBorder with solid insets

MatteBorder with solid insets

MatteBorder can also use an icon (rather than a solid color) to fill the border insets. First, let’s load the icon. We can either load a file directly from disk, or use one of Matlab’s standard icons. Here are both of these alternatives:

% Alternative #1: load from disk file
icon = javax.swing.ImageIcon('C:\Yair\star.gif');
 
% Alternative #2: load a Matlab resource file
jarFile = fullfile(matlabroot,'/java/jar/mlwidgets.jar');
iconsFolder = '/com/mathworks/mlwidgets/graphics/resources/';
iconURI = ['jar:file:/' jarFile '!' iconsFolder 'favorite_hoverover.png'];  % 14x14 px
icon = javax.swing.ImageIcon(java.net.URL(iconURI));

We can now pass this icon reference to MatteBorder‘s constructor:

w = icon.getIconWidth;
h = icon.getIconHeight;
jNewBorder = javax.swing.border.MatteBorder(h,w,h,w,icon)  % top,left,bottom,right, icon
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

MatteBorder with icon insets

MatteBorder with icon insets

Additional useful Swing borders can be found in the list of classes implementing the Border interface, or via the BorderFactory class. For example, let’s create a dashed border having a 3-2 ratio between the line lengths and the spacing:

jColor = java.awt.Color.blue;  % or: java.awt.Color(0,0,1);
lineWidth = 1;
relativeLineLength = 3;
relativeSpacing = 2;
isRounded = false;
jNewBorder = javax.swing.BorderFactory.createDashedBorder(jColor,lineWidth,relativeLineLength,relativeSpacing,isRounded);
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

StrokeBorder (dashed)

StrokeBorder (dashed)

After seeing all these possibilities, I think you’ll agree with me that Matlab’s standard uipanel borders look pale in comparison.

Have you used any interesting borders in your Matlab GUI? Or have you customized your panels in some other nifty manner? If so, then please place a comment below.

]]>
https://undocumentedmatlab.com/blog_old/customizing-matlab-uipanels/feed 14
Customizing listbox/combobox itemshttps://undocumentedmatlab.com/blog_old/customizing-listbox-combobox-items https://undocumentedmatlab.com/blog_old/customizing-listbox-combobox-items#comments Wed, 17 Sep 2014 12:01:34 +0000 http://undocumentedmatlab.com/?p=5029 Related posts:
  1. UISplitPane UISplitPane was recently chosen as Matlab Central's Pick of the Week. Here I detail its use of some undocumented Matlab features....
  2. Additional uicontrol tooltip hacks Matlab's uicontrol tooltips have several limitations that can be overcome using the control's underlying Java object....
  3. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  4. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...
]]>
Last week I wrote about using a variety of techniques to customize listbox items with an attached checkbox icon. Some of these methods used a standard Matlab listbox uicontrol, others used other controls. Today I wish to extend the discussion and show how Matlab listbox and combobox (pop-up) items can be customized in a variety of ways.

To add icons to listbox/combobox items, we could use standard HTML, as I’ve shown last week. This is the simplest method, requires no Java knowledge, and it usually works well. The problem is that when a listbox/combobox has numerous items (hundreds or more), it may start getting sluggish. In such case it is faster to use a dedicated Java cell-renderer that sets the icon, font, colors, tooltip and other aspects on an item-by-item basis. This runs faster and enables far greater customizability than what is possible with HTML. The drawback is that it requires some Java programming. No free lunch…

Listbox and combobox cell-renderers need to extend javax.swing.ListCellRenderer, similarly to uitable cell-renderers. This is basically a simple Java class that minimally contains just an empty constructor and a getListCellRendererComponent() method with a predefined signature. getListCellRendererComponent() is automatically called by the Swing render engine separately for each listbox item, and gets as input args a JList reference, the item value (typically a string), an integer list index, a boolean flag indicating whether the item is currently selected, and another flag indicating whether the item is currently in focus. getListCellRendererComponent() uses these parameters to customize and return a java.awt.Component, which is typically (but not necessarily) a standard Swing JLabel.

Here is a simple example that displays a folder of icon files in a Matlab listbox and combobox. Each item is the filename, with a customization that if the file is an icon, then this icon is displayed next to the file name, otherwise the name appears in red italic without an icon. For illustration, we’ll use Matlab’s builtin icons folder: %matlabroot%/toolbox/matlab/icons/:

Custom listbox cell-renderer    Custom combobox cell-renderer

Creating the cell renderer

We start by creating a custom ListCellRenderer. Place the following code in a file called LabelListBoxRenderer.java:

import java.awt.*;
import javax.swing.*;
import java.util.Hashtable;
 
public class LabelListBoxRenderer extends JLabel implements ListCellRenderer
{
    private String folderPath;
    private final Hashtable<String,ImageIcon> iconsCache = new Hashtable<String,ImageIcon>();
 
    // Class constructors
    public LabelListBoxRenderer() {
        setOpaque(true);
        setHorizontalAlignment(LEFT);
        setVerticalAlignment(CENTER);
    }
    public LabelListBoxRenderer(String folderPath) {
        this();
        this.folderPath = folderPath;
    }
 
    // Return a label displaying both text and image.
    public Component getListCellRendererComponent(
            JList list,
            Object value,
            int index,
            boolean isSelected,
            boolean cellHasFocus)
    {
        String label = value.toString();
        setFont(list.getFont());
        if (isSelected) {
            // Selected cell item
            setBackground(list.getSelectionBackground());
            setForeground(list.getSelectionForeground());
        } else {
            // Unselected cell item
            setBackground(list.getBackground());
            setForeground(list.getForeground());
        }
        try {
            String iconFname = (folderPath + "/" + label).replace('\\', '/');
            ImageIcon icon = getFileIcon(iconFname);
            setIcon(icon);
            if (icon.getIconWidth() > 0) {
                // Cell item is a valid icon filename
                list.setToolTipText(iconFname + " (" + icon.getIconWidth() + " x " + icon.getIconHeight() + ")");
            } else {
                // Cell item is not an icon filename
                list.setToolTipText(iconFname + " (not an icon)");
                setFont(getFont().deriveFont(Font.ITALIC));
                setForeground(Color.red);
            }
        } catch (Exception e) {
            list.setToolTipText(e.getMessage());
        }
        //System.out.println(index + ": " + label);  // debug console printout
        setText(label);
        return this;
    }
 
    // Modify the folder path (default = current folder)
    public void setFolderPath(String folderPath) {
        this.folderPath = folderPath;
    }
 
    // Lazily load the file icons only as needed, later reuse cached data
    private ImageIcon getFileIcon(String filename) {
        ImageIcon icon;
        if (iconsCache.containsKey(filename)) {
            // Reuse cached data
            icon = iconsCache.get(filename);
        } else {
            // Lazily load the file icons only as needed
            icon = new ImageIcon(filename);
            iconsCache.put(filename, icon);  // store in cache for later use
        }
        return icon;
    }
}

In the code above, I’ve cached the ImageIcons, so that the actual disk file is only accessed once rather than repeatedly whenever the cell needs to be rendered. For even improved performance, we could also cache the tooltips and derived italic font so that they would not be regenerated each time (note that the list’s font is not the same as the cell component’s font) – I will leave this as an exercise to the reader.

Next, compile this file (using the standard javac compiler or any Java IDE), ensuring that you target a JVM compatible with your Matlab (JVM 5 will work on R14SP2 onward, 6 on R2007b onward, and 7 only on R2013b or newer). For convenience, both the source and compiled files for the LabelListBoxRenderer class can be downloaded here: LabelListBoxRenderer.java, LabelListBoxRenderer.class.

Using the cell-renderer in Matlab listboxes

Now that we have a custom cell renderer, we should add the LabelListBoxRenderer.class file to Matlab’s Java classpath using the javaaddpath function and then use this class in Matlab:

% Create the Matlab listbox
iconsFolder = fullfile(matlabroot, 'toolbox/matlab/icons');
files = dir(iconsFolder);
hListbox = uicontrol('Style','list', 'String',{files.name}, 'Position',[10,10,120,150]);
 
% Find the uicontrol's underlying Java component
jScrollpane = findjobj(hListbox);
jListbox = jScrollpane.getViewport.getView;
 
% Update the listbox's cell-renderer
javaaddpath 'C:\Yair\Undocumented Matlab\Work\'   % location of my LabelListBoxRenderer.class
jRenderer = LabelListBoxRenderer(iconsFolder);
jListbox.setCellRenderer(jRenderer);
 
% Give the icons some space...
jListbox.setFixedCellHeight(18);

Custom listbox cell-renderer

Wasn’t too painful was it?

Using the cell-renderer in Matlab combo-boxes

Customizing Matlab combo-boxes is just as easy, and uses the same LabelListBoxRenderer class:

% Create the Matlab combobox
iconsFolder = fullfile(matlabroot, 'toolbox/matlab/icons');
files = dir(iconsFolder);
hCombobox = uicontrol('Style','popup', 'String',{files.name}, 'Position',[10,10,120,150]);
 
% Find the uicontrol's underlying Java component
jCombobox = findjobj(hCombobox);  % no scroll-pane for combos
 
% Update the combobox's cell-renderer
javaaddpath 'C:\Yair\Undocumented Matlab\Work\'   % location of my LabelListBoxRenderer.class
jRenderer = LabelListBoxRenderer(iconsFolder);
jCombobox.setRenderer(jRenderer);  % Note: not setCellRenderer()
 
% Give the icons some space...
jCombobox.setFixedCellHeight(18);
 
% Make the drop-down list shorter than the default (=20 items)
jCombobox.setMaximumRowCount(8);

Custom combobox cell-renderer

For additional aspects of listbox and combobox customizations, refer to sections 6.6 and 6.7 of my Matlab-Java programming book.

]]>
https://undocumentedmatlab.com/blog_old/customizing-listbox-combobox-items/feed 2
Animated busy (spinning) iconhttps://undocumentedmatlab.com/blog_old/animated-busy-spinning-icon https://undocumentedmatlab.com/blog_old/animated-busy-spinning-icon#comments Wed, 16 Apr 2014 08:00:53 +0000 http://undocumentedmatlab.com/?p=4769 Related posts:
  1. Plot-type selection components Several built-in components enable programmatic plot-type selection in Matlab GUI - this article explains how...
  2. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
  3. Auto-completion widget Matlab includes a variety of undocumented internal controls that can be used for an auto-completion component. ...
  4. uigetfile/uiputfile customizations A file-selector dialog window that includes an integrated preview panel is shown and explained. ...
]]>
Matlab includes a wide variety of internal widgets (GUI components) that could be very useful in our GUIs. One such widget is an animated spinning icon, which is often used by Matlab itself and numerous toolboxes to illustrate a running task:

Sample usage of an animated spinning icon

Sample usage of an animated spinning icon

One of the internal widgets that are readily-available for use in our Matlab GUI and displays a similar (but not identical) spinning icon is BusyAffordance, which is included in the built-in com.mathworks.widgets package. BusyAffordance creates a visible panel with an animated spinning icon and optional text label as long as the panel’s object is in the “started” mode (the mode can be started/stopped numerous times).

Animated spinner icon

Animated spinner icon

The usage is very simple:

try
    % R2010a and newer
    iconsClassName = 'com.mathworks.widgets.BusyAffordance$AffordanceSize';
    iconsSizeEnums = javaMethod('values',iconsClassName);
    SIZE_32x32 = iconsSizeEnums(2);  % (1) = 16x16,  (2) = 32x32
    jObj = com.mathworks.widgets.BusyAffordance(SIZE_32x32, 'testing...');  % icon, label
catch
    % R2009b and earlier
    redColor   = java.awt.Color(1,0,0);
    blackColor = java.awt.Color(0,0,0);
    jObj = com.mathworks.widgets.BusyAffordance(redColor, blackColor);
end
jObj.setPaintsWhenStopped(true);  % default = false
jObj.useWhiteDots(false);         % default = false (true is good for dark backgrounds)
javacomponent(jObj.getComponent, [10,10,80,80], gcf);
jObj.start;
    % do some long operation...
jObj.stop;
jObj.setBusyText('All done!');

Note how I’ve used the javacomponent function to place the BusyAffordance object onscreen, at position 10,10 of the current Matlab figure, and gave it an initial size of 80×80 pixels.

When the object is stop()ed, the icon and label are removed by default, but can be displayed un-animated (non-spinning) via the PaintsWhenStopped property:

BusyAffordance started... (animated spinning icon)

BusyAffordance started...
(animated spinning icon)

   
...stopped (PaintsWhenStopped = false)

...stopped
(PaintsWhenStopped = false)

   
...stopped (PaintsWhenStopped = true)

...stopped
(PaintsWhenStopped = true)

The small-icon (16×16) variant of the BusyAffordance control is used by another internal Matlab component, ProgressBarDialog. This control presents an animated progress-bar dialog window, similar to Matlab’s built-in waitbar function but with an animated busy icon:

d = com.mathworks.mlwidgets.dialog.ProgressBarDialog.createProgressBar('test...', []);
d.setValue(0.75);                        % default = 0
d.setProgressStatusLabel('testing...');  % default = 'Please Wait'
d.setSpinnerVisible(true);               % default = true
d.setCircularProgressBar(false);         % default = false  (true means an indeterminate (looping) progress bar)
d.setCancelButtonVisible(true);          % default = true
d.setVisible(true);                      % default = false

ProgressBarDialog with animated BusyAffordance

ProgressBarDialog with animated BusyAffordance

For those interested, the 16×16 animated GIF used here is spinner.gif, which can be found in %matlabroot%/java/jar/mlwidgets.jar (remember that JAR files are simply ZIP files, so they can be opened in WinZip/WinRar etc.). BusyAffordance also includes a 32×32 icon which is not available as a separate icon file. Also, the BusyAffordance spin direction is reversed compared to the spinner icon. From this we learn that BusyAffordance probably creates its spinner image on-the-fly (programmatically), rather than use spinner.gif.

For additional information on BusyAffordance, com.mathworks.widgets and other internal Matlab components, refer to chapter 5 in my Matlab-Java programming book.

As with other internal Matlab components, I categorized this feature as “High risk of breaking in a future release“. Still, BusyAffordance has existed in its present form since R2010a (and with a slightly different interface for years before then), so there’s a good chance that it will continue as-is in the foreseeable future. Then again, it might be removed as early as the next upcoming release, without prior warning…

More advanced animated busy indications, including automated percentage and time-remaining labels, can be specified using JBusyComponent, which is a JXLayer decorator that can be applied to any displayable component. In R2013b or newer that use Java7, we can also use the built-in JLayer class. We can also simply embed the animated GIF image directly in our GUI, as I explained here.

In the past I have already shown how to use other internal components in Matlab’s com.mathworks.widgets package, including syntax-highlighted labels and text panes that can be embedded in our Matlab GUI.

Have you used BusyAffordance or some other internal Matlab component in a neat way in your GUI? if so, please do tell us about it in a comment below.

]]>
https://undocumentedmatlab.com/blog_old/animated-busy-spinning-icon/feed 51
Rich-contents log panelhttps://undocumentedmatlab.com/blog_old/rich-contents-log-panel https://undocumentedmatlab.com/blog_old/rich-contents-log-panel#comments Wed, 18 Sep 2013 14:00:16 +0000 http://undocumentedmatlab.com/?p=4180 Related posts:
  1. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  2. Aligning uicontrol contents Matlab uicontrols can often be customized using plain HTML/CSS, without need for advanced Java. ...
  3. Icon images & text in Matlab uicontrols HTML can be used to add image icons to Matlab listbox and popup (drop-down) controls. ...
  4. Multi-line uitable column headers Matlab uitables can present long column headers in multiple lines, for improved readability. ...
]]>
I often include a log panel in Matlab applications that process data. By sending messages to the log panel, I can avoid msgbox popups and Command Window messages that interfere with the regular workflow. In Matlab, such log panels typically use a simple listbox or editbox control. The problem with this is that all text messages in the log panel look the same. Matlab does not have a documented way to highlight specific messages or words. Well, this has never stopped us before, has it? :-)

The listbox solution

I have often noted in past articles that most Matlab uicontrols support HTML formatting. We can use a listbox control for our log panel, and use HTML formatting for the various log messages, based on their severity or content. For example:

Listbox with HTML'ed items

Listbox with HTML colored items

uicontrol('Style','list', 'Position',[10,10,70,70], 'String', ...
   {'<html><font color="red">Hello</font></html>', 'world', ...
    '<html><font style="font-family:impact;color:green"><i>What a', ...   % note: </i></font></html> are not needed
    '<html><font color="blue" face="Comic Sans MS">nice day!</font>'});   % note: </html> is not needed

Rich listboxes such as this are very easy to set up and use. As I just showed, all it takes is sending an HTML string to a regular listbox. The down-side is that listboxes only display single-line messages, so if our message is too long we need to manually split it into separate listbox lines, which is rather inconvenient. Using HTML <br/> does not work since the allocated line height remains unchanged. We can fix this by playing around with the underlying Java object‘s RowHeight property, but that again is rather inconvenient.

The editbox solution

Instead of a listbox, I often use a multi-line editbox. Unfortunately, HTML is not as-easy to use in multi-line editbox contents, but as I have shown before, it is indeed possible and actually quite powerful. In fact, I am using such an editbox-based log panel’s in my online presentation at the MATLAB Computational Finance Virtual Conference tomorrow (Thursday Sep 19, 2013 at 2pm EST / 8pm CEST, see details below):

Real-time trading system demo in Matlab (click to zoom)

Real-time trading system demo in Matlab (click to zoom)

We can see in the screenshot that some log messages (the red warning message) can span multiple lines. Moreover, the panels can be interactively dragged/resized, making the multi-line log messages “flow” based on available space. So using an editbox is preferable to a listbox. The solution implemented in the demo is quite simple:

First we define the logging utility function (the icon filenames may need to be changed based on your Matlab release):

function logMessage(jEditbox,text,severity)
   % Ensure we have an HTML-ready editbox
   HTMLclassname = 'javax.swing.text.html.HTMLEditorKit';
   if ~isa(jEditbox.getEditorKit,HTMLclassname)
      jEditbox.setContentType('text/html');
   end
 
   % Parse the severity and prepare the HTML message segment
   if nargin < 3,  severity='info';  end
   switch lower(severity(1))
      case 'i',  icon = 'greenarrowicon.gif'; color='gray';
      case 'w',  icon = 'demoicon.gif';       color='black';
      otherwise, icon = 'warning.gif';        color='red';
   end
   icon = fullfile(matlabroot,'toolbox/matlab/icons',icon);
   iconTxt =['<img src="file:///',icon,'" height=16 width=16/>'];
   msgTxt = ['&nbsp;<font color=',color,'>',text,'</font>'];
   newText = [iconTxt,msgTxt];
   endPosition = jEditbox.getDocument.getLength;
   if endPosition>0, newText=['<br />' newText];  end
 
   % Place the HTML message segment at the bottom of the editbox
   currentHTML = char(jEditbox.getText);
   jEditbox.setText(strrep(currentHTML,[60 '/body>'],newText));
   endPosition = jEditbox.getDocument.getLength;
   jEditbox.setCaretPosition(endPosition); % end of content
end

Next, we initialize the log panel editbox and store the editbox’s underlying Java component (jEditbox) using the findjobj utility:

% Prepare the log editbox
hLogPanel = uicontrol('style','edit', 'max',5, 'Parent',hLeftBottomPanel, 'Units','norm', 'Position',[0,0.2,1,0.8], 'Background','w');
 
% Get the underlying Java editbox, which is contained within a scroll-panel
jScrollPanel = findjobj(hLogPanel);
try
    jScrollPanel.setVerticalScrollBarPolicy(jScrollPanel.java.VERTICAL_SCROLLBAR_AS_NEEDED);
    jScrollPanel = jScrollPanel.getViewport;
catch
    % may possibly already be the viewport, depending on release/platform etc.
end
jEditbox = handle(jScrollPanel.getView,'CallbackProperties');

Now, we can use this logging utility function to log messages in our application. For example:

logMessage(jEditbox, 'a regular info message...');
logMessage(jEditbox, 'a warning message...', 'warn');
logMessage(jEditbox, 'an error message!!!', 'error');
logMessage(jEditbox, 'a regular message again...', 'info');

Rich editbox contents (a log file)

Rich editbox contents (a log file)

HTML editboxes are normally editable, images included. In actual applications, we usually wish to prevent editing the displayed log. To do this, we simply call jEditbox.setEditable(false). Similarly, it is easy to set-up a Matlab callback-function to handle hyperlink clicks in the log panel (unlike what we might think, this is not handled automatically by the HTML processing engine):

% Prevent user editing in the log-panel
jEditbox.setEditable(false);
 
% Set-up a Matlab callback function to handle hyperlink clicks
set(jEditbox,'HyperlinkUpdateCallback',@linkCallbackFcn);

About the MATLAB Computational Finance Virtual Conference and my presentation

The MATLAB Computational Finance Virtual Conference is a one-day (Thursday Sep 19, 2013) event of hour-long presentations by industry professionals that showcase real-world examples demonstrating how financial-industry researchers and developers can excel at their jobs, improve their research and business processes, reduce costs, and mitigate risks by using Matlab. Registration to the conference is free and it’s a virtual conference, so there’s no need for a tie and jacket and you’re welcome to join…

MATLAB Computational Finance Conference 2013

My presentation on “A Real-Time Trading System in MATLAB“, is scheduled for 2pm EST / 8pm CEST. Following a half-hour presentation, I will answer audience questions online. The presentation slides can be downloaded here. Here is the recorded presentation video:

The demo system’s user interface showcases the hidden visualization and interactivity potential of Matlab for tracking order executions and charting financial time-series in real time. The undocumented features used in the demo include:

So, even if you’re not interested in real-time financial trading with Matlab, you might find it interesting to see the neat things that Matlab can do using a Java API interface and a few undocumented GUI tricks (such as the rich-contents log that I explained above).

The demo source code is provided here (tradingDemo.m and supporting files). Note that this is provided as-is, free of charge but without any warranty or support. You would naturally need IB-Matlab and an Interactive Brokers account to run it. But you can reuse parts of the source code in your Matlab programs even without an IB account or IB-Matlab.

]]>
https://undocumentedmatlab.com/blog_old/rich-contents-log-panel/feed 15
Images in Matlab uicontrols & labelshttps://undocumentedmatlab.com/blog_old/images-in-matlab-uicontrols-and-labels https://undocumentedmatlab.com/blog_old/images-in-matlab-uicontrols-and-labels#comments Wed, 17 Oct 2012 18:00:57 +0000 http://undocumentedmatlab.com/?p=3177 Related posts:
  1. Rich-contents log panel Matlab listboxes and editboxes can be used to display rich-contents HTML-formatted strings, which is ideal for log panels. ...
  2. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  3. Multi-line tooltips Multi-line tooltips are very easy to set up, once you know your way around a few undocumented hiccups....
  4. Multi-line uitable column headers Matlab uitables can present long column headers in multiple lines, for improved readability. ...
]]>
A couple of weeks ago, a reader here asked how to integrate images in Matlab labels. I see quite a few queries about this, so I wanted to take today’s opportunity to explain how this can be done, and how to avoid common pitfalls.

In fact, there are two main methods of displaying images in Matlab GUI – the documented method, and the undocumented one:

The documented method

Some Matlab uicontrols (buttons, radio and checkboxes) have the CData property that can be used to load and display an image. For example:

imgData = imread('myImage.jpg');   % or: imread(URL)
hButton = uicontrol('CData',imgData, ...);

While label uicontrols (uicontrol(‘style’,’text’, …)) also have the CData property, it has no effect on these controls. Instead, we can create an invisible axes that displays the image using the image function.

The undocumented method

web-based images

I’ve already written extensively about Matlab’s built-in support for HTML in many of its controls. The supported HTML subset includes the <img> tag, and can therefore display images. For example:

htmlStr = '<html><b>Logo</b>: <img src="https://undocumentedmatlab.com/images/logo_68x60.png"/></html>';
hButton = uicontrol('Position',[10,10,120,70], 'String',htmlStr, 'Background','white');

uicontrol with HTML image

uicontrol with HTML image

local images

Note that the image src (filename) needs to be formatted in a URL-compliant format such as 'http://www.website.com/folder/image.gif' or 'file:/c:/folder/subfolder/img.png'. If we try to use a non-URL-format filename, the image will not be rendered, only a placeholder box:

uicontrol('Position',..., 'String','<html><img src="img.gif"/></html>');  %bad
uicontrol('Style','list', ... 'String',{...,'<html><img src="img.gif"/></html>'});  %bad

Ill-specified HTML images in Matlab uicontrols Ill-specified HTML images in Matlab uicontrols

Ill-specified HTML images in Matlab uicontrols

Instead, we need to use correct URI syntax when specifying local images, which means using the 'file:/' protocol prefix and the '/' folder separator:

>> iconsFolder = fullfile(matlabroot,'/toolbox/matlab/icons/');
>> iconUrl = strrep(['file:/' iconsFolder 'matlabicon.gif'],'\','/');
>> str = ['<html><img src="' iconUrl '"/></html>']
str =
<html><img src="file:/C:/Program Files/MATLAB/ ..... /icons/matlabicon.gif"/></html>
 
>> uicontrol('Position',..., 'String',str);
>> uicontrol('Style','list', ... str});

Correctly-specified HTML images in Matlab uicontrols Correctly-specified HTML images in Matlab uicontrols

Correctly-specified HTML images in Matlab uicontrols

A similar pitfall exists when trying to integrate images in GUI control tooltips. I already discussed this issue here.

You can use HTML to resize the images, using the <img> tag’s width, height attributes. However, beware that enlarging an image might introduce pixelization effects. I discussed image resizing here – that article was in the context of menu-item icons, but the discussion of image resizing also applies in this case.

images in text labels

As for text labels, since text-style uicontrols do not unfortunately support HTML, we can use the equivalent Java JLabels, as I have explained here. Here too, we need to use the 'file:/' protocol prefix and the '/' folder separator if we want to use local files rather than internet files (http://…).

Java customizations

Using a uicontrol’s underlying Java component, we can customize the displayed image icon even further. For example, we can specify a different icon for selected/unselected/disabled/hovered/pressed/normal button states, as I have explained here. In fact, we can even specify a unique icon that will be used for the mouse cursor when it hovers on the control:

Custom cursor Custom cursor

Custom uicontrol cursors

]]>
https://undocumentedmatlab.com/blog_old/images-in-matlab-uicontrols-and-labels/feed 28
Customizing menu items part 3https://undocumentedmatlab.com/blog_old/customizing-menu-items-part-3 https://undocumentedmatlab.com/blog_old/customizing-menu-items-part-3#comments Wed, 09 May 2012 18:00:05 +0000 http://undocumentedmatlab.com/?p=2909 Related posts:
  1. Customizing menu items part 2 Matlab menu items can be customized in a variety of useful ways using their underlying Java object. ...
  2. Blurred Matlab figure window Matlab figure windows can be blurred using a semi-transparent overlaid window - this article explains how...
  3. Minimize/maximize figure window Matlab figure windows can easily be maximized, minimized and restored using a bit of undocumented magic powder...
  4. 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. ...
]]>
In the past weeks I’ve shown how Matlab menus can be customized in a variety of undocumented manners, using HTML, pure Matlab, and Java. Today I conclude this mini-series with an article that explains how to use the underlying Java object to customize menu item icons. Menu customizations are explored in depth in section 4.6 of my book.

A reminder: accessing the underlying Java object

Matlab menus (uimenu) are basically simple wrappers for the much more powerful and flexible Java Swing JMenu and JMenuItem on which they are based. Many important functionalities that are available in Java menus are missing from the Matlab uimenus.

Getting the Java reference for the figure window’s main menu is very easy:

jFrame = get(handle(hFig),'JavaFrame');
try
    % R2008a and later
    jMenuBar = jFrame.fHG1Client.getMenuBar;
catch
    % R2007b and earlier
    jMenuBar = jFrame.fFigureClient.getMenuBar;
end

There are many customizations that can only be done using the Java handle: setting icons, several dozen callback types, tooltips, background color, font, text alignment, and so on. etc. Interested readers may wish to get/set/inspect/methodsview/uiinspect the jSave reference handle and/or to read the documentation for JMenuItem. Today’s article will focus on icon customizations.

Setting simple menu item icons

Many of Matlab’s icons reside in either the [matlabroot ‘/toolbox/matlab/icons/’] folder or the [matlabroot ‘/java/jar/mwt.jar’] file (a JAR file is simply a zip file that includes Java classes and resources such as icon images). Let us create icons from the latter, to keep a consistent look-and-feel with the rest of Matlab (we could just as easily use our own external icon files):

% External icon file example
jSave.setIcon(javax.swing.ImageIcon('C:\Yair\save.gif'));
 
% JAR resource example
jarFile = fullfile(matlabroot,'/java/jar/mwt.jar');
iconsFolder = '/com/mathworks/mwt/resources/';
iconURI = ['jar:file:/' jarFile '!' iconsFolder 'save.gif'];
iconURI = java.net.URL(iconURI);  % not necessary for external files
jSave.setIcon(javax.swing.ImageIcon(iconURI));

Note that setting a menu item’s icon automatically re-aligns all other items in the menu, including those that do not have an icon (an internal bug that was introduced in R2010a causes a misalignment, as shown below):

Menu item with a custom Icon (R2009b)

Menu item with a custom Icon (R2009b)

   
...and the same in R2010a onward

...and the same in R2010a onward

Checkmark icon

The empty space on the left of the menu is reserved for the check mark. Each Matlab menu item is check-able, since it is an object that extends the com.mathworks.mwswing.MJCheckBoxMenuItem class. I have not found a way to eliminate this empty space, which is really unnecessary in the File-menu case (it is only actually necessary in the View and Tools menus). Note that if an icon is set for the item, both the icon and the checkmark will be displayed, side by side.

The check mark is controlled by the State property of the Java object (which accepts logical true/false values), or the Checked property of the Matlab handle (which accepts the regular ‘on’/’off’ string values):

% Set the check mark at the Matlab level
set(findall(hFig,'tag','figMenuFileSave'), 'Checked','on');
 
% Equivalent - set the checkmark at the Java level
jSave.setState(true);

State = true, Icon = [ ]

State = true, Icon = [ ]

   
State = true, Icon = custom

State = true, Icon = custom

Customizing menu icons

Icons can be customized: modify the gap between the icon and the label with the IconTextGap property (default = 4 [pixels]); place icons to the right of the label by setting HorizontalTextPosition to jSave.LEFT (=2), or centered using jSave.CENTER (=0). Note that the above-mentioned misalignment bug does not appear in these cases:

jSave.setHorizontalTextPosition(jSave.LEFT)

jSave.setHorizontalTextPosition
(jSave.LEFT)

   
jSave.setHorizontalTextPosition(jSave.CENTER)

jSave.setHorizontalTextPosition
(jSave.CENTER)

Note how the label text can be seen through (or on top of) the icon when it is centered. This feature can be used to create stunning menu effects as shown below. Note how the width and height of the menu item automatically increased to accommodate my new 77×31 icon size (icons are normally sized 16×16 pixels):

Overlaid icon (HorizontalTextPosition = CENTER)

Overlaid icon (HorizontalTextPosition = CENTER)

To resize an icon programmatically before setting it in a Java component, we can use the following example:

myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/matlabicon.gif');
imageToolkit = java.awt.Toolkit.getDefaultToolkit;
iconImage = imageToolkit.createImage(myIcon);
iconImage = iconImage.getScaledInstance(32,32,iconImage.SCALE_SMOOTH);
jSave.setIcon(javax.swing.ImageIcon(iconImage));

Remember when rescaling images, particularly small ones with few pixels, that it is always better to shrink than to enlarge images: enlarging a small icon image might introduce a significant pixelization effect:

16x16 icon image resized to 32x32

16x16 icon image resized to 32x32

Separate icons can be specified for a different appearance during mouse hover (RolloverIcon; requires RolloverEnabled=1), item click/press (PressedIcon), item selection (SelectedIcon, RolloverSelectedIcon, DisabledSelectedIcon), and disabled menu item (DisabledIcon). All these properties are empty ([]) by default, which applies a predefined default variation (image color filter) to the main item’s Icon. For example, let us modify DisabledIcon:

myIcon = 'C:\Yair\Undocumented Matlab\Images\save_disabled.gif';
jSaveAs.setDisabledIcon(javax.swing.ImageIcon(myIcon));
jSaveAs.setEnabled(false);

Enabled, main Icon

Enabled, main Icon

   
Disabled, default Icon variation

Disabled, default Icon variation

   
Disabled, custom DisabledIcon

Disabled, custom DisabledIcon

Note the automatic graying of disabled menu items, including their icon. This effect can also be achieved programmatically using the static methods in com.mathworks.mwswing.IconUtils: changeIconColor(), createBadgedIcon(), createGhostedIcon(), and createSelectedIcon(). When we use a non-default custom DisabledIcon, it is used instead of the gray icon variant.

This concludes my mini-series of customizing menus in Matlab. If you have used any nifty customization that I have not mentioned, please post a comment about it below.

Ken & MikeIn an unrelated note, I would like to extend good wishes to Mike Katz, who has left the MathWorks mobile development team to join Kinvey a few days ago. Mike has been with MathWorks since 2005 and has been responsible for maintaining the official MATLAB Desktop blog, together with Ken Orr. I’m not sure yet which direction the Desktop blog will take, and by whom, but in any case it won’t be the same. You’re both missed, Mike & Ken!

 

]]>
https://undocumentedmatlab.com/blog_old/customizing-menu-items-part-3/feed 39
Uitab colors, icons and imageshttps://undocumentedmatlab.com/blog_old/uitab-colors-icons-images https://undocumentedmatlab.com/blog_old/uitab-colors-icons-images#comments Wed, 10 Nov 2010 18:00:01 +0000 http://undocumentedmatlab.com/?p=1955 Related posts:
  1. 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....
  2. Customizing uitree nodes – part 1 This article describes how to customize specific nodes of Matlab GUI tree controls created using the undocumented uitree function...
  3. Customizing uitree nodes – part 2 This article shows how Matlab GUI tree nodes can be customized with checkboxes and similar controls...
  4. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
]]>
A few months ago I published a post about Matlab’s semi-documented tab-panel functionality, where I promised a follow-up article on tab customizations. A reader of this blog asked a related question earlier today, so I decided it’s about time I fulfilled this promise.

As with most Matlab controls, the underlying Java component enables far greater customization than possible using plain Matlab. Today I will show three specific customizations. We start with a basic tab group, and get the underlying Java component:

% Prevent an annoying warning msg
warning off MATLAB:uitabgroup:OldVersion
 
% Prepare a tab-group consisting of two tabs
hTabGroup = uitabgroup; drawnow;
tab1 = uitab(hTabGroup, 'title','Panel 1');
a = axes('parent', tab1); surf(peaks);
tab2 = uitab(hTabGroup, 'title','Panel 2');
uicontrol(tab2, 'String','Close', 'Callback','close(gcbf)');
 
% Get the underlying Java reference (use hidden property)
jTabGroup = getappdata(handle(hTabGroup),'JTabbedPane');

Foreground & background tab colors

We can set the tab font color using setForeground() and setForegroundAt(), or via HTML. Note that setForegroundAt() overrides anything set by setForeground(). Also remember that Java uses 0-based indexing so tab #1 is actually the second tab:

% Equivalent manners to set a red tab foreground:
jTabGroup.setForegroundAt(1,java.awt.Color(1.0,0,0)); % tab #1
jTabGroup.setTitleAt(1,'<html><font color="red"><i>Panel 2');
jTabGroup.setForeground(java.awt.Color.red);

Unfortunately, the corresponding setBackgroundAt(tabIndex,color) method has no visible effect, and the Matlab-extended tabs keep their white/gray backgrounds. A similar attempt to modify the tab’s BackgroundColor property fails, since Matlab made this property unmodifiable (=’none’). A simple solution is to use a CSS background:

% Equivalent manners to set a yellow tab background:
jTabGroup.setTitleAt(0,'<html><div style="background:#ffff00;">Panel 1');
jTabGroup.setTitleAt(0,'<html><div style="background:yellow;">Panel 1');

uitabgroup with non-default forground and background tab colors and fonts

uitabgroup with non-default forground and background tab colors and fonts

We can set the foreground text color using the CSS color directive. Similarly, we can also set a background gradient image for the tabs, using the CSS background-image directive. Which leads us to our next customization:

Icon images

Icons and sub-components can be added to the tabs. Unfortunately, for some reason that I do not fully understand, jTabGroup.setIconAt() has no apparent effect. The solution is to set our own custom control as the requested tab, and add our icon (or other customizations) to it. Here is a simple example:

% Add an icon to tab #1 (=second tab)
icon = javax.swing.ImageIcon('C:\Yair\save.gif');
jLabel = javax.swing.JLabel('Tab #2');
jLabel.setIcon(icon);
jTabGroup.setTabComponentAt(1,jLabel);	% Tab #1 = second tab
 
% Note: icon is automatically grayed when label is disabled
jLabel.setEnabled(false);
jTabGroup.setEnabledAt(1,false);  % disable only tab #1

tab with a custom icon (enabled)
tab with a custom icon (enabled)

tab with a custom icon (enabled & disabled)

Close buttons

Now let’s try a more complex example, of adding a close (‘x’) button to one of the tabs. Generalizing this code snippet is left as an exercise to the reader:

% First let's load the close icon
jarFile = fullfile(matlabroot,'/java/jar/mwt.jar');
iconsFolder = '/com/mathworks/mwt/resources/';
iconURI = ['jar:file:/' jarFile '!' iconsFolder 'closebox.gif'];
icon = javax.swing.ImageIcon(java.net.URL(iconURI));
 
% Now let's prepare the close button: icon, size and callback
jCloseButton = handle(javax.swing.JButton,'CallbackProperties');
jCloseButton.setIcon(icon);
jCloseButton.setPreferredSize(java.awt.Dimension(15,15));
jCloseButton.setMaximumSize(java.awt.Dimension(15,15));
jCloseButton.setSize(java.awt.Dimension(15,15));
set(jCloseButton, 'ActionPerformedCallback',@(h,e)delete(tab2));
 
% Now let's prepare a tab panel with our label and close button
jPanel = javax.swing.JPanel;	% default layout = FlowLayout
set(jPanel.getLayout, 'Hgap',0, 'Vgap',0);  % default gap = 5px
jLabel = javax.swing.JLabel('Tab #2');
jPanel.add(jLabel);
jPanel.add(jCloseButton);
 
% Now attach this tab panel as the tab-group's 2nd component
jTabGroup.setTabComponentAt(1,jPanel);	% Tab #1 = second tab

tab with an attached close button

tab with an attached close button

Next week’s article will conclude the series on Matlab’s uitab. Any particular customization you are interested in? Please do post a comment.

Addendum Oct 3 2014: the uitab and uitabgroup functions have finally become fully supported and documented in Matlab version 8.4 (R2014b). However, the Java-based customizations shown in this article are still unsupported and undocumented, although they remain practically unchanged from what I’ve described in this article, four years earlier.

]]>
https://undocumentedmatlab.com/blog_old/uitab-colors-icons-images/feed 39
Customizing uitree nodes – part 2https://undocumentedmatlab.com/blog_old/customizing-uitree-nodes-2 https://undocumentedmatlab.com/blog_old/customizing-uitree-nodes-2#comments Wed, 01 Sep 2010 08:00:57 +0000 http://undocumentedmatlab.com/?p=1850 Related posts:
  1. 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....
  2. Uitab colors, icons and images Matlab's semi-documented tab panels can be customized using some undocumented hacks...
  3. Customizing uitree This article describes how to customize Matlab GUI tree controls created using the undocumented uitree function...
  4. Customizing uitree nodes – part 1 This article describes how to customize specific nodes of Matlab GUI tree controls created using the undocumented uitree function...
]]>
In my previous posts I have shown how Matlab’s semi-documented uitree and uitreenode functions can be used to display hierarchical (tree) control in Matlab GUI. Today I conclude this mini-series by answering a reader’s request to show how checkboxes, radio buttons and other similar controls can be attached to tree nodes.

There are actually several ways this can be done:

Matlab icon control

The simplest is to create two icons (checked/unchecked) and switch the node’s icon whenever it is selected (use mtree’s NodeSelectedCallback or jtree’s MouseClickedCallback callbacks) – a sample implementation was posted by Gwendolyn Fischer a couple of years ago, based on even earlier posts by John Anderson, Brad Phelan and me. Here it is, with minor fixes:

function uitree_demo
% function based on treeExperiment6 by John Anderson
% see https://www.mathworks.com/matlabcentral/newsreader/view_thread/104957#269485
%
% The mousePressedCallback part is inspired by Yair Altman
%
% derived from Brad Phelan's tree demo
% create a tree model based on UITreeNodes and insert into uitree.
% add and remove nodes from the treeModel and update the display
import javax.swing.*
import javax.swing.tree.*;
 
% figure window
f = figure('Units', 'normalized');
 
b1 = uicontrol( 'string','add Node', ...
   'units' , 'normalized', ...
   'position', [0 0.5 0.5 0.5], ...
   'callback', @b1_cb);
 
b2 = uicontrol( 'string','remove Node', ...
   'units' , 'normalized', ...
   'position', [0.5 0.5 0.5 0.5], ...
   'callback', @b2_cb);
 
%[I,map] = imread([matlab_work_path, '/checkedIcon.gif']);
[I,map] = checkedIcon;
javaImage_checked = im2java(I,map);
 
%[I,map] = imread([matlab_work_path, '/uncheckedIcon.gif']);
[I,map] = uncheckedIcon;
javaImage_unchecked = im2java(I,map);
 
% javaImage_checked/unchecked are assumed to have the same width
iconWidth = javaImage_unchecked.getWidth;
 
% create top node
rootNode = uitreenode('v0','root', 'File List', [], 0);
% [matlab_work_path, '/fileListIcon.gif'],0);
 
% create two children with checkboxes
cNode = uitreenode('v0','unselected', 'File A', [], 0);
% as icon is embedded here we set the icon via java, otherwise one could
% use the uitreenode syntax uitreenode(value, string, icon, isLeaf) with
% icon being a qualified pathname to an image to be used.
cNode.setIcon(javaImage_unchecked);
rootNode.add(cNode);
 
cNode = uitreenode('v0','unselected', 'File B', [], 0);
cNode.setIcon(javaImage_unchecked);
rootNode.add(cNode);
 
% set treeModel
treeModel = DefaultTreeModel( rootNode );
 
% create the tree
tree = uitree('v0');
tree.setModel( treeModel );
% we often rely on the underlying java tree
jtree = handle(tree.getTree,'CallbackProperties');
% some layout
drawnow;
set(tree, 'Units', 'normalized', 'position', [0 0 1 0.5]);
set(tree, 'NodeSelectedCallback', @selected_cb );
 
% make root the initially selected node
tree.setSelectedNode( rootNode );
 
% MousePressedCallback is not supported by the uitree, but by jtree
set(jtree, 'MousePressedCallback', @mousePressedCallback);
 
  % Set the mouse-press callback
  function mousePressedCallback(hTree, eventData) %,additionalVar)
  % if eventData.isMetaDown % right-click is like a Meta-button
  % if eventData.getClickCount==2 % how to detect double clicks
 
  % Get the clicked node
    clickX = eventData.getX;
    clickY = eventData.getY;
    treePath = jtree.getPathForLocation(clickX, clickY);
    % check if a node was clicked
    if ~isempty(treePath)
      % check if the checkbox was clicked
      if clickX <= (jtree.getPathBounds(treePath).x+iconWidth)
        node = treePath.getLastPathComponent;
        nodeValue = node.getValue;
        % as the value field is the selected/unselected flag,
        % we can also use it to only act on nodes with these values
        switch nodeValue
          case 'selected'
            node.setValue('unselected');
            node.setIcon(javaImage_unchecked);
            jtree.treeDidChange();
          case 'unselected'
            node.setValue('selected');
            node.setIcon(javaImage_checked);
            jtree.treeDidChange();
        end
      end
    end
  end % function mousePressedCallback
 
  function selected_cb( tree, ev )
    nodes = tree.getSelectedNodes;
    node = nodes(1);
    path = node2path(node);
  end
 
  function path = node2path(node)
    path = node.getPath;
    for i=1:length(path);
      p{i} = char(path(i).getName);
    end
    if length(p) > 1
      path = fullfile(p{:});
    else
      path = p{1};
    end
  end
 
  % add node
  function b1_cb( h, env )
    nodes = tree.getSelectedNodes;
    node = nodes(1);
    parent = node;
    childNode = uitreenode('v0','dummy', 'Child Node', [], 0);
    treeModel.insertNodeInto(childNode,parent,parent.getChildCount());
 
    % expand to show added child
    tree.setSelectedNode( childNode );
 
    % insure additional nodes are added to parent
    tree.setSelectedNode( parent );
  end
 
  % remove node
  function b2_cb( h, env )
    nodes = tree.getSelectedNodes;
    node = nodes(1);
    if ~node.isRoot
      nP = node.getPreviousSibling;
      nN = node.getNextSibling;
      if ~isempty( nN )
        tree.setSelectedNode( nN );
      elseif ~isempty( nP )
        tree.setSelectedNode( nP );
      else
        tree.setSelectedNode( node.getParent );
      end
      treeModel.removeNodeFromParent( node );
    end
  end
end % of main function treeExperiment6
 
  function [I,map] = checkedIcon()
    I = uint8(...
        [1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0;
         2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,1;
         2,2,2,2,2,2,2,2,2,2,2,2,0,2,3,1;
         2,2,1,1,1,1,1,1,1,1,1,0,2,2,3,1;
         2,2,1,1,1,1,1,1,1,1,0,1,2,2,3,1;
         2,2,1,1,1,1,1,1,1,0,1,1,2,2,3,1;
         2,2,1,1,1,1,1,1,0,0,1,1,2,2,3,1;
         2,2,1,0,0,1,1,0,0,1,1,1,2,2,3,1;
         2,2,1,1,0,0,0,0,1,1,1,1,2,2,3,1;
         2,2,1,1,0,0,0,0,1,1,1,1,2,2,3,1;
         2,2,1,1,1,0,0,1,1,1,1,1,2,2,3,1;
         2,2,1,1,1,0,1,1,1,1,1,1,2,2,3,1;
         2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
         2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,1;
         2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,1;
         1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1]);
     map = [0.023529,0.4902,0;
            1,1,1;
            0,0,0;
            0.50196,0.50196,0.50196;
            0.50196,0.50196,0.50196;
            0,0,0;
            0,0,0;
            0,0,0];
  end
 
  function [I,map] = uncheckedIcon()
     I = uint8(...
       [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1;
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1;
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,1,1,1,1,1,1,1,1,1,1,2,2,3,1;
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,1;
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,1;
        1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1]);
     map = ...
      [0.023529,0.4902,0;
       1,1,1;
       0,0,0;
       0.50196,0.50196,0.50196;
       0.50196,0.50196,0.50196;
       0,0,0;
       0,0,0;
       0,0,0];
  end

uitree with custom checkbox icons

uitree with custom checkbox icons

Custom Java classes

An alternative is to create a custom tree Java class and/or a custom TreeCellRenderer/TreeCellEditor. Specifically, to change the icons of each node you have to implement your own java component which derives from DefaultMutableTreeNode.

Some online resources to get you started:

Built-in classes

Another option is to use Matlab’s built-in classes, either com.mathworks.mwswing.checkboxtree.CheckBoxTree or com.jidesoft.swing.CheckBoxTree:

import com.mathworks.mwswing.checkboxtree.*
jRoot = DefaultCheckBoxNode('Root');
l1a = DefaultCheckBoxNode('Letters'); jRoot.add(l1a);
l1b = DefaultCheckBoxNode('Numbers'); jRoot.add(l1b);
l2a = DefaultCheckBoxNode('A'); l1a.add(l2a);
l2b = DefaultCheckBoxNode('b'); l1a.add(l2b);
l2c = DefaultCheckBoxNode('<html><b>&alpha;'); l1a.add(l2c);
l2d = DefaultCheckBoxNode('<html><i>&beta;'); l1a.add(l2d);
l2e = DefaultCheckBoxNode('3.1415'); l1b.add(l2e);
 
% Present the standard MJTree:
jTree = com.mathworks.mwswing.MJTree(jRoot);
jScrollPane = com.mathworks.mwswing.MJScrollPane(jTree);
[jComp,hc] = javacomponent(jScrollPane,[10,10,120,110],gcf);
 
% Now present the CheckBoxTree:
jCheckBoxTree = CheckBoxTree(jTree.getModel);
jScrollPane = com.mathworks.mwswing.MJScrollPane(jCheckBoxTree);
[jComp,hc] = javacomponent(jScrollPane,[150,10,120,110],gcf);

a regular MJTree (left) and a CheckBoxTree (right)

a regular MJTree (left) and a CheckBoxTree (right)

Note: Matlab’s CheckBoxTree does not have a separate data model. Instead, it relies on the base MJTree’s model, which is a DefaultTreeModel by default. JIDE’s CheckBoxTree does have its own model.

This concludes my uitree mini-series. If you have any special customizations, please post a comment below.

]]>
https://undocumentedmatlab.com/blog_old/customizing-uitree-nodes-2/feed 61
Figure toolbar componentshttps://undocumentedmatlab.com/blog_old/figure-toolbar-components https://undocumentedmatlab.com/blog_old/figure-toolbar-components#comments Thu, 27 Aug 2009 16:31:36 +0000 http://undocumentedmatlab.com/?p=541 Related posts:
  1. Uitab colors, icons and images Matlab's semi-documented tab panels can be customized using some undocumented hacks...
  2. Customizing uitree nodes – part 2 This article shows how Matlab GUI tree nodes can be customized with checkboxes and similar controls...
  3. Customizing uitree This article describes how to customize Matlab GUI tree controls created using the undocumented uitree function...
  4. Customizing uitree nodes – part 1 This article describes how to customize specific nodes of Matlab GUI tree controls created using the undocumented uitree function...
]]>
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 (Command 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 another post I 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

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

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

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.

]]>
https://undocumentedmatlab.com/blog_old/figure-toolbar-components/feed 48
Button customizationhttps://undocumentedmatlab.com/blog_old/button-customization https://undocumentedmatlab.com/blog_old/button-customization#comments Fri, 24 Apr 2009 05:51:04 +0000 http://undocumentedmatlab.com/?p=184 Related posts:
  1. Uicontrol callbacks This post details undocumented callbacks exposed by the underlying Java object of Matlab uicontrols, that can be used to modify the control's behavior in a multitude of different events...
  2. FindJObj GUI – display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
  3. Rich Matlab editbox contents The Matlab editbox uicontrol does not handle HTML contents as do other uicontrols. In this article I show how this limitation can be removed....
  4. Setting line position in an edit-box uicontrol Matlab uicontrols have many useful features that are only available via Java. Here's how to access them....
]]>
Matlab’s button uicontrols (pushbutton and togglebutton) are basically wrappers for a Java Swing JButton object.

This will be the first in a series of posts showing how Matlab uicontrols can be customized in ways that you may never have thought possible.

Probably the simplest undocumented customization is the control’s acceptance of HTML and CSS Strings:

tooltip = '<html>HTML-aware<br><b>tooltips</b><br><i>supported';
labelTop= '<HTML><center><FONT color="red">Hello</Font> <b>world</b>';
labelBot=['<div style="font-family:impact;color:green"><i>What a</i>'...
          ' <Font color="blue" face="Comic Sans MS">nice day!'];
set(hButton, 'tooltip',tooltip, 'string',[labelTop '<br>' labelBot]);

Button with HTML label and tooltip

Button with HTML label and tooltip

For more powerful customization, we need to access the control’s underlying JList object. We do this by using my FindJObj submission on the File Exchange (which was explained here):

>> jButton = java(findjobj(hButton))
jButton =
com.mathworks.hg.peer.PushButtonPeer$1[,0,0,...]

Now that we have the jButton Java object reference, we can use get and set just like any Matlab handle. To see the list of all available properties, methods and callbacks, we can use my UIINSPECT submission on the File Exchange, or use Matlab’s built-in methodsview function.

This post is too short to present all the numerous ways in which the control can be customized with the Java properties and methods. Let’s list some of the more interesting properties:

  • Border – specified the border frame around the button, which is responsible for its 3D appearance. It can be modified to anything from a simple colored borderline to a recurring icon-pattern, as shown here. If set to [] then the button achieves a flat appearance, which can be useful for displaying click-able labels. For example, the blog hyperlink at the bottom of the FindJObj window is a simple button with no border, an HTML label and a callback that opens this blog webpage using the built-in web function:
    Button appearing as a hyperlink label

    Button appearing as a hyperlink label

  • Cursor – this can be used to set a control-specific cursor. For example, in the hyperlink button above, the cursor was set to: java.awt.Cursor(java.awt.Cursor.HAND_CURSOR). In another post I’ll show how to set a custom cursor, like the following Matlab icon:
    Custom cursor

    Custom cursor

    Note: This feature only works on R2013a and earlier; custom cursors are ignored in Matlab R2013b and newer (see here).

  • DisplayedMnemonicIndex – (default=-1) indicates the character position within the text label where the Mnemonic (i.e, keyboard shortcut) should be displayed. Associated property Mnemonic (default=0) indicates the ASCII code of the mnemonic. In the following case, DisplayedMnemonicIndex=3 (remember that Java indices start at 0) and Mnemonic=73 (=’r’):
    Button With mnemonic

    Button With mnemonic

  • Margin, VerticalAlignment, HorizontalAlignment – these properties enable setting the label contents with respect to its borders. For example:
    Top-left with 8-pixel top margin

    Top-left with 8-pixel top margin

  • Icon, DisabledIcon, DisabledSelectedIcon, PressedIcon, RolloverIcon, RolloverSelectedIcon, SelectedIcon – these icons may be set to present a different appearance depending on component state. Associated property IconTextGap (default=4) determines the gap in pixels between the icon and the button text label. Associated properties HorizontalTextPosition and VerticalTextPosition specify the label text’s alignment relative to the label icon. These two properties accept the same SwingConstants values as HorizontalAlignment and VerticalAlignment above. For example, let’s display an icon to the right and upward of the text:
    
    myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/warning.gif');
    jButton.setIcon(javax.swing.ImageIcon(myIcon));
    jButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
    jButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
    

    Button with text and icon

    Button with text and icon

  • MultiClickThreshhold – (default=0) sets the number of milliseconds between subsequent processed user mouse clicks on the button. Any clicks that occur within the specified number (e.g., fast double-clicks) will be considered by the component as only a single click. The default value of 0 means that all clicks will be processed separately, which is often undesirable in GUI applications. Remember that the value is in milliseconds, not seconds.
  • FlyOverAppearance – boolean flag (default=false); if set, the button appearance is changed to a flat (2D) appearance with a special 3D border effect displayed on mouse hover. This appearance is useful for toolbar buttons, and is an extension by Matlab’s button implementation (does not exist in the standard Swing class).

There are quite a few other useful properties, methods (for example, jButton.doClick() to programmatically click a button) and even some 30 callbacks, detailed in a separate post. The list above is by no way comprehensive – I hope it whet your appetites for exploration using FindJObj and UIINSPECT – it’s a fun ride and the GUI rewards are worth the effort!

Please let me know of any nice customizations in your Matlab applications. Leave a comment below or drop me an email.

]]>
https://undocumentedmatlab.com/blog_old/button-customization/feed 30
Setting system tray popup messageshttps://undocumentedmatlab.com/blog_old/setting-system-tray-popup-messages https://undocumentedmatlab.com/blog_old/setting-system-tray-popup-messages#comments Tue, 31 Mar 2009 23:09:25 +0000 http://undocumentedmatlab.com/?p=130 Related posts:
  1. Setting system tray icons System-tray icons can be programmatically set and controlled from within Matlab, using new functionality available since R2007b....
  2. Modifying Matlab’s Look-and-Feel Matlab's entire Look-and-Feel (PLAF, or L&F) can be modified at the control or application level - this article shows how...
  3. Uitab colors, icons and images Matlab's semi-documented tab panels can be customized using some undocumented hacks...
  4. Customizing menu items part 3 Matlab menu items can easily display custom icons, using just a tiny bit of Java magic powder. ...
]]>
Continuing my previous post about setting system-tray icons, I will now show how to set informational popup messages next to these icons.

Asynchronous informational messages can be presented next to the sys-tray icon, in a fashion similar to what we came to expect from modern programs. This could be used to indicate some unexpected event that was detected, or the end of a complex calculation phase. The message title, text and severity icon are all customizable.

Unfortunately, the Java method used to display messages, java.awt.TrayIcon.displayMessage(), expects an object of type java.awt.TrayIcon.MessageType, which is an enumeration within the TrayIcon class. However, Matlab’s dot-notation does not recognize what should have been the following correct notation, so we need to resort to Java reflection:

>> trayIcon.displayMessage('title','info msg',TrayIcon.MessageType.INFO);
??? No appropriate method or public field MessageType for class java.awt.TrayIcon

>> trayIconClasses = trayIcon.getClass.getClasses;
>> trayIconClasses(1)
ans =
class java.awt.TrayIcon$MessageType	<= hurray!!!
>> MessageTypes = trayIconClasses(1).getEnumConstants
MessageTypes =
java.awt.TrayIcon$MessageType[]:
    [java.awt.TrayIcon$MessageType]	<= 1: ERROR
    [java.awt.TrayIcon$MessageType]	<= 2: WARNING
    [java.awt.TrayIcon$MessageType]	<= 3: INFO
    [java.awt.TrayIcon$MessageType]	<= 4: NONE
>> trayIcon.displayMessage('title','info msg',MessageTypes(3));

systray INFO message

and another example, now with a WARNING icon:

systray WARNING message

If the title string is left empty, then neither title nor the severity icon will be displayed. The message can still be manually dismissed by clicking within its boundaries:


systray messages without a title (hence also without a severity icon)
systray messages without a title (hence also without a severity icon)

Informational popup messages are automatically aligned and positioned by the system. Messages are automatically dismissed by the system after some time, if not dismissed by the user first. The exact time is determined by system and user activity and other such external factors. Informational messages replace one another, if the previous message has still not been cleared by the user.

I have created a utility function called SYSTRAY, which is a convenience function that facilitates the setup and update of system tray icons and messages. SYSTRAY (with source code) can be downloaded from the File Exchange.

I would be happy to hear if and how you’re using the new system-tray functionality in your application – let me know below.

]]>
https://undocumentedmatlab.com/blog_old/setting-system-tray-popup-messages/feed 21
Setting system tray iconshttps://undocumentedmatlab.com/blog_old/setting-system-tray-icons https://undocumentedmatlab.com/blog_old/setting-system-tray-icons#comments Tue, 24 Mar 2009 20:47:54 +0000 http://undocumentedmatlab.com/?p=67 Related posts:
  1. Setting system tray popup messages System-tray icons and messages can be programmatically set and controlled from within Matlab, using new functionality available since R2007b....
  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 uitree nodes – part 2 This article shows how Matlab GUI tree nodes can be customized with checkboxes and similar controls...
  4. Customizing menu items part 3 Matlab menu items can easily display custom icons, using just a tiny bit of Java magic powder. ...
]]>
Java 1.6, included in Matlab releases since Matlab 7.5 (R2007b), enables programmatic access to system tray icons on such systems that support this functionality (Windows, Linux and possibly others).  If the SystemTray object indicates that it isSupported(), then a TrayIcon can be added, along with an associated tooltip and popup menu:

sysTray = java.awt.SystemTray.getSystemTray;
if (sysTray.isSupported)
   myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/matlabicon.gif');
   iconImage = java.awt.Toolkit.getDefaultToolkit.createImage(myIcon);
   trayIcon = java.awt.TrayIcon(iconImage, 'initial tooltip');
   trayIcon.setToolTip('click this icon for applicative context menu');
end

sample system tray icon

sample system tray icon

The icon image can be made to automatically resize to the system-tray dimensions, using the trayIcon.setImageAutoSize(true) method (by default the icon image will maintain its original size, getting cropped or appearing small as the case may be).

Of course, after initial setup, all the sys-tray icon’s properties (icon image, popup, tooltip etc.) can be modified with convenient set methods (setImage(), setPopupMenu(), setTooltip()) or via Matlab’s set() function.

Icon popup menus are very similar in concept to Matlab uicontextmenus. Unfortunately, they need to be programmed separately since Java does not accept uicontextmenu handles. This is actually quite easy, as the following code snippet shows:

% Prepare the context menu
menuItem1 = java.awt.MenuItem('action #1');
menuItem2 = java.awt.MenuItem('action #2');
menuItem3 = java.awt.MenuItem('action #3');

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

% Disable one of the menu items
menuItem2.setEnabled(0);        % or: set(menuItem2,'Enabled','off');

% Add all menu items to the context menu (with internal separator)
jmenu = java.awt.PopupMenu;
jmenu.add(menuItem1);
jmenu.add(menuItem2);
jmenu.addSeparator;
jmenu.add(menuItem3);

% Finally, attach the context menu to the icon
trayIcon.setPopupMenu(jmenu);    % or: set(trayIcon,'PopupMenu',jmenu);

Tray icon context (right-click) menu

Tray icon context (right-click) menu

Unfortunately, neither the icon tooltip nor its popup menu supports HTML. The reason is that SystemTray is actually not part of Swing at all. The system-tray functionality resides in the java.awt package, and does not inherit javax.swing.JLabel’s (and Matlab uicontrols) support for HTML.

I have created a utility function called SYSTRAY, which is a convenience function that facilitates the setup and update of system tray icons. SYSTRAY (with source code) can be downloaded from the File Exchange.

In a separate post, I shall detail how informational pop-up messages can be attached to system-tray icons. This requires a bit of Java-hacking, so is beyond the scope of a single blog post.

Please note the new TODO page, which details my future posts. I would be happy to hear your requests for new topics, or telling me which topics you’d like to see earlier than others.

Addendum (May 15, 2009): A kind reader today left a comment on another post of this blog with a solution for some reported Java exceptions when using systray in Matlab R2008b onward.

]]>
https://undocumentedmatlab.com/blog_old/setting-system-tray-icons/feed 15