Archive for the ‘High risk of breaking in future versions’ Category

Syntax highlighted labels & panels

Wednesday, July 14th, 2010

A few weeks ago, a reader of my article about rich Matlab editbox contents asked whether it is possible to display syntax-highlighted contents, i.e. contents whose color changes based on its underlying text, often called syntax hilite in affection. I gave a very specific answer in a reply comment, which I expand in today’s full-length article.

Matlab has two built-in Java classes that can present syntax-highlighted text: SyntaxTextLabel presents single-line labels, while SyntaxTextPane presents a multi-line editor pane. Both of these classes support C, HTML/XML, Java and Matlab syntax highlighting, as well as standard plaint-text. Some related JIDE classes are also described.

SyntaxTextLabel

SyntaxTextLabel is used to display a syntax-highlighted single-line text label according to the specified programming language: C_STYLE, HTML_STYLE, JAVA_STYLE, PLAIN_STYLE and of course M_STYLE for Matlab code:

str = 'for id=1:3, set(h(id),''string'',num2str(id)); end  % Matlab code';
codeType = com.mathworks.widgets.SyntaxTextLabel.M_STYLE;
jCodeLabel = com.mathworks.widgets.SyntaxTextLabel(str,codeType)
[jhLabel,hContainer] = javacomponent(jCodeLabel,[10,10,300,20],gcf);

SyntaxTextLabels (different code styles)

SyntaxTextLabels (different code styles)

StyledLabel

More flexibility in the displayed label styles can be achieved with HTML/CSS, and the bundled JIDE class com.jidesoft.swing.StyledLabel provides even more flexibility:

import java.awt.*
import com.jidesoft.swing.*
str = 'Mixed Underlined Strikethrough Super and Subscript combo Styles';
com.mathworks.mwswing.MJUtilities.initJIDE;
jStyledLabel = StyledLabel(str); 
styles = [StyleRange(0,5,  Font.BOLD,   Color.BLUE), ...
          StyleRange(6,10, Font.PLAIN,StyleRange.STYLE_UNDERLINED),...
          StyleRange(17,13,Font.PLAIN,  Color.RED,   ...
                           StyleRange.STYLE_STRIKE_THROUGH), ...
          StyleRange(31,5, Font.PLAIN,  Color.BLUE,  ...
                           StyleRange.STYLE_SUPERSCRIPT), ...
          StyleRange(37,3, Font.ITALIC, Color.BLACK), ...
          StyleRange(41,9, Font.PLAIN,  Color.BLUE,  ...
                           StyleRange.STYLE_SUBSCRIPT), ...
          StyleRange(51,5, Font.PLAIN,  StyleRange.STYLE_WAVED + ...
                           StyleRange.STYLE_STRIKE_THROUGH)];
jStyledLabel.setStyleRanges(styles);
[jhLabel,hContainer] = javacomponent(jStyledLabel,[10,10,300,20],gcf);

JIDE StyledLabel (different font styles)

JIDE StyledLabel (different font styles)

StyledLabels have subclasses that can be used to present styled text in tables, trees or lists. JIDE also provides the convenient StyledLabelBuilder, which enables easy multi-style text construction.

Finally, JIDE provides the ClickThroughStyledLabel, a StyledLabel extension that allows setting a target component, so that mouse clicks on the label will actually trigger the target component. This can be useful in forms where components have adjacent descriptive labels.

SyntaxTextPane

Multi-line syntax-highlighted code can be displayed with Matlab’s SyntaxTextPane class. SyntaxTextPane uses MIME types rather than styles for syntax-highlighting, but the end-result appears similar:

jCodePane = com.mathworks.widgets.SyntaxTextPane;
codeType = jCodePane.M_MIME_TYPE;  % ='text/m-MATLAB'
jCodePane.setContentType(codeType)
str = ['% create a file for output\n' ...
       '!touch testFile.txt\n' ...
       'fid = fopen(''testFile.txt'', ''w'');\n' ...
       'for i=1:10\n' ...
       '    % Unterminated string:\n' ...
       '    fprintf(fid,''%6.2f \\n, i);\n' ...
       'end'];
str = sprintf(strrep(str,'%','%%'));
jCodePane.setText(str)
jScrollPane = com.mathworks.mwswing.MJScrollPane(jCodePane);
[jhPanel,hContainer] = javacomponent(jScrollPane,[10,10,300,100],gcf);

SyntaxTextPane panel (Matlab MIME type)

SyntaxTextPane panel (Matlab MIME type)

The nice thing about SyntaxTextPane is that it syntax-highlights on-the-fly as you type or edit in the SyntaxTextPane (assuming you have not disabled editing with the setEditable(flag) method). This is exactly the behavior we have come to expect in the full-blown Matlab editor, and can now be embedded as a simple panel within our GUI.

Despite its misleadingly-simple look, SyntaxTextPane actually has most capabilities of the full-blown editor, not just syntax highlighting. This includes multiple undo/redo actions; smart indentation/commenting; automatic indication of corresponding block elements (if-end, for-end, etc. – also known as delimiter matching); search/replace, drag-and-drop and cut-copy-paste support; and many more.

Interested readers can use the uiinspect and checkClass utilities to explore the full capabilities offered by SyntaxTextPane. In this respect it would be helpful to also look at its super-class (SyntaxTextPaneBase) and the related SyntaxTextPaneUtilities class.

Summary

These Java classes are examples of built-in classes that can be used in Matlab applications, enabling a much richer GUI experience than possible using the standard (documented/supported) Matlab widgets.

As I have shown above, using these classes is extremely easy, and requires absolutely no Java knowledge. On the flip side, these internal Matlab classes may easily break in any future Matlab release, so be extra careful when deciding to use them. Future articles in this website will describe other similarly-useful built-in classes.

Have you found any other useful built-in Matlab class? If so, please post a comment.

JMI wrapper – remote MatlabControl

Wednesday, May 26th, 2010

Perhaps the most difficult aspect of Matlab-Java integration is JMI (Java-to-Matlab Integration) over a remote connection, meaning a Java program that communicates with a separate Matlab process. Once again I welcome guest blogger Joshua Kaplan, who concludes his series of JMI-related articles with the awaited holy grail on this topic.

Remote control of Matlab

Last week I demonstrated using matlabcontrol to call Matlab from Java from within the Matlab application. Today I will explain how to control Matlab from a remote Java session. We will create a small Java program that allows us to launch and connect to Matlab, then send it eval commands and receive the results. While this example will involve creating a dedicated user interface, matlabcontrol can be integrated into any existing Java program without requiring any user interface.

matlabcontrol was originally created for controlling Matlab, not for performing computations. If your exclusive concern is to perform Matlab computations and use the results in Java, then check the Matlab Builder JA toolbox, which is made by MathWorks and is officially supported. Unfortunately this toolbox is quite expensive and does not enable interaction with a running Matlab session (it uses the non-GUI Matlab engine, much as the compiler does). It is for this purpose that the open-source (free) matlabcontrol package was created.

Note that matlabcontrol opens a new running Matlab session and does not connect to an already-running session. Matlab commands can then be invoked either interactively (in Matlab’s Command Window) or remotely (from Java). Debugging an already-open Matlab session can be done with jdb over a dedicated port, using an altogether different mechanism than matlabcontrol – this will be discussed in a future post.

Matlab has documented support for a COM interface (Windows) and process pipes (Unix/Mac) that allow remote communication from external applications. Unfortunately Java does not natively support COM, which is where matlabcontrol helps using its RMI approach. Interested readers can also try using a Java/COM bridge (JACOB or JCOM) as an alternative that would have the added benefits of enabling communication with an existing Matlab session and of MathWorks’ documented support.

A simple RemoteExample

Today’s RemoteExample demo is too long to paste into this post; instead you can download the source code, or a jar file that contains both the pre-compiled classes and matlabcontrol. To run this jar on Windows or Mac OS X you only need to double click on it (if you are running on Linux I’m sure you know what to do…). If you wish to download and compile the source file, remember that you will need the matlabcontrol jar referenced in your Java classpath.

Let’s dive in: The file begins with the mainline followed by default sizes and status messages. The user interface is then built using standard Swing components – there’s nothing special here, just some panels, panes, text fields, buttons, etc.

The interesting part begins when the RemoteMatlabProxyFactory object is created:

RemoteMatlabProxyFactory factory = new RemoteMatlabProxyFactory();

This Matlab-proxy factory object is used when the user clicks the “Connect” button:

factory.requestProxy();

This creates a RemoteMatlabProxy object. RemoteMatlabProxys must be created by a RemoteMatlabProxyFactory and cannot be directly constructed. When requestProxy() is called, matlabcontrol launches Matlab and connects to it using RMI. When the connection is established, a MatlabConnectionListener added to the factory will be notified using its connectionEstablished(RemoteMatlabProxy proxy) callback method. The RemoteMatlabProxy object passed into this method is now connected to Matlab.

