KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > palette > ui > DnDSupport


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.palette.ui;
21
22 import java.awt.Component JavaDoc;
23 import java.awt.Point JavaDoc;
24 import java.awt.Rectangle JavaDoc;
25 import java.awt.datatransfer.Transferable JavaDoc;
26 import java.awt.dnd.DnDConstants JavaDoc;
27 import java.awt.dnd.DragGestureEvent JavaDoc;
28 import java.awt.dnd.DragGestureListener JavaDoc;
29 import java.awt.dnd.DragGestureRecognizer JavaDoc;
30 import java.awt.dnd.DragSource JavaDoc;
31 import java.awt.dnd.DragSourceAdapter JavaDoc;
32 import java.awt.dnd.DragSourceDropEvent JavaDoc;
33 import java.awt.dnd.DragSourceListener JavaDoc;
34 import java.awt.dnd.DropTarget JavaDoc;
35 import java.awt.dnd.DropTargetDragEvent JavaDoc;
36 import java.awt.dnd.DropTargetDropEvent JavaDoc;
37 import java.awt.dnd.DropTargetEvent JavaDoc;
38 import java.awt.dnd.DropTargetListener JavaDoc;
39 import java.awt.dnd.InvalidDnDOperationException JavaDoc;
40 import java.awt.event.ActionEvent JavaDoc;
41 import java.awt.event.ActionListener JavaDoc;
42 import java.awt.geom.Line2D JavaDoc;
43 import java.util.ArrayList JavaDoc;
44 import java.util.HashSet JavaDoc;
45 import java.util.Iterator JavaDoc;
46 import java.util.Set JavaDoc;
47 import java.util.logging.Level JavaDoc;
48 import java.util.logging.Logger JavaDoc;
49 import javax.swing.SwingUtilities JavaDoc;
50 import javax.swing.Timer JavaDoc;
51 import org.netbeans.modules.palette.Category;
52 import org.netbeans.modules.palette.Item;
53
54 /**
55  * Drag and drop support for palette items and categories.
56  *
57  * @author S. Aubrecht
58  */

