UIInspect – 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 Getting default HG property valueshttps://undocumentedmatlab.com/blog_old/getting-default-hg-property-values https://undocumentedmatlab.com/blog_old/getting-default-hg-property-values#comments Wed, 13 Feb 2013 18:00:01 +0000 https://undocumentedmatlab.com/?p=3622 Related posts:
  1. Multi-column (grid) legend This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
  2. Undocumented view transformation matrix Matlab's view function returns an undocumented output transformation matrix....
  3. FIG files format FIG files are actually MAT files in disguise. This article explains how this can be useful in Matlab applications....
  4. HG2 update HG2 appears to be nearing release. It is now a stable mature system. ...
]]>
All Matlab’s Handle Graphics (HG) property have default values. These values are used unless we specifically override the property value. For example, in R2012a, Matlab figure handles have 62 documented and 28 undocumented properties, all of which have some default value. When we create a new Matlab figure, we typically override only a handful of these properties.

How Matlab determines an HG property value

How Matlab determines an HG property value

For example, we might override the figure’s Name, NumberTitle, Position, Visible, Colormap and perhaps a few other properties. All the others are either read-only (i.e., un-settable), or left at their default values. This is also true for all HG objects: axes, images, plots, patches, uicontrols, annotations, Java control containers etc.

Matlab makes a distinction between factory and default values. Users can modify the default values, but not the factory values, which makes sense. In essence, user-specified property values override the default values, which in turn override the factory values. I find that this makes the process of using default values quite intuitive. I like this factory/default design.

Matlab has a dedicated doc page explaining how we can use, set and reset the default property values.

Unfortunately, MathWorks has not seen fit to explain how to get the full list of current default defaults, nor how to get the factory values. Today’s article provides the missing manual pages and completes the picture.

Accessing default and factory property values

To access any specific property’s default value, we need to compose a fictitious property name from the string ‘Default’ or ‘Factory’, followed by the object’s type (‘Figure’, ‘Axes’, ‘Line’ etc., as reported by the object’s Type property), and lastly the property name. For example: DefaultFigureColor or FactoryAxesUnits. As with all HG properties, these names are case insensitive. These fictitious properties all belong to Matlab’s root (0) handle.

We can now get and set the values of any of these fictitious properties (naturally, factory properties cannot be set):

>> get(0,'FactoryFigureUnits')
ans =
pixels
 
>> get(0,'FactoryFigureColor')
ans =
     0     0     0
 
>> get(0,'DefaultFigureColor')
ans =
                       0.8                       0.8                       0.8
 
>> set(0,'DefaultFigureColor','y');  % new figures will now have a yellow background color...
 
>> set(0,'DefaultFigureColor','factory');  % resets the default value to the factory value [0,0,0]=black

Note that since the default and factory property names are fictitious (i.e., dynamic properties that are parsed on-the-fly), they do not appear when you get(0), getundoc(0) or even uiinspect(0).

My uiinspect utility reports the factory values in its property-details panel, along with additional meta-data such as whether the properties are settable, readable etc.

uiinspect's 'Other properties' meta-data table

uiinspect's 'Other properties' meta-data table

Getting the full list of factory/default values

To get the long list of factory values, simply get a partial fictitious property name:

>> get(0,'factory')
ans = 
                         factoryFigureAlphamap: [1x64 double]
                       factoryFigureBusyAction: 'queue'
                    factoryFigureButtonDownFcn: ''
                         factoryFigureClipping: 'on'
                  factoryFigureCloseRequestFcn: 'closereq'
                            factoryFigureColor: [0 0 0]
                        (... 655 additional properties ...)
 
>> get(0,'default')
ans = 
               defaultTextColor: [0 0 0]
              defaultAxesXColor: [0 0 0]
              defaultAxesYColor: [0 0 0]
              defaultAxesZColor: [0 0 0]
          defaultPatchFaceColor: [0 0 0]
          defaultPatchEdgeColor: [0 0 0]
               defaultLineColor: [0 0 0]
    defaultFigureInvertHardcopy: 'on'
             defaultFigureColor: [0.8 0.8 0.8]
               defaultAxesColor: [1 1 1]
          defaultAxesColorOrder: [7x3 double]
          defaultFigureColormap: [64x3 double]
        defaultSurfaceEdgeColor: [0 0 0]
         defaultFigurePaperType: 'A4'
        defaultFigurePaperUnits: 'centimeters'
         defaultFigurePaperSize: [20.98404194812 29.67743169791]
          defaultFigurePosition: [200 200 560 420]
 
>> get(0,'DefaultAxes')
ans = 
        defaultAxesXColor: [0 0 0]
        defaultAxesYColor: [0 0 0]
        defaultAxesZColor: [0 0 0]
         defaultAxesColor: [1 1 1]
    defaultAxesColorOrder: [7x3 double]

We can see that the defaults list is much shorter than the factory list. There are very few actual default overrides of the factory values. In fact, if we try to get the default value of a property that was not overridden (e.g., DefaultFigureNumberTitle), Matlab is smart enough to return the factory value (in this case, FactoryFigureNumberTitle=’on’).

Hidden properties

Hidden (undocumented) properties are not shown by default, but you can always access them directly, and their list can also be seen if we set the root handle’s HideUndocumented property:

>> get(0,'FactoryAxesLooseInset')
ans =
         0.13         0.11         0.095         0.075
 
>> get(0,'DefaultPatchLineSmoothing')
ans =
off
 
>> set(0,'DefaultLineLineSmoothing','on');  % default appears to be 'off' for Windows, 'on' for Macs
 
>> set(0,'HideUndocumented','off')
>> allPropDefaults = get(0,'factory');
>> length(fieldnames(allPropDefaults))   % 661 documented + 277 undocumented properties
ans =
   938

Factory values internals

For those interested in some internals, the factory values are stored (and can be accessed) via the object’s UDD reference, or rather the schema.prop reference of the properties (additional information on UDD properties can be found here). For example:

>> get(0,'FactoryFigurePosition')
ans =
   100   100   660   520
 
>> hProp = findprop(handle(gcf),'pos')
hProp =
	schema.prop
 
>> get(hProp)
            Name: 'Position'
     Description: ''
        DataType: 'figurePositionType'
    FactoryValue: [100 100 660 520]
     AccessFlags: [1x1 struct]
         Visible: 'on'
     GetFunction: []
     SetFunction: []
 
>> hProp.FactoryValue
ans =
   100   100   660   520

Note that in this example, the FactoryFigurePosition value ([100 100 660 520]) is different than the DefaultFigurePosition value ([200 200 560 420]), which overrides it.

Conclusion

Setting default values enables easy setup of property values for all instances of an HG property in a Matlab session. It could be very tempting to add such setup to the startup.m file, so that such customizations automatically occur for all Matlab sessions. However, I strongly suggest against this: the moment you will try to run your application on any other computer or Matlab installation, you may find that your GUI/graphics look entirely different.

A much safer approach is to understand how these default values affect your application and then specifically set the desired property values in your m-code. This way, whatever the installation’s default values are, your application will always retain a consistent look-and-feel.

Have you found or ever used any interesting default or factory property value? If so, please share your experience in a comment.

]]>
https://undocumentedmatlab.com/blog_old/getting-default-hg-property-values/feed 7
uiinspecthttps://undocumentedmatlab.com/blog_old/uiinspect https://undocumentedmatlab.com/blog_old/uiinspect#comments Wed, 23 Jan 2013 18:00:09 +0000 https://undocumentedmatlab.com/?p=3477 Related posts:
  1. Minimize/maximize figure window Matlab figure windows can easily be maximized, minimized and restored using a bit of undocumented magic powder...
  2. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
  3. Detecting window focus events Matlab does not have any documented method to detect window focus events (gain/loss). This article describes an undocumented way to detect such events....
  4. JIDE Property Grids The JIDE components pre-bundled in Matlab enable creating user-customized property grid tables...
]]>
After several years in which I have mentioned my uiinspect utility in posts, I figured it is high time to actually describe this utility in detail.

uiinspect in action (Java, HG, COM)

uiinspect in action (Java, HG, COM)

uiinspect, downloadable from the Matlab file Exchange, is a Matlab GUI utility that inspects the specified object and provides detailed information about its super-classes, methods, properties, static fields and callbacks in a unified Matlab window. uiinspect works on a very wide variety of inputs: Matlab/Java/Dot-Net class names and class objects; COM/DCOM objects, Handle Graphics handles etc.

In essence, uiinspect incorporates the information presented by the following built-in Matlab functions: inspect, get, and methodsview. uiinspect also presents additional aspects that are not available in any built-in Matlab function (for example, inheritance information, undocumented hidden properties, properties meta-data, grouping of callbacks by type).

uiinspect displays hidden properties and fields that are not normally displayed in Matlab (see my related getundoc utility). Property meta-data such as type, accessibility, visibility and default value are also displayed. Object properties and callbacks may be modified interactively within the uiinspect window.

Of over 40 utilities that I have so-far submitted to the File Exchange, uiinspect is one of my most complex (together with findjobj). It has undergone 24 revisions since its initial release in 2007. The latest revision has nearly 3000 source-code lines, of which 75% are code lines, 20% are comment lines and the rest are empty spacer lines. That’s a pretty complex utility to describe, and it relies on plenty of undocumented aspects, so today’s post will only highlight the important aspects. Readers are more than welcome to have a look at the source code for additional details. It is pretty-well documented, if I may say so myself.

Usage syntax

The basic syntax is:

hFig = uiinspect(handle)

Examples:

hFig = uiinspect(0);                         % the root handle
hFig = uiinspect(handle(0));
hFig = uiinspect(gcf);                       % current figure
hFig = uiinspect(handle(gcf));
uiinspect('java.lang.String');               % Java classname
uiinspect(java.lang.String('yes'));          % Java object
uiinspect(get(gcf,'JavaFrame'));             % Java object
uiinspect(classhandle(handle(gcf)));         % UDD class object
uiinspect(findprop(handle(gcf),'MenuBar'));  % UDD property
uiinspect(actxserver('Excel.Application'));  % COM object
uiinspect(Employee)                          % Matlab class object
uiinspect(?handle)                           % Matlab metaclass object
uiinspect('meta.class')                      % Matlab class name
uiinspect(System.DateTime.Now)               % Dot-Net object

uiinspect returns a handle to the created figure window. uiinspect opens a regular Matlab figure window which may be accessed via hFig (unlike Matlab’s methodsview and inspect functions which open Java frame that is not accessible from Matlab).

Unlike Matlab’s functions, multiple uiinspect windows can be opened simultaneously, for different objects. The differentiation is done based on figure title, which contains the inspected object’s name (if available) and its class – reinspecting the same object will reuse the existing figure window, but in all other cases a new figure window will be created.

Main panels

