File Source: ArrayListTransferHandler.java

         /* 
    P/P   *  Method: com.dmdirc.addons.ui_swing.components.reorderablelist.ArrayListTransferHandler__static_init
          */
     1  /*
     2   * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
     3   *
     4   * Permission is hereby granted, free of charge, to any person obtaining a copy
     5   * of this software and associated documentation files (the "Software"), to deal
     6   * in the Software without restriction, including without limitation the rights
     7   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   * copies of the Software, and to permit persons to whom the Software is
     9   * furnished to do so, subject to the following conditions:
    10   *
    11   * The above copyright notice and this permission notice shall be included in
    12   * all copies or substantial portions of the Software.
    13   *
    14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   * SOFTWARE.
    21   */
    22  
    23  package com.dmdirc.addons.ui_swing.components.reorderablelist;
    24  
    25  import com.dmdirc.logger.ErrorLevel;
    26  import com.dmdirc.logger.Logger;
    27  
    28  import java.awt.datatransfer.DataFlavor;
    29  import java.awt.datatransfer.Transferable;
    30  import java.awt.datatransfer.UnsupportedFlavorException;
    31  import java.io.IOException;
    32  import java.util.ArrayList;
    33  import java.util.List;
    34  
    35  import javax.swing.DefaultListModel;
    36  import javax.swing.JComponent;
    37  import javax.swing.JList;
    38  import javax.swing.TransferHandler;
    39  
    40  /**
    41   * Arraylist Transfer handler.
    42   */
    43  public final class ArrayListTransferHandler extends TransferHandler {
    44  
    45      /**
    46       * A version number for this class. It should be changed whenever the class
    47       * structure is changed (or anything else that would prevent serialized
    48       * objects being unserialized with the new class).
    49       */
    50      private static final long serialVersionUID = 1;
    51      /** Local Transfer flavour. */
    52      private DataFlavor localArrayListFlavor;
    53      /** Serial Transfer flavour. */
    54      private final DataFlavor serialArrayListFlavor;
    55      /** Source component. */
    56      private JList sourceList;
    57      /** Dragged Indices. */
    58      private int[] indices;
    59      /** Index to add item(s). */
    60      private int addIndex = -1;
    61      /** Number of items to add. */
    62      private int addCount;
    63  
    64      /** Instantiates a new ArrayListTransferHandler. */
    65      public ArrayListTransferHandler() {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.reorderablelist.ArrayListTransferHandler()
                  * 
                  *  Presumptions:
                  *    init'ed(com.dmdirc.logger.ErrorLevel.LOW)
                  * 
                  *  Postconditions:
                  *    this.addIndex == -1
                  *    init'ed(this.localArrayListFlavor)
                  *    this.serialArrayListFlavor == &new DataFlavor(ArrayListTransferHandler#3)
                  *    new DataFlavor(ArrayListTransferHandler#1) num objects <= 1
                  *    new DataFlavor(ArrayListTransferHandler#3) num objects == 1
                  */
    66          super();
    67  
    68          try {
    69              localArrayListFlavor = new DataFlavor(
    70                      DataFlavor.javaJVMLocalObjectMimeType + ";class=java.util.ArrayList");
    71          } catch (ClassNotFoundException e) {
    72              Logger.userError(ErrorLevel.LOW, "unable to create data flavor: " + e.getMessage());
    73          }
    74          serialArrayListFlavor = new DataFlavor(ArrayList.class, "ArrayList"); //NOPMD
    75      }
    76  
    77      /** {@inheritDoc} */
    78      @Override
    79      public boolean importData(final JComponent comp, final Transferable t) {
                 /* 
    P/P           *  Method: bool importData(JComponent, Transferable)
                  * 
                  *  Preconditions:
                  *    t != null
                  *    (soft) comp != null
                  *    (soft) init'ed(this.indices)
                  *    (soft) this.indices.length in {1..232}
                  *    (soft) init'ed(this.indices[0])
                  *    (soft) init'ed(this.indices[...])
                  *    (soft) init'ed(this.localArrayListFlavor)
                  *    (soft) this.sourceList != null
                  * 
                  *  Presumptions:
                  *    init'ed(com.dmdirc.logger.ErrorLevel.LOW)
                  *    java.awt.datatransfer.Transferable:getTransferData(...)@86 != null
                  *    java.awt.datatransfer.Transferable:getTransferData(...)@88 != null
                  *    java.awt.datatransfer.Transferable:getTransferDataFlavors(...).length@80 <= 232-1
                  *    java.awt.datatransfer.Transferable:getTransferDataFlavors(...).length@85 <= 232-1
                  *    ...
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  *    possibly_updated(this.addCount)
                  *    possibly_updated(this.addIndex)
                  *    this.indices == One-of{old this.indices, null}
                  *    init'ed(this.indices)
                  */
    80          if (!canImport(comp, t.getTransferDataFlavors())) {
    81              return false;
    82          }
    83  
    84          try {
    85              if (hasLocalArrayListFlavor(t.getTransferDataFlavors())) {
    86                  return doImport((JList) comp, (ArrayList) t.getTransferData(localArrayListFlavor));
    87              } else if (hasSerialArrayListFlavor(t.getTransferDataFlavors())) {
    88                  return doImport((JList) comp, (ArrayList) t.getTransferData(serialArrayListFlavor));
    89              } else {
    90                  return false;
    91              }
    92          } catch (UnsupportedFlavorException e) {
    93              Logger.userError(ErrorLevel.LOW, "Unsupported data flavor: " + e.getMessage());
    94              return false;
    95          } catch (IOException e) {
    96              Logger.userError(ErrorLevel.LOW, "Unable to import data: " + e.getMessage());
    97              return false;
    98          }
    99      }
   100  
   101      /**
   102       * Imports the tranferrable data into the list.
   103       * 
   104       * @param target target list
   105       * @param transferList transferable list
   106       * 
   107       * @return Whether the data was imported
   108       */
   109      private boolean doImport(final JList target, final List transferList) {
                 /* 
    P/P           *  Method: bool doImport(JList, List)
                  * 
                  *  Preconditions:
                  *    target != null
                  *    this.sourceList != null
                  *    (soft) init'ed(this.indices)
                  *    (soft) this.indices.length in {1..232}
                  *    (soft) init'ed(this.indices[0])
                  *    (soft) init'ed(this.indices[...])
                  *    (soft) transferList != null
                  * 
                  *  Presumptions:
                  *    java.util.List:size(...)@131 + index in {-232..232-1}
                  *    javax.swing.DefaultListModel:getSize(...)@117 <= 232-2
                  *    javax.swing.JList:getModel(...)@116 != null
                  *    javax.swing.JList:getSelectedIndex(...)@110 <= 232-3
                  * 
                  *  Postconditions:
                  *    return_value == 1
                  *    possibly_updated(this.addCount)
                  *    possibly_updated(this.addIndex)
                  *    this.indices == One-of{null, old this.indices}
                  *    init'ed(this.indices)
                  * 
                  *  Test Vectors:
                  *    this.indices: Addr_Set{null}, Inverse{null}
                  *    java.lang.Object:equals(...)@111: {0}, {1}
                  *    javax.swing.JList:getSelectedIndex(...)@110: {0..232-3}, {-231..-1}
                  */
   110          int index = target.getSelectedIndex();
   111          if (sourceList.equals(target) && indices != null && index >= indices[0] - 1 && index <= indices[indices.length - 1]) {
   112              indices = null;
   113              return true;
   114          }
   115  
   116          final DefaultListModel listModel = (DefaultListModel) target.getModel();
   117          final int max = listModel.getSize();
   118  
   119          if (index < 0) {
   120              index = max;
   121          } else {
   122              index++;
   123              if (index > max) {
   124                  index = max;
   125              }
   126  
   127          }
   128          addIndex = index;
   129          addCount = transferList.size();
   130  
   131          for (int i = 0; i < transferList.size(); i++) {
   132              listModel.add(index++, transferList.get(i));
   133          }
   134  
   135          return true;
   136      }
   137  
   138      /** {@inheritDoc} */
   139      @Override
   140      protected void exportDone(final JComponent source, final Transferable data,
   141              final int action) {
                 /* 
    P/P           *  Method: void exportDone(JComponent, Transferable, int)
                  * 
                  *  Preconditions:
                  *    (soft) init'ed(this.addCount)
                  *    (soft) this.addIndex != 232-2
                  *    (soft) init'ed(this.indices)
                  *    (soft) this.indices[...] in {-231+1..232-2}
                  *    (soft) this.indices.length <= 232-1
                  *    (soft) this.sourceList != null
                  * 
                  *  Presumptions:
                  *    javax.swing.JList:getModel(...)@143 != null
                  * 
                  *  Postconditions:
                  *    this.addCount == 0
                  *    this.addIndex == -1
                  *    this.indices == null
                  *    init'ed(this.indices[...])
                  * 
                  *  Test Vectors:
                  *    action: {-231..1, 3..232-1}, {2}
                  *    this.addCount: {-231..0}, {1..232-1}
                  *    this.indices: Addr_Set{null}, Inverse{null}
                  */
   142          if ((action == MOVE) && (indices != null)) {
   143              final DefaultListModel model = (DefaultListModel) sourceList.getModel();
   144  
   145              if (addCount > 0) {
   146                  for (int i = 0; i < indices.length; i++) {
   147                      if (indices[i] > addIndex) {
   148                          indices[i] += addCount;
   149                      }
   150                  }
   151              }
   152              for (int i = indices.length - 1; i >= 0; i--) {
   153                  model.remove(indices[i]);
   154              }
   155          }
   156  
   157          indices = null;
   158          addIndex = -1;
   159          addCount = 0;
   160      }
   161  
   162      /** 
   163       * Do any of the specified flavours match the local flavour.
   164       * 
   165       * @param transferFlavors Flavours to check
   166       *
   167       * @return whether the transferFlavors is supported
   168       */
   169      private boolean hasLocalArrayListFlavor(final DataFlavor[] transferFlavors) {
                 /* 
    P/P           *  Method: bool hasLocalArrayListFlavor(DataFlavor[])
                  * 
                  *  Preconditions:
                  *    init'ed(this.localArrayListFlavor)
                  *    (soft) transferFlavors != null
                  *    (soft) transferFlavors.length <= 232-1
                  *    (soft) transferFlavors[...] != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    this.localArrayListFlavor: Inverse{null}, Addr_Set{null}
                  *    java.awt.datatransfer.DataFlavor:equals(...)@175: {0}, {1}
                  */
   170          if (localArrayListFlavor == null) {
   171              return false;
   172          }
   173  
   174          for (int i = 0; i < transferFlavors.length; i++) {
   175              if (transferFlavors[i].equals(localArrayListFlavor)) {
   176                  return true;
   177              }
   178          }
   179  
   180          return false;
   181      }
   182  
   183      /** 
   184       * Do any of the specified flavours match the serial flavour.
   185       * 
   186       * @param transferFlavors Flavours to check
   187       *
   188       * @return whether the flavour is supported
   189       */
   190      private boolean hasSerialArrayListFlavor(final DataFlavor[] transferFlavors) {
                 /* 
    P/P           *  Method: bool hasSerialArrayListFlavor(DataFlavor[])
                  * 
                  *  Preconditions:
                  *    (soft) transferFlavors != null
                  *    (soft) transferFlavors.length <= 232-1
                  *    (soft) transferFlavors[...] != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    this.serialArrayListFlavor: Inverse{null}, Addr_Set{null}
                  *    java.awt.datatransfer.DataFlavor:equals(...)@196: {0}, {1}
                  */
   191          if (serialArrayListFlavor == null) {
   192              return false;
   193          }
   194  
   195          for (int i = 0; i < transferFlavors.length; i++) {
   196              if (transferFlavors[i].equals(serialArrayListFlavor)) {
   197                  return true;
   198              }
   199          }
   200  
   201          return false;
   202      }
   203  
   204      /** {@inheritDoc} */
   205      @Override
   206      public boolean canImport(final JComponent comp, final DataFlavor[] transferFlavors) {
                 /* 
    P/P           *  Method: bool canImport(JComponent, DataFlavor[])
                  * 
                  *  Preconditions:
                  *    (soft) init'ed(this.localArrayListFlavor)
                  *    (soft) transferFlavors != null
                  *    (soft) transferFlavors.length <= 232-1
                  *    (soft) transferFlavors[...] != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   207          if (!(comp instanceof JList) || !(((JList) comp).getModel() instanceof DefaultListModel)) {
   208              return false;
   209          }
   210  
   211          if (hasLocalArrayListFlavor(transferFlavors)) {
   212              return true;
   213          }
   214  
   215          if (hasSerialArrayListFlavor(transferFlavors)) {
   216              return true;
   217          }
   218  
   219          return false;
   220      }
   221  
   222      /** {@inheritDoc} */
   223      @Override
   224      protected Transferable createTransferable(final JComponent c) {
                 /* 
    P/P           *  Method: Transferable createTransferable(JComponent)
                  * 
                  *  Presumptions:
                  *    values.length@228 <= 232-1
                  *    values[i]@228 != null
                  * 
                  *  Postconditions:
                  *    return_value in Addr_Set{null,&amp;new ArrayListTransferable(createTransferable#2)}
                  *    possibly_updated(this.indices)
                  *    this.sourceList == One-of{c, old this.sourceList}
                  *    new ArrayList(createTransferable#1) num objects <= 1
                  *    new ArrayListTransferable(createTransferable#2) num objects <= 1
                  *    new ArrayListTransferable(createTransferable#2).data == &amp;new ArrayList(createTransferable#1)
                  *    new ArrayListTransferable(createTransferable#2).localArrayListFlavor in Addr_Set{null,&amp;new DataFlavor(ArrayListTransferable#1)}
                  *    new ArrayListTransferable(createTransferable#2).serialArrayListFlavor == &amp;new DataFlavor(ArrayListTransferable#3)
                  *    new DataFlavor(ArrayListTransferable#1) num objects <= 1
                  *    new DataFlavor(ArrayListTransferable#3) num objects <= 1
                  * 
                  *  Test Vectors:
                  *    javax.swing.JList:getSelectedValues(...)@228: Addr_Set{null}, Inverse{null}
                  *    values.length@228: {1..232-1}, {0}
                  */
   225          if (c instanceof JList) {
   226              sourceList = (JList) c;
   227              indices = sourceList.getSelectedIndices();
   228              final Object[] values = sourceList.getSelectedValues();
   229  
   230              if (values == null || values.length == 0) {
   231                  return null;
   232              }
   233  
   234              final ArrayList<Object> alist = new ArrayList<Object>(values.length);
   235  
   236              for (int i = 0; i < values.length; i++) {
   237                  final Object o = values[i];
   238                  String str = o.toString();
   239                  if (str == null) {
   240                      str = "";
   241                  }
   242                  alist.add(str);
   243              }
   244  
   245              return new ArrayListTransferable(alist);
   246          }
   247  
   248          return null;
   249      }
   250  
   251      /** {@inheritDoc} */
   252      @Override
   253      public int getSourceActions(final JComponent c) {
                 /* 
    P/P           *  Method: int getSourceActions(JComponent)
                  * 
                  *  Postconditions:
                  *    return_value == 3
                  */
   254          return COPY_OR_MOVE;
   255      }
   256  }








SofCheck Inspector Build Version : 2.17854
ArrayListTransferHandler.java 2009-Jun-25 01:54:24
ArrayListTransferHandler.class 2009-Sep-02 17:04:15