59 public class DnDSupport implements DragGestureListener JavaDoc, DropTargetListener JavaDoc {
60     
61     final static private int DELAY_TIME_FOR_EXPAND = 1000;
62
63     private Set JavaDoc<DragGestureRecognizer JavaDoc> recognizers = new HashSet JavaDoc<DragGestureRecognizer JavaDoc>( 5 );
64     private Set JavaDoc<DropTarget JavaDoc> dropTargets = new HashSet JavaDoc<DropTarget JavaDoc>( 5 );
65
66     private Category draggingCategory;
67     private Item draggingItem;
68     private CategoryList dragSourceCategoryList;
69     private Item targetItem;
70     
71     private boolean dropBefore;
72     
73     private DragSourceListener JavaDoc dragSourceListener;
74     
75     private DropGlassPane dropPane;
76     
77     private PalettePanel palette;
78     
79     private Timer JavaDoc timer;
80     
81     private static final Logger JavaDoc ERR = Logger.getLogger("org.netbeans.modules.palette"); // NOI18N
82

83     /** Creates a new instance of DnDSupport */
84     public DnDSupport( PalettePanel palette ) {
85         this.palette = palette;
86     }
87     
88     void add( CategoryDescriptor descriptor ) {
89         CategoryList list = descriptor.getList();
90         recognizers.add( DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer( list, DnDConstants.ACTION_MOVE, this ) );
91         dropTargets.add( new DropTarget JavaDoc( list, this ) );
92         
93         CategoryButton button = descriptor.getButton();
94         recognizers.add( DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer( button, DnDConstants.ACTION_MOVE, this ) );
95         dropTargets.add( new DropTarget JavaDoc( button, this ) );
96     }
97
98     void remove( CategoryDescriptor descriptor ) {
99         ArrayList JavaDoc<DragGestureRecognizer JavaDoc> recognizersToRemove = new ArrayList JavaDoc<DragGestureRecognizer JavaDoc>( 2 );
100         for( Iterator JavaDoc<DragGestureRecognizer JavaDoc> i=recognizers.iterator(); i.hasNext(); ) {
101             DragGestureRecognizer JavaDoc dgr = i.next();
102             if( dgr.getComponent() == descriptor.getButton()
103                 || dgr.getComponent() == descriptor.getList() ) {
104                 recognizersToRemove.add( dgr );
105                 dgr.removeDragGestureListener( this );
106             }
107         }
108         recognizers.removeAll( recognizersToRemove );
109         
110         ArrayList JavaDoc<DropTarget JavaDoc> dropTargetsToRemove = new ArrayList JavaDoc<DropTarget JavaDoc>( 2 );
111         for( Iterator JavaDoc<DropTarget JavaDoc> i=dropTargets.iterator(); i.hasNext(); ) {
112             DropTarget JavaDoc dt = i.next();
113             if( dt.getComponent() == descriptor.getButton()
114                 || dt.getComponent() == descriptor.getList() ) {
115                 dropTargetsToRemove.add( dt );
116                 dt.removeDropTargetListener( this );
117             }
118         }
119         dropTargets.removeAll( dropTargetsToRemove );
120     }
121
122     public void dragGestureRecognized( DragGestureEvent JavaDoc dge ) {
123         Transferable JavaDoc t = null;
124         
125         if( dge.getComponent() instanceof CategoryButton ) {
126             //trying to drag a palette category
127
CategoryButton button = (CategoryButton)dge.getComponent();
128             draggingCategory = button.getCategory();
129             t = draggingCategory.getTransferable();
130             
131         } else if( dge.getComponent() instanceof CategoryList ) {
132             //trying to drag a palette item
133
CategoryList list = (CategoryList)dge.getComponent();
134             int selIndex = list.locationToIndex( dge.getDragOrigin() );
135             draggingItem = list.getItemAt( selIndex );
136             if( null == draggingItem ) {
137                 return;
138             }
139             t = draggingItem.drag();
140             dragSourceCategoryList = list;
141         }
142         if( null != t ) {
143             dge.getDragSource().addDragSourceListener( getDragSourceListener() );
144             try {
145                 dge.startDrag( null, t );
146             } catch( InvalidDnDOperationException JavaDoc idndE ) {
147                 ERR.log( Level.INFO, idndE.getMessage(), idndE );
148             }
149         }
150     }
151
152     public void drop( DropTargetDropEvent JavaDoc dtde ) {
153         Component JavaDoc target = dtde.getDropTargetContext().getComponent();
154         Category targetCategory = null;
155         if( target instanceof CategoryList ) {
156             targetCategory = ((CategoryList)target).getCategory();
157         } else if( target instanceof CategoryButton ) {
158             targetCategory = ((CategoryButton)target).getCategory();
159         }
160         if( null != draggingCategory ) {
161             //dragging a category to reorder
162
boolean res = false;
163             if( null != targetCategory && (target instanceof CategoryButton) ) {
164                 res = palette.getModel().moveCategory( draggingCategory, targetCategory, dropBefore );
165             }
166             dtde.dropComplete( res );
167         } else {
168             //dragging an item to reorder or move to a different category
169
//or dragging something from outside the palette to create a new item
170
dtde.acceptDrop( dtde.getDropAction() );
171             boolean res = false;
172             if( null != targetCategory ) {
173                 Transferable JavaDoc t;
174                 if( null != draggingItem ) {
175                     //internal drag'n'drop - an item is being moved from a different category
176
t = draggingItem.cut();
177                 } else {
178                     //a new item is being dropped to the palette from e.g. editor area
179
t = dtde.getTransferable();
180                 }
181                 res = targetCategory.dropItem( t, dtde.getDropAction(), targetItem, dropBefore );
182             }
183             dtde.dropComplete( res );
184         }
185         cleanupAfterDnD();
186     }
187
188     public void dragExit( DropTargetEvent JavaDoc dte ) {
189         removeDropLine();
190         if (DropGlassPane.isOriginalPaneStored()) {
191             DropGlassPane.putBackOriginal();
192         }
193         removeTimer();
194     }
195
196     public void dropActionChanged( DropTargetDragEvent JavaDoc dtde ) {
197     }
198
199     public void dragOver( DropTargetDragEvent JavaDoc dtde ) {
200         checkStoredGlassPane();
201         
202         doDragOver( dtde );
203     }
204
205     public void dragEnter( DropTargetDragEvent JavaDoc dtde ) {
206         checkStoredGlassPane();
207         
208         Component JavaDoc target = dtde.getDropTargetContext().getComponent();
209         if( target instanceof CategoryButton && null == draggingCategory ) {
210             final CategoryButton button = (CategoryButton)target;
211             if( !button.isSelected() && (null == timer || !timer.isRunning()) ) {
212                 removeTimer();
213                 timer = new Timer JavaDoc(
214                     DELAY_TIME_FOR_EXPAND,
215                     new ActionListener JavaDoc() {
216                         final public void actionPerformed(ActionEvent JavaDoc e) {
217                             button.setExpanded( true );
218                         }
219                     }
220                 );
221                 timer.setRepeats(false);
222                 timer.start();
223             }
224         }
225         doDragOver( dtde );
226     }
227     
228
229     /** Removes timer and all listeners. */
230     private void removeTimer() {
231         if (timer != null) {
232             ActionListener JavaDoc[] l = (ActionListener JavaDoc[]) timer.getListeners(ActionListener JavaDoc.class);
233
234             for (int i = 0; i < l.length; i++) {
235                 timer.removeActionListener(l[i]);
236             }
237
238             timer.stop();
239             timer = null;
240         }
241     }
242
243     
244     private void doDragOver( DropTargetDragEvent JavaDoc dtde ) {
245         Component JavaDoc target = dtde.getDropTargetContext().getComponent();
246         if( null != draggingCategory ) {
247             //a whole category is being dragged within the palette panel
248
Category targetCategory = null;
249             if( target instanceof CategoryButton ) {
250                 CategoryButton button = (CategoryButton)target;
251                 targetCategory = button.getCategory();
252             }
253             if( null == targetCategory || !palette.getModel().canReorderCategories() ) {
254                 dtde.rejectDrag();
255                 removeDropLine();
256                 return;
257             }
258             dropBefore = dtde.getLocation().y < (target.getHeight()/2);
259             Point JavaDoc p1 = target.getLocation();
260             Point JavaDoc p2 = target.getLocation();
261             p2.x += target.getWidth();
262             if( !dropBefore ) {
263                 p1.y += target.getHeight();
264                 p2.y += target.getHeight();
265             }
266             p1 = SwingUtilities.convertPoint( target, p1, palette.getRootPane() );
267             p2 = SwingUtilities.convertPoint( target, p2, palette.getRootPane() );
268             Line2D JavaDoc line = new Line2D.Double JavaDoc( p1.x, p1.y, p2.x, p2.y );
269             dropPane.setDropLine( line );
270         } else {
271             //dragging an existing item to reorder
272
//or somebody is trying to drop a new item from outside the palette panel
273
Category targetCategory = null;
274             if( target instanceof CategoryList ) {
275                 CategoryList list = (CategoryList)target;
276                 targetCategory = list.getCategory();
277             } else if( target instanceof CategoryButton ) {
278                 CategoryButton button = (CategoryButton)target;
279                 targetCategory = button.getCategory();
280             }
281             if( null != targetCategory && targetCategory.dragOver( dtde ) ) {
282                 dtde.acceptDrag( dtde.getDropAction() );
283             } else {
284                 dtde.rejectDrag();
285                 removeDropLine();
286                 targetItem = null;
287                 return;
288             }
289
290             if( target instanceof CategoryList ) {
291                 CategoryList list = (CategoryList)target;
292                 int dropIndex = list.locationToIndex( dtde.getLocation() );
293                 if( dropIndex < 0 ) {
294                     dropPane.setDropLine( null );
295                     targetItem = null;
296                 } else {
297                     boolean verticalDropBar = list.getColumnCount() > 1;
298                     Rectangle JavaDoc rect = list.getCellBounds( dropIndex, dropIndex );
299                     if( verticalDropBar )
300                         dropBefore = dtde.getLocation().x < (rect.x + rect.width/2);
301                     else
302                         dropBefore = dtde.getLocation().y < (rect.y + rect.height/2);
303                     Point JavaDoc p1 = rect.getLocation();
304                     Point JavaDoc p2 = rect.getLocation();
305                     if( verticalDropBar ) {
306                         p2.y += rect.height;
307                         if( !dropBefore ) {
308                             p1.x += rect.width;
309                             p2.x += rect.width;
310                         }
311                     } else {
312                         p2.x += rect.width;
313                         if( !dropBefore ) {
314                             p1.y += rect.height;
315                             p2.y += rect.height;
316                         }
317                     }
318                     p1 = SwingUtilities.convertPoint( list, p1, palette.getRootPane() );
319                     p2 = SwingUtilities.convertPoint( list, p2, palette.getRootPane() );
320                     Line2D JavaDoc line = new Line2D.Double JavaDoc( p1.x, p1.y, p2.x, p2.y );
321                     dropPane.setDropLine( line );
322                     targetItem = (Item)list.getModel().getElementAt( dropIndex );
323                 }
324             } else {
325                 targetItem = null;
326                 dropBefore = false;
327             }
328         }
329         //parent.repaint();
330
}
331     
332     private DragSourceListener JavaDoc getDragSourceListener() {
333         if( null == dragSourceListener ) {
334             dragSourceListener = new DragSourceAdapter JavaDoc() {
335                 public void dragDropEnd( DragSourceDropEvent JavaDoc dsde ) {
336                     dsde.getDragSourceContext().getDragSource().removeDragSourceListener( this );
337                     cleanupAfterDnD();
338                 }
339             };
340         }
341         return dragSourceListener;
342     }
343     
344     private void cleanupAfterDnD() {
345         draggingItem = null;
346         draggingCategory = null;
347         targetItem = null;
348         if( null != dragSourceCategoryList ) {
349             dragSourceCategoryList.resetRollover();
350         }
351         dragSourceCategoryList = null;
352         removeDropLine();
353         if (DropGlassPane.isOriginalPaneStored()) {
354             DropGlassPane.putBackOriginal();
355         }
356         removeTimer();
357     }
358
359     private void checkStoredGlassPane() {
360         // remember current glass pane to set back at end of dragging over this compoment
361
if( !DropGlassPane.isOriginalPaneStored() ) {
362             Component JavaDoc comp = palette.getRootPane().getGlassPane();
363             DropGlassPane.setOriginalPane( palette, comp, comp.isVisible() );
364
365             // set glass pane for paint selection line
366
dropPane = DropGlassPane.getDefault( palette );
367             palette.getRootPane().setGlassPane( dropPane );
368             dropPane.revalidate();
369             dropPane.validate();
370             dropPane.setVisible(true);
371         }
372     }
373     
374     private void removeDropLine() {
375         if( null != dropPane )
376             dropPane.setDropLine( null );
377     }
378 }
379
Popular Tags