uiinspect includes the following information panels, that shall be described separately below:

  • Class information (including superclasses, if applicable)
  • Methods (for objects) or graphic handle hierarchy (for Handle Graphics)
  • Callbacks (where applicable)
  • Inspectable properties
  • Other properties plus full meta-data (where applicable)

The panels are fully resizable. We can drag the divider lines up/down or left/right and the contents automatically adjust accordingly. Each panel has a minimal viewable width/height, and the dividers cannot be dragged to squeeze the panels below these minimums – they can only be minimized, which hides the relevant panel entirely. To minimize a panel, simply click the relevant small arrow mark on the divider. The opposite arrow mark next to it maximizes the panel, effectively minimizing the panel on the other side. Once minimized/maximized, the divider can be restored by simply clicking it once, or by dragging it (again, panel minimum sizes apply).

uiinspect only uses Java panels, so implementing the dividers required use of the simple JSplitPane. In a general case where we might wish to embed Matlab graphs in one of the side panels, we would need to employ a more sophisticated solution (see my UISplitPane utility).

Class information

The top-left panel displays a label with information about the object’s class and super-classes inheritance (where applicable).

The class name itself is hyper-linked to the class’s documentation: if this is a standard Java class, then to the official online javadoc for this class which opens up in Matlab’s internal web browser. In fact, since different Matlab releases use different JVM versions (1.3 through 1.6), the link points to the documentation page corresponding to the JVM version actually used.

If the class is non-Java, the hyperlink displays the class’s help section in Matlab’s Command Window / console. The panel’s tooltip displays the same information in a slightly different manner.

The hyperlink in the label is actually an optical illusion. In fact, the entire label is hyper-linked, and clicking any part of it will display the relevant documentation (a similar optical illusion is used to display the hyperlink at the footer of the utility window). The illusion is achieved using Matlab’s HTML formatting, where the part of the label string consisting of the class name is underlined. The cursor was dynamically modified to a pointed hand-finger when the mouse hovers over the label, using the following simple Java-based command:

methodsLabel.setCursor(java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));

Special treatment is done to extract the class’s superclass, the interfaces that it implements and any possible class qualifiers (for example, “final”).

For those interested to dig within the code, all this is done in uiinspect‘s getMethodsPane function.

Next to the class label, a checkbox is presented (“Extra”). Clicking this checkbox displays additional meta-data information (qualifiers, interrupts and inheritance) in the methods pane beneath. Not all classes have all these extra meta-data fields – only the relevant extra meta-information fields are displayed. If there are is extra meta-data, then the checkbox is not displayed. This is done in the getMethodsTable function.

Methods or HG hierarchy panel

The utility’s main panel displays either a table of methods (functions) for a class object, or a tree hierarchy for an HG handle.

Class object methods

The methods table takes the information from the getObjMethods function, which is an adaptation of Matlab’s built-in methodsview function. Part of the adaptation is to hyperlink all class references (used in the methods’ inputs, outputs and meta-data), such that clicking them will open new corresponding uiinspect windows.

Class object methods panel

Class object methods panel

The methods data is displayed within a non-editable Java table (in the getMethodsTable function) that auto-resizes the columns. The table columns are sortable, even sortable on multiple columns by CTRL-clicking (methodsview allows only simple sorting). This is done using JIDE’s TreeTable component. The table is placed within a scroll-pane having automatic scrollbars that only appear as needed.

The table’s MouseMovedCallback property is set to tbMouseMoved, which updates the mouse cursor (either regular or pointed finger) based on the current mouse position in the table (whether over a hyperlinked cell or not).

The table’s MousePressedCallback property is set to tbMousePressed, which opens new uiinspect figure windows for the hyperlinked classes (if any) in the clicked cell.

HG hierarchy tree

For HG handles, getHandleTree creates a Java tree that displays the hierarchy of HG children (as recursively reported by any HG handle’s Children property). For convenience, I have chosen to use the built-in component com.mathworks.hg.peer.UITreePeer that underlies the built-in uitree function. For performance reasons, the tree is not fully evaluated: the inspected handle’s Parent is set as the tree’s Root. The root node is expanded to get all the parent’s Children (i.e., the inspected handle’s siblings), and then the inspected handle’s tree node is again expanded to display its direct descendents.

Normal dynamic HG handle tooltip

Normal dynamic HG handle tooltip

A MouseMovedCallback is set on the tree to process mouse hover events in the treeMouseMovedCallback function. This function updates the tree tooltip dynamically, in the sense that it presents a different tooltip for different handles (tree nodes).

Invalid HG handles (this can happen if the HG handle was deleted since the time that uiinspect generated the tree) are displayed with a special warning message.

Invalid HG handle tooltip

Invalid HG handle tooltip

This dynamic tree behavior is achieved by storing the relevant handle information in the UserData of the different tree nodes. Unfortunately, starting in R2012a, Matlab has made a change in the internal support of Java objects, and the UserData property is no longer available. Such a case is detected and the data is stored in the tree nodes’ ApplicationData property instead (using setappdata(node,’userdata’,…) ).

Dynamic context (right-click) menu

Dynamic context (right-click) menu

A MousePressedCallback is set on the tree to process context (right-click) events in the treeMousePressedCallback function. The context-menu is also dynamic, in the sense that it presents a different context menu for different handles (tree nodes), again based on their user-data.

Left-clicking a node is not processed by treeMousePressedCallback, but rather by the tree’s NodeSelectedCallback which is processed in nodeSelected, and by NodeExpandedCallback which is processed by nodeExpanded. nodeSelected reloads uiinspect for the selected handle; nodeExpanded merely displays the expanded handle’s children.

Since the ‘+’ sign (which triggers nodeExpanded) and the handle icon (which triggers nodeSelected) are so close, we should be careful to click the ‘+’, otherwise the entire uiinspect window will reload the tree based on the clicked node… If anyone has a good idea how to solve this dilemma, then I’m all ears.

Like the methods table, the tree is also placed in a dynamic scroll-pane that displays scrollbars only as needed.

Callbacks panel

The callbacks panel, computed in getCbsData is based on a reflection of the object’s data as reported by the undocumented built-in classhandle function. I aggregate all the object’s events, as well as all the object property names that end with ‘Fcn’ or ‘Callback’. This takes care (I hope) of all the different manners by which different kinds of objects raise events that are trappable in Matlab callbacks. Specifically, it takes care of Java/Matlab classes as well as HG handles and COM objects. If anyone thinks that I have forgotten something, please let me know.

The getCbsPane function then displays the callbacks data (callbacks’ property name and value) in a Java table (JIDE PropertyTable, JIDE TreeTable, or failing those a simple JTable).

Modifiable object callbacks

Modifiable object callbacks

The callbacks are automatically grouped by name into logical groups (in getTreeData). For example, all callbacks whose names start with “Mouse*” are grouped in the “Mouse callbacks” group. The last group is always called “Other callbacks” and contains all callbacks for which a matching sibling callback has not been found. The groups are automatically collapsed by default; if only a single group is found then this group is automatically opened (for example, in the case of uiinspect(0) ).

The callbacks table’s toolbar enables displaying the callbacks by groups or sorted alphabetically. It also has “expand” and “collapse” icons that affect all the groups.

A checkbox next to the table’s toolbar enables hiding standard Java Swing callbacks. This is important when we inspect Java controls and only wish to see its unique callbacks. When using this checkbox, red Java exceptions are sometimes displayed in the Matlab console – these are harmless and you can safely ignore them (I hope to find a way to prevent them one day).

The table’s right column displays the callback properties values (if available). This column is editable and we can interactively modify any callback’s property. As shown, we can enter callback value in either of Matlab’s supported formats: string, function handle and (for non-COM objects only!) a cell array of function handle and additional data. An error message will be displayed if the callback value is invalid or cannot be set for some reason.

If it is determined that there are no callbacks, then the callbacks panel is automatically minimized, to enable maximum space for the methods panel above it.

Properties inspector panel

The properties inspection panel, prepared in getPropsPane, is actually composed of two separate panes: the top pane uses the built-in Matlab component com.mathworks.mlwidgets.inspector.PropertyView, which in turn uses JIDE’s PropertyTable. PropertyView is the same component used by Matlab’s standard inspect function (that’s how I came to know it, if anyone wonders).

uiinspect's property inspector table

uiinspect's property inspector table

The benefit of using Matlab’s PropertyView component rather than JIDE’s PropertyTable is that PropertyView has the very useful method setObject which I use to point the component at the inspected object, which automatically infers its non-hidden properties and updates the table, saving me a lot of work.

There are two drawbacks of using Matlab’s PropertyView:

  • PropertyView only displays non-hidden properties. One day when I have time, I intent to add the hidden properties to the resulting JIDE PropertyTable. But for now it only shows non-hidden properties.
  • PropertyView causes a Matlab crash on some Matlab releases, in case dbstop if error is active (this can be replicated using Matlab’s standard inspect). I therefore regrettably need to disable this specific dbstop.

I’ve been meaning to do these two fixes ever since I released uiinspect back in 2007, but for now that’s the way it is…

The properties data is retrieved via the getPropsData function. This function uses the built-in Matlab functions meta.class.fromName(className) and metaclass(classObject) to get the class handle of Matlab classes (in getMetaClass); similarly, loadClass loads the class definition for a Java class. I inspect these class handles for their contained properties. I then use the fieldnames function to add static class fields, which are not standard properties (for example, “RED” is a static field of the java.awt.Color class).

From the class handle, I retrieve the full definition of each property. This includes meta-data such as whether the property is regular or hidden (undocumented); settable or not; gettable or not; and any additional qualifiers (e.g., Sealed, Dependent, Constant, Abstract, Transient, Default (factory) value).

Object properties tooltip

Object properties tooltip

We now have a list of all properties and static fields, and this is used to display the entire properties data in the properties panel’s title (“Inspectable object properties”) tooltip. This tooltip, created in updateObjTooltip and getPropsHtml, uses some fancy HTML formatting to display all the object’s properties and values, color- and font-style-coded to show which of the properties is read-only, hidden, undefined etc.

The 'Other properties' meta-data table

The 'Other properties' meta-data table

The entire information is also displayed in the properties meta-data pane (“Other properties”) beneath JIDE’s inspector pane. Here we use a simple Java table to display the information in color-coding (gray for read-only properties; blue for static fields; red for irretrievable properties).

Separate checkboxes enable displaying all properties (by default only the properties that are NOT displayed in JIDE’s inspector table are displayed); and whether or not to display the extra meta-data in the properties table (by default only the property name and current value are displayed).

In some cases (e.g., Dot-Net objects), Matlab’s inspector does not know how to extract the property-bean information and so the PropertyView inspector is not shown, only the “other properties” table.

Both JIDE’s inspector table and the “other properties” table enable the user to modify existing values. Note that in some cases Matlab prevents interactive update of some properties, and in some other cases I have seen Matlab hang when trying to update a few specific properties. But in most cases updating the value does work as expected.

