Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/puppycrawl/tools/checkstyle/gui/FileDrop.java


1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2002  Oliver Burn
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.gui;
21  
22  import java.awt.Color;
23  import java.awt.Component;
24  import java.awt.Container;
25  import java.awt.datatransfer.DataFlavor;
26  import java.awt.datatransfer.Transferable;
27  import java.awt.datatransfer.UnsupportedFlavorException;
28  import java.awt.dnd.DnDConstants;
29  import java.awt.dnd.DropTarget;
30  import java.awt.dnd.DropTargetDragEvent;
31  import java.awt.dnd.DropTargetDropEvent;
32  import java.awt.dnd.DropTargetEvent;
33  import java.awt.dnd.DropTargetListener;
34  import java.awt.event.HierarchyEvent;
35  import java.awt.event.HierarchyListener;
36  import java.io.File;
37  import java.io.IOException;
38  import java.util.List;
39  import java.util.TooManyListenersException;
40  import javax.swing.BorderFactory;
41  import javax.swing.JComponent;
42  import javax.swing.border.Border;
43  
44  /**
45   * This class makes it easy to drag and drop files from the operating
46   * system to a Java program. Any <tt>java.awt.Component</tt> can be
47   * dropped onto, but only <tt>javax.swing.JComponent</tt>s will indicate
48   * the drop event with a changed border.
49   * <p/>
50   * To use this class, construct a new <tt>FileDrop</tt> by passing
51   * it the target component and a <tt>Listener</tt> to receive notification
52   * when file(s) have been dropped. Here is an example:
53   * <p/>
54   * <code><pre>
55   *      JPanel myPanel = new JPanel();
56   *      new FileDrop( myPanel, new FileDrop.Listener()
57   *      {   public void filesDropped( java.io.File[] files )
58   *          {   
59   *              // handle file drop
60   *              ...
61   *          }   // end filesDropped
62   *      }); // end FileDrop.Listener
63   * </pre></code>
64   * <p/>
65   * You can specify the border that will appear when files are being dragged by
66   * calling the constructor with a <tt>javax.swing.border.Border</tt>. Only
67   * <tt>JComponent</tt>s will show any indication with a border.
68   * <p/>
69   *
70   * <p>Original author: Robert Harder, rharder@usa.net</p>
71   *
72   * @author  Robert Harder
73   * @author  Lars K?hne
74   */
75  class FileDrop
76  {
77      // TODO: Not sure that changing borders is a good idea.
78      // At least we should make sure that the border insets are preserved so
79      // that the panel layout does not change during the DnD operation.
80  
81      private transient Border normalBorder;
82      private transient DropTargetListener dropListener;
83  
84      // TODO: Blue is not a nice color in all LookAndFeels
85      /* Default border color */
86      private static final Color DEFAULT_BORDER_COLOR =
87              new Color(0f, 0f, 1f, 0.25f);
88  
89      /**
90       * Constructs a {@link FileDrop} with a default light-blue border
91       * and, if <var>c</var> is a {@link java.awt.Container}, recursively
92       * sets all elements contained within as drop targets, though only
93       * the top level container will change borders.
94       *
95       * @param c Component on which files will be dropped.
96       * @param listener Listens for <tt>filesDropped</tt>.
97       * @since 1.0
98       */
99      FileDrop(
100             final Component c,
101             final Listener listener)
102             throws TooManyListenersException
103     {
104         this(   c, // Drop target
105                 BorderFactory.createMatteBorder(2, 2, 2, 2, DEFAULT_BORDER_COLOR), // Drag border
106                 true, // Recursive
107                 listener);
108     }
109 
110 
111     /**
112      * Full constructor with a specified border and debugging optionally turned on.
113      * With Debugging turned on, more status messages will be displayed to
114      * <tt>out</tt>. A common way to use this constructor is with
115      * <tt>System.out</tt> or <tt>System.err</tt>. A <tt>null</tt> value for
116      * the parameter <tt>out</tt> will result in no debugging output.
117      *
118      * @param c Component on which files will be dropped.
119      * @param dragBorder Border to use on <tt>JComponent</tt> when dragging occurs.
120      * @param recursive Recursively set children as drop targets.
121      * @param listener Listens for <tt>filesDropped</tt>.
122      * @since 1.0
123      */
124     FileDrop(
125             final Component c,
126             final Border dragBorder,
127             final boolean recursive,
128             final Listener listener)
129             throws TooManyListenersException
130     {
131         dropListener = new FileDropTargetListener(c, dragBorder, listener);
132         makeDropTarget(c, recursive);
133     }
134 
135 
136     private void makeDropTarget(final Component c, boolean recursive)
137             throws TooManyListenersException
138     {
139         // Make drop target
140         final DropTarget dt = new DropTarget();
141         dt.addDropTargetListener(dropListener);
142 
143         // Listen for hierarchy changes and remove the
144         // drop target when the parent gets cleared out.
145         c.addHierarchyListener(new HierarchyListener()
146         {
147             public void hierarchyChanged(HierarchyEvent evt)
148             {
149                 Component parent = c.getParent();
150                 if (parent == null) {
151                     c.setDropTarget(null);
152                 }
153                 else {
154                     new DropTarget(c, dropListener);
155                 }
156             }
157         });
158 
159         if (c.getParent() != null) {
160             new DropTarget(c, dropListener);
161         }
162 
163         if (recursive && (c instanceof Container)) {
164             Container cont = (Container) c;
165             Component[] comps = cont.getComponents();
166             for (int i = 0; i < comps.length; i++)
167                 makeDropTarget(comps[i], recursive);
168         }
169     }
170 
171 
172     /** Determine if the dragged data is a file list. */
173     private boolean isDragOk(final DropTargetDragEvent evt)
174     {
175         boolean ok = false;
176         DataFlavor[] flavors = evt.getCurrentDataFlavors();
177 
178         // See if any of the flavors are a file list
179         int i = 0;
180         while (!ok && i < flavors.length) {   // Is the flavor a file list?
181             if (flavors[i].equals(DataFlavor.javaFileListFlavor))
182                 ok = true;
183             i++;
184         }
185 
186         return ok;
187     }
188 
189 
190     /**
191      * Removes the drag-and-drop hooks from the component and optionally
192      * from the all children. You should call this if you add and remove
193      * components after you've set up the drag-and-drop.
194      * This will recursively unregister all components contained within
195      * <var>c</var> if <var>c</var> is a {@link .Container}.
196      *
197      * @param c The component to unregister as a drop target
198      * @since 1.0
199      */
200     static void remove(Component c)
201     {
202         remove(c, true);
203     }
204 
205 
206     /**
207      * Removes the drag-and-drop hooks from the component and optionally
208      * from the all children. You should call this if you add and remove
209      * components after you've set up the drag-and-drop.
210      *
211      * @param c The component to unregister
212      * @param recursive Recursively unregister components within a container
213      * @since 1.0
214      */
215     static void remove(Component c, boolean recursive)
216     {
217         c.setDropTarget(null);
218         if (recursive && (c instanceof Container)) {
219             Component[] comps = ((Container) c).getComponents();
220             for (int i = 0; i < comps.length; i++) {
221                 remove(comps[i], recursive);
222             }
223         }
224     }
225 
226 
227     /**
228      * Implement this inner interface to listen for when files are dropped. For example
229      * your class declaration may begin like this:
230      * <code><pre>
231      *      public class MyClass implements FileDrop.Listener
232      *      ...
233      *      public void filesDropped( File[] files )
234      *      {
235      *          ...
236      *      }   // end filesDropped
237      *      ...
238      * </pre></code>
239      *
240      * @since 1.0
241      */
242     public interface Listener
243     {
244         /**
245          * This method is called when files have been successfully dropped.
246          *
247          * @param files An array of <tt>File</tt>s that were dropped.
248          * @since 1.0
249          */
250         void filesDropped(File[] files);
251     }
252 
253     private class FileDropTargetListener implements DropTargetListener
254     {
255         private final Component mC;
256         private final Border mDragBorder;
257         private final Listener mListener;
258 
259         public void dragEnter(DropTargetDragEvent evt)
260         {
261             if (isDragOk(evt)) {
262                 if (mC instanceof JComponent) {
263                     JComponent jc = (JComponent) mC;
264                     normalBorder = jc.getBorder();
265                     jc.setBorder(mDragBorder);
266                 }
267                 evt.acceptDrag(DnDConstants.ACTION_COPY);
268             }
269             else {
270                 evt.rejectDrag();
271             }
272         }
273 
274         public void drop(DropTargetDropEvent evt)
275         {
276             try {
277                 Transferable tr = evt.getTransferable();
278 
279                 if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
280                     evt.acceptDrop(DnDConstants.ACTION_COPY);
281 
282                     List fileList = (List) tr.getTransferData(
283                             DataFlavor.javaFileListFlavor);
284                     File[] files = new File[fileList.size()];
285                     fileList.toArray(files);
286 
287                     if (mListener != null) {
288                         mListener.filesDropped(files);
289                     }
290 
291                     evt.getDropTargetContext().dropComplete(true);
292                 }
293                 else {
294                     evt.rejectDrop();
295                 }
296             }
297             catch (IOException io) {
298                 evt.rejectDrop();
299             }
300             catch (UnsupportedFlavorException ufe) {
301                 evt.rejectDrop();
302             }
303             finally {
304                 if (mC instanceof JComponent) {
305                     JComponent jc = (JComponent) mC;
306                     jc.setBorder(normalBorder);
307                 }
308             }
309         }
310 
311         public void dragExit(DropTargetEvent evt)
312         {
313             if (mC instanceof JComponent) {
314                 JComponent jc = (JComponent) mC;
315                 jc.setBorder(normalBorder);
316             }
317         }
318 
319         public void dropActionChanged(DropTargetDragEvent evt)
320         {
321             if (isDragOk(evt)) {
322                 evt.acceptDrag(DnDConstants.ACTION_COPY);
323             }
324             else {
325                 evt.rejectDrag();
326             }
327         }
328 
329         public void dragOver(DropTargetDragEvent dtde)
330         {
331         }
332 
333         public FileDropTargetListener(Component aC, Border aDragBorder, Listener aListener)
334         {
335             mC = aC;
336             mDragBorder = aDragBorder;
337             mListener = aListener;
338         }
339     }
340 
341 }