Display name and Icon in Registry API

Display name and icon is in current Netbeans defined for lot of objects directly in module layer. This document analyses current state, usecases where declarative display name and icon are useful and proposes how this should work after switch to Registry API.

Current state

Any file defined in module layer (that is both file and folder) can have localized display name and icon. They are provided by following attributes which can be specified for file or folder:
  • SystemFileSystem.localizingBundle - value of this attribute is Bundle file containing localized name of the file/folder. The fullpath of the file is used as property key.
  • SystemFileSystem.icon - value of this property is URL pointing to localized icon of this file
The DataNode which is by default used as Node for DataObjects uses these attributes to implement Node.getDisplayName() and Node.getIcon() methods.

Usage

It is the way for module writers to define localized display name and icon for files for which there is general loader (eg. InstanceDataObject, DataFolder). These DataObjects can be then presented directly in UI.

Open issue: Anything else? It is possible I missed something.

So here are a few cases in detail:
  • Menu
The display name (and possibly icon) is defined on folders which stand for Menu and is used as menu name. Action instances in the folder do not define display name nor icon.
  • Toolbar
The display name is defined on toolbar's folder and is used as toolbar name. Action instances in the folder do not define display name nor icon.
  • New from Template
The display name is defined on folders and is used as name of group of templates. Files in the folder have display name and icon which are used as template name and icon.
  • Options
The display name and icon is defined on SystemOptions instances registered for Options dialog and are used for presentation of that instance.

Usecases

There are no direct user's usecases related to display name and icon.

Analysis

Looking at the current state there are two types of usage of display name and icon which should be supported after switch to Registry API:
  • lazy loading of objects
  • vizualization of folders

Lazy loading

According to Usage chapter it is clear that lot of objects could be loaded lazily. All what is needed to know about them is display name of the object and its icon. This information is sufficient for presentation of objects.

For example Templates. The template has display name and icon and till the concrete template is choosen for instantiation it is all what is needed to present all available templates in the system. Similarly (in future) panels in Options dialog: they have name and icon which is shown in left tree view, but actual panel is not needed till it is selected in the tree. Also Actions are good examples, but declarative enablement might be needed in addition to display name and icon to properly enable/disable action without loading its class.

Folder visualization

From the Usage chapter it is clear that folders are used directly in the UI and so they need to have some display name and possibly some icon. After switch to Registry the Registry Context will be used instead of Filesystem folder, but it will play the same role - the display name and icon of the Context will be needed.

Solution

The requirements identified in Analysis chapter must be addressed when we migrate to Registry API:

Lazy loading

This is out of scope of Registry API. It is up to clients who are defining some Contexts with some semantics to provide a way for lazy object declaration. Suggested way is illustrated on the example below.

Example of lazy loading support

Let's demonstrate this on simplified options dialog. Let's say we have following interface describing individual options panel:

public interface SimpleOptionsPanel {
    public String getDisplayName();
    public Icon getIcon();
    public JComponent getPanel();
    public boolean handleOK();
    public boolean handleCancel();
}

The UI of simple options dialog is simple too. It has two panes: the left pane contains plain list of names of panels with their icons and right pane contains JComponent created by the selected SimpleOptionsPanel. The implementations of the SimpleOptionsPanel interface are searched in defined Registry context for example /SimpleOptionsDialog. They are listed in the simple options dialog according to order in which they are defined in the context.

When simple options dialog is going to be shown the display names and icons of all registered panels need to be enumerated. Creating all instances bound in the context might be overhead when only their names and icons are needed.

Thus simple options dialog infrastructure should provide support for declaration of display name and icon. It should define persisted format of SimpleOptionsPanel objects which allows to declare:
  • display name
  • icon
  • real implementation of SimpleOptionsPanel
The format can look like:

<simpleoptionspanel xmlns=".../simpleoptionspanel_namespace">

    <displayname>
        <key>foopaneldisplayname</key>
        <localizingbundle>org.netbeans.module.foo.Bundle</localizingbundle>
    </displayname>
    <icon>nbres:/org/netbeans/module/foo/resources/foopanel.gif</icon>

    <!-- Here is the place for real panel instance definion. -->
    <!-- Let's use instance convertor for example: -->
    <instance xmlns="http://www.netbeans.org/ns/registry">
        <class>org.netbeans.module.foo.FooSimpleOptionsPanel</class>
    </instance>

</simpleoptionspanel>

