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

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

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

draggableDataTips utility in action

draggableDataTips utility in action


Technical implementation

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

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

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

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

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

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

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

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

Notes:

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

HG2

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

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

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

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

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

]]>
https://undocumentedmatlab.com/blog_old/draggable-plot-data-tips/feed 6
Extending a Java class with UDDhttps://undocumentedmatlab.com/blog_old/extending-a-java-class-with-udd https://undocumentedmatlab.com/blog_old/extending-a-java-class-with-udd#comments Thu, 29 Mar 2012 14:32:46 +0000 https://undocumentedmatlab.com/?p=2824 Related posts:
  1. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
  2. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
  3. UDD Events and Listeners UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...
  4. Matlab and the Event Dispatch Thread (EDT) The Java Swing Event Dispatch Thread (EDT) is very important for Matlab GUI timings. This article explains the potential pitfalls and their avoidance using undocumented Matlab functionality....
]]>
Once again I welcome Donn Shull, with another article about Matlab’s internal UDD mechanism

Extending a Java class with UDD

During the series on UDD, we have mentioned the connection between UDD and Java. In UDD Events and Listeners we described how in Matlab, each Java object can have a UDD companion. In Hierarchical Systems with UDD we briefly noted that a UDD hierarchy may be passed to Java. In the numerous posts on handle graphics and callbacks, Yair has discussed the UDD packages javahandle and javahandle_withcallbacks. Based on this information, it seems reasonable to speculate that it may be possible to extend a Java class with UDD using UDD’s class inheritance mechanism.

This can be extremely useful in two cases:

  • You don’t know Java but found a Java class you would like to use in Matlab, it just needs minor modifications for your specific needs
  • You do know Java, but don’t have access to the original source code, and choose to extend the Java class with Matlab code, rather than Java code

Today I will show how this can be done using a simple example. Our example will illustrate the following things:

  1. Subclassing a Java class with UDD
  2. Adding UDD properties to the to the subclass
  3. Overloading a Java method with Matlab code
  4. Directly accessing the superclass methods

The example will show extending Java socket classes to provide a simple method for communication between two Matlab sessions. The protocol has been kept purposely simple and is not robust. Additional work would need to be done to create a real-life socket-based communication between Matlab systems (see for example this FEX submission).

Today’s example consists of two subclasses: a subclass of java.net.ServerSocket and a subclass of java.net.Socket. The protocol will be sending strings back and forth between the two sessions. In each direction the information exchange will consist of two bytes containing the string length, followed by the actual string. The entire source code can be downloaded from here.

Creating the simple.ServerSocket class

As in the UDD series, we will use the simple package for our classes and in this package create a ServerSocket class and a Socket class. Recall the simple package definition class is placed in a file named schema.m in a directory called @simple, placed somewhere on the Matlab path. schema.m consists of:

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

In our ServerSocket class we will add three UDD properties and overload two of the Java class methods. It is worth noting that our final class will have all the parent Java classes public properties and methods and if necessary we can access the parent or super class methods directly. As before, we create a subfolder of the @simple folder named @ServerSocket; in this folder we place four files:

  1. schema.m – the class definition file
  2. ServerSocket.m – the class constructor
  3. accept.m – one of the Java methods that we will overload
  4. bind.m – the other Java method that we will overload

At the beginning of our schema.m file, we will use the following code to subclass the Java class:

function schema
%SCHEMA simple.ServerSocket class definition function.
 
    % parent schema.class definition
    javaPackage = findpackage('javahandle');
    javaClass = findclass(javaPackage, 'java.net.ServerSocket');
 
    % class package (schema.package)
    simplePackage = findpackage('simple');
 
    % class definition
    simpleClass = schema.class(simplePackage, 'ServerSocket', javaClass);

Here, we use findpackage and findclass to obtain the schema.class for the Java class that we are going to use as our parent. We then obtain a handle to the containing package, and finally use the subclass variation to define our ServerSocket as a variation of the Java parent’s schema.class.