Connecting Java to Matlab using RMI

Connecting Java to Matlab using RMI

While this example only deals with communicating with a single Matlab session, matlabcontrol can handle multiple remote sessions. Whenever a new session is established, connectionEstablished(RemoteMatlabProxy proxy) is invoked on each connection listener. When a connection is lost due to Matlab closing, or in very rare cases Matlab encountering extremely severe errors, connectionLost(RemoteMatlabProxy proxy) is called. Calling methods on this proxy will lead to exceptions being thrown, as it can no longer communicate with Matlab. The proxy is passed because this information is useful when controlling multiple sessions of Matlab simultaneously.

When the “Invoke” button is pressed, the command and number of return arguments is sent to Matlab. If the number of return arguments is 0, the command will still execute but nothing will be returned. If the number is positive but less than the total number of return arguments, then only up to that number of arguments will be returned. If the number of return arguments specified exceeds the actual amount of arguments returned, a Java exception will be thrown. By default the fields are populated to return the result of “sqrt(5)“. Press “Invoke” to see what happens. Change the number of return arguments to 0, and click “Invoke” again. Now change the number to 2 and try once more.

Invoking Matlab commands from Java using JMI

Invoking Matlab commands from Java using JMI

When the Java program closes, it also exits Matlab. This is accomplished by adding a WindowListener to the program, which detects the Java closure event. It is important to call Matlab’s exit command as opposed to eval(“exit”), because all other proxy methods block (pause) until completion but in the case of exiting Matlab no signal will ever be sent by Matlab to indicate it has closed.

Parsing Matlab’s return values

Our eval commands are being sent using RemoteMatlabProxy’s returningEval(String command, int returnCount) method, whose return type is Object, because Matlab can return multiple return types. For example, the expression “sqrt(5)” will return an array of doubles, “pwd” will return a java.lang.String, and “whos” will return a complicated array of arrays with a variety of base types and Objects.

This is what occurs in Matlab R2009b, but not necessarily in past or future versions. You will have to experiment to find out what is being returned on your particular platform. The demo can help as it lists everything returned, including array contents. The demo contains the formatResult(Object result, int level) method which recursively goes through the object returned from Matlab and builds a description of what it contains. As discussed in my introductory post on matlabcontrol, Matlab functions will either return a base type, an array of base types, or a String. However, if we call a Java function inside the Matlab environment then any Java object might be returned. This isn’t actually that absurd of a situation; it might arise if you are trying to control the Matlab UI.

When returning Java objects from Matlab certain restrictions and limitations apply. First, the object must be Serializable because of the underlying use of RMI. In practice this isn’t a huge issue as a very large number of built-in Java classes are Serializable, and making your own classes Serializable is usually trivial.

The second limitation is that whatever class you send from the Matlab environment to your Java program must be defined in your Java program. For any standard built-in Java class this won’t cause issues. However, if you attempt to send over classes custom to Matlab then your Java program must have those classes in its classpath (in practice this means reference the jar file containing that class). For HG (or rather, UDD) classes, you can use the following Matlab function to create a Java class interface that can be used in your Java code to access the Matlab object, or access the jar file that contains that class as explained above:

% This will create a figure.java file in the current folder:
myClassHandle = classhandle(handle(gcf));
myClassHandle.createJavaInterface(myClassHandle.name, pwd);
 
% alternately, you can use myClassHandle.JavaInterfaces{1}
% = 'com.mathworks.hg.Figure' in this particular case
% i.e., in your java code import com.mathworks.hg.Figure

(UDD will be described in much more detail in a future article that is currently being prepared)

The third caveat is that you will be returned a copy of the Java object. This means that if you have a Java array in Matlab, send it to your Java program and then insert an object into the array, the array in Matlab will not be affected. However, you can then send that array back to Matlab, so in practice this does not cause significant issues. None of these restrictions are applicable to matlabcontrol for local sessions.

Conclusion

Today we have shown how a dedicated Matlab session can be started from a Java application, which then communicates with that Matlab session using the matlabcontrol package. This concludes my series on matlabcontrol. Please check out the matlabcontrol website for more information, examples and updates. If you use matlabcontrol, filling out this survey so that I can improve it, would be greatly appreciated.

Since the past few articles were heavy on Matlab-Java topics, the next few articles will be devoted to undocumented pure-Matlab tips and tricks, starting next week with the topic of how to customize the default menubar and toolbar actions.

JMI wrapper – local MatlabControl part 2

Wednesday, May 19th, 2010

Once again I welcome guest blogger Joshua Kaplan for his continued series on MatlabControl – the Java-to-Matlab Interface (JMI) wrapper

Last week I introduced a Java package called matlabcontrol which can be used to access Matlab from Java.

Let’s now put matlabcontrol to work from Java. Below is a very simple Java class called LocalExample which uses Swing to create a window (JFrame), a text field (JTextField), and a button (JButton). When the button is pressed, the text in the field will be evaluated in Matlab using LocalMatlabProxy.eval(…), which was explained in the previous post.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
 
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
 
import matlabcontrol.LocalMatlabProxy;
import matlabcontrol.MatlabInvocationException;
 
/**
 * A simple demo of some of matlabcontrol's functionality.
 * 
 * @author Joshua Kaplan
 */
public class LocalExample extends JFrame
{
  /**
   * Constructs this example and displays it.
   */
  public LocalExample()
  {
    //Window title
    super("Local Session Example");
 
    //Panel to hold field and button
    JPanel panel = new JPanel();
    this.add(panel);
 
    //Input field
    final JTextField inputField = new JTextField();
    inputField.setColumns(15);
    panel.add(inputField);
 
    //Eval button
    JButton evalButton = new JButton("eval");
    panel.add(evalButton);
 
    //Eval runnable, to execute in separate (non-EDT) thread
    final ExecutorService executor = Executors.newSingleThreadExecutor();
    final Runnable evalRunnable = new Runnable()
    {
      public void run()
      {
        try
        {
          LocalMatlabProxy.eval(inputField.getText());
        }
        catch (MatlabInvocationException exc) { }
      }
    };
 
    //Eval action event for button and field
    ActionListener evalAction = new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        //This uses the EDT thread, which may hang Matlab...
        //LocalMatlabProxy.eval(inputField.getText());
 
        //Execute runnable on a separate (non-EDT) thread
        executor.execute(evalRunnable);
      }
    };
    evalButton.addActionListener(evalAction);
    inputField.addActionListener(evalAction);
 
    //On closing, release resources of this frame
    this.addWindowListener(new WindowAdapter()
    {
      public void windowClosing(WindowEvent e)
      {
        LocalExample.this.dispose();
      }
    });
 
    //Display
    this.pack();
    this.setResizable(false);
    this.setVisible(true);
  }
}

We can either copy and compile the above code (remember to import the matlabcontrol JAR file in your compiler; four class files will be created), or download the already-compiled code here. Note that the already-compiled classes were compiled using JDK 1.6, so if you have Matlab R2007a (7.4) or earlier you will need to compile using an earlier Java compiler.

We now need to tell Matlab where to find both the matlabcontrol JAR file, and our LocalExample class files. We can either add the files to the static java classpath (by editing the classpath.txt file), or add them only to the current Matlab session’s dynamic classpath:

% Add Java files to current Matlab session's dynamic classpath
javaaddpath LocalExample.zip
javaaddpath matlabcontrol-3.01.jar

To run the Java program, simply type LocalExample in the Matlab Command Window – A small Java window will appear and JMI will evaluate any expression typed into it:

>> LocalExample
ans =
LocalExample[frame0,0,0,202x67,title=Local Session Example,...]

Java window calling Matlab via JMI

Java window calling Matlab via JMI

a =
          1.77245385090552

When we called LocalMatlabControl.eval(…) from the Command Window last week, what occurred behind the scenes was actually quite different from what happens when we press the “eval” button in the Java program. This is because in the Command Window everything executes in Matlab’s single main thread. When we pressed “eval”, the code executed from the Event Dispatch Thread (EDT), which is a separate thread.

EDT is used extensively by Matlab when accessing graphical components such as a figure window, uicontrols or plots. When calling a function from JMI, the calling thread always blocks (pauses) until Matlab is done completing whatever has been asked of it. So, if we called JMI/matlabcontrol from the EDT and Matlab needed to use the EDT, then everything will lock up. To fix this potential problem, when you press the “eval” button the command is sent off to a separate thread which can block without preventing Matlab from doing its work. Future versions of matlabcontrol will try to simplify this process further. matlabcontrol over a remote connection, the topic of my next post, does not suffer from this complication because Matlab and your program are not sharing the same EDT or even the same Java runtime process (JVM).

While the above Java example is quite simple, using a combination of all of the methods described throughout my previous post, a much more sophisticated program can be created. To explore the methods in more detail you can use the demo available here. The demo uses a remote connection to Matlab, but the available methods are the same. In my next and final article on this subject, I will explore controlling Matlab using matlabcontrol over a remote connection.

