schema.prop – 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 2 (ToolGroup App)https://undocumentedmatlab.com/blog_old/matlab-toolstrip-part-2-toolgroup-app https://undocumentedmatlab.com/blog_old/matlab-toolstrip-part-2-toolgroup-app#comments Wed, 05 Dec 2018 17:00:48 +0000 https://undocumentedmatlab.com/?p=8059 Related posts:
  1. Matlab toolstrip – part 9 (popup figures) Custom popup figures can be attached to Matlab GUI toolstrip controls. ...
  2. Figure window customizations Matlab figure windows can be customized in numerous manners using the underlying Java Frame reference. ...
  3. Builtin PopupPanel widget We can use a built-in Matlab popup-panel widget control to display lightweight popups that are attached to a figure window. ...
  4. Matlab toolstrip – part 6 (complex controls) Multiple types of customizable controls can be added to Matlab toolstrips...
]]>
A while ago I posted the first of my planned miniseries on the Matlab toolstrip (ribbon). Today I will expand that post by discussing how toolstrips can be added to Matlab GUIs. This post will remain at a high-level as the previous post, with followup posts drilling into the technical details of the toolstrip components (inner packages and classes).

We can add a Matlab toolstrip to 3 types of Matlab GUI windows:

  1. To a Java-based Matlab figure (so-called “legacy” figures, created using GUIDE or the figure function)
  2. To a container window of docked Java-based figures, typically called an “App” (marketing name) or “Tool Group” (internal technical name)
  3. To a JavaScript/HTML-based Matlab figure (so called “web” figures, created using App Designer or the uifigure function)

