Desktop – 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 Matlab toolstrip – part 1https://undocumentedmatlab.com/blog_old/matlab-toolstrip-part-1 https://undocumentedmatlab.com/blog_old/matlab-toolstrip-part-1#comments Mon, 03 Sep 2018 15:00:22 +0000 https://undocumentedmatlab.com/?p=7952 Related posts:
  1. Setting status-bar text The Matlab desktop and figure windows have a usable statusbar which can only be set using undocumented methods. This post shows how to set the status-bar text....
  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. Variables Editor scrolling The Matlab Variables Editor can be accessed to provide immediate scrolling to a specified cell location. ...
  4. Programmatic shortcuts manipulation – part 1 Matlab Desktop shortcuts can be programmatically accessed and customized. ...
]]>
The Matlab toolstrip (ribbon) has been around officially since R2012a, and unofficially for a couple of years earlier. Since then, I blogged about the toolstrip only rarely (example). I believe the time has come to start a short mini-series about this functionality, eventually showing how users can use toolstrips in their own custom applications.

My plan is to start the miniseries with a discussion of the built-in showcase examples, followed by a post on the built-in classes that make up the toolstrip building-blocks. Finally, I’ll describe how toolstrips can be added to figures, not just in client/tool groups.

Matlab’s internal showcase examples

I start the discussion with a description of built-in examples for the toolstrip functionality, located in %matlabroot%/toolbox/matlab/toolstrip/+matlab/+ui/+internal/+desktop/. The most important of these are showcaseToolGroup.m and showcaseMPCDesigner.m, both of which use Java-based (Swing) containers and controls. Readers who wish to integrate toolstrips into their app immediately, without waiting for my followup posts in this series, are welcome to dig into the examples’ source-code and replicate it in their programs:

1. showcaseToolGroup
h = matlab.ui.internal.desktop.showcaseToolGroup

showcaseToolGroup built-in example

2. showcaseMPCDesigner
>> h = matlab.ui.internal.desktop.showcaseMPCDesigner
 
h =
  showcaseMPCDesigner with properties:
 
    ToolGroup: [1×1 matlab.ui.internal.desktop.ToolGroup]
       Dialog: [1×1 toolpack.component.TSTearOffPopup]
      Figure1: [1×1 Figure]
      Figure2: [1×1 Figure]

showcaseMPCDesigner built-in example

3. showcaseHTML and showcaseCEF

In addition to these showcase examples, the folder also contains a showcaseHTML.m and showcaseCEF.m files, that are supposed to showcase the toolstrip functionality in JavaScript-based containers (browser webpage and uifigure apps, respectively). Unfortunately, on my system running these classes displays blank, although the toolstrip is indeed created, as seen below (if you find out how to make these classes work, please let me know):

>> h = matlab.ui.internal.desktop.showcaseHTML
building toolstrip hierarchy...
rendering toolstrip...
 
h = 
  Toolstrip with properties:
 
               SelectedTab: [1×1 matlab.ui.internal.toolstrip.Tab]
              DisplayState: 'expanded'
    DisplayStateChangedFcn: @PropertyChangedCallback
                       Tag: 'toolstrip'
 
>> hs = struct(h)
Warning: Calling STRUCT on an object prevents the object from hiding its implementation details and should thus be avoided.
Use DISP or DISPLAY to see the visible public details of an object. See 'help struct' for more information.
(Type "warning off MATLAB:structOnObject" to suppress this warning.)
 
hs = 
  struct with fields:
 
                         SelectedTab: [1×1 matlab.ui.internal.toolstrip.Tab]
                        DisplayState: 'expanded'
              DisplayStateChangedFcn: @PropertyChangedCallback
                 DisplayStatePrivate: 'expanded'
                        QABIdPrivate: '2741bf89'
               QuickAccessBarPrivate: [1×1 matlab.ui.internal.toolstrip.impl.QuickAccessBar]
       DisplayStateChangedFcnPrivate: @PropertyChangedCallback
         SelectedTabChangedListeners: [1×1 event.listener]
                                 Tag: 'toolstrip'
                                Type: 'Toolstrip'
                          TagPrivate: 'toolstrip'
    WidgetPropertyMap_FromMCOSToPeer: [3×1 containers.Map]
    WidgetPropertyMap_FromPeerToMCOS: [3×1 containers.Map]
                              Parent: [0×0 matlab.ui.internal.toolstrip.base.Node]
                            Children: [1×1 matlab.ui.internal.toolstrip.TabGroup]
                             Parent_: []
                           Children_: [1×1 matlab.ui.internal.toolstrip.TabGroup]
                                Peer: [1×1 com.mathworks.peermodel.impl.PeerNodeImpl]
                   PropertySetSource: [1 java.util.HashMap]
                    PeerModelChannel: '/ToolstripShowcaseChannel'
                   PeerEventListener: [1×1 handle.listener]
                 PropertySetListener: [1×1 handle.listener]
 
>> hs.Peer
ans =
PeerNodeImpl{id='4a1e4b08', type='Toolstrip', properties={displayState=expanded, hostId=ToolStripShowcaseDIV, tag=toolstrip, QABId=2741bf89}, parent=878b0e2b, children=[
    PeerNodeImpl{id='5bb9632c', type='TabGroup', properties={QAGroupId=ea9b628c, tag=, selectedTab=f90db10c}, parent=4a1e4b08, children=[
        PeerNodeImpl{id='f90db10c', type='Tab', properties={mnemonic=, tag=tab_buttons, title=BUTTONS}, parent=5bb9632c, children=[
            PeerNodeImpl{id='1ccc9246', type='Section', properties={collapsePriority=0.0, mnemonic=, tag=sec_push, title=PUSH BUTTON}, parent=f90db10c, children=[
                PeerNodeImpl{id='8323f06e', type='Column', properties={horizontalAlignment=left, width=0.0, tag=}, parent=1ccc9246, children=[
                    PeerNodeImpl{id='af368d7b', type='PushButton', properties={textOverride=, descriptionOverride=, mnemonic=, actionId=230d471b, iconOverride=, tag=pushV, iconPathOverride=}, parent=8323f06e, children=[]}]}
                PeerNodeImpl{id='a557a712', type='Column', properties={horizontalAlignment=left, width=0.0, tag=}, parent=1ccc9246, children=[
                    PeerNodeImpl{id='f0d6a9fc', type='EmptyControl', properties={tag=}, parent=a557a712, children=[]}
                    PeerNodeImpl{id='74bc4cd2', type='PushButton', properties={textOverride=, descriptionOverride=, mnemonic=, actionId=12d6a26a, iconOverride=, tag=pushH, iconPathOverride=}, parent=a557a712, children=[]}
                    PeerNodeImpl{id='bcb5a9d0', type='EmptyControl', properties={tag=}, parent=a557a712, children=[]}]}]}
            PeerNodeImpl{id='0e515319', type='Section', properties={collapsePriority=0.0, mnemonic=, tag=sec_dropdown, title=DROP DOWN BUTTON}, parent=f90db10c, children=[
                PeerNodeImpl{id='80482225', type='Column', properties={horizontalAlignment=left, width=0.0, tag=}, parent=0e515319, children=[
                    PeerNodeImpl{id='469f469a', type='DropDownButton', properties={textOverride=, descriptionOverride=, mnemonic=, actionId=c6ca7335, iconOverride=, tag=dropdownV, iconPathOverride=}, parent=80482225, children=[]}]}
                ...

Note: showcaseCEF has been removed in 2018, but is available in older Matlab releases.

Levels of toolstrip encapsulation

Matlab currently has several levels of encapsulation for toolstrip components:

  • Top-level m-file classes for showcasing the toolstrip functionality and creating toolstrips in Java-based containers and web-based apps – these are located in %matlabroot%/toolbox/matlab/toolstrip/+matlab/+ui/+internal/+desktop/
  • Mid-level m-file classes that contain the toolstrip building blocks (tabs, sections, controls) – these are located in %matlabroot%/toolbox/matlab/toolstrip/+matlab/+ui/+internal/+toolstrip/
  • Low-level Java classes that implement the underlying user-interface for Java-based UI – these are located in %matlabroot%/java/jar/toolstrip.jar. I discussed this briefly in a post few years ago.

The top- and mid-level m-file classes are provided with full source code that is quite well-documented internally (as m-file source-code comments). However, note that it is not officially documented or supported (i.e., semi-documented in this blog’s parlance).

The low-level Java classes on the other hand are compiled without available source code – we can inspect these classes (e.g., using uiinspect or checkClass), but we cannot see their original source-code. Luckily, the higher-level m-file classes provide us with plenty of hints and usage examples that we could use to tailor the appearance, functionality and integration of toolstrip components into our app.

Robyn Jackey’s Widgets Toolbox

Users who hesitate to mess around with the built-in toolstrip functionality may find interest in MathWorker Robyn Jackey’s Toolstrip look-alike, which is part of his open-source Widgets Toolbox on the Matlab File Exchange. Unlike other parts of Robyn’s toolbox, which use undocumented functionality, his Toolstrip class seems to use documented components (panels, uicontrols etc.), with just a small reliance on undocumented functionality (matlab.ui.* for example). This has a fair chance to continue working well into future releases, even if Matlab’s built-in toolstrip functionality changes:

Robyn Jackey's Toolstrip look-alike

Strong caution

Over the years, Matlab’s internal toolstrip interface has changed somewhat, but not dramatically. This could change at any time, since the toolstrip uses deeply undocumented functionality. What I will demonstrate over the next few posts might stop working in R2019a, or in R2025b – nobody really knows, perhaps not even MathWorks at this stage. Something that we do know for a fact is that Matlab is slowly transitioning away from Java-based user interfaces to web-based (HTML/JavaScript/CSS) interfaces, and this could have a drastic effect on the toolstrip functionality/API. It seems reasonable to assume that even if MathWorks would one day open up the toolstrip functionality, this would only be for the new web-based uifigure apps (not legacy Java-based figures), and might well have a different API than the one that I’ll discuss in this miniseries. Still, users could use the unofficial/undocumented information that I present here in their own Java figures today and quite possibly also in near-term upcoming releases.

Despite the many unknowns regarding future supportability/roadmap of the built-in toolstrip API, I believe that my readers are smart enough to decide for themselves whether they want to take the associated risks to improve their Matlab programs today, or wait until a documented API will possibly be provided sometime in the future. The choice is yours, as it always is when using undocumented tips from my blog.

With this warning stated, let’s start having fun with Matlab’s built-in toolstrip!

]]>
https://undocumentedmatlab.com/blog_old/matlab-toolstrip-part-1/feed 5
Spicing up the Matlab Editorhttps://undocumentedmatlab.com/blog_old/spicing-up-the-matlab-editor https://undocumentedmatlab.com/blog_old/spicing-up-the-matlab-editor#respond Thu, 29 Mar 2018 21:34:20 +0000 https://undocumentedmatlab.com/?p=7472 Related posts:
  1. Variables Editor scrolling The Matlab Variables Editor can be accessed to provide immediate scrolling to a specified cell location. ...
  2. EditorMacro – assign a keyboard macro in the Matlab editor EditorMacro is a new utility that enables setting keyboard macros in the Matlab editor. this post details its inner workings....
  3. Non-textual editor actions The UIINSPECT utility can be used to expand EditorMacro capabilities to non-text-insertion actions. This is how:...
  4. EditorMacro v2 – setting Command Window key-bindings The EditorMacro utility was extended to support built-in Matlab Editor and Command-Window actions and key-bindings. This post describes the changes and the implementation details....
]]>
I’d like to introduce guest blogger Andreas Justin, who will discuss some way-cool features in his Editor Plugin utility. Many of his feature implementations are not Editor-specific and can be reused in other Matlab-Desktop applications, for example dockable panels, and integration with Matlab’s main Preferences window.

Note: I will be traveling to the USA in June, and to Spain in August. If you would like me to visit your location for onsite consulting or training, then please let me know.

Happy Easter/Passover!

Overview

Editor-plugin's cool logo

Editor-plugin's cool logo

Compared to other IDE like IntellIJ, Eclipse and many more, Matlab’s editor seems somewhat outdated. Especially writing Object-Oriented code in Matlab is kind of a hassle. To make Matlab more user friendly, I’ve written a Java app that adds important features to the editor – Features such as navigating inside Class-code and in Inherited members; Searching through methods and instantly jumping to desired location; Reopening an editor that was closed by accident; Storing bookmarks between Matlab sessions; and Live Templates using commands directly written in the editor, replaced by pre-defined text.

The default Keyboard shortcuts listed below for the features can be customized. Most variables can be customized as well (I will point out which variables are not [yet] customizable).

Most GUIs have a search field. Within this search field you can move the list or the tree up and down using arrow keys, or hit <escape> to return to editor. These search fields allow you to enter regular expressions to limit results shown in list or tree. Also, most GUIs are dockable.

The Editor-Plugin utility is open-source. It is available on GitHub and also mirrored on the Matlab File Exchange. A detailed setup guide is provided on the utility’s wiki section in GitHub.

If you discover any problem or have any suggestion for improvement, please visit the utility’s Issues section on GitHub, where all open/closed issues can be tracked and discussed.

A brief overview of some of the features is presented below. For a detailed explanation of these and other features (which are not listed below), please review the Features section of the utility’s wiki (you guessed it: on GitHub…).

Editing

  • Delete / duplicate linesCTRL + SHIFT + Y or D allows you to delete or duplicate current line.
    Deleting/duplicating complete lines
  • Move lines up or downCTRL + ALT + UP or DOWN allows you to move selected lines up or down.
    Moving complete lines
  • Live (auto-replace) templates – Live Templates are editor commands you can design to insert predefined code. Here’s an example for the command %this% (delivered within the package). When you type a command into the editor the string will get replaced by the predefined text. This predefined text may include variables depending on what you want to achieve. %this% was designed to insert the fully qualified name of the current class you’re in (or function, or script).
    Auto-replace template
  • Clipboard StackCTRL + SHIFT + V opens the Clipboard Stack, where the last 10 copied/cut text are stored and can be directly inserted into the current editor position. The Clipboard Stack only stores text copied from editor.

  • Auto switch current folder and detail viewer – Switching editor tabs will update the Desktop’s current folder and detail viewer. This behavior can be directly changed in the detail viewer bar.
    Use the new icons in the Desktop’s Current Folder panel: Toggle detail viewer to toggle detail viewer and Toggle following the current editor file to toggle following the current editor file.
    Follow current editor file
  • File Structure – I personally use this one the most: CTRL + F12 will show a GUI that let you search methods and properties including inherited ones.
    File structure analysis
  • Navigation History – Every editor file that is opened is stored in the navigation history. Up to 50 editor file paths are stored. If you have a 5-Button Mouse, you can navigate through previous location (backward and forward).
  • Recently ClosedCTRL + SHIFT + T will show a GUI that allows you to reopen closed editors this or last session.
  • BookmarksCTRL + SHIFT + F2 will show a GUI that allows you to name, search and delete bookmarks. Matlab has this nice feature to delete bookmarks after closing the editor. This feature will store all bookmarks. If an editor or Matlab is closed and opened later. All Bookmarks will be restored.
    This feature has some issues though. The most obvious first: if the source file has been changed outside of Matlab, the bookmark does not get updated, and may point to the wrong line, or gets deleted. Also on some Systems the default shortcut does not work. But there are workarounds.

Other useful features

  • Dockable Windows – As mentioned before, most GUIs are dockable.
    Dockable Windows
  • Preferences – Preferences panel integrated in Matlab’s main Preferences window.
    Preferences panel integrated in Matlab's main Preferences window
  • Execute current lineSHIFT + F9 allows you to execute the current line. This is equivalent to selecting the entire line, then clicking F9, and is similar in concept to the editor’s built-in ability to execute the current cell-block.
    Execute current line
  • VarDiff – Select two variables in the workspace and compare them using Matlab’s internal comparison feature (adding a custom hook to the Workspace context-menu was discussed by Yair back in 2010).
    Variables comparison integrated in the Workspace browser
  • KeyPressListener – Allows you to create custom keyboard shortcuts for your own functions. A similar functionality was discussed by Yair back in 2009.

As noted above, a detailed explanation of these and other features is provided in the Features section of the utility’s wiki. If you discover any problem or have any suggestion for improvement, please visit the utility’s Issues section on GitHub, where issues can be tracked and discussed.

]]>
https://undocumentedmatlab.com/blog_old/spicing-up-the-matlab-editor/feed 0
The HotLinks featurehttps://undocumentedmatlab.com/blog_old/the-hotlinks-feature https://undocumentedmatlab.com/blog_old/the-hotlinks-feature#comments Tue, 24 Oct 2017 12:43:13 +0000 https://undocumentedmatlab.com/?p=7128 Related posts:
  1. uiundo – Matlab’s undocumented undo/redo manager The built-in uiundo function provides easy yet undocumented access to Matlab's powerful undo/redo functionality. This article explains its usage....
  2. Matlab’s HG2 mechanism HG2 is presumably the next generation of Matlab graphics. This article tries to explore its features....
  3. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
  4. Pinning annotations to graphs Annotation object can be programmatically set at, and pinned-to, plot axes data points. ...
]]>
Back in 2010, I posted about Matlab’s undocumented feature function. One of the features that I mentioned was 'HotLinks'. A few days ago I had an occasion to remember this feature when a StackOverflow user complained that the headers of table outputs in the Matlab console appear with HTML tags (<strong>) in his diary output. He asked whether it was possible to turn off this automated headers markup.

