/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Eclipse Public License, Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.eclipse.org/org/documents/epl-v10.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.ide.eclipse.adt.internal.editors.layout.gle2; import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; import org.eclipse.swt.dnd.ByteArrayTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.dnd.TransferData; import java.io.UnsupportedEncodingException; /** * A d'n'd {@link Transfer} class that can transfer a <em>simplified</em> XML fragment * to transfer elements and their attributes between {@link LayoutCanvas}. * <p/> * The implementation is based on the {@link ByteArrayTransfer} and what we transfer * is text with the following fixed format: * <p/> * <pre> * {element-name element-property ... * attrib_name="attrib_value" * attrib2="..." * {...inner elements... * } * } * {...next element... * } * * </pre> * The format has nothing to do with XML per se, except for the fact that the * transfered content represents XML elements and XML attributes. * * <p/> * The detailed syntax is: * <pre> * - ELEMENT := {NAME PROPERTY*\nATTRIB_LINE*ELEMENT*}\n * - PROPERTY := $[A-Z]=[^ ]* * - NAME := [^\n=]+ * - ATTRIB_LINE := @URI:NAME=[^\n]*\n * </pre> * * Elements are represented by {@link SimpleElement}s and their attributes by * {@link SimpleAttribute}s, all of which have very specific properties that are * specifically limited to our needs for drag'n'drop. */ final class SimpleXmlTransfer extends ByteArrayTransfer { // Reference: http://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html private static final String TYPE_NAME = "android.ADT.simple.xml.transfer.1"; //$NON-NLS-1$ private static final int TYPE_ID = registerType(TYPE_NAME); private static final SimpleXmlTransfer sInstance = new SimpleXmlTransfer(); /** Private constructor. Use {@link #getInstance()} to retrieve the singleton instance. */ private SimpleXmlTransfer() { // pass } /** Returns the singleton instance. */ public static SimpleXmlTransfer getInstance() { return sInstance; } /** * Helper method that returns the FQCN transfered for the given {@link ElementDescriptor}. * <p/> * If the descriptor is a {@link ViewElementDescriptor}, the transfered data is the FQCN * of the Android View class represented (e.g. "android.widget.Button"). * For any other non-null descriptor, the XML name is used. * Otherwise it is null. * * @param desc The {@link ElementDescriptor} to transfer. * @return The FQCN, XML name or null. */ public static String getFqcn(ElementDescriptor desc) { if (desc instanceof ViewElementDescriptor) { return ((ViewElementDescriptor) desc).getFullClassName(); } else if (desc != null) { return desc.getXmlName(); } return null; } @Override protected int[] getTypeIds() { return new int[] { TYPE_ID }; } @Override protected String[] getTypeNames() { return new String[] { TYPE_NAME }; } /** Transforms a array of {@link SimpleElement} into a native data transfer. */ @Override protected void javaToNative(Object object, TransferData transferData) { if (object == null || !(object instanceof SimpleElement[])) { return; } if (isSupportedType(transferData)) { StringBuilder sb = new StringBuilder(); for (SimpleElement e : (SimpleElement[]) object) { sb.append(e.toString()); } String data = sb.toString(); try { byte[] buf = data.getBytes("UTF-8"); //$NON-NLS-1$ super.javaToNative(buf, transferData); } catch (UnsupportedEncodingException e) { // unlikely; ignore } } } /** * Recreates an array of {@link SimpleElement} from a native data transfer. * * @return An array of {@link SimpleElement} or null. The array may be empty. */ @Override protected Object nativeToJava(TransferData transferData) { if (isSupportedType(transferData)) { byte[] buf = (byte[]) super.nativeToJava(transferData); if (buf != null && buf.length > 0) { try { String s = new String(buf, "UTF-8"); //$NON-NLS-1$ return SimpleElement.parseString(s); } catch (UnsupportedEncodingException e) { // unlikely to happen, but still possible } } } return null; } }