KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > nodes > IndexedCustomizer


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.openide.nodes;
21
22 import java.awt.Component JavaDoc;
23 import java.awt.Container JavaDoc;
24 import java.awt.Dimension JavaDoc;
25 import java.awt.GridBagConstraints JavaDoc;
26 import java.awt.GridBagLayout JavaDoc;
27 import java.awt.Insets JavaDoc;
28 import java.awt.Point JavaDoc;
29 import java.awt.datatransfer.DataFlavor JavaDoc;
30 import java.awt.datatransfer.Transferable JavaDoc;
31 import java.awt.datatransfer.UnsupportedFlavorException JavaDoc;
32 import java.awt.dnd.Autoscroll JavaDoc;
33 import java.awt.dnd.DnDConstants JavaDoc;
34 import java.awt.dnd.DragGestureEvent JavaDoc;
35 import java.awt.dnd.DragGestureListener JavaDoc;
36 import java.awt.dnd.DragSource JavaDoc;
37 import java.awt.dnd.DragSourceDragEvent JavaDoc;
38 import java.awt.dnd.DragSourceDropEvent JavaDoc;
39 import java.awt.dnd.DragSourceEvent JavaDoc;
40 import java.awt.dnd.DragSourceListener JavaDoc;
41 import java.awt.dnd.DropTarget JavaDoc;
42 import java.awt.dnd.DropTargetDragEvent JavaDoc;
43 import java.awt.dnd.DropTargetDropEvent JavaDoc;
44 import java.awt.dnd.DropTargetEvent JavaDoc;
45 import java.awt.dnd.DropTargetListener JavaDoc;
46 import java.awt.dnd.InvalidDnDOperationException JavaDoc;
47 import java.awt.event.ActionEvent JavaDoc;
48 import java.awt.event.ActionListener JavaDoc;
49 import java.beans.Customizer JavaDoc;
50 import java.beans.PropertyChangeListener JavaDoc;
51 import java.io.IOException JavaDoc;
52 import java.util.logging.Level JavaDoc;
53 import java.util.logging.Logger JavaDoc;
54 import javax.swing.JButton JavaDoc;
55 import javax.swing.JComponent JavaDoc;
56 import javax.swing.JDialog JavaDoc;
57 import javax.swing.JLabel JavaDoc;
58 import javax.swing.JList JavaDoc;
59 import javax.swing.JPanel JavaDoc;
60 import javax.swing.JScrollPane JavaDoc;
61 import javax.swing.JViewport JavaDoc;
62 import javax.swing.SwingUtilities JavaDoc;
63 import javax.swing.UIManager JavaDoc;
64 import javax.swing.border.Border JavaDoc;
65 import javax.swing.border.LineBorder JavaDoc;
66 import javax.swing.event.ChangeEvent JavaDoc;
67 import javax.swing.event.ChangeListener JavaDoc;
68 import javax.swing.event.ListSelectionEvent JavaDoc;
69 import javax.swing.event.ListSelectionListener JavaDoc;
70 import org.openide.util.NbBundle;
71 import org.openide.util.datatransfer.ExTransferable;
72
73 /** A dialog for reordering nodes. This dialog can reorder
74 * nodes for all implementors of the {@link Index} cookie.
75 * The dialog can invoke reorder actions on a given <code>Index</code>
76 * implementation immediatelly, or these actions can be accumulated
77 * and invoked at once, when the dialog is closed.
78 *
79 * <p>This class is final only for performance reasons.
80 *
81 * @author Jan Jancura, Ian Formanek, Dafe Simonek
82 * @deprecated Better to use {@link Index.Support#showIndexedCustomizer} which behaves better
83 * with the window system.
84 */