Next, in the class definition file we place the code to define the signatures for the methods we are overloading:

    % accept.m overloads java accept method and adds communication protocol
    m = schema.method(simpleClass, 'accept');
    s = m.Signature;
    s.varargin    = 'off';
    s.InputTypes  = {'handle'};
    s.OutputTypes = {'string'};
 
    % bind.m overloads java bind method
    m = schema.method(simpleClass, 'bind');
    s = m.Signature;
    s.varargin    = 'off';
    s.InputTypes  = {'handle'};
    s.OutputTypes = {};be

Finally, we add three UDD properties to the class: The first will be used to hold a string representation of the address of our ServerSocket; the second will store the communication port number; the third is a handle property that will hold the reference to the socket used by the actual communication.

    % holds remote address as a matlab string
    p = schema.prop(simpleClass, 'address', 'string');
    p.FactoryValue = 'localhost';
 
    % holds remote port as a matlab int
    p = schema.prop(simpleClass, 'port', 'int16');
    p.FactoryValue = 2222;
 
    % holds a handle reference to the socket created in the accept method
    p = schema.prop(simpleClass, 'socket', 'handle');
end

We now need to write our overloaded methods. The bind method is simple: it first creates a Java internet address using the new address and port properties; then it uses the standard Java class methods to call the superclass’s bind method with the specified internet address:

function bind(this)
    % use the object socket and port port properties to bind this instance
    % to a address calling the superclass bind method
    inetAddress = java.net.InetSocketAddress(this.address, this.port);
    this.java.bind(inetAddress);
end

The overloaded accept method is a bit more complicated and crude: It starts by calling the superclass accept method to create a communication socket and stores the created socket in our class’s socket property. Then it goes into an infinite loop of waiting for incoming commands, uses evalc to execute them, and returns the captured result to the caller. The only way out of this loop is using Ctrl-C from the keyboard.

function accept(this)
 
    % use the superclass accept
    this.socket = handle(this.java.accept);
 
    % infinite loop use ctrl-c to exit
    while 1
        % wait for a command then execute it capturing output
        while this.socket.getInputStream.available < 2
        end
 
        msb = this.socket.getInputStream.read;
        lsb = this.socket.getInputStream.read;
 
        numChar = 256 * msb + lsb;
        cmd = uint8(zeros(1, numChar));
 
        for index = 1:numChar
            cmd(index) = this.socket.getInputStream.read;
        end
        result = evalc(char(cmd));
 
        % send the result back to the calling system
        len = numel(result);
        msb = uint8(floor(len/256));
        lsb = uint8(mod(len,256));
 
        this.socket.getOutputStream.write(uint8([msb, lsb, result]));
    end
end

Creating the simple.Socket class

The simple.Socket class is created like ServerSocket, this time in the @Socket folder under the @simple folder. In this subclass we add properties for the address and port, just as in ServerSocket. We overload the superclass’s connect method with our own variant, and add a new method to make the remote calls to the ServerSocket running in another Matlab instance. Beginning with the schema.m file we have:

function schema
%SCHEMA simple.Socket class definition function.
 
    % package definition
    simplePackage = findpackage('simple');
    javaPackage = findpackage('javahandle');
    javaClass = findclass(javaPackage, 'java.net.Socket');
 
    % class definition
    simpleClass = schema.class(simplePackage, 'Socket', javaClass);
 
    % define class methods
    % connect.m overloads java connect method
    m = schema.method(simpleClass, 'connect');
    s = m.Signature;
    s.varargin    = 'off';
    s.InputTypes  = {'handle'};
    s.OutputTypes = {};
 
    % remoteEval.m matlab method for remote evaluation of Matlab commands
    m = schema.method(simpleClass, 'remoteEval');
    s = m.Signature;
    s.varargin    = 'off';
    s.InputTypes  = {'handle', 'string'};
    s.OutputTypes = {'string'};
 
    % add properties to this class
    % holds remote address as a Matlab string
    p = schema.prop(simpleClass, 'address', 'string');
    p.FactoryValue = 'localhost';
 
    % holds remote port as a Matlab int
    p = schema.prop(simpleClass, 'port', 'int16');
    p.FactoryValue = 2222;
