Home | History | Annotate | Download | only in gle2
      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.TransferData;
     24 
     25 import java.io.UnsupportedEncodingException;
     26 
     27 /**
     28  * A d'n'd {@link Transfer} class that can transfer a <em>simplified</em> XML fragment
     29  * to transfer elements and their attributes between {@link LayoutCanvas}.
     30  * <p/>
     31  * The implementation is based on the {@link ByteArrayTransfer} and what we transfer
     32  * is text with the following fixed format:
     33  * <p/>
     34  * <pre>
     35  * {element-name element-property ...
     36  *  attrib_name="attrib_value"
     37  *  attrib2="..."
     38  *  {...inner elements...
     39  *  }
     40  * }
     41  * {...next element...
     42  * }
     43  *
     44  * </pre>
     45  * The format has nothing to do with XML per se, except for the fact that the
     46  * transfered content represents XML elements and XML attributes.
     47  *
     48  * <p/>
     49  * The detailed syntax is:
     50  * <pre>
     51  * - ELEMENT     := {NAME PROPERTY*\nATTRIB_LINE*ELEMENT*}\n
     52  * - PROPERTY    := $[A-Z]=[^ ]*
     53  * - NAME        := [^\n=]+
     54  * - ATTRIB_LINE := @URI:NAME=[^\n]*\n
     55  * </pre>
     56  *
     57  * Elements are represented by {@link SimpleElement}s and their attributes by
     58  * {@link SimpleAttribute}s, all of which have very specific properties that are
     59  * specifically limited to our needs for drag'n'drop.
     60  */
     61 final class SimpleXmlTransfer extends ByteArrayTransfer {
     62 
     63     // Reference: http://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html
     64 
     65     private static final String TYPE_NAME = "android.ADT.simple.xml.transfer.1";    //$NON-NLS-1$
     66     private static final int TYPE_ID = registerType(TYPE_NAME);
     67     private static final SimpleXmlTransfer sInstance = new SimpleXmlTransfer();
     68 
     69     /** Private constructor. Use {@link #getInstance()} to retrieve the singleton instance. */
     70     private SimpleXmlTransfer() {
     71         // pass
     72     }
     73 
     74     /** Returns the singleton instance. */
     75     public static SimpleXmlTransfer getInstance() {
     76         return sInstance;
     77     }
     78 
     79     /**
     80      * Helper method that returns the FQCN transfered for the given {@link ElementDescriptor}.
     81      * <p/>
     82      * If the descriptor is a {@link ViewElementDescriptor}, the transfered data is the FQCN
     83      * of the Android View class represented (e.g. "android.widget.Button").
     84      * For any other non-null descriptor, the XML name is used.
     85      * Otherwise it is null.
     86      *
     87      * @param desc The {@link ElementDescriptor} to transfer.
     88      * @return The FQCN, XML name or null.
     89      */
     90     public static String getFqcn(ElementDescriptor desc) {
     91         if (desc instanceof ViewElementDescriptor) {
     92             return ((ViewElementDescriptor) desc).getFullClassName();
     93         } else if (desc != null) {
     94             return desc.getXmlName();
     95         }
     96 
     97         return null;
     98     }
     99 
    100     @Override
    101     protected int[] getTypeIds() {
    102         return new int[] { TYPE_ID };
    103     }
    104 
    105     @Override
    106     protected String[] getTypeNames() {
    107         return new String[] { TYPE_NAME };
    108     }
    109 
    110     /** Transforms a array of {@link SimpleElement} into a native data transfer. */
    111     @Override
    112     protected void javaToNative(Object object, TransferData transferData) {
    113         if (object == null || !(object instanceof SimpleElement[])) {
    114             return;
    115         }
    116 
    117         if (isSupportedType(transferData)) {
    118             StringBuilder sb = new StringBuilder();
    119             for (SimpleElement e : (SimpleElement[]) object) {
    120                 sb.append(e.toString());
    121             }
    122             String data = sb.toString();
    123 
    124             try {
    125                 byte[] buf = data.getBytes("UTF-8");  //$NON-NLS-1$
    126                 super.javaToNative(buf, transferData);
    127             } catch (UnsupportedEncodingException e) {
    128                 // unlikely; ignore
    129             }
    130         }
    131     }
    132 
    133     /**
    134      * Recreates an array of {@link SimpleElement} from a native data transfer.
    135      *
    136      * @return An array of {@link SimpleElement} or null. The array may be empty.
    137      */
    138     @Override
    139     protected Object nativeToJava(TransferData transferData) {
    140         if (isSupportedType(transferData)) {
    141             byte[] buf = (byte[]) super.nativeToJava(transferData);
    142             if (buf != null && buf.length > 0) {
    143                 try {
    144                     String s = new String(buf, "UTF-8"); //$NON-NLS-1$
    145                     return SimpleElement.parseString(s);
    146                 } catch (UnsupportedEncodingException e) {
    147                     // unlikely to happen, but still possible
    148                 }
    149             }
    150         }
    151 
    152         return null;
    153     }
    154 }
    155