85 @Deprecated JavaDoc
86 public final class IndexedCustomizer extends JDialog JavaDoc implements Customizer JavaDoc {
87     // initializations ................................................................................
88
static final long serialVersionUID = -8731362267771694641L;
89
90     // variables .....................................................................................
91

92     /** The actual JList control */
93     private JList JavaDoc control;
94
95     /** Buttons */
96     private JButton JavaDoc buttonUp;
97
98     /** Buttons */
99     private JButton JavaDoc buttonDown;
100
101     /** Buttons */
102     private JButton JavaDoc buttonClose;
103
104     /** index to sort */
105     private Index index;
106     private Node[] nodes;
107
108     /** Whether or not change the order immediatelly */
109     private boolean immediateReorder = true;
110
111     /** Permutation array, which stores moves in case when
112     * immediateReorder property is false */

113     private int[] permutation;
114
115     /** Listener to the changes in the nodes */
116     private ChangeListener JavaDoc nodeChangesL;
117
118     /** Construct a new customizer. */
119     public IndexedCustomizer() {
120         this(null, true);
121     }
122
123     /** Construct a dummy customizer.
124      * Might not actually be used as a JDialog, however its GUI
125      * layout and logic will be used.
126      * Cf. #9323.
127      * @param c a container on which to draw the GUI
128      * @param closeButton if true, add a Close button and other dialog logic, else no
129      */

130     IndexedCustomizer(Container JavaDoc p, boolean closeButton) {
131         super(TMUtil.mainWindow(), true);
132
133         GridBagConstraints JavaDoc constraints;
134
135         if (closeButton) {
136             setDefaultCloseOperation(javax.swing.JDialog.DISPOSE_ON_CLOSE);
137
138             // attach cancel also to Escape key
139
getRootPane().registerKeyboardAction(
140                 new java.awt.event.ActionListener JavaDoc() {
141                     public void actionPerformed(java.awt.event.ActionEvent JavaDoc evt) {
142                         setVisible(false);
143                         dispose();
144                     }
145                 }, javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ESCAPE, 0, true),
146                 javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW
147             );
148
149             setTitle(Node.getString("LAB_order"));
150         }
151          // closeButton
152

153         if (p == null) {
154             p = getContentPane();
155         }
156
157         p.setLayout(new GridBagLayout JavaDoc());
158
159         JLabel JavaDoc l = new JLabel JavaDoc(Node.getString("LAB_listOrder"));
160         l.setDisplayedMnemonic(Node.getString("LAB_listOrder_Mnemonic").charAt(0));
161         constraints = new GridBagConstraints JavaDoc();
162         constraints.gridx = 0;
163         constraints.gridy = 0;
164         constraints.anchor = GridBagConstraints.WEST;
165         constraints.insets = new Insets JavaDoc(12, 12, 2, 12);
166         p.add(l, constraints);
167
168         control = new AutoscrollJList();
169         l.setLabelFor(control);
170         control.addListSelectionListener(
171             new ListSelectionListener JavaDoc() {
172                 public void valueChanged(ListSelectionEvent JavaDoc e) {
173                     if (control.isSelectionEmpty()) {
174                         buttonUp.setEnabled(false);
175                         buttonDown.setEnabled(false);
176                     } else {
177                         int i = control.getSelectedIndex();
178
179                         if (i > 0) { //PENDING - jeste testovat, jestli jsou OrderedCookie.Child
180
buttonUp.setEnabled(true);
181                         } else {
182                             buttonUp.setEnabled(false);
183                         }
184
185                         if (i < (nodes.length - 1)) {
186                             buttonDown.setEnabled(true);
187                         } else {
188                             buttonDown.setEnabled(false);
189                         }
190                     }
191                 }
192             }
193         );
194         control.setCellRenderer(new IndexedListCellRenderer());
195         control.setVisibleRowCount(15);
196         control.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
197
198         // list has to be scrolling
199
constraints = new GridBagConstraints JavaDoc();
200         constraints.gridx = 0;
201         constraints.gridy = 1;
202         constraints.fill = GridBagConstraints.BOTH;
203         constraints.weightx = 1.0;
204         constraints.weighty = 1.0;
205         constraints.insets = new Insets JavaDoc(0, 12, 11, 11);
206         p.add(new JScrollPane JavaDoc(control), constraints);
207
208         JPanel JavaDoc bb = new JPanel JavaDoc();
209
210         if (closeButton) {
211             buttonClose = new JButton JavaDoc(Node.getString("Button_close"));
212             buttonClose.setMnemonic(Node.getString("Button_close_Mnemonic").charAt(0));
213         }
214
215         buttonUp = new JButton JavaDoc(Node.getString("Button_up"));
216         buttonUp.setMnemonic(Node.getString("Button_up_Mnemonic").charAt(0));
217         buttonDown = new JButton JavaDoc(Node.getString("Button_down"));
218         buttonDown.setMnemonic(Node.getString("Button_down_Mnemonic").charAt(0));
219
220         bb.setLayout(new GridBagLayout JavaDoc());
221
222         constraints = new GridBagConstraints JavaDoc();
223         constraints.gridx = 0;
224         constraints.gridy = 0;
225         constraints.anchor = GridBagConstraints.NORTH;
226         constraints.fill = GridBagConstraints.HORIZONTAL;
227         constraints.insets = new Insets JavaDoc(0, 0, 5, 11);
228         bb.add(buttonUp, constraints);
229
230         constraints = new GridBagConstraints JavaDoc();
231         constraints.gridx = 0;
232         constraints.gridy = 1;
233         constraints.anchor = GridBagConstraints.NORTH;
234         constraints.fill = GridBagConstraints.HORIZONTAL;
235         constraints.weighty = 1.0;
236         constraints.insets = new Insets JavaDoc(0, 0, 0, 11);
237         bb.add(buttonDown, constraints);
238
239         if (closeButton) {
240             constraints = new GridBagConstraints JavaDoc();
241             constraints.gridx = 0;
242             constraints.gridy = 2;
243             constraints.anchor = GridBagConstraints.SOUTH;
244             constraints.fill = GridBagConstraints.HORIZONTAL;
245             constraints.insets = new Insets JavaDoc(0, 0, 11, 11);
246             bb.add(buttonClose, constraints);
247         }
248
249         buttonUp.addActionListener(
250             new ActionListener JavaDoc() {
251                 public void actionPerformed(ActionEvent JavaDoc e) {
252                     int i = control.getSelectedIndex();
253                     moveUp(i);
254                     updateList();
255                     control.setSelectedIndex(i - 1);
256                     control.ensureIndexIsVisible(i - 1);
257                     control.repaint();
258                 }
259             }
260         );
261
262         buttonDown.addActionListener(
263             new ActionListener JavaDoc() {
264                 public void actionPerformed(ActionEvent JavaDoc e) {
265                     int i = control.getSelectedIndex();
266                     moveDown(i);
267                     updateList();
268                     control.setSelectedIndex(i + 1);
269                     control.ensureIndexIsVisible(i + 1);
270                     control.repaint();
271                 }
272             }
273         );
274
275         if (closeButton) {
276             buttonClose.addActionListener(
277                 new ActionListener JavaDoc() {
278                     public void actionPerformed(ActionEvent JavaDoc e) {
279                         doClose();
280                         dispose();
281                     }
282                 }
283             );
284         }
285
286         buttonUp.setEnabled(false);
287         buttonDown.setEnabled(false);
288         constraints = new GridBagConstraints JavaDoc();
289         constraints.gridx = 1;
290         constraints.gridy = 1;
291         constraints.fill = GridBagConstraints.VERTICAL;
292         p.add(bb, constraints);
293
294         // disable drag support, as DnD crashes all environment
295
// under current implementation of VMs on unixes, ans causes
296
// some deadlocks on windows...
297
//dragSupport = new IndexedDragSource(control);
298
//dropSupport = new IndexedDropTarget(this, dragSupport);
299
if (closeButton) {
300             pack();
301             setBounds(org.openide.util.Utilities.findCenterBounds(getSize()));
302
303             buttonClose.requestFocus(); // to get shortcuts to work
304

305             buttonClose.getAccessibleContext().setAccessibleDescription(Node.getString("ACSD_Button_close"));
306         }
307
308         buttonUp.getAccessibleContext().setAccessibleDescription(Node.getString("ACSD_Button_up"));
309         buttonDown.getAccessibleContext().setAccessibleDescription(Node.getString("ACSD_Button_down"));
310         control.getAccessibleContext().setAccessibleDescription(Node.getString("ACSD_ListOrder"));
311         p.getAccessibleContext().setAccessibleDescription(Node.getString("ACSD_IndexedCustomizer"));
312         getAccessibleContext().setAccessibleDescription(Node.getString("ACSD_IndexedCustomizer"));
313     }
314
315     /** Simulate behavior of the Close button, minus actual dialog disposal.
316      * Might do the same as setImmediateReorder(true), but I am not sure.
317      */