There are several ways this problem can be solved, ranging from creating a custom table display function, to modifying the table’s internal disp method (%matlabroot%/toolbox/matlab/datatypes/@tabular/disp.m), to using this method’s second optional argument (disp(myTable,false)). Note that simply subclassing the table class to overload disp() will not work because the table class is Sealed, but we could instead subclass table‘s superclass (tabular) just like table does.

Inside the disp.m method mentioned above, the headers markup is controlled (around line 45, depending on your Matlab release) by matlab.internal.display.isHot. Unfortunately, there is no corresponding setHot() method, nor corresponding m- or p-code that can be inspected. But the term “Hot” rang a bell, and then I remembered my old post about the HotLinks feature, which is apparently reflected by matlab.internal.display.isHot.

feature('HotLinks',false);  % temporarily disable bold headers and hyperlinks (matlab.internal.display.isHot=false)
disp(myTable)
myTable        % this calls disp() implicitly
feature('HotLinks',true);   % restore the standard behavior (markup displayed, matlab.internal.display.isHot=true)

Searching for “isHot” or “HotLinks” under the Matlab installation folder, we find that this feature is used in hundreds of places (the exact number depends on your installed toolboxes). The general use appears to be to disable/enable output of hyperlinks to the Matlab console, such as when you display a Matlab class, when its class name is hyperlinked and so is the “Show all properties” message at the bottom. But in certain cases, such as for the table output above, the feature is also used to determine other types of markup (bold headers in this case).

>> feature('HotLinks',0)  % temporarily disable bold headers and hyperlinks
>> groot
ans = 
  Graphics Root with properties:
 
          CurrentFigure: [0×0 GraphicsPlaceholder]
    ScreenPixelsPerInch: 96
             ScreenSize: [1 1 1366 768]
       MonitorPositions: [2×4 double]
                  Units: 'pixels'
 
  Use GET to show all properties

>> feature('HotLinks',1)  % restore the standard behavior (markup displayed)
>> groot
ans = 
  Graphics Root with properties:
 
          CurrentFigure: [0×0 GraphicsPlaceholder]
    ScreenPixelsPerInch: 96
             ScreenSize: [1 1 1366 768]
       MonitorPositions: [2×4 double]
                  Units: 'pixels'
 
  Show all properties

There’s nothing really earth shuttering in all this, but the HotLinks feature could be useful when outputting console output into a diary file. Of course, if diary would have automatically stripped away markup tags we would not need to resort to such hackery. Then again, this is not the only problem with diary, which is long-overdue an overhaul.

]]>
https://undocumentedmatlab.com/blog_old/the-hotlinks-feature/feed 1
User-defined tab completions – take 2https://undocumentedmatlab.com/blog_old/user-defined-tab-completions-take-2 https://undocumentedmatlab.com/blog_old/user-defined-tab-completions-take-2#comments Wed, 12 Jul 2017 13:00:30 +0000 https://undocumentedmatlab.com/?p=6961 Related posts:
  1. Setting desktop tab completions The Matlab desktop's Command-Window tab-completion can be customized for user-defined functions...
  2. Class object tab completion & improper field names Tab completions and property access can be customized for user-created Matlab classes. ...
  3. Recovering previous editor state Recovering the previous state of the Matlab editor and its loaded documents is possible using a built-in backup config file. ...
  4. The HotLinks feature feature('HotLinks') can be used to temporarily disable hyperlinks and other markups in the Matlab console. ...
]]>
Back in 2010, I posted about Matlab’s undocumented mechanism for setting Matlab desktop tab-completions. That mechanism used a couple of internal files (TC.xml and TC.xsd) to describe the various possible options that are auto-completed (or displayed in a small tooltip window) when the user clicks the <Tab> key on partially-entered function input parameters.

Using TabComplete for user-defined functions

Using TabComplete for user-defined functions

Unfortunately, this mechanism apparently broke in R2016a and was replaced with a new mechanism, as explained below.

The new mechanism relies on a file called functionSignatures.json which exists in every single folder that contains Matlab files that have functions whose input parameters ought to be tab-completable.

The new mechanism offers far greater versatility and flexability in defining the input types and inter-relationsships compared to the old TC.*-based mechanism. Another important benefit is that we can now add custom user-defined functionSignatures.json files to our user folders, next to our m-files, without having to modify any Matlab system file.

Note that you may need to restart Matlab the first time that you create a functionSignatures.json file. But once it’s created, you can modify it within a Matlab session and the changes take effect immediately.

Note: Credit for first posting about this new mechanism goes to Nicholas Mati. I’ve known about this new mechanism for over a year, but I never found the time to write about it until now, so Nicholas gets credit for breaking the scoop. The discussion below uses and expands Nicholas’ original post.

Syntax

The functionSignatures.json file has the general form:

{
	"FunctionName1":
	{
		"key1":"val1",
		"key2":"val2",
		"keyn":"valn"
	},
	"FunctionName2":
	{
		"key1":"val1",
		"key2":"val2",
		"keyn":"valn"
	}
}

A number of keys are supported including “platform“, “setsAns“, “inputs“, and “outputs“, although inputs and outputs are by far the most common (and presumably only inputs are relevant for tab-completion). These keys take an array of (or a single) object value(s). The objects typically take one of the following forms:

{"name":"variable_name", "kind":"kind_option", "type":"string_or_array_of_type"}
{"mutuallyExclusiveGroup":
	[
		...
	]
}
{"name":"varargin", "kind":"optional", "multiplicity":"append"}

The value for “kind” can be “required”, “optional”, “positional”, “flag”, “namevalue” or “platform” (and perhaps a few other lesser-used kinds):

  • required” means that the specified input is mandatory
  • optional” means that it can be added or omitted
  • positional” means that it’s an optional input but if it is specified then it must appear at the specified position relative to the previous (earlier) inputs
  • flag” means that it’s an optional input flag, from a predefined list of one or more single-token strings. For example, in regexp(s1,s2,'once') the last input arg ('once') is such a flag.
  • namevalue” means that it follows Matlab’s standard practice of using P-V pairs (parameter name followed by its value). For example, func('propName',propValue)
  • platform” indicates that this input is only available on the specified platform(s)

These “kind”s are all explained below.

The value for “type” can be a string such as “char” or “numeric” or “filepath”, or a more complicated JSON array (see below).

In addition to “name”, “kind” and “type”, we can also define a “default” value (e.g. "default":"false") and a “display” string. While these are [currently] not used by Desktop tab-completion, they might be used by other components such as the JIT compiler or the Editor, if not today then perhaps in a future release.

Note that while pure JSON format does not accept comments, Matlab’s functionSignatures.json does accept C++-style comments, as discovered by Heiko in a comment below. To add a comment, simply add // comment text at the end of any line, or /* comment text */ anywhere within a line.

Usage examples

Multiple examples of functionSignatures.json files can be found in subfolders of %matlabroot%/toolbox/matlab. For example, here’s the tab-completion definition for the visdiff function, which displays a visual comparison between two files, and resides in %matlabroot%/toolbox/shared/comparisons/functionSignatures.json:

{
"visdiff":
{
    "inputs":
    [
        {"name":"filename1", "kind":"required",   "type":"filepath"},
        {"name":"filename2", "kind":"required",   "type":"filepath"},
        {"name":"type",      "kind":"positional", "type":"choices={'text', 'binary'}"}
    ]
}
}

As can be seen in this example, the first and second inputs are expected to be a filename, whereas the third input is one of the two predefined strings ‘text’ or ‘binary’. This third input has “kind”:”positional”, meaning that it is optional, but if it is provided then it must be in the 3rd position and cannot appear sooner. Moreover, if the user specifies any input argument to the “right” of a positional input, then the positional argument becomes required, not optional.

Whereas a “positional” parameter has a specific position in the args list (#3 in the case of visdiff above), an “optional” parameter may appear anywhere in the list of inputs.

Here’s a more complex example, for the built-in regexprep function (in %matlabroot%/toolbox/matlab/strfun/functionSignatures.json). This example shows how to limit the input to certain data types and how to specify optional input flags with pre-defined choices:

"regexprep":
{
	"inputs":
	[
		{"name":"str",               "kind":"required",  "type":[["char"], ["cell"], ["string"]]},
		{"name":"expression",        "kind":"required",  "type":[["char"], ["cell"], ["string"]]},
		{"name":"replace",           "kind":"required",  "type":[["char"], ["cell"], ["string"]]},
		{"name":"optMatch",          "kind":"flag",      "display":"", "type":[["char", "choices={'all','once'}"], ["numeric", "scalar"]],   "default":"'all'"},
		{"name":"optWarnings",       "kind":"flag",      "display":"", "type":["char", "choices={'nowarnings','warnings'}"],                 "default":"'nowarnings'"},
		{"name":"optCase",           "kind":"flag",      "display":"", "type":["char", "choices={'matchcase','ignorecase','preservecase'}"], "default":"'matchcase'"},
		{"name":"optEmptyMatch",     "kind":"flag",      "display":"", "type":["char", "choices={'noemptymatch','emptymatch'}"],             "default":"'noemptymatch'"},
		{"name":"optDotAll",         "kind":"flag",      "display":"", "type":["char", "choices={'dotall','dotexceptnewline'}"],             "default":"'dotall'"},
		{"name":"optStringAnchors",  "kind":"flag",      "display":"", "type":["char", "choices={'stringanchors','lineanchors'}"],           "default":"'stringanchors'"},
		{"name":"optSpacing",        "kind":"flag",      "display":"", "type":["char", "choices={'literalspacing','freespacing'}"],          "default":"'literalspacing'"}
	],
	"outputs":
	[
		{"name":"newStr", "type":[["char"], ["cell"], ["string"]]}
	]
},

Here’s an even more complex example, this time for the codegen function (in %matlabroot%/toolbox/coder/matlabcoder/functionSignatures.json, part of the Matlab Coder toolbox). This example shows how to limit the filenames to certain extensions and how to specify name-value input pairs:

"codegen":
{
	"inputs":
	[
		{"name":"compile_only",  "kind":"flag",       "type":"choices={'-c'}"},
		{"name":"config_flag",   "kind":"flag",       "type":"choices={'-config:mex','-config:lib','-config:dll','-config:exe','-config:hdl'}"},
		{"name":"debug",         "kind":"flag",       "type":"choices={'-g'}"},
		{"name":"report",        "kind":"flag",       "type":"choices={'-report'}"},
		{"name":"launchreport",  "kind":"flag",       "type":"choices={'-launchreport'}"},
		{"name":"file",          "kind":"flag",       "type":"filepath=*.m,*.mlx,*.c,*.cpp,*.h,*.o,*.obj,*.a,*.so,*.lib,*.tmf", "multiplicity":"append"},
		{"name":"-d",            "kind":"namevalue",  "type":"folderpath"},
		{"name":"-I",            "kind":"namevalue",  "type":"folderpath"},
		{"name":"-globals",      "kind":"namevalue"},
		{"name":"-o",            "kind":"namevalue",  "type":[["char"], ["filepath"]]},
		{"name":"-O",            "kind":"namevalue",  "type":"choices={'enable:inline','disable:inline','enable:blas','disable:blas','enable:openmp','disable:openmp'}"},
		{"name":"-args",         "kind":"namevalue",  "type":[["identifier=variable"], ["char"]]},
		{"name":"-config",       "kind":"namevalue",  "type":[["identifier=variable"], ["char"]]},
		{"name":"verbose",       "kind":"flag",       "type":"choices={'-v'}"},
		{"name":"singleC",       "kind":"flag",       "type":"choices={'-singleC'}"},
		{"name":"-test",         "kind":"namevalue",  "type":"identifier=function"}
	]
},

Argument types

As noted above, we use "type":... to specify the expected data type of each parameter. This can be a simple string such as “char”, “cellstr”, “numeric”, “table”, “categorical”, “filepath”, “folderpath”, “matlabpath”, class name, or a more complicated JSON array. For example:

  • "type":["numeric","scalar"]
  • "type":["numeric","numel=3",">=4"]
  • "type":[["char"], ["cellstr"], ["numeric"], ["logical","vector"]]
  • "type":[["char", "choices={'-ascii'}"]]
  • "type":[["filepath"], ["matlabpath=*.m,*.mlx"], ["char"]]
  • "type":"identifier=variable,function,localfunction,package,classdef"
  • "type":"matlab.graphics.axis.Axes"
  • "type":"choices={'yes','no','maybe'}"

We can even specify on-the-fly Matlab computation that returns a cell-array of values, for example a list of available fonts via "type":"choices=listfonts". A more complex example is the definition of the rmfield function, where the possible input choices for the second input arg (highlighted) depend on the struct that is provided in the first input arg (by running the fieldnames function on it):

"rmfield":
{
	"inputs":
	[
		{"name":"s",     "kind":"required", "type":"struct"},
		{"name":"field", "kind":"required", "type":"choices=fieldnames(s)"}	],
	"outputs":
	[
		{"name":"s", "type":"struct"}
	]
},

Alternative inputs

Multiple alternative inputs can be specified in the functionSignatures.json file. The easiest way to do so is to simply create multiple different definitions for the same function, one beneath the other. Matlab’s tab-completion parser is smart enough to combine those definitions and proceed with the most appropriate one based on the user-entered inputs.

For example, in the same Coder file above we find 6 alternative definitions. If (for example) we start typing coder('-ecoder', and click <Tab>, Matlab would automatically auto-complete the second input to “false”, and then another <Tab> click would set the third input to the required ‘-new’ parameter (see highlighted lines below):

...
"coder":
{
	"inputs":
	[
		{"name":"projectname", "kind":"required", "type":"filepath=*.prj"}
	]
},
"coder":
{
	"inputs":
	[
		{"name":"-open", "kind":"namevalue", "type":"filepath=*.prj"}
	]
},
"coder":
{
	"inputs":
	[
		{"name":"-build", "kind":"namevalue", "type":"filepath=*.prj"}
	]
},
"coder":
{
	"inputs":
	[
		{"name":"-new", "kind":"namevalue", "type":[["filepath=*.prj"], ["char"]]}
	]
},
"coder":
{
	"inputs":
	[
		{"name":"ecoderFlag",  "kind":"required", "type":"choices={'-ecoder'}"},		{"name":"ecoderValue", "kind":"required", "type":[["logical"], ["choices={'false'}"]]},		{"name":"newFlag",     "kind":"required", "type":"choices={'-new'}"},		{"name":"newvalue",    "kind":"required", "type":[["filepath=*.prj"], ["char"]]}	]
},
"coder":
{
	"inputs":
	[
		{"name":"tocodeFlag",  "kind":"required", "type":"choices={'-tocode'}"},
		{"name":"tocodevalue", "kind":"required", "type":"filepath=*.prj"},
		{"mutuallyExclusiveGroup":
			[
				[],
				[
					{"name":"scriptFlag", "kind":"required", "type":"choices={'-script'}"},
					{"name":"scriptname", "kind":"required", "type":[["filepath=*.m"], ["char"]]}
				]
			]
		}
	]
}

This example also shows, in the last definition for the coder function, another mechanism for specifying alternative inputs, using “mutuallyExclusiveGroup” (aka “MEGs”). A MEG is defined using an array of options, enclosed in square brackets ([]). Each of the MEG options is exclusive to each of the others, meaning that we can only work with one of them and not the others. This is equivalent to duplicating the definition as we saw above, and saves us some copy-paste (in some cases a lot of copy-pastes, especially with multiple and/or nested MEGs). However, MEGs have a major drawback of reduced readability. I believe that in most cases we only have a single MEG and few input args, and in such cases it makes more sense to use repeated function defs rather than a MEG. The Matlab signature files contain numerous usage examples for either of these two mechanisms.

Platform dependencies

If a specific function (or a specific signature variant) depends on the running platform, this can be specified via the “platform” directive. For example, the winopen function only works on Windows, but not on Linux/Mac. Its corresponding signature definition is:

"winopen":
{
	"platform":"win32,win64",	"inputs":
	[
		{"name":"filename", "kind":"required", "type":"filepath"},
		{"name":"varargin", "kind":"optional", "multiplicity":"append"}
	]
}

Platform dependence could also be specified at the parameter level, not just the entire function level. For example, in the xlsread function (defined in %matlabroot%/toolbox/matlab/iofun/functionSignatures.json), we see that the usage variant xlsread(filename,-1) is only available on Windows (note that the numeric value is defined as "<=-1", not necessarily -1), and so is the “functionHandle” input (which is called processFcn in the documentation – for some reason that escapes me the names of many input args do not match in the documentation and functionSignature):

"xlsread":
{
	"inputs":
	[
		{"name":"filename", "kind":"required", "type":"filepath=*.xls,*.xlsx,*.xlsb,*.csv"},
		{"mutuallyExclusiveGroup":
			[
				{"name":"openExcel", "kind":"required", "display":"", "type":["numeric", "<=-1"], "platform":"win64,win32"},				{"name":"xlRange",   "kind":"required", "type":["char", "@(x) isempty(x) || ~isempty(strfind(x, ':'))"], "default":"''"},
				[
					{"name":"sheet",          "kind":"positional", "type":[["char", "choices=matlab.internal.language.introspective.tabcompletion.xlsread_vsheet(filename)"], ["numeric", ">=1"]], "default":"1"},
					{"name":"xlRange",        "kind":"positional", "type":"char", "default":"''"},
					{"name":"basic",          "kind":"positional", "display":"", "type":["char", "choices={'basic',''}"]},
					{"name":"functionHandle", "kind":"positional", "type":"function_handle", "platform":"win64,win32"}				]
			]
		}
	],
        ...

Parsing errors

The new mechanism is not very user-friendly when you get something wrong. In the best case, it issues a cryptic error message (see below), and in the worst case it simply ignores the changes and the user has no idea why the new custom tab-completion is not working as intended.

The most likely causes of such problems are:

  • The most common problem is that you placed the functionSignatures.json file in a different folder than the Matlab function. For example, if the myFunction() function is defined in myFunction.m, then the tab-completion of this function MUST be located in a functionSignatures.json file that resides in the same folder, not anywhere else on the Matlab path. In other words, the Matlab path is NOT relevant for tab-completion.
  • Your functionSignatures.json file does not follow the [extremely strict] syntax rules above, to the letter. For example, forgetting the top or final curly braces, forgetting a comma or adding an extra one, or not closing all brackets/braces properly.
  • You mistyped one or more of the input parameters, types or options.

In case of a parsing error, you’d see a red error message on the Matlab console the next time that you try to use tab-completion:

Error parsing JSON data; Boost reports "(189): expected ',' or ']'".

Unfortunately the error message only tells us the problematic line location within the functionSignatures.json file, but not the file’s location, so if we haven’t recently edited this file we’d need to find it in the relevant folder. For example:

edit(fullfile(fileparts(which('myFunction')), 'functionSignatures.json')

Moreover, when a JSON syntax error (such as the one above) occurs, the entire file is not parsed, not just the definition that caused the error.

Another limitation of tab-completion is that it does not work while the main Matlab thread is working (e.g., during a uiwait or waitfor). This may be somewhat misleading since most editor/debugging actions do work.

Arguably, this new tab-completion mechanism could be made more programmer-friendly. Perhaps this will improve in a future Matlab release.

Addendum: MathWorks has now made this functionality supported and documented. Read about it here.

For a related mechanism, see my article on tab-completion for class properties and methods from 2014, which is apparently still relevant and functional.

]]>
https://undocumentedmatlab.com/blog_old/user-defined-tab-completions-take-2/feed 8
Handling red Java console errorshttps://undocumentedmatlab.com/blog_old/handling-red-java-console-errors https://undocumentedmatlab.com/blog_old/handling-red-java-console-errors#comments Wed, 29 Jun 2016 17:00:51 +0000 https://undocumentedmatlab.com/?p=6468 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. 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....
  3. JGit-Matlab integration JGit source-control integration package can easily be integrated in Matlab. ...
  4. Non-textual editor actions The UIINSPECT utility can be used to expand EditorMacro capabilities to non-text-insertion actions. This is how:...
]]>
Anyone who has worked with non-trivial Matlab GUIs knows that from time to time we see various red Java stack-trace errors appear in the Matlab console (Command Window). These errors do not appear often when using documented Matlab controls, but they do from time to time. The errors appear significantly more frequently when working with undocumented Java-based hacks that I often show on this blog, and especially when working with complex controls such as uitable or uitree. Such controls have a very large code-base under the hood, and the Matlab code and data sometimes clashes with the asynchronous Java methods that run on a separate thread. Such clashes and race conditions often lead to red Java stack-trace errors that are spewed onto the Matlab console. For example:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at com.jidesoft.plaf.basic.BasicCellSpanTableUI.paint(Unknown Source)
	at javax.swing.plaf.ComponentUI.update(Unknown Source)
	at javax.swing.JComponent.paintComponent(Unknown Source)
	at com.jidesoft.grid.CellStyleTable.paintComponent(Unknown Source)
	at javax.swing.JComponent.paint(Unknown Source)
	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
	...

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 >= 0
	at java.util.Vector.elementAt(Unknown Source)
	at javax.swing.table.DefaultTableColumnModel.getColumn(Unknown Source)
	at com.jidesoft.grid.ContextSensitiveTable.getCellRenderer(Unknown Source)
	at com.jidesoft.grid.CellSpanTable.getCellRenderer(Unknown Source)
	at com.jidesoft.grid.TreeTable.getActualCellRenderer(Unknown Source)
	at com.jidesoft.grid.GroupTable.getCellRenderer(Unknown Source)
	at com.jidesoft.grid.JideTable.b(Unknown Source)
	at com.jidesoft.grid.CellSpanTable.calculateRowHeight(Unknown Source)
	...