JMI wrapper – local MatlabControl part 1

Wednesday, May 12th, 2010

Once again I would like to welcome guest blogger Joshua Kaplan, who continues his series of JMI-related articles

Local and remote MatlabControl

Several weeks ago, I discussed the undocumented world of JMI (Java-to-Matlab Interface), that enables calling Matlab from Java. Today I will discuss matlabcontrol, an open-source wrapper I have written for JMI, that is both documented and user-friendly.

matlabcontrol supports calling Matlab in two different ways: local control where the Java code is launched from Matlab, and remote control where the Java code launches Matlab. Today we shall explore matlabcontrol’s local control methods; in my next post we’ll create a simple Java program that uses matlabcontrol for local control; a later post will discuss the remote control path. These posts assume a medium to high level of Java experience.

matlabcontrol is a collection of Java classes, bundled together in a downloadable jar file, which is essentially just a zip file with a different file extension. As of this post the most recent version is matlabcontrol-3.01.jar. Note down where you’ve downloaded the jar file – you’ll need to use this information shortly.

For local control we’ll interact with the classes LocalMatlabProxy and MatlabInvocationException. LocalMatlabProxy contains all the methods required for calling Matlab; instances of MatlabInvocationException will be thrown when a problem occurs while attempting to control Matlab.

To tell Matlab where matlabcontrol-3.01.jar is, add the jar file path to Matlab’s dynamic (via the built-in javaaddpath function) or static (via edit(‘classpath.txt’)) Java classpath. You will need to restart Matlab if you have modified the static classpath, but it has the benefit of working better than the dynamic classpath in some situations.

Matlab now knows where to find the Java class files in matlabcontrol. To save some typing later on, type the following in the Matlab Command Window (or in your JMI-empowered Matlab application):

import matlabcontrol.*

LocalMatlabProxy methods

LocalMatlabProxy is easy to use. All of its methods are static meaning they can be called without needing to assign LocalMatlabProxy to a variable. The methods are:

void exit()
java.lang.Object getVariable(java.lang.String variableName)
void setVariable(java.lang.String variableName, java.lang.Object value)
void eval(java.lang.String command)
java.lang.Object returningEval(java.lang.String command, int returnCount)
void feval(java.lang.String functionName, java.lang.Object[] args)
java.lang.Object returningFeval(java.lang.String functionName, java.lang.Object[] args)
java.lang.Object returningFeval(java.lang.String functionName, java.lang.Object[] args, int returnCount)
void setEchoEval(boolean echoFlag)

Detailed javadocs exist for all these methods. Here is an overview:

  • exit() is as straightforward as it sounds: it will exit Matlab. While it is possible to programmatically exit Matlab by other means, they may be unreliable. So, to exit Matlab from Java:
     LocalMatlabProxy.exit();
  • Setting and getting variables can be done using the getVariable(…) and setVariable(…) methods. These methods will auto-convert between Java and Matlab types where applicable.

       Using getVariable(…):

    • Java types in the Matlab environment retrieved will be returned as Java types.
    • Matlab types will be converted into Java types.

       Using setVariable(…):

    • Java types will be converted into Matlab types if they can. The rules are outlined here. Java Strings are converted to Matlab char arrays. Additionally, arrays of one of those Java types are converted to arrays of the corresponding Matlab type.

       Using these methods is fairly intuitive:

     >> LocalMatlabProxy.setVariable('x',5)
     
    >> LocalMatlabProxy.getVariable('x') 
    ans = 
         5

       Getting and setting basic types (numbers, strings and Java objects) is quite reliable and consistent. It gets complicated when passing in an array (particularly multidimensional) from Java using setVariable(…), or getting a Matlab struct or cell array using getVariable(…). The type conversion in such cases is unpredictable, and may be inconsistent across Matlab versions. In such cases you are best off building a Java object with Matlab code and then getting the Java object you created.

  • The eval() and feval() methods were described in detail in my previous post. The functions will return the result, if any, as a Java object. Due to the way the underlying JMI operates, it is necessary to know in advance the number of expected return arguments. Matlab built-in nargout function reveals this number. Some functions (e.g., feval) return a variable number of arguments, in which case nargout returns -1. For instance:
     >> nargout sqrt 
    ans = 
         1
     
    >> nargout feval
    ans = 
         -1
  • LocalMatlabProxy’s returningFeval(functionName, args) method uses the nargout information to determine the number of returned arguments and provide it to JMI. It will likely not function as expected if the function specified by functionName returns a variable number of arguments. In such a case, call returningFeval(…) with a third input argument that specifies the expected number of returned arguments. Since an eval() function can evaluate anything, just as if it were typed in the Command Window, there is no reliable way to determine what will be returned. All of this said, in most situations returningEval(…) can be used with a return count of 1, and the returningFeval(…) that automatically determines the return count will operate as expected.

Some simple usage examples

Let’s perform some of the same simple square root operations we did in the pure-JMI article, this time using matlabcontrol. First we’ll take the square root of 5, assigning the result to the Matlab variable y (note that we are calling Matlab from Java, that is called from within Matlab):

>> LocalMatlabProxy.eval('sqrt(5)') 
ans = 
    2.2361 
 
>> y = LocalMatlabProxy.returningEval('sqrt(5)',1) 
y = 
    2.2361 
 
>> LocalMatlabProxy.feval('sqrt',5)
 
>> y = LocalMatlabProxy.returningFeval('sqrt',5) 
y = 
    2.2361 
 
>> y = LocalMatlabProxy.returningFeval('sqrt',5,1) 
y = 
    2.2361

In this situation there is no major difference between using eval() or feval() in the above situation. However, if instead of taking the square root of 5 we want to take the square root of a variable, then eval() is our only option.

>> a = 5 
a = 
     5 
 
>> LocalMatlabProxy.eval('sqrt(a)') 
ans = 
    2.2361 
 
>> y = LocalMatlabProxy.returningEval('sqrt(a)',1) 
y = 
    2.2361 
 
>> LocalMatlabProxy.feval('sqrt','a')
??? Undefined function or method 'sqrt' for input arguments of type 'char'.
??? Java exception occurred:
matlabcontrol.MatlabInvocationException: Method could not return a value because of an internal Matlab exception
      at matlabcontrol.JMIWrapper.returningFeval(JMIWrapper.java:256)
      at matlabcontrol.JMIWrapper.feval(JMIWrapper.java:210)
      at matlabcontrol.LocalMatlabProxy.feval(LocalMatlabProxy.java:132)
Caused by: com.mathworks.jmi.MatlabException: Undefined function or method 'sqrt' for input arguments of type 'char'.
      at com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Native Method)
      at com.mathworks.jmi.NativeMatlab.sendMatlabMessage(NativeMatlab.java:212)
      at com.mathworks.jmi.MatlabLooper.sendMatlabMessage(MatlabLooper.java:121)
      at com.mathworks.jmi.Matlab.mtFevalConsoleOutput(Matlab.java:1511)
      at matlabcontrol.JMIWrapper.returningFeval(JMIWrapper.java:252)
      ... 2 more

The automatic Matlab/Java type conversions discussed above are equally applicable to eval() and feval(). feval() automatically converted the argument ‘a’ into a Matlab char, instead of considering it as a Matlab variable. As seen above, the feval() invocation fails with a Java MatlabInvocationException. So, the only way to interact with Matlab variables is via eval() methods; feval() will not work.

Lastly there is the setEchoEval(echoFlag) method: If this method is called with a true argument, then all Java to Matlab calls will be logged in a dedicated window. This can be very helpful for debugging.

In my next post we shall put together this knowledge to create a small Java program that uses matlabcontrol to interact with Matlab.

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.

Matlab’s HG2 mechanism

Friday, May 7th, 2010

A few days ago I posted a lengthy article about Matlab’s undocumented feature function. In it, I mentioned a feature called HG2, that I believe merits a dedicated article, due to its potential high impact on future Matlab releases.

HG2, which presumably stands for “Handle Graphics 2nd generation”, was already reported in the past as an undocumented hidden figure property (UseHG2). In normal Matlab usage, this boolean property is ‘off’:

>> get(gcf,'usehg2')
ans =
off

HG2 is mentioned in quite a few Matlab files:

  • clf.m, hgload.m, ishg2figure.m, datetick.m, linkdata.m, linkplotfunc.m, cameratoolbar, /bin/registry/handle_graphics.xml, /ja/xlate and many more
  • uimodemanager.m (and others) temporarily disables a ‘MATLAB:handle:hg2′ warning
  • defaulterrorcallback.m mentions ‘MATLAB:HG2:SceneNode’ and ‘MATLAB:HG2:Property’
  • getplotbrowserproptable.m mentions several special HG2 types (hg2.Line, hg2.Lineseries, hg2.Patch etc.)
  • There’s even a dedicated /toolbox/matlab/graphics/private/ishg2figure.m function that determines whether a figure contains any HG2 graphics based on the existence of ‘hg2peer’ appdata (getappdata(fig,’hg2peer’)).
  • /toolbox/matlab/plottools/@objutil/@eventmanager/schema.m (and a few others) has the following comment:
     % may contain either UDD or MCOS listeners during the hg2 migration.