318     void doClose() {
319         if ((!immediateReorder) && (index != null) && (permutation != null)) {
320             int[] realPerm = new int[permutation.length];
321
322             for (int i = 0; i < realPerm.length; i++) {
323                 realPerm[permutation[i]] = i;
324
325                 //System.out.println (i + "-->" + permutation[i]); // NOI18N
326
}
327
328             index.reorder(realPerm);
329         }
330     }
331
332     // other methods ................................................................................
333

334     /** Called when an explored context changes and the list needs to be
335     * recreated.
336     */

337     private void updateList() {
338         if (index == null) {
339             return;
340         }
341
342         Node[] localNodes = index.getNodes();
343
344         //System.out.println ("Nodes taken, size: " + localNodes.length); // NOI18N
345
// obtain nodes with help from permutation array, if
346
// conditions met
347
if (!immediateReorder) {
348             getPermutation();
349
350             int origLength = permutation.length;
351             int newLength = localNodes.length;
352
353             if (origLength < newLength) {
354                 // some nodes added, we must synchronize the permutation
355
nodes = new Node[newLength];
356
357                 int[] newPerm = new int[newLength];
358                 System.arraycopy(newPerm, 0, permutation, 0, origLength);
359
360                 for (int i = 0; i < newLength; i++) {
361                     if (i < origLength) {
362                         nodes[i] = localNodes[permutation[i]];
363                     } else {
364                         // added nodes....
365
nodes[i] = localNodes[i];
366                         newPerm[i] = i;
367                     }
368                 }
369
370                 permutation = newPerm;
371             } else if (origLength > newLength) {
372                 // some nodes removed, we must re-initialize the permutation
373
nodes = new Node[newLength];
374                 permutation = new int[newLength];
375
376                 for (int i = 0; i < newLength; i++) {
377                     nodes[i] = localNodes[i];
378                     permutation[i] = i;
379                 }
380             } else {
381                 // node count is the same, only permute the nodes
382
nodes = new Node[newLength];
383
384                 for (int i = 0; i < newLength; i++)
385                     nodes[i] = localNodes[permutation[i]];
386             }
387         } else {
388             nodes = localNodes.clone();
389         }
390
391         control.setListData(nodes);
392
393         if ((nodes.length > 0) && (control.getSelectedIndex() == -1)) {
394             control.setSelectedIndex(0);
395         }
396     }
397
398     public Dimension JavaDoc getPreferredSize() {
399         return new Dimension JavaDoc(300, super.getPreferredSize().height);
400     }
401
402     /** Will reorders be reflected immediately?
403     * @return <code>true</code> if so
404     */