The combination of the inspector table, the meta-data table and the tooltip, enable users to fully understand the accessible properties of the inspected object. Of course, it would have been much better to merge the JIDE inspector table with the hidden properties (=additional rows) and meta-data (=additional columns). But let’s leave something for the future, shall we?

Auto-update mechanism

uiinspect auto-update notice

uiinspect auto-update notice

uiinspect employs the same auto-update background mechanism used by findjobj – after presenting the GUI, the utility silently checks the File Exchange webpage to see whether any newer version of this utility has been uploaded. If so, then a popup notice is presented with the date and description of the latest version. The popup enables users to download the newer version into their Matlab path, or skip. There is also an option to skip the update and not to remind ever again.

I find this background auto-update mechanism quite useful and generic. In fact, I uploaded it as a separate File Exchange utility today, following Brett Shoelson’s suggestion last month. You can find the underlying code in the checkVersion function.

TODO

  • cleanup internal functions, remove duplicates etc.
  • link property objects to another uiinspect window for these objects
  • display object children (& link to them) – COM/Java
  • find a way to merge the other-properties table with the inspector table (hidden props + meta-data)
  • find a way to use the inspector without disabling dbstop if error
  • Fix: some fields generate a Java Exception from: com.mathworks.mlwidgets.inspector.PropertyRootNode$PropertyListener$1$1.run
  • Fix: using the “Hide standard callbacks” checkbox sometimes issues Java Exceptions on the console
  • Fix: In HG tree view, sometimes the currently-inspected handle is not automatically selected

I would be happy if anyone can help with any of these.

Conclusion

I believe that this has been my longest blog post ever; certainly the one that I have labored most over. This correlates well with the uiinspect utility, which has been one of my most complex tasks. I’m guessing I must have invested 100-200 man-hours developing and improving it over the years.

I hope you find uiinspect as useful and as fun as I do. I believe that its source-code is certainly worth reading if you are interested in any advanced Matlab GUI programming, showing how Java GUI components can be combined in Matlab. Go ahead and download uiinspect from the Matlab file Exchange.

]]>
https://undocumentedmatlab.com/blog_old/uiinspect/feed 6
Pinning annotations to graphshttps://undocumentedmatlab.com/blog_old/pinning-annotations-to-graphs https://undocumentedmatlab.com/blog_old/pinning-annotations-to-graphs#comments Wed, 12 Dec 2012 18:00:51 +0000 https://undocumentedmatlab.com/?p=3398 Related posts:
  1. uiundo – Matlab’s undocumented undo/redo manager The built-in uiundo function provides easy yet undocumented access to Matlab's powerful undo/redo functionality. This article explains its usage....
  2. Matlab’s HG2 mechanism HG2 is presumably the next generation of Matlab graphics. This article tries to explore its features....
  3. New information on HG2 More information on Matlab's new HG2 object-oriented handle-graphics system...
  4. HG2 update HG2 appears to be nearing release. It is now a stable mature system. ...
]]>
Many Matlab users are aware of Matlab’s annotation functionality, which enables us to assign graphic elements such as arrows, lines, ellipses and text labels to Matlab figures. Matlab has a corresponding built-in function, annotation, that enables creation of annotation objects. Through the handle returned by annotation we can customize the annotation’s appearance (for example, line width/style or text font properties).

Limitations of Matlab annotations

Unfortunately, annotation has several major deficiencies, that are in fact related:

A Matlab text-arrow annotation (unpinned)

A Matlab text-arrow annotation (unpinned)

  1. annotation requires us to specify the annotation’s position in normalized figure units. Often, we are interested in an annotation on a plot axes that does NOT span the entire figure’s content area. To correctly convert the position from plot axes data coordinates to figure coordinates requires non-trivial calculations.
  2. The created annotation is NOT pinned to the plot axes by default. This means that the annotation retains its relative position in the figure when the plot is zoomed, panned or rotated. This results in unintelligible and misleading annotations. We can indeed pin the annotation to the graph, but this requires delicate manual interaction (click the Edit Plot toolbar icon, then right-click the relevant annotation end-point, then select “Pin to Axes” from context menu). Unfortunately, the annotation handle does not provide a documented way to do this programmatically.
  3. Finally, the annotation objects are only displayed on top of plot axes – they are obscured by any GUI uicontrols that may happen to be present in the figure.

All of these limitations originate from the underlying implementation of annotation objects in Matlab. This is based on a transparent hidden axes that spans the entire figure’s content area, on which the annotations are being drawn (also called the scribe layer). The annotations may appear to be connected to the plot axes, but this is merely a visual illusion. In fact, they are located in a separate axes layer. For this reason, annotation requires figure position – in fact, the annotation has no information about the axes beneath it. Since plot axes are always obscured by uicontrols, so too is the annotation layer.

Matlab’s implementation of annotation is an attempt to replicate Java’s standard glass-pane mechanism. But whereas the Java glass-pane is a true transparent layer, on top of all other window components (examples), Matlab’s implementation only works for axes.

Oh well, it’s better than nothing, I guess. But still, it would be nice if we could specify the annotation in graph (plot axes) data units, and have it pinned automatically without requiring manual user interaction.

Debugging the problem

The obvious first place to start debugging this issue is to go to the annotation handle’s context-menu (accessible via the UIContextMenu property), drill down to the “Pin” menu item and take a look at its callback. We could then use the hgfeval function to execute this callback programmatically. Unfortunately, this does not work well, because the context-menu is empty when the annotation is first created. A context-menu is only assigned to the annotation after the Edit Plot toolbar button and then the annotation object are clicked.

Being too lazy in nature to debug this all the way through, I opted for an easier route: I started the Profiler just prior to clicking the context-menu’s “Pin to Axes”, and stopped it immediately afterwards. This showed me the code path (beneath %matlabroot%/toolbox/matlab/scribe/), and placing breakpoints in key code lines enabled me to debug the process step-by-step. This in turn enabled me to take the essence of the pinning code and implement it in my stand-alone application code.

Believe me when I say that the scribe code is complex (anyone say convoluted?). So I’ll spare you the gruesome details and skip right to the chase.

The solution

Positioning the annotation in axes data units

The first step is to ensure that the initial annotation position is within the figure bounds. Otherwise, the annotation function will shout. Note that it is ok to move the annotation outside the figure bounds later on (via panning/zooming) – it is only the initial annotation creation that must be within the figure bounds (i.e., between 0.0-1.0 in normalized X and Y units):

% Prepare the annotation's X position
% Note: we need 2 X values: one for the annotation's head, another for the tail
x = [xValue, xValue];
xlim = get(hAxes,'XLim');
 
% Prepare the annotation's Y position
% Note: we need 2 Y values: one for the annotation's head, another for the tail
% Note: we use a static Y position here, spanning the center of the axes.
% ^^^^  We could have used some other Y data value for this
yLim = get(hAxes,'YLim');
y = yLim(1) + 0*sum(yLim) + [0.1,0]*diff(ylim);  % TODO: handle reverse, log Y axes
 
% Ensure that the annotation fits in the window by enlarging
% the axes limits as required
if xValue < xlim(1) || xValue > xlim(2)
    hold(hAxes,'on');
    plot(hAxes,xValue,y(2),'-w');
    drawnow;
 
    % YLim may have changed, so recalculate y
    yLim = get(hAxes,'YLim');
    y = yLim(1) + 0*sum(yLim) + [0.1,0]*diff(ylim);  % TODO: handle reverse, log Y-axes
end

Next, we convert our plot data units, in order to get the annotation’s requested position in the expected figure units. For this we use %matlabroot%/toolbox/matlab/scribe/@scribe/@scribepin/topixels.m. This is an internal method of the scribepin UDD class, so in order to use it we need to create a dummy scribepin object. topixels then converts the dummy object’s position from axes data units to pixel units. We then use the undocumented hgconvertunits function to convert from pixel units into normalized figure units:

% Convert axes data position to figure normalized position
% uses %matlabroot%/toolbox/matlab/scribe/@scribe/@scribepin/topixels.m
scribepin = scribe.scribepin('parent',hAxes,'DataAxes',hAxes,'DataPosition',[x;y;[0,0]]');
figPixelPos = scribepin.topixels;
hFig = ancestor(hAxes,'figure');
figPos = getpixelposition(hFig);
figPixelPos(:,2) = figPos(4) - figPixelPos([2,1],2);
figNormPos = hgconvertunits(hFig,[figPixelPos(1,1:2),diff(figPixelPos)],'pixels','norm',hFig);
annotationX = figNormPos([1,1]);
annotationY = figNormPos([2,2]) + figNormPos(4)*[1,0];
Pinning the annotation to the axes data

Finally, we use the annotation handle’s pinAtAffordance() method and set the Pin.DataPosition property to the requested X,Y values (we need to do both of these, otherwise the annotation will jump around when we zoom/pan):

A Matlab text-arrow annotation (pinned)

A Matlab text-arrow annotation (pinned)

% Ensure that the annotation is within the axes bounds, then display it
if any([annotationX,annotationY] < 0) || any([annotationX,annotationY] > 1)
    % Annotation position is outside axes boundaries, so bail out without drawing
    hAnnotation = handle([]);
elseif ~isempty(annotationObj)
    % Create a text-arrow annotation with the requested string at the requested position
    hAnnotation = handle(annotation('textarrow', annotationX, annotationY, ...
                                    'String',annotationStr, 'TextColor','b', 'Tag','annotation'));
 
    % Example for setting annotation properties
    hAnnotation.TextEdgeColor = [.8,.8,.8];
 
    % Pin the annotation object to the required axes position
    % Note: some of the following could fail in certain cases - never mind
    try
        hAnnotation.pinAtAffordance(1);
        hAnnotation.pinAtAffordance(2);
        hAnnotation.Pin(1).DataPosition = [xValue, y(1), 0];
        hAnnotation.Pin(2).DataPosition = [xValue, y(2), 0];
    catch
        % never mind - ignore (no error)
    end
end

p.s. Notice that all this relies on pure Matlab code (i.e., no mention of the dreaded J-word…). In fact, practically the entire scribe code is available in m-file format in the base Matlab installation. Masochistic readers may find many hours of pleasure sifting through the scribe code functionality for interesting nuggets such as the one above. If you ever find any interesting items, please drop me an email, or post a comment below.

Undocumented annotation properties

Annotation objects have a huge number of undocumented properties. In fact, they have more undocumented properties than documented ones. You can see this using my uiinspect or getundoc utilities. Here is the list for a simple text-arrow annotation, such as the one that we used above:

>> getundoc(hAnnotation)
ans = 
              ALimInclude: 'on'
                   Afsize: 6
          ApplicationData: [1x1 struct]
                 Behavior: [1x1 struct]
              CLimInclude: 'on'
               ColorProps: {5x1 cell}
     EdgeColorDescription: 'Color'
        EdgeColorProperty: 'Color'
                  Editing: 'off'
                EraseMode: 'normal'
     FaceColorDescription: 'Head Color'
        FaceColorProperty: 'HeadColor'
             FigureResize: 0
            HeadBackDepth: 0.35
                HeadColor: [0 0 0]
            HeadColorMode: 'auto'
            HeadEdgeColor: [0 0 0]
            HeadFaceAlpha: 1
            HeadFaceColor: [0 0 0]
               HeadHandle: [1x1 patch]
         HeadHypocycloidN: 3
            HeadLineStyle: '-'
            HeadLineWidth: 0.5
               HeadRosePQ: 2
                 HeadSize: 10
             HelpTopicKey: ''
          IncludeRenderer: 'on'
                 MoveMode: 'mouseover'
                    NormX: [0.2 0.4]
                    NormY: [0.5 0.7]
                      Pin: [0x1 double]
                   PinAff: [1 2]
           PinContextMenu: [2x1 uimenu]
                PinExists: [0 0]
              PixelBounds: [0 0 0 0]
        PropertyListeners: [8x1 handle.listener]
        ScribeContextMenu: [9x1 uimenu]
                 Selected: 'off'
             Serializable: 'on'
                ShapeType: 'textarrow'
                    Srect: [2x1 line]
           StoredPosition: []
                TailColor: [0 0 0]
               TailHandle: [1x1 line]
            TailLineStyle: '-'
            TailLineWidth: 0.5
     TextColorDescription: 'Text Color'
            TextColorMode: 'auto'
        TextColorProperty: 'TextColor'
        TextEdgeColorMode: 'manual'
            TextEraseMode: 'normal'
               TextHandle: [1x1 text]
         UpdateInProgress: 0
    VerticalAlignmentMode: 'auto'
              XLimInclude: 'on'
              YLimInclude: 'on'
              ZLimInclude: 'on'
]]>
https://undocumentedmatlab.com/blog_old/pinning-annotations-to-graphs/feed 13
Accessing plot brushed datahttps://undocumentedmatlab.com/blog_old/accessing-plot-brushed-data https://undocumentedmatlab.com/blog_old/accessing-plot-brushed-data#comments Wed, 06 Oct 2010 18:00:45 +0000 https://undocumentedmatlab.com/?p=1911 Related posts:
  1. Modifying default toolbar/menubar actions The default Matlab figure toolbar and menu actions can easily be modified using simple pure-Matlab code. This article explains how....
  2. FIG files format FIG files are actually MAT files in disguise. This article explains how this can be useful in Matlab applications....
  3. Pinning annotations to graphs Annotation object can be programmatically set at, and pinned-to, plot axes data points. ...
  4. HG2 update HG2 appears to be nearing release. It is now a stable mature system. ...
]]>
A few days ago, a reader of the Matlab Desktop blog asked whether it is possible to store plot brushed data in a separate variable for later processing. Data Brushing, first introduced in R2008a, enables interactive selection and marking of plot data points. The brushed data can then be stored in a variable using the context (right-click) menu, or the figure’s Tools/Brushing menu.

