View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.log4j.chainsaw.dnd;
    18
    19
    20  import org.apache.log4j.Logger;
    21
    22  import javax.swing.*;
    23  import java.awt.*;
    24  import java.awt.datatransfer.DataFlavor;
    25  import java.awt.datatransfer.Transferable;
    26  import java.awt.dnd.*;
    27  import java.beans.PropertyChangeListener;
    28  import java.beans.PropertyChangeSupport;
    29  import java.util.HashMap;
    30  import java.util.List;
    31  import java.util.Map;
    32
    33  /**
    34   * This class provides all the functionality to work out when files are dragged onto
    35   * a particular JComponent instance, and then notifies listeners via
    36   * the standard PropertyChangesListener semantics to indicate that a list of
    37   * files have been dropped onto the target.
    38   * <p>
    39   * If you wish to know whan the files have been dropped, subscribe to the "fileList" property change.
    40   *
    41   * @author psmith
    42   */
    43  public class FileDnDTarget implements DropTargetListener {
    44      /**
    45       * Logger for this class
    46       */
    47      private static final Logger LOG = Logger.getLogger(FileDnDTarget.class);
    48
    49      protected int acceptableActions = DnDConstants.ACTION_COPY;
    50
    51      private List fileList;
    52
    53      private JComponent guiTarget;
    54      private Map<JComponent, DropTarget> dropTargets = new HashMap<>();
    55
    56
    57      private PropertyChangeSupport propertySupport = new PropertyChangeSupport(this);
    58
    59      /**
    60       *
    61       */
    62      public FileDnDTarget(JComponent c) {
    63          this.guiTarget = c;
    64      }
    65
    66      public void addDropTargetToComponent(JComponent c) {
    67          dropTargets.put(c, new DropTarget(c, this));
    68      }
    69
    70      /**
    71       * @param listener
    72       */
    73      public void addPropertyChangeListener(PropertyChangeListener listener) {
    74          propertySupport.addPropertyChangeListener(listener);
    75      }
    76
    77      /**
    78       * @param propertyName
    79       * @param listener
    80       */
    81      public void addPropertyChangeListener(String propertyName,
    82                                            PropertyChangeListener listener) {
    83          propertySupport.addPropertyChangeListener(propertyName, listener);
    84      }
    85
    86      /**
    87       *
    88       */
    89      private void decorateComponent() {
    90  //        TODO work out a better way of decorating a component
    91          guiTarget.setBorder(BorderFactory.createLineBorder(Color.black));
    92      }
    93
    94
    95      public void dragEnter(DropTargetDragEvent e) {
    96          //LOG.debug(dtde);
    97          if (isDragOk(e) == false) {
    98              e.rejectDrag();
    99              return;
    100         }
    101         decorateComponent();
    102
    103         e.acceptDrag(acceptableActions);
    104     }
    105
    106
    107     public void dragExit(DropTargetEvent dte) {
    108         removeComponentDecoration();
    109     }
    110
    111
    112     public void dragOver(DropTargetDragEvent e) {
    113         //LOG.debug(dtde);
    114
    115         if (isDragOk(e) == false) {
    116             e.rejectDrag();
    117             return;
    118         }
    119         e.acceptDrag(acceptableActions);
    120     }
    121
    122     public void drop(DropTargetDropEvent dtde) {
    123         Transferable transferable = dtde.getTransferable();
    124         LOG.debug(transferable);
    125         dtde.acceptDrop(acceptableActions);
    126         try {
    127             List list = (List) transferable.getTransferData(DataFlavor.javaFileListFlavor);
    128             LOG.debug(list);
    129             setFileList(list);
    130             dtde.getDropTargetContext().dropComplete(true);
    131             removeComponentDecoration();
    132
    133         } catch (Exception e) {
    134             LOG.error("Error with DnD", e);
    135         }
    136
    137     }
    138
    139     public void dropActionChanged(DropTargetDragEvent dtde) {
    140         //LOG.debug(dtde);
    141     }
    142
    143     /**
    144      * @return Returns the fileList.
    145      */
    146     public final List getFileList() {
    147         return fileList;
    148     }
    149
    150     private boolean isDragOk(DropTargetDragEvent e) {
    151         DataFlavor[] flavors = new DataFlavor[]{DataFlavor.javaFileListFlavor};
    152         DataFlavor chosen = null;
    153         for (DataFlavor flavor : flavors) {
    154             if (e.isDataFlavorSupported(flavor)) {
    155                 chosen = flavor;
    156                 break;
    157             }
    158         }
    159         /*
    160          * the src does not support any of the StringTransferable flavors
    161          */
    162         if (chosen == null) {
    163             return false;
    164         }
    165         // the actions specified when the source
    166         // created the DragGestureRecognizer
    167         int sa = e.getSourceActions();
    168
    169         // we're saying that these actions are necessary
    170         return (sa & acceptableActions) != 0;
    171     }
    172
    173     /**
    174      *
    175      */
    176     private void removeComponentDecoration() {
    177         this.guiTarget.setBorder(null);
    178     }
    179
    180     /**
    181      * @param listener
    182      */
    183     public void removePropertyChangeListener(PropertyChangeListener listener) {
    184         propertySupport.removePropertyChangeListener(listener);
    185     }
    186
    187     /**
    188      * @param propertyName
    189      * @param listener
    190      */
    191     public void removePropertyChangeListener(String propertyName,
    192                                              PropertyChangeListener listener) {
    193         propertySupport.removePropertyChangeListener(propertyName, listener);
    194     }
    195
    196     /**
    197      * @param fileList The fileList to set.
    198      */
    199     private final void setFileList(List fileList) {
    200         Object oldValue = this.fileList;
    201         this.fileList = fileList;
    202         propertySupport.firePropertyChange("fileList", oldValue, this.fileList);
    203     }
    204 }