405     public boolean isImmediateReorder() {
406         return immediateReorder;
407     }
408
409     /** Set whether reorders will take effect immediately.
410     * @param immediateReorder <code>true</code> if so
411     */

412     public void setImmediateReorder(boolean immediateReorder) {
413         if (this.immediateReorder == immediateReorder) {
414             return;
415         }
416
417         this.immediateReorder = immediateReorder;
418
419         if (immediateReorder) {
420             if (permutation != null) {
421                 index.reorder(permutation);
422                 permutation = null;
423                 updateList();
424             }
425         }
426     }
427
428     // implementation of Customizer ............................................................
429

430     /** Set the nodes to reorder.
431     * @param bean must implement {@link Index}
432     * @throws IllegalArgumentException if not
433     */

434     public void setObject(Object JavaDoc bean) {
435         if (bean instanceof Index) {
436             index = (Index) bean;
437
438             // add weak listener to the Index
439
nodeChangesL = new ChangeListener JavaDoc() {
440                         public void stateChanged(ChangeEvent JavaDoc ev) {
441                             SwingUtilities.invokeLater(
442                                 new Runnable JavaDoc() {
443                                     public void run() {
444                                         updateList();
445                                     }
446                                 }
447                             );
448                         }
449                     };
450             updateList();
451             control.invalidate();
452             validate();
453             index.addChangeListener(org.openide.util.WeakListeners.change(nodeChangesL, index));
454         } else {
455             throw new IllegalArgumentException JavaDoc();
456         }
457     }
458
459     // I don't change any property...
460
public void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) {
461     }
462
463     public void removePropertyChangeListener(PropertyChangeListener JavaDoc listener) {
464     }
465
466     /** Moves up. Performs differently according to
467     * immediateReorder property value.
468     */