In almost all such Java error messages, the error is asynchronous to the Matlab code and does not interrupt it. No error exception is thrown (or can be trapped), and the Matlab code proceeds without being aware that anything is wrong. In fact, in the vast majority of such cases, nothing is visibly wrong – the program somehow overcomes the reported problem and there are no visible negative effects on the GUI. In other words, these error messages are harmless and can almost always be ignored. Still, if we could only stop those annoying endless red stack-trace messages in the Matlab console!

Note that today’s post only discusses untrappable asynchronous Java error messages, not synchronous errors that can be trapped in Matlab via try-catch. These synchronous errors are often due to programmatic errors (e.g., bad method input args or an empty reference handle) and can easily be handled programmatically. On the other hand, the asynchronous errors are non-trappable, so they are much more difficult to isolate and fix.

In many of the cases, the error occurs when the control’s underlying data model is changed by the Matlab code, and some of the controls’s Java methods are not synced with the new model by the time they run. This can be due to internal bugs in the Matlab or Java control’s implementation, or to simple race conditions that occur between the Matlab thread and the Java Event Dispatch Thread (EDT). As noted here, such race conditions can often be solved by introducing a simple delay into the Matlab code:

javaControl.doSomething();
pause(0.05); drawnow;javaControl.doSomethingElse();

In addition, asking Matlab to run the Java component’s methods on the EDT can also help solve race conditions:

javaControl = javaObjectEDT(javaControl);

Unfortunately, sometimes both of these are not enough. In such cases, one of the following ideas might help:

  • Add fprintf(' \b') to your Matlab code: this seemingly innocent hack of displaying a space & immediately erasing it with backspace, appears to force the Java engine to flush its event queue and synchronize things, thereby avoiding the annoying Java console errors. I know it sounds like adding a sprinkle of useless black magic to the code, but it does really work in some cases!
    javaControl.doSomething();
    pause(0.05); drawnow;  % this never hurt anyone!
    fprintf(' \b');javaControl.doSomethingElse();
  • It is also possible to directly access the console text area and remove all the text after a certain point. Note that I strongly discourage messing around with the console text in this manner, since it might cause problems with Matlab’s internals. Still, if you are adventurous enough to try, then here’s an example:
    jCmdWinDoc = com.mathworks.mde.cmdwin.CmdWinDocument.getInstance;
    currentPos = cmdWinDoc.getLength;
     
    javaControl.doSomething();
    pause(0.05); drawnow;  % this never hurt anyone!
    javaControl.doSomethingElse();
     
    pause(0.1);  % let the java error time to display itself in the console
    jCmdWinDoc.remove(currentPos, cmdWinDoc.getLength-currentPos);
  • When all else fails, consider simply clearing the Matlab console using the Matlab clc command a short while after updating the Java control. This will erase the red Java errors, along with everything else in the console, so naturally it cannot be freely used if you use the console to display useful information to the user.

It should be emphasized: not all of these suggested remedies work in all cases; in some cases some of them work, and in other cases others might work. There does not seem to be a general panacea to this issue. The main purpose of the article was to list the possible solutions in a single place, so that users could try them out and select those that work for each specific case.

Do you know of any other (perhaps better) way of avoiding or hiding such asynchronous Java console errors? If so, then please post a comment below.

]]>
https://undocumentedmatlab.com/blog_old/handling-red-java-console-errors/feed 6
Programmatic shortcuts manipulation – part 2https://undocumentedmatlab.com/blog_old/programmatic-shortcuts-manipulation-part-2 https://undocumentedmatlab.com/blog_old/programmatic-shortcuts-manipulation-part-2#comments Wed, 30 Dec 2015 16:42:52 +0000 https://undocumentedmatlab.com/?p=6169 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. 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....
  4. setPrompt – Setting the Matlab Desktop prompt The Matlab Desktop's Command-Window prompt can easily be modified using some undocumented features...
]]>
Today I will expand last week’s post on customizing Matlab Desktop’s shortcuts. I will show that we can incorporate non-standard controls, and add tooltips and user callbacks in undocumented ways that are not available using the interactive Desktop GUI.

Custom shortcut controls

Custom shortcut controls


Today’s article will focus on the new toolstrip interface of Matlab release R2012b and later; adaptation of the code to R2012a and earlier is relatively easy (in fact, simpler than the toolstrip-based code below).

Displaying the Shortcuts panel

Before we begin to modify shortcuts in the Toolstrip’s shortcuts menu, we need to ensure that the Shortcuts panel is visible and active (in current focus), otherwise our customizations will be ignored or cause an error. There is probably a more direct way of doing this, but a simple way that I found was to edit the current Desktop’s layout to include a directive to display the Shortcuts tab, and then load that layout:

jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
hMainFrame = com.mathworks.mde.desk.MLDesktop.getInstance.getMainFrame;
jToolstrip = hMainFrame.getToolstrip;
isOk = jToolstrip.setCurrentTab('shortcuts');
if ~isOk  % i.e., Shortcuts tab is NOT displayed
    % Save the current Desktop layout
    jDesktop.saveLayout('Yair');  pause(0.15);
 
    % Update the layout file to display the Shortcuts tab
    filename = fullfile(prefdir, 'YairMATLABLayout.xml');
    fid = fopen(filename, 'rt');
    txt = fread(fid, '*char')';
    fclose(fid);
    txt = regexprep(txt,'(ShowShortcutsTab=)"[^"]*"','');
    txt = regexprep(txt,'(<Layout [^>]*)>','$1 ShowShortcutsTab="yes">');
    fid = fopen(filename, 'wt');
    fwrite(fid,txt);
    fclose(fid);
 
    % Load the modified layout
    jDesktop.restoreLayout('Yair');  pause(0.15);
 
    % The shortcuts tab should now be visible, so transfer focus to that tab
    jToolstrip.setCurrentTab('shortcuts');
end

Custom controls

As I explained in last week’s post, we can use scUtils.addShortcutToBottom to add a simple push-button shortcut to the relevant category panel within the Shortcuts toolstrip tab. To add custom controls, we can simply add the controls to the relevant shortcut category panel container (a com.mathworks.toolstrip.components.TSPanel object). The standard shortcuts are typically placed in the Shortcuts tab’s second TSPanel (“general”), and other categories have TSPanels of their own.

Now here’s the tricky part about TSPanels: we cannot directly add components to the sectino panel (that would be too easy…): the section panels are composed of an array of internal TSPanels, and we need to add the new controls to those internal panels. However, these panels only contain 3 empty slots. If we try to add more than 3 components, the 4th+ component(s) will simply not be displayed. In such cases, we need to create a new TSPanel to display the extra components.

Here then is some sample code to add a combo-box (drop-down) control:

% First, get the last internal TSPanel within the Shortcuts tab's "general" section panel
% Note: jToolstrip was defined in the previous section above
jShortcutsTab = jToolstrip.getModel.get('shortcuts').getComponent;
jSectionPanel = jShortcutsTab.getSectionComponent(1).getSection.getComponent;  % the TSPanel object "general"
jContainer = jSectionPanel.getComponent(jSectionPanel.getComponentCount-1);
 
% If the last internal TSPanel is full, then prepare a new internal TSPanel next to it
if jContainer.getComponentCount >= 3
    % Create a new empty TSPanel and add it to the right of the last internal TSPanel
    jContainer = com.mathworks.toolstrip.components.TSPanel;
    jContainer.setPreferredSize(java.awt.Dimension(100,72));
    jSectionPanel.add(jContainer);
    jSectionPanel.repaint();
    jSectionPanel.revalidate();
end
 
% Create the new control with a custom tooltip and callback function
optionStrings = {'Project A', 'Project B', 'Project C'};
jCombo = com.mathworks.toolstrip.components.TSComboBox(optionStrings);
jCombo = handle(javaObjectEDT(jCombo), 'callbackproperties'));
set(jCombo, 'ActionPerformedCallback', @myCallbackFunction);
jCombo.setToolTipText('Select the requested project');
 
% Now add the new control to the internal TSPanel
jContainer.add(jCombo);
jContainer.repaint();
jContainer.revalidate();

Custom shortcut controls

Custom shortcut controls

Matlab’s internal com.mathworks.toolstrip.components package contains many embeddable controls, including the following (I emphasized those that I think are most useful within the context of the Shortcuts panel): TSButton, TSCheckBox, TSComboBox, TSDropDownButton (a custom combo-box component), TSFormattedTextField, TSLabel, TSList, TSRadioButton, TSScrollPane, TSSlider, TSSpinner, TSSplitButton, TSTextArea, TSTextField, and TSToggleButton. These controls are in most cases simple wrappers of the corresponding Java Swing controls. For example, TSSpinner extends the standard Swing JSpinner control. In some cases, the controls are more complex: for example, the TSSplitButton is similar to Matlab’s uisplittool control.

Toolstrip controls

Toolstrip controls

In fact, these controls can be used even outside the toolstrip, embedded directly in our Matlab figure GUI, using the javacomponent function. For example:

dataModel = javax.swing.SpinnerNumberModel(125, 15, 225, 0.5);  % defaultValue, minValue, maxValue, stepSize
jSpinner = com.mathworks.toolstrip.components.TSSpinner(dataModel);
jSpinner = handle(javaObjectEDT(jSpinner), 'CallbackProperties');
[hjSpinner, hContainer] = javacomponent(jSpinner, [10,10,60,20], gcf);

You can find additional interesting components within the %matlabroot%/java/jar/toolstrip.jar file, which can be opened in any zip file utility or Java IDE. In fact, whatever controls that you see Matlab uses in its Desktop toolstrip (including galleries etc.) can be replicated in custom tabs, sections and panels of our own design.

Matlab Desktop’s interactive GUI only enables creating simple push-button shortcuts having string callbacks (that are eval‘ed in run-time). Using the undocumented programmatic interface that I just showed, we can include more sophisticated controls, as well as customize those controls in ways that are impossible via the programmatic GUI: add tooltips, set non-string (function-handle) callbacks, enable/disable controls, modify icons in run-time etc.

For example (intentionally showing two separate ways of setting the component properties):