Saving brushed data to a variable

Saving brushed data to a variable

The said reader has specifically wanted programmatic access, rather than interactivity. The official answer is that data brushing was designed to be an interactive tool, and so this cannot be done. However, this has never stopped us before. So off I went to launch my favorite inspection tool, the UIInspect utility on the figure above (UIInspect will be described in a near-future article), which can be recreated with the following simple code:

t=0:0.2:25; plot(t,sin(t),'.-');
% Now brush some data points...
uiinspect(gca);

UIInspect-ion of a data-brushed plot

UIInspect-ion of a data-brushed plot (click for details)

A couple of alternative answers to the reader’s question were immediately apparent:

Directly accessing brushed data

First, we notice that data brushing added data-brushing context menus, both of which are called BrushSeriesContextMenu (the duplication is an internal Matlab bug, that does not affect usability as far as I can tell).

Also, an invisible scribe overlay axes has been added to hold the new annotations (data brushing is considered an annotation; scribe axes deserve a separate article, which they will indeed get someday).

More importantly for our needs, we see a new line item called ‘Brushing’, which displays the red lines and data points that we seek. We can now easily get the brushed data using this line’s XData and YData properties: non-brushed data points simply have NaN values:

UIInspect-ion of the data-brushing line

UIInspect-ion of the data-brushing line

hBrushLine = findall(gca,'tag','Brushing');
brushedData = get(hBrushLine, {'Xdata','Ydata'});
brushedIdx = ~isnan(brushedData{1});
brushedXData = brushedData{1}(brushedIdx);
brushedYData = brushedData{2}(brushedIdx);
% and similarly for ZData in 3D plots

Accessing brushing callbacks

Yet another way of approaching the problem is to use the available callback functions built-into the data-brushing functionality. We can access either the BrushSeriesContextMenu or the figure’s Tools/Brushing menu. I will leave the former (context-menu) approach as an exercise to the reader, and just describe the figure’s menu approach.

As I have already explained in a dedicated article, figure menu-bar actions are accessible via their handles, and we can retrieve that using a unique tag (well, most of the time – read that article for details). In our case, the Tools/Brushing/Create-new-variable menu item has the unique tag ‘figDataManagerNewVar’. So let’s use it:

>> hNewVarMenuItem = findall(gcf,'tag','figDataManagerNewVar')
hNewVarMenuItem =
          742.000244140625
 
>> hNewVarCallback = get(hNewVarMenuItem,'callback')
hNewVarCallback = 
    @datamanager.newvar
 
>> hNewVarCallback(gcf)   % activate the callback
% => set 'ans' as the new variable holding the brushed data
 
>> ans
ans =
                       6.4         0.116549204850494
                       6.6         0.311541363513379
                       6.8         0.494113351138609
                         7         0.656986598718789
                       7.2         0.793667863849153
                       7.4         0.898708095811627
                       7.6         0.967919672031486
                       7.8         0.998543345374605
                       ...         ...

Of course, we could also have gone the hard way, via the scribe axes and the annotations route. For masochistic people like me it could even be a worthwhile challenge. But for all other normal people, why bother when there are such simple alternatives, if we only knew how to find them. :-)

Updates for HG2 (R2014b+)

In HG2 (R2014b+), findall(gca,'tag','Brushing') returns empty data since the way that brushed data is stored has changed. You can access the brushing data using the plot line’s hidden BrushHandles property, as follows:

hLine = plot(...);
hBrushHandles = hLine.BrushHandles;
hBrushChildrenHandles = hBrushHandles.Children;  % Marker, LineStrip

I described the new Marker objects here, and LineStrip objects here. The brushed vertex data can be retrieved from either of them. For example:

>> hBrushChildrenHandles(1).VertextData
ans = 
     1     2     3     4   % X-data of 4 data points
     1     2     3     4   % Y-data of 4 data points
     0     0     0     0   % Z-data of 4 data points

If you only need the brushed data points (not the handles for the Markers and LineStrip, you can get them directly from the line handle, using the hidden BrushData property:

>> brushedIdx = logical(hLine.BrushData);  % logical array
>> brushedXData = hLine.XData(brushedIdx);
>> brushedYData = hLine.YData(brushedIdx)
brushedYData =
     1     2     3     4

Addendum 28 Feb, 2018: MathWorks posted an official post on Matlab Answers that references the BrushData functionality – see here.

]]>
https://undocumentedmatlab.com/blog_old/accessing-plot-brushed-data/feed 25
JIDE Property Gridshttps://undocumentedmatlab.com/blog_old/jide-property-grids https://undocumentedmatlab.com/blog_old/jide-property-grids#comments Thu, 22 Apr 2010 00:37:52 +0000 https://undocumentedmatlab.com/?p=1287 Related posts:
  1. Advanced JIDE Property Grids JIDE property grids can use complex cell renderer and editor components and can signal property change events asynchronously to Matlab callbacks...
  2. Tri-state checkbox Matlab checkboxes can easily be made to support tri-state functionality....
  3. propertiesGUI propertiesGUI is a utility that presents property-value structs in a convenient table format, useful in Matlab GUIs. ...
  4. Date selection components The JIDE package, pre-bundled in Matlab, contains several GUI controls for selecting dates - this article explains how they can be used...
]]>
I would like to welcome guest blogger Levente Hunyadi.

Matlab’s property inspector

We often wish to edit properties of heterogeneous objects using a common interface. Matlab’s property inspector, invoked with the built-in inspect function, answers this need. The inspector is based on a two-column table of property names and values. Properties and their values are populated automatically, and the user can edit values in-place. The inspector enables property categorization, sub-categorization and sorting, which help users find and modify properties easily. For each property, the inspector displays a matching edit control: editbox/combobox/checkbox etc. This simplifies property value editing and prevents illegal value entry. Matlab’s GUI builder, GUIDE, uses the inspector to let users edit GUI properties such as position, color etc. It is also used by other tools such as the Plot Editor.

Matlab's built-in property inspector

Matlab's built-in property inspector

The Matlab inspector can be embedded, with not-too-much effort, within Matlab GUI applications. Examples of this can be found in the FindJObj and UIInspect utilities.

FindJObj - embedded property inspector

FindJObj - embedded property inspector

Unfortunately, Matlab’s property inspector is limited to Handle Graphics, Java and COM objects, and cannot be used for structures or user-defined Matlab classes. We shall see below how to set up our own property grid, populate it with data, and subscribe to property change events. This is a rather procedural approach. It is usually more convenient to use a declarative approach in which a structure or Matlab class is passed to a function that automatically discovers its properties and their meta-information. The Property Grid utility at Matlab File Exchange provides these services.

A simple property grid

Matlab’s property inspector is based on a property grid control by JIDE Software. JIDE Grids is a collection of components that extend the standard Java Swing JTable component, and is included in each Matlab installation (/java/jarext/jide/jide-grids.jar under the Matlab root). In particular, JIDE Grids includes the PropertyTable class, which is a fully customizable property grid component. You can find further details on JIDE Grids in the Developer Guide and the Javadoc documentation.

There are several related classes associated with the PropertyTable class. First, a PropertyTableModel encapsulates all properties that are visualized in the property grid. Each property derives from the Property abstract class, which features some common actions to properties, most notably to get and set property value. DefaultProperty is a default concrete subclass of Property. Finally, PropertyPane decorates a property grid with icons for changing category view to alphabetically sorted view as well as expanding and collapsing categories, and a description text box at the bottom that can be shown or hidden.

Here are the DefaultProperty fields and their respective roles:

FieldRole
NameInteral property name, not necessarily displayed, used as a key to identify the property.
DisplayNameA short property name shown in the left column of the property grid.
DescriptionA concise description of the property, shown at the bottom of the property pane, below the grid.
TypeThe Java type associated with the property, used to invoke the appropriate renderer or editor.
EditorContextAn editor context object. If set, both the type and the context are used to look up the renderer or editor to use. This lets, for instance, one flag value to display as a true/false label, while another as a checkbox.
CategoryA string specifying the property’s category, for grouping purposes.
EditableSpecifies whether the property value is modifiable or read-only.
ValueThe current property value, as a Java object.

