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. */ SimpleXmlTransfer()70 private SimpleXmlTransfer() { 71 // pass 72 } 73 74 /** Returns the singleton instance. */ getInstance()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 */ getFqcn(ElementDescriptor desc)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 getTypeIds()101 protected int[] getTypeIds() { 102 return new int[] { TYPE_ID }; 103 } 104 105 @Override getTypeNames()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 javaToNative(Object object, TransferData transferData)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 nativeToJava(TransferData transferData)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