469     private void moveUp(final int position) {
470         if (index == null) {
471             return;
472         }
473
474         if (immediateReorder) {
475             index.moveUp(position);
476         } else {
477             getPermutation();
478
479             int temp = permutation[position];
480             permutation[position] = permutation[position - 1];
481             permutation[position - 1] = temp;
482         }
483     }
484
485     /** Moves down. Performs differently according to
486     * immediateReorder property value.
487     */

488     private void moveDown(final int position) {
489         if (index == null) {
490             return;
491         }
492
493         if (immediateReorder) {
494             index.moveDown(position);
495         } else {
496             getPermutation();
497
498             int temp = permutation[position];
499             permutation[position] = permutation[position + 1];
500             permutation[position + 1] = temp;
501         }
502     }
503
504     /** Safe getter for permutation.
505     * Initializes permutation to identical permutation if it is null.<br>
506     * index variable must not be null when this method called */

507     private int[] getPermutation() {
508         if (permutation == null) {
509             if (nodes == null) {
510                 nodes = index.getNodes().clone();
511             }
512
513             permutation = new int[nodes.length];
514
515             for (int i = 0; i < nodes.length; permutation[i] = i++)
516                 ;
517         }
518
519         return permutation;
520     }
521
522     /** Permute the list as given permutation dictates.
523     * Sets selection to the given selected index.
524     * Called from dropSupport as result of succesfull DnD operation.
525     */

526     void performReorder(int[] perm, int selected) {
527         if (immediateReorder) {
528             index.reorder(perm);
529         } else {
530             // merge current and reversed given permutation
531
// (reverse given permutation first)
532
int[] reversed = new int[perm.length];
533
534             for (int i = 0; i < reversed.length; i++)
535                 reversed[perm[i]] = i;
536
537             int[] orig = getPermutation();
538             permutation = new int[orig.length];
539
540             for (int i = 0; i < orig.length; i++) {
541                 permutation[i] = orig[reversed[i]];
542
543                 // System.out.println(permutation[i] + " ----> " + i); // NOI18N
544
}
545         }
546
547         updateList();
548         control.setSelectedIndex(selected);
549         control.repaint();
550     }
551
552     /** Implementation of drag functionality in
553     * reorder dialog. */

554     private static final class IndexedDragSource implements DragGestureListener JavaDoc, DragSourceListener JavaDoc {
555         /** Asociated JList component where the drag will
556         * take place */

557         JList JavaDoc comp;
558
559         /** User gesture that initiated the drag */
560         DragGestureEvent JavaDoc dge;
561
562         /** Out data flavor used to transfer the index */
563         DataFlavor JavaDoc myFlavor;
564
565         /** Creates drag source with asociated list where drag
566         * will take place.
567         * Also creates the default gesture and asociates this with
568         * given component */

569         IndexedDragSource(JList JavaDoc comp) {
570             this.comp = comp;
571
572             // initialize gesture
573
DragSource JavaDoc ds = DragSource.getDefaultDragSource();
574             ds.createDefaultDragGestureRecognizer(comp, DnDConstants.ACTION_MOVE, this);
575         }
576
577         /** Initiating the drag */
578         public void dragGestureRecognized(DragGestureEvent JavaDoc dge) {
579             // check allowed actions
580
if ((dge.getDragAction() & DnDConstants.ACTION_MOVE) == 0) {
581                 return;
582             }
583
584             // prepare transferable and start the drag
585
int index = comp.locationToIndex(dge.getDragOrigin());
586
587             // no index, then no dragging...
588
if (index < 0) {
589                 return;
590             }
591
592             // System.out.println("Starting drag..."); // NOI18N
593
// create our flavor for transferring the index
594
myFlavor = new DataFlavor JavaDoc(
595                     String JavaDoc.class, NbBundle.getBundle(IndexedCustomizer.class).getString("IndexedFlavor")
596                 );
597
598             try {
599                 dge.startDrag(DragSource.DefaultMoveDrop, new IndexTransferable(myFlavor, index), this);
600
601                 // remember the gesture
602
this.dge = dge;
603             } catch (InvalidDnDOperationException JavaDoc exc) {
604                 Logger.getLogger(IndexedCustomizer.class.getName()).log(Level.WARNING, null, exc);
605
606                 // PENDING notify user - cannot start the drag
607
}
608         }
609
610         public void dragEnter(DragSourceDragEvent JavaDoc dsde) {
611         }
612
613         public void dragOver(DragSourceDragEvent JavaDoc dsde) {
614         }
615
616         public void dropActionChanged(DragSourceDragEvent JavaDoc dsde) {
617         }
618
619         public void dragExit(DragSourceEvent JavaDoc dse) {
620         }
621
622         public void dragDropEnd(DragSourceDropEvent JavaDoc dsde) {
623         }
624
625         /** Utility accessor */
626         DragGestureEvent JavaDoc getDragGestureEvent() {
627             return dge;
628         }
629     }
630      // end of IndexedDragSource
631

