org.openide.explorer
.
Classes pertaining to the Property Sheet (which displays properties of
explored nodes) may be found in
org.openide.explorer.propertysheet
.
A set of standard Explorer Views is available in
org.openide.explorer.view
.
A given Explorer instance will be some visual component (such as a
Swing panel) displaying some representation of a subtree of the
complete Node hierarchy; the topmost node being displayed is said to
be the root of the Explorer. Be careful not to confuse the
root of a particular Explorer instance, which is selected according to
what the user wishes to see, with the root(s) of the entire Node
hierarchy, which generally are fixed.
However, the Explorer API is also used for other visual components
whose basic structure is derived from the structure of nodes, but for
which the treelike view in the normal Explorer is inappropriate. For
example, when a new object is to be created from template (by clicking
on the toolbar "New"), a dialog window pops up asking the user to
select a template. This window is actually a special view that only
displays one parent at a time, and displays the children as icons. In
fact, the popup menu obtained by right-clicking on a package ("New
from Template...") is really an Explorer view too!
The API permits you to use the prebuilt views, and also to create
your own if you need to.
If you want to use a special view, it is first necessary to
understand the structure of a live Explorer instance:
The package
Since views by default will share the same manager if they are
added to the same manager-providing container, just adding a regular
Explorer view and a property sheet to the same container will result
in the property sheet being sensitive to the node selection in the
regular view, which is usually the desired effect.
An Explorer view may be any
visual component;
it need not implement any particular interface, etc. However, the
convention is that it keep track of the Explorer manager that controls
it; this manager should be located when it is
added
to a parent component, by calling
The view will want to use a
property change listener
to keep track of what the manager expects it to do;
possibly it could also
veto
certain changes.
Other than these requirements, nearly any visual representation is
possible, and so the API does not specify any more than this.
You may want to customize the property editor behaviour in different situations:
Explorer views
The Explorer window that pops up when "Open Explorer" is selected, and
that is usually used by users wishing to look at some arbitrary part
of the system, is actually only one possible view of the Node
hierarchy--it provides a particular way of displaying and working with
the nodes.
Using the Explorer
It is rather easy to use the Explorer API to just display an Explorer
window of some type, browsing some set of nodes.
Displaying a new Explorer window
Probably the easiest way to pop up an Explorer window is just to call
TopManager.NodeOperation.explore(...)
.
This will simply show a node and its subtree (if any) in a new window
using the normal tree-style Explorer view. It does not permit any
customization of the UI, however--it creates a standard window with
the usual buttons, etc.
So, for most purposes it is possible to create a custom UI component
using Explorer views by starting with an ExplorerManager.Provider
.
This topmost container does not really do anything; it just makes sure
that an ExplorerManager
can be found by its
children. Most likely you can always just use
ExplorerPanel
,
which does nothing in particular except provide the ability to hold
one or more Explorer views, and add whatever displayable components
you like to it (treat it as a frame).
ExplorerManager
itself handles the control of the Explorer view or views it is
attached to. It provides the external interface by which the selection
of nodes, e.g., can be examined or set, and permits multiple views to
be synchronized. ExplorerPanel
can create a manager for
you.
ExplorerActions
object will be attached to the manager to make sure that such things
as cut/copy/paste actions are correctly enabled or disabled according
to the current node selection. Typically, the topmost component will
attach these actions to the manager when it is
activated
or otherwise given focus (and detach them when
not). ExplorerPanel
does this for you.
ExplorerManager.Provider
. This manager should then be
used for all interactions with the views.
ExplorerPanel
;
setting its layout if necessary; adding one or more Explorer views in
some configuration; adding other miscellaneous components if needed;
any preconfiguring the manager, for example by giving it a particular
root node to explore, according to the application's needs.
org.openide.explorer.view
contains a number of prebuilt views which you may use. Of special note
are the
BeanTreeView
,
which is the standard tree view used to implement the Explorer window
proper;
and
MenuView
,
which is of interest because it actually implements a view using popup
menus, rather than a static display. The best way to familiarize
yourself with the standard views, and to test any custom view you
might build, is probably to create an ExplorerPanel
which
adds some or all of them; the views will be automatically
synchronized, which will be helpful in understanding how they behave.
Displaying a property sheet
Adding a Property Sheet (which just shows the properties of
the selected node(s), and may allow editing of those properties) is
quite easy--all you need to do is to add a
PropertySheetView
to the container. It is an Explorer view which does not actually
display any nodes, but rather displays a list of properties for the
node or nodes which are selected according to a manager.
Aspects of nodes affecting the Explorer
Particular Explorer views are of course free to display the node
hierarchy any way they wish; however, there are a few common aspects
of the represented nodes which are likely to be visually mirrored:
Children.Keys
.
Generally nodes may allow their children to be
reordered.
Node.getActions()
,
Node.getContextActions()
,
Node.getDefaultAction()
,
Node.getContextMenu()
,
etc. are typically used to build an event-handling system for the
visual representation of the nodes.
Node.hasCustomizer()
,
Node.getCookie(...)
,
Node.getNewTypes()
,
Node.getPasteTypes(...)
,
and so on affect other UI components (such as toolbars) which may hold
action presenters.
Node.getPropertySets()
is of course used by the Property Sheet view.
Node.canRename()
,
Node.cloneNode()
,
or
Node.clipboardCut()
.
Customizing the Explorer
It is possible to customize how the Explorer works for specialized
purposes.
Creating a new Explorer view
Anyone may create a new Explorer view and use it for special purposes
with a custom UI, to provide an alternate representation of nodes
suited to some particular application. For example, you may require
that your view only display a root node of a certain class which has
added behaviors used in display. As a rule, it is preferable to add
special functionality directly to the node if that is possible, and to
use a special Explorer view only when a truly different means of
display is required.
ExplorerManager.find(...)
,
and then use that manager's properties to control it; the view should
also stop consulting the manager when the component is
removed
from its parent.
Subclassing the tree views
The abstract base class
TreeView
may be used to create a specialized view based on the normal visual
metaphor of an expandable tree of nodes being explored. Many
customizations to it may be done by modifying the
model
it uses to determine which nodes are to be displayed.
Or, one of its implementations may be fine-tuned:
BeanTreeView
provides the usual Explorer view;
ContextTreeView
provides something similar but only displaying non-leaf nodes (which
may be useful as one panel of a multi-paned UI setup, also including a
list view pane).
Customizing property editors
The core implementation provides a set of property editors for common types
of properties. These editors implement the org.openide.explorer.propertysheet.ExPropertyEditor
interface. It allows passing custom values to the property editor instances.
This can be useful for customizing the property editors appearance.
When creating a new bean
The properties can be passed to beaninfo. They are propagated through
BeanNode to the property editor. For example if you have a java.io.File property
in your bean you can use this in the beaninfo:
// assuming you have this line generated by the ide in the beaninfo class
properties[PROPERTY_testFile] = new PropertyDescriptor ( "testFile", TestBean.class, "getTestFile", "setTestFile" );
// or alternatively if you return your own array of PropertyDescriptors for
// your bean apply it to the appropriate PropertyDescriptor
// you can add a custom parameter to the PropertyDescriptor
properties[PROPERTY_testFile].setValue("files", Boolean.FALSE);
// (the property editor will not allow selecting files)
When creating a new node
You can directly pass the custom parameters to the properties. One
example is when overriding method createSheet --- you can use the property there.
Or anywhere where you have access to the org.openide.nodes.Node.Property
value of the property edited by the property editor.
protected Sheet createSheet() {
Sheet s = Sheet.createDefault();
try {
PropertySupport.ReadWrite p = new PropertySupport.ReadWrite (
"myDirectory", // NOI18N
java.io.File.class,
getString ("PROP_directory"),
getString ("HINT_directory")
) {
public Object getValue () {
return <get the value from somewhere>
}
public void setValue (Object o) {
<do something with the value>
}
};
p.setValue("files", Boolean.FALSE); // passing the custom property value here
s.get (Sheet.PROPERTIES).put(p);
} catch (Exception ex) {
TopManager.getDefault().getErrorManager ().notify (ex);
}
return s;
}
When using a PropertyPanel
If you use property panel for displaying the property value you can
pass the custom parameters while constructing the model for the property:
// t is a bean with methods getMyFile() and setMyFile(File)
DefaultPropertyModel model = new DefaultPropertyModel(t, "myFile");
model.getFeatureDescriptor().setValue("files", Boolean.FALSE);
PropertyPanel c = new PropertyPanel(model, PropertyPanel.PREF_CUSTOM_EDITOR);
getContentPane().add(c); // or whatever with c
When do you want to disable/enable Ok when displaying custom property editor
If you property editor supplies a custom property editor the IDE will display
the custom editor in separate window with Ok, Cancel buttons. If you want to
enable/disable the Ok button you can fire from your property editor (NOTE: from
the property editor, not from the custom property editor)
You can fire this change even if you property editor does not implement the
ExPropertyEditor interface. The Ok button should be enabled/disabled accordingly.
firePropertyChange (ExPropertyEditor.PROP_VALUE_VALID, null, Boolean.TRUE);
Custom parameters in core editors
Following table presents all property editors in core that can be
used with the mechanism of passing named properties. If you pass a
property that is not supported in the editor (or if you pass wrong argument
type) the custom parameter is ignored.
Property type | Parameter name | Parameter type | Description |
---|---|---|---|
java.io.File | directories | Boolean | should directories be selectable as values for the property |
files | Boolean | should files be selectable as values for the property | |
filter | javax.swing.filechooser.FileFilter, java.io.FileFilter, java.io.FilenameFilter | the value can be of any of the supported types and represents filter for the file dialog | |
currentDir | java.io.File | the dir that should be preselected when displaying the dialog | |
org.openide.ServiceType | createNew | Boolean | if set to true new instances of the services are created as values, default is false |
superClass | java.lang.Class | parent class of the service displayed in custom property editor, if not set org.openide.ServiceType is used | |
noneServiceClass | org.openide.ServiceType | service representing no service |
Affected part | Parameter name | Parameter type | Description |
---|---|---|---|
property sheet | canEditAsText | java.lang.Boolean | useful especially when passing value Boolean.FALSE - in this case disable the possibility of editing the the value as text but allows getAsText to return non null |
custom property editor display | title | java.lang.String | title of the custom property dialog, must be passed to the component itself (e.g. panel.putClientProperty("title", "New custom title.");) |
property sheet | longerDisplayName | java.lang.String | title for the property sheet, must be passed to the bean descriptor (or node) |