Obviously, much effort was invested in HG2 functionality. The fact that HG2 has been under development at least since 2007 (when I first discovered and reported it) seems to indicate a major upheaval in Matlab’s Handle Graphics mechanism. This hunch is reinforced by cryptic comments made by MathWorks personnel over the past few years that they are indeed looking at the HG system, which in their opinion is nearing its limitations. Perhaps I’m mixing unrelated stuff here, but it does make sense in light of Matlab’s push of its OOP class system over the past few releases.

To preview this HG2 system, we need to turn it on. Unfortunately, when we set the figure’s UseHG2 to ‘on’ there doesn’t seem to be any visible effect. However, this changes after we use the corresponding ‘UseHG2′ feature using the feature function (this caused lots of nasty-looking errors in past releases but works ok in R2010a):

>> feature('usehg2',1)

The /ja/xlate file (which is used in conjunction with the undocumented xlate function to translates Matlab messages from English to Japanese) has another key to unlocking HG2: This file contains the following message: “feature(‘useGBT2′) is only available when Matlab is started with -hgVersion 2 option.“. So let’s do as the xlate message advises and start a new Matlab session with the undocumented “-hgVersion 2″ command-line option. Now feature(‘usehg2′) is true by default and we can test the HG2 system.

Matlab looks basically the same in HG2 as in HG1. All the regular graphic functions behave just as we would expect from the existing (HG1) implementation. There are two major differences though:

  • the figure toolbars/menubars are missing and cannot be shown, even when the relevant figure properties are set. Without a menubar and toobar, Matlab figures are extremely less useful than their HG1 counterparts. This problem does not occur in HG2-enabled figures in the regular Matlab session (i.e., without using the “-hgVersion 2″ command-line option)
  • all the HG handles are now Matlab class handles rather than numeric values (These class handles are similar to those returned today (in HG1) using the undocumented handle function). There’s an exception to this rule: in regular Matlab sessions (i.e., without using the “-hgVersion 2″ command-line option), after setting the ‘UseHG2′ feature on, the returned figure handle is numeric rather than a class handle (but if you now plot within this figure you get the class object handles). Here’s the output from the “-hgVersion 2″ Matlab session:
    >> hFig = figure
    hFig = 
    	ui.Figure
     
    >> hLine = plot(1:5)
    hLine = 
    	hg2.Lineseries
     
    >> get(hLine,'Parent')
    ans = 
    	hg2.Axes
     
    >> findprop(gcf,'Tag')
    ans = 
      meta.property handle
      Package: meta
     
      Properties:
                       Name: 'Tag'
                Description: 'Tag PropInfo'
        DetailedDescription: ''
                  GetAccess: 'public'
                  SetAccess: 'public'
                  Dependent: 1
                   Constant: 0
                   Abstract: 0
                  Transient: 0
                     Hidden: 0
              GetObservable: 1
              SetObservable: 1
                   AbortSet: 0
                  GetMethod: []
                  SetMethod: []
                 HasDefault: 0
              DefiningClass: [1x1 meta.class]
      Methods, Events, Superclasses
     
    >> methods(gcf)
     
    Methods for class ui.Figure:
     
    Figure                  disp                    get                     horzcat                 lt                      subsasgn                
    addlistener             double                  getParentImpl           ishghandlewithargs      ne                      vertcat                 
    addprop                 eq                      getSceneViewer          ishghandlewoargs        notify                  
    applydefaultproperties  findobj                 getdisp                 isvalid                 reset                   
    cat                     findprop                gt                      java                    set                     
    delete                  ge                      hgclose                 le                      setdisp                 
     
    Static methods:
     
    getDefaultObject        
     
    >> methods(gcf,'-full')
     
    Methods for class ui.Figure:
     
    ui.Figure lhs1 Figure(rhs0)
    event.listener L addlistener(handle sources, char vector eventname, function_handle scalar callback)  % Inherited from hg2utils.HGHandle
    event.proplistener L addlistener(handle sources, meta.property propertyname, char vector eventname, function_handle scalar callback)  % Inherited from hg2utils.HGHandle
    event.proplistener L addlistener(handle sources, string propertyname, char vector eventname, function_handle scalar callback)  % Inherited from hg2utils.HGHandle
    event.proplistener L addlistener(handle sources, cell propertyname, char vector eventname, function_handle scalar callback)  % Inherited from hg2utils.HGHandle
    meta.property prop addprop(handle scalar object, string propname)  % Inherited from dynamicprops
    applydefaultproperties(HGHandle object, rhs1)  % Inherited from hg2utils.HGHandle
    HeterogeneousHandle lhs3 cat(double rhs0, rhs1, rhs2)  % Inherited from HeterogeneousHandle
    delete(handle obj)  % Inherited from handle
    disp(object)  % Inherited from hg2utils.HGHandle
    lhs1 double(handle object)  % Inherited from hg2utils.HGHandle
    logical TF eq(A, B)  % Inherited from hg2utils.HGHandle
    handle output findobj(handle object, varargin)  % Inherited from hg2utils.HGHandle
    meta.property prop findprop(handle scalar object, string propname)  % Inherited from handle
    logical TF ge(A, B)  % Inherited from handle
    varargout get(hgsetget object, rhs1)  % Inherited from hg2utils.HGHandle
    Static HeterogeneousHandle lhs0 getDefaultObject  % Inherited from hg2utils.HGHandle
    lhs2 getParentImpl(handle scalar object, rhs1)  % Inherited from hg2utils.HGObject
    lhs2 getSceneViewer(handle scalar object, rhs1)  % Inherited from ui.UISceneViewerParent
    getdisp(hgsetget rhs0)  % Inherited from hgsetget
    logical TF gt(A, B)  % Inherited from handle
    hgclose(handle scalar object)
    HeterogeneousHandle lhs2 horzcat(rhs0, rhs1)  % Inherited from HeterogeneousHandle
    lhs2 ishghandlewithargs(handle scalar object, rhs1)  % Inherited from hg2utils.HGObject
    lhs1 ishghandlewoargs(handle scalar object)  % Inherited from hg2utils.HGObject
    logical validity isvalid(handle obj)  % Inherited from handle
    j java(JavaVisible scalar h)  % Inherited from JavaVisible
    logical TF le(A, B)  % Inherited from handle
    logical TF lt(A, B)  % Inherited from handle
    logical TF ne(A, B)  % Inherited from hg2utils.HGHandle
    notify(handle sources, string eventname, event.EventData scalar eventdata)  % Inherited from handle
    notify(handle sources, string eventname)  % Inherited from handle
    reset(handle scalar object)  % Inherited from hg2utils.HGHandle
    varargout set(hgsetget object, rhs1)  % Inherited from hg2utils.HGHandle
    setdisp(hgsetget rhs0)  % Inherited from hgsetget
    varargout subsasgn(rhs0, rhs1, rhs2, rhs3)  % Inherited from HeterogeneousHandle
    HeterogeneousHandle lhs2 vertcat(rhs0, rhs1)  % Inherited from HeterogeneousHandle

The latest Matlab releases have shown how the Matlab handle class can be extended using user-created derived classes. It stands to reason that so do all the new HG2 objects. This would theoretically enable Matlab programmers to customize graphic objects appearance to suit their needs in a more intuitive manner than possible using HG1.

Many mysteries remain:

  • is it possible to mix HG1 and HG2 objects in the same figure?
  • can we switch between HG1 and HG2 in the same Matlab session (I got some crashes…)?
  • why is there a need for the separate feature options ‘UseHG2′, ‘UseGBT2′ and ‘HGUsingMatlabClasses’?
  • why is there a need for “-hgVersion 2″ Matlab sessions if we can simply use feature(‘UseHG2′)?
  • is it possible to restore the figure menubar and toolbar in “-hgVersion 2″ Matlab sessions?
  • is it indeed possible to extend HG2 objects using user-defined classes? and if so, can we modify the appearance/behavior beyond what is available in the existing list of HG2 properties?
  • beyond changing numeric handles into class handles, are there any actual benefits to the HG2 system over HG1?
  • what is the difference between HG2, GBT2 and GBT1.5 (which are mentioned together as separate entities in cameratoolbar.m)?

HG2 is still buggy, which explains why it is still not officially released. For example, the inspect(gca) function crashes Matlab, figure toolbars/menubars are missing, and some properties that are available in HG1 are missing in HG2. Also, we can add Java components to a Matlab figure using javacomponent as in HG1 (the returned container handles is a ui.HGJavaComponent class handle), but we get an error when we close the figure…