% Toggle-button
jTB = handle(javaObjectEDT(com.mathworks.toolstrip.components.TSToggleButton('Toggle button')), 'CallbackProperties')
jTB.setSelected(true)
jTB.setToolTipText('toggle me!')
jTB.ActionPerformedCallback = @(h,e)doSomething();
jContainer.add(jTB);
 
% Check-box
jCB = handle(javaObjectEDT(com.mathworks.toolstrip.components.TSCheckBox('selected !')), 'CallbackProperties');
set(jCB, 'Selected', true, 'ToolTipText','Please select me!', 'ActionPerformedCallback',{@myCallbackFunction,extraData});
jContainer.add(jCB);

(resulting in the screenshot at the top of this post)

Important note: none of these customizations is saved to file. Therefore, they need to be redone programmatically for each separate Matlab session. You can easily do that by calling the relevant code in your startup.m file.

If you wish me to assist with any customization of the Desktop shortcuts, or any other Matlab aspect, then contact me for a short consultancy.

Happy New Year everybody!

]]>
https://undocumentedmatlab.com/blog_old/programmatic-shortcuts-manipulation-part-2/feed 4
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 https://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
Another couple of Matlab bugs and workaroundshttps://undocumentedmatlab.com/blog_old/couple-of-matlab-bugs-and-workarounds https://undocumentedmatlab.com/blog_old/couple-of-matlab-bugs-and-workarounds#comments Wed, 26 Nov 2014 18:00:27 +0000 https://undocumentedmatlab.com/?p=5272 Related posts:
  1. A couple of internal Matlab bugs and workarounds A couple of undocumented Matlab bugs have simple workarounds. ...
  2. FIG files format FIG files are actually MAT files in disguise. This article explains how this can be useful in Matlab applications....
  3. HG2 update HG2 appears to be nearing release. It is now a stable mature system. ...
  4. Matlab compiler bug and workaround Both the Matlab compiler and the publish function have errors when parsing block-comments in Matlab m-code. ...
]]>
Every now and then I come across some internal Matlab bugs. In many cases I find a workaround and move on, sometimes bothering to report the bugs to MathWorks support, but often not. In truth, it’s a bit frustrating to hear the standard response that the issue [or “unexpected behavior”, but never “bug” – apparently that’s a taboo word] “has been reported to the development team and they will consider fixing it in one of the future releases of MATLAB”.

To date I’ve reported dozens of bugs and as far as I can tell, few if any of them have actually been fixed, years after I’ve reported them. None of them appear on Matlab’s official bug parade, which is only a small subset of the full list that MathWorks keeps hidden for some unknown reason (update: see the discussion in the comments thread below, especially the input by Steve Eddins). Never mind, I don’t take it personally, I simply find a workaround and move on. I’ve already posted about this before. Today I’ll discuss two additional bugs I’ve run across once-too-often, and my workarounds:

Nothing really earth-shattering, but annoying nonetheless.

Saving non-Latin Command Window text using diary

The diary function is well-known for saving Matlab’s Command-Window (CW) text to a file. The function has existed for the past two decades at least, possibly even longer.

Unfortunately, perhaps the developer never thought that Matlab would be used outside the Americas and Western Europe, otherwise I cannot understand why to this day diary saves the text in ASCII format rather than the UTF-16 variant used by the CW. This works ok for basic Latin characters, but anyone who outputs Chinese, Japanese, Korean, Hindi, Arabic, Hebrew or other alphabets to the CW, and tries to save it using diary, will find the file unreadable.

Here is a sample illustrative script, that outputs the Arabic word salaam (peace, سلام) to the CW and then tries to save this using diary. If you try it, you will see it ok in the CW, but garbage text in the generated text file:

>> fname='diary_bug.txt'; diary(fname); disp(char([1587,1604,1575,1605])); diary off; winopen(fname)
سلام

The problem is that since diary assumes ASCII characters, any characters having a numeric value above 255 get truncated and are stored as invalid 1-byte characters, char(26) in this case.

Here’s my workaround:

% Output Command Window text to a text file
function saveCmdWinText(filename)
    cmdWinDoc = com.mathworks.mde.cmdwin.CmdWinDocument.getInstance;
    txt = char(cmdWinDoc.getText(0,cmdWinDoc.getLength));
    fid = fopen(filename,'W');
    fwrite(fid,txt,'uint16');  % store as 2-byte characters
    fclose(fid);
    %winopen(filename);  % in case you wish to verify...
end

This works well, saving the characters in their original 2-byte format, for those alphabets that use 2-bytes: non-basic Latins, Greek, Cyrillic, Armenian, Arabic, Hebrew, Coptic, Syriac and Tāna (I don’t think there are more than a handful of Matlab users who use Coptic, Syriac or Tāna but never mind). However, UTF-8 specifies that CJK characters need 3-4 bytes and this is apparently not supported in Matlab, whose basic char data type only has 2 bytes, so I assume that Chinese, Japanese and Korean will probably require a different solution (perhaps the internal implementation of char and the CW is different in the Chinese/Japanese versions of Matlab, I really don’t know. If this is indeed the case, then perhaps a variant of my workaround can also be used for CJK output).

Correction #1: I have learned since posting (see Steve Eddins’ comment below) that Matlab actually uses UTF-16 rather than UTF-8, solving the CJK issue. I humbly stand corrected.

Correction #2: The saveCmdWinText code above saves the CW text in UTF-16 format. This may be problematic in some text editors that are not UTF-savvy. For such editors (or if your editor get confused with the various BOM/endianness options), consider saving the data in UTF-8 format – again, assuming you’re not using an alphabet [such as CJK] outside the ASCII range (thanks Rob):

function saveCmdWinText_UTF8(filename)
    cmdWinDoc = com.mathworks.mde.cmdwin.CmdWinDocument.getInstance;
    txt = char(cmdWinDoc.getText(0,cmdWinDoc.getLength));
    fid = fopen(filename,'W','n','utf-8');
    fwrite(fid,txt,'char');
    fclose(fid);
    %winopen(filename);  % in case you wish to verify...
end

Also, this workaround is problematic in the sense that it’s a one-time operation that stores the entire CW text that is visible at that point. This is more limited than diary‘s ability to start and stop output recording in mid-run, and to record output on-the-fly (rather than only at the end). Still, it does provide a solution in case you output non-ASCII 2-byte characters to the CW.

Update: I plan to post a utility to the Matlab File Exchange in the near future that will mimic diary‘s ability to start/stop text recording, rather than simply dumping the entire CW contents to file. I’ll update here when this utility is ready for download.

There are various other bugs related to entering non-Latin (and specifically RTL) characters in the CW and the Matlab Editor. Solving the diary bug is certainly the least of these worries. Life goes on…

p.s. – I typically use this translator to convert from native script to UTF codes that can be used in Matlab. I’m sure there are plenty of other translators, but this one does the job well enough for me.

For people interested in learning more about the Command Window internals, take a look at my cprintf and setPrompt utilities.

cprintf usage examples

cprintf usage examples

setPrompt usage examples

setPrompt usage examples

Printing GUIs reliably

Matlab has always tried to be far too sophisticated for its own good when printing figures. There’s plenty of internal code that tries to handle numerous circumstances in the figure contents for optimal output. Unfortunately, this code also has many bugs. Try printing even a slightly-complex GUI containing panels and/or Java controls and you’ll see components overlapping each other, not being printed, and/or being rendered incorrectly in the printed output. Not to mention the visible flicker that happens when Matlab modifies the figure in preparation for printing, and then modifies it back to the original.

All this when a simple printout of a screen-capture would be both much faster and 100% reliable.

Which is where my ScreenCapture utility comes in. Unlike Matlab’s print and getframe, ScreenCapture takes an actual screen-capture of an entire figure, or part of a figure (or even a desktop area outside any Matlab figure), and can then send the resulting image to a Matlab variable (2D RGB image), an image file, system clipboard, or the printer. We can easily modify the <Print> toolbar button and menu item to use this utility rather than the builtin print function:

Matlab's default toolbar Print action

Matlab's default toolbar Print action

hToolbar = findall(gcf,'tag','FigureToolBar');
hPrintButton = findall(hToolbar, 'tag','Standard.PrintFigure');
set(hPrintButton, 'ClickedCallback','screencapture(gcbf,[],''printer'')');
 
hPrintMenuItem = findall(gcf, 'type','uimenu', 'tag','printMenu');
set(hPrintMenuItem,      'Callback','screencapture(gcbf,[],''printer'')');

This prints the entire figure, including the frame, menubar and toolbar (if any). If you just wish to print the figure’s content area, then make sure to create a top-level uipanel that spans the entire content area and in which all the contents are included. Then simply pass this top-level container handle to ScreenCapture:

hTopLevelContainer = uipanel('BorderType','none', 'Parent',gcf, 'Units','norm', 'Pos',[0,0,1,1]);
...
hToolbar = findall(gcf,'tag','FigureToolBar');
hPrintButton = findall(hToolbar, 'tag','Standard.PrintFigure');
set(hPrintButton, 'ClickedCallback',@(h,e)screencapture(hTopLevelContainer,[],'printer'));
 
hPrintMenuItem = findall(gcf, 'type','uimenu', 'tag','printMenu');
set(hPrintMenuItem,      'Callback',@(h,e)screencapture(hTopLevelContainer,[],'printer'));

In certain cases (depending on platform/OS/Matlab-release), the result may capture a few pixels from the figure’s window frame. This can easily be corrected by specifying a small offset to ScreenCapture:

set(hPrintButton, 'ClickedCallback',@(h,e)printPanel(hTopLevelContainer));
set(hPrintMenuItem,      'Callback',@(h,e)printPanel(hTopLevelContainer));
 
function printPanel(hTopLevelContainer)
    pos = getpixelposition(hTopLevelContainer);
    screencapture(hTopLevelContainer, pos+[2,4,0,0], 'printer');
end
]]>
https://undocumentedmatlab.com/blog_old/couple-of-matlab-bugs-and-workarounds/feed 32
Online (web-based) Matlabhttps://undocumentedmatlab.com/blog_old/online-web-based-matlab https://undocumentedmatlab.com/blog_old/online-web-based-matlab#comments Mon, 04 Aug 2014 14:17:36 +0000 https://undocumentedmatlab.com/?p=4935 Related posts:
  1. cprintf – display formatted color text in the Command Window cprintf is a utility that utilized undocumented Matlab desktop functionalities to display color and underline-styled formatted text in the Command Window...
  2. Setting status-bar text The Matlab desktop and figure windows have a usable statusbar which can only be set using undocumented methods. This post shows how to set the status-bar text....
  3. Setting desktop tab completions The Matlab desktop's Command-Window tab-completion can be customized for user-defined functions...
  4. uisplittool & uitogglesplittool Matlab's undocumented uisplittool and uitogglesplittool are powerful controls that can easily be added to Matlab toolbars - this article explains how...
]]>
For many years I searched for a good solution for deploying Matlab applications in online web-pages. There used to be a solution over a decade ago but it was taken off the market. We could use the Java Builder to wrap our Matlab apps in a JAR that could be called by a Java-based application server, but we’d still need to develop the front-end web GUI as well as the middle-tier plumbing. A similar limitation exists if we wish to use the new Matlab Production Server (MSP). Developing this front-end and middle-tier is by no means a trivial exercise, as much as MathWorks presentations would like it to appear. Not to mention the fact that the Builder and the MSP are relatively costly (~$5-7K and ~$30K respectively).

I was thrilled to see the answer in the recent Matlab Computational Finance Conference, London. I presented at last year’s conference, so I was excited to review this year’s presentations when I came across a nugget in Kevin Shea’s keynote presentation on new Matlab developments. Note that there were two separate Matlab computational-finance events in 2014 – in London (June 24) and NY (April 9); the interesting piece is from London. Unlike the NY conference, the London conference proceedings do not include a video recording, only the slides (perhaps the video will be added to the proceedings page later, after all it takes some time to process). The last slide of Kevin’s presentation shows a screenshot of a Chrome browser displaying what appears to be a full-fledged Matlab desktop (Workspace, Editor, Command Window, figures) at https://matlab.mathworks.com:

Matlab Online (click to zoom)
Matlab Online (click to zoom)

The benefits of using Matlab Online are potentially tremendous: excluding some limitations (e.g., limited GUI, run time and supported toolboxes), we could deploy our Matlab programs online with minimal to no additional dev effort.

Information on Matlab Online can be found at http://mathworks.com/products/matlab/online. It even includes detailed dedicated documentation for all the supported functions and features.

For some reason, MathWorks has chosen not to link this new (and in my humble opinion, great) product in its official list of products. Perhaps the reason is that MathWorks do not wish for Matlab Online to cannibalize its main offerings. This might also explain the limitations placed on the online version (some limitations are technical, the rest are business-related). Matlab Online requires a dedicated login access, provided by MathWorks. Unfortunately, it is still not fully released to the public and is only available to users with up to date student licenses.

Still, if you are an important enough client of MathWorks, you might ask for access. Even with its current limitations, Matlab Online may well be useful for your needs. If you press strongly enough, and if your account is large enough, perhaps MathWorks might even enable a dedicated subdomain for you (as in intel.mathworks.com or matlab.apple.com).

Here’s another screenshot, in case you’re not convinced yet:

Matlab Online (click to zoom)
Matlab Online (click to zoom)

A post by MathWorks on the Answers forum earlier this year lists Matlab Online along with some additional online-computing alternatives for Matlab.

And now for some guesswork/speculation: MathWorks placed a major bet on Java technology in the early 2000’s (actually the late 90’s, since R12 took a few years to develop). Java was indeed hot at that time, but then so were some other technologies over the years. Fortunately for MathWorks, Java proved agile, mature and portable enough to enable mobile and online porting. This could explain the lack of Simulink GUI support, since Simulink GUI is still C++-based to a large extent. It might also explain the extra work done in HG2 in the graphic infrastructure (previously C++-based). After all, the basic MCOS graphic classes were available years ago, so if HG2 was only about a transition from double-value handles to MCOS, and some nice beautifications (anti-aliasing, CVD-aware colors etc.) then HG2 could be released long ago. Working on the underlying engine to make it portable could well explain HG2’s belated arrival.

So what does all this mean about Matlab’s future? Well, it appears to me that MathWorks’ apparent move towards SaaS (software as a service) and cloud-based computing is slightly belated, but quite evidently follows a general industry trend. In my eyes it heralds a move by MathWorks from desktop to online services, perhaps even to pay-per-use computing (as by Techila for example). The Matlab desktop will still be MathWorks’ bread and butter for many years to come. But the ability of Matlab programs to work either locally (on a Matlab client, either thin or thick) or online would be an enormous productivity benefit, in essence being a “killer feature” over Matlab’s competitors.

Technically, Matlab’s online integration could enable closer integration of online content in Matlab programs (esp. GUI). I’ve already shown how active web content can be displayed in Matlab GUI, but a closer integration could mean this might all become fully documented and integrated (recall Windows’ failed Active Desktop on one hand, but smart-phones’ enormously-successful active widgets on the other). It could also enable closer integration with online graphing services such as Plotly.

I for one, can’t wait to see this dream being realized. It’s not too far down the road, it would seem. I just hope that licensing and cost considerations won’t keep us from using it. MathWork’s recent Home License scheme seems to indicate that this is well understood by MathWorks, so I am highly optimistic :-)

Then again, all this might be pure baseless speculation. Time will tell.

]]>
https://undocumentedmatlab.com/blog_old/online-web-based-matlab/feed 5
Class object tab completion & improper field nameshttps://undocumentedmatlab.com/blog_old/class-object-tab-completion-and-improper-field-names https://undocumentedmatlab.com/blog_old/class-object-tab-completion-and-improper-field-names#comments Thu, 17 Jul 2014 18:48:29 +0000 https://undocumentedmatlab.com/?p=4918 Related posts:
  1. Setting desktop tab completions The Matlab desktop's Command-Window tab-completion can be customized for user-defined functions...
  2. User-defined tab completions – take 2 Matlab has changed the mechanism that enables user-defined tab-completion of function inputs. ...
  3. Recovering previous editor state Recovering the previous state of the Matlab editor and its loaded documents is possible using a built-in backup config file. ...
  4. Undocumented classdef attributes Matlab's object-oriented class definition enables usage of some useful undocumented attributes. ...
]]>
I recently consulted to a very large industrial client. Following a merger/acquisition, the relevant R&D department had two development groups using different technologies: one group uses Matlab, the other does not. My client wanted both groups to use Matlab, something that would naturally please MathWorks.