Then it must register Convertor for such a format. The instance created by the Convertor will be wrapper which uses declared values to implement getDisplayName() and getIcon() method. Calling any other method results in loading of the real implementation class and delegation call to it.

This mechanism allows lazy loading of simple options panels and does not restrict module writers implementing the panels. The above format allows to define real panel instance whatever way clients want. Instead of <instance> element there can be whatever XML element (with subelements) under the condition that there is registered Convertor for that element - the format of the instance definition is not fixed! For example's sake the default instance convertor was used in example above.

The advantage of this design is that clients defining semantics of some contexts can provide their wrappers suitable and optimized for their types of objects. For example wrapper for actions can contain section for expressing declarative enablement of action, template wrapper can has additional fields like template description, etc.

The disadvantage is that display name and icon values are duplicated - they are defined in the Java class and also in XML module layer. To identify mistakes it is recommended that wrapper class compares real display name and icon when real instance was loaded with the declared values and log warning if they do not match.

Folder vizualization

There is more options how to solve this.

First is to let it as it is now. Reuse the attributes (but rename them) and add into some utilities module a new method which for the given Context returns its display name and icon.

Other option is to enhance Registry API with the concept of object's display name and icon. The disadvantage is that object's display name and icon do not fit into primary Registry API functionality and that it is expected that in future there might appear other attributes which would need to be added into Registry API. "Polluting" Registry API this way is not desired and so this option is rejected.

Another option (discussed in detail in the rest of this chapter) is to define a class (in different module than Registy API) which would represent "folder" and which instance could be bound directly to Registry. Such a class could look like:

public final class FolderDescriptor { // or ContextDesc? GroupDesc? VisualDesc?
    public
FolderDescriptor(String dispName, Icon icon) {...};
    public String getDisplayName() {...};
    public Icon getIcon() {...};
}

There would be convention that Context which should have display name and icon would have to have instance of FolderDescriptor bound under some fixed binding name like "contextvisualdescriptor". Everything would work as before, but instead of reading display name from attributes the well known binding would be retrieved with expected type of class. Clients enumerating context would have to ignore that binding.

More radical solution would be to extend the FolderDescriptor class with "path" which would point to the context it represents. That would by the way allow to define hierarchy of objects independent on the physical structure of Contexts. The class could look like:

public final class FolderDescriptor {
    public
FolderDescriptor(String dispName, Icon icon, String relativePath) {...};
    public String getDisplayName() {...};
    public Icon getIcon() {...};
    public String getPath() {...};
}

In this case the subcontexts would be completely ignored and instead of that the FolderDescriptor instances would be read and their path would be used to find "sub"folders. The path could be fully qualified or relative and would be resolved by the client according to context in which the instance of FolderDescriptor was found (there could be method Context FolderDescriptor.resolvePath(Context ctx) to simplify that). The declaration of such an object could look like:

<folderdescriptor xmlns=".../some_namespace">
    <displayname>
        <key>foldernamekey</key>
        <localizingbundle>org.netbeans.module.bar.Bundle</localizingbundle>
    </displayname>
    <icon>nbres:/org/netbeans/module/bar/resources/foldericon.gif</icon>
    <path>somepath
</path>
    <!-- somepath can be "/Menu/some/other/menu" or just "other" for
        
subcontext or even smth like "../../something/different" -->
</folderdescriptor>

I'm not sure whether it is advantage, but masking of subcontexts is much simplified, because it is masking of regular binding. Definitely the advantage is that hierarchy of objects is independent on structure of Contexts.

Other question is that FolderDescriptor makes perfect sense for Options case or New from Template case, but for Menu or Toolbar case the more natural would be for example MenuDescriptor with methods to create JMenuBar or JPopupMenu from the context full of action instances.

The specialized descriptor for menu could be also extended with features for menu only. For example one of the usecases mentioned in Ordering proposal was alphabetical sorting of menu items. The MenuDescriptor is ideal place where the alphabetical sorting could be set and which would override default Registry ordering. Rough and simplified example how the menu definition would look like in layer can be found here.

Open issues

1: How the Folder vizualization should be resolved? Any other proposals? If I should choose from the options I mentioned above I like more radical version with separate support for generic folders (including toolbar case) and for menu.

2: Are there any other usages of display name and icon in today's NetBeans which are not covered by this proposal?

Project Features

About this Project

openide was started in November 2009, is owned by Antonin Nebuzelsky, and has 87 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20160708.bf2ac18). © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
 
 
Close
loading
Please Confirm
Close