Still, with all this effort invested into HG2 I believe that it is only a matter of time before HG2 becomes officially released. This could happen perhaps even as soon as the upcoming R2010b release, but with the current state as seen above I suspect it will not happen before 2011. Also, my gut feeling is that Matlab will define any release that includes HG2 as a major release and we will finally have Matlab 8.0.

I would dearly love to hear any further information anyone discovers about HG2 and related issues. Please share your findings by email or in the comments section below.

Undocumented feature() function

Tuesday, May 4th, 2010

Taking a short break from Java-related stuff in Matlab, I wanted to share and expand a reply I posted a short while ago on the StackOverflow forum, in response to a reader’s request to explain Matlab’s feature function. This article uses pure Matlab and is absolutely unrelated to Java, so those of you who are Java-phobic can be at ease trying this at home…

feature is an entirely undocumented and unsupported Matlab function, and unlike most other undocumented Matlab functions it actually does often change without prior notice between Matlab releases, so be very careful when using this function in your code.

feature accepts two arguments: the name of the feature and an optional new value. This is similar to get/set functions: When only one argument is supplied, Matlab returns the current feature value (like get), otherwise the value is modified (like set). In some rare cases (feature(‘timing’)), a third input argument is sometimes expected.

Feature names are case-insensitive. The built-in function system_dependent appears to be a synonym for feature (not exactly – some system_dependent features are unavailable in feature…). We can find several references to system_dependent online, mostly for old Matlab releases. There’s even an entry in the official Matlab FAQ (which has no usful info), and I’ve seen online references going all the way back to 1993…

One of the very rare official comments about this function says:

The system_dependent function is an unpublished function that we use for a variety of crufty things. It will most certainly change from time to time and possibly even go away completely. The system_dependent function performs different functionality on each of the platforms supported by MATLAB.

Several feature options have been reported over the years, mainly on the CSSM forum and also seen in the installed Matlab code base, as listed below (the code references are from the latest Matlab release – 7.10, aka R2010a). Note that many of these features may not work on your platform:

  • feature(‘usehg2′,flag) – this apparently relates to a new Handle-Graphics implementation that is under development for the past few years (I think I saw references to HG2 as far back as 2007, possibly earlier). HG2 is automatically active when Matlab is started with -hgVersion 2 option. It appears that the numeric HG handles have been replaced with their object-oriented (Matlab class system) handle counterparts in HG2 (today these class-system handles can be gotten using the handle function). Some handle properties are not implemented in HG2, and some GUI elements appear missing (figure menubar and toolbar, for example), but the basic plots look similar to our familiar HG. If anyone has any further information about HG2 I would love to hear it…
  • feature(‘useGBT2′) – “feature(‘useGBT2′) is only available when Matlab is started with -hgVersion 2 option.” – In /ja/xlate:15419; also see in: clf.m
  • feature(‘HGUsingMatlabClasses’) – see hgrc.m, subplot.m, title.m, xlabel.m, ylabel.m, zlabel.m, mesh.m, surf.m, colorbar.m etc. etc.
  • feature(‘JavaFigures’) – see propedit.m; disabled since R2007a when native (non-Java) Matlab figures were disabled.
  • feature(‘UseJava’) – see usejava.m
  • feature(‘ClearJava’,1) – see javaclasspath.m
  • feature(‘SetPrecision’) – accepts values 24, 53 or 64
  • feature(‘SetRound’) – accepts values 0, 0.5, Inf or -Inf
  • feature(‘NewPrintAPI’) – see \toolbox\matlab\graphics\private\setup.m
  • feature(‘accel’,’on/off’) – see here and here.
  • feature(‘GetOS’) – see ver.m
  • feature(‘GetWinSys’) – see ver.m
  • feature(‘GetPid’) – returns the Matlab process ID (well, actually the PID of its JVM but that’s the same PID as Matlab’s). Also see the similar java.lang.management.ManagementFactory.getRuntimeMXBean.getName.char. This latter function returns the PID mangled with the computer name (for example: ‘1234@My-desktop’).
  • feature(‘NumCores’) – returns the number of CPU cores seen by Matlab
  • feature(‘MemStats’), feature(‘DumpMem’), feature(‘ProcessMem’) – these are memory reports that are even recommended by official MathWorks tech notes (1,2), newsletter and technical solutions (1,2). Numerous references to these features can be found online.
  • feature(‘CheckMallocMemoryUsage’) – see this official technical paper
  • feature(‘CheckMallocHeapWalk’) – see here
  • feature(‘ShowCommandWindow’) – see here = commandwindow
  • feature(‘LogDir’) – see here = tempdir
  • feature(‘HotLinks’) – used to disable hyperlinks in the Command Window. This is used by Word notebooks (see mwMatlabEval macro in the Microsoft Word template file %matlabroot%\notebook\pc\M-BOOK.DOT). Also see: info.m, mlint.m, doclink.m, guidefunc.m, displayEndOfDemoMessage.m
  • feature(‘UseOldFileDialogs’) – see toolbox\matlab\uitools\private\usejavadialog.m
  • feature(‘timing’) – For example: cpucount = feature(‘timing’,'cpucount’); There are several other 2nd arg options, as explained by the following informative error message:
    >> feature timing
    ??? Error using ==> feature
    Choose second argument from:
      'resolution_tictoc'  - Resolution of Tic/Toc clock in sec (double)
      'overhead_tictoc'    - Overhead of Tic/Toc command in sec (double)
      'cpucount'           - Current CPU cycles used (uint64) [Using utCPUcount]
      'getcpuspeed_tictoc' - Stored CPU cycles/sec (double) [Used by tic/toc]
      'cpuspeed'           - Current CPU cycles/sec (double) [Simple MathWorks]
      'winperfcount'       - Current CPU cycles used (uint64) [Windows call]
      'winperfspeed'       - Current CPU cycles/sec (double) [Windows call]
      'wintime'            - Current Windows time (uint32) [Windows call]
                             units: msec since startup [Wraps]
      'wintimeofday'       - Current time of day converted to file time (unit64)[Windows call]
                             units: 100 nsec since 01-Jan-1601 (UTC)
      'clocks_per_sec'     - clock() speed in cycles/sec [CLOCKS_PER_SEC]
     
    Choose second and third arguments from:
      'cpuspeed', double num             - Current CPU cycles/sec (double) [MathWorks - num iterations]
      'setcpuspeed_tictoc', double speed - Set the CPU cycles/sec [Used by tic/toc]
       uint64 arg2, uint64 arg3          - uint64 difference = arg2 - arg3 (uint64)
  • feature(‘memtic’), feature(‘memtoc’) – possibly related to feature(‘timing’); mentioned in /ja/xlate:5780-5781
  • feature(‘locale’) – see mlint.m, mtree.m, helpmenufcn.m
  • feature(‘DefaultCharacterSet’) – see here
  • feature(‘COM_SafeArraySingleDim’) – explained here and here.
  • feature(‘COM_ActxProgidCheck’,flag) – see /help/techdoc/helpsearch/_533.cfs
  • feature(‘FigureTools’) – see domymenu.m
  • feature(‘TimeSeriesTools’,1) – see /help/techdoc/helpsearch/_533.cfs
  • feature(‘launch_activation’, ‘forcecheck’) – see StudentActivationStatus.m
  • feature(‘EightyColumns’,flag) – see matlabrc.m
  • feature(‘GetSharedLibExt’) – see loadlibrary.m and /toolbox/matlab/audiovideo/private/privateMMReaderPluginSearch.m
  • feature(‘GetDefaultPrinter’) – see printdlg.m, printopt.m
  • feature(‘GetPrinterInfo’) – see pagesetupdlg.m
  • feature(‘GetPrinterColor’) – see /toolbox/matlab/graphics/private/defaultprtcolor.m
  • feature(‘GetSpecifiedPrinterPort’,printerName) – see /toolbox/matlab/graphics/private/send.m
  • feature(‘ShowFigureWindows’) – see printjob.m, printtables.m, /toolbox/matlab/graphics/private/warnfiguredialog.m
  • feature(‘SearchUDDClassesForHelp’) – see /toolbox/matlab/helptools/+helpUtils/@HelpProcess/getHelpText.m
  • feature(‘AutomationServer’) – see notebook.m, enableservice.m = enableservice(‘AutomationServer’, true)
  • feature(‘EnableDDE’,flag) – see enableservice.m = enableservice(‘DDEServer’, true)
  • feature(‘GetUserWorkFolder’) – see userpath.m, savepath.m
  • feature(‘DirsAddedFreeze’), feature(‘DirsAddedUnfreeze’) – see addpath.m
  • feature(‘ToolboxFreeze’), feature(‘ToolboxUnfreeze’) – explained here
  • feature(‘DirChangeHandleWarn’) – accepts ‘always’, ‘once’, ‘never’ or ’status’. Mentioned in an official Matlab technical solution and also in changeNotificationAdvanced.m.
  • feature(‘DirReloadMsg’) – accepts ‘on’, ‘off’ or ’status’. See changeNotificationAdvanced.m and here.
  • feature(‘RemoteCWDPolicy’) – accepts ‘Reload’, ‘TimecheckDir’, ‘TimecheckDirFile’, ‘TimecheckFile, ‘None’ or ’status’. See changeNotification.m and here.
  • feature(‘RemotePathPolicy’) – accepts ‘Reload’, ‘TimecheckDir’, ‘TimecheckDirFile’, ‘TimecheckFile, ‘None’ or ’status’. See changeNotification.m, here and this official technical solution.
  • feature(‘GetPref’,prefName) – returns the system preference value for the requested preference name in the global prefs file ([prefdir,'/matlab.prf']) that is explained here.
  • feature(‘IsDebugMode’) – mentioned here and several other online places
  • feature(‘ForceFramesOnBottom’) – mentioned here

Oddly, some features are only accessible via system_dependent, and not via feature:

  • system_dependent(‘builtinEditor’,flag) – see matlabrc.m
  • system_dependent(‘miedit’,filename) – referenced here, here and in edit.m. See matlabrc.m.
  • system_dependent(4,…) – See cedit.m, arrayviewfunc.m, dbmex.m, mexdebug.m. In addition to 4, I have seen references to features #2, 7-14, 44, 45, 1000-1003.
  • system_dependent(12,flag) – See %matlabroot%\notebook\pc\M-BOOK.DOT macro InitFromSavedSettings.

The following are OpenGL-related features that are used in the opengl.m function:

  • feature(‘OpenglMode’)
  • feature(‘OpenGLLoadStatus’)
  • feature(‘UseMesaSoftwareOpenGL’,1)- unix only
  • feature(‘UseGenericOpengl’,1)
  • feature(‘GetOpenglInfo’) = opengl(‘info’)
  • feature(‘GetOpenglData’) = opengl(‘data’)
  • feature(‘OpenGLVerbose’,1)

If you lasted this far you deserve a special treat: Last but not least we have feature(‘dwim’). Unfortunately, this feature sometimes fails on some systems…

Have you discovered or used any interesting feature? If so, please do share them in the comments section below

JMI – Java-to-Matlab Interface

Wednesday, April 14th, 2010

I would like to welcome guest writer Joshua Kaplan, an expert in one of the darkest undocumented corners of Matlab – that of the Java-to-Matlab interface (JMI). Today, Joshua will introduce JMI and its core functionality. Later articles will explore additional aspects of this complex technology.

As you’ve seen many times on this blog before, Matlab can easily call Java. This article explores the dark undocumented territory known as JMI (Java Matlab Interface) that enables calling Matlab from Java. This interface takes the form of a file called jmi.jar that comes with every copy of Matlab released in the past decade. JAR files are essentially a zip file containing Java class files. In this case, several Java classes in jmi.jar enable interaction with Matlab. This post will discuss the most important class: com.mathworks.jmi.Matlab.

Matlab’s dynamic evaluation functions

JMI easily allows calling two built-in Matlab functions: eval and feval. Essentially, eval evaluates any string typed into Matlab’s Command Window, and feval allows calling any function by name and passing in arguments. For example:

>> sqrt(5)
ans =
    2.2361
>> eval('sqrt(5)')
ans =
    2.2361
>> feval('sqrt',5)
ans =
    2.2361

The first approach takes the square root of 5 normally by directly calling Matlab’s square root function sqrt. JMI does not enable this direct-invocation approach. Instead, JMI uses the second approach, where eval mimics the first call by evaluating the entire expression inside single quotes. The third option, also used by JMI, is to use feval where the function and arguments are specified separately. While in the above example calling eval and feval is very similar, there are differences. For instance, assignment can be done as x=5 or eval(‘x=5’) but there is no feval equivalent. There are also other eval relatives, such as hgfeval, evalc and evalin, which will not be explained today.

Before we explore com.mathworks.jmi.Matlab, it is important to note a few things: Everything that follows is based on many hours of experimentation and online research and so while I am more or less certain of what I am about to explain, it could be deficient or incorrect in many respects. In fact, this area is so undocumented that an article written in 2002 by one of The MathWorks employees and published in the official newsletter, has been removed from their website a year or two ago.

Secondly, this post is written to satisfy people’s curiosities regarding JMI. If you actually wish to call Matlab from Java, I strongly suggest you use MatlabControl, a user-friendly Java library I have written that wraps JMI. There are many complications that arise with threading, method completion blocking, virtual machine restrictions, and other domains that prevent using JMI directly to be practical and reliable.

com.mathworks.jmi.Matlab class and its mtEval() method

With all of that said, let’s dive in! In the Matlab Command Window type:

methodsview('com.mathworks.jmi.Matlab')

You will see all of the Matlab class’s numerous methods. Many of the methods have extremely similar names; many others have the same names and just different parameters. In order to call eval and feval we are going to use two of Matlab’s methods:

public static Object mtEval(String command, int returnCount)
public static Object mtFeval(String functionName, Object[] args, int returnCount)

Since Matlab can call Java, we can experiment with these methods from Matlab. That’s right, we’re about to use Matlab to call Java to call Matlab!

First, let’s import the Java package that contains the Matlab class, to reduce typing:

import com.mathworks.jmi.*

Now let’s take the square root of 5 like we did above, but this time from Java. Using JMI’s eval-equivalent:

Matlab.mtEval('sqrt(5)',1)

Here, ’sqrt(5)’ is what will be passed to eval, and 1 signifies that Matlab should expect one value to be returned. It is important that the second argument be accurate. If instead the call had been:

Matlab.mtEval('sqrt(5)',0)

Then an empty string (”) will be returned. If instead, 2 or more were passed in:

Matlab.mtEval('sqrt(5)',2)

Then a Java exception like the one below will occur:

??? Java exception occurred:
com.mathworks.jmi.MatlabException: Error using ==> sqrt
Too many output arguments.
    at com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Native Method)
    at com.mathworks.jmi.NativeMatlab.sendMatlabMessage(NativeMatlab.java:212)
    at com.mathworks.jmi.MatlabLooper.sendMatlabMessage(MatlabLooper.java:121)
    at com.mathworks.jmi.Matlab.mtFeval(Matlab.java:1478)
    at com.mathworks.jmi.Matlab.mtEval(Matlab.java:1439)