Unfortunately, it turns out that a technical challenge was preventing this move: the other technology enabled data field names (identifiers) longer than Matlab’s namelengthmax=63 characters, and these names also sometimes contained illegal identifier characters, such as spaces or symbols. This prevented an easy code transition, indefinitely delaying the migration to Matlab.

Accessing improper fieldnames

I suggested to this client to use Matlab class objects that overloaded the subsref() and subsasgn() methods: the long original identifiers would be stored in some internal container (cell array or containers.Map etc.), and they would be accessed not directly (which would be impossible since they are not valid Matlab identifiers) but via the overloaded methods. Something along the following lines:

classdef ExtendedFieldsClass
    % The internal data implementation is not publicly exposed
    properties (Access = 'protected')
        props = containers.Map;
    end
 
    methods (Access = 'public', Hidden=true)
 
        % Overload property assignment
        function obj = subsasgn(obj, subStruct, value)
            if strcmp(subStruct.type,'.')
                try
                    obj.props(subStruct.subs) = value;
                catch
                    error('Could not assign "%s" property value', subStruct.subs);
                end
            else  % '()' or '{}'
                error('not supported');
            end
        end
 
        % Overload property retrieval (referencing)
        function value = subsref(obj, subStruct)
            if strcmp(subStruct.type,'.')
                try
                    value = obj.props(subStruct.subs);
                catch
                    error('"%s" is not defined as a property', subStruct.subs);
                end
            else  % '()' or '{}'
                error('not supported');
            end
        end
    end
end

This works splendidly, as the following snippet shows:

>> c = ExtendedFieldsClass
c = 
  ExtendedFieldsClass with no properties.
 
>> c.(' asd f @#$^$%&') = -13.5;  % no error
 
>> c.(' asd f @#$^$%&')
ans =
                     -13.5
 
>> c.(' asd f @#$^$%& xyz')  % note the extra "xyz"
Error using ExtendedFieldsClass/subsref (line 27)
" asd f @#$^$%& xyz" is not defined as a property

Note how we need to use the () parentheses in order to access the “properties” as dynamic fieldnames. We would naturally get an error if we tried to directly access the field:

>> c. asd f @#$^$%&
 c. asd f @#$^$%&
        |
Error: Unexpected MATLAB expression.

Tab completion

So far so good.

The problem is that we would also like to see the defined “properties” when in the desktop’s tab completion. i.e., when I type “c.” and then click <tab> in the Matlab command prompt, I’d like to see the list of defined “properties” in a tooltip (in the example above: ” asd f @#$^$%&”). Instead, I get the message “No Completions Found.”:

Missing tab completion

Missing tab completion

I described the hack for desktop tab-completion a few years ago. Unfortunately, that hack only works for functions. We need to find another solution for Matlab class objects.

The solution is to overload the fieldnames() function as well, such that it would return a cell-array of the relevant strings:

classdef ExtendedFieldsClass
    % The internal data implementation is not publicly exposed
    properties (Access = 'protected')
        props = containers.Map;
    end
 
    methods (Access = 'public', Hidden=true)
 
        % Overload property assignment
        function obj = subsasgn(obj, subStruct, value)
            ...  (as above)
        end
 
        % Overload property retrieval (referencing)
        function value = subsref(obj, subStruct)
            ...  (as above)
        end
 
        % Overload fieldnames retrieval
        function names = fieldnames(obj)            names = sort(obj.props.keys);  % return in sorted order        end    end
end

When we now run this in the command prompt, we get the expected behavior:

Working tab completion

Working tab completion

R2014a

Unfortunately, this works only up to and including Matlab release R2013b. In R2014a, MathWorks made some internal change that prevents overloading the fieldnames function. To be more precise, we can still overload it as above, and it will indeed work if we directly call fieldnames(c), but it no longer has any effect on the tab completion. On R2014a, the tab-completion remains broken and returns “No Completions Found.” When this was reported to MathWorks some time ago, the official response was that the previous behavior was considered a “bug”, and this was “fixed” in R2014a (don’t bother searching for it in the official bugs parade). Go figure…

So what do you think I should now do? Remember: this is a large client, who knows how many licenses are at stake. Should I suggest to my client not to switch to Matlab? Or should I suggest that they keep using R2013b across the entire organization and cancel their annual maintenance? Or maybe I should simply tell them to accept the fact that some important functionality should be expected to get broken whenever Matlab is upgraded?

These sort of things just blow me away. Sometimes I feel as if I am swimming against the current, and that’s frustrating. I admit it doesn’t happen very often. Then again, I guess if things were straight-forward, nobody would need me to consult them…

Don’t mind me – just blowing off some steam. I’m allowed to, every now and then, aren’t I? :-)

Addendum July 21, 2014: I found out today that on R2014a+ we can simply overload the properties method. This is a function that returns the properties of a class, and so it makes perfect sense for a class object’s tab-completion to use properties rather than fieldnames. So I can now indeed see why the past behavior was considered by MathWorks to be a bug that should be fixed. Still, it would have been nice if for backward-compatibility considerations, Matlab (or at least mlint) would have detected the fact that fieldnames is being overloaded in a user class and warned/alerted regarding the fact that we should now overload properties. In any case, to be fully backward compatible, simply overload both methods, and make one of them call the other. For example:

        % Overload property names retrieval
        function names = properties(obj)
            names = fieldnames(obj);
        end

My client would be quite happy to hear of this new development :-)

Michal Kutil described a mechanism for overloading the methods function, which is also part of the tab-completion tooltip. The problem here is that we cannot simply overload methods in our class, since Matlab calls methods with the class name (not the class object reference) when it wants to determine the relevant methods to display in the tooltip. Michal’s solution was to create a wrapper function that calls the overloaded variant. This wrapper function can then be placed within a @char folder somewhere in the Matlab path. I used a similar trick for my profile_history utility last month.

Related newsgroup posts by Eric Salemi here and here.

Similarly, in order to overload the data-value tooltip (when hovering over the object in the editor), or when displaying the object in the Matlab command prompt, simply overload the disp() function (see related):

        % Overload class object display
        function disp(obj)
            disp([obj.props.keys', obj.props.values']);  % display as a cell-array
        end

In a related matter, we can limit the values that a property can accept using the matlab.system.StringSet class of the matlab.System package, as recently discovered by Oleg Komarov (additional details; a different way to constrict property data type):

classdef foo < matlab.System
    properties
        Coordinates
    end
    properties(Hidden,Transient)
        CoordinatesSet = matlab.system.StringSet({'north','south','east','west'});
    end
end

restricting Matlab property values

This blog will now take a short vacation for a few weeks, due to my U.S. trip. I will return with some fresh material in August – stay tuned!

]]>
https://undocumentedmatlab.com/blog_old/class-object-tab-completion-and-improper-field-names/feed 14
Another Command Window text color hackhttps://undocumentedmatlab.com/blog_old/another-command-window-text-color-hack https://undocumentedmatlab.com/blog_old/another-command-window-text-color-hack#comments Wed, 06 Nov 2013 18:00:35 +0000 https://undocumentedmatlab.com/?p=4358 Related posts:
  1. uisplittool & uitogglesplittool Matlab's undocumented uisplittool and uitogglesplittool are powerful controls that can easily be added to Matlab toolbars - this article explains how...
  2. Undocumented Profiler options part 3 An undocumented feature of the Matlab Profiler can report call history timeline - part 3 of series. ...
  3. Undocumented Profiler options part 4 Several undocumented features of the Matlab Profiler can make it much more useful - part 4 of series. ...
  4. Non-textual editor actions The UIINSPECT utility can be used to expand EditorMacro capabilities to non-text-insertion actions. This is how:...
]]>
Matlab’s Command Window text is notorious for its boring black & white appearance when sending output via the built-in fprintf or disp commands. Back in 2009, I explained the undocumented ability to display red or hyperlinked text using fprintf, or colored and underlined text using my cprintf utility. I followed this up last year with the relatively new ability to display bold text formatting, using either fprintf or cprintf.

A short while ago, Carsten Allefeld (a regular on this blog) alerted me to the fact that recent Matlab releases have added yet another undocumented feature, this time the ability to specify orange formatting to the output text. This made sense: after all, recent releases have started to display warnings as orange text on STDOUT. While errors have for ages been rendered red by the simple act of directing their output to STDERR, warnings are output to STDOUT and so a bypass was naturally devised. This is similar to the <strong> bypass that I explained last year, for the bold formatting. By redirecting STDOUT, Carsten was able to see that by adding '[\b...]\b' to the output text, anything between the brackets was given an orange color. Of course, we can still use cprintf to display any color in the rainbow, orange included:

Orange color in Command Window text

Orange color in Command Window text


The \b hack relies on the fact that \b is actually the standard back-space control-character (BS, or ASCII 8), which erases the preceding [ (bracket) character. Matlab’s implementation of fprintf simply has a back-door that switches to orange color when it sees a [\b – ]\b couple. By the way, it won’t work if you use any other combination, or if there are not exactly two such in the displayed text. MathWorks made the hack very specific so that it would be close to impossible to come by it by mistake.

Since ‘\b’ translates into the BS character, we can directly use char(8), as follows:

disp(['this is [' 8 'orange]' 8 ' text'])

The [\b sequence is reminiscent of the CSI ANSI sequence used in days of yore, on non-graphic consoles. In those old days, we used the ESC-[ sequence to add text formatting to the console text. Perhaps some MathWorker was nostalgic. Note the related FEX utility tcprintf, which implements ANSI sequences for color-coding the Matlab console output.

<editorial>
If you ask me, this is an example of bad design: instead of modifying fprintf to enable generic color and text formatting, the developer hard-coded a specific [\b hack for a specific color, and a different specific <strong> hack for bold formatting. If tomorrow a green color or underlined text will be needed, they’ll need to modify the hard-coding and extend it with yet new hard-coding. Moreover, the [\b hack does not enable multiple segments of orange colors in the same text, a natural extension. In their shoes, I’d probably have extended the <strong> paradigm with something like <font color="orange"> or: <span style="color:#FF8000;"> (I wonder where I got this idea from? hmm…) Maybe I’m just being too harsh: it’s obviously easier to bitch from the benches than to score at the field…
</editorial>

Anyway, if you only need black, red and orange colors in your text, you need look no further than fprintf. If, however, you require your outputs to be a bit more lively, then consider using cprintf:

cpintf demo

cpintf demo

Do you know of any additional undocumented Command Window hack? If so, please do leave a comment below.

]]>
https://undocumentedmatlab.com/blog_old/another-command-window-text-color-hack/feed 6
Variables Editor scrollinghttps://undocumentedmatlab.com/blog_old/variables-editor-scrolling https://undocumentedmatlab.com/blog_old/variables-editor-scrolling#comments Wed, 11 Sep 2013 10:35:27 +0000 https://undocumentedmatlab.com/?p=4161 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. Disabling menu entries in deployed docked figures Matlab's standard menu items can and should be removed from deployed docked figures. This article explains how. ...
  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....
]]>
I would like to introduce guest blogger Oleg Komarov. Oleg has gathered a reputation as a Matlab veteran with plenty of insight into the arcane corners of Matlab, originally on the CSSM newsgroup, and more recently on StackExchange (which admittedly contains more Q&As of the challenging type). Today Oleg discusses a non-trivial solution to a deceivingly-simple problem.

Introduction

I often work with datasets that in one way or another have millions of rows and several columns. Although the dimensions preclude visual-based approaches, e.g. imagine keeping all data on a spreadsheet, especially during the development and testing phases, I need to inspect the dataset at given ‘coordinates’.

As a concrete example, in my work on financial time-series I sometimes encounter a subtle irregularity that might arise from a bug in the code when you stack different series of prices. Then you calculate returns and wonder why you get -99% or +2000%.

Thankfully, the Variables Editor (VE) is very much what I would need for such inspection tasks, if it wasn’t that its usefulness is inversely proportional to the size of the data. An example would better clarify what I mean. Suppose you need to scroll to position 5677545 of your 1e8-by-1 data variable, the following screenshot illustrates how the scrollbar, pgdown/pgup or the arrow keys are not fine-tuned for such task.

Problematic Variables Editor scrolling (and the scrollto solution)

Problematic Variables Editor scrolling (and the scrollto solution)

You can easily waste minutes to mindless scrolling!

We could argue that the task is painlessly accomplished through basic logical indexing in the Command Window (CW), as the following image shows (note that I already set the display to format compact):

Sub-indexing into a large data matrix

Sub-indexing into a large data matrix

However, this approach is limited because:

  1. it displays a static snapshot of the selected region, and often precludes interaction with the data, e.g. copy-paste
  2. it requires more visual space than the VE, which either means that you need to modify your layout or scroll the CW
  3. typing in the CW can be even more tedious than scrolling the VE…

Why openvar is not a good-enough solution

In search of a solution that would retain the VE interactivity and would speed up the task of scrolling to the point of interest, I first checked if there was an API for the VE similar to that for the documents Editor. As a side-note: to date, the Editor’s API remains undocumented/unsupported, although having been published in what was then called the Desktop Blog (renamed MATLAB Spoken Here since Ken and Mike have left MathWorks and the blog focus has changed).

In any case, it turns out that there is a stub of an API for the Variables Editor, matlab.desktop.vareditor, which however comes much short of my expectations. In fact, it only goes as far as visualizing the data of some variable within a completely separate basic version of the VE. This could prove to be a valid embeddable alternative to the uitable, but it does not help us with the need to scroll to a specific data cell.

Unlucky with the VE API, I looked into openvar for an undocumented option that would let me open some variable in the VE and then scroll to the desired ‘coordinates’ – this effort proved fruitless.

A description of the solution that did work

Since the standard Matlab did not offer a programmatic solution, I started digging into the underlying Java components.

I found that one simple direct way is to open our variable of interest in the VE with openvar, retrieve the Java Desktop instance (in the same manner as we do to get the Desktop instance to customize the Editor). From this instance we can find the handle to the appropriate com.mathworks.mlwidgets.array.ArrayTable with findjobj (remember that there could be multiple ArrayTables, one for each inspected variable). Finally, we scroll to the desired position using the scrollCellToVisible() method.

Note that the Matlab object builds on the javax.swing.JViewport and provides a convenient interface as in the case of the scrolling function, since its java counterpart scrollRectToVisible() requires as input a java.awt.rectangle object rather than scalar doubles.

A succinct usage example would be:

% Create example variable
a = randn(1e8,1);
name = 'a';
 
% Open 'a' in the VE or grab focus
openvar(name)
 
% Retrieve Desktop instance and handle to client
desktop = com.mathworks.mde.desk.MLDesktop.getInstance;
varclient = desktop.getClient(name);
 
% Retrieve handle to scrollable table with findjobj
jVarTable = findjobj(varclient,'property',{'name','VariableTable'});
 
% Select, scroll and update the UI (note the zero-indexing, i.e. row-1)
row = 5677545;
col = 1;
jVarTable.setRowSelectionInterval(row-1, row-1)
jVarTable.setColumnSelectionInterval(col-1, col-1)
jVarTable.scrollCellToVisible(row-1, col-1)
jVarTable.updateUI

The scrollto utility

As most of the lines of the usage example above should already be familiar and/or self-explanatory to the followers of this blog, the next logical step is to encapsulate the snippet into a function which you can already find on the File Exchange: scrollto.

The scrollto function provides the following features:

  • Accepts subs or indices
  • You can scroll indexed variables, i.e. ‘a{1}’ or ‘a.field{2,3}’ etc.
  • Scrolling is also supported in debug mode (from ver2.00), i.e. on variables of the ‘caller’ workspace
  • Handles asynchronous rendering of the VE (see below)

and supports the following classes (should be 2D arrays):

  • Numeric and logical data – ‘VariableTable’
  • Cell arrays – ‘CellTable’
  • Timeseries – ‘TimeSeriesArrayEditorTablePanel:fDataTable’
  • Datasets (Statistics Toolbox) – ‘DatasetVariableTable’

Matlab handles different classes in the VE through different interfaces. For this reason, for each supported class I reported the ‘name’ property to use with findjobj.

Synchronization issues

Asynchronous rendering of the VE can happen in either of two cases:

  1. if the variable has never been opened in the VE, or the variable was opened but it does not exist in the workspace anymore
  2. in code that opens and interacts with the VE

Writing scrollto proved to be more than a simple wrapping effort and it is worth mentioning the workaround implemented to allow a smooth workflow. The biggest issue I faced is the asynchronous rendering of the VE. As Yair reports in his book Undocumented Secrets of Matlab-Java Programming, p. 538:

“The tight-coupling of the Variable Editor to the Desktop Workspace variables is unfortunate in some respects. … Matlab only has a single computational thread, so Matlab code has to finish before the JMI request can be handled. This means that the Variables Editor contents cannot be displayed synchronously by the Matlab code that invokes it.”

In other words, we cannot retrieve the handle to e.g. the VariableTable until the function has finished executing.

A workaround is to call openvar, wait until the focus is back to the CW, and then call scrollto. I cannot tell you how this workflow made me feel so close and yet so far from a satisfactory implementation.

The ideal flowchart of a basic wrapper around the example (see above) would have been:

Ideal scrollto workflow

Ideal scrollto workflow

Now, since we cannot retrieve the handle to the VariableTable if the VE has not rendered yet, I implemented an asynchronous second call to scrollto through a timer object that fires after the first call to scrollto has finished executing:

Asynchronous scrollto workflow

Asynchronous scrollto workflow

The result is a better experience without unexpected interruptions or breaks in the workflow.

I would like to thank Yair for his comments and guidance. Without his support, scrollto would not exist and humankind would be doomed to scroll the VE manually!

Public-service announcement

(This is Yair again):

I wish to invite you to join my online presentation (webinar) on “A Real-Time Trading System in MATLAB” in the upcoming MATLAB Computational Finance Virtual Conference next Thursday, September 19, 2013. I will be speaking at 2pm EST (8pm CEST). Registration is free and it’s a virtual conference, so there’s no need for a tie and jacket… Following a half-hour presentation, I will be answering audience questions online.

I gave an earlier version of this presentation at the Computational Finance Conference in New York on May 23, and you are welcome to look there for a preview. The presentation slides can be downloaded here. 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.

MATLAB Computational Finance Conference 2013

]]>
https://undocumentedmatlab.com/blog_old/variables-editor-scrolling/feed 6
JGit-Matlab integrationhttps://undocumentedmatlab.com/blog_old/jgit-matlab-integration https://undocumentedmatlab.com/blog_old/jgit-matlab-integration#comments Wed, 10 Jul 2013 18:00:49 +0000 https://undocumentedmatlab.com/?p=3973 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. 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....
  3. Variables Editor scrolling The Matlab Variables Editor can be accessed to provide immediate scrolling to a specified cell location. ...
  4. Handling red Java console errors Red Java errors are sometimes displayed in the Matlab console. They can be removed or avoided in a variety of means. ...
]]>
I would like to introduce guest blogger Mark Mikofski, of SunPower Corp. Mark has developed the JGit4MATLAB utility, which can be used to integrate Matlab with the popular JGit open-source version-control system.