end

The class constructor Socket.m is simply:

function skt = Socket
%SOCKET constructor for the simple.Socket class
    skt = simple.Socket;
end

The overloaded connect method is almost identical to the overloaded bind method we used for ServerSocket. We form a Java internet address from our new properties and then invoke the superclass’s connect Java method:

function connect(this)
%CONNECT overload of the java.net.Socket connect method
    % use the object address and port properties to connect to the remote
    % session via the superclass connect method
    inetAddress = java.net.InetSocketAddress(this.address, this.port);
    this.java.connect(inetAddress);
end

Finally, our remoteEval method is very similar to the loop portion of the overloaded accept method we wrote for simple.ServerSocket. We take the command string input and convert it into a series of bytes prepended by the length of the string, send it to the other Matlab session and wait for a response:

function result = remoteEval(this, cmd)
%REMOTEEVAL evaluate a Matlab command on a remotely connected Matlab
 
    % The command string is sent as a series of bytes preceded by a pair of
    % bytes which represents the length of the string  
    cmd = uint8(cmd);
 
    len = numel(cmd);
    msb = uint8(floor(len/256));
    lsb = uint8(mod(len,256));
 
    this.getOutputStream.write([msb, lsb, cmd]);
 
    % We will expect the remote session to return a string in the same format
    % as the command
    while this.getInputStream.available < 2
    end
 
    msb = this.getInputStream.read;
    lsb = this.getInputStream.read;
 
    numChar = 256 * msb + lsb;
 
    result = uint8(zeros(1, numChar));
    for index = 1:numChar
        result(index) = this.getInputStream.read;
    end
    result = char(result);
end

Using simple.ServerSocket and simple.Socket to communicate between Matlab sessions

To use this example, add the zip contents to your Matlab path, then open an instance of Matlab and issue the following commands:

>> ss = simple.ServerSocket;
>> ss.bind;
>> ss.accept;

Then open another Matlab instance and issue these commands:

>> s = simple.Socket;
>> s.connect;

At this point you can send commands from this Matlab instance (the client) to the first instance (the server) using the remoteEval method. The command will then be transmitted to the server, executed, and the server will return the captured string result to the client:

>> remoteResult = s.remoteEval('pi')
remoteResult =
    3.1416

The defaults are for localhost and port 2222. These can be changed prior to using the server’s bind method and the client’s connect method. To keep things as simple as possible, error checking etc. has been left out, so this is just a demonstration and is far from robust.

There are some things to note about our new classes. If we type methods(s) or s.methods at the Matlab command prompt in our simple.Socket session we obtain:

>> s.methods
 
Methods for class simple.Socket:
 
Socket                     getOOBInline               isClosed                   setReuseAddress            
bind                       getOutputStream            isConnected                setSendBufferSize          
close                      getPort                    isInputShutdown            setSoLinger                
connect                    getReceiveBufferSize       isOutputShutdown           setSoTimeout               
equals                     getRemoteSocketAddress     java                       setSocketImplFactory       
getChannel                 getReuseAddress            notify                     setTcpNoDelay              
getClass                   getSendBufferSize          notifyAll                  setTrafficClass            
getInetAddress             getSoLinger                remoteEval                 shutdownInput              
getInputStream             getSoTimeout               sendUrgentData             shutdownOutput             
getKeepAlive               getTcpNoDelay              setKeepAlive               toString                   
getLocalAddress            getTrafficClass            setOOBInline               wait                       
getLocalPort               hashCode                   setPerformancePreferences  
getLocalSocketAddress      isBound                    setReceiveBufferSize

This shows that our simple.Socket class has all of the methods of the Java superclass, plus our added remoteEval method and the java method that was automatically added by Matlab. This means that all of the Java methods are methods of our class instance and the added java means that we can access the superclass methods from our class instance if the need arises. If we use the struct function which Yair has previously discussed, we obtain:

