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:
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.
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.
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.
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?