Just as with any Java object, these fields may either be accessed with the Java get/set semantics (e.g. getName() or setName(name)), or the Matlab get/set semantics (e.g. get(prop,’Name’) or set(prop,’Name’,name)). When using the Matlab syntax, remember to wrap the Java object in a handle() call, to prevent a memory leak.

To use a property grid in Matlab, first construct a set of DefaultProperty objects. For each object, set at least the name, type and initial value. Next, add the properties to a table model. Finally, construct a property grid with the given table model and encapsulate in a property pane:

% Initialize JIDE's usage within Matlab
com.mathworks.mwswing.MJUtilities.initJIDE;
 
% Prepare the properties list
list = java.util.ArrayList();
prop1 = com.jidesoft.grid.DefaultProperty();
prop1.setName('stringProp');
prop1.setType(javaclass('char',1));
prop1.setValue('initial value');
prop1.setCategory('My Category');
prop1.setDisplayName('Editable string property');
prop1.setDescription('A concise description for my property.');
prop1.setEditable(true);
list.add(prop1);
 
prop2 = com.jidesoft.grid.DefaultProperty();
prop2.setName('flagProp');
prop2.setType(javaclass('logical'));
prop2.setValue(true);
prop2.setCategory('My Category');
prop2.setDisplayName('Read-only flag property');
prop2.setEditable(false);
list.add(prop2);
 
% Prepare a properties table containing the list
model = com.jidesoft.grid.PropertyTableModel(list);
model.expandAll();
grid = com.jidesoft.grid.PropertyTable(model);
pane = com.jidesoft.grid.PropertyPane(grid);
 
% Display the properties pane onscreen
hFig = figure;
panel = uipanel(hFig);
javacomponent(pane, [0 0 200 200], panel);
 
% Wait for figure window to close & display the prop value
uiwait(hFig);
disp(prop1.getValue());

Here, com.mathworks.mwswing.MJUtilities.initJIDE is called to initialize JIDE’s usage within Matlab. Without this call, we may see a JIDE warning message in some Matlab releases. We only need to initJIDE once per Matlab session, although there is no harm in repeated calls.

javaclass is a function (included in the Property Grid utility, or directly downloadable from here) that returns a Java class for the corresponding Matlab type with the given dimension: javaclass(‘logical’) or javaclass(‘logical’,0) (a single logical flag value) returns a java.lang.Boolean class; javaclass(‘char’,1) (a character array) returns a java.lang.String class; javaclass(‘double’,2) (a matrix of double-precision floating point values) returns double[][].

javacomponent is the undocumented built-in Matlab function that adds Java Swing components to a Matlab figure, using the given dimensions and parent handle. When the user closes the figure, prop.getValue() fetches and displays the new property value.

A simple user-defined property grid

A simple user-defined property grid

Next week’s article will show how to add more complex renderers and editors (display the flag value as a checkbox for example), define nested properties, and subscribe to property value change events. So stay tuned…

]]>
https://undocumentedmatlab.com/blog_old/jide-property-grids/feed 17
Accessing the Matlab Editorhttps://undocumentedmatlab.com/blog_old/accessing-the-matlab-editor https://undocumentedmatlab.com/blog_old/accessing-the-matlab-editor#comments Mon, 19 Oct 2009 18:00:20 +0000 https://undocumentedmatlab.com/?p=671 Related posts:
  1. Non-textual editor actions The UIINSPECT utility can be used to expand EditorMacro capabilities to non-text-insertion actions. This is how:...
  2. EditorMacro – assign a keyboard macro in the Matlab editor EditorMacro is a new utility that enables setting keyboard macros in the Matlab editor. this post details its inner workings....
  3. EditorMacro v2 – setting Command Window key-bindings The EditorMacro utility was extended to support built-in Matlab Editor and Command-Window actions and key-bindings. This post describes the changes and the implementation details....
  4. R2009b keyboard bindings The new Matlab release R2009b includes the ability to customize keyboard bindings for the editor and Command Window. However, there are still some uses for the EditorMacro utility and its...
]]>
Matlab’s built-in editor, like most other Matlab GUI, is Java-based. As such, it can easily be accessed programmatically. ImageAnalyst, a well-respected member of the Matlab community and a frequent CSSM (newsgroup) and FEX (File Exchange) contributor, recently asked whether it is possible to retrieve the name of the Editor’s currently edited file. The answer is that this is very easy, but I decided to use this opportunity to show how other interesting things can be done with the Editor.

Before we start, it should be made clear that this entire article relies on MathWorks internal implementation of the Editor and Desktop, which may change without prior notice in future Matlab releases. The code below appears to work under Matlab 6 & 7, but users who rely on forward compatibility should be aware of this warning.

We start by retrieving the Editor handle. This can be done in a number of ways. The easiest is via the Matlab desktop:

try
    % Matlab 7
    desktop = com.mathworks.mde.desk.MLDesktop.getInstance;
    jEditor = desktop.getGroupContainer('Editor').getTopLevelAncestor;
    % we get a com.mathworks.mde.desk.MLMultipleClientFrame object
catch
    % Matlab 6
    % Unfortunately, we can't get the Editor handle from the Desktop handle in Matlab 6:
    %desktop = com.mathworks.ide.desktop.MLDesktop.getMLDesktop;
 
    % So here's the workaround for Matlab 6:
    openDocs = com.mathworks.ide.editor.EditorApplication.getOpenDocuments;  % a java.util.Vector
    firstDoc = openDocs.elementAt(0);  % a com.mathworks.ide.editor.EditorViewContainer object
    jEditor = firstDoc.getParent.getParent.getParent;
    % we get a com.mathworks.mwt.MWTabPanel or com.mathworks.ide.desktop.DTContainer object
end

Now that we have the Editor handle, let’s retrieve its currently open (active) file name from the Editor’s title:

title = jEditor.getTitle;
currentFilename = char(title.replaceFirst('Editor - ',''));

The entire list of open file names can be retrieved in several ways:

% Alternative #1:
edhandle = com.mathworks.mlservices.MLEditorServices;
allEditorFilenames = char(edhandle.builtinGetOpenDocumentNames);
 
% Alternative #2:
openFiles = desktop.getWindowRegistry.getClosers.toArray.cell;
allEditorFilenames = cellfun(@(c)c.getTitle.char,openFiles,'un',0);

At the top-level Editor-window level, we can prevent its resizing, update its status bar, modify its toolbar/menu-bar, control docking and do other similar fun things:

% Actions via built-in methods:
jEditor.setResizable(0);
jEditor.setStatusText('testing 123...');
jEditor.setTitle('This is the Matlab Editor');
 
% Equivalent actions via properties:
set(jEditor, 'Resizable', 'off');
set(jEditor, 'StatusText', 'testing 123...');
set(jEditor, 'Title', 'This is the Matlab Editor');

Actually, the jEditor handle has over 300 invokable methods and close to 200 properties that we can get/set. Perhaps the easiest way to find interesting things we can programmatically do with the Editor handle, is to use my UIInspect utility on the File Exchange:

uiinspect(jEditor);  % or: jEditor.uiinspect
Matlab Editor methods, callbacks and properties as seen by uiinspect (click to zoom)

Matlab Editor methods, callbacks and properties as seen by uiinspect
(click to zoom)

The Editor handle is actually a container for many internal panels (toolbars etc.) and documents. The entire object hierarchy can be seen with another of my File Exchange utilities, FindJObj:

findjobj(jEditor);  % or: jEditor.findjobj
Matlab Editor object hierarchy as seen by findjboj (click to zoom)

Matlab Editor object hierarchy as seen by findjboj (click to zoom)

We can modify text within the open Editor documents, and instrument these document to handle event callbacks. To see how, I refer users to my EditorMacro utility on the Matlab File Exchange.

If you find some other nifty and/or useful things that can be done using the Editor handle, please post them in the comments section below.

]]>
https://undocumentedmatlab.com/blog_old/accessing-the-matlab-editor/feed 50
Detecting window focus eventshttps://undocumentedmatlab.com/blog_old/detecting-window-focus-events https://undocumentedmatlab.com/blog_old/detecting-window-focus-events#comments Wed, 09 Sep 2009 20:49:51 +0000 https://undocumentedmatlab.com/?p=584 Related posts:
  1. Enable/disable entire figure window Disabling/enabling an entire figure window is impossible with pure Matlab, but is very simple using the underlying Java. This article explains how....
  2. Transparent Matlab figure window Matlab figure windows can be made fully or partially transparent/translucent or blurred - this article explains how...
  3. Minimize/maximize figure window Matlab figure windows can easily be maximized, minimized and restored using a bit of undocumented magic powder...
  4. Setting status-bar text The Matlab desktop and figure windows have a usable statusbar which can only be set using undocumented methods. This post shows how to set the status-bar text....
]]>
A CSSM reader recently asked whether it is possible to detect window focus events (specifically, the focus-gain event) asynchronously, so that such events can trigger a callback without necessitating a polling thread to constantly monitor the windows state.

The user correctly mentioned the fact that although mouse-clicks within the window frame can be detected using the documented figure callback WindowButtonDownFcn, there are other methods by which a window can gain focus: keyboard (<Alt>-<Tab> on Windows, for example), clicking the window frame edge etc. These methods are all undetected by WindowButtonDownFcn.

This problem is, to the best of my knowledge, insoluble using standard documented Matlab. However, there is indeed a simple solution using undocumented/unsupported Matlab features. The solution relies on the fact that all Matlab windows are basically Java Swing objects, and these objects have dozens of standard callback hooks that can be utilized (Matlab only exposes a few callbacks). The list of standard Swing callbacks was detailed in my earlier article about uicontrol callbacks, which is also relevant for Java window frames.

In this specific case, we are interested in FocusGainedCallback. This callback is invoked for the figure Frame’s AxisComponent (a part of the Frame that will be explained in another article). For each of our monitored figure windows, we set this callback to a predefined Matlab function. We may also wish to set its companion FocusLostCallback.

Here’s the resulting code snippet (hFig is our Matlab figure handle):

% Prepare the figure
hFig = figure;  % etc. - prepare the figure
 
% Get the underlying Java reference
warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame
jFig = get(hFig, 'JavaFrame');
jAxis = jFig.getAxisComponent;
 
% Set the focus event callback
set(jAxis,'FocusGainedCallback',{@myMatlabFunc,hFig});
% perhaps also set the FocusLostCallback here

Whenever any of the monitored figures now gets focus, by whichever means, the user-defined Matlab function myMatlabFunc() will be invoked. This function should be defined as follows:

function myMatlabFunc(jAxis, jEventData, hFig)
   % do whatever you wish with the event/hFig information
end

Extra input parameters can be added during callback setup and definition, as follows:

set(jAxis,'FocusLostCallback',{@myMatlabFunc,hFig,data1,data2})
...
function myMatlabFunc(jAxis, jEventData, hFig, data1, data2)
   % do whatever you wish with the event/hFig/data information
end

A very similar technique can detect other windowing events (maximization/minimization/movement etc.). Depending on the case, you may need to use jFig.fFigureClient.getWindow instead of jFig.getAxisComponent. The list of available callbacks for each of these objects can be seen using a simple set(jFig.getAxisComponent) command, or via my UIInspect or FindJObj utilities on the Matlab File Exchange.

Note that all this relies on the undocumented hidden figure property JavaFrame, which issues a standing warning (since Matlab release R2008a) of becoming obsolete in some future Matlab release. Since it worked so far, I have turned off this warning in the code above, but note that this code may well fail in some future Matlab version. If and when JavaFrame does become obsolete, be sure to look in this blog for workarounds…

Addendum Aug 21, 2015: In in HG2 (R2014b onward), setting the Focus events (FocusGained, FocusLost etc.) on the AxisComponent does not work. Instead, we can simply set the callbacks on the AxisComponent’s direct child, as follows:

set(jAxis.getComponent(0),'FocusGainedCallback',{@myMatlabFunc,hFig});
]]>
https://undocumentedmatlab.com/blog_old/detecting-window-focus-events/feed 41
Figure toolbar customizationshttps://undocumentedmatlab.com/blog_old/figure-toolbar-customizations https://undocumentedmatlab.com/blog_old/figure-toolbar-customizations#comments Wed, 02 Sep 2009 16:00:14 +0000 https://undocumentedmatlab.com/?p=564 Related posts:
  1. Detecting window focus events Matlab does not have any documented method to detect window focus events (gain/loss). This article describes an undocumented way to detect such events....
  2. Setting status-bar text The Matlab desktop and figure windows have a usable statusbar which can only be set using undocumented methods. This post shows how to set the status-bar text....
  3. Setting status-bar components Matlab status-bars are Java containers in which we can add GUI controls such as progress-bars, not just simple text labels...
  4. Figure toolbar components Matlab's toolbars can be customized using a combination of undocumented Matlab and Java hacks. This article describes how to access existing toolbar icons and how to add non-button toolbar components....
]]>
Last week, I described how to access existing Matlab figure toolbar icons and how to add non-button toolbar components. Today, I describe how the toolbar itself can be customized using undocumented functionality and properties.

All the important undocumented customizations can only be accessed via the toolbar’s Java handle, which is retrieved so:

hToolbar = findall(hFig,'tag','FigureToolBar');
jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer');

One interesting functionality is enabling a floating toolbar, via jToolbar.setFloatable(1). The toolbar can then be dragged from its docked position at the top of the figure menu, becoming enclosed in an independent floating window (a non-modal javax.swing.JDialog child of the parent figure, to be exact). Since this toolbar window has a very small initial size and no name, a simple immediate fix is required:

% Modify Java toolbar properties
jToolbar.setFloatable(1);
hjToolbar = handle(jToolbar,'CallbackProperties');
set(hjToolbar,'AncestorAddedCallback',@dockUndockCallbackFcn);
 
% Sample dockUndockCallbackFcn function
function dockUndockCallbackFcn(hjToolbar, eventdata)
   if hjToolbar.isFloating
      jToolbarWin = hjToolbar.getTopLevelAncestor;
      jToolbarWin.setTitle('Toolbar');
      %jToolbarWin.setResizable(1); %if you wish manual resize
      jToolbarWin.setPreferredSize(java.awt.Dimension(380,57));
      jToolbarWin.setSize(java.awt.Dimension(380,57));
      jToolbar.revalidate;  %repaint toolbar
      jToolbarWin.getParent.validate; %repaint parent figure
   end
end

Floating toolbar   ...and after minor fixes

Floating toolbar                 ...and after minor fixes        

Re-docking a floating toolbar can be done by simply closing the floating window – the toolbar then reappears in its default (top) position within the parent figure window.

There are other interesting functions/properties available via the Java interface – readers are encouraged to explore via the methods, methodsview, inspect functions, or my uiinspect utility.

For example, addGap() can be used to add a transparent gap between the rightmost toolbar component and the window border: this gap is kept even if the window is shrunk to a smaller width – the rightmost components disappear, maintaining the requested gap.

setBackground() sets the background color that is seen beneath transparent pixels of button images and gaps. Non-transparent (opaque or colored) pixels are not modified. If the button icons are improperly created, the result looks bad:

jToolbar.setBackground(java.awt.Color.cyan); %or: Color(0,1,1)

Default figure toolbar with cyan background

Default figure toolbar with cyan background

This problem can be fixed by looping over the toolbar icons and modifying the pixel values from their default gray background to transparent. An example for this practice was given at the beginning of last week’s article.

setMorePopupEnabled() is used to specify the behavior when the window resizes to such a small width that one or more toolbar buttons need to disappear – by default (=1 or true) the chevron (>>) mark appears on the toolbar’s right, enabling display of the missing buttons, but this behavior can be overridden (0 or false) to simply crop the extra buttons.

setRollover() controls the behavior when the mouse passes (“rolls”) over toolbar buttons. The default parameter (1 or true), displays a 3-dimensional button border, creating an embossing effect; this can be overridden (0 or false) to use a different 3D effect:

% Set non-default Rollover, MorePopupEnabled
jToolbar.setRollover(0);         % or: set(jToolbar,'Rollover','off');
jToolbar.setMorePopupEnabled(0); % or: set(jToolbar,'MorePopupEnabled','off');

default Rollover & MorePopupEnabled properties
non-default Rollover & MorePopupEnabled properties

default (top) and non-default (bottom)
Rollover & MorePopupEnabled properties

Remember that toolbars are simply containers for internal components, generally buttons and separators. These components may be accessed individually and manipulated. An example of such manipulation can be found in my FindJObj utility on the File Exchange, that lists the individual figure components: whenever the user selects a toolbar button (or any other Java component for that matter), its border is temporarily modified to a flashing red rectangle helping users understand the component’s location. Here’s the relevant code snip and screenshot (readers are encouraged to look at the actual code, which is more complex – FindJObj sub-function flashComponent()):

% Prepare the red border panel
oldBorder = jComponent.getBorder;
redBorder = javax.swing.border.LineBorder(java.awt.Color.red,2,0);
redBorderPanel = javax.swing.JPanel;
redBorderPanel.setBorder(redBorder);
redBorderPanel.setOpaque(0);  % transparent interior, red border
redBorderPanel.setBounds(jComponent.getBounds);
isSettable(compIdx) = ismethod(jComponent,'setBorder');
 
% flash by periodically displaying/hiding the panel
for idx = 1 : 2*numTimes
   if idx>1,  pause(delaySecs);  end  % don't pause at start
   visible = mod(idx,2);
   jParent = jComponent.getParent;
 
   % Most Java components allow modifying their borders
   if isSettable
      if visible
         % Set a red border
         jComp.setBorder(redBorder);
         try jComponent.setBorderPainted(1); catch, end
      else %if ~isempty(oldorder)
         % Remove red border by restoring the original border
         jComp.setBorder(oldBorder);
      end
      jComp.repaint;
 
   % Other Java components are highlighted by a transparent red-
   % border panel, placed on top of them in their parent's space
   elseif ~isempty(jParent)
      if visible
         % place the transparent red-border panel on top
         jParent.add(redBorderPanel);
         jParent.setComponentZOrder(redBorderPanel,0);
      else
         jParent.remove(redBorderPanel);
      end
      jParent.repaint;
   end
end  % idx flash loop

FindJObj - flashing red border around a toolbar icon

FindJObj - flashing red border around a toolbar icon

]]>
https://undocumentedmatlab.com/blog_old/figure-toolbar-customizations/feed 24
Non-textual editor actionshttps://undocumentedmatlab.com/blog_old/non-textual-editor-actions https://undocumentedmatlab.com/blog_old/non-textual-editor-actions#comments Fri, 17 Jul 2009 13:55:39 +0000 https://undocumentedmatlab.com/?p=454 Related posts:
  1. EditorMacro – assign a keyboard macro in the Matlab editor EditorMacro is a new utility that enables setting keyboard macros in the Matlab editor. this post details its inner workings....
  2. EditorMacro v2 – setting Command Window key-bindings The EditorMacro utility was extended to support built-in Matlab Editor and Command-Window actions and key-bindings. This post describes the changes and the implementation details....
  3. R2009b keyboard bindings The new Matlab release R2009b includes the ability to customize keyboard bindings for the editor and Command Window. However, there are still some uses for the EditorMacro utility and its...
  4. Accessing the Matlab Editor The Matlab Editor can be accessed programmatically, for a wide variety of possible uses - this article shows how....
]]>
Following my EditorMacro post a couple of weeks ago, which showed how to assign a keyboard macro to the integrated Matlab Editor, several people have asked me whether it is possible to assign a macro to non-textual actions, in addition to the text insertion/replacement which EditorMacro supports.

The quick answer is yes, with some careful programming. Instead of specifying the end result, I will use this opportunity to illustrate how Java objects (not just the editor) can be inspected for their supported actions/properties.

Our first step is to get the requested Java reference handle. This can be done via the Matlab Command Window (interested readers can look at the EditorMacro.m source code, specifically at its getJEditor() function). However, a much easier way is to assign some macro using EditorMacro and then simply place a breakpoint in EditorMacro’s keyPressedCallback() callback function. Then press an arrow key (or any other key) in the editor, and wait for the breakpoint focus to arrive (don’t forget to clear the breakpoint…). From here on, all our actions will be done in the Command Window.

We now have a variable called jEditorPane, which is a reference to a Java object of type javahandle_withcallbacks. com.mathworks.mde.editor.EditorSyntaxTextPane (in Matlab 7 – it’s something similar in Matlab 6). This is a Matlab wrapper for the basic Java object, used for accessing the callback hooks, as explained in a previous post. In our case we are not interested in this wrapper but in its wrapped object, which is retrieved via Matlab’s built-in java function (java(jEditorPane) or jEditorPane.java). The inspection itself is done using Matlab’s standard tools (inspect, methodsview etc.) or via my UIINSPECT utility. I suggest using UIINSPECT, which displays all the information of the standard tools and lots extra, but I’m of course biased…

uiinspect(jEditorPane.java);

jEditorPane inspection using UIINSPECT (click to see details)

jEditorPane inspection using UIINSPECT (click to see details)

Without diving into all the UIINSPECT options (I shall do this in a dedicated post), we see the supported methods/actions on the left, and properties on the right. It is true that none of them are documented, but many are self-explanatory. For example, the cut()/copy()/paste() methods or the caretPosition/caretColor properties. Any combination of these methods and properties can be used in a user-defined macro.

