Programmatic shortcuts manipulation – part 1

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!

Categories: Desktop, High risk of breaking in future versions, Icons, Undocumented feature

Tags: , , ,

Bookmark and SharePrint Print

5 Responses to Programmatic shortcuts manipulation – part 1

  1. Andi says:

    Yair

    Thank you for addressing the shortcut customization in MatLab.

    The code to update the shortcuts during a session, which is discussed in your article, works very well in MatLab 2012a. However, it does not work reliably in MatLab 2015a, even though I tried to adapt it.

    I have addressed this issue with Mathworks. The response was that they do not support this functionality.

    I have also done some work, where I have tried to update the quick access toolbar, but again found, that is works very unreliably.

    I am very interested in solutions for both issues, which work in MatLab 2015a.

    Thanks, Andi

    • @Andi – I am not sure what exactly is not working for you in R2015a – it works well for me up to and including R2016a. Try to add a short pause() before you update the shortcuts on startup, maybe this will help. If you would like me to look at your specific issue for a small consulting fee, then email me.

  2. Thierry says:

    Hi Yair.
    Thanks for this post!
    Do you know a way to programmatically assign the created shortcut to the Quick Access Toolbar?
    (This way the shortcuts are also visible on the MATLAB Editor.)
    Many thanks.

  3. Julien says:

    Thanks a lot for these tips, it works very well on Matlab 2016b.
    It seems since the R2018a, shortcuts have disappeared to be replaced by favorites commands… do you have any idea on how to manipulate favorites programatically ?

    I saw this on Matlab Central : https://www.mathworks.com/matlabcentral/answers/411846-how-to-create-favorites-by-code-command-window
    But there is no solution.

    • michel bertrand says:

      There is a solution to create categories and get favorites, code, etc posted on nov 27.
      I am playing with these ideas, and in the process of re-writing the Matlab code I wrote and maintained for more than ten years (following a Yair’suggestions, also many years ago) to save shortcuts when exiting Matlab so as to be able to restore those as they were on a specific day when exiting Matlab; a kind of laymen time machine for shortcuts.

      I found scUtils still “works” in Matlab2018b, but it appears to process something which is distinct from the Favorites that were created when I first launched Maltab2018.
      My first launching of Matlab2018b a few weeks ago followed a Matlab session ending under Matlab 2017b. On its first opening, Matlab2018b did some clean up on shortcuts it found and created their Favorites counterpart using the same name and the same code.
      In my current usage of 2018b, scUtils can still see the old shortcuts and it will give shortcut names and code line exactly the same as those appearing under Favorites, provided those Favorites haven’t been modified with the favorite editor; after a favorite is edited, rerunning scUtils will show the original code, unchanged.

Leave a Reply

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