Introduction

JGit logo

JGit logo

JGit is an open-source Java implementation of Git, a popular distributed version control system. Since Matlab is essentially a Java interpreter, JGit is an obvious candidate for integrating Git into Matlab. Luckily, JGit also comes with a porcelain class that has the most popular commands conveniently packaged. This is the starting point for JGit4MATLAB – a thin Matlab wrapper utility on the Matlab File Exchange.

The first step is to download and install JGit4MATLAB in your Matlab path. The first time that the JGit Matlab class is called, it downloads the latest version of org.eclipse.jgit.jar, adds it to Matlab’s static Java classpath and makes a backup of the existing javaclasspath.txt file as javaclasspath.JGitSaved. Matlab must then be restarted for the changes to the static Java class path to take effect. From now on, you can use the commands in the JGit Matlab class or the jgit.m wrapper function. These use basic JGit commands, which shall be described below:

Most of the important JGit methods are encapsulated in the Matlab JGit wrapper class and jgit.m function, but you can also use them directly if you wish. The Matlab wrapper currently supports ADD, BRANCH, CHECKOUT, CLONE, COMMIT, DIFF, INIT, LOG, MERGE & STATUS, but there are many more in org.eclipse.jgit.api.Git that you can use directly. In fact you don’t really need to use the wrapper at all if you don’t want to – all you really need is the JAR file, which the wrapper downloads and installs for you. You can also download the JAR file independently from here (latest only, which is what JGit4MATLAB does), or here (latest and previous releases). If you’re using JGit4MATLAB, you can update the JAR file to the latest version at will, by issuing JGit.downloadJGitJar('@JGit\org.eclipse.jgit.jar').

The most basic Git commands are clone, init, add and commit. Let us explore how to use JGit’s “Git-Porcelain API” class in Matlab to perform these tasks.

Clone and Init

Clone and Init are both class methods of the Git-Porcelain API class and return a Command API class object, which is what nearly all of the Git-Porcelain methods do:

import org.eclipse.jgit.api.Git   % import the package
cloneCMD = Git.cloneRepository;   % return a CloneCommand object
URI = 'git://github.com/mikofski/JGit4Matlab.git';   % a Git repository
cloneCMD.setURI(URI)   % set the repository to clone
g = cloneCMD.call;   % clone the repository

or more compactly:

g = org.eclipse.jgit.api.Git.cloneRepository.setURI(URI).call;

The call method executes the command with the options and arguments set by the other methods. Calling the clone method also returns a Git instance. The full API for the CloneCommand class lists all the possible options and arguments for cloning. One option lets you set an optional progress monitor; there are some already included in JGit, but unfortunately, they use the carriage return (or ‘\r’) escape sequence which in Windows is the same as a newline (read here). So, I implemented a customized ProgressMonitor class for Matlab that uses backspace (or ‘\b’) instead.

Init is very similar to clone:

g = org.eclipse.jgit.api.Git.init.call;

Configuring author information

Before moving on, it is important to set the “author” and “email” fields in the Git config. JGit will use your computer’s info if you provide nothing. You probably want to set these values globally, so the place to put them is in your $HOME folder in the “.gitconfig” file.

file = java.io.File(fullfile(getenv('home'),'.gitconfig'));
gitconfig = org.eclipse.jgit.storage.file.FileBasedConfig(file, org.eclipse.jgit.util.FS.DETECTED);
gitconfig.setString('user',[], 'name','John Doe');       % place your name in here
gitconfig.setString('user',[], 'email','john@doe.com');  % place your email in here
gitconfig.save;

Hopefully your commits will all have the right name and email address in them from now on.

Typical JGit Workflow

Now that you have a Git repository, you will want to start working with it. The typical workflow is to create a feature branch in which to work. But first JGit needs a Git instance. If you saved it from cloning or initializing a new repo then good for you! But if you need to recreate it, just pass the constructor a File object that points to the .git folder inside your Git repo:

JGit workflow

JGit workflow

file = java.io.File(fullfile('path', 'to', 'repo', '.git'));
g = org.eclipse.jgit.api.Git.open(file);
g.checkout.setCreateBranch(true).setName('newbranch').call;

Now you are no longer on the “master” branch, which is usually reserved for buildable/deployable code. Start working. But before you do too much, commit your work to your branch:

g.add.addFilepattern('file1.m').addFilepattern('file2.m').call;
g.commit.setMessage('initial dump').call;

JGit commit log

JGit commit log


All commits should have a message, so you know what work was completed in that commit. Branch and commit frequently. You can always clean them up later. There are lots of options for adding and committing files, so look at the API’s AddCommand and CommitCommand classes.

Everything else is pretty much the same as above: Get a Git instance; create a command; set the options; and finally call the command:

file = java.io.File(fullfile('path', 'to', 'repo', '.git'));
g = org.eclipse.jgit.api.Git.open(file);
r = g.getRepository;  % a Repository instance can be very useful
g.status.call;
g.log.call;
g.checkout.setName('master').call;
g.merge.include(r.resolve('newbranch')).call;
g.push.call;
g.pull.call;

Note: Repository.resolve() is one of the most powerful methods.

The JGit log window on the left can be gotten using glog – the standalone JGit command line log GUI (slightly similar to gitk) that can be downloaded as a binary for systems with /bin/sh from the eclipse site (same place as the jar download).

Some tricks can be gleaned by what little work I’ve done so far on the JGit4MATLAB wrapper on the Matlab File Exchange. I’ll be happy to answer whatever questions I can there, or comments here. I’m also happy to accept pull requests on Github, of course using JGit4MATLAB!

Authentication

You can only use an SSH paired keys to authenticate remote repositories, the keys must **not** have a pass-phrase, they must be in the openSSH format and they must be in $HOME/.ssh. PuTTYgen let’s you do all of this, so it’s really not an issue. Of course you can still use remotes that do not require authentication with no problems.

All commands that deal with remotes and that require authentication, e.g. CLONE, FETCH, PULL, PUSH, will only work

  • with SSH
  • with *no* passphrase
  • with keys in the openSSH format
  • with keys and known hosts in $HOME\.ssh

Obviously remotes that do not require authentication will work fine. e.g. public, read-only and local repositories.

SSH is very easy to set up:

  1. Download puttygen (Intel x86). Disregard the “Intel x86” business, it doesn’t matter what processor you have or whether your os is 64-bit or 32-bit. Puttygen is a very mature well establish application that is used by many other applications, for example all of the TortoiseXXX scm clients use Putty, Plink and Pageant. Here is the actual download here (click to download then click to install): http://the.earth.li/~sgtatham/putty/latest/x86/puttygen.exe
  2. Create a folder called .ssh in your %– USERPROFILE%. On Windows 7 this is C:\Users\ and on XP it is C:\Documents and Settings\. You can do this in Matlab: mkdir(fullfile(getenv('userprofile'), '.ssh')).
  3. Create a key using puttygen, this is fairly self explanatory, and kind of fun, but do *not* set a pass-phrase; leave those fields blank!
  4. Using puttygen, find the conversion menu tab and export the key in the openSSH format to the .ssh folder that you created earlier.
  5. Now copy and paste your public key to your remote repositories (Github, Bitbucket, etc.) as needed. Jsch, which is the ssh client that JGit uses, should now work out of the box.

Unfortunately using SSL (HTTPS) isn’t possible with JGit4MATLAB. Sorry. but hopefully you’ll love the excitement of using ssh key pairs!

Further development

Possible future work on the Matlab-JGit integration includes assigning standard keyboard-shortcuts to common source-control tasks, integration as toolbar/toolstrip icons for easier access, and in the Matlab Editor in general. Only a few days ago, a reader on this blog has shown interest in this.

In the far future, integration with Matlab’s existing source-control system. Anyone wish to pick up the glove?

JGit is covered by the BSD 3-clause license which is very permissive, and should allow MathWorks or anyone for that matter to develop an integrated JGit application for Matlab. There are more packages in JGit than just the porcelain API, including Swing utilities and other utilities that can be used to create rich user interfaces and experiences, but the development would have to be in Java. Developers should look at the developer’s section of the JGit website and use either the Maven or Github repository to set up their forks.

Conclusion

JGit and Matlab are a natural combination. JGit is a mature and thorough open-source project. Most porcelain commands are available without any additional work. There are some arcanae, but the API documentation is sufficient to figure out most things using short high-level code. If you find yourself diving too deep, then scan the docs some more, and you will probably find a shortcut.

]]>
https://undocumentedmatlab.com/blog_old/jgit-matlab-integration/feed 6
Disabling menu entries in deployed docked figureshttps://undocumentedmatlab.com/blog_old/disabling-menu-entries-in-deployed-docked-figures https://undocumentedmatlab.com/blog_old/disabling-menu-entries-in-deployed-docked-figures#comments Wed, 14 Nov 2012 18:00:46 +0000 https://undocumentedmatlab.com/?p=3344 Related posts:
  1. setPrompt – Setting the Matlab Desktop prompt The Matlab Desktop's Command-Window prompt can easily be modified using some undocumented features...
  2. Docking figures in compiled applications Figures in compiled applications cannot officially be docked since R2008a, but this can be done using a simple undocumented trick....
  3. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
  4. Matlab callbacks for Java events Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...
]]>
Last week I presented an article explaining how to solve an issue with deployed (compiled) Matlab applications. Today I’d like to welcome guest blogger Alexander Mering, who will explain how to disable standard Matlab menu items in deployed docked Matlab figures. Alexander has been an avid follower of this blog, and from his CSSM posts we can tell that he’s been heavily using advanced GUI features presented in this blog. His article today nicely shows how we can use different building-blocks presented in different articles in this blog, to achieve something new and useful.

As Yair pointed out in many occasions, the power of Matlab could be greatly enhanced using the underlying Java mechanism. To me, while developing a larger standalone tool for technical calculations, these hints are worth a mint (as I guess for many of you).

One of these very useful hints is the ability to dock figure windows in standalone applications. This perfectly fits to my understanding of a “clean desktop”, i.e., having as less as possible separate windows. Since in many calculations dozens of figures are generated, the desktop gets up crowded very fast – if these are not grouped. So docking is essential (at least for me). Unfortunately there seems to be a serious problem with the resulting menu entries (at least in R2011b on Win XP), leading to a crash of the standalone application. Based on the posts by Yair, I will sketch a possible route to avoid this issue.

The symptom

In the compiled application, docking could be accomplished by accessing the figure frame’s underlying Java level:

% get java frame for sophisticated modifications
jframe = get(handle(figure_handle), 'JavaFrame');
 
% allow docking
jframe.fHG1Client.setClientDockable(true)

Using this modification, the user is now allowed to dock and undock the figures manually. For initial docking of the figure,

javaFrame.fHG1Client.setClientWindowStyle(true,false)

could be used during figure creation. Unfortunately, there are menu entries in the Figures container which are either unwanted (since not usable) or even directly crash the standalone applications:

Useless Debug menu items in deployed applications

Useless Debug menu items in deployed applications

Menu items crashing deployed applications

Menu items crashing deployed applications

Since crashing menu entries will be found and used by end-users (though these are somehow hidden), these prohibit the usage of the docking feature as long as these could be invoked. So how can we disable / remove these menu items?

The unsuccessful solution

Unfortunately, the straight forward solution of getting the handle to the Figures containers’ menu bar and remove the unwanted items does not work. The reason for this is the (to me unexpected behavior) that the menu bar seems to be rebuilt whenever a figure is docked/undocked.

This is actually the same behavior that automatically rebuilds the Editor’s menu bar whenever an editor file is added/removed. The Editor container is basically the same docking container as the Figures container, as shown by Yair’s setFigDockGroup utility:

Docking a figure in the Editor container (group)

Docking a figure in the Editor container (group)

Therefore, removing unwanted menu items only helps until the next figure docking/undocking. To make it even worse: also pressing any of the buttons within the document bar (if having more than one figure) somehow rebuilds the entire menu structure, reverting our changes. So the solution becomes a bit more complex.

The working solution

For the working solution, many pieces presented by Yair should be put together. The first piece results from the question how to detect a dock/undock event. Since no such callback is defined, we need to use a property listener as Yair showed in his post about the continuous slider callback:

% listen to the WindowStyle property to detect docking / undocking events
hProp = findprop(handle(figure_handle),'WindowStyle');  % a schema.prop object
 
% if the event occurs, invoke the callback
hlistener = handle.listener(handle(figure_handle), hProp, 'PropertyPostSet',{@(source, event) Callback_DockingFcn});
 
% attach listener to the GUI since it needs to be known (as long as the figure exists)
setappdata(figure_handle, 'Handle_Listener', hlistener);

Now, whenever the figure’s WindowStyle property (which controls the docking state) is changed, our docking callback is invoked.

The next piece of the puzzle takes care of the menu rebuild whenever any document bar button is pressed. To overcome this behavior, the idea is to define the MousePressed callback of theses buttons to (again) invoke the docking callback. This is necessary for two reasons: First, pressing the button (i.e., changing the current figure) rebuilds the menu, overwriting our changed menu entries. Secondly, all other buttons are also somehow rebuilt and the callbacks are removed if a new figure is docked.

The handles to the document bar buttons could be found using Yair’s findjobj utility. We have already seen that the Editor container is analogous to the Figures docking container. So let’s use the method described by Yair for accessing the Editor container, to access the Figures container:

figures_container = javaObjectEDT(matlab_instance.getGroupContainer('Figures'));
figures_frame = javaObjectEDT(figures_container.getTopLevelAncestor);

Once we get the Java Frame for the Figures container, the buttons could be found by digging through its children. This finally allows to set the callback using

