001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Evgeniya G. Maenkova
019: * @version $Revision$
020: */package javax.swing;
021:
022: import java.awt.Toolkit;
023: import java.awt.datatransfer.Clipboard;
024: import java.awt.datatransfer.DataFlavor;
025: import java.awt.datatransfer.Transferable;
026: import java.awt.datatransfer.UnsupportedFlavorException;
027: import java.awt.event.ActionEvent;
028: import java.awt.event.InputEvent;
029: import java.beans.BeanInfo;
030: import java.beans.IntrospectionException;
031: import java.beans.Introspector;
032: import java.beans.PropertyDescriptor;
033: import java.io.IOException;
034: import java.io.Serializable;
035: import java.lang.reflect.InvocationTargetException;
036: import java.lang.reflect.Method;
037:
038: import org.apache.harmony.awt.text.ActionNames;
039:
040: public class TransferHandler implements Serializable {
041: public static final int NONE = ActionNames.NONE;
042: public static final int COPY = ActionNames.COPY;
043: public static final int MOVE = ActionNames.MOVE;
044: public static final int COPY_OR_MOVE = ActionNames.COPY_OR_MOVE;
045: private static final String MIME_PREFIX = DataFlavor.javaJVMLocalObjectMimeType
046: + ";class=";
047:
048: private static final String CUT_ACTION_NAME = "cut";
049: private static final String COPY_ACTION_NAME = "copy";
050: private static final String PASTE_ACTION_NAME = "paste";
051:
052: private static final Action CUT_ACTION = new AbstractAction(
053: CUT_ACTION_NAME) {
054: public void actionPerformed(final ActionEvent e) {
055: Object source = e.getSource();
056: TransferHandler transferHandler = getTransferHandler(source);
057: Clipboard clipboard = getSystemClipboard();
058:
059: if ((transferHandler != null) && (clipboard != null)) {
060: transferHandler.exportToClipboard((JComponent) source,
061: clipboard, MOVE);
062: }
063: }
064: };
065:
066: private static final Action COPY_ACTION = new AbstractAction(
067: COPY_ACTION_NAME) {
068: public void actionPerformed(final ActionEvent e) {
069: Object source = e.getSource();
070: TransferHandler transferHandler = getTransferHandler(source);
071: Clipboard clipboard = getSystemClipboard();
072:
073: if ((transferHandler != null) && (clipboard != null)) {
074: transferHandler.exportToClipboard((JComponent) source,
075: clipboard, COPY);
076: }
077: }
078: };
079:
080: private static final Action PASTE_ACTION = new AbstractAction(
081: PASTE_ACTION_NAME) {
082: public void actionPerformed(final ActionEvent e) {
083: Object source = e.getSource();
084: TransferHandler transferHandler = getTransferHandler(source);
085: Clipboard clipboard = getSystemClipboard();
086:
087: if ((transferHandler != null) && (clipboard != null)) {
088: Transferable t = clipboard.getContents(this );
089:
090: if (t != null) {
091: transferHandler.importData((JComponent) source, t);
092: }
093: }
094: }
095: };
096:
097: private class Data implements Transferable {
098: DataFlavor[] flavors;
099: JComponent component;
100: Object value;
101:
102: public Data(final JComponent c) {
103: component = c;
104: PropertyDescriptor descriptor = getPropertyDescriptor(c);
105: if (descriptor == null) {
106: return;
107: }
108:
109: Method reader = descriptor.getReadMethod();
110: try {
111: value = reader.invoke(component, (Object[]) null);
112: } catch (InvocationTargetException e) {
113: } catch (IllegalAccessException e) {
114: }
115: String mimeType = MIME_PREFIX
116: + descriptor.getPropertyType().getName();
117: DataFlavor flavor = null;
118: try {
119: flavor = new DataFlavor(mimeType);
120: } catch (ClassNotFoundException e) {
121:
122: }
123: flavors = new DataFlavor[] { flavor };
124: }
125:
126: public Object getTransferData(final DataFlavor flavor)
127: throws UnsupportedFlavorException, IOException {
128: return value;
129: }
130:
131: public DataFlavor[] getTransferDataFlavors() {
132: return flavors;
133: }
134:
135: public boolean isDataFlavorSupported(final DataFlavor flavor) {
136: for (int i = 0; i < flavors.length; i++) {
137: if (flavors[i].equals(flavor)) {
138: return true;
139: }
140: }
141: return false;
142: }
143: }
144:
145: private static TransferHandler getTransferHandler(final Object src) {
146: Object source = src;
147: return (source instanceof JComponent) ? ((JComponent) source)
148: .getTransferHandler() : null;
149: }
150:
151: private static Clipboard getSystemClipboard() {
152: try {
153: return Toolkit.getDefaultToolkit().getSystemClipboard();
154: } catch (SecurityException e) {
155: // we need to catch this exception in order to be compatible with RI
156: // see HARMONY-3479
157: return null;
158: }
159: }
160:
161: private PropertyDescriptor getPropertyDescriptor(final JComponent c) {
162: PropertyDescriptor result = null;
163: try {
164: result = new PropertyDescriptor(propertyName, c.getClass());
165: } catch (IntrospectionException e) {
166: try {
167: BeanInfo bi = Introspector.getBeanInfo(c.getClass());
168: PropertyDescriptor pds[] = bi.getPropertyDescriptors();
169: for (int i = 0; i < pds.length; i++) {
170: if (pds[i].getName().equals(propertyName)) {
171: return pds[i];
172: }
173: }
174: } catch (IntrospectionException e1) {
175: }
176: }
177: return result;
178: }
179:
180: private String propertyName;
181:
182: public TransferHandler(final String property) {
183: propertyName = property;
184: }
185:
186: protected TransferHandler() {
187: this (null);
188: }
189:
190: public Icon getVisualRepresentation(final Transferable t) {
191: return null;
192: }
193:
194: public void exportAsDrag(final JComponent c, final InputEvent e,
195: final int action) {
196: // TODO: implement
197: return;
198: }
199:
200: protected void exportDone(final JComponent c, final Transferable t,
201: final int action) {
202: }
203:
204: private DataFlavor getPrefferedFlavor(final Transferable t,
205: final Class propertyType) {
206: DataFlavor[] flavors = t.getTransferDataFlavors();
207: DataFlavor result = null;
208: for (int i = 0; i < flavors.length; i++) {
209: result = flavors[i];
210: if (propertyType.isAssignableFrom(result
211: .getRepresentationClass())) {
212: return result;
213: }
214: }
215: return null;
216: }
217:
218: public boolean importData(final JComponent c, final Transferable t) {
219: PropertyDescriptor descriptor = getPropertyDescriptor(c);
220: if (descriptor == null) {
221: return false;
222: }
223: Class propertyType = descriptor.getPropertyType();
224: DataFlavor flavor = getPrefferedFlavor(t, propertyType);
225: if (flavor == null) {
226: return false;
227: }
228:
229: try {
230: Object value = t.getTransferData(flavor);
231: Method writer = descriptor.getWriteMethod();
232: writer.invoke(c, new Object[] { value });
233: return true;
234: } catch (UnsupportedFlavorException e) {
235: } catch (IOException e) {
236: } catch (InvocationTargetException e) {
237: } catch (IllegalAccessException e) {
238: }
239: return false;
240: }
241:
242: protected Transferable createTransferable(final JComponent c) {
243: return new Data(c);
244: }
245:
246: public boolean canImport(final JComponent c,
247: final DataFlavor[] flavors) {
248: PropertyDescriptor descriptor = getPropertyDescriptor(c);
249: if (descriptor == null || descriptor.getWriteMethod() == null
250: || flavors == null) {
251: return false;
252: }
253:
254: int length = flavors.length;
255: Class propertyType = descriptor.getPropertyType();
256: for (int i = 0; i < length; i++) {
257: DataFlavor flavor = flavors[i];
258: if (DataFlavor.javaJVMLocalObjectMimeType.equals(flavor
259: .getHumanPresentableName())
260: && propertyType.equals(flavor
261: .getRepresentationClass())) {
262: return true;
263: }
264: }
265: return false;
266: }
267:
268: public void exportToClipboard(final JComponent c,
269: final Clipboard clipboard, final int action) {
270: Transferable t = createTransferable(c);
271: if (t == null) {
272: return;
273: }
274: int actionId = action & getSourceActions(c);
275: if (actionId == NONE) {
276: exportDone(c, t, actionId);
277: return;
278: }
279: try {
280: clipboard.setContents(t, null);
281: } catch (IllegalStateException e) {
282: }
283: exportDone(c, t, actionId);
284: }
285:
286: public int getSourceActions(final JComponent c) {
287: BeanInfo beanInfo = null;
288: try {
289: beanInfo = Introspector.getBeanInfo(c.getClass());
290: } catch (IntrospectionException e) {
291: }
292:
293: PropertyDescriptor[] list = beanInfo.getPropertyDescriptors();
294: for (int i = 0; i < list.length; i++) {
295: String name = list[i].getName();
296: if (name.equals(propertyName)) {
297: return COPY;
298: }
299: }
300: return NONE;
301: }
302:
303: public static Action getPasteAction() {
304: return PASTE_ACTION;
305: }
306:
307: public static Action getCutAction() {
308: return CUT_ACTION;
309: }
310:
311: public static Action getCopyAction() {
312: return COPY_ACTION;
313: }
314: }
|