632     /** Implementation of drop functionality in
633     * reorder dialog. */

634     private static final class IndexedDropTarget implements DropTargetListener JavaDoc {
635         /** Asociated JList component for dropping */
636         JList JavaDoc comp;
637
638         /** Cell renderer which renders the list items */
639         IndexedListCellRenderer cellRenderer;
640
641         /** Indexed dialog */
642         IndexedCustomizer dialog;
643
644         /** Drag source support instance */
645         IndexedDragSource ids;
646
647         /** last index dragged over */
648         int lastIndex = -1;
649
650         /** Creates the instance, makes given component active for
651         * drop operation. */

652         IndexedDropTarget(IndexedCustomizer dialog, IndexedDragSource ids) {
653             this.dialog = dialog;
654             this.comp = dialog.control;
655             this.cellRenderer = (IndexedListCellRenderer) this.comp.getCellRenderer();
656             this.ids = ids;
657             new DropTarget JavaDoc(comp, DnDConstants.ACTION_MOVE, this, true);
658         }
659
660         /** User is starting to drag over us */
661         public void dragEnter(DropTargetDragEvent JavaDoc dtde) {
662             if (!checkConditions(dtde)) {
663                 dtde.rejectDrag();
664             } else {
665                 lastIndex = comp.locationToIndex(dtde.getLocation());
666                 cellRenderer.draggingEnter(lastIndex, ids.getDragGestureEvent().getDragOrigin(), dtde.getLocation());
667                 comp.repaint(comp.getCellBounds(lastIndex, lastIndex));
668             }
669         }
670
671         /** User drag over us */
672         public void dragOver(DropTargetDragEvent JavaDoc dtde) {
673             if (!checkConditions(dtde)) {
674                 dtde.rejectDrag();
675
676                 if (lastIndex >= 0) {
677                     cellRenderer.draggingExit();
678                     comp.repaint(comp.getCellBounds(lastIndex, lastIndex));
679                     lastIndex = -1;
680                 }
681             } else {
682                 dtde.acceptDrag(DnDConstants.ACTION_MOVE);
683
684                 int index = comp.locationToIndex(dtde.getLocation());
685
686                 if (lastIndex == index) {
687                     cellRenderer.draggingOver(index, ids.getDragGestureEvent().getDragOrigin(), dtde.getLocation());
688                 } else {
689                     if (lastIndex < 0) {
690                         lastIndex = index;
691                     }
692
693                     cellRenderer.draggingExit();
694                     cellRenderer.draggingEnter(index, ids.getDragGestureEvent().getDragOrigin(), dtde.getLocation());
695                     comp.repaint(comp.getCellBounds(lastIndex, index));
696                     lastIndex = index;
697                 }
698             }
699         }
700
701         public void dropActionChanged(DropTargetDragEvent JavaDoc dtde) {
702         }
703
704         /** User exits the dragging */
705         public void dragExit(DropTargetEvent JavaDoc dte) {
706             if (lastIndex >= 0) {
707                 cellRenderer.draggingExit();
708                 comp.repaint(comp.getCellBounds(lastIndex, lastIndex));
709             }
710         }
711
712         /** Takes given index transferable and reorders
713         * the items as appropriate (and if possible) */

714         public void drop(DropTargetDropEvent JavaDoc dtde) {
715             // reject all but local moves
716
if ((DnDConstants.ACTION_MOVE != dtde.getDropAction()) || !dtde.isLocalTransfer()) {
717                 dtde.rejectDrop();
718             }
719
720             int target = comp.locationToIndex(dtde.getLocation());
721
722             if (target < 0) {
723                 dtde.rejectDrop();
724
725                 return;
726             }
727
728             Transferable JavaDoc t = dtde.getTransferable();
729
730             // System.out.println("Dropping..."); // NOI18N
731
dtde.acceptDrop(DnDConstants.ACTION_MOVE);
732
733             try {
734                 int source = Integer.parseInt((String JavaDoc) t.getTransferData(ids.myFlavor));
735
736                 if (source != target) {
737                     performReorder(source, target);
738                     dtde.dropComplete(true);
739                 } else {
740                     dtde.dropComplete(false);
741                 }
742             } catch (IOException JavaDoc exc) {
743                 dtde.dropComplete(false);
744             } catch (UnsupportedFlavorException JavaDoc exc) {
745                 dtde.dropComplete(false);
746             } catch (NumberFormatException JavaDoc exc) {
747                 dtde.dropComplete(false);
748             }
749         }
750
751         /** Actually performs the reordering which results from
752         * succesfull drag-drop operation.
753         * @param source
754         */

755         void performReorder(int source, int target) {
756             int[] myPerm = new int[comp.getModel().getSize()];
757
758             // positions will change only between source and target
759
// indexes, the rest remains the same
760
for (int i = 0; i < Math.min(source, target); i++)
761                 myPerm[i] = i;
762
763             for (int i = Math.max(source, target) + 1; i < myPerm.length; i++)
764                 myPerm[i] = i;
765
766             // reorder the rest
767
myPerm[source] = target;
768
769             if (source > target) {
770                 // dragging was up the list
771
for (int i = target; i < source; i++)
772                     myPerm[i] = i + 1;
773             } else {
774                 // dragging was down the list
775
for (int i = source + 1; i < (target + 1); i++)
776                     myPerm[i] = i - 1;
777             }
778
779             // and finally perform the reordering
780
dialog.performReorder(myPerm, target);
781         }
782
783         /** @return True if conditions to continue with DnD
784         * operation were satisfied */

785         boolean checkConditions(DropTargetDragEvent JavaDoc dtde) {
786             int index = comp.locationToIndex(dtde.getLocation());
787
788             return (DnDConstants.ACTION_MOVE == dtde.getDropAction()) && (index >= 0);
789         }
790     }
791      // end of IndexedDropTarget
792

