| <html><head><style> |
| BODY { |
| background-color: #ffffff; |
| font-size: 12px; |
| font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif; |
| color: #000000; |
| |
| margin-top:0px; |
| margin-left:10px; |
| margin-right:8px; |
| margin-bottom:16px; |
| |
| padding:0px; |
| min-width:780px; |
| } |
| |
| h1 { |
| font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif; |
| border-bottom:1px solid #AFAFAF; |
| clear:both; |
| font-size: 16px; |
| font-weight:bold; |
| margin:0px; |
| padding:0px; |
| color:#D20005; |
| } |
| |
| h2 { |
| font-size: 14px; |
| font-weight:bold; |
| margin:0px; |
| border-bottom:1px solid #808080; |
| margin-top:5px; |
| margin-bottom:5px; |
| color:#D20005; |
| } |
| |
| h3 { |
| font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif; |
| font-size: 13px; |
| font-weight:bold; |
| margin:0px; |
| padding:0px; |
| color:#D20005; |
| } |
| |
| .examplecode { |
| font-family: "Courier New", monospace; |
| background-color: #ffffcc; |
| } |
| </style><title>NetBeans Palette API tutorial</title></head> |
| |
| |
| |
| <body> |
| |
| <h1>NetBeans Palette API Tutorial</h1> |
| |
| <p>This tutorial shows you how to use the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/overview-summary.html">Palette API</a> and make a palette available for your |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html">TopComponent</a>. |
| You will also learn how to create a simple TopComponent using the wizard, how to display a status-bar message |
| and a dialog. But all these other things are just so that you'll learn how to display a nice palette for |
| your TopComponent, with icons, localized text and drag-and-drop support. |
| |
| </p><h2>Downloads</h2> |
| |
| <p>You are going to need for this tutorial |
| </p><ul> |
| <li>A functional NetBeans 5.x (with Java 1.4 or more) |
| </li><li>Optionally, the source code of this tutorial (<a href="http://www.lisp.ro/nb/module2.zip">download</a>) |
| </li></ul> |
| |
| <h2>Creating the module</h2> |
| |
| <ol> |
| <li>Choose File > New Project. Under Categories, select |
| NetBeans Plug-in Modules. Under projects, select Module Project and |
| click Next. </li> |
| <li>In the Name and Location panel, type <b>palette-demo</b> |
| in Project Name. Set the the Project Location and Project Folder to |
| whatever folder you fancy. Select the Standalone Modulde radio button |
| and select the Set as Main Project checkbox. Click Next. </li> |
| <li>In the Basic Module Configuration panel, set the Code Name Base to <b>com.example.palette</b> (or your preffered package name) and the Module Display Name to Palette Demo. Press Finish. |
| </li> |
| |
| </ol> |
| |
| <h2>Creating a window</h2> |
| |
| <p> |
| As seen in the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/overview-summary.html">Palette API javadoc</a>, you need to have an active <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html">TopComponent</a> in order to see the palette. For help regarding TopComponents, please check some other NetBeans tutorials. |
| </p> |
| |
| <ol> |
| <li>In the Projects window, select the <b>Palette Demo</b> (this is not necessary if |
| Palette Demo is your only project open). |
| </li> |
| <li>Choose File > New File... .Under Categories, select NetBeans Module Development, |
| then Window Component under File Types. Click Next. |
| </li> |
| |
| <li>In the Basic Settings panel, select <b>editor</b> for Window Position. Click Next. |
| </li> |
| <li>In the Name, Icon and Location panel, type <b>Drawing</b>. Click Finish. |
| </li> |
| </ol> |
| |
| <p> |
| The DrawingTopComponent should open in the GUI Editor and you should have some new generated |
| XML and Java files. |
| |
| </p><p> |
| <img width="640" src="../images/tutorials/palette_api/shot-01.jpg" alt="The TopComponent"> |
| |
| </p><p> |
| To see what you have managed so far, right-click the Palette Demo project and select |
| Install/Reload in Target Platform. A build should start and a new NetBeans instance should |
| run. In the new instance, select Window > Open Drawing Window. You should see an empty |
| window with the name Drawing Window. |
| |
| </p><h2>Adding a palette</h2> |
| |
| In order to use the Palette API you'll have to declare a dependency for your module. |
| <ol> |
| <li>Right-click the Palette Demo > Properties. |
| </li><li>Under the Libraries category click Add... . Select then Core - Component Palette and |
| Nodes API. Click Ok. |
| </li></ol> |
| |
| <p> |
| A Palette contains one or more categories with items. First you'll have to define a new item. |
| |
| </p><ol> |
| <li>Right-click the project, select New -> File/Folder... Choose XML under Categories then XML |
| Document under File Types. Click Browse... and select src/com/example/palette (Click Select Folder). |
| Click Next. |
| </li><li> |
| In the Name and Location panel, type simple-item for the File Name. Click Next. |
| </li><li> |
| In the Select Document Type choose DTD-Constrained Document. Click Next. |
| </li><li> |
| In the DTD Options, choose from the list for DTD Public ID <b>-//NetBeans//Editor Palette Item 1.0//EN</b>. |
| Select <b>editor_palette_item</b> for the Document Root. |
| Click Finish. |
| </li></ol> |
| |
| <p> |
| You should see this: |
| |
| </p><pre class="examplecode"><?xml version="1.0" encoding="UTF-8"?> |
| |
| <!-- |
| Document : <tt>simple-item.xml</tt> |
| Created on : February 25, 2006, 12:57 AM |
| Author : emi |
| Description: |
| Purpose of the document follows. |
| --> |
| |
| <!DOCTYPE editor_palette_item PUBLIC '-//NetBeans//Editor Palette Item 1.0//EN' |
| <b> "https://netbeans.org/dtds/editor-palette-item-1_0.dtd"</b>> |
| <editor_palette_item> |
| |
| </editor_palette_item> |
| </pre> |
| |
| <p> |
| Make sure to add the missing part above. |
| |
| </p><p> |
| We have now a barebone Palette Item. Open now the <b><tt>layer.xml</tt></b> file and add the following lines at the bottom, |
| before </ filesystem > |
| |
| </p><pre class="examplecode"> <folder name="MyPalette"> |
| <folder name="Category1"> |
| <file name="PaletteItem_1.xml" url="<tt>simple-item.xml</tt>"/> |
| </folder> |
| <folder name="Category2"> |
| <file name="PaletteItem_2.xml" url="<tt>simple-item.xml</tt>"/> |
| </folder> |
| </folder> |
| </pre> |
| |
| <p> |
| What did we do? We declared a folder called MyPalette (which will represent our palette) and added some |
| inner folders. These will be the categories. The files inside the categories folders are the items. |
| The items may have any names you want but note the <b>url</b> refers to the <tt>simple-item.xml</tt>. |
| |
| </p><h3>More items</h3> |
| |
| <p> |
| In order to have more than one item, you'll need to create more XML files (like <tt>simple-item.xml</tt>) and refer |
| them via <b>url</b> in the <tt>layer.xml</tt> file. The are ways of programatically adding new items, but you'll have |
| to refer to the Palette API Javadoc for that. |
| |
| </p><h3>Link it to the TopComponent</h3> |
| |
| <p> |
| But so far there is no link between our rudimentary palette and our TopComponent. The <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/overview-summary.html">Palette API javadoc</a> |
| helps us here. We need to create a <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteController.html">PaletteController</a> then link it to the <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html">TopComponent</a> (via <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/Lookup.html">Lookup</a>). |
| |
| </p><ol> |
| |
| <li><a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteFactory.html#createPalette%28java.lang.String,%20org.netbeans.spi.palette.PaletteActions%29">PaletteFactory.createPalette</a> takes care of the creation part. It just needs the palette name (meaning the |
| folder declared in the <tt>layer.xml</tt> and the actions for the palette). Since we don't need any actions right now |
| we'll just create a dummy anonymous inner class. |
| |
| <pre class="examplecode"> private PaletteController initializePalette() { |
| try { |
| return PaletteFactory.createPalette( "MyPalette", new <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteActions.html">PaletteActions</a>() { |
| public Action[] getCustomCategoryActions(Lookup lookup) { |
| return new Action[0]; |
| } |
| public Action[] getCustomItemActions(Lookup lookup) { |
| return new Action[0]; |
| } |
| public Action[] getCustomPaletteActions() { |
| return new Action[0]; |
| } |
| public Action[] getImportActions() { |
| return new Action[0]; |
| } |
| public Action getPreferredAction(Lookup lookup) { |
| return null; //TODO |
| } |
| }); |
| } catch (IOException ex) { |
| ex.printStackTrace(); |
| |
| } |
| return null; |
| } |
| |
| </pre> |
| |
| We add the initializePalette() method to the DrawingTopComponent class. Since there are going to be lots of import |
| problems an Alt + Shift + F should help (Source > Fix Imports). When you are asked about the Action class, |
| just select javax.swing.Action |
| |
| </li> |
| |
| <li> |
| We add the PaletteController in the Lookup of the TopComponent. We modify the DrawingTopComponent constructor |
| to accept an InstanceLookup and we add a new no-arg constructor: |
| |
| <pre class="examplecode"><b> private DrawingTopComponent(){ |
| this(new InstanceContent()); |
| } |
| </b> |
| private DrawingTopComponent(<b>InstanceContent content</b>) { |
| <b> super( new AbstractLookup( content ) ); |
| content.add( initializePalette() ); |
| </b> |
| initComponents(); |
| setName(NbBundle.getMessage(DrawingTopComponent.class, "CTL_DrawingTopComponent")); |
| setToolTipText(NbBundle.getMessage(DrawingTopComponent.class, "HINT_DrawingTopComponent")); |
| // setIcon(Utilities.loadImage(ICON_PATH, true)); |
| } |
| </pre> |
| </li> |
| |
| </ol> |
| |
| <p> |
| Re-run the application (Right-click Palette Demo > Install/Reload in |
| Target Platform). Select Window > Open Drawing Window should also |
| show the palette. |
| </p><p> |
| <img width="640" src="../images/tutorials/palette_api/shot-02.jpg"> |
| |
| </p><h2>But what does it do ?</h2> |
| |
| <p> |
| So far our Palette Demo is quite simple. The palette isn't that nice, no icons and it also doesn't do anything. |
| |
| </p><p> |
| First, let's add some icons for our palette items and localized text. |
| |
| </p><h3>Icons</h3> |
| |
| <p>The palette requires two versions of each icon for the palette item. A 16x16 pixel and a 32x32 version. |
| |
| </p><ol> |
| <li>Take 2 icons (the 16 and the 32 pixel icons) and add them to your project (this seems amazingly complicated; |
| just use your favorite file manager to copy the icons in src/com/example/palette). Name the two files |
| configure-16.png and configure-32.png. |
| </li><li>Edit the <tt>simple-item.xml</tt> file to configure the palette item with the new icon. The file should look like: |
| |
| <pre class="examplecode"><!DOCTYPE editor_palette_item PUBLIC '-//NetBeans//Editor Palette Item 1.0//EN' |
| <b> "https://netbeans.org/dtds/editor-palette-item-1_0.dtd"</b>> |
| <editor_palette_item><b> |
| <icon16 urlvalue="com/example/palette/configure-16.png" /> |
| <icon32 urlvalue="com/example/palette/configure-32.png" /> |
| </b></editor_palette_item> |
| </pre> |
| </li></ol> |
| |
| <h3>Text</h3> |
| |
| <ol> |
| <li>We change the <tt>simple-item.xml</tt> file some more and add text description |
| <pre class="examplecode"><editor_palette_item> |
| <icon16 urlvalue="com/example/palette/configure-16.png" /> |
| <icon32 urlvalue="com/example/palette/configure-32.png" /> |
| |
| <b> |
| <description localizing-bundle="com.example.palette.Bundle" |
| display-name-key="Item_Name" |
| tooltip-key="Item_Tooltip" /> |
| </b> |
| </editor_palette_item> |
| |
| </pre> |
| |
| <p>Each text should be possible to localize, you define the bundle (localizing-bundle) and then define the |
| display and tooltip key. |
| |
| </p></li><li>Since we make a reference in the <tt>simple-item.xml</tt> to the Bundle, we must edit it to add the new keys. |
| Open the Bundle.properties file and add the keys: |
| |
| <pre class="examplecode">CTL_DrawingAction=Open Drawing Window |
| CTL_DrawingTopComponent=Drawing Window |
| HINT_DrawingTopComponent=This is a Drawing window |
| OpenIDE-Module-Name=Palette Demo |
| <b>Item_Name=Item name |
| Item_Tooltip=A tooltip</b> |
| </pre> |
| |
| </li></ol> |
| |
| <p> |
| If you start the module in the platform, you should see the new icons and text: |
| |
| </p><p> |
| <img width="640" src="../images/tutorials/palette_api/shot-03.jpg"> |
| |
| </p><h2>Palette item class</h2> |
| |
| <p> |
| Ok, if you looked at the messages in the output window, you would probably see some warnings about the bad |
| XML format. Each palette item must have besides the icon and text an attached class. The class must implement |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-text/org/openide/text/ActiveEditorDrop.html">ActiveEditorDrop</a> (which assumes a text-only situation but works for non-text data also). The main part |
| of this class is to be instantiated by the Palette when doing a drag and drop operation. Here it goes: |
| |
| </p><ol> |
| <li>Add a new class (File > New File... > Java Classes category > Java Class) with the name <b>MyPaletteItem</b>. It should look like this: |
| |
| <pre class="examplecode">package com.example.palette; |
| |
| import javax.swing.text.JTextComponent; |
| import org.openide.text.ActiveEditorDrop; |
| |
| public class MyPaletteItem implements ActiveEditorDrop{ |
| public boolean handleTransfer(JTextComponent jTextComponent) { |
| //IGNORE, we don't really care |
| return true; |
| } |
| } |
| </pre> |
| |
| </li><li>Configure the palette items with the new class. palette-item.xml should be now: |
| |
| <pre class="examplecode"><editor_palette_item version='1.0'> |
| |
| <b> <class name="com.example.palette.MyPaletteItem"/></b> |
| |
| <icon16 urlvalue="com/example/palette/configure-16.png" /> |
| <icon32 urlvalue="com/example/palette/configure-32.png" /> |
| |
| <description localizing-bundle="com.example.palette.Bundle" |
| display-name-key="Item_Name" |
| tooltip-key="Item_Tooltip" /> |
| |
| </editor_palette_item> |
| </pre> |
| |
| </li></ol> |
| |
| <h3>Partial summary</h3> |
| |
| <p>So, in order to use the palette we must add to the Lookup of a TopComponent a PaletteController. When creating the |
| PaletteController, we give to the PaletteFactory the name of a palette folder in the <tt>layer.xml</tt>. |
| |
| </p><p>The folder structure in the <tt>layer.xml</tt> is quite simple, with subfolders for categories and files for items. Each |
| item must refer a standard XML file (with a specific Palette DTD). In the palette item XML we define the icons, |
| the text (via bundle keys) and a corresponding class. |
| |
| </p><h2>Next</h2> |
| |
| <p>What we need now is a way to: |
| </p><ul> |
| <li>Find out which element is selected in the Palette |
| </li><li>Do a drop of a Palette item |
| </li></ul> |
| |
| <h3>Selected element in the Palette</h3> |
| |
| <p>The Palette API allows us to place a listener for changes. Thus we find out the selected object. |
| |
| </p><ol> |
| <li>First, we add the <a href="https://netbeans.org/download/dev/javadoc/org-openide-awt/overview-summary.html">UI Utilities API</a> |
| to the library (Right-click on Palette Demo > Properties > |
| Libraries > Add.. and select UI Utilities API). It's not mandatory - |
| that is, you may add the listener without it - but it's nice to show |
| messages in the status bar. |
| </li><li>We edit the DrawingTopComponent constructor to place our listener: |
| |
| <pre class="examplecode"> private DrawingTopComponent(InstanceContent content) { |
| super( new AbstractLookup( content ) ); |
| <b> final PaletteController controller= initializePalette(); |
| content.add( controller ); |
| controller.addPropertyChangeListener( new PropertyChangeListener() { |
| public void propertyChange(PropertyChangeEvent evt) { |
| if( PaletteController.PROP_SELECTED_ITEM.equals( evt.getPropertyName() ) ) { |
| Lookup selItem = controller.getSelectedItem(); |
| if( null != selItem ) { |
| ActiveEditorDrop selNode = (ActiveEditorDrop)selItem.lookup( ActiveEditorDrop.class ); |
| if(null != selNode){ |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-awt/org/openide/awt/StatusDisplayer.html">StatusDisplayer</a>.getDefault().setStatusText("Selected "+selNode); |
| } |
| } |
| } |
| } |
| |
| }); |
| </b> |
| initComponents(); |
| setName(NbBundle.getMessage(DrawingTopComponent.class, "CTL_DrawingTopComponent")); |
| setToolTipText(NbBundle.getMessage(DrawingTopComponent.class, "HINT_DrawingTopComponent")); |
| // setIcon(Utilities.loadImage(ICON_PATH, true)); |
| } |
| </pre> |
| |
| Since there are going to be some import problems, a Source > Fix Imports is necessary. |
| </li></ol> |
| |
| <p>We now have the basic mechanism for our basic Palette implementation. We just need to modify the listener method |
| and do whatever we need (like change mouse cursor, do an action on next mouse click on our TopComponent, etc). |
| |
| </p><p><img src="../images/tutorials/palette_api/shot-04.jpg"> |
| |
| </p><h3>Drag and drop</h3> |
| |
| <p> |
| The Palette already takes care of the drag part, we just have to provide the drop. (Actually we could also customize |
| the drag with some custom flavors. Better check the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/overview-summary.html">Palette API javadoc</a> if you are in need of such things). |
| |
| </p><p>Since we are going to display a message dialog, you need to add the <a href="https://netbeans.org/download/dev/javadoc/org-openide-dialogs/overview-summary.html">Dialogs API</a> to the module dependencies |
| (Right-click Palette Demo > Properties > Libraries > Add... > Dialogs API) |
| |
| </p><p> |
| |
| Modify the DrawingTopComponent and add the following code |
| |
| </p><pre class="examplecode"> private DrawingTopComponent(InstanceContent content) { |
| super( new AbstractLookup( content ) ); |
| final PaletteController controller= initializePalette(); |
| content.add( controller ); |
| controller.addPropertyChangeListener( XXX); // removed to save space |
| <b>setDropTarget(new DropTarget(this,new <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/awt/dnd/DropTargetListener.html">DropTargetListener</a>() { |
| public void dragEnter(DropTargetDragEvent dropTargetDragEvent) { |
| } |
| public void dragExit(DropTargetEvent dropTargetEvent) { |
| } |
| public void dragOver(DropTargetDragEvent dropTargetDragEvent) { |
| } |
| public void drop(DropTargetDropEvent dropTargetDropEvent) { |
| NotifyDescriptor d =new NotifyDescriptor.Message("Drop", |
| NotifyDescriptor.INFORMATION_MESSAGE); |
| DialogDisplayer.getDefault().notify(d); |
| |
| } |
| public void dropActionChanged(DropTargetDragEvent dropTargetDragEvent) { |
| } |
| }));</b> |
| //the rest removed to save space |
| </pre> |
| |
| <p>That's all there is to it. Our <b>drop</b> method is invoked when necessary and we may use the Palette API for |
| fun and profit ! |
| |
| </p><p>Please note that in order to make drop work nicely you should comment the select code (at least the display of |
| the dialog) since it would interfere with the drop. |
| |
| </p><h2>Some fun</h2> |
| |
| <ol> |
| <li> |
| Open the DrawingTopComponent in Design mode, right-click the design window, select Layout and click Null Layout. |
| </li><li>Open it now in Source mode, and modify the <b>drop</b> method: |
| |
| <pre class="examplecode"> public void drop(DropTargetDropEvent dropTargetDropEvent) { |
| JButton j=new JButton("drop"); |
| j.setBounds(dropTargetDropEvent.getLocation().x, |
| dropTargetDropEvent.getLocation().y,100,20); |
| add(j); |
| |
| validate(); |
| repaint(); |
| |
| //accept drop |
| dropTargetDropEvent.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); |
| } |
| </pre> |
| |
| <p> |
| The code above adds a JButton on the coordinates of the drop. |
| |
| </p></li></ol> |
| |
| <p> |
| <img src="../images/tutorials/palette_api/shot-05.jpg"> |
| |
| |
| <br> |
| <div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback:%20Palette%20API%20Module%20Tutorial">Send Us Your Feedback</a></div> |
| <br style="clear:both;" /> |
| |
| </p><h2>Versioning</h2> |
| |
| <ol> |
| <li> 26 February 2006 - Initial version |
| </li></ol> |
| |
| <h3>Notes</h3> |
| |
| <p>Tutorial made by Emilian Bold (http://web.info.uvt.ro/~fierarul/typo3/) |
| |
| </p><p>The sample code has two icons from the Nuvola set, which is LGPL. Feel free to contact me, as LGPL requires, in |
| order to get the full set. Hopefully I'll replace those icons with some BSD ones. |
| |
| </p></body></html> |