DTDocumentBar = javaObjectEDT(figures_frame.getRootPane.getLayeredPane.getComponent(1).getComponent(1).getComponent(0).getComponent(0).getComponent(1).getComponent(0));
ContentPanel = javaObjectEDT(DTDocumentBar.getComponent(0).getComponent(0).getViewport.getView);
 
if ~isempty(ContentPanel.getComponents) % less than two documents are open and no DTDocumentbar exists
    drawnow; pause(0.05)
    GroupPanel = javaObjectEDT(ContentPanel.getComponent(0));
    GroupPanel_Elements = javaObjectEDT(GroupPanel.getComponents);
 
    % change the MousePressed Callback for each of the buttons to invoke the function which disables the menu
    for n = 1 : GroupPanel.getComponentCount
        thisElement = GroupPanel_Elements(n);
        if isequal(char(thisElement.getClass.toString), 'class com.mathworks.widgets.desk.DTDocumentBar$DocumentButton')
            set(handle(thisElement, 'CallbackProperties'), 'MousePressedCallback', {@(source, event) Cbrake_Callback_Diagrams_DockingFcn})
        end
    end
    drawnow; pause(0.05)
end

where the loop runs through the current buttons in the document bar.

As the last step of our procedure, we finally remove (or disable) the menu entries which are unwanted. This is achieved by extracting the handle to the Figures menu by:

figures_menu = javaObjectEDT(figures_frame.getJMenuBar);

Running through the menu items, searching for the unwanted entries (as long as they have pre-defined menu-item names) at the end sets us into the position to take care of the menu items:

% run through top-level menu items
for n = 1 : figures_menu.getMenuCount
    % completely deactivate Debugging options
    if isequal(char(figures_menu.getMenu(n-1).getName), 'DesktopDebugMenu')
        DesktopDebugMenuPos = n - 1;
    end
 
    % Remove some items from the Desktop menu
    if isequal(char(figures_menu.getMenu(n-1).getName), 'DesktopMenu')
        desktop_menu = javaObjectEDT(figures_menu.getMenu(n-1));
 
        DeletePos = [];
        for m = 1: desktop_menu.getMenuComponentCount
            if ismember({char(desktop_menu.getMenuComponent(m-1).getName)}, ...
                        {'ToggleFigure PaletteCheckBoxMenuItem', 'TogglePlot BrowserCheckBoxMenuItem', 'ToggleProperty EditorCheckBoxMenuItem'})
                DeletePos(end+1) = m - 1;
            end
        end
 
        for m = length(DeletePos) : -1 : 1
            desktop_menu.remove(DeletePos(m))
        end
    end
end
 
% finally remove the "Debug" menu
if ~isempty(DesktopDebugMenuPos)
    figures_menu.remove(DesktopDebugMenuPos)
end

Since this callback is invoked whenever a figure is docked/undocked, or the currently shown figure is changed (by pressing the document bar button), all unwanted menu items within the Figures menu could be removed.

As a result, the new Figures container menu looks like:

Deployed menu without unwanted items

Deployed menu without unwanted items

Remarks

I must admit that above solution is still imperfect. For instance, sometimes there is a larger delay between the docking (or button press event) and the removing of the menu item. Nevertheless, this solution allows me to distribute my standalone with docked figures without having menu items directly leading to a fatal error.

Obviously, the solution has some positive side effects:

  • As could be seen from the screen shot, the Matlab desktop becomes available also within your compiled applications. This might be wanted. If not, it could be removed the same way as the other menu items. One drawback of making the desktop available should be mentioned: In my tests, the standalone Matlab desktop shows the whole list of recent files I have in the Matlab editor at compile time. This is somehow ugly but not that problematic.
  • Additional menu items could be added, giving more possibilities for modifications.

I have uploaded a first version of the docking and creation functions, together with a small test project, to the Matlab file Exchange. Readers are welcome to download the code and send me improvement suggestions. Or you could simply leave a comment below.

]]>
https://undocumentedmatlab.com/blog_old/disabling-menu-entries-in-deployed-docked-figures/feed 14
Matlab installation take 2https://undocumentedmatlab.com/blog_old/matlab-installation-take-2 https://undocumentedmatlab.com/blog_old/matlab-installation-take-2#comments Wed, 12 Sep 2012 13:08:34 +0000 https://undocumentedmatlab.com/?p=3140 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. 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....
  3. Changing Matlab’s Command Window colors – part 2 The Matlab Command Window enables a limited degree of inline color customization - this post describes how to use it...
  4. 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...
]]>
It’s that time of the year again. With Matlab 8.0 (R2012b) now available for download, I once again installed a new release. Today’s post will detail some of the post-installation steps I did for the new installation to work properly, for me at least. Nothing special compared to past releases, but worth listing anyway I guess. I won’t bother repeating the list that I published here exactly one year ago.

Removing extra files

Since my complaint last year, I see that some (not all) of the Japanese-language files have been removed from the installation. This is good, although some large Japanese files remain (e.g., the installation guide PDF and many help files) which a smart installer (or even better – the JNLP downloader) might know to ignore based on my computer’s locale.

In any case, what has been added to my dislike, are files in Chinese, specifically the helpsearch_zh_CN folder in %matlabroot%/help/ and %matlabroot%/help/matlab/, each weighing a hefty 14MB. I really hate giving Matlab the adjective of “bloatware”, but its releases keep getting larger and large (R2012b weighs over 800MB!) and I feel that a lot of it, like these Chinese files, could be avoided with only a little bit of extra care on the part of MathWorks. Not all computers have 100GB of free disk space, you know…

Modifying some Matlab m-files

I have several standard changes that I often make to Matlab files. These changes are naturally not propagated when installing a new Matlab release. I can understand this and I’m not complaining. I just need to go over the list of functions and re-modify them:

  1. profview and matlab-report-styles.css (both in %matlabroot%/toolbox/matlab/codetools/) – I’ll post a separate article about this next week, together with some additional undocumented profiling options that I did not cover in my previous article on this topic.
  2. uitree, uitab and other semi-documented functions (mostly in %matlabroot%/toolbox/matlab/uitools/) such as the useful hgfeval – add a % character at the beginning of line #3, in order to make the help section become visible during help or doc.

Preferences, workspace

This is one step that I do not need to do when installing on a machine having a previous Matlab installation. The installer is smart enough to detect that installation and copy its preference files to the new installation. However, updating the default preferences is indeed necessary for a fresh install, and since I was asked about this I thought to include this here.

So here are the changes that I normally make to the default preferences:

  1. General – Confirmation Dialogs – uncheck several confirmations
  2. General – Java Heap Memory – increase to 256 or 512MB
  3. Keyboard – check the <Tab key narrows completion> option (most useful for the desktop – see related article)
  4. Fonts – Monospaced 10pt => Courier New 8pt (the Monospace font is often displayed incorrectly, as a proportional rather than fixed-width font. Using Courier solves this problem. 8pt gives me more real-estate and still looks good on my display)
  5. Colors – Programming Tools – check all the options except <Show lines between sections>
  6. Command Window – Text display: long g compact; uncheck <Show getting started msg>; scroll buffer: 5K=>25K (will MathWorks ever increase this hard-coded limit?!)
  7. Editor – Most recently used (MRU): 4=>12 (until recently Matlab only supported 9, hurray)
  8. Editor – Display – check all options (on some older releases the <Show lines between sections> was here and needed to be unchecked; this option is now in Colors – programming Tools); Show line at 75 => 120 columns
  9. Editor – Tab – check all options
  10. Editor – Language – Max column width: 75 => 120; Indent all functions (not just nested)
  11. Editor – Code Folding – check all options in the <Enable> column; check most options in the <Fold Initially> column
  12. Editor – Autosave – Append file name with asv => ~
  13. GUIDE – uncheck all options except <Show file extension in window title>

And in the Workspace panel, only show the Name, Value, Bytes and Class columns (right-click the column headers to select).

A few words about R2012b

The new R2012b release has received the version ID of 8.0. Despite my speculations in 2010 (here and here) that Matlab 8.0 will bring along the promise of the much-awaited HG2, it turns out that I was incorrect. The new release still does not incorporate HG2. We can see a gradual progression in the work by starting Matlab with the “-hgVersion 2” switch that I described there, but this has still not made it into the mainstream figure window. Hopefully we will get HG2 sometime next year.

R2012b does include a major facelift to the Desktop and Editor, using the new MS-Office-like toolstrip that I exposed here last year. Some people hate toolstrips, some love them, but whatever your personal preference is, Matlab does not have an option to switch back to the non-toolstripped appearance, so for good or worse we’re stuck with the new look. The new toolstrip is currently shown only in the Desktop and related tools, not in figure windows (perhaps in anticipation for HG2? I don’t know). Which reminds me that it’s really about time for me to write a detailed technical article explaining how to add a toolstrip to figure windows.

Another thing you’ll notice in the new release is a facelift to the documentation and the Matlab browser (tabs, finally!), along with a Quick Access Bar (QAB) and a Win7-like current-folder combo-box control.

Matlab's new look (click to zoom)

Matlab's new look (click to zoom)

One specific new features that readers of this blog (I, for one) will probably bless, is the ability to create a custom user Java static classpath and librarypath files, that will override and extend Matlab’s auto-generated classpath.txt and librarypath.txt files. The new custom files should be called javaclasspath.txt, javalibrarypath.txt and be placed in your prefdir or startup folder (the latter is useful for deployed applications). This finally puts an end to the need to update these files for each Matlab release, along with the ensuing compatibility problems that arose from incompatible set of Matlab JAR files. This solves a very painful operational issue for me and I’m sure that also for others.

Another Java-related improvement is the ability to get the underlying Java exception object in the catch part of a try-catch block. Not a biggie for me, but certainly a nice-to-have.

Sadly, if you’re looking for really important engine upgrades, then I haven’t found any that really caught my eye in the release notes. Maybe next year…

]]>
https://undocumentedmatlab.com/blog_old/matlab-installation-take-2/feed 32
Bold color text in the Command Windowhttps://undocumentedmatlab.com/blog_old/bold-color-text-in-the-command-window https://undocumentedmatlab.com/blog_old/bold-color-text-in-the-command-window#comments Wed, 08 Aug 2012 18:00:34 +0000 https://undocumentedmatlab.com/?p=3052 Related posts:
  1. 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....
  2. setPrompt – Setting the Matlab Desktop prompt The Matlab Desktop's Command-Window prompt can easily be modified using some undocumented features...
  3. Customizing Workspace context-menu Matlab's Workspace table context-menu can be configured with user-defined actions - this article explains how....
  4. Variables Editor scrolling The Matlab Variables Editor can be accessed to provide immediate scrolling to a specified cell location. ...
]]>
A reader comment last week sent me on a short wild goose chase, that had an interesting and useful conclusion. The comment requested a way to display bold text in the Command Window, similarly to the way that we can display colored and underlined text using my cprintf utility.

Since Matlab release 7.13 (R2011b), the Matlab Command Window (CW) has the ability to display bold text. This is used, for example, when displaying the function name in the output of the help function (i.e., help(‘max’) will display the term ‘max’ in bold when displaying the help section). It therefore seemed a reasonable request to add this functionality to cprintf.

Attempt #1: use the underlying Java

I stated out investigating the relevant attributes used by the CW’s underlying Java component to display the text. It turns out that in addition to the three custom attributes used by Matlab in past releases, a fourth attribute called BoldStartTokens was added, which stored the relative position index of the bold text within each text element.

Unfortunately, this attribute contains an array of integer values, that get converted to a simple numeric array in Matlab. This means that unlike the SyntaxTokens attribute, which contains an array of Java String objects that can be modified one at a time (this is used by cprintf), the BoldStartTokens attribute value cannot be modified in a similar manner. Attempting to remove and add the attribute afresh (with modified values) failed due to a javax.swing.text.StateInvariantError: Illegal cast to MutableAttributeSet Java exception.

So unless I find a way to update the BoldStartTokens attribute values from Matlab, this looked like a dead end.

Attempt #2: follow the Matlab trail

My second attempt was to follow the Matlab trail, to see exactly what the help function does internally to format parts of the text as bold. Starting with help‘s m-file (%matlabroot%/toolbox/matlab/helptools/help.m), and step-by-step debugging, I quickly found out that the internal function prepareHelpForDisplay parses the help text and wraps the relevant terms with an HTML <strong> tag to make these terms appear bold.

We can easily use this information ourselves:

>> fprintf('not bold, <strong> bold </strong>\n')
not bold, bold     % the 'bold' term appears bolded

Matlab does have an internal limitation, of not allowing hyperlinks and bold formatting together. If both <a> and <strong> tags are present, then only the inner tag set is parsed.

Updating cprintf

Using <strong> is great, but apparently if we use the <strong> tag in cprintf, the output gets messed up – the HTML tag confuses cprintf. So I took the opportunity to update cprintf such that (1) it will not get confused by a <strong> tag, and (2) so that we could use ‘*’ in the style part (input argument #1) to specify bold format:

>> cprintf('*blue', 'this is bold\n')
this is bold     % this text appears bolded-blue

cprintf demo

cprintf demo


The benefit of using cprintf over directly using the <strong> tag is that it works seamlessly on Matlab release 2011a and earlier that do not support the tag (the text is simply not bolded, whereas if we had used <strong> this tag would be displayed onscreen, which is ugly). Moreover, cprintf catches a situation of trying to use both underline and bold formats, and issues a warning. Finally, of course, ‘*’ is more compact and easier to use and maintain than ‘<strong>…</strong>’ …

Please feel free to download cprintf from the File Exchange and read its contents to see how a not-too-large utility can achieve something previously believed to be impossible. And if you find ways to make cprintf better, please do let me know (I don’t mean suggestions for *me* to work on: I mean actual improvements that *you* made to the code).

]]>
https://undocumentedmatlab.com/blog_old/bold-color-text-in-the-command-window/feed 3
Recovering previous editor statehttps://undocumentedmatlab.com/blog_old/recovering-previous-editor-state https://undocumentedmatlab.com/blog_old/recovering-previous-editor-state#comments Wed, 11 Jan 2012 18:00:49 +0000 https://undocumentedmatlab.com/?p=2656 Related posts:
  1. Setting desktop tab completions The Matlab desktop's Command-Window tab-completion can be customized for user-defined functions...
  2. Class object tab completion & improper field names Tab completions and property access can be customized for user-created Matlab classes. ...
  3. Another couple of Matlab bugs and workarounds A couple of internal Matlab bugs and their workarounds. ...
  4. User-defined tab completions – take 2 Matlab has changed the mechanism that enables user-defined tab-completion of function inputs. ...
]]>
Editor with multiple loaded documents I find it very useful to use the Matlab editor’s ability to load multiple files to help me remember which files I still need to work on. I typically have a few dozen files loaded in the editor. I guess you could say that the editor’s list of files is a simple reflection of my open tasks. It would be extremely inconvenient if I ever lost this list.

Which is, unfortunately, exactly what happened to me yesterday.

I was about to close a figure window and accidentally closed the editor window that was behind it.

I was now in quite a jam: reopening the editor would not load all my files, but start with a blank (empty) editor. The Matlab editor, unlike modern browsers, does not have a ‘reopen last session’ option, and using the most-recently-used (MRU) files list would at best return the latest 9 files (the default Matlab preference is to have an MRU depth of only 4 files, but this is one of the very first things that I change whenever I install Matlab, along with a few other very questionable [IMHO] default preferences).

Luckily for me, there is an escape hatch: Matlab stores its Desktop windows state in a file called MATLABDesktop.xml that is located in the user’s prefdir folder. This file includes information about the position and state (docked/undocked etc.) of every Desktop window. Since the editor files are considered Desktop documents (you can see them under the Desktop’s main menu’s Window menu), they are also included in this file. When I closed the Editor, these documents were simply removed from the MATLABDesktop.xml file.

It turns out that Matlab automatically stores a backup version of this file in another file called MATLABDesktop.xml.prev, in the same prefdir folder. We can inspect the folder using our system’s file browser. For example, on Windows we could use:

winopen(prefdir)

So before doing anything else, I closed Matlab (I actually crashed it to prevent any cleanup tasks to accidentally erase this backup file, but that turned out to be an unnecessary precaution), deleted the latest MATLABDesktop.xml file, replaced it with a copy of the MATLABDesktop.xml.prev file (which I renamed MATLABDesktop.xml), and only then did I restart Matlab.