>> struct(s)
ans = 
              OOBInline: 0
                  Bound: 1
                Channel: []
                  Class: [1x1 java.lang.Class]
                 Closed: 0
              Connected: 1
            InetAddress: [1x1 java.net.Inet4Address]
          InputShutdown: 0
            InputStream: [1x1 java.net.SocketInputStream]
              KeepAlive: 0
           LocalAddress: [1x1 java.net.Inet4Address]
              LocalPort: 51269
     LocalSocketAddress: [1x1 java.net.InetSocketAddress]
         OutputShutdown: 0
           OutputStream: [1x1 java.net.SocketOutputStream]
      ReceiveBufferSize: 8192
    RemoteSocketAddress: [1x1 java.net.InetSocketAddress]
           ReuseAddress: 0
         SendBufferSize: 8192
               SoLinger: -1
              SoTimeout: 0
             TcpNoDelay: 0
           TrafficClass: 0
                address: 'localhost'
                   port: 2222

We see that we have access to all of the public properties of the Java superclass, as well as the UDD properties that we have added.

Conclusion

At the beginning of this post I said that this would be a simple non-robust communications method. In order to make this anything more than that, a number of things would need to be implemented, for example:

  • Improve the accept method to exit after a timeout or when a connection has been made and then terminated
  • Add checksums and timeouts for communication to determine the reliability of the communication
  • Add a retry request protocol for instances of communication failure
  • Add support for any serializable Matlab type, not just strings

The intent here was just to show that extending Java classes with Matlab is possible, relatively simple, and can be extremely useful. After all, with over 10 million Java developers out there, chances are that somebody somewhere has already posted a Java class that answers your exact need, or at least close enough that it can be used in Matlab with only some small modifications.

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

Creating a new UDD package

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

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

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

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

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

Creating a new UDD class

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

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

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

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

Defining class methods

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

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

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

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

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

And the dialog method (in dialog.m):

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

Testing our new class

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

a = simple.object

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

UDD simple class GUI

UDD simple class GUI

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

a = 
  Name: a
 Value: 1.000000

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

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

Accessing UDD help

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

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

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

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

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

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

Background on UDD

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

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

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

Why should we bother learning UDD?

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

The case against studying UDD classes

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

The case for studying UDD classes

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

Tools for Learning about UDD

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

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

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

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

Exploring some important built-in UDD Classes

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

The schema package

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

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

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

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

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

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

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

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

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

The handle package

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

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

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

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

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

The hg package

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

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

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

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

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

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

]]>
https://undocumentedmatlab.com/blog_old/introduction-to-udd/feed 7
Undocumented cursorbar objecthttps://undocumentedmatlab.com/blog_old/undocumented-cursorbar-object https://undocumentedmatlab.com/blog_old/undocumented-cursorbar-object#comments Wed, 29 Sep 2010 18:00:12 +0000 https://undocumentedmatlab.com/?p=1903 Related posts:
  1. Matlab’s HG2 mechanism HG2 is presumably the next generation of Matlab graphics. This article tries to explore its features....
  2. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
  3. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
  4. Controlling plot data-tips Data-tips are an extremely useful plotting tool that can easily be controlled programmatically....
]]>
Every now and then, I stumble on a Matlab feature that looks interesting and potentially useful and has existed for many previous Matlab releases, yet remains undocumented and unsupported. Today I present one such object, Matlab’s graphics.cursorbar.

The graphics.cursorbar object answers a very basic need that is often encountered in graph exploration: displaying data values together with horizontal/vertical cross-hairs, similarly to ginput.

While Matlab has provided the data-cursor mode for a long time, the cross-hair feature is still missing as of R2010b. Many CSSM newsgroup readers have asked about this missing feature. Some recent examples: here, here, and here.

DataMatrix

To answer this need I have created the DataMatrix utility, which is available on the Matlab File Exchange:

DataMatrix: customizable data tooltip & cross-hairs

DataMatrix: customizable data tooltip & cross-hairs

DataMatrix displays matlab’s standard data-cursor tooltip together with dotted cross-hairs, both of which move with the mouse pointer. DataMatrix is actually based mostly on fully-documented stuff: the undocumented aspects are secondary to the main program flow and mostly just ensure old releases compatibility and correct behavior in the presence of some figure modes.

