| <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 Drag and Drop Tutorial</title></head> |
| |
| |
| |
| <body> |
| |
| <h1>NetBeans Drag and Drop Tutorial</h1> |
| <hr> |
| <p><b>Draft tutorial: Use/believe at your own risk.</b> |
| <hr> |
| |
| <p>Drag and drop enables data transfer |
| across Java programming language and |
| native applications, between Java programming |
| language applications, and within a single Java |
| programming language application. Within the |
| context of the NetBeans APIs, drag and drop is |
| commonly used between the Component Palette |
| and a Swing component. Different types of files |
| may provide different types of Component Palettes. |
| For example, JSP files in NetBeans IDE come |
| with a Component Palette with items that |
| generate JSP tags in the IDE's Source Editor. |
| Similarly, a Swing container in the IDE, such |
| as a JFrame, is supported by a Component |
| Palette containing items that can be dragged |
| and dropped onto the JFrame. |
| |
| <p>In this tutorial, you will learn how to |
| create a Component Palette for a custom |
| component. A custom component is |
| provided by the NetBeans API TopComponent class. |
| You will use a wizard to create |
| a TopComponent. Then you will create items |
| that can be dragged from the TopComponent's |
| Component Palette onto the TopComponent. You will |
| also be shown how to add functionality for dragging |
| an item after it has been dropped. |
| |
| |
| <p>In this tutorial, you will do the following: |
| |
| <ol> |
| <li>Use the File Type wizard to create a |
| new file type recognized by file extension. The |
| file type will be used to create the items in |
| the Component Palette. |
| <li>Create the file |
| content that you want to drag |
| from the Component Palette onto the TopComponent. |
| <li>Edit the data loader and data node |
| to add the data into |
| the data node's transferable. |
| <li>Create a few more sample files |
| and create a palette folder in the XML layer file, to |
| register the items. |
| <li>Use the Window Component wizard to create |
| a new TopComponent. |
| <li>Add a palette controller to the TopComponent's |
| Lookup. |
| <li>Create an item displayer class for rendering |
| the item on the TopComponent. |
| <li>Add drag and drop listeners to the |
| TopComponent, for handling drag and drop events. |
| </ol> |
| |
| <p>The following topics are covered below:</p> |
| <ul> |
| |
| <li><a href="#prerequisites">Prerequisites</a> |
| <li><a href="#requirements">Requirements</a></li> |
| <li><a href="#sample">Looking at the Sample</a></li> |
| <li><a href="#moduleproject">Creating the Module Project</a></li> |
| <li><a href="#topcomponent">Creating a Custom Window Component</a></li> |
| <li><a href="#dataloader">Creating a New File Type</a></li> |
| <li><a href="#dependencies">Setting Dependencies</a></li> |
| <li><a href="#item">Creating, Registering, and Using a Drag and Drop Item</a></li> |
| <li><a href="#associating">Associating a Component Palette with a Window Component</a></li> |
| <li><a href="#droptarget">Creating a Drop Target</a></li> |
| <li><a href="#draggesture">Defining a Drag Gesture</a></li> |
| <li><a href="#dragimage">Defining a Drag Image</a></li> |
| <li><a href="#additionalitems">Adding Additional Items</a></li> |
| <li>Supplemental Topics</a></li> |
| <ul> |
| <li><a href="#visuallibraryapi">Drag and Drop and the Visual Library API</a></li> |
| <li><a href="#explorermanagerapi">Drag and Drop and Bean Tree Views</a></li> |
| <li><a href="#sourceeditor">Drag and Drop and the NetBeans Source Editor</a></li> |
| <li><a href="#existing">Adding Items to Existing Component Palettes</a></li> |
| </ul> |
| </ul> |
| |
| |
| |
| <p><a name="top"></a>Once the software is installed, this tutorial can be completed in 60 minutes. |
| |
| <p>For more information on working with modules, see the <a href="https://platform.netbeans.org/index.html"> |
| NetBeans Development Project home</a> on the NetBeans website. If you have questions, visit the |
| <a href="http://wiki.netbeans.org/wiki/view/NetBeansDeveloperFAQ">NetBeans Developer FAQ</a> or use the feedback link |
| at the top of this page.</p> |
| |
| <br /> |
| |
| |
| |
| |
| <h2 class="tutorial"><a name="prerequisites"></a>Prerequisites</h2> |
| <p>Before beginning this tutorial, you need |
| to be familiar with the concepts and terminology relating to Swing drag and drop. |
| |
| |
| <p>As a quick refresher, here are some common terms used in Swing drag and drop, taken |
| directly from the specification: |
| |
| <ul> |
| <li><b>Drag Source.</b> The entity responsible for the initiation of the drag and drop operation. |
| <li><b>Drop Target.</b> Encapsulates all of the platform-specific handling of the Drag and Drop |
| protocol with respect to the role of the recipient or destination of the operation. |
| <li><b>Transferable.</b> Represents the object(s) or data that are the operand(s), |
| or the subject(s), of the Drag and Drop operation, that is, the information that will |
| subsequently be passed from the DragSource to the DropTarget as a result of a successful |
| Drop on the Component associated with that DropTarget. |
| <li><b>Data Flavor.</b> The type of data. |
| <li><b>DragGestureEvent.</b> Encapsulates all the information regarding the nature of the gesture |
| that has just been recognized. |
| </ul> |
| |
| <p>For details on these and other concepts related to drag and drop, see the links listed above. |
| |
| <h2 class="tutorial"><a name="requirements"></a>Requirements</h2> |
| |
| <ul> |
| <li>NetBeans IDE 5.x. |
| <li>Optionally, and for troubleshooting purposes, the sources of the sample discussed in this tutorial. (To come.) |
| </ul> |
| |
| |
| |
| <h2 class="tutorial"><a name="sample"></a>Looking at the Sample</h2> |
| |
| <p>Once completed, the module that this tutorial shows |
| you how to build will look as follows: |
| |
| <p><img border=1 src="../images/tutorials/palette_api/dndsample1.png"> |
| |
| |
| <p>When you install the module, you will have a TopComponent |
| with a Component Palette. You will be able to drag an item from |
| the Component Palette and drop it in a JPanel within the |
| TopComponent: |
| |
| <p><img border=1 src="../images/tutorials/palette_api/dndsample4.png"> |
| |
| <p>When you drag the dropped item, you will be able to drop it |
| somewhere else on the JPanel in the TopComponent. |
| |
| <p>You will also be able to drag the item from an explorer window, |
| in addition to being able to do so from the Component Palette: |
| |
| <p><img border=1 src="../images/tutorials/palette_api/dndsample5.png"> |
| |
| <p>When you drag the item from the Component Palette, as shown above, you |
| will be able to drop it on the JPanel in the TopComponent. |
| |
| <p>You will also be shown how to add a drag image at the cursor: |
| |
| |
| <p><img border=1 src="../images/tutorials/palette_api/dndsample6.png"> |
| |
| |
| <h2 class="tutorial"><a name="moduleproject"></a>Creating the Module Project</h2> |
| |
| <ol> |
| <p><li>Choose File > New Project. Under Categories, select |
| NetBeans Plug-in Modules. Under projects, select Module Project. |
| Click Next. |
| <p><li>In the Name and Location panel, type <tt>DragAndDropSample</tt> |
| in Project Name. |
| <p><li>In Project Location, specify an appropriate location for |
| storing your module. |
| <p><li>Select the Standalone Module radio button, if not selected. |
| <p><li>Select the Set as Main Project checkbox, if not selected. |
| Click Next. |
| <p><li>In the Basic Module Configuration panel, set the Code Name |
| Base to <tt>org.netbeans.dndsample</tt>. |
| <p><li>Leave the Module Display Name as <tt>DragAndDropSample</tt>. |
| Click Finish. |
| |
| |
| </ol> |
| |
| |
| <h2 class="tutorial"><a name="topcomponent"></a>Creating a Custom Window Component</h2> |
| |
| |
| <ol> |
| <p><li>In the Projects window, right-click the DragAndDropSample |
| project, |
| and choose New > File/Folder. In the New File wizard, |
| under Categories, select NetBeans Module Development. |
| Under File Types, select Window Component. Click Next. |
| <p><li>In the Basic Settings panel, select <tt>editor</tt> as |
| the Window Position. This specifies that the window component will |
| open in the 'editor' area of the IDE. |
| <p><li>Select Open on Application Start. Click Next. |
| <p><li>In the Name, Icon and Location panel, type |
| <tt>DropTargetWindow</tt>. Optionally, select an icon |
| with a dimension of 16x16 pixels. Click Finish. |
| <p> |
| The DropTargetWindowTopComponent opens in the IDE, |
| together with several supporting |
| XML and Java files. |
| |
| <li>Right-click the module project and choose Install/Reload |
| in Development IDE. |
| |
| <p>If you receive a warning message, click OK. Once it is installed, |
| go to the Window menu and choose Open DropTargetWindow Window. |
| The new window component opens in the IDE. |
| |
| </ol> |
| |
| <h2 class="tutorial"><a name="dataloader"></a>Creating a New File Type</h2> |
| |
| |
| <ol> |
| <p><li>In the Projects window, right-click the project |
| and choose New > File/Folder. In the New File wizard, |
| under Categories, select NetBeans Module Development. |
| Under File Types, select File Type. Click Next. |
| <p><li>In the Basic Settings panel, set the following: |
| <ul> |
| <li>MIME Type: <tt>text/x-my-palette-item</tt> |
| <li>Extension(s): <tt>myitem</tt> |
| </ul> |
| Click Next. |
| <p><li>In the Name, Icon and Location panel, type |
| <tt>MyItem</tt> as the Class Name Prefix. Optionally, select an icon |
| with a dimension of 16x16 pixels. |
| <p><li>In Package, type <tt>org.netbeans.dndsample.palette</tt>. |
| Click Finish. |
| </ol> |
| |
| <h2 class="tutorial"><a name="dependencies"></a>Setting Dependencies</h2> |
| |
| <p>To use the Palette API, |
| you need to declare a dependency on the Component Palette API. |
| <ol> |
| <p><li>Right-click the module project and choose Properties. |
| <p><li>In the Libraries category, click Add, next to the |
| Module Dependencies list. |
| <p><li>Add <tt>Core - Component Palette</tt> |
| to the list of dependencies. The following dependencies |
| should now be in the module dependencies list: |
| <p><ul> |
| <li>Core - Component Palette |
| <li>Datasystems API |
| <li>File System API |
| <li>Nodes API |
| <li>Swing Layout Extensions integration |
| <li>Text API |
| <li>UI Utilities API |
| <li>Utilities API |
| <li>Window System API |
| </ul> |
| |
| <p><li>Click OK. |
| </ol> |
| |
| |
| <h2 class="tutorial"><a name="item"></a>Creating, Registering, and Using a Drag and Drop Item</h2> |
| |
| <p>Each item that you drag from the Component Palette |
| can contain information that you want to transfer |
| to the drop target. In this section, you are shown how |
| to provide information to an item and how to register |
| the item in the <tt>layer.xml</tt> file. |
| |
| <ol> |
| <p><li>Create a new package called |
| <tt>org.netbeans.dndsample.palette.items</tt>. |
| <p><li>Move <tt>MyItemTemplate.myitem</tt> |
| into the new package. |
| <p><li>Rename <tt>MyItemTemplate.myitem</tt> |
| to <tt>id1.myitem</tt>. |
| <p><li>Replace the content of the file |
| with the following: |
| <pre class="examplecode">id=id1 |
| displayName=Item 1 |
| icon16=org/netbeans/dndsample/palette/items/bean.gif |
| icon32=org/netbeans/dndsample/palette/items/bean32.gif |
| comment=This is item 1</pre> |
| <p><li>Add two image files, called |
| bean.gif and bean32.gif, to the package. The former |
| must be 16x16 pixels in size; the latter 32x32 pixels. |
| You can create you own or right-click the two images here |
| and save them in the folder specified in the item |
| file above: |
| |
| <p><img border=1 src="../images/tutorials/palette_api/bean.gif"> |
| |
| <p><img border=1 src="../images/tutorials/palette_api/bean32.gif"> |
| |
| |
| <p><li>Register the item in the <tt>layer.xml</tt> |
| file, below the opening <tt><filesystem></tt> tag, as follows: |
| <pre class="examplecode"><folder name="MyPalette"> |
| <folder name="Category"> |
| <file name="Item1.myitem" url="palette/items/id1.myitem"/> |
| </folder> |
| </folder></pre> |
| |
| <p><li>In <tt>org.netbeans.dndsample.palette</tt>, |
| create a Java class called <tt>MyItemData.java</tt>. The |
| content of the file is as follows: |
| |
| <p><pre class="examplecode">package org.netbeans.dndsample.palette; |
| |
| import java.awt.Image; |
| import java.util.Properties; |
| import org.openide.util.Utilities; |
| |
| public class MyItemData { |
| private Properties props; |
| |
| private Image icon16; |
| private Image icon32; |
| |
| public static final String PROP_ID = "id"; |
| public static final String PROP_NAME = "displayName"; |
| public static final String PROP_COMMENT = "comment"; |
| public static final String PROP_ICON16 = "icon16"; |
| public static final String PROP_ICON32 = "icon32"; |
| |
| /** Creates a new instance of MyItemData */ |
| MyItemData( Properties props ) { |
| this.props = props; |
| loadIcons(); |
| } |
| |
| public String getId() { |
| return props.getProperty( PROP_ID ); |
| } |
| |
| public String getDisplayName() { |
| return props.getProperty( PROP_NAME ); |
| } |
| |
| public String getComment() { |
| return props.getProperty( PROP_COMMENT ); |
| } |
| |
| public Image getSmallImage() { |
| return icon16; |
| } |
| |
| public Image getBigImage() { |
| return icon32; |
| } |
| |
| public boolean equals(Object obj) { |
| if( obj instanceof MyItemData ) { |
| return getId().equals( ((MyItemData)obj).getId() ); |
| } |
| return false; |
| } |
| |
| private void loadIcons() { |
| String iconId = props.getProperty( PROP_ICON16 ); |
| icon16 = Utilities.loadImage( iconId ); |
| iconId = props.getProperty( PROP_ICON32 ); |
| icon32 = Utilities.loadImage( iconId ); |
| } |
| }</pre> |
| |
| <p><li>We need to load the content of our data object |
| into the MyItemData class. To do this, declare the |
| MyItemData class at the top of the MyItemDataObject class: |
| |
| <p><pre class="examplecode">private MyItemData data;</pre> |
| |
| <p>Next, change the data object's Constructor to |
| the following: |
| |
| <p><pre class="examplecode">public MyItemDataObject(FileObject pf, MyItemDataLoader loader) throws DataObjectExistsException, IOException { |
| super(pf, loader); |
| //DND start |
| //create the 'data' from properties file: |
| InputStream input = pf.getInputStream(); |
| Properties props = new Properties(); |
| props.load( input ); |
| input.close(); |
| data = new MyItemData( props ); |
| //DND end |
| }</pre> |
| |
| <p>Change <tt>createNodeDelegate()</tt>, so that the |
| data is passed to the node, together with the data object: |
| |
| <p><pre class="examplecode">protected Node createNodeDelegate() { |
| return new MyItemDataNode(this, data ); |
| }</pre> |
| |
| |
| <p>When prompted, let the IDE generate the following |
| import statements: |
| |
| <p><pre class="examplecode">import java.io.InputStream; |
| import java.util.Properties;</pre> |
| |
| |
| |
| <p><li>Now we edit the data node to add the data |
| to the data node's transferable. The data node |
| should be as follows: |
| |
| <p><pre class="examplecode">package org.netbeans.dndsample.palette; |
| |
| import java.awt.Image; |
| import java.awt.datatransfer.Transferable; |
| import java.awt.datatransfer.UnsupportedFlavorException; |
| import java.beans.BeanInfo; |
| import java.io.IOException; |
| import org.openide.loaders.DataNode; |
| import org.openide.nodes.Children; |
| import org.openide.util.datatransfer.ExTransferable; |
| |
| public class MyItemDataNode extends DataNode { |
| private MyItemData data; |
| |
| public MyItemDataNode( MyItemDataObject obj, MyItemData data ) { |
| super( obj, Children.LEAF ); |
| this.data = data; |
| setName( data.getId() ); |
| setShortDescription( data.getComment() ); |
| } |
| |
| public Image getIcon(int i) { |
| if( i == BeanInfo.ICON_COLOR_16x16 || i == BeanInfo.ICON_MONO_16x16 ) { |
| return data.getSmallImage(); |
| } |
| return data.getBigImage(); |
| } |
| |
| public String getDisplayName() { |
| return data.getDisplayName(); |
| } |
| |
| // DND start |
| public Transferable drag() throws IOException { |
| ExTransferable retValue = ExTransferable.create( super.drag() ); |
| //add the 'data' into the Transferable |
| retValue.put( new ExTransferable.Single( Utils.MY_DATA_FLAVOR ) { |
| protected Object getData() throws IOException, UnsupportedFlavorException { |
| return data; |
| } |
| }); |
| return retValue; |
| } |
| //DND end |
| }</pre> |
| |
| <p>An error remains because the code referes to a data flavor |
| in a class that you have not created yet. You will do so |
| in the next step. |
| |
| <p><li>In <tt>org.netbeans.dndsample.palette</tt>, |
| create a Java class named <tt>Utils.java</tt>. |
| |
| |
| <p>Create the following data flavor |
| at the top of Utils.java: |
| |
| <p><pre class="examplecode">public static final DataFlavor MY_DATA_FLAVOR = new DataFlavor( MyItemData.class, "My Item Data" );</pre> |
| |
| <p>When prompted, let the IDE generate an import statement |
| for <tt>java.awt.datatransfer.DataFlavor</tt>. |
| |
| </ol> |
| <p>Here, you have declared a folder called "MyPalette". This |
| represents our palette in the <tt>layer.xml</tt> file. |
| We added an |
| inner folder, which will be a new category. The files inside the categories folders are the items. |
| The items may have any names you want but note |
| the <tt>url</tt> attribute refers to the location |
| of our item data. |
| |
| <h2 class="tutorial"><a name="associating"></a>Associating a Component Palette with the Window Component</h2> |
| |
| <ol> |
| |
| <p><li>At the end of the window component's Constructor, |
| add the following lines: |
| |
| <p><pre class="examplecode">//make sure the common palette shows up when this window is activated |
| associateLookup( Lookups.fixed( new Object[] {Utils.getPalette()} ) );</pre> |
| |
| |
| <p><li>The IDE prompts you to create an import statement |
| for <tt>org.openide.util.lookup.Lookup</tt>. Click on |
| the tip to let the IDE generate the import statement. |
| |
| |
| <p><li>Declare the palette controller at the top of the Utils.java |
| class: |
| |
| <p><pre class="examplecode">private static PaletteController thePalette;</pre> |
| |
| <p><li>Add this |
| method to the Utils.java class: |
| |
| <pre class="examplecode">public static PaletteController getPalette() { |
| //create the palette |
| if( null == thePalette ) { |
| try { |
| //DND start |
| //use custom DragAndDropHandler when creating the palette so that our custom |
| //dataflavor gets added when an item is being dragged from the palette: |
| thePalette = PaletteFactory.createPalette( "MyPalette", new MyActions() );//, null, new MyDnDHandler() ); |
| //DND end |
| } catch (IOException ex) { |
| ex.printStackTrace(); |
| } |
| } |
| return thePalette; |
| }</pre> |
| |
| <p><li>Add the following actions to the Utils.java class: |
| |
| <p><pre class="examplecode">private static class MyActions extends PaletteActions { |
| public Action[] getImportActions() { |
| return null; |
| } |
| |
| public Action[] getCustomPaletteActions() { |
| return null; |
| } |
| |
| public Action[] getCustomCategoryActions(Lookup lookup) { |
| return null; |
| } |
| |
| public Action[] getCustomItemActions(Lookup lookup) { |
| return null; |
| } |
| |
| public Action getPreferredAction(Lookup lookup) { |
| return null; |
| } |
| |
| }</pre> |
| |
| <p><li>Right-click in the Source Editor, choose Fix Imports, |
| and choose to import <tt>javax.swing.Action</tt>. |
| |
| <p><li>Right-click the module project and choose Install/Reload |
| in Development IDE. |
| |
| <p><li>Once it is installed, |
| go to the Window menu and choose Open DropTargetWindow Window. |
| The window component opens in the IDE. The new |
| Component Palette, containing your one item, is |
| displayed as well: |
| |
| <p><img border=1 src="../images/tutorials/palette_api/dndsample2.png"> |
| |
| <p>As can be seen above, you can drag the item, but you |
| cannot drop it. That is because you have not created |
| a drop target yet, which we will do in the next section. |
| When you right-click in the Component Palette, several |
| menu items are available, which you didn't have to |
| code yourself. For example, if you choose Show Big Icons, |
| the 32x32 pixel icon will be shown. |
| |
| <p><img border=1 src="../images/tutorials/palette_api/dndsample3.png"> |
| |
| </ol> |
| |
| |
| <h2 class="tutorial"><a name="droptarget"></a>Creating a Drop Target</h2> |
| |
| <p><ol><li>In <tt>org.netbeans.dndsample</tt>, |
| create a Java class called <tt>ItemDataDisplayer.java</tt>. |
| You will use this class to render the data in your |
| window component. It extends <tt>JLabel</tt> and is defined |
| as follows: |
| |
| <p><pre class="examplecode">package org.netbeans.dndsample; |
| |
| import javax.swing.ImageIcon; |
| import javax.swing.JLabel; |
| import org.netbeans.dndsample.palette.MyItemData; |
| |
| public class ItemDataDisplayer extends JLabel { |
| |
| private MyItemData data; |
| |
| /** Creates a new instance of ItemDataDisplayer */ |
| public ItemDataDisplayer( MyItemData data ) { |
| super( "" ); |
| this.data = data; |
| setIcon( new ImageIcon( data.getBigImage() ) ); |
| setToolTipText( data.getComment() ); |
| } |
| |
| public MyItemData getData() { |
| return data; |
| } |
| }</pre> |
| |
| |
| <li>Open DropTargetWindowTopComponent in the Design view |
| of the GUI Builder. |
| <p><li>Drag a JPanel from the Component Palette and drop |
| it on the window component. |
| <p><li>Resize the JPanel so that it covers the whole |
| window component. |
| <p><li>Right-click in the JPanel, choose Change Variable |
| Name, and rename the JPanel to <tt>dropPanel</tt>. |
| <p><li>In the Properties section of the Properties window (Ctrl-Shift-7), |
| click "border", choose Line Border, and click OK. Now you |
| can see the edges of the JPanel, if it doesn't completely |
| cover the window component. Doing this gives the user |
| a visual indication of where to drop an item from the |
| Component Palette. |
| |
| <p><li>In the Source view, declare the following |
| at the top of the class: |
| |
| <p><pre class="examplecode">private Map displayers = new HashMap(); |
| private DragGestureRecognizer recognizer;</pre> |
| |
| <p>When prompted to do so, let the IDE generate import statements |
| for <tt>import java.util.HashMap</tt>, <tt>import java.util.Map</tt>, |
| and <tt>java.awt.dnd.DragGestureRecognizer</tt>. |
| |
| <p><li>Add the following to the end of the window |
| component's Constructor: |
| |
| <p><pre class="examplecode">//DND start |
| //start listening for for d'n'd events in the dropPanel |
| dropPanel.setDropTarget( new DropTarget( dropPanel, new DropTargetListener() { |
| public void dragEnter(DropTargetDragEvent dtde) { |
| doDragOver( dtde ); |
| } |
| public void dragExit(DropTargetEvent dte) { |
| } |
| public void dragOver(DropTargetDragEvent dtde) { |
| doDragOver( dtde ); |
| } |
| public void drop(DropTargetDropEvent dtde) { |
| doDrop( dtde ); |
| } |
| public void dropActionChanged(DropTargetDragEvent dtde) { |
| //ignore |
| //we don't really care whether it's a COPY or MOVE operation, let's treat both cases as the same |
| } |
| }) ); |
| //DND end |
| dropPanel.setLayout( null );</pre> |
| |
| <p>When prompted, let the IDE generate the following |
| import statements: |
| |
| <p><pre class="examplecode">import java.awt.dnd.DragGestureEvent; |
| import java.awt.dnd.DragGestureListener;</pre> |
| |
| <p>Also let the IDE generate the following import statements: |
| |
| <p><pre class="examplecode">import java.awt.dnd.DropTargetDragEvent; |
| import java.awt.dnd.DropTargetDropEvent; |
| import java.awt.dnd.DropTargetEvent;</pre> |
| |
| <p><li>The <tt>doDragOver</tt> event is defined as follows: |
| |
| <p><pre class="examplecode">private void doDragOver( DropTargetDragEvent dtde ) { |
| if( dtde.isDataFlavorSupported( Utils.MY_DATA_FLAVOR ) ) { |
| //only accept object of our type |
| dtde.acceptDrag( DnDConstants.ACTION_COPY_OR_MOVE ); |
| } else { |
| //reject everything else |
| dtde.rejectDrag(); |
| } |
| }</pre> |
| |
| |
| <p><li>The <tt>doDrop</tt> event is defined as follows: |
| |
| <p><pre class="examplecode">private void doDrop( DropTargetDropEvent dtde ) { |
| //first check if we support this type of data |
| if( !dtde.isDataFlavorSupported( Utils.MY_DATA_FLAVOR ) ) { |
| dtde.rejectDrop(); |
| } |
| //accept the drop so that we can access the Transferable |
| dtde.acceptDrop( DnDConstants.ACTION_COPY_OR_MOVE ); |
| MyItemData data = null; |
| try { |
| //get the dragged data from the transferable |
| data = (MyItemData) dtde.getTransferable().getTransferData(Utils.MY_DATA_FLAVOR); |
| } catch (IOException ex) { |
| ex.printStackTrace(); |
| } catch (UnsupportedFlavorException ex) { |
| ex.printStackTrace(); |
| } |
| |
| dtde.dropComplete( null != data ); |
| if( null != data ) { |
| //find the displayer for the data |
| ItemDataDisplayer displayer = (ItemDataDisplayer)displayers.get( data ); |
| if( null == displayer ) { |
| //it's a drop from the palette and the data is not in our list yet |
| displayer = new ItemDataDisplayer( data ); |
| |
| //This is where a drag and drop listener should be added, |
| //if you want to add functionality for dragging after the item is dropped. |
| //See the next section for details. |
| |
| //add the displayer to the panel |
| dropPanel.add( displayer ); |
| displayer.setSize( displayer.getPreferredSize() ); |
| displayers.put( data, displayer ); |
| } |
| //update displayer's location from the drop point |
| displayer.setLocation( dtde.getLocation() ); |
| } |
| }</pre> |
| |
| |
| <p><li>When you install the module, you will have a TopComponent |
| with a Component Palette. You will be able to drag an item from |
| the Component Palette and drop it in a JPanel within the |
| TopComponent: |
| |
| <p><img border=1 src="../images/tutorials/palette_api/dndsample4.png"> |
| |
| <p>When you try to drag the dropped item, nothing happens. The next |
| section explains how to define the drag gesture event. |
| |
| </ol> |
| |
| |
| <h2 class="tutorial"><a name="draggesture"></a>Defining a Drag Gesture</h2> |
| |
| <p>You can specify what should happen when the user drags the dropped item. Here, |
| we assume that the dropped item should be dragged elsewhere when the drag event |
| is handled. |
| |
| <ol> |
| <p><li>Change the window component's signature to |
| specify that <tt>DragGestureListener</tt> should be implemented. |
| When prompted, let the IDE generate the import statements |
| and abstract methods. |
| |
| <p>Fill out the generated <tt>dragGestureRecognized</tt> event as follows: |
| |
| <p><pre class="examplecode">public void dragGestureRecognized(DragGestureEvent dge) { |
| //first check which object is to be dragged |
| if( dge.getComponent() instanceof ItemDataDisplayer ) { |
| ItemDataDisplayer displayer = (ItemDataDisplayer)dge.getComponent(); |
| //get the data from the displayer and create a new transferable for dragging |
| dge.startDrag( null, new ItemDataTransferable(displayer.getData()) ); |
| } |
| }</pre> |
| |
| |
| <p><li>At the end of the window component class, |
| add this helper class that that wraps MyItemData |
| in a transferable, using the correct Data Flavor. |
| |
| <p><pre class="examplecode">private static class ItemDataTransferable implements Transferable { |
| private MyItemData data; |
| public ItemDataTransferable( MyItemData data ) { |
| this.data = data; |
| } |
| public DataFlavor[] getTransferDataFlavors() { |
| return new DataFlavor[] { Utils.MY_DATA_FLAVOR }; |
| } |
| |
| public boolean isDataFlavorSupported(DataFlavor flavor) { |
| return Utils.MY_DATA_FLAVOR.equals( flavor ); |
| } |
| |
| public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { |
| if( !isDataFlavorSupported( flavor ) ) { |
| throw new UnsupportedFlavorException( flavor ); |
| } |
| return data; |
| } |
| }</pre> |
| |
| <p><li>Search for the following text in the TopComponent: |
| |
| <p><pre class="examplecode">//This is where a drag and drop listener should be added, |
| //if you want to add functionality for dragging after the item is dropped.</pre> |
| |
| <p>Replace the text with the following to register a listener on the displayer: |
| |
| <p><pre class="examplecode">//register a d'n'd listener on the new displayer so that we can drag it too |
| DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer( displayer, DnDConstants.ACTION_COPY_OR_MOVE, this );</pre> |
| |
| |
| |
| </ol> |
| |
| <h2 class="tutorial"><a name="dragimage"></a>Defining a Drag Image</h2> |
| |
| <p>A nice touch is to display an image when the user drags an item. To |
| do this, the assumption is that you want to show the large image, that is, |
| the image that is 32x32 pixels in size, as specified in the item's file earlier. |
| |
| <ol> |
| <p><li>In the TopComponent's doDragOver() event, add the following after the code |
| that is already there: |
| |
| <p><pre class="examplecode">MyItemData data = null; |
| try { |
| data = (MyItemData) dtde.getTransferable().getTransferData(Utils.MY_DATA_FLAVOR); |
| } catch (IOException ex) { |
| ex.printStackTrace(); |
| } catch (UnsupportedFlavorException ex) { |
| ex.printStackTrace(); |
| } |
| |
| ItemDataDisplayer displayer = new ItemDataDisplayer( data ); |
| Image dragImage = displayer.getData().getBigImage(); |
| |
| Graphics2D g2 = (Graphics2D) getGraphics(); |
| Rectangle visRect = getVisibleRect(); |
| paintImmediately(visRect.x, visRect.y, visRect.width, visRect.height); |
| g2.drawImage(dragImage, |
| AffineTransform.getTranslateInstance(dtde.getLocation().getX(), |
| dtde.getLocation().getY()), |
| null);</pre> |
| |
| <p><li>Install the module again. Drag an item, either from the |
| Component Palette or from an explorer window. When you do so, |
| notice that an image appears at the cursor, once the cursor |
| is over the drop target: |
| |
| |
| <p><img border=1 src="../images/tutorials/palette_api/dndsample6.png"> |
| |
| |
| </ol> |
| <h2 class="tutorial"><a name="additionalitems"></a>Adding Additional Items</h2> |
| |
| <p>Currently, you only have one item in the Component Palette. To add additional items, |
| take the steps below. |
| |
| <ol> |
| <p><li>If the module is installed, uninstall it using the Module Manager in the Tools menu. |
| <p><li>In <tt>org.netbeans.dndsample.palette.items</tt>, copy <tt>id1.myitem</tt> |
| and name it <tt>id2.myitem</tt>. |
| <p><li>Open the new file in the Source Editor and change the data. |
| <p><li>Add a new 16x16 pixel icon and a new 32x32 pixel icon. |
| <p><li>Register the new item in the <tt>layer.xml</tt> file, below the |
| one you registered earlier. |
| </ol> |
| |
| <h2 class="tutorial"><a name="visuallibraryapi"></a>Drag and Drop and the Visual Library API</h2> |
| |
| <p>See the <a href="https://platform.netbeans.org/tutorials/nbm-visual_library.html">Visual Library 2.0 Tutorial (Part 1)</a>. |
| |
| |
| <h2 class="tutorial"><a name="explorermanagerapi"></a>Drag and Drop and Bean Tree Views</h2> |
| |
| <p>See the <a href="https://platform.netbeans.org/tutorials/nbm-nodesapi3.html">NetBeans Nodes, Explorer Manager, and Component Palette Tutorial</a>. |
| |
| |
| |
| <h2 class="tutorial"><a name="sourceeditor"></a>Drag and Drop and the NetBeans Source Editor</h2> |
| |
| <p>See the <a href="https://platform.netbeans.org/tutorials/nbm-palette-api2.html">NetBeans Component Palette Module Tutorial</a>. |
| |
| |
| <h2 class="tutorial"><a name="existing"></a>Adding Items to Existing Component Palettes</h2> |
| |
| <p>See the <a href="https://platform.netbeans.org/tutorials/nbm-palette-api1.html">NetBeans Code Snippet Module Tutorial</a>. |
| |
| <br> |
| <div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback:%20Drag%20and%20Drop%20Tutorial">Send Us Your Feedback</a></div> |
| <br style="clear:both;" /> |
| |
| |
| <h2>Open Issues</h2> |
| |
| <ol> |
| <li>Add lots of explanatory text. |
| <li>Add icons. |
| <li>Review by Stan. |
| </ol> |
| <hr> |
| </body></html> |
| |