Let’s do a simple example, setting the <Ctrl-E> combination to a macro moving to the end-of-line (unix-style – equivalent to <End> on Windows), and <Ctrl-Shift-E> to a similar macro doing the same while also selecting the text (like <Shift-End> on Windows). We shall even use the same macro code, by simply checking in the eventData whether the <Shift> key is depressed:

function EOL_Macro(hDocument,eventData)
 
  % Find the position of the next EOL mark
  currentPos = hDocument.getCaretPosition;
  docLength = hDocument.getLength;
  textToEOF = char(hDocument.getTextStartEnd(currentPos,docLength));
  nextEOLPos = currentPos+find(textToEOF<=13,1)-1;  % next CR/LF pos
  if isempty(nextEOLPos)
      % no EOL found (=> move to end-of-file)
      nextEOLPos = docLength;
  end
 
  % Do action based on whether <Shift> was pressed or not
  %get(eventData);
  if eventData.isShiftDown
      % Select to EOL
      hDocument.moveCaretPosition(nextEOLPos);
  else
      % Move to EOL (without selection)
      hDocument.setCaretPosition(nextEOLPos);
  end
 
end  % EOL_Macro

…and now let’s activate this macro in the Matlab Command Window:

>> macros = EditorMacro('ctrl-e',@EOL_Macro,'run');
>> macros = EditorMacro('ctrl-shift-e',@EOL_Macro,'run')
macros = 
    'ctrl alt pressed T'      @(a,b)datestr(now)    'text'
    'ctrl pressed E'          @EOL_Macro            'run' 
    'shift ctrl pressed E'    @EOL_Macro            'run'

Please do explore all the possible actions/properties exposed by the jEditorPane object. Probably the worst that could happen (and very rarely) is that you’ll crash Matlab and need to restart it – no biggy. If you find an interesting macro combination, please post it to the File Excahnge, and/or let us all know by placing a comment below.

]]>
https://undocumentedmatlab.com/blog_old/non-textual-editor-actions/feed 5
GUIDE customizationhttps://undocumentedmatlab.com/blog_old/guide-customization https://undocumentedmatlab.com/blog_old/guide-customization#comments Wed, 10 Jun 2009 17:00:43 +0000 https://undocumentedmatlab.com/?p=383 Related posts:
  1. Detecting window focus events Matlab does not have any documented method to detect window focus events (gain/loss). This article describes an undocumented way to detect such events....
  2. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
  3. Customizing Matlab labels Matlab's text uicontrol is not very customizable, and does not support HTML or Tex formatting. This article shows how to display HTML labels in Matlab and some undocumented customizations...
  4. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
]]>
GUIDE is the acronym for Matlab’s Graphical User Interface Design Editor. It is very handy for designing simple GUI figures, although my experience has shown that it has limitations for complex GUIs. Nevertheless, GUIDE is the tool used by most Matlab developers when designing GUIs. In this post, I will show a few undocumented customizations that could help make GUIDE sessions more productive.

The starting point is GUIDE’s undocumented return value, which is a Java reference to the Layout Editor panel within the GUIDE figure frame:

>> h = guide
h =
Layout Document [untitled]

>> h.getClass
ans =
class com.mathworks.toolbox.matlab.guide.LayoutEditor

This return handle can be used to access GUIDE components and functionality. We can start by inspecting the interesting GUIDE layout hierarchy using my FindJObj utility, and the associated properties and method using my UIInspect utility:

>> h.findjobj;
>> h.uiinspect;

Hierarchy of Layout Editor within the GUIDE frame

Hierarchy of Layout Editor within the GUIDE frame

Note: If you wish to see the hierarchy of the entire GUIDE figure frame, simply run FindJObj on the frame reference, by either of the two following methods (and similarly for UIInspect):

>> findjobj(h.getFrame);
>> findjobj(h.getTopLevelWindow);

We see that the Layout Editor contains, in addition to the expected LayoutArea and two MWScrollbars, several objects that relate to a ruler. These rulers can be activated via the GUIDE menu (Tools / Grid and Rulers), or via the Matlab Command Prompt as described below:

Looking at the ruler properties in FindJObj or UIInspect, we can see a settable boolean property called “RulerState”. If we turn it on we can see that a very handy pixels-ruler appears. Once we set this property, it remains in effect for every future GUIDE session:

Before: GUIDE with no rulers

Before: GUIDE with no rulers

h.getComponent(0).getComponent(4).setRulerState(true);  % Horizontal
h.getComponent(0).getComponent(5).setRulerState(true);  % Vertical

Note: RulerState actually controls a system preference (LayoutShowRulers, a boolean flag) that controls the visibility of both rulers, and persists across Matlab/GUIDE sessions. To change the visibility of only a single ruler for this GUIDE session only, or on old Matlab versions (e.g. Matlab 7.1 aka R14 SP3) that do not have the ‘RulerState’ property, use the hide()/show()/setVisible(flag) methods, or set the ‘Visible’ property:

% Equivalent ways to show horizontal ruler for this GUIDE session only
hRuler = h.getComponent(0).getComponent(4);  % =top horizontal ruler
set(hRuler, 'Visible','on');
hRuler.setVisible(true);  % or: hRuler.setVisible(1)
hRuler.show();

After: GUIDE with pixel rulers

After: GUIDE with pixel rulers

Using this method, we can customize the rulers – options which are unavailable using the standard GUIDE menu options: We can specify horizontal/vertical grid size, tick & label interval and similar ruler properties. For example, let’s set a 5-pixel minor tick interval, 25-pixel major interval, labels every 50 pixels, starting offset of 40 pixels and a ruler size limited at 260 pixels:

hRuler = h.getComponent(0).getComponent(4);  % =top horizontal ruler
set(hRuler, 'MinorInterval',5, 'MajorInterval',25);
set(hRuler, 'LabelInterval',50, 'LabelUnit',50);
set(hRuler, 'Margin',40, 'Length',260);

GUIDE with modified pixel rulers

GUIDE with modified pixel rulers

Note that the vertical ruler’s labels start (=LabelStart property) at the figure’s height, and have a decreasing LabelInterval of -50. This is done because Java coordinates start counting from the top-left corner downward, whereas Matlab counts from the bottom-left upward. In GUIDE, we naturally wish to display the Matlab coordinates, hence the transformation.

Note: unfortunately, most of these properties do not have equivalent settable system properties that I could find. Here is a list of all the GUIDE-related system properties that I found:

  • LayoutShowRulers – boolean, controls display of both rulers
  • LayoutShowGuides – boolean, controls display of blue guidelines
  • LayoutShowGrid – boolean, controls display of gray gridlines
  • LayoutGridWidth – integer, controls the size of the grid boxes
  • LayoutSnapToGrid – boolean, controls snap-to-grid behavior
  • LayoutActivate – boolean, controls ability to run (activate) unsaved figures without confirmation
  • LayoutChangeDefaultCallback – boolean, ??? (I can see this preference in my matlab.prf file but I have no idea what it does or how it got there…)
  • LayoutExport – boolean, controls ability to export unsaved figures without confirmation
  • LayoutExtension – boolean, controls display of file extension in the GUIDE window title
  • LayoutFullPath – boolean, controls display of file path in the GUIDE window title
  • LayoutMCodeComments – boolean, controls generation of comments for m-file callbacks
  • LayoutToolBar – boolean, controls display of the GUIDE widow toolbar
  • LayoutToolNames – boolean, controls display of tool names in the components palette

Have you discovered other undocumented features in GUIDE? If so, please share your findings in the comments section below.

Warning: These undocumented features are way deep in unsupported territory. They depend heavily on Matlab’s internal implementation, which may change without any prior notice between Matlab releases. They work ok on Matlab versions 7.1 (R14 SP3) through 7.6 (R2008a), and perhaps on other versions as well. However, the very next Matlab release might break these features, so beware.

]]>
https://undocumentedmatlab.com/blog_old/guide-customization/feed 6
Uicontrol callbackshttps://undocumentedmatlab.com/blog_old/uicontrol-callbacks https://undocumentedmatlab.com/blog_old/uicontrol-callbacks#comments Fri, 01 May 2009 09:58:16 +0000 https://undocumentedmatlab.com/?p=223 Related posts:
  1. Customizing editboxes Matlab's editbox can be customized in many useful manners...
  2. Setting listbox mouse actions Matlab listbox uicontrol can be modified to detect mouse events for right-click context menus, dynamic tooltips etc....
  3. Customizing Matlab labels Matlab's text uicontrol is not very customizable, and does not support HTML or Tex formatting. This article shows how to display HTML labels in Matlab and some undocumented customizations...
  4. GUI integrated HTML panel Simple HTML can be presented in a Java component integrated in Matlab GUI, without requiring the heavy browser control....
]]>
In my previous post I showed how we can extensively customize a Matlab uicontrol’s appearance and behavior by accessing its undocumented underlying Java object. In this post I will show how to further customize the control’s behavior using the callbacks exposed by its underlying object.

