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