Problem solved – everything back to normal. Resume breathing. Once again I have my never-ending virtual task list in front of me as I write this.

Lessons learned:

  1. don’t be too quick on the close button trigger
  2. always keep a relatively recent backup copy of your important config files (BTW, I use the same advice with my FireFox browser, where I normally have dozens of open tabs – I keep a backup copy of the sessionstore.js file)
  3. if you do get into a jam, don’t do anything hasty that might make recovery impossible. Calm down, look around, and maybe you’ll find an automatic backup somewhere
]]>
https://undocumentedmatlab.com/blog_old/recovering-previous-editor-state/feed 22
Transparent Matlab figure windowhttps://undocumentedmatlab.com/blog_old/transparent-matlab-figure-window https://undocumentedmatlab.com/blog_old/transparent-matlab-figure-window#comments Wed, 13 Apr 2011 23:22:38 +0000 https://undocumentedmatlab.com/?p=2246 Related posts:
  1. Detecting window focus events Matlab does not have any documented method to detect window focus events (gain/loss). This article describes an undocumented way to detect such events....
  2. Enable/disable entire figure window Disabling/enabling an entire figure window is impossible with pure Matlab, but is very simple using the underlying Java. 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. Setting status-bar text The Matlab desktop and figure windows have a usable statusbar which can only be set using undocumented methods. This post shows how to set the status-bar text....
]]>
Every now and then, a user asks whether it is possible to make an entire Matlab window transparent (example). This could be used, for example, for window fade-in/fade-out effects. The short answer is that there is no supported way of doing this with pure documented Matlab, but it is trivially easy to achieve using just a bit of Java magic powder (surprise, surprise).

Matlab figure window transparency

Following an idea I got from Malcolm Lidierth’s MUtilities submission on the Matlab File Exchange, the solution for setting Matlab figure window transparency is quite simple: Get the figure’s underlying Java window reference handle, as in last week’s article. Then use Java’s setWindowOpacity method to set the window’s transparency value. Actually, setWindowOpacity sets the opacity level, rather than transparency, but they are obviously complementary and I personally find “transparency” to be more easily understandable.

By default, windows are created with an opacity of 1.0 (= not transparent). They can be set to any floating-point value between 0.0-1.0, where an opacity of 0.0 means full transparency, and any value in between means partial transparency (i.e., translucency):

jFigPeer = get(handle(gcf),'JavaFrame');
jWindow = jFigPeer.fFigureClient.getWindow;
com.sun.awt.AWTUtilities.setWindowOpacity(jWindow,0.7)

Semi-transparent (translucent) Matlab figure (click to enlarge)

Semi-transparent (translucent) Matlab figure (click to enlarge)

Similarly, you can set the entire Matlab Desktop’s transparency/opacity value:

jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance.getMainFrame;
com.sun.awt.AWTUtilities.setWindowOpacity(jDesktop, 0.8);

Note that the com.sun.awt.AWTUtilities class also enables other GUI effects that would make a Matlab GUI developer’s mouth to start drooling: shaped windows, per-pixel transparency values, mirroring/reflection, window shadows, gradients etc. Perhaps I’ll explore their adaptation for Matlab figures someday.

Fade-in / fade-out

Window fade-in/fade-out effects can easily be achieved using transparency: Simply invoke the setWindowOpacity method several times, with progressively higher or lower values. This is easily done in a simple blocking loop. For example, to fade-out a window:

for stepIdx = 1 : 5
   newAlpha = 1.0 - 0.2*stepIdx;
   com.sun.awt.AWTUtilities.setWindowOpacity(jWindow,newAlpha);
   jWindow.repaint;
   pause(0.2);  % seconds
end

Gradual window fade-out

Gradual window fade-out

A more general example dynamically computes the opacity step size/duration and also enables non-blocking fade effects using an asynchronous timer:

% Compute the required opacity-setting steps
fadeDuration = 1.5;  % seconds
oldAlpha = com.sun.awt.AWTUtilities.getWindowOpacity(jWindow);
newAlpha = 0.0;
deltaAlpha = newAlpha - oldAlpha;
maxStepAlpha = 0.03;
steps = fix(abs(deltaAlpha) / maxStepAlpha) + 1;
stepAlpha = deltaAlpha / steps;
stepDuration = fadeDuration / (steps-1);
 
% If blocking, do the fade effect immediately
if blockingFlag || steps==1
   for stepIdx = 1 : steps
      newAlpha = oldAlpha + stepAlpha*stepIdx;
      com.sun.awt.AWTUtilities.setWindowOpacity(jWindow,newAlpha);
      jWindow.repaint;
      if stepIdx < steps,  pause(stepDuration);  end
   end
else
   % non-blocking: fade in/out asynchronously using a dedicated timer
   start(timer('ExecutionMode','fixedRate', 'Period',0.1, 'TasksToExecute',steps, ...
               'TimerFcn', {@timerFcn,jWindow,oldAlpha,stepAlpha}));
end
 
% Timer function for non-blocking fade-in/fade-out effect
function timerFcn(hTimer,eventData,jFrame,currentAlpha,stepAlpha)  %#ok<INUSL> eventData
  stepIdx = hTimer.TasksExecuted;
  newAlpha = currentAlpha + stepAlpha*stepIdx;
  com.sun.awt.AWTUtilities.setWindowOpacity(jFrame,newAlpha);
  jFrame.repaint;
  if stepIdx == hTimer.TasksToExecute
      stop(hTimer);
      delete(hTimer);
  end
end  % timerFcn

Of course, you can also fade-in/out to intermediate values such as 0.3 or 0.8. If you fade-out completely (i.e., to a value of 0.0), it might be a good idea to actually close the figure window once it gets the totally-transparent value of 0.0.

I’ve prepared a Matlab utility that contains all these options, including optional blocking/non-blocking fade effects, in my setFigTransparency utility, which is available for download on the Matlab File Exchange. You may also wish to use Malcolm Lidierth’s MUtilities, which also has similar functionalities (plus some other goodies).

Limitations

Setting a figure window’s transparency requires using Java Run-time Engine (JRE) 1.6.0_10 (also called “Java 6 update 10”) or higher. This means that it’s supported on Matlab release 7.9 (R2009b) and higher by default, and on earlier releases using a JRE retrofit.

If you are using an earlier Matlab release, consider a retrofit of JRE 1.6.0_10 or any later version (e.g., the latest available version today is 1.6 update 24). The JRE can be downloaded from here, and you can configure Matlab to use it according to the instructions here. As noted, Matlab R2009b (7.9) and onward, at least on Microsoft Windows, pre-bundle a JRE version that does support transparency/opacity and so do not require a retrofit.

You can check your current Java version in Matlab as follows:

>> version -java
ans =
Java 1.6.0_17-b04 with Sun Microsystems Inc. Java HotSpot(TM) Client VM mixed mode

Unfortunately, Matlab plot axes cannot be made transparent. If you have any axes in your GUI, the axes area will simply appear as a shaded axes, whose intensity depends on the selected alpha (transparency) value; the contents beneath the window will not be merged in the axes area as it is in the non-axes areas.

Finally, note that com.sun.awt.AWTUtilities is itself an undocumented Java class. It is bundled with the standard Java release since 2008 (1.6.0_10), and yet is not part of the official release because its API has not yet settled. In fact, in the upcoming Java 7 release, which is expected in a few months, and which I expect to be available in Matlab sometime in 2012, the set of transparency/opacity methods have migrated to the fully-documented java.awt.Window class.

Blurred figure window

So here’s a riddle for you: using figure window transparency, can you guess how to make a Matlab figure appear blurred for disabled figures (see the screenshot there)? There are several possible ways to do this – can you find the simplest? The first one to post a comment with a correct answer gets a smiley… My answer will appear in next week’s article.

Upgraded website

Also, did you notice my new website design? It’s supposed to be much more readable (yes – also on Android…). It now also runs on a multi-server cloud, which means more stability and faster response times. Do you like the new design? hate it? I would love to hear your feedback via comment or email.

]]>
https://undocumentedmatlab.com/blog_old/transparent-matlab-figure-window/feed 18
uisplittool & uitogglesplittoolhttps://undocumentedmatlab.com/blog_old/uisplittool-uitogglesplittool https://undocumentedmatlab.com/blog_old/uisplittool-uitogglesplittool#comments Thu, 09 Dec 2010 00:06:33 +0000 https://undocumentedmatlab.com/?p=1994 Related posts:
  1. uiundo – Matlab’s undocumented undo/redo manager The built-in uiundo function provides easy yet undocumented access to Matlab's powerful undo/redo functionality. This article explains its usage....
  2. uisplittool & uitogglesplittool callbacks Matlab's undocumented uisplittool and uitogglesplittool are powerful toolbar controls - this article explains how to customize their behavior...
  3. Customizing uiundo This article describes how Matlab's undocumented uiundo undo/redo manager can be customized...
  4. Customizing the standard figure toolbar, menubar The standard figure toolbar and menubar can easily be modified to include a list of recently-used files....
]]>
Matlab 7.6 (R2008a) and onward contain a reference to uisplittool and uitogglesplittool in the javacomponent.m and %matlabroot%/bin/registry/hg.xml files. These are reported as built-in functions by the which function, although they have no corresponding m-file as other similar built-in functions (note the double ‘t’, as in split-tool):

>> which uisplittool
built-in (C:\Matlab\R2010b\toolbox\matlab\uitools\uisplittool)

These uitools are entirely undocumented, even today (R2010b). They puzzled me for a very long time. An acute reader (Jeremy Raymonds) suggested they are related to toolbars, like other uitools such as the uipushtool and uitoggletool. This turned out to be the missing clue that unveiled these useful tools:

So what are uisplittool and uitogglesplittool?

Both uisplittool and uitogglesplittool are basic Handle-Graphics building blocks used in Matlab toolbars, similarly to the well-documented uipushtool and uitoggletool.

uisplittool presents a simple drop-down, whereas uitogglesplittool presents a drop-down that is also selectable.

The Publish and Run controls on the Matlab Editor’s toolbar are examples of uisplittool, and so are the Brush / Select-Data control on the figure toolbar, and the plot-selection drop-down on the Matlab Desktop’s Workspace toolbar:

uisplittool in action in the Matlab Desktop

uisplittool in action in the Matlab Desktop

Adding uisplittool and uitogglesplittool to a toolbar

Adding a uisplittool and uitogglesplittool to a toolbar is done in a similar manner to adding uipushtools and uitoggletools:

hToolbar = findall(gcf,'tag','FigureToolBar');
hUndo=uisplittool('parent',hToolbar);       % uisplittool
hRedo=uitogglesplittool('parent',hToolbar); % uitogglesplittool

Like uipushtool and uitoggletool, uisplittool and uitogglesplittool also have unique Type property values, ‘uisplittool’ and ‘uitogglesplittool’ respectively. The handles can also be tested using the built-in isa function:

>> isa(handle(hUndo),'uisplittool')   % or: 'uitogglesplittool'
ans =
     1
>> class(handle(hUndo))
ans =
uisplittool

Just as with uipushtools and uitoggletools, the new buttons have an empty button-face appearance, until we fix their CData, Tooltip and similar settable properties:

% Load the Redo icon
icon = fullfile(matlabroot,'/toolbox/matlab/icons/greenarrowicon.gif');
[cdata,map] = imread(icon);
 
% Convert white pixels into a transparent background
map(find(map(:,1)+map(:,2)+map(:,3)==3)) = NaN;
 
% Convert into 3D RGB-space
cdataRedo = ind2rgb(cdata,map);
cdataUndo = cdataRedo(:,[16:-1:1],:);
 
% Add the icon (and its mirror image = undo) to latest toolbar
set(hUndo, 'cdata',cdataUndo, 'tooltip','undo','Separator','on', ...
           'ClickedCallback','uiundo(gcbf,''execUndo'')');
set(hRedo, 'cdata',cdataRedo, 'tooltip','redo', ...
           'ClickedCallback','uiundo(gcbf,''execRedo'')');

User-created uisplittool & uitogglesplittool toolbar buttons

User-created uisplittool & uitogglesplittool toolbar buttons

Note that the controls can be created with these properties in a single command:

hUndo = uisplittool('parent',hToolbar, 'cdata',cdataRedo, ...);

Re-arranging the toolbar controls placement

Let us now re-arrange our toolbar buttons. Unfortunately, a bug causes uisplittools and uitogglesplittools to always be placed flush-left when the toolbar’s children are re-arranged (anyone at TMW reading this in time for the R2011a bug-parade selection?).

So, we can’t re-arrange the buttons at the HG-children level. Luckily, we can re-arrange directly at the Java level (note that until now, the entire discussion of uisplittool and uitogglesplittool was purely Matlab-based):

jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer');
jButtons = jToolbar.getComponents;
for buttonId = length(jButtons)-3 : -1 : 7  % end-to-front
   jToolbar.setComponentZOrder(jButtons(buttonId), buttonId+1);
end
jToolbar.setComponentZOrder(jButtons(end-2), 5);   % Separator
jToolbar.setComponentZOrder(jButtons(end-1), 6);   % Undo
jToolbar.setComponentZOrder(jButtons(end), 7);     % Redo
jToolbar.revalidate;

Re-arranged uisplittool & uitogglesplittool toolbar buttons

Re-arranged uisplittool & uitogglesplittool toolbar buttons
(not as simple as it may sound)

Next week, I will combine the information in this article, with last year’s articles about uiundo, and show how we can create a dynamic figure toolbar drop-down of undo/redo events. Here is a preview to whet your appetite:

undo/redo buttons implemented using uisplittool

undo/redo buttons implemented using uisplittool

]]>
https://undocumentedmatlab.com/blog_old/uisplittool-uitogglesplittool/feed 9
Customizing Workspace context-menuhttps://undocumentedmatlab.com/blog_old/customizing-workspace-context-menu https://undocumentedmatlab.com/blog_old/customizing-workspace-context-menu#comments Wed, 03 Nov 2010 18:00:17 +0000 https://undocumentedmatlab.com/?p=1943 Related posts:
  1. Variables Editor scrolling The Matlab Variables Editor can be accessed to provide immediate scrolling to a specified cell location. ...
  2. Programmatic shortcuts manipulation – part 2 Non-standard shortcut controls and customizations can easily be added to the Matlab desktop. ...
  3. 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....
  4. setPrompt – Setting the Matlab Desktop prompt The Matlab Desktop's Command-Window prompt can easily be modified using some undocumented features...
]]>
My first article of 2010 described customizing Matlab’s Workspace table, in particular the values presented in the Bytes column.

Last week, a reader of that article posted a comment asking how to customize the context (right-click) menu with some user-defined actions. The user has found that modifying the menu via the regular table handles gets reset automatically.

Today’s article will describe an easy and effective way to add user-defined actions to the Workspace table, for specific object types.

The trick is not to modify the context-menu directly. As the reader above has noticed, this menu is automatically recreated on the fly, so no change will be persistent. Instead, we modify Matlab’s internal registry of class-specific context-menus. This is done in several prefspanel.m files in the Matlab codebase (For example: \toolbox\matlab\audiovideo\prefspanel.m and \toolbox\signal\signal\prefspanel.m).

The mechanism relies on the following Java method, which is unsupported and undocumented, yet has existed in the present form for the past several releases:

classes = {'double', 'java.lang.Object'};
menuName = 'My context-menu';
menuItems = {'Inspect', 'Properties', '-', 'class name'};
menuActions = {'inspect($1)', 'get($1)', '', 'class($1)'};
com.mathworks.mlwidgets.workspace.MatlabCustomClassRegistry.registerClassCallbacks(classes,menuName,menuItems,menuActions);

Customizable Workspace table context-menu

Customizable Workspace table context-menu

Once you have found your particular context-menu configuration useful, place the short customization code in your startup.m file so that the change becomes permanent in all future Matlab sessions.

A few other supporting static methods are available in the com.mathworks.mlwidgets.workspace.MatlabCustomClassRegistry class: getClassCallbacksInformation (className), registerSimilarClassCallbacks(newClassNames,definedClassName) and unregisterClassCallbacks(definedClassName). For example:

com.mathworks.mlwidgets.workspace.MatlabCustomClassRegistry.getClassCallbacksInformation('double')
 
ans =
java.lang.Object[]:
    'My context-menu'
    [4 element array]        % = menuItems
    [4 element array]        % = menuActions
]]>
https://undocumentedmatlab.com/blog_old/customizing-workspace-context-menu/feed 19