graphics.cursorbar

When I created DataMatrix in 2007, I had no idea that graphics.cursorbar already existed. graphics.cursorbar is an internal Matlab object, that is undocumented and unsupported. It has several advantages over DataMatrix, being more customizable in the cross-hairs and data marker, although not enabling to customize the tooltip text nor to present both cross-hairs (only horizontal/vertical, not both). It is one of the earliest examples of Matlab’s old class system (schema-based).

We initialize a graphics.cursorbar object by supplying an axes (not very useful) or plot-line handle (more useful). The cursorbar handle can be customized using properties such as BottomMarker, TopMarker, CursorLineColor, CursorLineStyle, CursorLineWidth, TargetMarkerSize, TargetMarkerStyle, ShowText, Orientation, Position (Position is a hidden property) etc., as well as the regular HG properties (UserData, Visibility, Parent etc.).

Once the cursor-bar is created, it can be dragged and moved via the mouse cursor, as the following code snippet and animated gif show:

t=0:.01:7; hp=plot(t,sin(t));
hCursorbar = graphics.cursorbar(hp); drawnow
hCursorbar.CursorLineColor = [.9,.3,.6]; % default=[0,0,0]='k'
hCursorbar.CursorLineStyle = '-.';       % default='-'
hCursorbar.CursorLineWidth = 2.5;        % default=1
hCursorbar.Orientation = 'vertical';     % =default
hCursorbar.TargetMarkerSize = 12;        % default=8
hCursorbar.TargetMarkerStyle = 'o';      % default='s' (square)

Matlab's internal cursorbar object

Matlab's internal cursorbar object

Comments within the internal code (%matlabroot%\toolbox\matlab\graphics\@graphics\@cursorbar\*.m) suggest that graphics.cursorbar has been around since 2003 at least, although I have not checked such old releases. The presented tooltip resembles one of the old data tips, not one of the modern ones. In addition, as far as I can tell, graphics.cursorbar is not used within the Matlab code corpus. For these reasons it would not surprise me at all to find that MathWorks will remove this feature in some near future release. Until then – have fun using it!

Can you find a good use for graphics.cursorbar? if so, please let us know by posting a comment below.

Note: graphics.cursorbar was removed in Matlab release R2014b (8.4), as part of the transition to the new graphics system (HG2). Perhaps one day a replacement functionality will be added. Until then, we can use Michelle Hirsch’s dualcursor utility, or Yaroslav Don’s direct replacement cursorbar (see comment below), which apparently has the official approval of MathWorks and was selected as File Exchange Pick of the Week.

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

Apparently I caused a bit of a stir…

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

UDD

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

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

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

MCOS

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

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

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

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

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

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

HG2

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

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

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

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

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

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

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

]]>
https://undocumentedmatlab.com/blog_old/new-information-on-hg2/feed 1
uiundo – Matlab’s undocumented undo/redo managerhttps://undocumentedmatlab.com/blog_old/uiundo-matlab-undocumented-undo-redo-manager https://undocumentedmatlab.com/blog_old/uiundo-matlab-undocumented-undo-redo-manager#comments Thu, 29 Oct 2009 22:11:11 +0000 https://undocumentedmatlab.com/?p=688 Related posts:
  1. Customizing uiundo This article describes how Matlab's undocumented uiundo undo/redo manager can be customized...
  2. uisplittool & uitogglesplittool Matlab's undocumented uisplittool and uitogglesplittool are powerful controls that can easily be added to Matlab toolbars - this article explains how...
  3. Adding dynamic properties to graphic handles It is easy and very useful to attach dynamic properties to Matlab graphics objects in run-time. ...
  4. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
]]>
Whenever we have a Matlab GUI containing user-modifiable controls (edit boxes, sliders, toggle buttons etc.), we may wish to include an undo/redo feature. This would normally be a painful programming task. Luckily, there is an undocumented built-in Matlab support for this functionality via the uiundo function. Note that uiundo and its functionality is not Java-based but rather uses Matlab’s classes and the similarly-undocumented schema-based object-oriented approach.

