Navigator API is good for clients (module writers) that want to show some structure or outline of their document in dedicated window, allowing end user fast navigation and control over the document.
API allows its clients to plug in their Swing based views easily, which then will be automatically shown in specialized Navigator UI.
Added SPI interface NavigatorPanelWithToolbar. Clients will implement this interface when they need a toolbar for their Navigator view/panel.
Added @NavigatorPanel.Registration for ease of use and lazy loading.
Added NavigatorDisplayer which can be implemented to provide a different visualization of the navigator panels than in the default Navigator window. Can be useful in a different app than NetBeans IDE. Added NavigatorHandler.activateNavigator.
Apr 16 '07 Added SPI interface NavigatorLookupPanelsPolicy.
NavigatorLookupPanelsPolicy is new SPI interface for SPI clients who want to affect searching mechanism for available NavigatorPanel implementations. Method NavigatorLookupPanelsPolicy.getPanelsPolicy() allows for example to remove active Node/DataObject related NavigatorPanel implementations from Navigator window.
Apr 10 '07 Added SPI interface NavigatorPanelWithUndo.
NavigatorPanelWithUndo is new SPI interface which extands NavigatorPanel by support for undoing and redoing changes in navigation views. Method NavigatorPanelWithUndo.getUndoRedo() allows clients to specify UndoRedo support that will be propagated to the Navigator TopComponent when this panel is active in navigation area.
In order to plug in a view into Navigator UI for certain document (data) type, module writers need to write a NavigatorPanel implementation marked with @Registration.
Implementing NavigatorPanel interface is easy, you can copy from template basic implementation BasicNavPanelImpl.java.
Instantiation: Your implementation of NavigatorPanel is instantied automatically by the system if you register it using @Registration.
getComponent method: Simply create and return your UI representation of your data in Swing's JComponent envelope. Just be sure that you don't create new JComponent subclass per every call, as performance will suffer then.
Do *not* perform any long computation in panelActivated directly, see below.
In panelDeactivated, be sure to remove all listeners to context given to you in panelActivated.
Long computation of content: What if rendering your Navigator view takes long time, more than several milliseconds? Right approach is to create and run new task using RequestProcessor techniques, each time when panelActivated call arrived or your listeners on data context got called.
While computing, UI of Navigator view should show some please wait message.
Declarative registration of your NavigatorPanel impl connects this implementation with specific content type, which is type of the document, expressed in mime-type syntax, for example 'text/x-java' for java sources. Infrastructure will automatically load and show your NavigatorPanel impl in UI, when currently activated Node is backed by primary FileObject whose FileObject.getMimeType() equals to content type specified in your registering annotation (see more options below).
There may be situations where linking between your Navigator view and activated Node's primary FileObject is not enough or not possible at all. This simply happens when the data you want to represent in Navigator are not accessible through primary FileObject or DataObject. Usual example is Multiview environment, where more views of one document exists.
The solution is to bind content of your Navigator view directly to your TopComponent. Then, whenever your TopComponent gets activated in the system, Navigator UI will show th content you connected to it.
Choose your content type, could be either well known or arbitrary, say 'text/my-amazing-type' and do all basic steps described in above use case.
Alter your TopComponent to contain your NavigatorLookupHint implementation (AmazingTypeLookupHint in this case) in its lookup, returned from TopComponent.getLookup() method.
Another option you have is to alter lookup of your Node subclass instead of directly altering lookup of your TopComponent. See Node.getLookup() method. Then Navigator will show your desired content whenever your Node subclass will be active in the system.
However, keep in mind that this option is less preferred, because it only uses implementation detail knowledge that default implementation of TopComponent.getLookup() includes also results from lookup of asociated Node. So this approach will stop working if you change default behaviour of TopComponent.getLookup() method.
Programmatic activation of specific navigator panel activates and shows navigator panel in navigation area, as if user had selected the panel manually. API clients are expected to use programmatic activation to activate/select preferred panel from a set of available panels.
Example: Several TopComponents in multiview arrangement, TopComponentA and TopComponentB. Both components provide the same NavigatorLookupHint impl, which is recognized by two providers NavigatorPanelA and NavigatorPanelB. Now when TopComponentA becomes activated (has a focus), it's desirable to select/show NavigatorPanelA from navigator panels. On the other side, when TopComponentB is activated, NavigatorPanelB should be activated automatically.
Get the instance of NavigatorPanel implementation that you want to activate/show in navigator area.
Sometimes clients need to alter activated Nodes of Navigator window, to better represent Navigator area content within the whole application. See TopComponent.getActivatedNodes() and TopComponent.Registry.html#getActivatedNodes() to find out what activated nodes of TopComponent and whole system mean.
Use Case Example: NavigatorPanel implementation shows list or tree of some Nodes in Navigator area. When user selects a Node in the list or tree, it is desirable to show selected Node's properties in Properties window and enable proper actions in main menu. Exactly this can be done by presenting Node selected in the list/tree as activated Node of Navigator window.
In your implementation of NavigatorPanel, implement method getLookup() to return Lookup instance filled with Node(s) that you want to set as activated Nodes of Navigator window.
Some complex navigation views need support for undoing and redoing edit changes done either directly in the view or in document which the view is representing.
Implement your navigation view as NavigatorPanelWithUndo, which is NavigatorPanel interface with extra method getUndoRedo().
All other things remain the same as with basic NavigatorPanel usage. UndoRedo support returned from NavigatorPanelWithUndo.getUndoRedo() is propagated to the Navigator TopComponent and returned as its UndoRedo support. For details see TopComponent.getUndoRedo() and UndoRedo interface.
In certain situations it's not desired to show NavigatorPanel implementations related to DataObject of active Node in Navigator window. Typically you need to have active Node of some type, so that actions in the system works properly. But you don't want to show NavigatorPanels that "come" with such active Node.
Implement interface NavigatorLookupPanelsPolicy, return kind of policy that suits you from getPanelsPolicy() method.
Put implementation instance into your TopComponent's subclass lookup, see TopComponent.getLookup() for details.
Now when your TopComponent becomes active in the system, found panels policy is used to limit/affect set of available NavigatorPanel implementations.
Explorer views comes handy when showing Nodes in varienty of situations and it is just natural to be able to integrate them into Navigator window. Working with explorer views is described at ExplorerUtils javadoc. Integration with Navigator is easy and there are only subtle differencies from integration into TopComponent.
Implement NavigatorPanel interface and return created explorer view from getComponent() method. Creating explorer view is described in ExplorerUtils.
Return lookup created using ExplorerUtils.createLookup(ExplorerManager, ActionMap) from getLookup() method of NavigatorPanel.
Use ExplorerUtils.activateActions(ExplorerManager, boolean) for actions activation and deactivation in panelActivated and panelDeactivated.
Navigator listen to system activated node changes and sets activated node for Navigator top component accordingly. Local activated node is set from system activated node if any provider agrees to display content for data object behind the node. Navigator relies on default lookup mechanism of TopComponent to populate its activated node. Currently it means that if node backed by JavaDataObject is activated node in the system, it is also activated node for Navigator's top component. So main menu actions like Compile File, Move Class etc. work as usual when Navigator window is active. Also, lookup of currently selected Node is searched for NavigatorPanel SPI instances.