Looking at this exception’s stack trace we notice that mtEval() is actually internally calling mtFeval().

com.mathworks.jmi.Matlab class’s mtFeval() method

Now to perform the square root using JMI’s feval-equivalent:

Matlab.mtFeval('sqrt',5,1)

Here, ’sqrt’ is the name of the Matlab function to be called, 5 is the argument to the function, and 1 is the expected number of return values. Again, the number of return values. If this number is specified as 0 instead of 1, the function call will still succeed, although not all of the results will necessarily be returned. The second mtFeval() argument, which specifies the arguments to the invoked Matlab function, can take any number of arguments as an array. Therefore the following is acceptable:

Matlab.mtFeval('sqrt',[5 3],1)

This will return an array containing both of their square roots. Note that although two vales are returned, they are considered as only 1 since it is a single array that is returned.

Multiple Matlab arguments can be specified in mtFeval() using a cell array. For example, consider the following equivalent formats (note the different returned array orientation):

>> min(1:4,2)
ans =
     1     2     2     2
>> Matlab.mtFeval('min',{1:4,2},1)
ans =
     1
     2
     2
     2

As we observed above, mtEval() is really just calling mtFeval(). This works because eval is a function, so feval can call it. An illustration:

Matlab.mtFeval('eval','sqrt(5)',1)

com.mathworks.jmi.Matlab class’s mtFevalConsoleOutput() method

Both mtFeval() and mtEval() have allowed us to interact with Matlab, but the effects are not shown in the Command Window. There is a method that will allow us to do this:

public static Object mtFevalConsoleOutput(String functionName, Object[] args, int returnCount)

mtFevalConsoleOutput() is just liked the mtFeval() command except that its effects will be shown. For instance:

>> Matlab.mtFeval('disp','hi',0);  % no visible output
>> Matlab.mtFevalConsoleOutput('disp','hi',0);
hi

There is no equivalent mtEvalConsoleOutput() method, but that’s not a problem because we have seen that eval can be accomplished using feval:

>> Matlab.mtFevalConsoleOutput('eval','x=5',0);
x =
     5

Other methods in com.mathworks.jmi.Matlab

There are many more eval and feval methods in the Matlab class. Most of these methods’ names begin with eval or feval instead of mtEval and mtFeval. Many of these methods are asynchronous, which means their effect on Matlab can occur after the method call returns. This is often problematic because if one method call creates a variable which is then used by the next call, there is no guarantee that the first call has completed (or even begun) by the time the second call tries to use the new variable. Unlike mtEval() and mtFeval(), these methods are not static, meaning we must have an instance of the Java class Matlab:

>> proxy = Matlab
proxy =
com.mathworks.jmi.Matlab@1faf67f0

Using this instance we will attempt to assign a variable and then retrieve it into a different variable. The result will be a Java exception indicating that ‘a’ does not currently exist:

>> proxy.evalConsoleOutput('a=5'); b = proxy.mtEval('a',1)
??? Java exception occurred:
com.mathworks.jmi.MatlabException: Error using ==> eval
Undefined function or variable 'a'.
    at com.mathworks.jmi.NativeMatlab.SendMatlabMessage(Native Method)
    at com.mathworks.jmi.NativeMatlab.sendMatlabMessage(NativeMatlab.java:212)
    at com.mathworks.jmi.MatlabLooper.sendMatlabMessage(MatlabLooper.java:121)
    at com.mathworks.jmi.Matlab.mtFeval(Matlab.java:1478)
    at com.mathworks.jmi.Matlab.mtEval(Matlab.java:1439)
a =
     5

If you run the above code you are not guaranteed to get that exception because of the nature of asynchronous method calls. However, this inherent unpredictability makes it difficult to perform almost any sequential action. Therefore, it is best to stick to mtEval, mtFeval, and mtFevalConsoleOutput, where this type of exception will be very remote. (They can still occur, about 1 in 100 times, as to why – I’d love to know as well.)

Two particular methods that may come in handy are mtSet() and mtGet(), which are the Java proxies for the Matlab set and get functions – they accept a Matlab handle (a double value) and a property name (a string) and either set the value or return it. Like Matlab, they also accept an array of property names. This can be used to update Matlab HG handles from within Java code, without needing to pass through an intermediary Matlab eval function:

>> Matlab.mtSet(gcf,'Color','b')
>> Matlab.mtGet(gcf,'Color')
ans =
     0
     0
     1
>> Matlab.mtGet(gcf,{'Color','Name'})
ans =
java.lang.Object[]:
    [3x1 double]
    'My figure'

Summary

With just eval and feval, an enormous amount of Matlab’s functionality can be accessed from Java. For instance, this allows for creating sophisticated Java GUIs with Swing and then being able to call Matlab code when the user clicks a button or moves a slider.

My next post will be on using MatlabControl to control Matlab from Java from within Matlab. The following post will discuss doing the same, but from a Java program launched outside of Matlab.

setPrompt – Setting the Matlab Desktop prompt

Monday, January 25th, 2010

A few days ago, a reader emailed me with a challenge to modify the standard matlab Command-Window prompt from “>> ” to some other string, preferably a dynamic prompt with the current timestamp. At first thought this cannot be done: The Command-Window prompts are hard-coded and to the best of my knowledge cannot be modified via properties or system preferences.

So the prompt can (probably) not be modified in advance, but what if it could be modified after being displayed? It is true that my cprintf utility modifies the Command-Window contents in order to display formatted text in a variety of font colors. But this case is different since cprintf runs once synchronously (user-invoked), whereas the prompt appears asynchronously multiple times.

There are two methods of handling multiple asynchronous events in Matlab: setting a callback on the object, and setting a PostSet handle.listener (or schema.listener) on the relevant object property. The first of these methods is a well-known Matlab practice, although we shall see that it uses an undocumented callback and functionality; the PostSet method is entirely undocumented and not well-known and shall be described in some later article. I decided to use the callback method to set the prompt – interested readers can try the PostSet method.

Setting the Command Window’s callback

The solution involved finding the Command-Window reference handle, and setting one of its many callbacks, in our case CaretUpdateCallback. This callback is fired whenever the desktop text is modified, which is an event we trap to replace the displayed prompt:

% Get the reference handle to the Command Window text area
jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
try
  cmdWin = jDesktop.getClient('Command Window');
  jTextArea = cmdWin.getComponent(0).getViewport.getComponent(0);
catch
  commandwindow;
  jTextArea = jDesktop.getMainFrame.getFocusOwner;
end
 
% Instrument the text area's callback
if nargin && ~isempty(newPrompt) && ~strcmp(newPrompt,'>> ')
  set(jTextArea,'CaretUpdateCallback',{@setPromptFcn,newPrompt});
else
  set(jTextArea,'CaretUpdateCallback',[]);
end

Now that we have the Command-Window object callback set, we need to set the logic of prompt replacement – this is done in the internal Matlab function setPromptFcn. Here is its core code:

% Does the displayed text end with the default prompt?
% Note: catch a possible trailing newline
try jTextArea = jTextArea.java;  catch,  end  %#ok
cwText = get(jTextArea,'Text');
pos = strfind(cwText(max(1,end-3):end),'>> ');
if ~isempty(pos)
  % Short prompts need to be space-padded
  newLen = jTextArea.getCaretPosition;
  if length(newPrompt)<3
    newPrompt(end+1:3) = ' ';
  elseif length(newPrompt)>3
    fprintfStr = newPrompt(1:end-3);
    fprintf(fprintfStr);
    newLen = newLen + length(fprintfStr);
  end
 
  % The Command-Window text should be modified on the EDT
  awtinvoke(jTextArea,'replaceRange(Ljava.lang.String;II)',...
            newPrompt(end-2:end), newLen-3, newLen);
  awtinvoke(jTextArea,'repaint()');
end

In this code snippet, note that we space-pad prompt string that are shorter than 3 characters: this is done to prevent an internal-Matlab mixup when displaying additional text – Matlab “knows” the Command-Window’s text position and it gets mixed up if it turns out to be shorter than expected.

Also note that I use the semi-documented awtinvoke function to replace the default prompt (and an automatically-appended space) on the Event-Dispatch Thread (more on this in a future article). Since Matlab R2008a, I could use the more convenient javaMethodEDT function, but I wanted my code to work on all prior Matlab 7 versions, where javaMethodEDT was not yet available.

Preventing callback re-entry

The callback snippet above would enter an endless loop if not changed: whenever the prompt is modified the callback would have been re-fired, the prompt re-modified and so on endlessly. There are many methods of preventing callback re-entry – here’s the one I chose:

function setPromptFcn(jTextArea,eventData,newPrompt)
 
  % Prevent overlapping reentry due to prompt replacement
  persistent inProgress
  if isempty(inProgress)
    inProgress = 1;  %#ok unused
  else
    return;
  end
 
  try
    % *** Prompt modification code goes here ***
 
    % force prompt-change callback to fizzle-out...
    pause(0.02);
  catch
    % Never mind - ignore errors...
  end
 
  % Enable new callbacks now that the prompt has been modified
  inProgress = [];
 
end  % setPromptFcn

Handling multiple prompt types

I now wanted my function to handle both static prompt strings (like: ‘[Yair] ‘) and dynamic prompts (like: ‘[25-Jan-2010 01:00:51] ‘). This is done by accepting string-evaluable strings/functions:

% Try to evaluate the new prompt as a function
try
  origNewPrompt = newPrompt;
  newPrompt = feval(newPrompt);
catch
  try
    newPrompt = eval(newPrompt);
  catch
    % Never mind - probably a string...
  end
end
if ~ischar(newPrompt) && ischar(origNewPrompt)
  newPrompt = origNewPrompt;
end

File Exchange submission

I then added some edge-case error handling and wrapped everything in a single utility called setPrompt that is now available on the File Exchange.

In the future, if I find time, energy and interest, maybe I’ll combine cprintf’s font-styling capabilities, to enable setting colored prompts.

Setting a continuously-updated timestamp prompt

Using the code above, we can now display a dynamic timestamp prompt, as follows:

setPrompt usage examples

setPrompt usage examples

However, the displayed timestamp is somewhat problematic in the sense that it indicates the time of prompt creation rather than the time that the associated Command-Window command was executed. In the screenshot above, [25-Jan-2010 01:29:42] is the time that the 234 command was executed, not the time that the setPrompt command was executed. This is somewhat misleading. It would be better if the last (current) timestamp was continuously updated and would therefore always display the latest command’s execution time. This can be done using a Matlab timer as follows:

% This is entered in the main function before setting the prompt:
stopPromptTimers;
if nargin && strcmpi(newPrompt,'timestamp')
  % Update initial prompt & prepare a timer to continuously update it
  newPrompt = @()(['[',datestr(now),'] ']);
  start(timer('Tag','setPromptTimer', 'Name','setPromptTimer', ...
              'ExecutionMode','fixedDelay', 'ObjectVisibility','off', ...
              'Period',0.99, 'StartDelay',0.5, ...
              'TimerFcn',{@setPromptTimerFcn,jTextArea}));
end
 
% Stop & delete any existing prompt timer(s)
function stopPromptTimers
  try
    timers = timerfindall('tag','setPromptTimer');
    if ~isempty(timers)
      stop(timers);
      delete(timers);
    end
  catch
    % Never mind...
  end
end  % stopPromptTimers
 
