|
org.netbeans.spi.palette/1 1.10 | |||||||||
PREV NEXT | FRAMES NO FRAMES |
See:
Description
Common Palette | |
---|---|
org.netbeans.spi.palette |
The API provides access to the Common Component Palette. The palette clients can use this API to define content to be displayed in the common palette TopComponent when their editors are active. The module will autoload. Palette
The API includes support for the clients writing palette content insertable into the text editor.
This support covers the DTD definition of the palette item definition file format and the content
of the Lookup holding object(s) representing the selected item.
editor-palette-item-1_0.dtd
The previous version of palette API mandated that editor TopComponent had to insert a PaletteController instance into its Lookup if it wants to associate the palette with it. Now it is possible to associate the palette also with an existing editor without the need to change its implementation, e.g. to add code snippets palette to java source editor.
If the mime type of active editor window has an associated instance of PaletteController in the XML layer system then palette window opens and displays the specified palette contents. The PaletteController from TopComponent's Lookup takes precedens over the PaletteController found from mime type lookup in the XML layer (if any) for backwards compatibility.
The new API is fully backwards compatible and there are no implications for existing palette providers.
Now it's possible to specify item's display name and tooltip directly in item's XML definition (instead of providing bundle name and keys). It's needed for items created at runtime, for example code snippets highlighted in the editor and dropped to the palette.
Now it's possible to provide an action that will be invoked as part of palette's 'refresh' logic.
Now it's possible to add helpId attribute to palette's root, categories and items that will be used to create appropriate HelpCtx. The attribute can be specified in XML layer as a folder (palette's root and categories) or file attribute (palette items) or it can be provided directly by appropriate Nodes.
When F1 key is pressed in palette's window then first the selected item is asked for HelpCtx id. If no item is selected or it does not provide specific help id then selected category is checked for help id. If the category does not provide any help id either then palette's root is asked for help id. If the root does not define any then the default help id CommonPalette will be used.
To indicate that this is now considered a stable API, the major release version was incremented to 1 from 0.
The Common Palette content is a two-level hierarchy. The top-most level are Categories, the Category children are Items. It's possible to select (highlight) items in the palette panel using a mouse or keyboard and then inserted/dropped into an editor that supports the palette.
The palette content can come from two different sources:
The following steps must be taken if a module wants to define its own palette content as a hierarchy of folders and files in its XML layer:
<filesystem> <folder name="MyModulePalette"> <folder name="Category1"> <file name="PaletteItem_1.myitem" url="palette/PaletteItem_1.xml" /> <file name="PaletteItem_2.myitem" url="palette/PaletteItem_2.xml" /> <file name="PaletteItem_3.myitem" url="palette/PaletteItem_3.xml" /> </folder> <folder name="Category2"> <file name="PaletteItem_4.myitem" url="palette/PaletteItem_4.xml" /> <file name="PaletteItem_5.myitem" url="palette/PaletteItem_5.xml" /> <file name="PaletteItem_6.myitem" url="palette/PaletteItem_6.xml" /> </folder> </folder> </filesystem>
class MyPaletteActions extends PaletteActions { public Action getPreferredAction(Lookup lookup) { Node itemNode = (Node)lookup.lookup( Node.class ); if( null != itemNode ) { return new InsertItemAtDefaultLocationAction( itemNode ); } return null; } public Action[] getCustomItemActions(Lookup lookup) { Node itemNode = (Node)lookup.lookup( Node.class ); if( null != itemNode ) { return new Action[] { new CustomizeItemAction( itemNode ) }; } return null; } public Action[] getCustomCategoryActions(Lookup lookup) { Node categoryNode = (Node)lookup.lookup( Node.class ); if( null != categoryNode ) { return new Action[] { new CustomizeCategoryAction( categoryNode ) }; } return null; } public Action[] getImportActions() { return new Action[] { new ImportItemsFromWebAction() }; } public Action[] getCustomPaletteActions() { return null; //no custom actions for palette's root } }
class MyClass { PaletteController controller; PaletteController initializePalette() { try { controller = PaletteFactory.createPalette( "MyPalette", new MyPaletteActions() ); } catch (IOException ex) { ex.printStackTrace(); return; } controller.addPropertyChangeListener( new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if( PaletteController.PROP_SELECTED_ITEM.equals( evt.getPropertyName() ) ) { Lookup selItem = controller.getSelectedItem(); if( null == selItem ) { //nothing is selected in palette } else { Node selNode = (Node)selItem.lookup( Node.class ); if( null != selNode ) { //change mouse cursor for editor window to indicate //the type of palette item that can be dropped changeCursorInEditorWindow( selNode ); } } } } }); return controller; } }
class MyEditorTopComponent extends TopComponent { private MyEditorTopComponent() { this( new InstanceContent() ); } private MyEditorTopComponent( InstanceContent content ) { super( new AbstractLookup( content ) ); content.add( initializePalette() ); initEditorComponents(); } PaletteController controller; private PaletteController initializePalette() { if( null == controller ) { controller = PaletteFactory.createPalette( "MyPalette", new MyPaletteActions() ); } return controller; } }
When an item is selected in the palette and user clicks into the editor window then the module can ask for selected item by calling PaletteController.getSelectedItem(). This method returns a Lookup that holds object(s) representing the selected item. After the item is inserted into the editor window the module may clear palette's selection (PaletteController.clearSelection()) or leave the item selected to implement 'multi drop' insertion scenario.
It is possible to filter palette content and hide some categories and/or items from the user by extending PaletteFilter class.
class MyPaletteFilter extends PaletteFilter { public boolean isValidItem(Lookup lookup) { Node itemNode = (Node)lookup.lookup( Node.class ); return isItemVisibleInCurrentEditorContext( itemNode ); } public boolean isValidCategory(Lookup lookup) { Node categoryNode = (Node)lookup.lookup( Node.class ); return isCategoryVisibleInCurrentEditorContext( categoryNode ); } private boolean isItemVisibleInCurrentEditorContext( Node item ) { boolean res = true; //check current cursor positions and/or item type and decide whether //the item is valid, i.e. can be selected and dropped into editor return res; } private boolean isCategoryVisibleInCurrentEditorContext( Node item ) { boolean res = true; //check current cursor positions and/or category type and decide whether //the category is valid, i.e. its items can be selected and dropped into editor return res; }
Then initialize the palette using the following method:
MyPaletteFilter filter = new MyPaletteFilter(); PaletteController controller = PaletteFactory.createPalette( "MyPalette", new MyPaletteActions(), filter, null );
It is necessary to call PaletteController.refresh() to refresh and repaint the palette window whenever the filtering condition has changed:
myPaletteFilter.setShowSomeSpecialCategories( false ); paletteController.refresh();
The initial state of the palette can be overridden by setting appropriate attributes to palette model. The list of supported attributes is defined in PaletteController class. If the palette model is create from Nodes then the attributes are extracted by calling Node.getValue() method on the root Node and category and item nodes. If the palette model is defined as folders and files in the layer then the attributes are extracted by calling FileObject.getAttribute().
In the example below the palette will not show item names initially
(only icons are visible), the user can change this in palette's context menu.
Category1 is read-only therefore the user cannot remove it.
Category2 is not initially visible, the user can change this in
palette's customizer.
<filesystem> <folder name="MyModulePalette"> <attr name="showItemNames" stringvalue="false"/> <folder name="Category1"> <attr name="isReadonly" stringvalue="true"/> <file name="PaletteItem_1.myitem" url="palette/PaletteItem_1.myitem" /> <file name="PaletteItem_2.myitem" url="palette/PaletteItem_2.myitem" /> <file name="PaletteItem_3.myitem" url="palette/PaletteItem_3.myitem" /> </folder> <folder name="Category2"> <attr name="isVisible" stringvalue="false"/> <file name="PaletteItem_4.myitem" url="palette/PaletteItem_4.myitem" /> <file name="PaletteItem_5.myitem" url="palette/PaletteItem_5.myitem" /> <file name="PaletteItem_6.myitem" url="palette/PaletteItem_6.myitem" /> </folder> </folder> </filesystem>
It is possible to add new palette categories and/or palette item at runtime when the palette window is already visible.
Adding a new category is very straight-forward, it basically means creating a new folder under palette's root folder in XML layer:
FileSystem fs = Repository.getDefault().getDefaultFileSystem(); FileObject paletteRoot = fs.findResource( "MyModulePalette" ); paletteRoot.createFolder( "NewCategory" );
Adding a new item is a similar task:
FileObject paletteRoot = Repository.getDefault().getDefaultFileSystem().findResource( "MyPalette" ); FileObject targetCategoryFO = paletteRoot.getFileObject( "CategoryName" ); DataFolder targetCategoryDF = DataFolder.findFolder( targetCategoryFO ); DataObject dobj = (DataObject)itemNode.getLookup().lookup( DataObject.class ); dobj.copy( targetCategoryFolder );
Please refer to Nodes API in case the palette content is defined as a hierarchy of arbitrary Nodes.
The following steps must be taken when writing the item using the support provided by this module:
|
|
|
|
The sources for the module are in NetBeans CVS in core/palette directory.
Nothing.
Read more about the implementation in the answers to architecture questions.
|
org.netbeans.spi.palette/1 1.10 | |||||||||
PREV NEXT | FRAMES NO FRAMES |