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…
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');
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);
Stay tuned…
Next week I will expand the discussion of Matlab shortcuts with the following improvements:
- Displaying non-standard controls as shortcuts: checkboxes, drop-downs (combo-boxes) and toggle-buttons
- Customizing the shortcut tooltip (replacing the default tooltip that simply repeats the callback string)
- Customizing the shortcut callback (rather than using an eval-ed callback string)
- Enabling/disabling shortcuts in run-time
Merry Christmas everyone!
Related posts:
- Programmatic shortcuts manipulation – part 2 Non-standard shortcut controls and customizations can easily be added to the Matlab desktop. ...
- Customizing menu items part 3 Matlab menu items can easily display custom icons, using just a tiny bit of Java magic powder. ...
- JMI wrapper – local MatlabControl part 2 An example using matlabcontrol for calling Matlab from within a Java class is explained and discussed...
- JMI wrapper – local MatlabControl part 1 MatlabControl is an open-source wrapper of JMI that allows an easy and documented way to communicate from Java to Matlab. This article describes this wrapper....