OSDN Git Service

ADT GLE2: paste element in empty layout.
authorRaphael Moll <ralf@android.com>
Thu, 22 Jul 2010 18:48:09 +0000 (14:48 -0400)
committerRaphael Moll <ralf@android.com>
Thu, 22 Jul 2010 21:23:30 +0000 (17:23 -0400)
Change-Id: I792947e39d4b0ef7828f2df394bac81c0da37970

eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java

index 5a4761d..0659d2d 100755 (executable)
@@ -110,8 +110,6 @@ import java.util.Map;
  *
  * TODO List:
  * - display error icon
- * - finish palette (see palette's todo list)
- * - finish canvas (see canvas' todo list)
  * - completly rethink the property panel
  */
 public class GraphicalEditorPart extends EditorPart
index e8a6dd4..c724207 100755 (executable)
 package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.editors.layout.gscripts.IDragElement;
 import com.android.ide.eclipse.adt.editors.layout.gscripts.INode;
 import com.android.ide.eclipse.adt.editors.layout.gscripts.Point;
 import com.android.ide.eclipse.adt.editors.layout.gscripts.Rect;
+import com.android.ide.eclipse.adt.editors.layout.gscripts.IDragElement.IDragAttribute;
 import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
 import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
@@ -134,9 +136,7 @@ import java.util.Set;
  * TODO list:
  * - gray on error, keep select but disable d'n'd.
  * - context menu handling of layout + local props (via IViewRules)
- * - handle empty root:
- *    - Must also be able to copy/paste into an empty document (prolly need to bypass script, and deal with the xmlns)
- *    - We must be able to move/copy/cut the top root element (mostly between documents).
+ * - properly handle custom views
  */
 class LayoutCanvas extends Canvas implements ISelectionProvider {
 
@@ -1471,7 +1471,6 @@ class LayoutCanvas extends Canvas implements ISelectionProvider {
             if (e.detail == DND.DROP_MOVE) {
                 // Remove from source. Since we know the selection, we'll simply
                 // create a cut operation on the existing drag selection.
-                AdtPlugin.printToConsole("CanvasDND", "dragFinished => MOVE");
 
                 // Create an undo wrapper, which takes a runnable
                 mLayoutEditor.wrapUndoRecording(
@@ -2008,9 +2007,114 @@ class LayoutCanvas extends Canvas implements ISelectionProvider {
         getRulesEngine().callOnPaste(targetNode, pasted);
     }
 
-    private void pasteInEmptyDocument(SimpleElement simpleElement) {
-        // TODO Auto-generated method stub
+    /**
+     * Paste a new root into an empty XML layout.
+     * <p/>
+     * In case of error (unknown FQCN, document not empty), silently do nothing.
+     * In case of success, the new element will have some default attributes set (xmlns:android,
+     * layout_width and height). The edit is wrapped in a proper undo.
+     * <p/>
+     * Implementation is similar to {@link #createDocumentRoot(String)} except we also
+     * copy all the attributes and inner elements recursively.
+     */
+    private void pasteInEmptyDocument(final IDragElement pastedElement) {
+        String rootFqcn = pastedElement.getFqcn();
+
+        // Need a valid empty document to create the new root
+        final UiDocumentNode uiDoc = mLayoutEditor.getUiRootNode();
+        if (uiDoc == null || uiDoc.getUiChildren().size() > 0) {
+            debugPrintf("Failed to paste document root for %1$s: document is not empty", rootFqcn);
+            return;
+        }
+
+        // Find the view descriptor matching our FQCN
+        final ViewElementDescriptor viewDesc = mLayoutEditor.getFqcnViewDescritor(rootFqcn);
+        if (viewDesc == null) {
+            // TODO this could happen if pasting a custom view not known in this project
+            debugPrintf("Failed to paste document root, unknown FQCN %1$s", rootFqcn);
+            return;
+        }
+
+        // Get the last segment of the FQCN for the undo title
+        String title = rootFqcn;
+        int pos = title.lastIndexOf('.');
+        if (pos > 0 && pos < title.length() - 1) {
+            title = title.substring(pos + 1);
+        }
+        title = String.format("Paste root %1$s in document", title);
+
+        mLayoutEditor.wrapUndoRecording(title, new Runnable() {
+            public void run() {
+                mLayoutEditor.editXmlModel(new Runnable() {
+                    public void run() {
+                        UiElementNode uiNew = uiDoc.appendNewUiChild(viewDesc);
+
+                        // A root node requires the Android XMLNS
+                        uiNew.setAttributeValue(
+                                "android",
+                                XmlnsAttributeDescriptor.XMLNS_URI,
+                                SdkConstants.NS_RESOURCES,
+                                true /*override*/);
 
+                        // Copy all the attributes from the pasted element
+                        for (IDragAttribute attr : pastedElement.getAttributes()) {
+                            uiNew.setAttributeValue(
+                                    attr.getName(),
+                                    attr.getUri(),
+                                    attr.getValue(),
+                                    true /*override*/);
+                        }
+
+                        // Adjust the attributes, adding the default layout_width/height
+                        // only if they are not present (the original element should have
+                        // them though.)
+                        DescriptorsUtils.setDefaultLayoutAttributes(uiNew, false /*updateLayout*/);
+
+                        uiNew.createXmlNode();
+
+                        // Now process all children
+                        for (IDragElement childElement : pastedElement.getInnerElements()) {
+                            addChild(uiNew, childElement);
+                        }
+                    }
+
+                    private void addChild(UiElementNode uiParent, IDragElement childElement) {
+                        String childFqcn = childElement.getFqcn();
+                        final ViewElementDescriptor childDesc =
+                            mLayoutEditor.getFqcnViewDescritor(childFqcn);
+                        if (childDesc == null) {
+                            // TODO this could happen if pasting a custom view
+                            debugPrintf("Failed to paste element, unknown FQCN %1$s", childFqcn);
+                            return;
+                        }
+
+                        UiElementNode uiChild = uiParent.appendNewUiChild(childDesc);
+
+                        // Copy all the attributes from the pasted element
+                        for (IDragAttribute attr : childElement.getAttributes()) {
+                            uiChild.setAttributeValue(
+                                    attr.getName(),
+                                    attr.getUri(),
+                                    attr.getValue(),
+                                    true /*override*/);
+                        }
+
+                        // Adjust the attributes, adding the default layout_width/height
+                        // only if they are not present (the original element should have
+                        // them though.)
+                        DescriptorsUtils.setDefaultLayoutAttributes(
+                                uiChild, false /*updateLayout*/);
+
+                        uiChild.createXmlNode();
+
+                        // Now process all grand children
+                        for (IDragElement grandChildElement : childElement.getInnerElements()) {
+                            addChild(uiChild, grandChildElement);
+                        }
+                    }
+                });
+            }
+        });
     }
 
     /**
@@ -2030,12 +2134,15 @@ class LayoutCanvas extends Canvas implements ISelectionProvider {
         // Need a valid empty document to create the new root
         final UiDocumentNode uiDoc = mLayoutEditor.getUiRootNode();
         if (uiDoc == null || uiDoc.getUiChildren().size() > 0) {
+            debugPrintf("Failed to create document root for %1$s: document is not empty", rootFqcn);
             return;
         }
 
         // Find the view descriptor matching our FQCN
         final ViewElementDescriptor viewDesc = mLayoutEditor.getFqcnViewDescritor(rootFqcn);
         if (viewDesc == null) {
+            // TODO this could happen if dropping a custom view not known in this project
+            debugPrintf("Failed to add document root, unknown FQCN %1$s", rootFqcn);
             return;
         }
 
@@ -2069,4 +2176,8 @@ class LayoutCanvas extends Canvas implements ISelectionProvider {
             }
         });
     }
+
+    private void debugPrintf(String message, Object... params) {
+        AdtPlugin.printToConsole("Canvas", String.format(message, params));
+    }
 }