• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.eclipse.org/org/documents/epl-v10.php
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
18 
19 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
20 import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
21 
22 import org.eclipse.swt.dnd.ByteArrayTransfer;
23 import org.eclipse.swt.dnd.Transfer;
24 import org.eclipse.swt.dnd.TransferData;
25 
26 import java.io.UnsupportedEncodingException;
27 
28 /**
29  * A d'n'd {@link Transfer} class that can transfer a <em>simplified</em> XML fragment
30  * to transfer elements and their attributes between {@link LayoutCanvas}.
31  * <p/>
32  * The implementation is based on the {@link ByteArrayTransfer} and what we transfer
33  * is text with the following fixed format:
34  * <p/>
35  * <pre>
36  * {element-name element-property ...
37  *  attrib_name="attrib_value"
38  *  attrib2="..."
39  *  {...inner elements...
40  *  }
41  * }
42  * {...next element...
43  * }
44  *
45  * </pre>
46  * The format has nothing to do with XML per se, except for the fact that the
47  * transfered content represents XML elements and XML attributes.
48  *
49  * <p/>
50  * The detailed syntax is:
51  * <pre>
52  * - ELEMENT     := {NAME PROPERTY*\nATTRIB_LINE*ELEMENT*}\n
53  * - PROPERTY    := $[A-Z]=[^ ]*
54  * - NAME        := [^\n=]+
55  * - ATTRIB_LINE := @URI:NAME=[^\n]*\n
56  * </pre>
57  *
58  * Elements are represented by {@link SimpleElement}s and their attributes by
59  * {@link SimpleAttribute}s, all of which have very specific properties that are
60  * specifically limited to our needs for drag'n'drop.
61  */
62 final class SimpleXmlTransfer extends ByteArrayTransfer {
63 
64     // Reference: http://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html
65 
66     private static final String TYPE_NAME = "android.ADT.simple.xml.transfer.1";    //$NON-NLS-1$
67     private static final int TYPE_ID = registerType(TYPE_NAME);
68     private static final SimpleXmlTransfer sInstance = new SimpleXmlTransfer();
69 
70     /** Private constructor. Use {@link #getInstance()} to retrieve the singleton instance. */
SimpleXmlTransfer()71     private SimpleXmlTransfer() {
72         // pass
73     }
74 
75     /** Returns the singleton instance. */
getInstance()76     public static SimpleXmlTransfer getInstance() {
77         return sInstance;
78     }
79 
80     /**
81      * Helper method that returns the FQCN transfered for the given {@link ElementDescriptor}.
82      * <p/>
83      * If the descriptor is a {@link ViewElementDescriptor}, the transfered data is the FQCN
84      * of the Android View class represented (e.g. "android.widget.Button").
85      * For any other non-null descriptor, the XML name is used.
86      * Otherwise it is null.
87      *
88      * @param desc The {@link ElementDescriptor} to transfer.
89      * @return The FQCN, XML name or null.
90      */
getFqcn(ElementDescriptor desc)91     public static String getFqcn(ElementDescriptor desc) {
92         if (desc instanceof ViewElementDescriptor) {
93             return ((ViewElementDescriptor) desc).getFullClassName();
94         } else if (desc != null) {
95             return desc.getXmlName();
96         }
97 
98         return null;
99     }
100 
101     @Override
getTypeIds()102     protected int[] getTypeIds() {
103         return new int[] { TYPE_ID };
104     }
105 
106     @Override
getTypeNames()107     protected String[] getTypeNames() {
108         return new String[] { TYPE_NAME };
109     }
110 
111     /** Transforms a array of {@link SimpleElement} into a native data transfer. */
112     @Override
javaToNative(Object object, TransferData transferData)113     protected void javaToNative(Object object, TransferData transferData) {
114         if (object == null || !(object instanceof SimpleElement[])) {
115             return;
116         }
117 
118         if (isSupportedType(transferData)) {
119             StringBuilder sb = new StringBuilder();
120             for (SimpleElement e : (SimpleElement[]) object) {
121                 sb.append(e.toString());
122             }
123             String data = sb.toString();
124 
125             try {
126                 byte[] buf = data.getBytes("UTF-8");  //$NON-NLS-1$
127                 super.javaToNative(buf, transferData);
128             } catch (UnsupportedEncodingException e) {
129                 // unlikely; ignore
130             }
131         }
132     }
133 
134     /**
135      * Recreates an array of {@link SimpleElement} from a native data transfer.
136      *
137      * @return An array of {@link SimpleElement} or null. The array may be empty.
138      */
139     @Override
nativeToJava(TransferData transferData)140     protected Object nativeToJava(TransferData transferData) {
141         if (isSupportedType(transferData)) {
142             byte[] buf = (byte[]) super.nativeToJava(transferData);
143             if (buf != null && buf.length > 0) {
144                 try {
145                     String s = new String(buf, "UTF-8"); //$NON-NLS-1$
146                     return SimpleElement.parseString(s);
147                 } catch (UnsupportedEncodingException e) {
148                     // unlikely to happen, but still possible
149                 }
150             }
151         }
152 
153         return null;
154     }
155 }
156