% Internal timer callback function
function setPromptTimerFcn(timerObj,eventData,jTextArea)
  try
    try jTextArea = jTextArea.java;  catch,  end  %#ok
    pos = getappdata(jTextArea,'setPromptPos');
    newPrompt = datestr(now);
    awtinvoke(jTextArea,'replaceRange(Ljava.lang.String;II)',...
              newPrompt, pos, pos+length(newPrompt));
    awtinvoke(jTextArea,'repaint()');
  catch
    % Never mind...
  end
end  % setPromptTimerFcn

Can you come up with some innovative prompts? If so, please share them in a comment below.

Update 2010-Jan-26: The code in this article was updated since it was first published yesterday.

Rich Matlab editbox contents

Wednesday, January 20th, 2010

In an earlier post, I mentioned that most Matlab uicontrols support HTML strings. Unfortunately, HTML is not supported in multi-line editbox contents. Today I will show how this limitation can be removed for a multi-line editbox, thereby enabling rich contents (enabling HTML for a single-line editbox needs a different solution).

We first need to get the editbox’s underlying Java object, as explained in my previous article about the findjobj utility. Since a multi-line editbox is contained within a scroll-pane, we need to dig within the scrollpane container to find the actual editable area object:

% Create a multi-line (Max>1) editbox uicontrol
hEditbox = uicontrol('style','edit', 'max',5, ...);
 
% Get the Java scroll-pane container reference
jScrollPane = findjobj(hEditbox);
 
% List the scroll-pane's contents:
>> jScrollPane.list
com.mathworks.hg.peer.utils.UIScrollPane[,0,0,100x50,...]
 javax.swing.JViewport[,1,1,81x48,...]
  com.mathworks.hg.peer.EditTextPeer$hgTextEditMultiline[,0,0,81x48,...,kit=javax.swing.text.StyledEditorKit@ce05fc,...]
 com.mathworks.hg.peer.utils.UIScrollPane$1[,82,1,17x48,...]
  com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[,0,31,17x17,...]
  com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[,0,0,17x17,...]
 com.mathworks.hg.peer.utils.UIScrollPane$2[,0,0,0x0,...]
  com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[,0,0,0x0,...]
  com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[,0,0,0x0,...]

In this listing, we see that jScrollPane contains a JViewport and two scrollbars (horizontal and vertical), as expected from standard Java scroll-panes. We need the internal hgTextEditMultiline object:

jViewPort = jScrollPane.getViewport;
jEditbox = jViewPort.getComponent(0);

The retrieved jEditbox reference, is an object of class com.mathworks.hg.peer.EditTextPeer$hgTextEditMultiline, which indirectly extends the standard javax.swing.JTextPane. The default Matlab implementation of the editbox uicontrol simply enables a multi-line vertical-scrollable text area using the system font. However, the underlying JTextPane object enables many important customizations, including the ability to specify different font attributes (size/color/bold/italic etc.) and paragraph attributes (alignment etc.) for text segments (called style runs) and the ability to embed images, HTML and other controls.

Setting rich contents can be done in several alternative ways. From easiest to hardest:

Setting page URL

Use the setPage(url) method to load a text page from the specified URL (any pre-existing editbox content will be erased). The page contents may be plain text, HTML or RTF. The content type will automatically be determined and the relevant StyledEditorKit and StyledDocument will be chosen for that content. Additional StyledEditorKit content parsers can be registered to handle additional content types. Here’s an example loading an HTML page:

jEditbox.setPage('http://tinyurl.com/c27zpt');

where the URL’s contents are:

<html><body>
<img src="images/dukeWaveRed.gif" width="64" height="64">
This is an uneditable <code>JEditorPane</code>, which was
<em>initialized</em> with <strong>HTML</strong> text 
<font size=-2>from</font> a <font size=+2">URL</font>.
<p>An editor pane uses specialized editor kits to read, write,
display, and edit text of different formats. The Swing text 
package includes editor kits for plain text, HTML, and RTF. 
You can also develop custom editor kits for other formats. 
<script language="JavaScript" 
  src="/js/omi/jsc/s_code_remote.js"></script>
</body></html>

Matlab editbox initialized from an HTML webpage URL

Matlab editbox initialized from an HTML webpage URL

Setting the EditorKit and ContentType

Set the requested StyledEditorKit (via setEditorKit()) or ContentType properties and then use setText() to set the text, which should be of the appropriate content type. Note that setting EditorKit or ContentType clears any existing text and left-aligns the contents (hgTextEditMultiline is center aligned by default). Also note that HTML <div>s get their own separate lines and that <html> and <body> opening and closing tags are accepted but unnecessary. For example:

jEditbox.setEditorKit(javax.swing.text.html.HTMLEditorKit);
% alternative: jEditbox.setContentType('text/html');
htmlStr = ['<b><div style="font-family:impact;color:green">'...
           'Matlab</div></b> GUI is <i>' ...
           '<font color="red">highly</font></i> customizable'];
jEditbox.setText(htmlStr)

HTML contents in a Matlab editbox

HTML contents in a Matlab editbox

Let’s show another usage example, of an event log file, spiced with icons and colored text based on event severity. First, define the logging utility function (the icon filenames may need to be changed based on your Matlab release):

function logMessage(jEditbox,text,severity)
   % Ensure we have an HTML-ready editbox
   HTMLclassname = 'javax.swing.text.html.HTMLEditorKit';
   if ~isa(jEditbox.getEditorKit,HTMLclassname)
      jEditbox.setContentType('text/html');
   end
 
   % Parse the severity and prepare the HTML message segment
   if nargin<3,  severity='info';  end
   switch lower(severity(1))
      case 'i',  icon = 'greenarrowicon.gif'; color='gray';
      case 'w',  icon = 'demoicon.gif';       color='black';
      otherwise, icon = 'warning.gif';        color='red';
   end
   icon = fullfile(matlabroot,'toolbox/matlab/icons',icon);
   iconTxt =['<img src="file:///',icon,'" height=16 width=16>'];
   msgTxt = ['&nbsp;<font color=',color,'>',text,'</font>'];
   newText = [iconTxt,msgTxt];
   endPosition = jEditbox.getDocument.getLength;
   if endPosition>0, newText=['<br/>' newText];  end
 
   % Place the HTML message segment at the bottom of the editbox
   currentHTML = char(jEditbox.getText);
   jEditbox.setText(strrep(currentHTML,'</body>',newText));
   endPosition = jEditbox.getDocument.getLength;
   jEditbox.setCaretPosition(endPosition); % end of content
end

Now, let’s use this logging utility function to log some messages:

logMessage(jEditbox, 'a regular info message...');
logMessage(jEditbox, 'a warning message...', 'warn');
logMessage(jEditbox, 'an error message!!!', 'error');
logMessage(jEditbox, 'a regular message again...', 'info');

Rich editbox contents (a log file)

Rich editbox contents (a log file)

HTML editboxes are normally editable, images included. In actual applications, we may wish to prevent editing the display log. To do this, simply call jEditbox.setEditable(false).

Setting a hyperlink handler is easy: first we need to ensure that we’re using an HTML content-type document. Next, set the editbox to be uneditable (hyperlinks display correctly when the editbox is editable, but are unclickable), using jEditbox.setEditable(false). Finally, set the callback function in the editbox’s HyperlinkUpdateCallback property:

jEditbox.setContentType('text/html');
jEditbox.setText('link: <a href= "http://UndocumentedMatlab.com">UndocumentedMatlab.com</a>');
jEditbox.setEditable(false);
hjEditbox = handle(jEditbox,'CallbackProperties');
set(hjEditbox,'HyperlinkUpdateCallback',@linkCallbackFcn);
 
function linkCallbackFcn(src,eventData)
   url = eventData.getURL;      % a java.net.URL object
   description = eventData.getDescription; % URL string
   jEditbox = eventData.getSource;
   switch char(eventData.getEventType)
      case char(eventData.getEventType.ENTERED)
               disp('link hover enter');
      case char(eventData.getEventType.EXITED)
               disp('link hover exit');
      case char(eventData.getEventType.ACTIVATED)
               jEditbox.setPage(url);
   end
end

Hyperlink in editbox

Hyperlink in editbox

Setting the style runs programmatically

Setting the styles programmatically, one style run after another, can be done via the text-pane’s Document property object. Individual character ranges can be set using the Document’s setCharacterAttributes method, or entire style runs can be inserted via insertString. Attributes are updated using the static methods available in javax.swing.text.StyleConstants. These methods include setting character attributes (font/size/bold/italic/strike-through/underline/subscript/superscript and foreground/background colors), paragraph attributes (indentation/spacing/tab-stops/bidi), image icons and any Swing Component (buttons etc.). Here is the end result:

Rich editbox contents: images, controls & font styles

Rich editbox contents: images, controls & font styles

Note that if a styled multi-line editbox is converted to a single-line editbox (by setting hEditbox’s Max property to 1), it loses all style information, embedded images and components. Returning to multi-line mode will therefore show only the plain-text.