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,&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 == &new ArrayList(createTransferable#1)
* new ArrayListTransferable(createTransferable#2).localArrayListFlavor in Addr_Set{null,&new DataFlavor(ArrayListTransferable#1)}
* new ArrayListTransferable(createTransferable#2).serialArrayListFlavor == &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 |