You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ArrayListTransferHandler.java 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. * Copyright (c) 2006-2010 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. package com.dmdirc.addons.ui_swing.components.reorderablelist;
  23. import com.dmdirc.logger.ErrorLevel;
  24. import com.dmdirc.logger.Logger;
  25. import java.awt.datatransfer.DataFlavor;
  26. import java.awt.datatransfer.Transferable;
  27. import java.awt.datatransfer.UnsupportedFlavorException;
  28. import java.io.IOException;
  29. import java.util.ArrayList;
  30. import java.util.List;
  31. import javax.swing.DefaultListModel;
  32. import javax.swing.JComponent;
  33. import javax.swing.JList;
  34. import javax.swing.TransferHandler;
  35. /**
  36. * Arraylist Transfer handler.
  37. */
  38. public final class ArrayListTransferHandler extends TransferHandler {
  39. /**
  40. * A version number for this class. It should be changed whenever the class
  41. * structure is changed (or anything else that would prevent serialized
  42. * objects being unserialized with the new class).
  43. */
  44. private static final long serialVersionUID = 1;
  45. /** Local Transfer flavour. */
  46. private DataFlavor localArrayListFlavor;
  47. /** Serial Transfer flavour. */
  48. private final DataFlavor serialArrayListFlavor;
  49. /** Source component. */
  50. private JList sourceList;
  51. /** Dragged Indices. */
  52. private int[] indices;
  53. /** Index to add item(s). */
  54. private int addIndex = -1;
  55. /** Number of items to add. */
  56. private int addCount;
  57. /** Instantiates a new ArrayListTransferHandler. */
  58. public ArrayListTransferHandler() {
  59. super();
  60. try {
  61. localArrayListFlavor = new DataFlavor(
  62. DataFlavor.javaJVMLocalObjectMimeType + ";class=java.util.ArrayList");
  63. } catch (ClassNotFoundException e) {
  64. Logger.userError(ErrorLevel.LOW, "unable to create data flavor: " + e.getMessage());
  65. }
  66. serialArrayListFlavor = new DataFlavor(ArrayList.class, "ArrayList"); //NOPMD
  67. }
  68. /** {@inheritDoc} */
  69. @Override
  70. public boolean importData(final JComponent comp, final Transferable t) {
  71. if (!canImport(comp, t.getTransferDataFlavors())) {
  72. return false;
  73. }
  74. try {
  75. if (hasLocalArrayListFlavor(t.getTransferDataFlavors())) {
  76. return doImport((JList) comp, (ArrayList) t.getTransferData(localArrayListFlavor));
  77. } else if (hasSerialArrayListFlavor(t.getTransferDataFlavors())) {
  78. return doImport((JList) comp, (ArrayList) t.getTransferData(serialArrayListFlavor));
  79. } else {
  80. return false;
  81. }
  82. } catch (UnsupportedFlavorException e) {
  83. Logger.userError(ErrorLevel.LOW, "Unsupported data flavor: " + e.getMessage());
  84. return false;
  85. } catch (IOException e) {
  86. Logger.userError(ErrorLevel.LOW, "Unable to import data: " + e.getMessage());
  87. return false;
  88. }
  89. }
  90. /**
  91. * Imports the tranferrable data into the list.
  92. *
  93. * @param target target list
  94. * @param transferList transferable list
  95. *
  96. * @return Whether the data was imported
  97. */
  98. private boolean doImport(final JList target, final List transferList) {
  99. int index = target.getSelectedIndex();
  100. if (sourceList.equals(target) && indices != null && index >= indices[0] - 1 && index <= indices[indices.length - 1]) {
  101. indices = null;
  102. return true;
  103. }
  104. final DefaultListModel listModel = (DefaultListModel) target.getModel();
  105. final int max = listModel.getSize();
  106. if (index < 0) {
  107. index = max;
  108. } else {
  109. index++;
  110. if (index > max) {
  111. index = max;
  112. }
  113. }
  114. addIndex = index;
  115. addCount = transferList.size();
  116. for (int i = 0; i < transferList.size(); i++) {
  117. listModel.add(index++, transferList.get(i));
  118. }
  119. return true;
  120. }
  121. /** {@inheritDoc} */
  122. @Override
  123. protected void exportDone(final JComponent source, final Transferable data,
  124. final int action) {
  125. if ((action == MOVE) && (indices != null)) {
  126. final DefaultListModel model = (DefaultListModel) sourceList.getModel();
  127. if (addCount > 0) {
  128. for (int i = 0; i < indices.length; i++) {
  129. if (indices[i] > addIndex) {
  130. indices[i] += addCount;
  131. }
  132. }
  133. }
  134. for (int i = indices.length - 1; i >= 0; i--) {
  135. model.remove(indices[i]);
  136. }
  137. }
  138. indices = null;
  139. addIndex = -1;
  140. addCount = 0;
  141. }
  142. /**
  143. * Do any of the specified flavours match the local flavour.
  144. *
  145. * @param transferFlavors Flavours to check
  146. *
  147. * @return whether the transferFlavors is supported
  148. */
  149. private boolean hasLocalArrayListFlavor(final DataFlavor[] transferFlavors) {
  150. if (localArrayListFlavor == null) {
  151. return false;
  152. }
  153. for (int i = 0; i < transferFlavors.length; i++) {
  154. if (transferFlavors[i].equals(localArrayListFlavor)) {
  155. return true;
  156. }
  157. }
  158. return false;
  159. }
  160. /**
  161. * Do any of the specified flavours match the serial flavour.
  162. *
  163. * @param transferFlavors Flavours to check
  164. *
  165. * @return whether the flavour is supported
  166. */
  167. private boolean hasSerialArrayListFlavor(final DataFlavor[] transferFlavors) {
  168. if (serialArrayListFlavor == null) {
  169. return false;
  170. }
  171. for (int i = 0; i < transferFlavors.length; i++) {
  172. if (transferFlavors[i].equals(serialArrayListFlavor)) {
  173. return true;
  174. }
  175. }
  176. return false;
  177. }
  178. /** {@inheritDoc} */
  179. @Override
  180. public boolean canImport(final JComponent comp, final DataFlavor[] transferFlavors) {
  181. return comp instanceof JList && ((JList) comp).getModel() instanceof DefaultListModel
  182. && (hasLocalArrayListFlavor(transferFlavors)
  183. || hasSerialArrayListFlavor(transferFlavors));
  184. }
  185. /** {@inheritDoc} */
  186. @Override
  187. protected Transferable createTransferable(final JComponent c) {
  188. if (c instanceof JList) {
  189. sourceList = (JList) c;
  190. indices = sourceList.getSelectedIndices();
  191. final Object[] values = sourceList.getSelectedValues();
  192. if (values == null || values.length == 0) {
  193. return null;
  194. }
  195. final ArrayList<Object> alist = new ArrayList<Object>(values.length);
  196. for (int i = 0; i < values.length; i++) {
  197. final Object o = values[i];
  198. String str = o.toString();
  199. if (str == null) {
  200. str = "";
  201. }
  202. alist.add(str);
  203. }
  204. return new ArrayListTransferable(alist);
  205. }
  206. return null;
  207. }
  208. /** {@inheritDoc} */
  209. @Override
  210. public int getSourceActions(final JComponent c) {
  211. return COPY_OR_MOVE;
  212. }
  213. }