A couple of months ago, I explained how to customize the figure toolbar. In that article, I used the undocumented uiundo function as a target for the toolbar customization and promised to explain its functionality later. I would now like to explain uiundo and its usage.

The uiundo function is basically an accessor for Matlab’s built-in undo/redo manager object. It is located in the uitools folder (%MATLABROOT%\toolbox\matlab\uitools) and its @uiundo sub-folder. To use uiundo, simply define within each uicontrol’s callback function (where we normally place our application GUI logic) the name of the undo/redo action, what should be done to undo the action, and what should be done if the user wished to redo the action after undoing it. uiundo then takes care of adding this data to the figure’s undo/redo options under Edit in the main figure menu.

For example, let’s build a simple GUI consisting of a slider that controls the value of an edit box:

hEditbox = uicontrol('style','edit', 'position',[20,60,40,40]); 
set(hEditbox, 'Enable','off', 'string','0');
hSlider = uicontrol('style','slider','userdata',hEditbox);
callbackStr = 'set(get(gcbo,''userdata''),''string'',num2str(get(gcbo,''value'')))';
set(hSlider,'Callback',callbackStr);

Simple GUI with slider update of a numeric value

Simple GUI with slider update of a numeric value

Now, let’s attach undo/redo actions to the slider’s callback. First, place the following in test_uiundo.m:

% Main callback function for slider updates
function test_uiundo(varargin)
 
  % Update the edit box with the new value
  hEditbox = get(gcbo,'userdata');
  newVal = get(gcbo,'value');
  set(hEditbox,'string',num2str(newVal));
 
  % Retrieve and update the stored previous value
  oldVal = getappdata(gcbo,'oldValue');
  if isempty(oldVal),  oldVal=0;  end
  setappdata(gcbo,'oldValue',newVal);
 
  % Prepare an undo/redo action
  cmd.Name = sprintf('slider update (%g to %g)',oldVal,newVal);
 
  % Note: the following is not enough since it only
  %       updates the slider and not the editbox...
  %cmd.Function        = @set;                  % Redo action
  %cmd.Varargin        = {gcbo,'value',newVal};
  %cmd.InverseFunction = @set;                  % Undo action
  %cmd.InverseVarargin = {gcbo,'value',oldVal};
 
  % This takes care of the update problem...
  cmd.Function        = @internal_update;       % Redo action
  cmd.Varargin        = {gcbo,newVal,hEditbox};
  cmd.InverseFunction = @internal_update;       % Undo action
  cmd.InverseVarargin = {gcbo,oldVal,hEditbox};
 
  % Register the undo/redo action with the figure
  uiundo(gcbf,'function',cmd);
end
 
% Internal update function to update slider & editbox
function internal_update(hSlider,newValue,hEditbox)
  set(hSlider,'value',newValue);
  set(hEditbox,'string',num2str(newValue));
end

And now let’s point the slider’s callback to our new function:

>> set(hSlider,'Callback',@test_uiundo);

Undo/redo functionality integrated in the figure

Undo/redo functionality integrated in the figure

We can also invoke the current Undo and Redo actions programmatically, by calling uiundo with the ‘execUndo’ and ‘execRedo’ arguments:

uiundo(hFig,'execUndo');
uiundo(hFig,'execRedo');

When invoking the current Undo and Redo actions programmatically, we can ensure that this action would be invoked only if it is a specific action that is intended:

uiundo(hFig,'execUndo','Save data');  % should equal cmd.Name

We can use this approach to attach programmatic undo/redo actions to new toolbar or GUI buttons. The code for this was given in the above-mentioned article. Here is the end-result:


Undo/redo functionality integrated in the figure toolbar

Undo/redo functionality integrated in the figure toolbar

Undo/redo functionality integrated in the figure toolbar


In my next post, due next week, I will explore advanced customizations of this functionality.

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

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

1. use the desktop’s hidden HideUndocumented property:

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

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

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

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

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

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

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

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

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

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

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

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

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