Today I will show how to add a basic dynamic toolstrip to a ToolGroup (App, window type #2):

ToolGroup with clients and dynamic toolstrip

ToolGroup with clients and dynamic toolstrip


Figure containers (“Tool Groups”)

Most Matlab users are familiar with window types #1 and #3 (legacy and web-based figures), but type #2 may seem strange. In fact, it shouldn’t be: All the Matlab “Apps” and Desktop components use such a container of docked clients. For example, both the Matlab Editor and Desktop are containers of individual client windows (individual files in the Editor; Command Window, Workspace etc. in the desktop).

Similarly, when we dock figures, they dock as client windows into a container called “Figures” (this can be controlled programmatically: see my setFigDockGroup utility on the File Exchange). This is the basis for all Matlab “Apps”, as far as I am aware (some Apps may possibly use a different GUI container, after all there are ~100 Matlab Apps and I’m not familiar with all of them). Such Apps are basically stand-alone Tool Groups (client container windows) that contain one or more docked figures, a toolstrip, and a side-panel with controls (so-called “Data Browser”).

Note: MathWorks uses confusing terminology here, using the same term “App” for both MathWorks-created GUIs containers (that have toolstrips, Data Browser and docked figures) and also user-created utilities on the File Exchange (that do not have these). Unfortunately, MathWorks has chosen not [yet] to release to the general public its set of tools that enable creating true “Apps”, i.e. those that have a toolstrip, Data Browser and docked figures.

Today’s post will attempt to fill this gap, by showing how we can create user Apps that have a toolstrip and docked figures. I will ignore the Data Browser today, and will describe it in a future post. Since docking figures into a standalone user-created container is a solved problem (using my setFigDockGroup utility), this post will focus on adding a toolstrip to such a container.

A ToolGroup object (matlab.ui.internal.desktop.ToolGroup) is created either implicitly (by docking a figure into a group that has a new name), or explicitly (by invoking its constructor):

% Create a new non-visible empty App (Tool Group)
hToolGroup = matlab.ui.internal.desktop.ToolGroup('Toolstrip example on UndocumentedMatlab.com');

Some things only work properly after the app is displayed, so let’s display the ToolGroup (however, note that for improved performance it is better to do whatever customizations and GUI updates that you can before the app is made visible):

% Display the ToolGroup window
hToolGroup.open();

Basic empty ToolGroup (without toolstrip or clients)

Basic empty ToolGroup (without toolstrip or clients)

An annoying quirk with ToolGroups is that they automatically close when their reference handle is deleted from Matlab memory. The specific behavior changes depending on the contents of the container and the Matlab release, but in general it’s safest to preserve the hToolGroup variable, to prevent the window from closing, when this variable goes out of scope, when the function (in which we create the ToolGroup) returns. There are many ways to persist this variable. Here’s one alternative, in which we persist it in itself (or rather, attached to its internal Java peer control):

% Store toolgroup reference handle so that app will stay in memory
jToolGroup = hToolGroup.Peer;
internal.setJavaCustomData(jToolGroup, hToolGroup);

internal.setJavaCustomData is an undocumented Matlab function that adds a new custom property to a Java reference handle. In our case, it adds a CustomData property to the jToolGroup handle and sets its value to the Matlab hToolGroup handle. The source code for internal.setJavaCustomData is available in %matlabroot%/toolbox/shared/controllib/general/+internal/setJavaCustomData.m and is very simple: it essentially uses the old schema-based schema.prop method for adding new properties to handles. Schema is an old deprecated mechanism that is mostly replaced by the newer MCOS (Matlab Class Object System), but for some specific cases such as this it’s still very useful (the standard addprop function can add new properties to Matlab GUI handles, but not to Java reference handles).

Finally, let’s discard the Data Browser side panel (I’ll discuss it in a separate future post):

% Discard the Data-browser left panel
hToolGroup.disableDataBrowser();

Adding a toolstrip to the ToolGroup

Now that we have the basic container ready, let’s add a toolstrip. To simplify matters in this introductory post (after all, I have still not described the internal packages and classes that make up a toolstrip), we’ll use some of the tabs used in the showcaseToolGroup example that I discussed in my previous post. You can see the relevant source code in %matlabroot%/toolbox/matlab/toolstrip/+matlab/+ui/+internal/+desktop/*.m, in case you want to jump ahead and customize your own toolstrip tabs, groups and buttons. In the code snippet below, we first create an empty TabGroup, then add toolstrip tabs into it, and finally add this TabGroup into our ToolGroup using its addTabGroup(hTabGroup) method:

% Create a new tab group
%hTabGroup = matlab.ui.internal.desktop.showcaseBuildTabGroup('swing');
hTabGroup = matlab.ui.internal.toolstrip.TabGroup();
hTab1 = matlab.ui.internal.desktop.showcaseBuildTab_Buttons('swing');
hTabGroup.add(hTab1);
%hTabGroup.add(matlab.ui.internal.desktop.showcaseBuildTab_Gallery());
hTabGroup.add(matlab.ui.internal.desktop.showcaseBuildTab_Layout('swing'));
 
% Select tab #1 (common)
hTabGroup.SelectedTab = hTab1;
 
% Add the tab group to the built-in toolstrip
hToolGroup.addTabGroup(hTabGroup);

We now have an “App” that has a toolstrip, but no clients (yet), and a hidden Data Browser side-panel:

ToolGroup "App" with a simple toolstrip (no clients yet)

Now let’s add some clients (docked figures):

Adding clients (docked figures) to the ToolGroup

There are two easy variants for adding docked figures in a ToolGroup: The easiest is to use the ToolGroup’s addFigure(hFigure) method:

% Create a figure and dock it into the tool-group
hFig1 = figure('Name','3D');
surf(peaks);
hToolGroup.addFigure(hFig1);

The second variant enables to dock a figure that has a specific set of toolstrip tabs attached to it. These tabs will only display in the toolstrip when that particular figure has focus. We do this by creating a new TabGroup (just as we have done above), and then add the figure and TabGroup to the container using the ToolGroup’s addClientTabGroup(hFigure,hTabGroup) method:

% Create the 2nd figure
hFig2 = figure('Name','2D');
plot(rand(5)); drawnow
 
% Add a few tabs that are only relevant to this specific figure
hTabGroup2 = matlab.ui.internal.toolstrip.TabGroup();
hTab2 = matlab.ui.internal.desktop.showcaseBuildTab_Selections();
hTabGroup2.add(hTab2);
hTabGroup2.add(matlab.ui.internal.desktop.showcaseBuildTab_EditValue());
 
% Add the figure and tabs to the ToolGroup
hToolGroup.addClientTabGroup(hFig2, hTabGroup2);

ToolGroup with clients and dynamic toolstrip

ToolGroup with clients and dynamic toolstrip

In this example, the “Selection” and “Values” toolstrip tabs only appear when the 2nd figure (“2D”) has focus. A similar behavior exists in the Matlab Desktop and Editor, where some tabs are only shown when certain clients have focus.

Removing the View tab

Note that the “View” toolstrip tab (which enables setting the appearance of the docked figures: layout, tab positions (top/bottom/left/right), ordering etc.) is automatically added to the toolstrip and always appears last. We can remove this View tab using the ToolGroup’s hideViewTab() method. The tab will not immediately be removed, only when the toolstrip is repainted, for example, when we switch focus between the docked figures:

hToolGroup.hideViewTab;  % toolstrip View tab is still visible at this point
figure(hFig1);  % change focus to hFig1 - toolstrip is repainted without View tab

Conclusion

It’s relatively easy to dock figures into a standalone “App” window that has a custom toolstrip, which can even be dynamically modified based on the figure which is currently in focus. Naturally, this has little benefit if we cannot customize the toolstrip components: labels, icons, control type, grouping and most importantly – callbacks. This topic deserves a dedicated post, which I plan to be the next in this miniseries. Stay tuned – hopefully the next post will not take me as long to publish as this post (I was quite busy recently)…

]]>
https://undocumentedmatlab.com/blog_old/matlab-toolstrip-part-2-toolgroup-app/feed 11
Adding custom properties to GUI objectshttps://undocumentedmatlab.com/blog_old/adding-custom-properties-to-gui-objects https://undocumentedmatlab.com/blog_old/adding-custom-properties-to-gui-objects#comments Thu, 15 Feb 2018 12:39:35 +0000 https://undocumentedmatlab.com/?p=7324 Related posts:
  1. Matlab and the Event Dispatch Thread (EDT) The Java Swing Event Dispatch Thread (EDT) is very important for Matlab GUI timings. This article explains the potential pitfalls and their avoidance using undocumented Matlab functionality....
  2. Tab panels – uitab and relatives This article describes several undocumented Matlab functions that support tab-panels...
  3. uitree This article describes the undocumented Matlab uitree function, which displays data in a GUI tree component...
  4. Borderless button used for plot properties A borderless button can be used to add unobtrusive functionality to plot axes...
]]>
Matlab objects have numerous built-in properties (some of them publicly-accessible/documented and others not, but that’s a different story). For various purposes, it is sometimes useful to attach custom user-defined properties to such objects. While there was never a fully-documented way to do this, most users simply attached such properties as fields in the UserData property or the object’s [hidden] ApplicationData property (accessible via the documented setappdata/getappdata functions).

An undocumented way to attach actual new user-defined properties to objects such as GUI handles or Java references has historically (in HG1, up to R2014a) been to use the undocumented schema.prop function, as I explained here. As I wrote in that post, in HG2 (R2014b onward), we can use the fully-documented addprop function to add new custom properties (and methods) to such objects. What is still NOT documented, as far as I could tell, is that all of Matlab’s builtin handle graphics objects indirectly inherit the dynamicprops class, which allows this. The bottom line is that we can dynamically add custom properties in run-time to any HG object, without affecting any other object. In other words, the new properties will only be added to the handles that we specifically request, and not to any others.

All this is important, because for some unexplained reason that escapes my understanding, MathWorks chose to seal its classes, thus preventing users to extend them with sub-classes that contain the new properties. So much frustration could have been solved if MathWorks would simply remove the Sealed class meta-property from its classes. Then again, I’d have less to blog about in that case…

Anyway, why am I rehashing old news that I have already reported a few years ago?

Well, first, because my experience has been that this little tidbit is [still] fairly unknown by Matlab developers. Secondly, I happened to run into a perfect usage example a short while ago that called for this solution: a StackExchange user asked whether it is possible to tell a GUI figure’s age, in other words the elapsed time since the figure was created. The simple answer would be to use setappdata with the creation date whenever we create a figure. However, a “cleaner” approach seems to be to create new read-only properties for the figure’s CreationTime and Age:

First, create a small Matlab function as follows, that attaches the CreationTime property to a figure:

function setCreationTime(hFig,varargin)
   hProp = addprop(hFig,'CreationTime');
   hFig.CreationTime = now;
   hProp.SetAccess = 'private';  % make property read-only after setting its initial value
 
   hProp = addprop(hFig,'Age');
   hProp.GetMethod = @(h,e) etime(datevec(hFig.CreationTime), clock);  % compute on-the-fly
   hProp.SetAccess = 'private';  % make property read-only
end

Now assign this function as the default CreateFcn callback function for all new figures from now on:

set(0,'DefaultFigureCreateFcn',@setCreationTime)

That’s it – you’re done! Whenever a new figure will be created from now on, it will have two custom read-only properties: CreationTime and Age.

For example:

>> newFig = figure;
>> newFig.CreationTime
ans =
      737096.613706748
 
>> ageInDays = now - newFig.CreationTime
ageInDays = 
       0.0162507836846635
>> ageDuration = duration(ageInDays*24,0,0)
ageDuration = 
  duration
   00:23:24
>> ageString = datestr(ageInDays, 'HH:MM:SS.FFF')
ageString = 
    '00:23:24.068'
 
>> ageInSecs = newFig.Age
ageInSecs =
       1404.06771035492

Note that an alternative way to set the computed property Age would have been to set its value to be an anonymous function, but this would have necessitated invoking it with parenthesis (as in: ageInSecs = newFig.Age()). By setting the property’s GetMethod meta-property we avoid this need.

Keen readers will have noticed that the mechanism that I outlined above for the Age property/method can also be used to add custom user methods. For example, we can create a new custom property named refresh that would be read-only and have a GetMethod which is the function handle of the function that refreshes the object in some way.

Do you have any special uses for custom user-defined properties/methods in your program? or perhaps you have a use-case that might show MathWorks why sub-classing the built-in classes might improve your work? if so, then please place a comment about it below. If enough users show MathWorks why this is important, then maybe it will be fixed in some future release.

]]>
https://undocumentedmatlab.com/blog_old/adding-custom-properties-to-gui-objects/feed 5
Adding dynamic properties to graphic handleshttps://undocumentedmatlab.com/blog_old/adding-dynamic-properties-to-graphic-handles https://undocumentedmatlab.com/blog_old/adding-dynamic-properties-to-graphic-handles#comments Wed, 16 Sep 2015 17:26:44 +0000 http://undocumentedmatlab.com/?p=6006 Related posts:
  1. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
  2. Performance: accessing handle properties Handle object property access (get/set) performance can be significantly improved using dot-notation. ...
  3. 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....
  4. Matlab’s HG2 mechanism HG2 is presumably the next generation of Matlab graphics. This article tries to explore its features....
]]>
A client recently asked me to extend one of Matlab’s built-in graphic containers (uiflowcontainer in this specific case) with automatic scrollbars that would enable the container to act as a scroll-panel. The basic idea would be to dynamically monitor the container’s contents and when it is determined that they overflow the container’s boundaries, then attach horizontal/vertical scrollbars to enable scrolling the contents into view:

Scrollable Matlab container

Scrollable Matlab container

This may sound simple, but there are actually quite a few undocumented hacks that make this possible, including listening to ObjectChildAdded/ObjectChildRemoved events, location/size/visibility events, layout changes etc. Maybe I’ll blog about it in some future article.

Today’s post is focused on a specific aspect of this project, attaching dynamic properties to the builtin uiflowcontainer, that would enable users to modify the container’s properties directly, as well as control aspects of the scrolling using the new properties: handles to the parent container, as well as the horizontal and vertical scrollbars, and even a new refresh() method.

The “textbook” approach to this would naturally be to create a new class that extends (inherits) uiflowcontainer and includes these new properties and methods. Unfortunately, for some reason that escapes my understanding, MathWorks saw fit to make all of its end-use graphic object classes Sealed, such that they cannot be extended by users. I did ask for this to be changed long ago, but the powers that be apparently decided that it’s better this way.

So the fallback would be to create our own dedicated class having all the new properties as well as those of the original container, and ensure that all the property values are synchronized in both directions. This is probably achievable, if you have a spare few days and a masochistic state of mind. Being the lazy bum and authority-rebel that I am, I decided to take an alternate approach that would simply add my new properties to the built-in container handle. The secret lies in the undocumented function schema.prop (for HG1, R2014a and older) and the fully-documented addprop function (for HG2, R2014b and newer).

In the examples below I use a panel, but this mechanism works equally well on any Matlab HG object: axes, lines, uicontrols, figures, etc.

HG2 – addprop function

The addprop function is actually a public method of the dynamicprops class. Both the dynamicprops class as well as its addprop function are fully documented. What is NOT documented, as far as I could tell, is that all of Matlab’s builtin handle graphics objects indirectly inherit dynamicprops, via matlab.graphics.Graphics, which is a high-level superclass for all HG objects. The bottom line is that we can dynamically add run-time properties to any HG object, without affecting any other object. In other words, the new properties will only be added to the handles that we specifically request, and not to any others. This suits me just fine:

hProp = addprop(hPanel, 'hHorizontalScrollBar');
hPanel.hHorizontalScrollBar = hMyScrollbar;
hProp.SetAccess = 'private';  % make this property read-only

The new property hHorizontalScrollBar is now added to the hPanel handle, and can be accessed just like any other read-only property. For example:

>> get(hPanel, 'hHorizontalScrollBar')
ans = 
    JavaWrapper

>> hPanel.hHorizontalScrollBar
ans = 
    JavaWrapper

>> hPanel.hHorizontalScrollBar = 123
You cannot set the read-only property 'hHorizontalScrollBar' of UIFlowContainer.

Adding new methods is more tricky, since we do not have a corresponding addmethod function. The trick I used was to create a new property having the requested new method’s name, and set its read-only value to a handle of the requested function. For example:

hProp = addprop(hPanel, 'refresh');
hPanel.refresh = @myRefreshFunc;
hProp.SetAccess = 'private';  % make this property read-only

We can then invoke the new refresh “method” using the familiar dot-notation:

hPanel.refresh();

Note: if you ever need to modify the initial value in your code, you should revert the property’s SetAccess meta-property to 'public' before Matlab will enable you to modify the value:

try
    % This will raise an exception if the property already exists
    hProp = addprop(hPanel, propName);
catch
    % Property already exists - find it and set its access to public
    hProp = findprop(hPanel, propName);
    hProp.SetAccess = 'public';
end
hPanel.(propName) = newValue;

HG1 – schema.prop function

In HG1 (R2014a and earlier), we can use the undocumented schema.prop function to add a new property to any HG handle (which is a numeric value in HG1). Donn Shull wrote about schema.prop back in 2011, as part of his series of articles on UDD (Unified Data Dictionary, MCOS’s precursor). In fact, schema.prop is so useful that it has its own blog tag here and appears in no less than 15 separate articles (excluding today). With HG2’s debut 2 years ago, MathWorks tried very hard to rid the Matlab code corpus of all the legacy schema-based, replacing most major functionalities with MCOS-based HG2 code. But so far it has proven impossible to get rid of schema completely, and so schema code is still used extensively in Matlab to this day (R2015b). Search your Matlab path for “schema.prop” and see for yourself.

Anyway, the basic syntax is this:

hProp = schema.prop(hPanel, propName, 'mxArray');

The 'mxArray' specifies that the new property can accept any data type. We can limit the property to only accept certain types of data by specifying a less-generic data type, among those recognized by UDD (details).

Note that the meta-properties of the returned hProp are somewhat different from those of HG2’s hProp. Taking this into account, here is a unified function that adds/updates a new property (with optional initial value) to any HG1/HG2 object:

function addProp(hObject, propName, initialValue, isReadOnly)
    try
        hProp = addprop(hObject, propName);  % HG2
    catch
        try
            hProp = schema.prop(hObject, propName, 'mxArray');  % HG1
        catch
            hProp = findprop(hObject, propName);
        end
    end
    if nargin > 2
        try
            hProp.SetAccess = 'public';  % HG2
        catch
            hProp.AccessFlags.PublicSet = 'on';  % HG1
        end
        hObject.(propName) = initialValue;
    end
    if nargin > 3 && isReadOnly
        try
            % Set the property as read-only
            hProp.SetAccess = 'private';  % HG2
        catch
            hProp.AccessFlags.PublicSet = 'off';  % HG1
        end
    end
end
]]>
https://undocumentedmatlab.com/blog_old/adding-dynamic-properties-to-graphic-handles/feed 4
Property value change listenershttps://undocumentedmatlab.com/blog_old/property-value-change-listeners https://undocumentedmatlab.com/blog_old/property-value-change-listeners#comments Wed, 13 Aug 2014 14:12:55 +0000 http://undocumentedmatlab.com/?p=4955 Related posts:
  1. HG2 update HG2 appears to be nearing release. It is now a stable mature system. ...
  2. Performance: accessing handle properties Handle object property access (get/set) performance can be significantly improved using dot-notation. ...
  3. Adding dynamic properties to graphic handles It is easy and very useful to attach dynamic properties to Matlab graphics objects in run-time. ...
  4. Graphic sizing in Matlab R2015b Matlab release R2015b's new "DPI-aware" nature broke some important functionality. Here's what can be done... ...
]]>
For performance reasons, it is almost always better to respond to events (asynchronously), than to continuously check a property value (synchronous polling). Therefore, if we wish to do something when some property value is changed (e.g., log the event, shut down the system, liquidate the portfolio, call the police, …), then it is preferable to attach a property-change listener callback.

The standard (documented) way of attaching a value-change listener to Matlab class properties is via the addlistener function. This only works for handle (not value) classes, and only to those properties that have the SetObservable and/or GetObservable attribute turned on:

addlistener(hClassObject, propertyName, 'PostSet', @myCallbackFcn);

This is all nice and well for Matlab class properties, but what about HG (handle Graphics: plots & GUI) properties? Can we similarly listen to changes in (say) the axes limits? Until now this has been possible, but undocumented. For example, this will trigger myCallbackFcn(hAxes,eventData) whenever the axes limits change (due to zoom, pan, plotting etc.):

addlistener(gca, 'YLim', 'PostSet', @(hAxes,eventData) myCallbackFcn(hAxes,eventData));
 
% Or (shorter equivalent):
addlistener(gca, 'YLim', 'PostSet', @myCallbackFcn);

This could be very useful when such properties could be modified from numerous different locations. Rather than updating all these location to call the relevant callback function directly, we simply attach the callback to the property-change listener. It could also be useful in cases where for some reason we cannot modify the source of the update (e.g., third-party or legacy code).

In addition to PostSet, we could also set listeners for PreSet. Also, we could set listeners on PostGet and PreGet – this could be useful for calculating dynamic (dependent) property values.

Under the hood

The HG1 variant of addlistener is basically equivalent to the following low-level UDD-based code snippet, as explained here:

% Create the listener object
hAxes = handle(gca);  % a UDD axes class object
hProp = findprop(hAxes,'YLim');  % a schema.prop class object
hListener = handle.listener(hAxes, hProp, 'PropertyPostSet', @myCallbackFcn);
 
% persist the listener in memory for as long as the source object (hAxes) is alive
setappdata(hAxes, 'listener__', hListener);

(in old Matlab releases, addlistener was a regular m-function that placed the listeners in the source handle’s ApplicationData property, as the code above shows; newer releases reimplemented addlistener as an internal built-in function and the listener is now stored somewhere in the DLL’s inaccessible memory, rather than in the ApplicationData property)

In HG2, handle.listener no longer works. Fortunately, we don’t need it since we have addlistener that works the same way for both HG1 (UDD objects) and HG2 (MCOS objects). Kudos on the backward-compatibility aspect, MathWorks!

]]>
https://undocumentedmatlab.com/blog_old/property-value-change-listeners/feed 14
Draggable plot data-tipshttps://undocumentedmatlab.com/blog_old/draggable-plot-data-tips https://undocumentedmatlab.com/blog_old/draggable-plot-data-tips#comments Wed, 23 Oct 2013 22:01:32 +0000 http://undocumentedmatlab.com/?p=4294 Related posts:
  1. Matlab’s HG2 mechanism HG2 is presumably the next generation of Matlab graphics. This article tries to explore its features....
  2. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
  3. getundoc – get undocumented object properties getundoc is a very simple utility that displays the hidden (undocumented) properties of a specified handle object....
  4. Handle Graphics Behavior HG behaviors are an important aspect of Matlab graphics that enable custom control of handle functionality. ...
]]>
A couple of years ago, I was asked by a client to figure out a way to make Matlab plot data-tips movable. The problem was that he had a very crowded plot and Matlab’s standard data-tips are displayed immediately adjacent to the data, thereby overlapping the plot parts. Matlab’s standard data-tips enable dragging to a very limited extent (only to the 4 corners of the data-point), and in any case the displayed textbox remains directly attached to the data point.

So I developed a small utility for my client that solves this problem. I then forgot all about it until a few days ago when I came across it again. Yesterday I uploaded this draggableDataTips utility to the File Exchange, where you can download it.

draggableDataTips enables the user to interactively drag any newly-created data-tip, anywhere in the Matlab figure. A dashed line connects the dragged data-tip with the original data point. Simple, intuitive, and effective. At 300 lines, the draggableDataTips.m source code is compact and easy to follow, and you’re welcome to take a look and further customize this utility for your specific needs.

draggableDataTips utility in action

draggableDataTips utility in action


Technical implementation

The implementation of draggableDataTips relies on undocumented aspects of the data-cursor object exposed via the datacursormode function. I have already shown how these can be used to customize and control data-tips programmatically (rather than interactively). For draggableDataTips, we first get the cursor object’s meta-data classhandle (a schema.class object), then use it to find the meta-data for its hidden CurrentDataCursor property (a schema.prop object). There is also a more direct approach, using the findprop function.

Whichever alternative we choose, we finally use this object to set the property’s SetFunction meta-property. Quite straight-forward, I should say:

% Get the cursor-mode object
cursorObj = datacursormode(hFig);
 
% Alternative #1: the indirect route to the meta-property
ch = classhandle(cursorObj);
hPropIdx = strcmpi(get(ch.Properties,'Name'), 'CurrentDataCursor');
hProp = ch.Properties(hPropIdx);
 
% Alternative #2: the direct approach
hProp = findprop(cursorObj, 'CurrentDataCursor');
 
% Update the meta-property to use a custom function whenever new data-tips are created
hProp.SetFunction = @installNewMoveFcn;

This has the effect that all new data-tips that will be created from then on will call our custom installNewMoveFcn function when the data-tip object is created. This installNewMoveFcn function, in turn, simply replaces the data-tips standard default callback for mouse movement (which is used while dragging), to a new custom function textBoxUpdateFcn:

% Install a replacement callback function for datatip textbox mouse movement
function hDataTip = installNewMoveFcn(cursorObj, hDataTip)
    srcObjs = get(hDataTip.SelfListenerHandles,'SourceObject');
    for srcIdx = 1 : length(srcObjs)
        if strcmpi(srcObjs{srcIdx}.Name,'Orientation')
            hDataTip.SelfListenerHandles(srcIdx).Callback = @textBoxUpdateFcn;
            hDataTip.MarkerHandle.Marker = 'none';
            break;
        end
    end
end

The textBoxUpdateFcn function basically moves the datatip textbox to the new mouse location, without limiting its positions as Matlab’s standard default callback function did. A dashed connector line is then drawn to connect the center of the textbox with the data-point. It’s a bit long to include here, but interested readers are welcome to look at the code (lines #99 onward in draggableDataTips.m).

As can be seen from the screenshot above, standard and draggable data-tips can be used in the same plot. This is done by simply turning the draggability functionality on and off by draggableDataTips before creating a new data-tip (using either alt-click or programmatically):

draggableDataTips on    % or: draggableDataTips('on')  or: draggableDataTips(true)
draggableDataTips off   % or: draggableDataTips('off') or: draggableDataTips(false)

Notes:

  1. The actual code of draggableDataTips naturally contains more sanity checks, exception handling etc. I have only presented the core code in the snippets above, but you should always include such extra checks in any real-life program.
  2. There is a minor bug that causes the connector line to be on top of the box rather than beneath it, but aside from this all works ok. For some reason, uistack did not work. If anyone has a fix for this bug, please let me know.
  3. Did you notice that Java was not mentioned anywhere above? Mode managers, such as the data-cursor mode, use pure-Matlab functionality.

HG2

Unfortunately, when I tested draggableDataTips on HG2, Matlab’s upcoming new graphics engine, the utility failed. Data-cursors have undergone a significant reengineering in HG2 (about time!), causing multiple properties and methods to change names and functionality. But this could be overcome (see lines #43-53 in draggableDataTips.m).

However, I could not overcome the apparent fact that unlike HG1 (or more specifically, schema objects, that HG1 uses for its data-tips functionality), in HG2 (or rather, MCOS class objects) we cannot override an object’s meta-properties, specifically its SetMethod (which is the MCOS equivalent of schema.prop‘s SetFunction meta-property).

So for the moment, draggableDataTips does not work on HG2. I hope to find a solution for this by the time HG2 launches. If anyone finds a fix for the problem, please let me know. If I ever find or receive a fix, I will update this post with the relevant technical details.

For the moment there is no rush, since HG2 is still relatively far away in the distant future, and draggableDataTips works splendidly in the current HG1.

Have you used plot data-tips in some nifty way? If so, please share your experience in a comment below.

]]>
https://undocumentedmatlab.com/blog_old/draggable-plot-data-tips/feed 6
Setting class property typeshttps://undocumentedmatlab.com/blog_old/setting-class-property-types https://undocumentedmatlab.com/blog_old/setting-class-property-types#comments Thu, 18 Apr 2013 14:12:06 +0000 http://undocumentedmatlab.com/?p=3725 Related posts:
  1. Undocumented classdef attributes Matlab's object-oriented class definition enables usage of some useful undocumented attributes. ...
  2. Setting class property types – take 2 R2016a saw the addition of class property types. However, a better alternative has existed for many years. ...
  3. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
  4. UDD Properties UDD provides a very convenient way to add customizable properties to existing Matlab object handles...
]]>
When I wrote about the undocumented aspects of classdef properties half a year ago, I did not expect to learn of another major undocumented aspect in Matlab’s class-object system. last month I discovered the additional undocumented classdef Description and DetailedDescription attributes, and updated that article accordingly. But a few days ago I was pleasantly surprised to read Amro’s comment about an entirely new and undocumented aspect of Matlab MCOS classes.

Amro is a top contributor on StackOverflow, where he frequently answers questions before I even get any subscription notification about them… His answers are generally characterized by a deep technical understanding of Matlab, and I’ve learned quite a lot from him in the past few years. This time was no different.

In a nutshell, Amro found an undocumented way to specify a class object property’s type, in such a way that would prevent accidental setting to an incompatible value. For example, if we have a class with properties Width and Height, we probably want to restrict their possible values to numbers, to prevent setting a string or struct value.

In UDD classes, we can do this easily by setting the property’s DataType meta-property. An easy way to do this is by setting the second argument of the schema.prop function. A detailed explanation was provided here.

We can still do this today, since UDD classes are still supported, side-by-side with the newer MCOS classes. Unfortunately, MCOS does not provide a documented way of specifying the property type as in UDD.

One simple way to prevent unintentional MCOS property updates is to override the property’s set method. In fact, this was the solution of Jonas, another StackOverflow heavyweight:

classdef myClass
   properties
      myProperty = uint16(23); %# specify default value using correct type
   end
   methods
      function obj = set.myProperty(obj,val)
         if ~isa(val,'uint16')
            error('only uint16 values allowed')
         end
         %# assign the value
         obj.myProperty = val;
      end
   end
end

But it turns out that there’s a much cleaner and simpler solution, provided by Amro:

classdef Packet
    properties
        HeaderLength@uint16
        PayloadLength@uint16 = uint16(0);
        PacketType@char
    end
end

As Amro notes, if you try to set a property with the wrong type, you get an error:

>> p = Packet;
>> p.PacketType = 'tcp';  % ok
>> p.HeaderLength = 100;  % not ok - should be a uint16
While setting the 'HeaderLength' property of Packet:
Value must be 'uint16'.

This syntax apparently supports all primitive types (char, int32, double, struct, cell etc.), in addition to any user-defined ones (just use any class name).

Note that setting the type as above seems to override any set method that may have been specified for the property.

Amro came across this syntax in an internal class in R2013a (toolboxdir(‘matlab’)/graphics/+graphics/+internal/+figfile/@FigFile/FigFile.m), but it also worked in R2012a, and probably older versions as well…

I admit there’s not much original work here by me – it’s basically all by Amro (and Donn Shull for the UDD part). But I thought it’s important enough to bring to the attention of the community.

I love to discover such undocumented treasures by digging in Matlab’s function. If you ever discover other such buried treasures, please do let me know by email or a comment.


Addendum June 21, 2013: As Sebastian Hölz mentioned in his comment below, the general syntax appears to be:

properties
   propName@className dimensionType = initialValue
end

where className, dimensionType and initialValue are optional elements:

  • className can be any Matlab class/type, such as double, single, or UserClass
  • dimensionType can be one of the following terms: scalar, vector, or matrix
  • the property may also be initiated with an initialValue (otherwise it receives a default value, depending on the property class)

Addendum August 12, 2014: 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; additional aspects of class property tab-completion):

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

restricting Matlab property values


Addendum April 8, 2015: As reported by Martin A. here and also below, R2015a has apparently added the new (and hidden) Type property to the meta.property class and the InputTypes and OutputTypes properties to the the meta.method class. This enables specifying and querying the types of properties as well as method inputs/outputs. For example:

mc = ?matlab.graphics.axis.Axes;
mc.PropertyList(1).Name % Camera
mc.PropertyList(1).Type % matlab.graphics.axis.camera.Camera
mc.MethodList(49).Name % addlistener
mc.MethodList(49).InputNames % [sources, propertyname, eventname, callback]
mc.MethodList(49).InputTypes % [handle, asciiString, char vector, function_handle scalar]

Addendum November 11, 2015: Apparently, when using the @double syntax, Matlab only allows the property to receive real values. In order to enable complex values, we can also add the undocumented “complex” attribute. Note that we have to enter the dimensionality (scalar/vector/matrix) first, since “complex” is not accepted as a valid dimensionality value. For example:

% This is ok:
classdef foo
    properties
        bar@double scalar complex = 1 + 2i    end
end
 
% This causes an error:
classdef foo
    properties
        bar@double complex = 1 + 2i    end
end

Addendum April 28, 2016: Matlab R2016a now has a similar documented functionality. However, I feel that there are important drawbacks to the new functionality compared to the one presented here. Read the full discussion about this.

The new (documented) syntax automatically type-casts the data to the specified data type, were possible, something that the undocumented (@) syntax presented above does not. In other words, the undocumented syntax is stricter and expects the data to be exactly the specified data type, without attempting any type-casting. As reported by Martin Afanasjew, we can add the property attribute to the data type to replicate the new syntax’s automatic type-casting:

classdef foo
    properties
        prop1@char = 'A'  % will only accept char inputs, not numeric values
        prop2@char property = 65  % will automatically type-cast: 65 will be converted to 'A'    end
end
]]>
https://undocumentedmatlab.com/blog_old/setting-class-property-types/feed 37
Setting axes tick labels formathttps://undocumentedmatlab.com/blog_old/setting-axes-tick-labels-format https://undocumentedmatlab.com/blog_old/setting-axes-tick-labels-format#comments Wed, 18 Apr 2012 18:00:17 +0000 http://undocumentedmatlab.com/?p=2856 Related posts:
  1. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
  2. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  3. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
  4. Multi-column (grid) legend This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
]]>
Have you ever tried to customize the way in which tick labels appear in Matlab plot axes?

For example, setting the numerical precision of the labels, or adding some short descriptive text (for example, the units)? If you have, then I bet that you have encountered the following dilemma: Once we modify the tick labels (for discussion sake, let’s assume the Y axis, so this is done by updating the YTickLabel property), then the corresponding YTickLabelMode property changes from ‘auto’ to ‘manual’ and loses its relationship to the tick values (YTick). So, if we now zoom or pan the plot, our new labels remain unchanged although the tick values have changed, causing much panic and frustration… If we also set the tick values manually, this solves that problem but leaves us with another: now, when we zoom or pan, we no longer see any ticks or tick labels at all!

Original plot Manual labels, auto ticks Manual labels, manual ticks

Original plot (left)
Manual labels, auto ticks (center)
Manual labels, manual ticks (right)

Of course, we can always trap the zoom and pan callback functions to update the tick labels dynamically while keeping the tick values automatically. This will work for these cases, but we need to do it separately for zoom and pan. Also, if we modify the axes limits explicitly (via the corresponding YLim property) or indirectly (by modifying the displayed plot data), then the callbacks are not called and the labels are not updated.

The solution – using a property change listener

A better way to solve this problem is to simply trap changes to the displayed tick values, and whenever these occur to call our dedicated function to update the labels according to the new tick values. This can be done by using UDD, or more precisely the ability to trap update events on any property (in our case, YTick). Such a mechanism was already demonstrated here in 2010, as one way to achieve continuous slider feedback. The idea is to use the built-in handle.listener function with the PropertyPostSet event, as follows:

hhAxes = handle(hAxes);  % hAxes is the Matlab handle of our axes
hProp = findprop(hhAxes,'YTick');  % a schema.prop object
hListener = handle.listener(hhAxes, hProp, 'PropertyPostSet', @myCallbackFunction);
setappdata(hAxes, 'YTickListener', hListener);

Note that we have used setappdata to store the hListener handle in the axes. This ensures that the listener exists for exactly as long as the axes does. If we had not stored this listener handle somewhere, then Matlab would have immediately deleted the listener hook and our callback function would not have been called upon tick value updates. Forgetting to store listener handles is a common pitfall when using them. If you take a look at the addlistener function’s code, you will see that it also uses setappdata after creating the listener, for exactly this reason. Unfortunately, addlistsner cannot always be used, and I keep forgetting under which circumstances, so I generally use handle.listener directly as above: It’s simple enough to use that I find I never really need to use the simple addlistener wrapper, but you are welcome to try it yourself.

That’s all there is to it: Whenever YTick changes its value(s), our callback function (myCallbackFunction) will automatically be called. It is quite simple to set up. While we cannot use TeX in tick labels yet (this will change in the upcoming HG2), using sprintf formatting does enable quite a bit of flexibility in formatting the labels. For example, let’s say I want my tick labels to have the format ‘%.1fV’ (i.e., always one decimal, plus the Volts units):

function myCallbackFunction(hProp,eventData)    %#ok - hProp is unused
   hAxes = eventData.AffectedObject;
   tickValues = get(hAxes,'YTick');
   newLabels = arrayfun(@(value)(sprintf('%.1fV',value)), tickValues, 'UniformOutput',false);
   set(hAxes, 'YTickLabel', newLabels);
end  % myCallbackFunction

Manual labels, automatically updated Manual labels, automatically updated

Manual labels, automatically updated

Handling duplicate tick labels

Of course, ‘%.1fV’ may not be a good format when we zoom in to such a degree that the values differ by less than 0.1 – in this case all the labels will be the same. So let’s modify our callback function to add extra decimals until the labels become distinct:

function myCallbackFunction(hProp,eventData)    %#ok - hProp is unused
   hAxes = eventData.AffectedObject;
   tickValues = get(hAxes,'YTick');
 
   %newLabels = arrayfun(@(value)(sprintf('%.1fV',value)), tickValues, 'UniformOutput',false);
   digits = 0;
   labelsOverlap = true;
   while labelsOverlap
      % Add another decimal digit to the format until the labels become distinct
      digits = digits + 1;
      format = sprintf('%%.%dfV',digits);
      newLabels = arrayfun(@(value)(sprintf(format,value)), tickValues, 'UniformOutput',false);
      labelsOverlap = (length(newLabels) > length(unique(newLabels)));
 
      % prevent endless loop if the tick values themselves are non-unique
      if labelsOverlap && max(diff(tickValues))< 16*eps
         break;
      end
   end
 
   set(hAxes, 'YTickLabel', newLabels);
end  % myCallbackFunction

non-distinct labels distinct labels

Non-distinct labels                   distinct labels

ticklabelformat

Based on a file that I received from an anonymous reader a few years ago, I have prepared a utility called ticklabelformat that automates much of the set-up above. Feel free to download this utility and modify it for your needs – it’s quite simple to read and follow. The usage syntax is as follows:

ticklabelformat(gca,'y','%.6g V')  % sets y axis on current axes to display 6 significant digits
ticklabelformat(gca,'xy','%.2f')   % sets x & y axes on current axes to display 2 decimal digits
ticklabelformat(gca,'z',@myCbFcn)  % sets a function to update the Z tick labels on current axes
ticklabelformat(gca,'z',{@myCbFcn,extraData})  % sets an update function as above, with extra data

Addendum for HG2 (R2014b or newer releases)

As I’ve indicated in my comment response below, in HG2 (R2014b or newer) we need to listen to the HG object’s MarkedClean event, rather than to a property change event.

I’ve updated my ticklabelformat utility accordingly, so that it works with both HG1 (pre-R2014a) and HG2 (R2014b+). Use this utility as-is, and/or look within its source code for the implementation details.

]]>
https://undocumentedmatlab.com/blog_old/setting-axes-tick-labels-format/feed 18
getundoc – get undocumented object propertieshttps://undocumentedmatlab.com/blog_old/getundoc-get-undocumented-object-properties https://undocumentedmatlab.com/blog_old/getundoc-get-undocumented-object-properties#comments Wed, 21 Sep 2011 19:00:16 +0000 http://undocumentedmatlab.com/?p=2437 Related posts:
  1. Multi-column (grid) legend This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
  2. Controlling plot data-tips Data-tips are an extremely useful plotting tool that can easily be controlled programmatically....
  3. Draggable plot data-tips Matlab's standard plot data-tips can be customized to enable dragging, without being limitted to be adjacent to their data-point. ...
  4. Undocumented view transformation matrix Matlab's view function returns an undocumented output transformation matrix....
]]>
Last week, I presented the list of undocumented properties available in Matlab’s cursor mode and data-tip objects. Over the past two years, I had posted quite a few other articles on this website that used such undocumented properties. So today I will show exactly how such properties can be discovered.

Hidden properties are object properties that for some reason or other MathWorks has decided not to expose to the general public. They can still be used by Matlab users, just like any other regular property. But if you use the built-in get and set functions to list the object’s properties, you will not find the hidden properties listed. You need to know the hidden properties’ exact name in order to use them. Which is where today’s post can help, by showing you how to list these hidden properties. I wrote about this a couple of years ago, and today’s article will expand on that original post.

Hidden properties are by their very nature undocumented and not officially supported. For this reason, you should take extra care when relying on them in your code. They could change functionality or even be removed without prior notice in any future Matlab release. Still, some of these properties enable very important functionality, as I have often shown on this website.

HideUndocumented

There are two distinct manners by which undocumented properties can be seen in Matlab. The simplest was reported by Hans Olsson all the way back in 1997, in one of the very earliest posts on the CSSM newsgroup (there is no earlier public report, as far as I could tell). Since then, this method was mentioned in about a dozen other CSSM posts.

By setting the Matlab root (handle 0)’s HideUndocumented property to ‘off’ (default=’on’), subsequent calls to the built-in get and set functions list the hidden properties in addition to the regular ones. Note that HideUndocumented is itself a hidden property, which is why Hans’ post is so important – he presented us with the loose end that then enabled us to untangle the hidden properties in any other HG object.

Here is a simple example, showing HideUndocumented‘s effect on the root (handle 0) object handle itself (hidden properties are highlighted):

% Display only regular properties
>> get(0)
	CallbackObject = []
	CommandWindowSize = [86 51]
	CurrentFigure = []
	Diary = off
	DiaryFile = diary
	Echo = off
	FixedWidthFontName = Courier New
	Format = longG
	FormatSpacing = compact
	Language = he_il
	MonitorPositions = [ (2 by 4) double array]
	More = off
	PointerLocation = [1084 590]
	RecursionLimit = [500]
	ScreenDepth = [32]
	ScreenPixelsPerInch = [96]
	ScreenSize = [1 1 1440 900]
	ShowHiddenHandles = off
	Units = pixels
 
	BeingDeleted = off
	ButtonDownFcn = 
	Children = []
	Clipping = on
	CreateFcn = 
	DeleteFcn = 
	BusyAction = queue
	HandleVisibility = on
	HitTest = on
	Interruptible = on
	Parent = []
	Selected = off
	SelectionHighlight = on
	Tag = 
	Type = root
	UIContextMenu = []
	UserData = []
	Visible = on
 
% Display ALL properties (including hidden ones, which are highlighted below)
>> set(0,'HideUndocumented','off')
>> get(0)
	BlackAndWhite = off	CallbackObject = []
	CommandWindowSize = [86 51]
	CurrentFigure = []
	Diary = off
	DiaryFile = diary
	Echo = off
	ErrorMessage = [ (1 by 79) char array]	FixedWidthFontName = Courier New
	Format = longG
	FormatSpacing = compact
	HideUndocumented = off	Language = he_il
	MonitorPositions = [ (2 by 4) double array]
	More = off
	PointerLocation = [1022 82]
	PointerWindow = [0]	RecursionLimit = [500]
	ScreenDepth = [32]
	ScreenPixelsPerInch = [96]
	ScreenSize = [1 1 1440 900]
	ShowHiddenHandles = off
	Units = pixels
	AutomaticFileUpdates = on 
	BeingDeleted = off
	PixelBounds = [0 0 0 0]	ButtonDownFcn = 
	Children = []
	Clipping = on
	CreateFcn = 
	DeleteFcn = 
	BusyAction = queue
	HandleVisibility = on
	HelpTopicKey = 	HitTest = on
	Interruptible = on
	Parent = []
	Selected = off
	SelectionHighlight = on
	Serializable = on	Tag = 
	Type = root
	UIContextMenu = []
	UserData = []
	ApplicationData = [ (1 by 1) struct array]	Behavior = [ (1 by 1) struct array]	Visible = on
	XLimInclude = on	YLimInclude = on	ZLimInclude = on	CLimInclude = on	ALimInclude = on	IncludeRenderer = on

Property definitions

An entirely different mechanism uses the schema.prop definitions that were presented here by Donn Scull at the beginning of 2011. The idea is to get the object’s classhandle reference, from it to get the list of properties definitions, and for each property look at its Visible meta-property: hidden properties will simply have Visible=’off’, whereas regular properties will have ‘on’.

It turns out that there is not always a full correspondence between these two mechanism. I can’t remember specific examples, and perhaps these were fixed in the latest Matlab releases. It doesn’t matter, because merging the list of hidden properties reported by these two methods is always safe to do. Which is exactly what my getundoc utility does:

getundoc utility

The getundoc utility is based on another utility by the same name, posted by Duane Hanselman to the Matlab File Exchange in 2006 (Duane has elected to remove all his submissions from FEX a year or two ago, but that’s an entirely separate [and extremely heated] topic for a different discussion). Duane’s original getundoc utility relied only on the first (HideUndocumented) mechanism.

I have since expanded this utility to include support for the second mechanism, as well as support for the upcoming HG2 (see below). The updated getundoc is now available for download on the File Exchange. Since it’s a very short utility, I will digress from my norm and simply present its code, in its present form, here:

function c = getundoc(arg)
%GETUNDOC Get Undocumented Object Properties.
% GETUNDOC('OBJECT') or GETUNDOC(H) returns a structure of
% undocumented properties (names & values) for the object having handle
% H or indentified by the string 'OBJECT'.
%
% For example, GETUNDOC('axes') or GETUNDOC(gca) returns undocumented
% property names and values for the axes object.
 
% Extension of Duane Hanselman's original utility (which is no longer
% available on the File Exchange):
% D.C. Hanselman, University of Maine, Orono, ME 04469
% MasteringMatlab@yahoo.com
% Mastering MATLAB 7
% 2006-01-06
 
if nargin~=1
   error('One Input Required.')
end
if ischar(arg) % GETUNDOC('OBJECT')
   switch lower(arg)
   case 'root'                                                       % root
      h=0;
      hf=0;
   case 'figure'                                                   % figure
      h=figure('Visible','off');
      hf=h;
   otherwise                          % some other string name of an object
      hf=figure('Visible','off');
      object=str2func(arg);
      try
         h=object('Parent',hf,'Visible','off');
      catch
         error('Unknown Object Type String Provided.')         
      end
   end
elseif ishandle(arg) % GETUNDOC(H)
   h=arg;
   hf=0;
else
   error('Unknown Object Handle Provided.')
end
 
wstate=warning;
warning off                                      % supress warnings about obsolete properties
try set(0,'HideUndocumented','off'); catch; end  % Fails in HG2
undocfnames=fieldnames(get(h));                  % get props including undocumented
try set(0,'HideUndocumented','on'); catch; end   % Fails in HG2
docfnames=fieldnames(get(h));                    % get props excluding undocumented
 
% Yair 18/3/2010 - add a few more undocs:
try
    % This works in HG1
    props = get(classhandle(handle(h)),'properties');
    undocfnames = [undocfnames; get(props(strcmp(get(props,'Visible'),'off')),'Name')];
catch
    % Yair 18/9/2011: In HG2, the above fails, so use the following workaround:
    try
        prop = findprop(handle(h),undocfnames{1});
        props = prop.DefiningClass.PropertyList;
        undocfnames = [undocfnames; {props.Name}'];   % {props([props.Hidden]).Name}
    catch
        % ignore...
    end
end
 
c = setdiff(undocfnames,docfnames);      % extract undocumented
 
% Get the values in struct format, if relevant
if ~isempty(c)
  s = struct;
  for fieldIdx = 1 : length(c)
      try
          fieldName = c{fieldIdx};
          s.(fieldName) = get(h,fieldName);
      catch
          s.(fieldName) = '???';
      end
  end
  c = s;
end
% Yair end
 
if hf~=0                     % delete hidden figure holding selected object
   delete(hf)
end
warning(wstate)

Usage of this utility is extremely simple:

>> getundoc(0)
ans = 
             ALimInclude: 'on'
         ApplicationData: [1x1 struct]
    AutomaticFileUpdates: 'on'
                Behavior: [1x1 struct]
           BlackAndWhite: 'off'
             CLimInclude: 'on'
            ErrorMessage: [1x79 char]
            HelpTopicKey: ''
        HideUndocumented: 'on'
         IncludeRenderer: 'on'
             PixelBounds: [0 0 0 0]
           PointerWindow: 0
            Serializable: 'on'
             XLimInclude: 'on'
             YLimInclude: 'on'
             ZLimInclude: 'on'
 
>> getundoc(gcf)
ans = 
               ALimInclude: 'on'
    ActivePositionProperty: 'position'
           ApplicationData: [1x1 struct]
              BackingStore: 'on'
                  Behavior: [1x1 struct]
               CLimInclude: 'on'
                CurrentKey: ''
           CurrentModifier: {1x0 cell}
                 Dithermap: [64x3 double]
             DithermapMode: 'manual'
              DoubleBuffer: 'on'
            ExportTemplate: []
               FixedColors: [3x3 double]
                   HelpFcn: ''
              HelpTopicKey: ''
              HelpTopicMap: ''
           IncludeRenderer: 'on'
                 JavaFrame: [1x1 com.mathworks.hg.peer.HG1FigurePeer]
               MinColormap: 64
             OuterPosition: [436 374 568 502]
               PixelBounds: [0 0 560 420]
             PrintTemplate: []
              Serializable: 'on'
                    UseHG2: 'off'
                WaitStatus: []
               XLimInclude: 'on'
               YLimInclude: 'on'
               ZLimInclude: 'on'

Fixes for HG2

Unfortunately, in the new HG2 (which is still not in production, but we must be prepared, mustn’t we?), the original mechanism above (HideUndocumented) fails completely (there is no such property in the new matlab.ui.root object), whereas the second mechanism (UDD property defs) needs to be modified: Apparently, classhandle fails for HG2 object handles. Instead, we use the workaround of using findprop to get the property definition for any regular property, then get its parent (the requested class definition), and then down again to list all available properties. Note that in HG2, the relevant meta-property is Hidden which holds logical (true/false) values, as opposed to Visible and ‘off’/’on’ values for HG1 above.

All of these fixes are now incorporated in the getundoc code that is listed above.

When comparing the list of hidden properties in the existing HG1 and the new HG2, we see many interesting differences. And yes: the figure’s JavaFrame property was indeed removed in HG2. Bummer! (don’t worry – there are several workarounds up my sleeve…)

Do you have any favorite hidden property that you use in your code? If so, please tell us about it in a comment below.

p.s. – For all the numerous good people telling me about cprintf – Yes: I am aware that the latest R2011b release has broken cprintf‘s functionality. I plan to release a workaround sometime soon, when I have some spare time. I’ll keep everybody posted of course. Please be patient. (if you can’t wait, you can always hire me to fix it sooner; otherwise I need to give priority to my paying clients…)

]]>
https://undocumentedmatlab.com/blog_old/getundoc-get-undocumented-object-properties/feed 8
UDD Events and Listenershttps://undocumentedmatlab.com/blog_old/udd-events-and-listeners https://undocumentedmatlab.com/blog_old/udd-events-and-listeners#comments Wed, 16 Mar 2011 18:43:16 +0000 http://undocumentedmatlab.com/?p=2200 Related posts:
  1. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
  2. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
  3. UDD Properties UDD provides a very convenient way to add customizable properties to existing Matlab object handles...
  4. Multi-column (grid) legend This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
]]>
Donn Shull continues his exploration of the undocumented UDD mechanism, today discussing the important and extremely useful topic of UDD events

The UDD event model

The UDD event model is very similar to the MCOS event model. There is an excellent discussion of the MCOS event model in Matlab’s official documentation. Most of the MCOS information also applies to UDD if you make the following substitutions:

MCOS Event ModelUDD Event Model
notifysend
event.EventDatahandle.EventData
events blockschema.event
event.listenerhandle.listener
PreGet, PreSetPropertyPreGet, PropertPreSet
PostGet, PostSetPropertyPostGet, PropertyPostSet

Event handler functions

To begin the UDD event model discussion we will start at the end, with the event handler. The event handler function requires at least two input arguments: the source object which triggered the event, and an object of type handle.EventData or a subclass of handle.EventData.

To demonstrate how this works, let’s write a simple event handler function. This event handler will display the class of the source event and the class of the event data:

function displayEventInfo(source, eventData)
%DISPLAYEVENTINFO display the classes of source, data objects
%
%   DISPLAYEVENTINFO(SOURCE, EVENTDATA) returns the classes
%   of the source object and the event data object
%
%   INPUTS:
%       SOURCE    : the event source
%       EVENTDATA : the event data
  if ~isempty(source)
    fprintf(1, 'The source object class is: %s',class(source));
  end
  if ~isempty(eventData)
    fprintf(1, 'The event data class is: %s',class(eventData));
  end
end

Creating a listener

In the section on Creating a Simple UDD Class we used schema.event in our simple.object class definition file to create a simpleEvent event. We now create an instance of simple.object, then use handle.listener to wait (“listen”) for the simpleEvent event to occur and call the displayEventInfo event handler function:

a = simple.object('a', 1);
hListener = handle.listener(a,'simpleEvent',@displayEventInfo);
setappdata(a, 'listeners', hListener);

Important: The hListener handle must remain stored somewhere in Matlab memory, or the listener will not be used. For this reason, it is good practice to attach the listener handle to the listened object, using the setappdata function, as was done above. The listener will then be alive for exactly as long as its target object is alive.

Creating an EventData object

Next, create the handle.EventData object. The handle.EventData object constructor requires two arguments: an instance of the events source object, and the name of the event:

evtData = handle.EventData(a, 'simpleEvent')

Generating an event

The last step is actually triggering an event. This is done by issuing the send command for the specified object, event name and event data:

>> a.send('simpleEvent', evtData)
The source object class is: simple.object
The event data class is: handle.EventData

If there is other information that you wish to pass to the callback function you can create a subclass of the handle.EventData. Add properties to hold your additional information and use your subclass as the second argument of the send method.

Builtin UDD events

The builtin handle package has six event data classes which are subclasses of the base handle.EventData class. Each of these classes is paired with specific UDD events that Matlab generates. Actions that trigger these events include creating/destroying an object, adding/removing objects from a hierarchy, and getting/setting property values. The following table lists the event names and handle.*EventData data types returned for these events:

event data typeevent trigger
handle.ClassEventDataClassInstanceCreated
handle.EventDataObjectBeingDestroyed
handle.ChildEventDataObjectChildAdded, ObjectChildRemoved
handle.ParentEventDataObjectParentChanged
handle.PropertyEventDataPropertyPreGet, PropertyPostGet
handle.PropertySetEventDataPropertyPreSet, PropertyPostSet

As an example of some of these events let’s look at a question recently asked on the CSSM newsgroup. The basic idea is that we want to monitor an axis, automatically make any added lines to be green in color, and prevent patches from being added.

The solution is to monitor the ObjectChildAdded event for an axis. We will write an event handler which checks the handle.ChildEventData to see what type of child was added. In the case of lines we will set their color to green; patch objects will be deleted from the axis. Here is our event handler function:

function modifyAxesChildren(~, eventData)
%MODIFYAXESCHILDREN monitor and axis and modify added children
%
%   MODIFYAXESCHILDREN(SOURCE,EVENTDATA) is an event handler to
%   change newly-added lines to green and remove added patches
%
%   INPUTS:
%       EVENTDATA : handle.ChildEventData object
   switch eventData.Child.classhandle.Name
      case 'line'
         eventData.Child.set('Color', 'green');
         disp('Color changed to green.')
      case 'patch'
         eventData.Child.delete;
         disp('Patch removed.')
   end
end

Next create an axis, and a listener which is triggered when children are added:

% create a new axes and get its handle
a = hg.axes;
 
% create the listener
listen = handle.listener(a, 'ObjectChildAdded', @modifyAxesChildren);
 
% add a line
>> hg.line;
Color changed to green.
 
% try to add a patch
>> hg.patch;
Patch removed.

Removing a child with either the delete or the disconnect method generates an ObjectChildRemoved event. The delete method also generates the ObjectBeingDestroyed event. Changing a child’s parent with the up method generates an ObjectParentChanged event.

Reading an object’s properties with either dot notation or with the get method generates PropertyPreGet and PropertyPostGet events.

Changing the value of a property generates the PropertyPreSet and PropertyPostSet events. As we saw in the section on UDD properties, when the AbortSet access flag is ‘on’, property set events are only generated when a set operation actually changes the value of the property (as opposed to leaving it unchanged).

Note that the handle.listener syntax is slightly different for property events:

hProp = findprop(a, 'Value');
hListener = handle.listener(a,hProp,'PropertyPreGet',@displayEventInfo);

Java events

The final specialized event data object in the handle package is handle.JavaEventData. In Matlab, Java classes are not UDD classes, but each Java instance can have a UDD peer. The peer is created using the handle function. The Java peers are created in either UDD’s javahandle package or the javahandle_withcallbacks package. As their names imply, the latter enables listening to Java-triggered events using a Matlab callback.

To illustrate how this works we will create a Java Swing JFrame and listen for MouseClicked events:

% Create the Java Frame
javaFrame = javax.swing.JFrame;
javaFrame.setSize(200, 200);
javaFrame.show;
 
% Create a UDD peer for the new JFrame (two alternatives)
javaFramePeer = javaFrame.handle('CallbackProperties');  % alternative #1
javaFramePeer = handle(javaFrame, 'CallbackProperties');  % alternative #2
 
% Create the a listener for the Java MouseClicked event
listen = handle.listener(javaFramePeer, 'MouseClicked', @displayEventInfo);

a simple Java Swing JFrame

a simple Java Swing JFrame

When we click on the JFrame, our UDD peer triggers the callback:

The source object class is: javahandle_withcallbacks.javax.swing.JFrame
The event data class is: handle.JavaEventData

Since we created our peer in the javahandle_withcallbacks package, it is not necessary to create a listener using handle.listener. If we place our callback function handle in the MouseClickedCallback property it will be executed whenever the MouseClicked event is triggered. Such *Callback properties are automatically generated by Matlab when it creates the UDD peer (details).

clear listen
javaFramePeer.MouseClickedCallback = @displayEventInfo

This will work the same as before without the need to create and maintain a handle.listener object. If we had created our UDD peer in the javahandle package rather than javahandle_withcallbacks, we would not have the convenience of the MouseClickedCallback property, but we could still use the handle.listener mechanism to monitor events.

Creating callback properties for custom UDD classes

It is easy to add callback properties to user created UDD objects. The technique involves embedding a handle.listener object in the UDD object. To illustrate this, we add a SimpleEventCallback property to our simple.object, then use a SimpleEventListener property to hold our embedded handle.listener. Add the following to simple.object‘s schema.m definition file:

   % Property to hold our callback handle
   prop = schema.prop(simpleClass, 'SimpleEventCallback', 'MATLAB callback');
   prop.setFunction = @setValue;
 
   % hidden property to hold the listener for our callback
   prop = schema.prop(simpleClass, 'SimpleEventListener', 'handle');
   prop.Visible = 'off';
end
 
function propVal = setValue(self, value)
   %SETVALUE function to transfer function handle from callback property to listener
   self.SimpleEventListener.Callback = value;
   propVal = value;
end

Next we add the following to our simple.object constructor file:

% set the hidden listener property to a handle.listener
simpleObject.SimpleEventListener = handle.listener(simpleObject, 'simpleEvent', []);

Now if we set the SimpleObjectCallback property to a function handle, the handle is transferred to the embedded handle.listener Callback property. When a simpleEvent event is generated, our SimpleEventCallback function will be executed.

This series will conclude next week with a look at the special relationship between UDD and Java.

]]>
https://undocumentedmatlab.com/blog_old/udd-events-and-listeners/feed 32
UDD Propertieshttps://undocumentedmatlab.com/blog_old/udd-properties https://undocumentedmatlab.com/blog_old/udd-properties#comments Wed, 09 Mar 2011 18:00:17 +0000 http://undocumentedmatlab.com/?p=2156 Related posts:
  1. Multi-column (grid) legend This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
  2. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
  3. UDD Events and Listeners UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...
  4. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
]]>
Donn Shull continues his series of articles on Matlab’s undocumented UDD mechanism. Today, Donn explains how to use and customize UDD properties.

Properties meta-data

The UDD system is a class system. UDD packages, classes, events, and properties are all classes. In this section we will take a closer look at property classes.

As we have already shown, properties are added to a UDD class by adding schema.prop calls to the schema.m class definition file. What this really means is that each property of a UDD class is itself a class object (schema.prop) with its own properties and methods. The methods of schema.prop are loadobj() and saveobj(), which are used to serialize objects of this class (i.e., storing them in a file or sending them elsewhere).

It is schema.prop‘s properties (so-called meta-properties) that interest us most:

PropertyData TypeDescription
AccessFlagsMatlab structureControls which objects can access (read/modify) the property
CaseSensitiveon/offDetermines if the exact case is required to access the property (i.e., can we use ‘casesensitive’ instead of ‘CaseSensitive’)
DataTypestringThe underlying object’s property data type, set by the constructor
DescriptionstringThis can hold a description of the property (normally empty)
FactoryValueAs specified by DataTypeThis is used to provide an initial or default property value
GetFunctionFunction handleA function handle that is called whenever the property value is read
NamestringThe name of the property, also set by the constructor
SetFunctionFunction handleA function handle that is called whenever the properties value is changed
Visibleon/offDetermines if a property will be displayed by the get method for a UDD object

We can manipulate the values of these meta-properties to control various aspects of our property:

% Create instance of simple.object
>> a = simple.object('a');
 
% Find the Value property and list its meta-properties
% We can manipulate these meta-properties within limits
>> a.findprop('Value').get
            Name: 'Value'
     Description: ''
        DataType: 'single'
    FactoryValue: 7.3891
     AccessFlags: [1x1 struct]
         Visible: 'on'
     GetFunction: []
     SetFunction: []
 
>> prop.Visible = 'off';  % i.e. hidden property (see below)
>> prop.AccessFlags.PublicSet = 'off';   % i.e. read-only
>> prop.AccessFlags.PublicGet = 'on';
 
% Find the DataType meta-property of the Value property
% This meta-property and all other schema.prop base class properties are fixed
>> a.findprop('Value').findprop('DataType').get
            Name: 'DataType'
     Description: ''
        DataType: 'string'
    FactoryValue: ''
           ...

Adding properties to existing objects in run-time

schema.prop is a very useful tool – it can be used to add new properties to existing object handles, even after these objects have been created. For example, let’s add a new property (MyFavoriteBlog) to a standard figure handle:

>> p=schema.prop(handle(gcf), 'MyFavoriteBlog','string')
p =
	schema.prop
 
>> set(gcf,'MyFavoriteBlog','UndocumentedMatlab.com')
 
>> get(gcf,'MyFavoriteBlog')
ans =
UndocumentedMatlab.com

Using this simple mechanism, we can add meaningful typed user data to any handle object. A similar functionality can be achieved via the setappdata/getappdata functions. However, the property-based approach above is much “cleaner” and more powerful, since we have built-in type checks, property-change event listeners and other useful goodies.

Property data types

In the article on creating UDD objects we saw that the Name and DataType meta-properties are set by the schema.prop constructor. Name must be a valid Matlab variable name (see isvarname).

DataType is more interesting: There are two equivalent universal data types, 'mxArray', and 'MATLAB array'. With either of these two data types a property can be set to a any Matlab type. If we use a more specific data type (e.g., ‘string’, ‘double’ or ‘handle’), Matlab automatically ensures the type validity whenever the property value is modified. In our simple.object we use ‘double’ and ‘string’. You can experiment with these and see that the Value property will only allow scalar numeric values and the Name property will only allow character values:

>> set(obj, 'Value', 'abcd')
??? Parameter must be scalar.
 
>> obj.Value='abcd'
??? Parameter must be scalar.
 
>> obj.Name=123
??? Parameter must be a string.

The following table lists the basic UDD data types:

CategoryData Type
UniversalMATLAB array, mxArray
Numeric Scalarsbool, byte, short, int, long, float, double
Numeric VectorsNints, NReals
Specialized Numericcolor, point, real point, real point3, rect, real rect
Enumerationon/off
Stringschar, string, NStrings, string vector
Handlehandle, handle vector, MATLAB callback, GetFunction, SetFunction
JavaAny java class recognized by Matlab

User-defined data types

While this is an extensive list, there are some obvious types missing. For example there are no unsigned integer types. To handle this UDD provides two facilities for creating your own data types. One is the schema.EnumType. As you can see, Matlab has had a form of enumerations for a really long time not just the last few releases. The other facility is schema.UserType.

With these two classes you can create any specialized data type you need. One word of caution: once you have created a new UDD data type it exists for the duration of that Matlab session. There is no equivalent of the clear classes mechanism for removing a data type. In addition once a new data type has been defined it cannot be redefined until Matlab is restarted.

Let’s use a problem discussed in the CSSM forum as example. The essence of the problem is the need to flag a graphic line object as either editable or not. The proposed proposed is to add a new Editable property to an existing line handle. We will use schema.EnumType to create a new type named 'yes/no' so that the new property could accept only ‘yes’ and ‘no’ values:

function tline = taggedLine(varargin)
%TAGGEDLINE create a line with Editable property
%
%   TLINE = TAGGEDLINE(VARARGIN) create a new handle graphics line
%   and add 'Ediatable' property to line. Default property value is 'yes'.
%
%   INPUTS:
%       VARARGIN  : property value pairs to pass to line
%
%   OUTPUTS:
%       TLINE     : hg line object with Editable property
 
    % If undefined define yes/no datatype</font>
    if isempty(findtype('yes/no'))
        schema.EnumType('yes/no', {'yes', 'no'});
    end
    tline = line(varargin{:});
    schema.prop(tline, 'Editable', 'yes/no');
end

It is necessary to test for the existence of a type before defining it, since trying to redefine a type will generate an error.

We can use this new taggedLine() function to create new line objects with the additional Editable property. Instead of adding a new property to the line class we could have defined a new class as a subclass of line:

function schema()
%SCHEMA  hg package definition function
    schema.package('hg');
end

We create our class definition as a subclass of the handle graphics line class:

function schema()
%SCHEMA  hg.taggedline class definition function
    % package definition
    superPackage = findpackage('hg');
    pkg = findpackage('hg');
 
    % class definition
    c = schema.class(pkg, 'taggedline', findclass(superPackage, 'line'));
 
    if isempty(findtype('yes/no'))
        schema.EnumType('yes/no', {'yes', 'no'});
    end
 
    % add properties to class
    schema.prop(c, 'Editable', 'yes/no');
end

And our constructor is:

function self = taggedline
%OBJECT constructor for the simple.object class
    self = hg.taggedline;
end

Here we have placed the schema.EnumType definition in the class definition function. It is usually better to place type definition code in the package definition function, which is executed prior to any of the package classes and available in all classes. But in this particular case we are extending the built-in hg package and because hg is already defined internally, our package definition code is never actually executed.

The schema.UserType has the following constructor syntax:

schema.UserType('newTypeName', 'baseTypeName', typeCheckFunctionHandle)

For example, to create a user-defined type for unsigned eight-bit integers we might use the following code:

schema.UserType('uint8', 'short', @check_uint8)
 
function check_uint8(value)
%CHECK_UINT8 Check function for uint8 type definition
    if isempty(value) || (value < 0) || (value > 255)
        error('Value must be a scalar between 0 and 255');
    end
end

Hidden properties

Visible is an 'on/off' meta-property that controls whether or not a property is displayed when using the get function without specifying the property name. Using this mechanism we can easily detect hidden undocumented properties. For example:

>> for prop = get(classhandle(handle(gcf)),'Properties')'
       if strcmpi(prop.Visible,'off'), disp(prop.Name); end
   end
 
BackingStore
CurrentKey
CurrentModifier
Dithermap
DithermapMode
DoubleBuffer
FixedColors
HelpFcn
HelpTopicMap
MinColormap
JavaFrame
OuterPosition
ActivePositionProperty
PrintTemplate
ExportTemplate
WaitStatus
UseHG2
PixelBounds
HelpTopicKey
Serializable
ApplicationData
Behavior
XLimInclude
YLimInclude
ZLimInclude
CLimInclude
ALimInclude
IncludeRenderer

Note that hidden properties such as these are accessible via get/set just as any other property. It is simply that they are not displayed when you run get(gcf) or set(gcf) – we need to specifically refer to them by their name: get(gcf,’UseHG2′). Many other similar hidden properties are described in this website.

You may have noticed that the CaseSensitive meta-property did not show up above when we used get to show the meta-properties of our Value property. This is because CaseSensitive has its own Visible meta-property set to 'off' (i.e., hidden).

Additional meta-properties

FactoryValue is used to set an initial value for the property whenever a new simple.object instance is created.

GetFunction and SetFunction were described in last week’s article, Creating a UDD Hierarchy.

AccessFlags is a Matlab structure of 'on/off' fields that control what happens when the property is accessed:

FieldnameDescription
PublicSetControls setting the property from code external to the class
PublicGetControls reading the property value from code external to the class
PrivateSetControls setting the property from internal class methods
PrivateGetControls reading the property value from internal class methods
InitControls initializing the property using FactoryValue in the class definition file
Default??? (Undocumented, no examples exist)
ResetControls initializing the property using FactoryValue when executing the built-in reset function
SerializeControls whether this object can be serialized
CopyControls whether to pass the property’s current value to a copy
ListenerControls whether property access events are generated or not
AbortSetControls whether property set events are generated when a set operation will not change the property’s value

The CaseSensitive meta-property has AccessFlag.Init = 'off'. This means that properties added to a class definition file are always case insensitive.

Another interesting fact is that properties can be abbreviated as long as the abbreviation is unambiguous. Using our simple.object as an example:

>> a = simple.object('a');
>> a.n  % abbreviation of Name
ans =
a
 
>> a.v  % abbreviation of Value
ans =
    0.0000

It is considered poor programming practice to use either improperly cased, or abbreviated names when writing code. It is difficult to read, debug and maintain. But show me a Matlab programmer who has never abbreviated Position as ‘pos’…

Note: for completeness’ sake, read yesterday’s post on MCOS properties on Loren’s blog, written by Dave Foti, author of the original UDD code. Dave’s post describes the fully-documented MCOS mechanism, which is newer than the undocumented UDD mechanism described here. As mentioned earlier, whereas UDD existed (and still exists) in all Matlab 7 releases, MCOS is only available since R2008a. UDD and MCOS co-exist in Matlab since R2008a. MCOS has definite advantages over UDD, but cannot be used on pre-2008 Matlab releases. Different development and deployment requirements may dictate using either UDD or MCOS (or both). Another pre-R2008a alternative is to use Matlab’s obsolete yet documented class system.

In the next installment of this series we will take a look at UDD events and listeners.

]]>
https://undocumentedmatlab.com/blog_old/udd-properties/feed 8
Hierarchical Systems with UDDhttps://undocumentedmatlab.com/blog_old/hierarchical-systems-with-udd https://undocumentedmatlab.com/blog_old/hierarchical-systems-with-udd#comments Wed, 02 Mar 2011 18:00:25 +0000 http://undocumentedmatlab.com/?p=2146 Related posts:
  1. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
  2. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
  3. UDD Properties UDD provides a very convenient way to add customizable properties to existing Matlab object handles...
  4. UDD Events and Listeners UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...
]]>
Once again I welcome guest blogger Donn Shull, who continues his multi-part series about Matlab’s undocumented UDD objects.

We have looked at the tools for working with UDD classes, and created a simple UDD class. Today I shall show how to create a hierarchy of UDD objects.

Creating hierarchical structures with UDD objects

UDD is the foundation for both Handle Graphics (HG) and Simulink. Both are hierarchical systems. It stands to reason that UDD would offer support for hierarchical structures. It is straightforward to connect UDD objects together into searchable tree structures. All that is necessary is a collection of UDD objects that don’t have any methods or properties named 'connect', 'disconnect', 'up', 'down', 'left', 'right' or 'find'.

We illustrate the technique by creating a hierarchy of simple.objects as shown in the following diagram:

Sample UDD objects hierarchy

Sample UDD objects hierarchy

To begin we create five instances of the simple.object class from the previous article:

% Remember that simple.object accepts a name and a value
a = simple.object('a', 1);
b = simple.object('b', 1);
c = simple.object('c', 0);
d = simple.object('d', 1);
e = simple.object('e', 1);

To form the structure we use the connect method. We can use either dot notation or the Matlab syntax:

% Dot-notation examples:
a.connect(b, 'down');
b.connect(a, 'up');       % alternative to the above
 
% Matlab notation examples:
connect(a, b, 'down');
connect(b, a, 'up');      % alternative to the above

Next, connect node c into our hierarchy. There are several options here: We can use ‘down’ to connect a to c. Or we could use ‘up’ to connect c to a. Similarly, we can use either ‘left’ or ‘right’ to connect b and c. Here’s one of the many possible ways to create our entire hierarchy:

b.connect(a, 'up');
c.connect(b, 'left');
d.connect(b, 'up');
e.connect(d, 'left');

Inspecting UDD hierarchy structures

We now have our structure and each object knows its connection to other objects. For example, we can inspect b’s connections as follows:

>> b.up
ans =
  Name: a
 Value: 1.000000
 
>> b.right
ans =
  Name: c
 Value: 0.000000
 
>> b.down
ans =
  Name: d
 Value: 1.000000

We can search our structure by using an undocumented form of the built-in find command. When used with connected UDD structures, find can be used in the following form:

objectArray = find(startingNode, 'property', 'value', ...)

To search from the top of our hierarchy for objects of type simple.object we would use:

>> find(a, '-isa', 'simple.object')
ans =
        simple.object: 5-by-1    % a, b, c, d, e

Which returns all the objects in our structure, since all of them are simple.objects. If we repeat that command starting at b we would get:

>> find(b, '-isa', 'simple.object')
ans =
	simple.object: 3-by-1    % b, d, e

find searches the structure downward from the current node. Like many Matlab functions, find can be used with multiple property value pairs, so if we want to find simple.object objects in our structure with Value property =0, we would use the command:

>> find(a, '-isa', 'simple.object', 'Value', 0)
ans =
  Name: c
 Value: 0.000000

Visualizing a UDD hierarchy

Hierarchical structures are also known as tree structures. Matlab has an undocumented function for visualizing and working with trees namely uitree. Yair has described uitree in a series of articles. Rather than following the techniques in shown in Yair’s articles, we are going to use a different method that will allow us to introduce the following important techniques for working with UDD objects:

  • Subclassing, building your class on the foundation of a parent class
  • Overloading properties and methods of the superclass
  • Using meta-properties GetfFunction and SetFunction

Because the steps shown below will subclass an HG class, they will modify our simple.object class and probably make it unsuitable for general use. Yair has shown that uitree is ready made for displaying HG trees and we saw above that HG is a UDD system. We will use the technique from uitools.uibuttongroup to make our simple.object class a subclass of the HG class hg.uipanel. Modify the class definition file as follows:

% class definition
superPackage = findpackage('hg');
superClass = findclass(superPackage, 'uipanel');
simpleClass = schema.class(simplePackage, 'object',superClass);

Now we can either issue the clear classes command or restart Matlab and then recreate our structure. The first thing that you will notice is that when we create the first simple.object that a figure is also created. This is expected and is the reason that this technique is not useful in general. We will however use this figure to display our structure with the following commands:

t = uitree('v0', 'root', a);  drawnow;
t.expand(t.getRoot);  drawnow;
t.expand(t.getRoot.getFirstChild);

Simple structure presented in a Matlab uitree

Simple structure presented in a Matlab uitree

The label on each of our objects is ‘uipanel’ and this is probably not what we want. If we inspect our object or its hg.uipanel super-class (note: this would be a great time to use Yair’s uiinspect utility), we can see there is a Type property that has a value of ‘uipanel’. Unfortunately this property is read-only, so we cannot change it. We can however overload it by placing a schema.prop in our class definition named Type. This will allow us to overload or replace the parent’s Type property with our own definition:

p = schema.prop(simpleClass, 'Type', 'string');
p.FactoryValue = 'simple.object';

Once again, issue the clear classes command or restart Matlab, then recreate our structure. Our tree now has each node labeled with the ‘simple.object’ label:

Corrected node names for our UDD structure

Corrected node names for our UDD structure

This is a little more descriptive but what would really be nice is if we could label each node with the value of the Name property. As luck would have it, we can do just that. When we add a property to a UDD class we are adding an object of type schema.prop. So our properties have their own properties and methods (so-called meta-data). We are going to set the GetFunction property of our Type property. GetFunction holds a handle of the function to be called whenever the property is accessed:

p = schema.prop(simpleClass, 'Type', 'string');
p.GetFunction = @getType;

The prototype for the function that GetFunction references has three inputs and one output: The inputs are the handle of the object possessing the property, the value of that property, and the property object. The output is the value that will be supplied when the property is accessed. So our GetFunction can be written to supply the value of the Name property whenever the Type property value is being read:

function propVal = getType(self, value, prop)
   propVal = self.Name;
end

Alternately, as a single one-liner in the schema definition file:

p.GetFunction = @(self,value,prop) self.Name;

Similarly, there is a corresponding SetFunction that enables us to intercept changes to a property’s value and possibly disallow invalid values.

With these changes when we recreate our uitree we obtain:

Overloaded property GetFunction

Overloaded property GetFunction

A Java class for UDD trees

We will have more to say about the relationship between UDD and Java in a future article. For now we simply note that the com.mathworks.jmi.bean.UDDObjectTreeModel class in the JMI package provides some UDD tree navigation helper functions. Methods include getChild, getChildCount, getIndexOfChild and getPathToRoot. The UDDObjectTreeModel constructor requires one argument, an instance of your UDD tree root node:

% Create a UDD tree-model instance
>> uddTreeModel = com.mathworks.jmi.bean.UDDObjectTreeModel(a);
 
% Get index of child e and its parent b:
>> childIndex = uddTreeModel.getIndexOfChild(b, e)
childIndex =
     1
 
% Get the root's first child (#0):
>> child0 = uddTreeModel.getChild(a, 0)
child0 =
  Name: b
 Value: 1.000000
 
% Get the path from node e to the root:
>> path2root = uddTreeModel.getPathToRoot(e)
path2root =
com.mathworks.jmi.bean.UDDObject[]:
    [simple_objectBeanAdapter2]      % <= a
    [simple_objectBeanAdapter2]      % <= b
    [simple_objectBeanAdapter2]      % <= e
 
>> path2root(3)
ans =
  Name: e
 Value: 1.000000

We touched on a few of the things that you can do by modifying the properties of a schema.prop in this article. In the following article we will take a more detailed look at this essential class.

]]>
https://undocumentedmatlab.com/blog_old/hierarchical-systems-with-udd/feed 5
Creating a simple UDD classhttps://undocumentedmatlab.com/blog_old/creating-a-simple-udd-class https://undocumentedmatlab.com/blog_old/creating-a-simple-udd-class#comments Wed, 23 Feb 2011 17:29:05 +0000 http://undocumentedmatlab.com/?p=2130 Related posts:
  1. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
  2. UDD Properties UDD provides a very convenient way to add customizable properties to existing Matlab object handles...
  3. UDD Events and Listeners UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...
  4. Hierarchical Systems with UDD UDD objects can be grouped in structured hierarchies - this article explains how...
]]>
Once again I welcome guest blogger Donn Shull, who continues his multi-part series about Matlab’s undocumented UDD objects.

Creating a new UDD package

To illustrate the construction of UDD classes with Matlab m-code, let’s create a simple class belonging to a new simple package. Our class will have two properties: a Name property of type string, and a Value property of type double. This class will have two methods that will illustrate overloading the built-in disp function, and using a dialog method to present a GUI. Our class will also have one event, to demonstrate UDD event handling.

To create this simple UDD class we need two directories and five m-files (downloadable here): The parent directory needs to be a directory on the Matlab path. A subdirectory of the parent directory is named with the symbol @ followed by our UDD package name – this is the package directory. In this example, the subdirectory is called @simple.

Within the @simple directory, place a file named schema.m, which is the package definition file. This is a very simple file, that merely calls schema.package to create a new package called ‘simple’:

function schema()
%SCHEMA simple package definition function.
   schema.package('simple');
end

If you place additional m-files in the package directory they will be called package function files. Those files will have package scope and can be accessed with the notation packagename.functionname. We will not use package functions in this example, so we will only have the schema.m file shown above.

Creating a new UDD class

Next, create another subdirectory beneath @simple, named with an @ symbol followed by the UDD class name. In this example we will create the directory @object (i.e., /@simple/@object/). We place four m-files in this directory:

The first file is yet another schema.m file, which is the class-definition file:

function schema()
%SCHEMA  simple.object class definition function.
 
   % Get a handle to the 'simple' package
   simplePackage = findpackage('simple');
 
   % Create a base UDD object
   simpleClass = schema.class(simplePackage, 'object');
 
   % Define the class methods:
 
   % dialog.m method
   m = schema.method(simpleClass, 'dialog');
   s = m.Signature;
   s.varargin    = 'off';
   s.InputTypes  = {'handle'};
   s.OutputTypes = {};
 
   % disp.m method
   m = schema.method(simpleClass, 'disp');
   s = m.Signature;
   s.varargin    = 'off';
   s.InputTypes  = {'handle'};
   s.OutputTypes = {};
 
   % Define the class properties:
   schema.prop(simpleClass, 'Name', 'string');
   schema.prop(simpleClass, 'Value', 'double');
 
   % Define the class events:
   schema.event(simpleClass, 'simpleEvent');
end

Here, we used the built-in findpackage function to identify our base package (simple). Then we used schema.class to define a new class ‘object’ within that base package. We next defined two class methods, two properties and finally an event.

Defining class methods

It is not mandatory to define the method signatures as we have done in our class definition file. If you omit the method signature definitions, Matlab will automatically generate default signatures that will actually work in most applications. However, I believe that it is bad practice to omit the method signature definitions in a class definition file, and there are cases where your classes will not work as you have intended if you omit them.

Now, place a file named object.m in the @object directory. This file contains the class constructor method, which is executed whenever a new instance object of the simple.object class is created:

function simpleObject = object()
%OBJECT constructor for the simple.object class
%
%   SIMPLEOBJECT = OBJECT(NAME, VALUE) creates an instance of the
%   simple.object class with the Name property set to NAME and the
%   Value property set VALUE
%
%   SIMPLEOBJECT = OBJECT(NAME) creates an instance of the simple.object
%   class with the Name property set to NAME. The Value property will be
%   given the default value of 0.
%
%   SIMPLEOBJECT = OBJECT creates an instance of the simple.object class
%   and executes the simple.object dialog method to open a GUI for editing
%   the Name and Value properties.
%
%   INPUTS:
%       NAME          : string
%       VALUE         : double
%
%   OUTPUTS:
%       SIMPLEOBJECT  : simple.object instance
   simpleObject = simple.object;
   switch nargin
      case 0
         simpleObject.dialog;
      case 1
         simpleObject.Name = name;
      case 2
         simpleObject.Name = name;
         simpleObject.Value = value;
   end
end

The two other m-files in the @object directory will be our class methods – a single file for each method. In our case they are disp.m and dialog.m:

function disp(self)
%DISP overloaded object disp method
%
%   DISP(SELF) or SELF.DISP uses the MATLAB builtin DISP function
%   to display the Name and Value properties of the object.
%
%   INPUTS:
%       SELF  : simple.object instance
   builtin('disp', sprintf('  Name: %s\n Value: %f', self.Name, self.Value));
   %Alternative: fprintf('\n  Name: %s\n Value: %f', self.Name, self.Value));
end

And the dialog method (in dialog.m):

function dialog(self)
%DIALOG dialog method for simple.object for use by openvar
%
%   DIALOG(SELF) or SELF.DIALOG where self is the name of the simple.object
%   instance opens a gui to edit the Name and Value properties of self.
%
%   INPUTS:
%       SELF  : simple.object
   dlgValues = inputdlg({'Name:', 'Value:'}, 'simple.object', 1, {self.Name, mat2str(self.Value)});
   if ~isempty(dlgValues)
      self.Name = dlgValues{1};
      self.Value = eval(dlgValues{2});
   end
end

Testing our new class

Now let’s test our new class by creating an instance without using any input arguments

a = simple.object

This calls the object’s constructor method, which launches the input dialog GUI:

UDD simple class GUI

UDD simple class GUI

Note the default empty string value for the Name property, and the default zero value for the Value property. In one of the following articles I will show how to control property values. For now let’s assign ‘a’ to Name and 1 to Value using the GUI. Selecting OK updates our object and closes the GUI. Matlab then calls the object’s disp method to display our object in the command window:

a = 
  Name: a
 Value: 1.000000

We can reopen our object’s GUI using three methods: The most obvious is to invoke the dialog method using a.dialog or dialog(a). Alternately, double click on a in the workspace explorer window – Matlab will automatically call the built-in openvar function with the variable name and value as arguments. Which leads us to the third method – simply call openvar(‘a’, a) directly:

% Alternatives for programmatically displaying the GUI
a.dialog();  % or simply: a.dialog
dialog(a);
openvar('a',a);

Accessing UDD help

You may have noticed that in our constructor and method files we have included help text. This is good practice for all Matlab files in general, and UDD is no exception. We can access the UDD class help as follows:

> help simple.object
 OBJECT constructor for the simple.object class
 
    SIMPLEOBJECT = OBJECT(NAME, VALUE) creates an instance of the 
    simple.object class with the Name property set to NAME and the 
    Value property set VALUE
 
    SIMPLEOBJECT = OBJECT(NAME) creates an instance of the simple.object
    class with the Name property set to NAME. The Value property will be
    given the default value of 0.
 
    SIMPLEOBJECT = OBJECT creates an instance of the simple.object class 
    and executes the simple.object dialog method to open a GUI for editing
    the Name and Value properties.
 
    INPUTS:
        NAME          : string
        VALUE         : double
 
    OUTPUTS:
        SIMPLEOBJECT  : simple.object instance
 
>> help simple.object.disp
 DISP overloaded object disp method
 
    DISP(SELF) or SELF.DISP uses the MATLAB builtin DISP function
    to display the Name and Value properties of the object.
 
    INPUTS:
        SELF  : simple.object instance

One of the best ways to learn how Matlab works is to examine code written by the Matlab development team. openvar is a good example: By looking at it we can see that if a variable is a handle object and is opaque, then openvar will check to see if it has a dialog method. If so, it will use that to open the variable for editing. With this information we can guess that MCOS, UDD and even java objects can all launch their own dialog editors simply by having an appropriate dialog method.

An excellent source of UDD information is available in the Matlab toolbox folders. The base Matlab toolbox contains sixteen different UDD packages to explore. Yummy!

In the next article of this UDD series we will look at creating hierarchical structures using our simple.object and a unique UDD method.

]]>
https://undocumentedmatlab.com/blog_old/creating-a-simple-udd-class/feed 3
Introduction to UDDhttps://undocumentedmatlab.com/blog_old/introduction-to-udd https://undocumentedmatlab.com/blog_old/introduction-to-udd#comments Wed, 16 Feb 2011 18:00:09 +0000 http://undocumentedmatlab.com/?p=2036 Related posts:
  1. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
  2. UDD Events and Listeners UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...
  3. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
  4. Multi-column (grid) legend This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
]]>
I would like to welcome guest blogger Donn Shull. Donn will present a series of articles about UDD classes and objects, on which many undocumented Matlab features and functions are based.

Background on UDD

Matlab has used objects for a long time. In R8 (Matlab 5.0), their first user accessible class system was introduced. Andy Register wrote a detailed reference on using this system. Although that original system is obsolete, it is still available in R24 (R2010b).

UDD objects (also referred to as schema objects) were introduced with R12 (Matlab 6.0). UDD has been a foundation platform for a number of core Matlab technologies. MathWorks have consistently maintained that UDD is only meant for internal development and not for Matlab users. So, while UDD has no formal documentation, there are plenty of examples and tools to help us learn about it.

It is somewhat odd that despite Matlab’s new object-oriented system (MCOS)’s introduction 3 years ago, and the ongoing concurrent development of HG2 classes, the older-technology UDD is still being actively developed, as evidenced by the increasing number of UDD classes in recent releases. More background on the differences between these different sets of classes can be found here.

Why should we bother learning UDD?

There are some things to consider before deciding if you want to spend the time to learn about the UDD class system:

The case against studying UDD classes

  • There is no documentation from The MathWorks for these classes
  • You will not get any help from The MathWorks in applying these classes
  • The UDD system is now more than a decade old and may be phased out in future Matlab releases (perhaps in HG2?)

The case for studying UDD classes

  • UDD is currently the foundation of handle graphics, Java integration, COM, and Simulink
  • The m code versions of UDD may be considered a forerunner of the newer MCOS class system
  • To avoid memory leaks when using Callbacks in GUI applications you currently need to use UDD
  • UDD techniques facilitate Matlab interaction with Java GUIs
  • UDD directly supports the Matlab style method invocation as well as dot notation for methods without the need to write subsasgn and subsref routines

Tools for Learning about UDD

We start by describing some undocumented Matlab tools that will help us investigate and understand UDD classes.

  • findpackage – All UDD Classes are defined as members of a package. findpackage takes the package name as an input argument and returns a schema.package object which provides information about the package
  • findclass – This method of the schema.package object returns a schema.class object of the named class if the class exists in the package
  • classhandle – For a given UDD object classhandle returns a schema.class object with information about the class. classhandle and findclass are two ways of getting the same information about a UDD class. findclass works with a schema.package object and a class name and does not require an instance of the class. classhandle works with an instance of a class
  • findprop – This method of the schema.class object returns a schema.prop object which contains information about the named property
  • findevent – This method of the schema.class object returns a schema.prop object which contains information about the named event
  • handle – handle is a multifaceted and unique term for The MathWorks. There are both UDD and MCOS handle classes. There is a UDD handle package. In terms of the tools we need, handle is also an undocumented function which converts a numeric handle into a UDD handle object. Depending on your background you may want to think of handle as a cast operator which casts a numeric handle into a UDD object.
  • methods – This is used to display the methods of an object
  • methodsview – Provides a graphic display of an objects methods
  • uiinspect – Yair Altman’s object inspection tool, which can be used for COM, Java and Matlab classes (uiinspect will be described in a separate article in the near future).

Before we apply these tools we need to discuss the basic structure of UDD classes. Let’s compare them with the newer, well documented MCOS classes:

MCOS classes can be defined simply as a standalone class or scoped by placing the class in a package or a hierarchy of packages. With UDD, all classes must be defined in a package. UDD Packages are not hierarchical so a UDD package may not contain other packages. UDD classes can always be instantiated with syntax of packageName.className. By default MCOS classes are value classes. With MCOS you can subclass the handle class to create handle classes. UDD classes are handle classes by default, but it is possible to create UDD value classes.

Exploring some important built-in UDD Classes

The current versions of Matlab include a number of built-in UDD packages. We will use our new tools to see what we can learn about these packages. Let us begin by inspecting the two packages that form the basis of the UDD class system.

The schema package

The built-in schema package contains the classes for creating user written UDD classes. It also is used to provide meta information about UDD classes. Using findpackage we will obtain a schema.package object for the schema package and then use it obtain information about the classes it contains:

>> pkg = findpackage('schema')
pkg =
        schema.package
 
>> pkg.get
               Name: 'schema'
    DefaultDatabase: [1x1 handle.Database]
            Classes: [9x1 schema.class]
          Functions: [0x1 handle]
        JavaPackage: ''
         Documented: 'on'

Note that here we have used the dot-notation pkg.get – we could also have used the Matlab notation get(pkg) instead.

We have now learned that that there are nine classes in the schema package. The information about them in a schema package’s Classes property. To see the information about individual classes we inspect this property:

>> pkg.Classes(1).get
               Name: 'class'
            Package: [1x1 schema.package]
        Description: ''
        AccessFlags: {0x1 cell}
             Global: 'off'
             Handle: 'on'
       Superclasses: [0x1 handle]
    SuperiorClasses: {0x1 cell}
    InferiorClasses: {0x1 cell}
            Methods: [4x1 schema.method]
         Properties: [13x1 schema.prop]
             Events: []
     JavaInterfaces: {0x1 cell}

Not surprisingly, the first class in the schema.package is ‘class’ itself. Here we can see that schema.class has 4 methods and 13 properties. We can also see that the schema.class objects have a Name property. Let’s use that information to list all the classes in the schema package:

>> names = cell(numel(pkg.Classes), 1);
>> for index = 1:numel(names), names{index} = pkg.Classes(index).Name; end;
>> names
names =
    'class'
    'method'
    'signature'
    'package'
    'event'
    'prop'
    'type'
    'EnumType'
    'UserType'

These are the base classes for the UDD package schema. To illustrate a different way to get information, let’s use the findclass method of schema.package to get information about the schema.prop class:

>> p = findclass(pkg, 'prop')
p =
        schema.class
 
>> get(p)
               Name: 'prop'
            Package: [1x1 schema.package]
        Description: ''
        AccessFlags: {0x1 cell}
             Global: 'off'
             Handle: 'on'
       Superclasses: [0x1 handle]
    SuperiorClasses: {0x1 cell}
    InferiorClasses: {0x1 cell}
            Methods: [2x1 schema.method]
         Properties: [9x1 schema.prop]
             Events: []
     JavaInterfaces: {0x1 cell}

The handle package

The second basic UDD package is the handle package. Handle holds a special place in Matlab and has multiple meanings: Handle is a type of Matlab object that is passed by reference; handle is a function which converts a numeric handle to an object; handle is an abstract object in the new MCOS class system and handle is also a UDD package as well as the default type for UDD objects.

There is an interesting connection between UDD and MCOS that involves handle. In Matlab releases R12 through R2007b, the UDD handle package had up to 12 classes and did not have any package functions (package functions are functions which are scoped to a package; their calling syntax is [outputs] = packageName.functionName(inputs)).

Beginning with the formal introduction of MCOS in R2008a, the abstract MCOS class handle was introduced. The MCOS handle class has 12 methods. It also turns out that beginning with R2008a, the UDD handle package has 12 package functions which are the MCOS handle methods.

The 12 UDD classes in the handle package fall into two groups: The database and transaction classes work with the schema.package to provide a UDD stack mechanism; the listener and family of EventData classes work with schema.event to provide the UDD event mechanism:

>> pkg = findpackage('handle')
pkg =
        schema.package
 
>> pkg.get
               Name: 'handle'
    DefaultDatabase: [1x1 handle.Database]
            Classes: [12x1 schema.class]
          Functions: [12x1 schema.method]
        JavaPackage: ''
         Documented: 'on'
 
>> names = cell(numel(pkg.Classes), 1);
>> for index = 1:numel(names), names{index} = pkg.Classes(index).Name; end
>> names
names =
    'Operation'
    'transaction'
    'Database'
    'EventData'
    'ClassEventData'
    'ChildEventData'
    'ParentEventData'
    'PropertyEventData'
    'PropertySetEventData'
    'listener'
    'JavaEventData'
    'subreference__'

The hg package

Arguably the most important UDD package in Matlab is the handle graphics package hg. Among the built-in UDD packages, hg is unique in several respects. As Matlab has evolved from R12 through R2011a, the number of default classes in the hg package has nearly doubled going from 17 classes to 30 (UDD has a mechanism for automatically defining additional classes as needed during run-time).

The hg package contains a mixture of Global and non Global classes. These classes return a numeric handle, unless they have been created using package scope. The uitools m-file package provides a great example of extending built-in UDD classes with user written m-file UDD classes.

The UDD class for a Handle-Graphics object can be obtained either by explicitly creating it with the hg package, or using the handle function on the numeric handle obtained from normal hg object creation. Using figure as an example, you can either use figh = hg.figure or fig = figure followed by figh = handle(fig):

>> pkg = findpackage('hg')
pkg =
        schema.package
 
>> pkg.get
               Name: 'hg'
    DefaultDatabase: [1x1 handle.Database]
            Classes: [30x1 schema.class]
          Functions: [0x1 handle]
        JavaPackage: 'com.mathworks.hg'
         Documented: 'on'
 
>> for index = 1:numel(names), names{index} = pkg.Classes(index).Name; end
>> names
names =
    'GObject'
    'root'
    'LegendEntry'
    'Annotation'
    'figure'
    'uimenu'
    'uicontextmenu'
    'uicontrol'
    'uitable'
    'uicontainer'
    'hgjavacomponent'
    'uipanel'
    'uiflowcontainer'
    'uigridcontainer'
    'uitoolbar'
    'uipushtool'
    'uisplittool'
    'uitogglesplittool'
    'uitoggletool'
    'axes'
    'hggroup'
    'text'
    'line'
    'patch'
    'surface'
    'rectangle'
    'light'
    'image'
    'hgtransform'
    'uimcosadapter'

So far we have just explored the very basic concepts of UDD. You may well be wondering what the big fuss is about, since the information presented so far does not have any immediately-apparent benefits.

The following set of articles will describe more advanced topics in UDD usage and customizations, using the building blocks presented today. Hopefully you will quickly understand how using UDD can help achieve some very interesting stuff with Matlab.

]]>
https://undocumentedmatlab.com/blog_old/introduction-to-udd/feed 7
The javacomponent functionhttps://undocumentedmatlab.com/blog_old/javacomponent https://undocumentedmatlab.com/blog_old/javacomponent#comments Wed, 04 Aug 2010 18:00:59 +0000 http://undocumentedmatlab.com/?p=1793 Related posts:
  1. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  2. Matlab and the Event Dispatch Thread (EDT) The Java Swing Event Dispatch Thread (EDT) is very important for Matlab GUI timings. This article explains the potential pitfalls and their avoidance using undocumented Matlab functionality....
  3. GUI integrated browser control A fully-capable browser component is included in Matlab and can easily be incorporated in regular Matlab GUI applications. This article shows how....
  4. Continuous slider callback Matlab slider uicontrols do not enable a continuous-motion callback by default. This article explains how this can be achieved using undocumented features....
]]>
In this blog I have often showed how using Java components can significantly improve Matlab GUI. Here is a simple reminder:

sample Java components integrated in Matlab figure window (click for details)

sample Java components integrated in Matlab figure window (click for details)

Matlab is highly integrated with Java, and Java classes can seamlessly be accessed from Matlab. However, displaying Java GUI objects, as opposed to using computational (non-displayable) Java classes, requires using Matlab’s built-in javacomponent function. I have often used this function in past articles here, and today I would like to describe it in more detail.

javacomponent

javacomponent, available since R14 (Matlab 7.0), is yet another semi-documented built-in function. This means that the function is explained in a comment within the function (which can be seen via the edit(‘javacomponent’) command), but nonetheless does not have official help or doc pages. It is an unsupported function originally intended only for internal Matlab use (which of course doesn’t mean we can’t use it).

javacomponent accepts a component class name (a string) or a reference to a previously-created component object, an optional pixel position parameter (default=[20,20,60,20], just like uicontrol; may also contain the strings ‘North’, ‘South’, ‘East’ or ‘West’), and an optional parent container handle (defaults to the current figure). javacomponent then adds the requested component as a child of the requested parent container and wraps it in a Matlab Handle-Graphics (HG) container. javacomponent returns two handles: the Matlab HG container handle and a reference (handle) to the Java component. Here are some sample invocation formats:

>> [jButton, hButton] = javacomponent('javax.swing.JButton')
hButton =
	javahandle_withcallbacks.javax.swing.JButton
jButton =
          158.002197265625
 
>> javacomponent('javax.swing.JButton','North');
>> javacomponent(javax.swing.JButton('Click me!'),[50,40,80,30]);
>> javacomponent(javax.swing.JButton('Click me!'),'East',hFig);

Note the difference between Java object creation and javacomponent: A pre-created Java object only resides in JVM (Java Virtual Machine) memory, not onscreen, until javacomponent is called to display it. javacomponent only creates objects when a class name (string) parameter is passed to it, as a convenience service to programmers. In practice, it is better to separate these two actions: create the Java object separately, and then pass the object’s reference handle to javacomponent for display. This enables easier error-trapping if the Java object cannot be created or fails to initialize, before attempting to display the object:

% Create and initialize a JScrollBar object
try
   jScrollbar = javaObjectEDT('javax.swing.JScrollBar');
   jScrollbar.setOrientation(jScrollbar.HORIZONTAL);
catch
   error('Cannot create Java-based scroll-bar!');
end
% Display the object onscreen
try
   javacomponent(jScrollbar,'South');
catch
   error('Cannot display Java-base scroll-bar!');
end

Note that Java GUI object should always use the EDT (Event Dispatch Thread). The reasons for this were outlined in the recent Matlab-EDT article. For this reason, the JScrollBar is created using the built-in javaObjectEDT function, which exists since R2008a and became documented/supported in R2009a.

javacomponent accepts parent handles that are figures, toolbars, uipanels or uicontainers. Unfortunately, frames are not uicontainers and therefore cannot be used as javacomponent parents. Addendum Aug 6 2010: I made an incorrect statement in the original post here regarding uipanels, which has now been removed. I thank the reader who pointed this out to me.

Once the component has been created, even before it has been placed onscreen, it can be manipulated just like any other Java object. For example:

jButton.setText('Click again!');  % or: set(jButton,'text','…')

The component can also be manipulated to some extent via its HG container, which is of a special Matlab type (class) called hgjavacomponent. This includes getting/setting the component position, position units, visibility, resizing callback, tag, UserData etc:

set(hButton,'units','norm', 'position',[0.2,0.3,0.1,0.05]);
set(hButton,'visible','off'); %note: on/off, not true/false as in Java
set(hButton,'ResizeFcn',{@resizeCallbackFunc,param1,param2});

When adding Java components which are container classes (descendants of java.awt.Container), it is important to remember that only other Java components can be added to these containers. Matlab objects such as axes (for plots or images) and uicontrols cannot be added since they do not have a Container wrapper. Therefore, feel free to use these Java containers as long as their contained GUI is limited to Java components (JButton, JComboBox etc.). This limitation is very annoying – it would be very useful to be able to place Matlab axes or uicontrols within a JTabbedPane or JSplitPane. Instead, we need to rely on Matlab-based workarounds (uitab and uisplitpane) which are cumbersome compared to their Java counterparts.

javacomponent can be used to place not only Swing components but also Swing-extended components onscreen. Matlab itself almost never uses Swing components as-is, instead preferring to use MathWorks-derived extensions of these components, generally in the com.mathworks.mwswing or com.mathworks.widgets packages. These packages and their classes are all in the static Java classpath and are therefore automatically available for use by Matlab programmers.

Just like Matlab components, javacomponent can also display third-party or your own Swing-derived components. There are quite a few online sources for Swing components that can easily be incorporated in your Matlab application. Simply download the relevant class files, add them to your static (via classpath.txt) or dynamic (via javaaddpath) Java classpath, use javacomponent to display them, then use their reference handle to manipulate their appearance and behavior.

javacomponent, useful as it is, has several limitations. In its string variant (classname) it requires a fully-qualified classname that is not inferred automatically. It also has a different parameters format than uicontrol, which may confuse users. javacomponent also cannot display java.awt.Window components. Finally, it returns two handles – one is a handle() reference of the Java object; the second an HG handle (a double numeric value) of the automatically-created HG container – users are often confused as to which property should be set on which of these handles.

javacomponent-based utility functions

To overcome these limitations, I created UIComponent – a utility that merges uicontrol and javacomponent, available for download on the File Exchange. It accepts all uicontrol parameters and styles, as well as any other displayable Java (Swing/AWT) class. uicontrol‘s calling syntax was preserved for full backwards compatibility. uicomponent uses the built-in uicontrol whenever possible (for standard Matlab styles), and javacomponent for all other Java classes.

uicomponent returns the same two handles that javacomponent returns (namely, a Java reference handle and a numeric HG handle), modified to include each other’s properties and handles (yet another undocumented trick that merits a dedicated article). Here are some examples (more can be found in uicomponent‘s help comment):

uicomponent('style','edit', 'String','hello');  % a regular uicontrol
uicomponent(hFig, 'style','edit', 'String','hello'); % specify parent
uicomponent('style','jspinner','value',7);
uicomponent('style','javax.swing.jslider','tag','myObj'); 
uicomponent('style','JComboBox',{1,pi,'text'},'editable',true);

Another File Exchange submission which aims to tackle some of javacomponent‘s limitations is Malcolm Lidierth’s JCONTROL. jcontrol uses Matlab’s new object-oriented class approach and has the benefit of returning just a single handle object, which aggregates the handles for both HG container and the contained Java object.

]]>
https://undocumentedmatlab.com/blog_old/javacomponent/feed 68
New information on HG2https://undocumentedmatlab.com/blog_old/new-information-on-hg2 https://undocumentedmatlab.com/blog_old/new-information-on-hg2#comments Mon, 10 May 2010 22:09:39 +0000 http://undocumentedmatlab.com/?p=1473 Related posts:
  1. Adding dynamic properties to graphic handles It is easy and very useful to attach dynamic properties to Matlab graphics objects in run-time. ...
  2. Matlab’s HG2 mechanism HG2 is presumably the next generation of Matlab graphics. This article tries to explore its features....
  3. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
  4. Draggable plot data-tips Matlab's standard plot data-tips can be customized to enable dragging, without being limitted to be adjacent to their data-point. ...
]]>
Last week I posted a couple of articles on the undocumented feature function and Matlab’s apparent move towards a class-based Handle-Graphics system called HG2.

Apparently I caused a bit of a stir…

This is normally a weekly blog. But I wanted to share some additional relevant information as well as some interesting tips I received in private communications. Please note that much of the following is speculation or guesswork and may be incorrect or even entirely wacky. Please read the following with more than the usual grain of skepticism…

UDD

A bit of historical background: Matlab’s existing Handle Graphics system is based on UDD (Universal Data Dictionary) objects. Prior to Matlab Release 12 (a.k.a. 6.0) back in 2000, Matlab was written exclusively in C and HG and Simulink used differing approaches to objects in the MathWorks codebase. UDD was then added for R12 using C++ code with C wrappers for internal use by the MathWorks developers. UDD enabled a new unified approach for HG and Simulink (recall the major overhaul to the Matlab interface in that release, which also modified the GUI to be Java-based). While the HG handles remained numeric, behind the scenes they relied on the new UDD system, which remained undocumented.

Matlab users who wished to leverage UDD classes could (and still can) access it via some undocumented interface functions: handle, handle.listener, handle.event, classhandle, schema.prop, schema.class, schema.event (and other schema.* functions), findprop, findclass, findevent and several others. Some of these functions were mentioned in past articles on this blog, and others will perhaps be explained in future articles. You can find numerous mentions and usage examples of UDD in the Matlab codebase that is part of each Matlab installation.

In /toolbox/matlab/helptools/+helpUtils/@HelpProcess/getHelpText.m we can see a related feature (feature(‘SearchUUDClassesForHelp’, flag)) which can apparently be used to allow access to the h1 line and help text for UDD methods. Unfortunately, I have not found any relevant UDD candidates for this. I would be very happy to hear if you know of any objects/methods which have a UDD help section.

MCOS

Perhaps Matlab’s Class Object System (MCOS), first introduced in R14 (a.k.a. 7.0, released in 2004) grew out of the UDD beginnings, and perhaps it was developed separately. The fact is that it shared several terms and concepts (“schema”, properties meta-data, events) with UDD, although no direct interaction between UDD and MCOS exists, AFAIK.

As an interesting side-note, MCOS was introduced as an opt-in beta-testing feature in R14SP2 (7.0.4, released in 2005). This beta feature cannot be found in the official online version of the R14SP2 release notes, but can be found in the hardcover version pages 10-11:

New syntax and features for creating and working with classes in MATLAB. For R14SP2, these features are at a Beta level. If you are interested in being a Beta tester for these features, see “Beta Test the MATLAB Class System” on page 11.

Beta Test the MATLAB Class System. MATLAB 7.0.4 includes a Beta version of new syntax and features for working with classes in MATLAB, which simplify and expand object-oriented programming capabilities in MATLAB. Participation in this Beta program is open only to customers who are current
on their maintenance for MATLAB. Trial passcodes will not be made available for this Beta test. If you are interested in being a Beta tester for these features, register on the MathWorks Web site, at http://www.mathworks.com/products/beta/r14sp2/signup_newfeatures.html.

(needless to say, this webpage was since removed…)

The MCOS syntax has changed between releases and was not very stable, until it was formally introduced in R2008a (a.k.a. 7.6, released in 2008). You can look at /toolbox/matlab/iofun/@memmapfile/memmapfile.m to see the MCOS evolution from R14 onward.

HG2

The new HG2 appears to be a merger of MCOS and UDD, using MCOS infrastructure for UDD classes and properties, finally throwing away the old numeric handles and C wrappers for the more powerful object-oriented approach.

For the transition period between HG and HG2, there seems to be a dedicated feature: feature(‘HGtoCOS’, handle) apparently converts a UDD (“HG”) handle into an HG2 (“COS”) handle. You can also use feature(‘HGtoCOS’, 0) to obtain an MCOS object of the desktop (=handle 0). Here is a sample result on a Matlab 2009 release:

>> hFig = figure
hFig =
     1
 
>> fmcos = feature('HGtoCOS', hFig)
fmcos =
 
  gbtmcos.figure handle
 
  Package: gbtmcos
 
  Properties:
                 Alphamap: [1x64 double]
             BeingDeleted: 'off'
               BusyAction: 'queue'
            ButtonDownFcn: []
                 Children: [0x1 double]
                 Clipping: 'on'
          CloseRequestFcn: 'closereq'
                    Color: [0.8000 0.8000 0.8000]
                 Colormap: [64x3 double]
                      ...  (all the regular figure properties)

Note that in that here, the new object package was called GBTMCOS – perhaps meaning a GBT version of the MCOS system. This corresponds to the feature(‘useGBT2’) that I reported in the features article. I have absolutely no idea what GBT stands for, whether it is a synonym for HG2 or not exactly, and what the differences are between GBT1.5 and GBT2. In any case, in R2010a, the same feature(‘HGtoCOS’, handle) code returns a ui.figure object: “GBTMCOS” was simply renamed “UI”.

I do not know how to convert an HG2 back to a UDD/HG handle. None of the following appears to work:

>> fmcos.getdoubleimpl
ans =
    -1
 
>> fmcos.double
ans =
on
 
>> double(fmcos)
ans =
    -1
 
>> handle(fmcos)
??? Error using ==> handle
Cannot convert to handle.

I would love to hear any additional information on these subjects, either anonymously or on record. You can use either a direct mail (see link at the top-right of this page) or the comments section.

]]>
https://undocumentedmatlab.com/blog_old/new-information-on-hg2/feed 1
Continuous slider callbackhttps://undocumentedmatlab.com/blog_old/continuous-slider-callback https://undocumentedmatlab.com/blog_old/continuous-slider-callback#comments Mon, 08 Feb 2010 09:13:39 +0000 http://undocumentedmatlab.com/?p=1052 Related posts:
  1. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  2. Setting listbox mouse actions Matlab listbox uicontrol can be modified to detect mouse events for right-click context menus, dynamic tooltips etc....
  3. Editbox data input validation Undocumented features of Matlab editbox uicontrols enable immediate user-input data validation...
  4. Setting line position in an edit-box uicontrol Matlab uicontrols have many useful features that are only available via Java. Here's how to access them....
]]>
Every few months, a CSSM forum reader asks how to set up a continuously-invoked slider callback: Matlab’s slider uicontrol invokes the user callback only when the mouse button is released, and not continuously while the slider’s thumb is dragged. This functionality was again referred-to yesterday, and I decided it merits a dedicated post.

There are three distinct simple ways to achieve continuous callbacks:

Using Java callbacks

As explained in an earlier article, Matlab uicontrols are basically Java Swing objects that possess a large number of useful callbacks. Matlab sliders’ underlying Java objects, which are really not JSliders but JScrollBars, have an AdjustmentValueChangedCallback property that is useful for our purposes and is accessible using the FindJObj utility. Simply download FindJObj from the File Exchange, and then:

hSlider = uicontrol('style','slider', ...);
jScrollBar = findjobj(hSlider);
jScrollBar.AdjustmentValueChangedCallback = @myCbFcn;
% or: set(jScrollBar,'AdjustmentValueChangedCallback',@myCbFcn)

Where myCbFcn is the Matlab callback function that will be invoked continuously when the arrow buttons are depressed or the slider’s thumb is dragged.

Using an event listener

An alternative to the Java route is to use Matlab’s undocumented handle.listener function to listen to the slider’s Action event, as follows:

hListener = handle.listener(hSlider,'ActionEvent',@myCbFcn);
setappdata(hSlider,'sliderListener',hListener);  % this is important - read below

This alternative is used by Matlab’s own imscrollpanel function:

if isJavaFigure
   % Must use these ActionEvents to get continuous events fired as slider
   % thumb is dragged. Regular callbacks on sliders give only one event
   % when the thumb is released.
   hSliderHorListener = handle.listener(hSliderHor,...
      'ActionEvent',@scrollHorizontal);
   hSliderVerListener = handle.listener(hSliderVer,...
      'ActionEvent',@scrollVertical);
   setappdata(hScrollpanel,'sliderListeners',...
      [hSliderHorListener hSliderVerListener]);
else
   % Unfortunately, the event route is only available with Java Figures,
   % so platforms without Java Figure support get discrete events only
   % when the mouse is released from dragging the slider thumb.
   set(hSliderHor,'callback',@scrollHorizontal)
   set(hSliderVer,'callback',@scrollVertical)
end

In this case, hScrollpanel is merely a handle to a panel in Matlab’s imscrollpanel code. You can use any Matlab control to store the listener handle, including hSlider itself, which would be simplest. It doesn’t matter where or how exactly you store hListener, since you will not use it directly in your program. The important thing is just to store it *anywhere*, so that it remains in persistent (heap) memory. As long as the reference handle is “alive”, the listener will keep working. This is explained here.

Addedndum 2014-08-20: In R2014a the event name has changed from ActionEvent to ContinuousValueChange. Also, handle.listener will not work in the upcoming HG2. Therefore, it would be best to use the following code snippet instead:

try    % R2013b and older
   addlistener(hSlider,'ActionEvent',@myCallbackFcn);
catch  % R2014a and newer
   addlistener(hSlider,'ContinuousValueChange',@myCallbackFcn);
end

Using a property listener

The handle.listener function can also be used to listen to property value changes. In our case, set a post-set listener, that gets triggered immediately following Value property updates, as follows:

hhSlider = handle(hSlider);
hProp = findprop(hhSlider,'Value');
try    % R2014b and newer
   % hProp is a matlab.graphics.internal.GraphicsMetaProperty object
   addlistener(hSlider,hProp,'PostSet',@myCbFcn);
catch  % R2014a and older
   % hProp is a schema.prop object
   hListener = handle.listener(hhSlider,hProp,'PropertyPostSet',@myCbFcn);
   setappdata(hSlider,'sliderListener',hListener);  % this is important - read above
end

In addition to ‘PostSet’, we could also listen on ‘PreSet’, which is triggered immediately before the property is modified. There are also corresponding ‘*Get’ options.

Do you know of any other way to achieve continuous callbacks? If so, I would be delighted to hear in the comments section below.

]]>
https://undocumentedmatlab.com/blog_old/continuous-slider-callback/feed 56
Context-Sensitive Helphttps://undocumentedmatlab.com/blog_old/context-sensitive-help https://undocumentedmatlab.com/blog_old/context-sensitive-help#comments Wed, 05 Aug 2009 18:20:26 +0000 http://undocumentedmatlab.com/?p=491 Related posts:
  1. Tab panels – uitab and relatives This article describes several undocumented Matlab functions that support tab-panels...
  2. Customizing print setup Matlab figures print-setup can be customized to automatically prepare the figure for printing in a specific configuration...
  3. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  4. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
]]>
A recent CSSM thread about implementing a system-wide GUI help system got me working on a post to present Matlab’s built-in hidden/unsupported mechanism for context-sensitive help. There are many different ways in which such a system can be implemented (read that thread for some ideas), so Matlab users are by no means limited to Matlab’s built-in implementation. However, the built-in system certainly merits consideration for its simplicity and usefulness.

We start with Matlab’s cshelp function (%matlabroot%\toolbox\matlab\uitools\cshelp.m). cshelp is semi-documented, meaning that it has a help section but no doc, online help or official support. This useful function was grandfathered (made obsolete) in Matlab 7.4 (R2007a) for an unknown reason and to my knowledge without any replacement. cshelp is entirely based on m-code (no hidden internal or Java code) and is surprisingly compact and readable.

cshelp basically attaches two new properties (CSHelpMode and CSHelpData) to the specified figure (this is done using the schema.prop mechanism which will be described in a separate post), temporarily disables all active uicontrols, modifies the figure’s WindowButtonDownFcn callback and sets the mouse cursor (using setptr – another semi-documented function) to an arrow with a question mark.

Clicking any object in the figure’s main area (beneath the toolbar), causes the modified WindowButtonDownFcn callback to run whatever is stored in the figure’s HelpFcn property (string, @function_handle or {@function_handle, params, …} format). Here is a simple example taken from CSSM (thanks Jérôme):

Hfcn = 'str=get(gco,''type''); title([''Type :'' str])';
set(gcf,'HelpFcn',Hfcn);
th = 0:0.314:2*pi;
plot(th,sin(th),'r-','linewidth',4);
uicontrol('units','normalized', 'position',[.45 .02 .1 .05]);
cshelp(gcf);
set(gcf,'CSHelpMode','on');

Simple context-sensitive help system

Simple context-sensitive help system

In order to exit CSHelp mode, the figure’s CSHelpMode property must be set to ‘off’. However, remember that all the figure’s uicontrols are disabled in CSHelp mode. Therefore, the user may use one or more of the following methods (other tactics are also possible, but the ones below seem intuitive):

  • Set the figure’s KeyPressFcn callback property to catch events (e.g., <ESC> key presses) and reset the CSHelpMode property from within the callback
  • Reset the CSHelpMode property at the end of the HelpFcn callback
  • Add a CS Help entry/exit option to the figure’s Help main menu
  • Add a CS Help entry/exit button to the figure toolbar

The following code sample implements all of these suggested tactics (the code to synchronize the states of the menu item and toolbar button is not presented):

% Set the <ESC> key press to exit CSHelp mode
keyFcn = ['if strcmp(get(gcbf,''CurrentKey''),''escape''), ' ...
             'set(gcbf,''CSHelpMode'',''off''); ' ...
          'end'];
set(gcf,'keyPressFcn',keyFcn);
 
% Exit CSHelp mode at the end of the CSHelp callback
helpFcn = 'title([''Type :'' get(gco,''type'')]); set(gcbf,''CSHelpMode'',''off'');';
set(gcf,'HelpFcn',helpFcn);
 
% Add a CSHelp button to the figure toolbar
% Note: retrieve the button icon from the CSHelp cursor icon
hToolbar = findall(allchild(gcf),'flat','type','uitoolbar');
oldPtr = getptr(gcf);
ptrData = setptr('help');
set(gcf, oldPtr{:});
icon(:,:,1) = ptrData{4}/2;  % Convert into RGB TrueColor icon
icon(:,:,2) = ptrData{4}/2;
icon(:,:,3) = ptrData{4}/2;
cbFcn = 'set(gcbf,''CSHelpMode'',get(gcbo,''state''))';
csName = 'Context-sensitive help';
uitoggletool(hToolbar,'CData',icon, 'ClickedCallback',cbFcn, 'TooltipString',csName);
 
% Add a CSHelp menu option to the Help main menu
% Note: unlike other main menus, the Help menu tag is empty, so
% ^^^^  findall(gcf,'tag','figMenuHelp') is empty... Therefore,
%       we find this menu by accessing the Help/About menu item
helpAbout = findall(gcf,'tag','figMenuHelpAbout');
helpMenu = get(helpAbout,'parent');
cbFcn = ['if strcmp(get(gcbo,''Checked''),''on''), ' ...
             'set(gcbo,''Checked'',''off''); ' ...
         'else, ' ...
             'set(gcbo,''Checked'',''on''); ' ...
         'end; ' ...
         'set(gcbf,''CSHelpMode'',get(gcbo,''checked''))'];
uimenu(helpMenu,'Label',csName,'Callback',cbFcn,'Separator','on');

Figure with context-sensitive help action in the main toolbar & menu

Figure with context-sensitive help action in the main toolbar & menu

cshelp has an additional optional argument, accepting another figure handle. This handle, if specified and valid, indicates a parent figure whose CSHelpMode, HelpFcn and HelpTopicMap properties should be shared with this figure (this is done using the handle.listener mechanism which will be described in a separate post). This option is useful when creating a multi-window GUI-wide context-sensitive help system. The user may then activate context-sensitive help in figure A and select the requested context object in figure B.

cshelp would normally be coupled with Matlab’s help system for non-trivial GUI implementations. The undocumented and hidden properties HelpTopicKey (of all handles) and HelpTopicMap (of figures), enable easy tie-in to the CSHelp system. A simplified sample is presented below:

Hfcn=['helpview(get(gco,''HelpTopicKey''),''CSHelpWindow'');'...
      'set(gcbf,''CSHelpMode'',''off'');' ];
set(gcf,'HelpFcn',Hfcn);
th = 0:0.314:2*pi;
hLine = plot(th,sin(th),'r-','linewidth',4);
set(hLine,'HelpTopicKey','MyCSHelpFile.html#Line');
set(gca,  'HelpTopicKey','MyCSHelpFile.html#Axes');

cshelp is by no way limited to presenting Matlab documentation: Refer to helpview‘s help section for an in-depth description of help maps and help topics. In a nutshell, helpview accepts any HTML webpage filepath (or webpage internal (#) reference), followed by optional parameter ‘CSHelpWindow’ (that indicates that the specified help page should be displayed in a stand-alone popup window rather than in the desktop’s standard Help tab), and optional extra parameters specifying the popup window’s figure handle and position. The webpage filepath parameter may be replaced by two string parameters, HelpTopicMap filepath and HelpTopicKey. Note that helpview itself is another semi-documented function.

]]>
https://undocumentedmatlab.com/blog_old/context-sensitive-help/feed 10
Displaying hidden handle propertieshttps://undocumentedmatlab.com/blog_old/displaying-hidden-handle-properties https://undocumentedmatlab.com/blog_old/displaying-hidden-handle-properties#comments Tue, 05 May 2009 23:03:55 +0000 http://undocumentedmatlab.com/?p=237 Related posts:
  1. Draggable plot data-tips Matlab's standard plot data-tips can be customized to enable dragging, without being limitted to be adjacent to their data-point. ...
  2. Figure window customizations Matlab figure windows can be customized in numerous manners using the underlying Java Frame reference. ...
  3. Matlab’s HG2 mechanism HG2 is presumably the next generation of Matlab graphics. This article tries to explore its features....
  4. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
]]>
Matlab Handle Graphics (HG) is a great way to manipulate GUI objects. HG handles often have some undocumented hidden properties. One pretty well-known example is the JavaFrame property of the figure handle, which enables access to the GUI’s underlying Java peer object. We can use hidden properties just like any other handle property, using the built-in get and set functions.

But how can we know about these properties? Here are two methods to do so. Like the hidden properties, these two methods are themselves undocumented…

1. use the desktop’s hidden HideUndocumented property:

set(0,'HideUndocumented','off');

From now on, when displaying handle properties using get and set you’ll see the hidden properties.

Note that some of the properties might display a warning indication:

>> get(gcf)
	Alphamap = [ (1 by 64) double array]
	BackingStore = on
	CloseRequestFcn = closereq
	Color = [0.8 0.8 0.8]
	Colormap = [ (64 by 3) double array]
	CurrentAxes = []
	CurrentCharacter = 
	CurrentKey = 
	CurrentModifier = [ (1 by 0) cell array]
	CurrentObject = []
	CurrentPoint = [0 0]
	DithermapWarning: figure Dithermap is no longer useful
 with TrueColor displays, and will be removed in a future release.
 = [ (64 by 3) double array]
        ...

2. Access the properties’ definition in the handle’s class definition:

>> ch = classhandle(handle(gcf));
>> props = get(ch,'Properties');
>> propsVisibility = get(props,'Visible')';
>> hiddenProps = props(strcmp(propsVisibility,'off'));
>> sort(get(hiddenProps,'Name'))
ans = 
    'ALimInclude'
    'ActivePositionProperty'
    'ApplicationData'
    'BackingStore'
    'Behavior'
    'CLimInclude'
    'CurrentKey'
    'CurrentModifier'
    'Dithermap'
    'DithermapMode'
    'ExportTemplate'
    'HelpFcn'
    'HelpTopicKey'
    'HelpTopicMap'
    'IncludeRenderer'
    'JavaFrame'
    'OuterPosition'
    'PixelBounds'
    'PrintTemplate'
    'Serializable'
    'ShareColors'
    'UseHG2'
    'WaitStatus'
    'XLimInclude'
    'YLimInclude'
    'ZLimInclude'

Different HG handles have different hidden properties. Not all these properties are useful. For example, I have found the PixelBounds property to be problematic – (it sometimes reports incorrect values!). Other properties (like Dithermap or ShareColors) are deprecated and display a warning wherever they are accessed.

But every so often we find a hidden property that can be of some actual benefit. Let’s take the figure handle’s OuterPosition property for example. It provides the figure’s external position values, including the space used by the window frame, toolbars etc., whereas the regular documented Position property only reports the internal bounds:

>> get(gcf,'pos')
ans =
   232   246   560   420
>> get(gcf,'outer')
ans =
   228   242   568   502

In future posts I will sometimes use such hidden properties. You can find the latest list by looking at this blog’s “Hidden property” category page.

Note: Like the rest of Matlab’s undocumented items, all hidden properties are undocumented, unsupported and may well change in future Matlab releases so use them with care.

Did you find any useful hidden property? If so, then please leave your finding in the comments section below.

]]>
https://undocumentedmatlab.com/blog_old/displaying-hidden-handle-properties/feed 14