793     /** This class takes responsibility of presenting the
794     * asociated index as transferable object.
795     */

796     private static final class IndexTransferable extends ExTransferable.Single {
797         /** Index to transfer */
798         int index;
799
800         /** Creates transferable of given index */
801         IndexTransferable(DataFlavor JavaDoc flavor, int index) {
802             super(flavor);
803             this.index = index;
804         }
805
806         /* Returns string representation of index */
807         protected Object JavaDoc getData() throws IOException JavaDoc, UnsupportedFlavorException JavaDoc {
808             return String.valueOf(index);
809         }
810     }
811      // end of IndexTransferable
812

813     /** Implements drag and drop visual feedback
814     * support for node list cell rendeder.
815     */

816     private static final class IndexedListCellRenderer implements javax.swing.ListCellRenderer JavaDoc {
817         static final long serialVersionUID = -5526451942677242944L;
818         protected static Border JavaDoc hasFocusBorder;
819
820         static {
821             hasFocusBorder = new LineBorder JavaDoc(UIManager.getColor("List.focusCellHighlight")); // NOI18N
822
}
823
824         /** delegate to use for rendering. Usually NodeRenderer, but if run
825          * without explorer, then it uses DefaultListCellRenderer
826          */

827         private javax.swing.ListCellRenderer JavaDoc delegate = TMUtil.findListCellRenderer();
828
829         /** Index of currently drag under cell in parent list */
830         int dragIndex;
831
832         /** Creates new renderer */
833         IndexedListCellRenderer() {
834             dragIndex = -1;
835         }
836
837         /** DnD operation enters, update visual
838         * presentation to the drag under state */

839         public void draggingEnter(int index, Point JavaDoc startingLoc, Point JavaDoc currentLoc) {
840             // System.out.println("Entering index: " + index); // NOI18N
841
this.dragIndex = index;
842         }
843
844         /** DnD operation dragging over. */
845         public void draggingOver(int index, Point JavaDoc startingLoc, Point JavaDoc currentLoc) {
846         }
847
848         /** DnD operation exits, reset visual state
849         * back to the normal */

850         public void draggingExit() {
851             dragIndex = -1;
852         }
853
854         public Component JavaDoc getListCellRendererComponent(
855             JList JavaDoc list, Object JavaDoc value, int index, boolean isSelected, boolean cellHasFocus
856         ) {
857             JComponent JavaDoc result = (JComponent JavaDoc) delegate.getListCellRendererComponent(
858                     list, value, index, isSelected, cellHasFocus
859                 );
860
861             if (index == dragIndex) {
862                 // System.out.println("Drawing...."); // NOI18N
863
result.setBorder(hasFocusBorder);
864             }
865
866             return result;
867         }
868     }
869      // end of IndexedListCellRenderer
870

