Posts Tagged ‘schema.prop’

The javacomponent function

Wednesday, August 4th, 2010

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, 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.

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.

New information on HG2

Monday, May 10th, 2010

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 (Unified Data Definition?) 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.

Continuous slider callback

Monday, February 8th, 2010

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);

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

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');  % a schema.prop object
hListener = handle.listener(hhSlider,hProp,'PropertyPostSet',@myCbFcn);

In addition to ‘PropertyPostSet’, we could also listen on ‘PropertyPreSet’, which is triggered immediately before the property is modified. There are also corresponding ‘*Get’ options. In relatively old Matlab releases (I believe R2007b and earlier, but I’m not certain), the option names were simply ‘PostSet’, ‘PreSet’ etc., without the ‘Property’ prefix.

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

Context-Sensitive Help

Wednesday, August 5th, 2009

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.

Displaying hidden handle properties

Tuesday, May 5th, 2009

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.