Matlab’s uicontrol handles normally expose only a few event callbacks. These are ‘CreateFcn’, ‘DeleteFcn’, ‘ButtonDownFcn’, ‘KeyPressFcn’ and the control-specific ‘Callback’. In contrast, the underlying Java control exposes many more callbacks: 26 standard callbacks, plus a few control-specific callbacks, as follows:

  • AncestorMovedCallback – fired when one of the component’s container ancestors has changed its position relative to its container.
  • AncestorAddedCallback – fired when one of the component’s container ancestors has been added to another container
  • AncestorRemovedCallback – fired when one of the component’s container ancestors has been removed from the component’s hierarchy
  • AncestorResizedCallback – fired when one of the component’s container ancestor has been resized
  • ComponentAddedCallback – fired when a sub-component is added as a direct child to this component. Compare: ComponentRemovedCallback
  • ComponentHiddenCallback – fired when the component is hidden (setVisible(false)). Compare: ComponentShownCallback
  • ComponentMovedCallback – fired when the component is moved within its container. Since Java components are enclosed in a tight-fitting HG container, this callback will never fire for them: it does not fire when the container moves or resizes, only when the component’s starting position is moved within it.
  • ComponentRemovedCallback – fired when a sub-component is added as a direct child to this component. Compare: ComponentAddedCallback
  • ComponentResizedCallback – fired when the component is resized, either directly or because its container was resized.
  • ComponentShownCallback – fired when the component is displayed (setVisible(true)). Compare: ComponentHiddenCallback
  • FocusGainedCallback – fired when the component gains GUI focus, by mouse click, Tab click, or calling the component’s requestFocus() method.
  • FocusLostCallback – fired when the component loses focus to another component or window. Compare: FocusGainedCallback
  • HierarchyChangedCallback – fired when the component changes its ancestors (for example, moved from one panel to another).
  • KeyPressedCallback – fired continuously when any keyboard button (including Shift, Ctrl etc.) was pressed while the component had focus. The meta-data contains details about the specific key and modifiers (Alt, Shift, Ctrl, …) that were pressed. Compare: KeyReleasedCallback, KeyTypedCallback
  • KeyReleasedCallback – fired when a keyboard button was released while the component had focus. The meta-data contains details about the specific key and modifiers (Alt, Shift, Ctrl, …) that were pressed. Compare: KeyPressedCallback
  • KeyTypedCallback – similar to KeyPressedCallback, but only fired (continuously) when an actual printable character is clicked. Therefore, for Shift-A, KeyPressedCallback will fire twice (Shift, ‘A’) but KeyTypedCallback will only fire once. Compare: KeyPressedCallback, KeyReleasedCallback
  • MouseClickedCallback – fired when a mouse button is pressed and then released (=clicked) within the component’s bounds. If either the press or the release occurs outside the component’s bounds, the event will not fire. The figure’s ‘SelectionType’ property will be ‘normal’, ‘extend’ or ‘alt’ depending on which button was pressed. Compare: MousePressedCallback, MouseReleasedCallback.
  • MouseDraggedCallback – fired continuously when the mouse is clicked within the component’s bounds and then moved while the button is still depressed (i.e., dragged), even beyond the component’s bounds. The callback event’s meta-data will contain the delta-x and delta-y of the movement (positive for x-right/y-down; negative for x-left/y-up). Compare: MouseMovedCallback
  • MouseEnteredCallback – fired when the mouse is moved (depressed or not) into the component’s bounds. Compare: MouseExitedCallback
  • MouseExitedCallback – fired when the mouse is moved (depressed or not) out of the component’s bounds. Compare: MouseEnteredCallback
  • MouseMovedCallback – fired continuously when the mouse is moved undepressed within the component’s bounds. The callback event’s meta-data will contain the delta-x and delta-y of the movement (positive for x-right/y-down; negative for x-left/y-up). Compare: MouseDraggedCallback
  • MousePressedCallback – fired immediately when the mouse button is depressed (even before it was released) within the component’s bounds. The callback event’s meta-data will contain the click location within the component’s bounds. Compare: MouseClickedCallback, MouseReleasedCallback
  • MouseReleasedCallback – fired immediately when the mouse button is released within the component’s bounds. The callback event’s meta-data will contain the click location within the component’s bounds. Compare: MousePressedCallback
  • MouseWheelMovedCallback – fired immediately when the mouse wheel is turned (even before it was released) within the component’s bounds.
  • PropertyChangeCallback – fired when one of the component’s properties has changed. For example, after setting the component’s text, tooltip or border. Does not fire when modifying the component’s callback properties.
  • VetoableChangeCallback – fired upon a constrained property value change, allowing the callback to intercept and prevent the property change by raising an exception. Of all the Swing components, only JInternalFrame actually declares vetoable properties which can be intercepted.

It should be noted that these callbacks are standard in all Swing GUI controls. Thus, they can be used not just for Matlab uicontrols’ underlying Java objects, but also for any Swing component that you display using Matlab’s built-in javacomponent function.

The specific list of callbacks supported by each component depends on component type. As noted above, some components have additional specific callbacks. For example, ActionPerformedCallback is fired when a user has performed the main action associated with the control (selecting/clicking etc.). This is one of the most commonly used callbacks, one of the few exposed by Matlab HG handles (as the general-purpose ‘Callback’). This callback is implemented by JButton and JCheckBox (for instance), but not by JList or JMenu. CaretUpdateCallback and CaretPositionChangedCallback are only supported by text-entry controls like JTextField or JEditorPane, but not by JSlider or JTabbedPane. Other components have other such specific callbacks.

To see the full list of supported callbacks for a particular object, use the UIINSPECT utility from the File Exchange or use the following code snippet:

>> props = sort(fieldnames(get(javax.swing.JButton))); 
>> callbackNames = props(~cellfun(@isempty,regexp(props,'Callback$')));
callbackNames = 
    'ActionPerformedCallback'
    'AncestorAddedCallback'
    'AncestorMovedCallback'
    ...

A nice example of using Java callbacks to automatically select (highlight) the content text in a text-box when focus is gained was one of the first online posts in CSSM to use Matlab 7’s new javacomponent Swing integration.

Another typical usage is to set a continuously-firing callback whenever a slider uicontrol is dragged – the Matlab HG callback only fires once after the drag has completed, whereas we often wish to update some value or graphics during the drag events. This can easily be done using JSlider’s underlying object (a Swing JScrollBar) callbacks.


In order to prevent memory leaks in heavily-laden GUIs, it is advisable to get and set callback properties using the handle object, instead of directly on the “naked” Java reference. For this reason, using set/get is discouraged by MathWorks and may even be disabled in some future Matlab release:

jb = javax.swing.JButton;
jbh = handle(jb,'CallbackProperties');
% or for an existing uicontrol: jbh = findjobj(hButton);
set(jbh, 'ActionPerformedCallback',@myCallbackFcn)  % ok!
set(jb,  'ActionPerformedCallback',@myCallbackFcn)  % bad! memory leak

In some future post I plan to present more details about handle() and its intricacies. But in a nutshell, this code snippet is all you need to start working.

Callbacks can be set in the normal Matlab fashion, using one of three methods:

set(jbh, 'ActionPerformedCallback',@myCallbackFcn);
set(jbh, 'ActionPerformedCallback',{@myCallbackFcn,param1,param2});
set(jbh, 'ActionPerformedCallback','disp(123);');

I would be happy to hear how you use these newly-exposed callbacks in your application. Please leave your welcome comments below.

]]>
https://undocumentedmatlab.com/blog_old/uicontrol-callbacks/feed 67
Button customizationhttps://undocumentedmatlab.com/blog_old/button-customization https://undocumentedmatlab.com/blog_old/button-customization#comments Fri, 24 Apr 2009 05:51:04 +0000 https://undocumentedmatlab.com/?p=184 Related posts:
  1. Uicontrol callbacks This post details undocumented callbacks exposed by the underlying Java object of Matlab uicontrols, that can be used to modify the control's behavior in a multitude of different events...
  2. FindJObj GUI – display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
  3. Rich Matlab editbox contents The Matlab editbox uicontrol does not handle HTML contents as do other uicontrols. In this article I show how this limitation can be removed....
  4. Setting line position in an edit-box uicontrol Matlab uicontrols have many useful features that are only available via Java. Here's how to access them....
]]>
Matlab’s button uicontrols (pushbutton and togglebutton) are basically wrappers for a Java Swing JButton object.

This will be the first in a series of posts showing how Matlab uicontrols can be customized in ways that you may never have thought possible.

Probably the simplest undocumented customization is the control’s acceptance of HTML and CSS Strings:

tooltip = '<html>HTML-aware<br><b>tooltips</b><br><i>supported';
labelTop= '<HTML><center><FONT color="red">Hello</Font> <b>world</b>';
labelBot=['<div style="font-family:impact;color:green"><i>What a</i>'...
          ' <Font color="blue" face="Comic Sans MS">nice day!'];
set(hButton, 'tooltip',tooltip, 'string',[labelTop '<br>' labelBot]);

Button with HTML label and tooltip

Button with HTML label and tooltip

For more powerful customization, we need to access the control’s underlying JList object. We do this by using my FindJObj submission on the File Exchange (which was explained here):

>> jButton = java(findjobj(hButton))
jButton =
com.mathworks.hg.peer.PushButtonPeer$1[,0,0,...]

Now that we have the jButton Java object reference, we can use get and set just like any Matlab handle. To see the list of all available properties, methods and callbacks, we can use my UIINSPECT submission on the File Exchange, or use Matlab’s built-in methodsview function.

This post is too short to present all the numerous ways in which the control can be customized with the Java properties and methods. Let’s list some of the more interesting properties:

  • Border – specified the border frame around the button, which is responsible for its 3D appearance. It can be modified to anything from a simple colored borderline to a recurring icon-pattern, as shown here. If set to [] then the button achieves a flat appearance, which can be useful for displaying click-able labels. For example, the blog hyperlink at the bottom of the FindJObj window is a simple button with no border, an HTML label and a callback that opens this blog webpage using the built-in web function:
    Button appearing as a hyperlink label

    Button appearing as a hyperlink label

  • Cursor – this can be used to set a control-specific cursor. For example, in the hyperlink button above, the cursor was set to: java.awt.Cursor(java.awt.Cursor.HAND_CURSOR). In another post I’ll show how to set a custom cursor, like the following Matlab icon:
    Custom cursor

    Custom cursor

    Note: This feature only works on R2013a and earlier; custom cursors are ignored in Matlab R2013b and newer (see here).

  • DisplayedMnemonicIndex – (default=-1) indicates the character position within the text label where the Mnemonic (i.e, keyboard shortcut) should be displayed. Associated property Mnemonic (default=0) indicates the ASCII code of the mnemonic. In the following case, DisplayedMnemonicIndex=3 (remember that Java indices start at 0) and Mnemonic=73 (=’r’):
    Button With mnemonic

    Button With mnemonic

  • Margin, VerticalAlignment, HorizontalAlignment – these properties enable setting the label contents with respect to its borders. For example:
    Top-left with 8-pixel top margin

    Top-left with 8-pixel top margin

  • Icon, DisabledIcon, DisabledSelectedIcon, PressedIcon, RolloverIcon, RolloverSelectedIcon, SelectedIcon – these icons may be set to present a different appearance depending on component state. Associated property IconTextGap (default=4) determines the gap in pixels between the icon and the button text label. Associated properties HorizontalTextPosition and VerticalTextPosition specify the label text’s alignment relative to the label icon. These two properties accept the same SwingConstants values as HorizontalAlignment and VerticalAlignment above. For example, let’s display an icon to the right and upward of the text:
    
    myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/warning.gif');
    jButton.setIcon(javax.swing.ImageIcon(myIcon));
    jButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
    jButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
    

    Button with text and icon

    Button with text and icon

  • MultiClickThreshhold – (default=0) sets the number of milliseconds between subsequent processed user mouse clicks on the button. Any clicks that occur within the specified number (e.g., fast double-clicks) will be considered by the component as only a single click. The default value of 0 means that all clicks will be processed separately, which is often undesirable in GUI applications. Remember that the value is in milliseconds, not seconds.
  • FlyOverAppearance – boolean flag (default=false); if set, the button appearance is changed to a flat (2D) appearance with a special 3D border effect displayed on mouse hover. This appearance is useful for toolbar buttons, and is an extension by Matlab’s button implementation (does not exist in the standard Swing class).

There are quite a few other useful properties, methods (for example, jButton.doClick() to programmatically click a button) and even some 30 callbacks, detailed in a separate post. The list above is by no way comprehensive – I hope it whet your appetites for exploration using FindJObj and UIINSPECT – it’s a fun ride and the GUI rewards are worth the effort!

Please let me know of any nice customizations in your Matlab applications. Leave a comment below or drop me an email.

]]>
https://undocumentedmatlab.com/blog_old/button-customization/feed 30