871     /** Implements autoscrolling support for JList.
872     * However, JList must be contained in some JViewport.
873     */

874     private static class AutoscrollJList extends JList JavaDoc implements Autoscroll JavaDoc {
875         static final long serialVersionUID = 5495776972406885734L;
876
877         /** Autoscroll insets */
878         Insets JavaDoc scrollInsets;
879
880         /** Insets for the autoscroll method to decide
881         * whether really perform or not */

882         Insets JavaDoc realInsets;
883
884         /** Viewport we are in */
885         JViewport JavaDoc viewport;
886
887         AutoscrollJList() {
888         }
889
890         /** notify the Component to autoscroll */
891         public void autoscroll(Point JavaDoc cursorLoc) {
892             JViewport JavaDoc viewport = getViewport();
893             Point JavaDoc viewPos = viewport.getViewPosition();
894             int viewHeight = viewport.getExtentSize().height;
895
896             if ((cursorLoc.y - viewPos.y) <= realInsets.top) {
897                 // scroll up
898
viewport.setViewPosition(new Point JavaDoc(viewPos.x, Math.max(viewPos.y - realInsets.top, 0)));
899             } else if (((viewPos.y + viewHeight) - cursorLoc.y) <= realInsets.bottom) {
900                 // scroll down
901
viewport.setViewPosition(
902                     new Point JavaDoc(viewPos.x, Math.min(viewPos.y + realInsets.bottom, this.getHeight() - viewHeight))
903                 );
904             }
905         }
906
907         /** @return the Insets describing the autoscrolling
908         * region or border relative to the geometry of the
909         * implementing Component.
910         */

911         public Insets JavaDoc getAutoscrollInsets() {
912             if (scrollInsets == null) {
913                 int height = this.getHeight();
914                 scrollInsets = new Insets JavaDoc(height, 0, height, 0);
915
916                 // compute also autoscroll insets for viewport
917
//Rectangle rect = getViewport().getViewRect();
918
realInsets = new Insets JavaDoc(15, 0, 15, 0);
919             }
920
921             return scrollInsets;
922         }
923
924         /** Asociates given viewport with this list.
925         * (Viewport is usually parent containing this component) */

926         JViewport JavaDoc getViewport() {
927             if (viewport == null) {
928                 Component JavaDoc comp = this;
929
930                 while (!(comp instanceof JViewport JavaDoc) && (comp != null)) {
931                     comp = comp.getParent();
932                 }
933
934                 viewport = (JViewport JavaDoc) comp;
935             }
936
937             return viewport;
938         }
939     }
940      // end of AutoscrollJViewport
941
}
942
Popular Tags