Code drop from //branches/cupcake/...@124589
diff --git a/tools/eclipse/buildConfig/allElements.xml b/tools/eclipse/buildConfig/allElements.xml
index 79f06df..99ab3aa 100644
--- a/tools/eclipse/buildConfig/allElements.xml
+++ b/tools/eclipse/buildConfig/allElements.xml
@@ -19,11 +19,6 @@
              <property name="id" value="com.android.ide.eclipse.adt" />
          </ant>
          
-        <ant antfile="${genericTargets}" target="${target}">
-            <property name="type" value="feature" />
-            <property name="id" value="com.android.ide.eclipse.editors" />
-        </ant>
-         
         <antcall target="buildInternalFeatures"/>
          
      </target>
@@ -35,15 +30,10 @@
      <target name="buildInternalFeatures" if="internalSite">
         <ant antfile="${genericTargets}" target="${target}">
             <property name="type" value="feature" />
-            <property name="id" value="com.android.ide.eclipse.platform" />
-        </ant>
-        <ant antfile="${genericTargets}" target="${target}">
-            <property name="type" value="feature" />
             <property name="id" value="com.android.ide.eclipse.tests" />
         </ant>
      </target>    
          
- 
      <!-- ===================================================================== -->
      <!-- Targets to assemble the built elements for particular configurations  -->
      <!-- These generally call the generated assemble scripts (named in         -->
@@ -55,14 +45,6 @@
          <ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
      </target>
     
-    <target name="assemble.com.android.ide.eclipse.editors">
-        <ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
-    </target>
-    
-    <target name="assemble.com.android.ide.eclipse.platform">
-        <ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
-    </target>
-    
     <target name="assemble.com.android.ide.eclipse.tests">
         <ant antfile="${assembleScriptName}" dir="${buildDirectory}"/>
     </target>
diff --git a/tools/eclipse/changes.txt b/tools/eclipse/changes.txt
index bbe26de..5cb8245 100644
--- a/tools/eclipse/changes.txt
+++ b/tools/eclipse/changes.txt
@@ -1,3 +1,6 @@
+0.9.0 (work in progress)
+- Support for SDK with multiple versions of the Android platform and vendor supplied add-ons.
+
 0.8.1:
 
 - Alternate Layout wizard. In the layout editor, the "create" button is now enabled, and allows to easily create alternate versions.
@@ -5,6 +8,8 @@
 - Export Wizard: To export an application for release, sign with a non debug key. Accessible from the export menu, from the Android Tools contextual menu, or from the overview page of the manifest editor.
 - New XML File Wizard: To easily create new XML resources file in the /res directory.
 - New checks on launch when attempting to debug on a device.
+- Basic support for drag'n'drop in Graphical layout editor. You can add new items by drag'n'drop from the palette. There's is no support for moving/resizing yet.
+- Undo/redo support in all XML form editors and Graphical layout editor.
 
 0.8.0:
 
diff --git a/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml b/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml
index f8356b0..191b76d 100644
--- a/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml
+++ b/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="com.android.ide.eclipse.adt"
       label="Android Development Tools"
-      version="0.8.1.qualifier"
+      version="0.9.0.qualifier"
       provider-name="The Android Open Source Project"
       plugin="com.android.ide.eclipse.adt">
 
@@ -14,37 +14,35 @@
       Copyright (C) 2007 The Android Open Source Project
    </copyright>
 
+   <license>
+      License TBD.
+   </license>
+
    <url>
       <update label="Android Update Site" url="https://dl-ssl.google.com/android/eclipse/"/>
    </url>
 
    <requires>
-      <import plugin="org.eclipse.core.resources"/>
       <import plugin="org.eclipse.core.runtime"/>
-      <import plugin="org.eclipse.jdt.core"/>
-      <import plugin="org.eclipse.ui.console"/>
-      <import plugin="org.eclipse.ui"/>
-      <import plugin="org.eclipse.jdt.ui"/>
-      <import plugin="org.eclipse.jface.text"/>
-      <import plugin="org.eclipse.ui.editors"/>
+      <import plugin="org.eclipse.core.resources"/>
       <import plugin="org.eclipse.debug.core"/>
       <import plugin="org.eclipse.debug.ui"/>
       <import plugin="org.eclipse.jdt"/>
       <import plugin="org.eclipse.ant.core"/>
+      <import plugin="org.eclipse.jdt.core"/>
+      <import plugin="org.eclipse.jdt.ui"/>
       <import plugin="org.eclipse.jdt.launching"/>
+      <import plugin="org.eclipse.jface.text"/>
+      <import plugin="org.eclipse.ui.editors"/>
       <import plugin="org.eclipse.ui.workbench.texteditor"/>
+      <import plugin="org.eclipse.ui.console"/>
       <import plugin="org.eclipse.core.filesystem"/>
+      <import plugin="org.eclipse.ui"/>
       <import plugin="org.eclipse.ui.ide"/>
+      <import plugin="org.eclipse.ui.forms"/>
    </requires>
 
    <plugin
-         id="com.android.ide.eclipse.common"
-         download-size="0"
-         install-size="0"
-         version="0.0.0"
-         unpack="false"/>
-
-   <plugin
          id="com.android.ide.eclipse.adt"
          download-size="0"
          install-size="0"
diff --git a/tools/eclipse/features/com.android.ide.eclipse.editors/.project b/tools/eclipse/features/com.android.ide.eclipse.editors/.project
deleted file mode 100644
index a960976..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.editors/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>editors-feature</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.pde.FeatureBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.pde.FeatureNature</nature>
-	</natures>
-</projectDescription>
diff --git a/tools/eclipse/features/com.android.ide.eclipse.editors/build.properties b/tools/eclipse/features/com.android.ide.eclipse.editors/build.properties
deleted file mode 100644
index 64f93a9..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.editors/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-bin.includes = feature.xml
diff --git a/tools/eclipse/features/com.android.ide.eclipse.editors/feature.xml b/tools/eclipse/features/com.android.ide.eclipse.editors/feature.xml
deleted file mode 100644
index f5f92e8..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.editors/feature.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<feature
-      id="com.android.ide.eclipse.editors"
-      label="Android Editors"
-      version="0.8.1.qualifier"
-      provider-name="The Android Open Source Project"
-      plugin="com.android.ide.eclipse.editors">
-
-   <description>
-      This feature provides Editors for Android files.
-   </description>
-
-   <copyright>
-      Copyright (C) 2007 The Android Open Source Project
-   </copyright>
-
-   <url>
-      <update label="Android Update Site" url="https://dl-ssl.google.com/android/eclipse/"/>
-   </url>
-
-   <requires>
-      <import plugin="com.android.ide.eclipse.common"/>
-      <import plugin="org.eclipse.ui"/>
-      <import plugin="org.eclipse.core.runtime"/>
-      <import plugin="org.eclipse.core.resources"/>
-      <import plugin="org.eclipse.ui.editors"/>
-      <import plugin="org.eclipse.jface.text"/>
-      <import plugin="org.eclipse.ui.ide"/>
-      <import plugin="org.eclipse.wst.sse.ui"/>
-      <import plugin="org.eclipse.wst.xml.ui"/>
-      <import plugin="org.eclipse.wst.xml.core"/>
-      <import plugin="org.eclipse.wst.sse.core"/>
-      <import plugin="org.eclipse.ui.forms"/>
-      <import plugin="org.eclipse.jdt.core"/>
-      <import plugin="org.eclipse.ui.browser"/>
-      <import plugin="org.eclipse.jdt.ui"/>
-      <import plugin="org.eclipse.gef"/>
-      <import plugin="org.eclipse.ui.views"/>
-      <import plugin="org.eclipse.ui.console"/>
-   </requires>
-
-   <plugin
-         id="com.android.ide.eclipse.editors"
-         download-size="0"
-         install-size="0"
-         version="0.0.0"
-         unpack="false"/>
-
-</feature>
diff --git a/tools/eclipse/features/com.android.ide.eclipse.platform/.project b/tools/eclipse/features/com.android.ide.eclipse.platform/.project
deleted file mode 100644
index 0bb8c34..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.platform/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>platform-feature</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.pde.FeatureBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.pde.FeatureNature</nature>
-	</natures>
-</projectDescription>
diff --git a/tools/eclipse/features/com.android.ide.eclipse.platform/build.properties b/tools/eclipse/features/com.android.ide.eclipse.platform/build.properties
deleted file mode 100644
index 64f93a9..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.platform/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-bin.includes = feature.xml
diff --git a/tools/eclipse/features/com.android.ide.eclipse.platform/feature.xml b/tools/eclipse/features/com.android.ide.eclipse.platform/feature.xml
deleted file mode 100644
index aa4b166..0000000
--- a/tools/eclipse/features/com.android.ide.eclipse.platform/feature.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<feature
-      id="com.android.ide.eclipse.platform"
-      label="Android Platform Tools"
-      version="0.8.1.qualifier"
-      provider-name="The Android Open Source Project">
-
-   <description>
-      This feature provides a ddms perspective and editor functionnality for Android.
-   </description>
-
-   <copyright>
-      Copyright (C) 2007 The Android Open Source Project
-   </copyright>
-
-   <url>
-      <update label="Android Update Site" url="https://android.corp.google.com/adt/"/>
-   </url>
-
-   <requires>
-      <import plugin="org.eclipse.core.resources"/>
-      <import plugin="org.eclipse.core.runtime"/>
-      <import plugin="org.eclipse.jdt.core"/>
-      <import plugin="org.eclipse.ui.console"/>
-      <import plugin="org.eclipse.ui"/>
-      <import plugin="org.eclipse.jdt.ui"/>
-      <import plugin="org.eclipse.jface.text"/>
-      <import plugin="org.eclipse.ui.editors"/>
-   </requires>
-
-   <plugin
-         id="com.android.ide.eclipse.common"
-         download-size="0"
-         install-size="0"
-         version="0.0.0"
-         unpack="false"/>
-
-   <plugin
-         id="com.android.ide.eclipse.platform"
-         download-size="0"
-         install-size="0"
-         version="0.0.0"
-         unpack="false"/>
-
-   <plugin
-         id="com.android.ide.eclipse.ddms"
-         download-size="0"
-         install-size="0"
-         version="0.0.0"
-         unpack="false"/>
-
-</feature>
diff --git a/tools/eclipse/features/com.android.ide.eclipse.tests/feature.xml b/tools/eclipse/features/com.android.ide.eclipse.tests/feature.xml
index b5a848c..2a3a74f 100644
--- a/tools/eclipse/features/com.android.ide.eclipse.tests/feature.xml
+++ b/tools/eclipse/features/com.android.ide.eclipse.tests/feature.xml
@@ -2,11 +2,11 @@
 <feature
       id="com.android.ide.eclipse.tests"
       label="ADT Tests"
-      version="0.8.1.qualifier"
+      version="0.9.0.qualifier"
       provider-name="The Android Open Source Project">
 
-  <copyright>
-         Copyright (C) 2007 The Android Open Source Project
+   <copyright>
+      Copyright (C) 2007 The Android Open Source Project
    </copyright>
 
    <requires>
@@ -15,8 +15,6 @@
       <import plugin="org.eclipse.core.resources"/>
       <import plugin="com.android.ide.eclipse.adt"/>
       <import plugin="org.junit"/>
-      <import plugin="com.android.ide.eclipse.common"/>
-      <import plugin="com.android.ide.eclipse.editors"/>
       <import plugin="org.eclipse.jdt.core"/>
       <import plugin="org.eclipse.jdt.launching"/>
       <import plugin="org.eclipse.ui.views"/>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath b/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
index 4dd4cac..bbcdff9 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
@@ -5,5 +5,12 @@
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="lib" path="jarutils.jar"/>
 	<classpathentry kind="lib" path="androidprefs.jar"/>
+	<classpathentry kind="lib" path="sdkstats.jar"/>
+	<classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
+	<classpathentry kind="lib" path="layoutlib_api.jar"/>
+	<classpathentry kind="lib" path="layoutlib_utils.jar"/>
+	<classpathentry kind="lib" path="ninepatch.jar"/>
+	<classpathentry kind="lib" path="sdklib.jar"/>
+	<classpathentry kind="lib" path="sdkuilib.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index 9926074..a464d5c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
@@ -2,14 +2,20 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Android Development Toolkit
 Bundle-SymbolicName: com.android.ide.eclipse.adt;singleton:=true
-Bundle-Version: 0.8.1.qualifier
+Bundle-Version: 0.9.0.qualifier
 Bundle-ClassPath: .,
  jarutils.jar,
- androidprefs.jar
+ androidprefs.jar,
+ sdkstats.jar,
+ kxml2-2.3.0.jar,
+ layoutlib_api.jar,
+ ninepatch.jar,
+ layoutlib_utils.jar,
+ sdklib.jar,
+ sdkuilib.jar
 Bundle-Activator: com.android.ide.eclipse.adt.AdtPlugin
 Bundle-Vendor: The Android Open Source Project
-Require-Bundle: com.android.ide.eclipse.common,
- com.android.ide.eclipse.ddms,
+Require-Bundle: com.android.ide.eclipse.ddms,
  org.eclipse.core.runtime,
  org.eclipse.core.resources,
  org.eclipse.debug.core,
@@ -26,11 +32,48 @@
  org.eclipse.core.filesystem,
  org.eclipse.ui,
  org.eclipse.ui.ide,
- org.eclipse.ui.forms
+ org.eclipse.ui.forms,
+ org.eclipse.gef,
+ org.eclipse.ui.browser,
+ org.eclipse.ui.views,
+ org.eclipse.wst.sse.core,
+ org.eclipse.wst.sse.ui,
+ org.eclipse.wst.xml.core,
+ org.eclipse.wst.xml.ui
 Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.adt.build;x-friends:="com.android.ide.eclipse.tests",
+Export-Package: com.android.ide.eclipse.adt,
+ com.android.ide.eclipse.adt.build;x-friends:="com.android.ide.eclipse.tests",
  com.android.ide.eclipse.adt.project;x-friends:="com.android.ide.eclipse.tests",
  com.android.ide.eclipse.adt.project.internal;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.adt.resources;x-friends:="com.android.ide.eclipse.tests"
+ com.android.ide.eclipse.adt.sdk;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.adt.wizards.newproject;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.common,
+ com.android.ide.eclipse.common.project,
+ com.android.ide.eclipse.common.resources,
+ com.android.ide.eclipse.editors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout.parts;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.layout.uimodel;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest.model;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.manifest.pages;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.menu;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.menu.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.configurations;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.descriptors;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.explorer;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.manager;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.manager.files;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.resources.uimodel;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.ui;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.ui.tree;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.uimodel;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.wizards;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.xml;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.editors.xml.descriptors;x-friends:="com.android.ide.eclipse.tests"
 
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/build.properties b/tools/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
index 6d6c2e8..c7eb749 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
@@ -5,6 +5,13 @@
                templates/,\
                about.ini,\
                jarutils.jar,\
-               androidprefs.jar
+               androidprefs.jar,\
+               sdkstats.jar,\
+               kxml2-2.3.0.jar,\
+               layoutlib_api.jar,\
+               layoutlib_utils.jar,\
+               ninepatch.jar,\
+               sdklib.jar,\
+               sdkuilib.jar
 source.. = src/
 output.. = bin/
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/add.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/add.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/add.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/az_sort.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/az_sort.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/az_sort.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/delete.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/delete.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/delete.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/dimension.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/dimension.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/dimension.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/down.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/down.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/down.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/dpi.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/dpi.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/dpi.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/error.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/error.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/error.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/keyboard.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/keyboard.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/keyboard.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/language.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/language.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/language.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/match.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/match.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/match.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.png
new file mode 100644
index 0000000..4dc95d7
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mcc.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mnc.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/mnc.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/mnc.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/navpad.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/navpad.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/navpad.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/orientation.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/orientation.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/orientation.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/region.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/region.png
new file mode 100644
index 0000000..9608cd6
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/region.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/text_input.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/text_input.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/text_input.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/touch.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/touch.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/touch.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/up.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/up.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/up.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/warning.png
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/warning.png
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/icons/warning.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index 51b1291..ade4646 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -2,6 +2,38 @@
 <?eclipse version="3.2"?>
 <plugin>
    <extension
+         id="com.android.ide.eclipse.common.xmlProblem"
+         name="Android XML Format Problem"
+         point="org.eclipse.core.resources.markers">
+      <super type="org.eclipse.core.resources.problemmarker"/>
+      <super type="org.eclipse.core.resources.textmarker"/>
+      <persistent value="true"/>
+   </extension>
+   <extension
+         id="com.android.ide.eclipse.common.aaptProblem"
+         name="Android AAPT Problem"
+         point="org.eclipse.core.resources.markers">
+      <super type="org.eclipse.core.resources.problemmarker"/>
+      <super type="org.eclipse.core.resources.textmarker"/>
+      <persistent value="true"/>
+   </extension>
+   <extension
+         id="com.android.ide.eclipse.common.aidlProblem"
+         name="Android AIDL Problem"
+         point="org.eclipse.core.resources.markers">
+      <super type="org.eclipse.core.resources.problemmarker"/>
+      <super type="org.eclipse.core.resources.textmarker"/>
+      <persistent value="true"/>
+   </extension>
+   <extension
+        id="com.android.ide.eclipse.common.androidProblem"
+        name="Android XML Content Problem"
+        point="org.eclipse.core.resources.markers">
+      <super type="org.eclipse.core.resources.problemmarker"/>
+      <super type="org.eclipse.core.resources.textmarker"/>
+      <persistent value="true"/>
+   </extension>
+   <extension
          id="ResourceManagerBuilder"
          name="Android Resource Manager"
          point="org.eclipse.core.resources.builders">
@@ -47,7 +79,7 @@
       <wizard
             canFinishEarly="false"
             category="com.android.ide.eclipse.wizards.category"
-            class="com.android.ide.eclipse.adt.project.internal.NewProjectWizard"
+            class="com.android.ide.eclipse.adt.wizards.newproject.NewProjectWizard"
             finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
             hasPages="true"
             icon="icons/android.png"
@@ -55,6 +87,18 @@
             name="Android Project"
             preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective"
             project="true"/>
+      <wizard
+            canFinishEarly="false"
+            category="com.android.ide.eclipse.wizards.category"
+            class="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
+            finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
+            hasPages="true"
+            icon="icons/android.png"
+            id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
+            name="Android XML File"
+            preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective"
+            project="false">
+      </wizard>
    </extension>
    <extension
          point="org.eclipse.debug.core.launchConfigurationTypes">
@@ -174,6 +218,13 @@
                label="Create Aidl preprocess file for Parcelable classes"
                menubarPath="com.android.ide.eclipse.adt.AndroidTools/group1"/>
          <action
+               class="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
+               enablesFor="1"
+               id="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
+               label="New Resource File..."
+               menubarPath="com.android.ide.eclipse.adt.AndroidTools/group1">
+         </action>
+         <action
                class="com.android.ide.eclipse.adt.project.ExportAction"
                enablesFor="1"
                id="com.android.ide.eclipse.adt.project.ExportAction"
@@ -183,7 +234,7 @@
                class="com.android.ide.eclipse.adt.project.ExportWizardAction"
                enablesFor="1"
                id="com.android.ide.eclipse.adt.project.ExportWizardAction"
-               label="Export Application..."
+               label="Export Signed Application Package..."
                menubarPath="com.android.ide.eclipse.adt.AndroidTools/group2"/>
          <action
                class="com.android.ide.eclipse.adt.project.FixProjectAction"
@@ -209,30 +260,32 @@
             class="com.android.ide.eclipse.adt.preferences.LaunchPreferencePage"
             id="com.android.ide.eclipse.adt.preferences.LaunchPreferencePage"
             name="Launch"/>
+      <page
+            category="com.android.ide.eclipse.preferences.main"
+            class="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
+            id="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
+            name="Usage Stats">
+      </page>
    </extension>
    <extension
          point="org.eclipse.core.runtime.preferences">
       <initializer class="com.android.ide.eclipse.adt.preferences.PreferenceInitializer"/>
    </extension>
    <extension
-         point="org.eclipse.ui.editors">
-      <editor
-            class="com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor"
-            contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"
-            default="true"
-            filenames="R.java, Manifest.java"
-            icon="icons/android.png"
-            id="com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor"
-            name="Android Java Editor"/>
-   </extension>
-   <extension
          id="com.android.ide.eclipse.adt.adtProblem"
-         name="Generic ADT Problem"
+         name="Android ADT Problem"
          point="org.eclipse.core.resources.markers">
       <super type="org.eclipse.core.resources.problemmarker"/>
       <persistent value="true"/>
    </extension>
    <extension
+         id="com.android.ide.eclipse.adt.targetProblem"
+         name="Android Target Problem"
+         point="org.eclipse.core.resources.markers">
+      <super type="org.eclipse.core.resources.problemmarker"/>
+      <persistent value="false"/>
+   </extension>
+   <extension
          point="org.eclipse.ui.perspectiveExtensions">
       <perspectiveExtension targetID="org.eclipse.jdt.ui.JavaPerspective">
          <newWizardShortcut id="com.android.ide.eclipse.adt.project.NewProjectWizard" />
@@ -305,4 +358,110 @@
             keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration">
       </keyBinding>
    </extension>
+   <extension
+         point="org.eclipse.ui.decorators">
+      <decorator
+            adaptable="true"
+            class="com.android.ide.eclipse.adt.project.FolderDecorator"
+            id="com.android.ide.eclipse.adt.project.FolderDecorator"
+            label="Android Decorator"
+            lightweight="true"
+            location="TOP_RIGHT"
+            objectClass="org.eclipse.core.resources.IFolder"
+            state="true">
+      </decorator>
+   </extension>
+   <extension
+         point="org.eclipse.ui.editors">
+      <editor
+            class="com.android.ide.eclipse.editors.manifest.ManifestEditor"
+            default="true"
+            filenames="AndroidManifest.xml"
+            icon="icons/android.png"
+            id="com.android.ide.eclipse.editors.manifest.ManifestEditor"
+            name="Android Manifest Editor">
+      </editor>
+      <editor
+            class="com.android.ide.eclipse.editors.resources.ResourcesEditor"
+            default="false"
+            extensions="xml"
+            icon="icons/android.png"
+            id="com.android.ide.eclipse.editors.resources.ResourcesEditor"
+            name="Android Resource Editor">
+      </editor>
+      <editor
+            class="com.android.ide.eclipse.editors.layout.LayoutEditor"
+            default="false"
+            extensions="xml"
+            icon="icons/android.png"
+            id="com.android.ide.eclipse.editors.layout.LayoutEditor"
+            matchingStrategy="com.android.ide.eclipse.editors.layout.MatchingStrategy"
+            name="Android Layout Editor">
+      </editor>
+      <editor
+            class="com.android.ide.eclipse.editors.menu.MenuEditor"
+            default="false"
+            extensions="xml"
+            icon="icons/android.png"
+            id="com.android.ide.eclipse.editors.menu.MenuEditor"
+            name="Android Menu Editor">
+      </editor>
+      <editor
+            class="com.android.ide.eclipse.editors.xml.XmlEditor"
+            default="false"
+            extensions="xml"
+            icon="icons/android.png"
+            id="com.android.ide.eclipse.editors.xml.XmlEditor"
+            name="Android Xml Resources Editor">
+      </editor>
+   </extension>
+   <extension
+         point="org.eclipse.ui.views">
+      <view
+            allowMultiple="false"
+            category="com.android.ide.eclipse.ddms.views.category"
+            class="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
+            icon="icons/android.png"
+            id="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
+            name="Resource Explorer">
+      </view>
+   </extension>
+   <extension
+         point="org.eclipse.wst.sse.ui.editorConfiguration">
+      <sourceViewerConfiguration
+            class="com.android.ide.eclipse.editors.manifest.ManifestSourceViewerConfig"
+            target="com.android.ide.eclipse.editors.manifest.ManifestEditor">
+      </sourceViewerConfiguration>
+      <sourceViewerConfiguration
+            class="com.android.ide.eclipse.editors.resources.ResourcesSourceViewerConfig"
+            target="com.android.ide.eclipse.editors.resources.ResourcesEditor">
+      </sourceViewerConfiguration>
+      <sourceViewerConfiguration
+            class="com.android.ide.eclipse.editors.layout.LayoutSourceViewerConfig"
+            target="com.android.ide.eclipse.editors.layout.LayoutEditor">
+      </sourceViewerConfiguration>
+      <sourceViewerConfiguration
+            class="com.android.ide.eclipse.editors.menu.MenuSourceViewerConfig"
+            target="com.android.ide.eclipse.editors.menu.MenuEditor">
+      </sourceViewerConfiguration>
+      <sourceViewerConfiguration
+            class="com.android.ide.eclipse.editors.xml.XmlSourceViewerConfig"
+            target="com.android.ide.eclipse.editors.xml.XmlEditor">
+      </sourceViewerConfiguration>
+   </extension>
+   <extension
+         point="org.eclipse.ui.propertyPages">
+      <page
+            adaptable="true"
+            class="com.android.ide.eclipse.adt.project.properties.AndroidPropertyPage"
+            id="com.android.ide.eclipse.adt.project.properties.AndroidPropertyPage"
+            name="Android"
+            nameFilter="*"
+            objectClass="org.eclipse.core.resources.IProject">
+         <enabledWhen>
+               <test property="org.eclipse.jdt.launching.hasProjectNature"
+                     args="com.android.ide.eclipse.adt.AndroidNature"/>
+         </enabledWhen>
+      </page>
+   </extension>
 </plugin>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
index 6d52aa5..61b3f4d 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
@@ -17,6 +17,7 @@
 package com.android.ide.eclipse.adt;
 
 
+
 /**
  * Constant definition class.<br>
  * <br>
@@ -39,6 +40,12 @@
     /** Generic marker for ADT errors. */
     public final static String MARKER_ADT = AdtPlugin.PLUGIN_ID + ".adtProblem"; //$NON-NLS-1$
 
+    /** Marker for Android Target errors.
+     * This is not cleared on each like other markers. Instead, it's cleared
+     * when a ContainerClasspathInitialized has succeeded in creating an
+     * {@link AndroidClasspathContainer}*/
+    public final static String MARKER_TARGET = AdtPlugin.PLUGIN_ID + ".targetProblem"; //$NON-NLS-1$
+
     /** Build verbosity "Always". Those messages are always displayed. */
     public final static int BUILD_ALWAYS = 0;
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index 9b24b07..d9c18cf 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -22,34 +22,55 @@
 import com.android.ddmuilib.console.IDdmConsole;
 import com.android.ide.eclipse.adt.build.DexWrapper;
 import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController;
-import com.android.ide.eclipse.adt.debug.ui.SkinRepository;
 import com.android.ide.eclipse.adt.preferences.BuildPreferencePage;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
 import com.android.ide.eclipse.adt.project.export.ExportWizard;
 import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer;
-import com.android.ide.eclipse.adt.resources.FrameworkResourceParser;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetParser;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
 import com.android.ide.eclipse.common.EclipseUiHelper;
 import com.android.ide.eclipse.common.SdkStatsHelper;
 import com.android.ide.eclipse.common.StreamHelper;
 import com.android.ide.eclipse.common.project.BaseProjectHelper;
 import com.android.ide.eclipse.common.project.ExportHelper;
 import com.android.ide.eclipse.common.project.ExportHelper.IExportCallback;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
 import com.android.ide.eclipse.ddms.DdmsPlugin;
 import com.android.ide.eclipse.ddms.ImageLoader;
+import com.android.ide.eclipse.editors.IconFactory;
+import com.android.ide.eclipse.editors.layout.LayoutEditor;
+import com.android.ide.eclipse.editors.menu.MenuEditor;
+import com.android.ide.eclipse.editors.resources.ResourcesEditor;
+import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
+import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
+import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
+import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor;
+import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener;
+import com.android.ide.eclipse.editors.xml.XmlEditor;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarkerDelta;
 import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.SubMonitor;
 import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
 import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
 import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.preference.IPreferenceStore;
@@ -57,14 +78,21 @@
 import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.jface.wizard.WizardDialog;
 import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
 import org.eclipse.ui.console.IConsoleConstants;
 import org.eclipse.ui.console.MessageConsole;
 import org.eclipse.ui.console.MessageConsoleStream;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.FileEditorInput;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -81,6 +109,8 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * The activator class controls the plug-in life cycle
@@ -106,14 +136,17 @@
     /** singleton instance */
     private static AdtPlugin sPlugin;
 
+    private static Image sAndroidLogo;
+    private static ImageDescriptor sAndroidLogoDesc;
+
     /** default store, provided by eclipse */
     private IPreferenceStore mStore;
 
     /** cached location for the sdk folder */
     private String mOsSdkLocation;
 
-    /** SDK Api Version */
-    String mSdkApiVersion;
+    /** The global android console */
+    private MessageConsole mAndroidConsole;
 
     /** Stream to write in the android console */
     private MessageConsoleStream mAndroidConsoleStream;
@@ -130,14 +163,14 @@
     /** Color used in the error console */
     private Color mRed;
     
-    private final ArrayList<IJavaProject> mPostDexProjects = new ArrayList<IJavaProject>();
+    /** Load status of the SDK. Any access MUST be in a synchronized(mPostLoadProjects) block */
+    private LoadStatus mSdkIsLoaded = LoadStatus.LOADING;
+    /** Project to update once the SDK is loaded.
+     * Any access MUST be in a synchronized(mPostLoadProjects) block */
+    private final ArrayList<IJavaProject> mPostLoadProjects = new ArrayList<IJavaProject>();
     
-    /** Boolean wrapper to run dialog in the UI thread, and still get the
-     * return code.
-     */
-    private static final class BooleanWrapper {
-        public boolean b;
-    }
+    private ResourceMonitor mResourceMonitor;
+    private ArrayList<Runnable> mResourceRefreshListener = new ArrayList<Runnable>();
 
     /**
      * Custom PrintStream for Dx output. This class overrides the method
@@ -210,10 +243,14 @@
 
         Display display = getDisplay();
 
+        // set the default android console.
+        mAndroidConsole = new MessageConsole("Android", null); //$NON-NLS-1$
+        ConsolePlugin.getDefault().getConsoleManager().addConsoles(
+                new IConsole[] { mAndroidConsole });
+
         // get the stream to write in the android console.
-        MessageConsole androidConsole = CommonPlugin.getDefault().getAndroidConsole();
-        mAndroidConsoleStream = androidConsole.newMessageStream();
-        mAndroidConsoleErrorStream = androidConsole.newMessageStream();
+        mAndroidConsoleStream = mAndroidConsole.newMessageStream();
+        mAndroidConsoleErrorStream = mAndroidConsole.newMessageStream();
         mRed = new Color(display, 0xFF, 0x00, 0x00);
 
         // because this can be run, in some cases, by a non ui thread, and beccause
@@ -267,22 +304,19 @@
 
                     // get the SDK location and build id.
                     if (checkSdkLocationAndId()) {
-                        // if sdk if valid, reparse the skin folder
-                        SkinRepository.getInstance().parseFolder(getOsSkinFolder());
+                        // if sdk if valid, reparse it
+                        
+                        // add the current Android project to the list of projects to be updated
+                        // after the SDK is reloaded
+                        synchronized (mPostLoadProjects) {
+                            // get the project to refresh.
+                            IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects();
+                            mPostLoadProjects.addAll(Arrays.asList(androidProjects));
+                        }
+    
+                        // parse the SDK resources at the new location
+                        parseSdkContent();
                     }
-
-                    // parse the SDK resources at the new location
-                    parseSdkContent();
-                    
-                    // get the project to refresh.
-                    IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects();
-                    
-                    // Setup the new container for each project. By providing new instances of
-                    // AndroidClasspathContainer, this will force JDT to call
-                    // IClasspathContainer#getClasspathEntries() again and receive the new
-                    // path to the framework jar.
-                    AndroidClasspathContainerInitializer.updateProjects(androidProjects);
-                    
                 } else if (PREFS_BUILD_VERBOSITY.equals(property)) {
                     mBuildVerbosity = BuildPreferencePage.getBuildLevel(
                             mStore.getString(PREFS_BUILD_VERBOSITY));
@@ -299,20 +333,11 @@
         }
 
         // check the location of SDK
-        if (checkSdkLocationAndId())  {
-            // if sdk if valid, parse the skin folder
-            SkinRepository.getInstance().parseFolder(getOsSkinFolder());
-
-            // parse the SDK resources.
-            parseSdkContent();
-        }
+        final boolean isSdkLocationValid = checkSdkLocationAndId();
         
         mBuildVerbosity = BuildPreferencePage.getBuildLevel(
                 mStore.getString(PREFS_BUILD_VERBOSITY));
 
-        // Ping the usage start server.
-        pingUsageServer();
-
         // create the loader that's able to load the images
         mLoader = new ImageLoader(this);
 
@@ -356,18 +381,31 @@
                 dialog.open();
             }
         });
+        
+        // initialize editors
+        startEditors();
 
-        /* The Editors plugin must be started as soon as Android projects are opened or created,
-         * in order to properly set default editors on the layout/values XML files.
-         * 
-         * This ensures that the default editors is really only set when a new XML file
-         * is added to the workspace (IResourceDelta.ADDED event), through project creation or
-         * manual add.
-         * Other methods would force to go through existing projects when the Editors plugin is
-         * started, and set the default editors for their XML files, possibly erasing user set
-         * default editors.
-         */
-        startEditorsPlugin();
+        // Ping the usage server and parse the SDK content.
+        // This is deferred in separate jobs to avoid blocking the bundle start.
+        // We also serialize them to avoid too many parallel jobs when Eclipse starts.
+        Job pingJob = createPingUsageServerJob();
+        pingJob.addJobChangeListener(new JobChangeAdapter() {
+           @Override
+            public void done(IJobChangeEvent event) {
+                super.done(event);
+    
+                // Once the ping job is finished, start the SDK parser
+                if (isSdkLocationValid) {
+                    // parse the SDK resources.
+                    parseSdkContent();
+                }
+            } 
+        });
+        // build jobs are run after other interactive jobs
+        pingJob.setPriority(Job.BUILD); 
+        // Wait 2 seconds before starting the ping job. This leaves some time to the
+        // other bundles to initialize.
+        pingJob.schedule(2000 /*milliseconds*/);
     }
 
     /*
@@ -379,6 +417,8 @@
     public void stop(BundleContext context) throws Exception {
         super.stop(context);
         
+        stopEditors();
+        
         DexWrapper.unloadDex();
 
         mRed.dispose();
@@ -418,37 +458,22 @@
 
     /** Returns the adb path relative to the sdk folder */
     public static String getOsRelativeAdb() {
-        return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_ADB;
+        return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_ADB;
     }
 
     /** Returns the aapt path relative to the sdk folder */
     public static String getOsRelativeAapt() {
-        return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AAPT;
+        return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AAPT;
     }
 
     /** Returns the emulator path relative to the sdk folder */
     public static String getOsRelativeEmulator() {
-        return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_EMULATOR;
+        return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_EMULATOR;
     }
 
     /** Returns the aidl path relative to the sdk folder */
     public static String getOsRelativeAidl() {
-        return AndroidConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AIDL;
-    }
-
-    /** Returns the framework jar path relative to the sdk folder */
-    public static String getOsRelativeFramework() {
-        return AndroidConstants.FN_FRAMEWORK_LIBRARY;
-    }
-
-    /** Returns the android sources path relative to the sdk folder */
-    public static String getOsRelativeAndroidSources() {
-        return AndroidConstants.FD_ANDROID_SOURCES;
-    }
-
-    /** Returns the framework jar path relative to the sdk folder */
-    public static String getOsRelativeAttrsXml() {
-        return AndroidConstants.OS_SDK_LIBS_FOLDER + AndroidConstants.FN_ATTRS_XML;
+        return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AIDL;
     }
 
     /** Returns the absolute adb path */
@@ -458,7 +483,7 @@
 
     /** Returns the absolute traceview path */
     public static String getOsAbsoluteTraceview() {
-        return getOsSdkFolder() + AndroidConstants.OS_SDK_TOOLS_FOLDER +
+        return getOsSdkFolder() + SdkConstants.OS_SDK_TOOLS_FOLDER +
                 AndroidConstants.FN_TRACEVIEW;
     }
 
@@ -467,21 +492,6 @@
         return getOsSdkFolder() + getOsRelativeAapt();
     }
 
-    /** Returns the absolute sdk framework path */
-    public static String getOsAbsoluteFramework() {
-        return getOsSdkFolder() + getOsRelativeFramework();
-    }
-
-    /** Returns the absolute android sources path in the sdk */
-    public static String getOsAbsoluteAndroidSources() {
-        return getOsSdkFolder() + getOsRelativeAndroidSources();
-    }
-
-    /** Returns the absolute attrs.xml path */
-    public static String getOsAbsoluteAttrsXml() {
-        return getOsSdkFolder() + getOsRelativeAttrsXml();
-    }
-
     /** Returns the absolute emulator path */
     public static String getOsAbsoluteEmulator() {
         return getOsSdkFolder() + getOsRelativeEmulator();
@@ -492,16 +502,6 @@
         return getOsSdkFolder() + getOsRelativeAidl();
     }
 
-    /** Returns the absolute path to the aidl framework import file. */
-    public static String getOsAbsoluteFrameworkAidl() {
-        return getOsSdkFolder() + AndroidConstants.OS_SDK_LIBS_FOLDER +
-                AndroidConstants.FN_FRAMEWORK_AIDL;
-    }
-
-    public static String getOsSdkSamplesFolder() {
-        return getOsSdkFolder() + AndroidConstants.OS_SDK_SAMPLES_FOLDER;
-    }
-
     /**
      * Returns a Url file path to the javaDoc folder.
      */
@@ -526,11 +526,7 @@
     }
 
     public static String getOsSdkToolsFolder() {
-        return getOsSdkFolder() + AndroidConstants.OS_SDK_TOOLS_FOLDER;
-    }
-
-    public static String getOsSkinFolder() {
-        return getOsSdkFolder() + AndroidConstants.OS_SDK_SKINS_FOLDER;
+        return getOsSdkFolder() + SdkConstants.OS_SDK_TOOLS_FOLDER;
     }
 
     public static synchronized boolean getAutoResRefresh() {
@@ -540,18 +536,6 @@
         return sPlugin.mStore.getBoolean(PREFS_RES_AUTO_REFRESH);
     }
 
-    /**
-     * Returns the SDK build id.
-     * @return a string containing the SDK build id, or null it it is unknownn.
-     */
-    public static synchronized String getSdkApiVersion() {
-        if (sPlugin != null) {
-            return sPlugin.mSdkApiVersion;
-        }
-        
-        return null;
-    }
-
     public static synchronized int getBuildVerbosity() {
         if (sPlugin != null) {
             return sPlugin.mBuildVerbosity;
@@ -705,23 +689,25 @@
         final Display display = getDisplay();
 
         // we need to ask the user what he wants to do.
-        final BooleanWrapper wrapper = new BooleanWrapper();
+        final boolean[] result = new boolean[1];
         display.syncExec(new Runnable() {
             public void run() {
                 Shell shell = display.getActiveShell();
-                wrapper.b = MessageDialog.openQuestion(shell, title, message);
+                result[0] = MessageDialog.openQuestion(shell, title, message);
             }
         });
-        return wrapper.b;
+        return result[0];
     }
     
     /**
      * Logs a message to the default Eclipse log.
      * 
-     * @param severity The severity code. Valid values are: {@link IStatus#OK}, {@link IStatus#ERROR},
-     * {@link IStatus#INFO}, {@link IStatus#WARNING} or {@link IStatus#CANCEL}.
+     * @param severity The severity code. Valid values are: {@link IStatus#OK},
+     * {@link IStatus#ERROR}, {@link IStatus#INFO}, {@link IStatus#WARNING} or
+     * {@link IStatus#CANCEL}.
      * @param format The format string, like for {@link String#format(String, Object...)}.
-     * @param args The arguments for the format string, like for {@link String#format(String, Object...)}.
+     * @param args The arguments for the format string, like for
+     * {@link String#format(String, Object...)}.
      */
     public static void log(int severity, String format, Object ... args) {
         String message = String.format(format, args);
@@ -845,7 +831,7 @@
         
         // now make sure it's not docked.
         ConsolePlugin.getDefault().getConsoleManager().showConsoleView(
-                CommonPlugin.getDefault().getAndroidConsole());
+                AdtPlugin.getDefault().getAndroidConsole());
     }
 
     /**
@@ -883,21 +869,17 @@
     }
     
     /**
-     * Adds a {@link IJavaProject} to a list of projects to be recompiled once dx.jar is loaded.
-     * @param javaProject
+     * Returns whether the Sdk has been loaded. If the SDK has not been loaded, the given
+     * <var>project</var> is added to a list of projects to recompile after the SDK is loaded.
      */
-    public void addPostDexProject(IJavaProject javaProject) {
-        synchronized (mPostDexProjects) {
-            if (DexWrapper.getStatus() == DexWrapper.LoadStatus.LOADED) {
-                // Setup the new container for each project. By providing new instances of
-                // AndroidClasspathContainer, this will force JDT to call
-                // IClasspathContainer#getClasspathEntries() again and receive the new
-                // path to the framework jar, and the project will be recompiled.
-                AndroidClasspathContainerInitializer.updateProjects(new IJavaProject [] {
-                        javaProject });
-            } else {
-                mPostDexProjects.add(javaProject);
+    public LoadStatus getSdkLoadStatus(IJavaProject project) {
+        synchronized (mPostLoadProjects) {
+            // only add the project to the list, if we are still loading.
+            if (mSdkIsLoaded == LoadStatus.LOADING && project != null) {
+                mPostLoadProjects.add(project);
             }
+            
+            return mSdkIsLoaded;
         }
     }
 
@@ -907,9 +889,6 @@
      * @return false if the location is not correct.
      */
     private boolean checkSdkLocationAndId() {
-        // Reset the sdk build first in case the SDK is invalid and we abort.
-        mSdkApiVersion = null;
-
         if (mOsSdkLocation == null || mOsSdkLocation.length() == 0) {
             displayError(Messages.Dialog_Title_SDK_Location, Messages.SDK_Not_Setup);
             return false;
@@ -949,17 +928,16 @@
                     String.format(Messages.Could_Not_Find_Folder, osSdkLocation));
         }
 
-        String osTools = osSdkLocation + AndroidConstants.OS_SDK_TOOLS_FOLDER;
+        String osTools = osSdkLocation + SdkConstants.OS_SDK_TOOLS_FOLDER;
         File toolsFolder = new File(osTools);
         if (toolsFolder.isDirectory() == false) {
             return errorHandler.handleError(
                     String.format(Messages.Could_Not_Find_Folder_In_SDK,
-                            AndroidConstants.FD_TOOLS, osSdkLocation));
+                            SdkConstants.FD_TOOLS, osSdkLocation));
         }
 
         // check the path to various tools we use
         String[] filesToCheck = new String[] {
-                osSdkLocation + getOsRelativeFramework(),
                 osSdkLocation + getOsRelativeAdb(),
                 osSdkLocation + getOsRelativeAapt(),
                 osSdkLocation + getOsRelativeAidl(),
@@ -990,118 +968,106 @@
     }
 
     /**
-     * Pings the usage start server.
+     * Creates a job than can ping the usage server.
      */
-    private void pingUsageServer() {
+    private Job createPingUsageServerJob() {
         // In order to not block the plugin loading, so we spawn another thread.
-        new Thread("Ping!") { //$NON-NLS-1$
+        Job job = new Job("Android SDK Ping") {  // Job name, visible in progress view
             @Override
-            public void run() {
-                // get the version of the plugin
-                String versionString = (String) getBundle().getHeaders().get(
-                        Constants.BUNDLE_VERSION);
-                Version version = new Version(versionString);
-                
-                SdkStatsHelper.pingUsageServer("adt", version); //$NON-NLS-1$
-            }
-        }.start();
-    }
-    
-    /**
-     * Starts the Editors plugin.
-     * <p/> 
-     * Since we do not want any dependencies between the plugins (Editors is an optional
-     * plugin not needed for Android development), we attempt to start the plugin through
-     * OSGi directly.
-     * <p/> 
-     * This is done in another thread to not delay the start of this plugin.
-     */
-    private void startEditorsPlugin() {
-        new Thread() {
-            @Override
-            public void run() {
+            protected IStatus run(IProgressMonitor monitor) {
                 try {
-                    // look for the bundle of the Editors plugin
-                    Bundle editorsBundle = Platform.getBundle(AndroidConstants.EDITORS_PLUGIN_ID);
-                    if (editorsBundle != null) {
-                        // we only start if the bundle is installed and not started.
-                        // STARTING means that its start is pending a triggering.
-                        int bundleState = editorsBundle.getState();
-                        if ((bundleState & (Bundle.RESOLVED | Bundle.INSTALLED
-                                | Bundle.STARTING)) != 0) {
-                            // Attempt to start it.
-                            // START_TRANSIENT is used because we don't want
-                            // to change the auto start value.
-                            editorsBundle.start(Bundle.START_TRANSIENT);
-                        }
-                    }
-                } catch (Exception e) {
-                    log(e, Messages.AdtPlugin_Failed_To_Start_s, AndroidConstants.EDITORS_PLUGIN_ID);
+
+                    // get the version of the plugin
+                    String versionString = (String) getBundle().getHeaders().get(
+                            Constants.BUNDLE_VERSION);
+                    Version version = new Version(versionString);
+                    
+                    SdkStatsHelper.pingUsageServer("editors", version); //$NON-NLS-1$
+                    
+                    return Status.OK_STATUS;
+                } catch (Throwable t) {
+                    log(t, "pingUsageServer failed"); //$NON-NLS-1$
+                    return new Status(IStatus.ERROR, PLUGIN_ID,
+                            "pingUsageServer failed", t);
                 }
             }
-        }.start();
+        };
+        return job;
     }
     
     /**
-     * Parses the SDK resources and set them in the {@link FrameworkResourceManager}.
+     * Parses the SDK resources.
      */
     private void parseSdkContent() {
         // Perform the update in a thread (here an Eclipse runtime job)
         // since this should never block the caller (especially the start method)
-        new Job(Messages.AdtPlugin_Android_SDK_Content_Loader) {
+        Job job = new Job(Messages.AdtPlugin_Android_SDK_Content_Loader) {
+            @SuppressWarnings("unchecked")
             @Override
             protected IStatus run(IProgressMonitor monitor) {
-                try {
-                    SubMonitor progress = null;
-                    try {
-                        progress = SubMonitor.convert(monitor, Messages.AdtPlugin_Parsing_Resources, 100);
-                        
-                        // load the values.
-                        FrameworkResourceParser parser = new FrameworkResourceParser();
-                        parser.parse(mOsSdkLocation, FrameworkResourceManager.getInstance(),
-                                progress);
-    
-                        // set the location of the layout lib jar file.
-                        FrameworkResourceManager.getInstance().setLayoutLibLocation(
-                                mOsSdkLocation + AndroidConstants.OS_SDK_LIBS_LAYOUTLIB_JAR);
-                        FrameworkResourceManager.getInstance().setFrameworkResourcesLocation(
-                                mOsSdkLocation + AndroidConstants.OS_SDK_RESOURCES_FOLDER);
-                        FrameworkResourceManager.getInstance().setFrameworkFontLocation(
-                                mOsSdkLocation + AndroidConstants.OS_SDK_FONTS_FOLDER);
-                    } catch (Throwable e) {
-                        AdtPlugin.log(e, "Android SDK Resource Parser failed"); //$NON-NLS-1$
-                        AdtPlugin.printErrorToConsole(Messages.AdtPlugin_Android_SDK_Resource_Parser,
-                                Messages.AdtPlugin_Failed_To_Parse_s + e.getMessage());
-                        
-                        return new Status(IStatus.ERROR, PLUGIN_ID, e.getMessage(), e);
-                    } finally {
-                        if (progress != null) {
-                            progress.worked(100);
-                        }
-                    }
+                try {                    
+                    SubMonitor progress = SubMonitor.convert(monitor,
+                            "Initialize SDK Manager", 100);
                     
-                    try {
-                        progress = SubMonitor.convert(monitor, Messages.AdtPlugin_Parsing_Resources, 20);
+                    Sdk sdk = Sdk.loadSdk(mOsSdkLocation);
+                    
+                    if (sdk != null) {
+                        
+                        progress.setTaskName(Messages.AdtPlugin_Parsing_Resources);
+                        
+                        for (IAndroidTarget target : sdk.getTargets()) {
+                            IStatus status = new AndroidTargetParser(target).run(progress);
+                            if (status.getCode() != IStatus.OK) {
+                                synchronized (mPostLoadProjects) {
+                                    mSdkIsLoaded = LoadStatus.FAILED;
+                                    mPostLoadProjects.clear();
+                                }
+                                return status;
+                            }
+                        }
+
+                        // FIXME: move this per platform, or somewhere else.
+                        progress = SubMonitor.convert(monitor,
+                                Messages.AdtPlugin_Parsing_Resources, 20);
                         DexWrapper.unloadDex();
 
                         IStatus res = DexWrapper.loadDex(
                                 mOsSdkLocation + AndroidConstants.OS_SDK_LIBS_DX_JAR);
                         if (res != Status.OK_STATUS) {
+                            synchronized (mPostLoadProjects) {
+                                mSdkIsLoaded = LoadStatus.FAILED;
+                                mPostLoadProjects.clear();
+                            }
                             return res;
-                        } else {
+                        }
+
+                        synchronized (mPostLoadProjects) {
+                            mSdkIsLoaded = LoadStatus.LOADED;
+
                             // update the project that needs recompiling.
-                            synchronized (mPostDexProjects) {
-                                if (mPostDexProjects.size() > 0) {
-                                    IJavaProject[] array = mPostDexProjects.toArray(
-                                            new IJavaProject[mPostDexProjects.size()]);
-                                    AndroidClasspathContainerInitializer.updateProjects(array);
-                                    mPostDexProjects.clear();
-                                }
+                            if (mPostLoadProjects.size() > 0) {
+                                IJavaProject[] array = mPostLoadProjects.toArray(
+                                        new IJavaProject[mPostLoadProjects.size()]);
+                                AndroidClasspathContainerInitializer.updateProjects(array);
+                                mPostLoadProjects.clear();
                             }
                         }
-                    } finally {
-                        if (progress != null) {
-                            progress.worked(20);
+                    }
+                        
+                    // Notify resource changed listeners
+                    progress.subTask("Refresh UI");
+                    progress.setWorkRemaining(mResourceRefreshListener.size());
+                    
+                    // Clone the list before iterating, to avoid Concurrent Modification
+                    // exceptions
+                    List<Runnable> listeners = (List<Runnable>)mResourceRefreshListener.clone();
+                    for (Runnable listener : listeners) {
+                        try {
+                            AdtPlugin.getDisplay().syncExec(listener);
+                        } catch (Exception e) {
+                            AdtPlugin.log(e, "ResourceRefreshListener Failed");  //$NON-NLS-1$
+                        } finally {
+                            progress.worked(1);
                         }
                     }
                 } finally {
@@ -1112,6 +1078,252 @@
 
                 return Status.OK_STATUS;
             }
-        }.schedule();
+        };
+        job.setPriority(Job.BUILD); // build jobs are run after other interactive jobs
+        job.schedule();
+    }
+    
+    /** Returns the global android console */
+    public MessageConsole getAndroidConsole() {
+        return mAndroidConsole;
+    }
+    
+    // ----- Methods for Editors -------
+
+    public void startEditors() {
+        sAndroidLogoDesc = imageDescriptorFromPlugin(AdtPlugin.PLUGIN_ID,
+                "/icons/android.png"); //$NON-NLS-1$
+        sAndroidLogo = sAndroidLogoDesc.createImage();
+        
+        // get the stream to write in the android console.
+        MessageConsole androidConsole = AdtPlugin.getDefault().getAndroidConsole();
+        mAndroidConsoleStream = androidConsole.newMessageStream();
+
+        mAndroidConsoleErrorStream = androidConsole.newMessageStream();
+        mRed = new Color(getDisplay(), 0xFF, 0x00, 0x00);
+
+        // because this can be run, in some cases, by a non ui thread, and beccause
+        // changing the console properties update the ui, we need to make this change
+        // in the ui thread.
+        getDisplay().asyncExec(new Runnable() {
+            public void run() {
+                mAndroidConsoleErrorStream.setColor(mRed);
+            }
+        });
+
+        // Add a resource listener to handle compiled resources.
+        IWorkspace ws = ResourcesPlugin.getWorkspace();
+        mResourceMonitor = ResourceMonitor.startMonitoring(ws);
+
+        if (mResourceMonitor != null) {
+            try {
+                setupDefaultEditor(mResourceMonitor);
+                ResourceManager.setup(mResourceMonitor);
+            } catch (Throwable t) {
+                log(t, "ResourceManager.setup failed"); //$NON-NLS-1$
+            }
+        }
+    }
+
+    /**
+     * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
+     * method saves this plug-in's preference and dialog stores and shuts down 
+     * its image registry (if they are in use). Subclasses may extend this
+     * method, but must send super <b>last</b>. A try-finally statement should
+     * be used where necessary to ensure that <code>super.shutdown()</code> is
+     * always done.
+     * 
+     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+     */
+    public void stopEditors() {
+        sAndroidLogo.dispose();
+        
+        IconFactory.getInstance().Dispose();
+        
+        // Remove the resource listener that handles compiled resources.
+        IWorkspace ws = ResourcesPlugin.getWorkspace();
+        ResourceMonitor.stopMonitoring(ws);
+
+        mRed.dispose();
+    }
+
+    /**
+     * Returns an Image for the small Android logo.
+     * 
+     * Callers should not dispose it.
+     */
+    public static Image getAndroidLogo() {
+        return sAndroidLogo;
+    }
+
+    /**
+     * Returns an {@link ImageDescriptor} for the small Android logo.
+     * 
+     * Callers should not dispose it.
+     */
+    public static ImageDescriptor getAndroidLogoDesc() {
+        return sAndroidLogoDesc;
+    }
+    
+    /**
+     * Returns the ResourceMonitor object.
+     */
+    public ResourceMonitor getResourceMonitor() {
+        return mResourceMonitor;
+    }
+
+    /**
+     * Sets up the editor to register default editors for resource files when needed.
+     * 
+     * This is called by the {@link AdtPlugin} during initialization.
+     * 
+     * @param monitor The main Resource Monitor object.
+     */
+    public void setupDefaultEditor(ResourceMonitor monitor) {
+        monitor.addFileListener(new IFileListener() {
+
+            private static final String UNKNOWN_EDITOR = "unknown-editor"; //$NON-NLS-1$
+            
+            /* (non-Javadoc)
+             * Sent when a file changed.
+             * @param file The file that changed.
+             * @param markerDeltas The marker deltas for the file.
+             * @param kind The change kind. This is equivalent to
+             * {@link IResourceDelta#accept(IResourceDeltaVisitor)}
+             * 
+             * @see IFileListener#fileChanged
+             */
+            public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
+                if (AndroidConstants.EXT_XML.equals(file.getFileExtension())) {
+                    // The resources files must have a file path similar to
+                    //    project/res/.../*.xml
+                    // There is no support for sub folders, so the segment count must be 4
+                    if (file.getFullPath().segmentCount() == 4) {
+                        // check if we are inside the res folder.
+                        String segment = file.getFullPath().segment(1); 
+                        if (segment.equalsIgnoreCase(AndroidConstants.FD_RESOURCES)) {
+                            // we are inside a res/ folder, get the actual ResourceFolder
+                            ProjectResources resources = ResourceManager.getInstance().
+                                getProjectResources(file.getProject());
+
+                            // This happens when importing old Android projects in Eclipse
+                            // that lack the container (probably because resources fail to build
+                            // properly.)
+                            if (resources == null) {
+                                log(IStatus.INFO,
+                                        "getProjectResources failed for path %1$s in project %2$s", //$NON-NLS-1$
+                                        file.getFullPath().toOSString(),
+                                        file.getProject().getName());
+                                return;
+                            }
+
+                            ResourceFolder resFolder = resources.getResourceFolder(
+                                (IFolder)file.getParent());
+                        
+                            if (resFolder != null) {
+                                if (kind == IResourceDelta.ADDED) {
+                                    resourceAdded(file, resFolder.getType());
+                                } else if (kind == IResourceDelta.CHANGED) {
+                                    resourceChanged(file, resFolder.getType());
+                                }
+                            } else {
+                                // if the res folder is null, this means the name is invalid,
+                                // in this case we remove whatever android editors that was set
+                                // as the default editor.
+                                IEditorDescriptor desc = IDE.getDefaultEditor(file);
+                                String editorId = desc.getId();
+                                if (editorId.startsWith(AndroidConstants.EDITORS_NAMESPACE)) {
+                                    // reset the default editor.
+                                    IDE.setDefaultEditor(file, null);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            private void resourceAdded(IFile file, ResourceFolderType type) {
+                // set the default editor based on the type.
+                if (type == ResourceFolderType.LAYOUT) {
+                    IDE.setDefaultEditor(file, LayoutEditor.ID);
+                } else if (type == ResourceFolderType.DRAWABLE
+                        || type == ResourceFolderType.VALUES) {
+                    IDE.setDefaultEditor(file, ResourcesEditor.ID);
+                } else if (type == ResourceFolderType.MENU) {
+                    IDE.setDefaultEditor(file, MenuEditor.ID);
+                } else if (type == ResourceFolderType.XML) {
+                    if (XmlEditor.canHandleFile(file)) {
+                        IDE.setDefaultEditor(file, XmlEditor.ID);
+                    } else {
+                        // set a property to determine later if the XML can be handled
+                        QualifiedName qname = new QualifiedName(
+                                AdtPlugin.PLUGIN_ID,
+                                UNKNOWN_EDITOR);
+                        try {
+                            file.setPersistentProperty(qname, "1");
+                        } catch (CoreException e) {
+                            // pass
+                        }
+                    }
+                }
+            }
+
+            private void resourceChanged(IFile file, ResourceFolderType type) {
+                if (type == ResourceFolderType.XML) {
+                    IEditorDescriptor ed = IDE.getDefaultEditor(file);
+                    if (ed == null || ed.getId() != XmlEditor.ID) {
+                        QualifiedName qname = new QualifiedName(
+                                AdtPlugin.PLUGIN_ID,
+                                UNKNOWN_EDITOR);
+                        String prop = null;
+                        try {
+                            prop = file.getPersistentProperty(qname);
+                        } catch (CoreException e) {
+                            // pass
+                        }
+                        if (prop != null && XmlEditor.canHandleFile(file)) {
+                            try {
+                                // remove the property & set editor
+                                file.setPersistentProperty(qname, null);
+                                IWorkbenchPage page = PlatformUI.getWorkbench().
+                                                        getActiveWorkbenchWindow().getActivePage();
+                                
+                                IEditorPart oldEditor = page.findEditor(new FileEditorInput(file));
+                                if (oldEditor != null &&
+                                        AdtPlugin.displayPrompt("Android XML Editor",
+                                            String.format("The file you just saved as been recognized as a file that could be better handled using the Android XML Editor. Do you want to edit '%1$s' using the Android XML editor instead?",
+                                                    file.getFullPath()))) {
+                                    IDE.setDefaultEditor(file, XmlEditor.ID);
+                                    IEditorPart newEditor = page.openEditor(
+                                            new FileEditorInput(file),
+                                            XmlEditor.ID,
+                                            true, /* activate */
+                                            IWorkbenchPage.MATCH_NONE);
+                                
+                                    if (newEditor != null) {
+                                        page.closeEditor(oldEditor, true /* save */);
+                                    }
+                                }
+                            } catch (CoreException e) {
+                                // setPersistentProperty or page.openEditor may have failed
+                            }
+                        }
+                    }
+                }
+            }
+
+        }, IResourceDelta.ADDED | IResourceDelta.CHANGED);
+    }
+
+    public void addResourceChangedListener(Runnable resourceRefreshListener) {
+        mResourceRefreshListener.add(resourceRefreshListener);
+    }
+
+    public void removeResourceChangedListener(Runnable resourceRefreshListener) {
+        mResourceRefreshListener.remove(resourceRefreshListener);
+    }
+    
+    public static synchronized OutputStream getErrorStream() {
+        return sPlugin.mAndroidConsoleErrorStream;
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java
index bac940a..6d85af3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/VersionCheck.java
@@ -16,9 +16,8 @@
 
 package com.android.ide.eclipse.adt;
 
-import com.android.ddmlib.Device;
 import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
-import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.sdklib.SdkConstants;
 
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
@@ -42,19 +41,6 @@
  *
  */
 final class VersionCheck {
-
-    /** Pattern to get the SDK build incremental version from the
-     * <code>$SDK/tools/lib/build.prop file</code>. */
-    private final static Pattern sBuildVersionPattern = Pattern.compile(
-            "^" + Device.PROP_BUILD_VERSION + "=(.+)$"); //$NON-NLS-1$
-
-    /**
-     * Pattern to parse release type SDK version number. This parses the content read with
-     * <code>sBuildIdPattern</code>.
-     */
-    private final static Pattern sSdkVersionPattern = Pattern.compile(
-            "^(\\d+)\\.(\\d+)_r(\\d+)$", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
-
     /**
      * Pattern to get the minimum plugin version supported by the SDK. This is read from
      * the file <code>$SDK/tools/lib/plugin.prop</code>.
@@ -69,58 +55,7 @@
      */
     public static boolean checkVersion(String osSdkPath, CheckSdkErrorHandler errorHandler) {
         AdtPlugin plugin = AdtPlugin.getDefault();
-        String osLibs = osSdkPath + AndroidConstants.OS_SDK_LIBS_FOLDER;
-
-        /*
-         * All plugins should work with all SDKs. Newer SDKs may require a newer plugin
-         * but this is handled below.
-         * Still, we need to grab the SDK version from this file. This is used
-         * to compare to running emulator/device when launching run/debug sessions.
-         */
-        try {
-            FileReader reader = new FileReader(osLibs + AndroidConstants.FN_BUILD_PROP);
-            BufferedReader bReader = new BufferedReader(reader);
-            String line;
-            while ((line = bReader.readLine()) != null) {
-                Matcher m = sBuildVersionPattern.matcher(line);
-                if (m.matches()) {
-                    plugin.mSdkApiVersion = m.group(1).trim();
-                    
-                    /*
-                     * No checks on the version at the moment.
-                     */
-                    /*
-                    if (plugin.mSdkBuildVersion != null) {
-                        // attempt to get version number from the build id
-                        m = sSdkVersionPattern.matcher(plugin.mSdkBuildVersion);
-                        if (m.matches()) {
-                            // get the platform version number
-                            int platformMajor = Integer.parseInt(m.group(1));
-                            int platformMinor = Integer.parseInt(m.group(2));
-                            @SuppressWarnings("unused") //$NON-NLS-1$
-                            int sdkRelease = Integer.parseInt(m.group(3));
-                            
-                            if (platformMajor != 0 || platformMinor != 9) {
-                                return errorHandler.handleError(String.format(
-                                        "This version of ADT requires the Android SDK version 0.9\n\nCurrent version is %1$s.\n\nPlease update your SDK to the latest version.",
-                                        plugin.mSdkBuildVersion));
-                            }
-                        } else {
-                            // unknown version format.
-                            AdtPlugin.printErrorToConsole(
-                                    (Object)String.format(Messages.VersionCheck_Unable_To_Parse_Version_s,
-                                            plugin.mSdkBuildVersion));
-                        }
-                    }
-                    */
-                    break;
-                }
-            }
-        } catch (FileNotFoundException e) {
-            // the build id will be null, and this is handled by the builders.
-        } catch (IOException e) {
-            // the build id will be null, and this is handled by the builders.
-        }
+        String osLibs = osSdkPath + SdkConstants.OS_SDK_TOOLS_LIB_FOLDER;
 
         // get the plugin property file, and grab the minimum plugin version required
         // to work with the sdk
@@ -128,7 +63,7 @@
         int minMinorVersion = -1;
         int minMicroVersion = -1;
         try {
-            FileReader reader = new FileReader(osLibs + AndroidConstants.FN_PLUGIN_PROP);
+            FileReader reader = new FileReader(osLibs + SdkConstants.FN_PLUGIN_PROP);
             BufferedReader bReader = new BufferedReader(reader);
             String line;
             while ((line = bReader.readLine()) != null) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java
index 0b1b647..4d16120 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java
@@ -19,6 +19,8 @@
 import com.android.ide.eclipse.adt.AdtConstants;
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.BaseProjectHelper;
 import com.android.jarutils.DebugKeyProvider;
@@ -28,6 +30,7 @@
 import com.android.jarutils.DebugKeyProvider.KeytoolException;
 import com.android.jarutils.SignedJarBuilder.IZipEntryFilter;
 import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
@@ -44,6 +47,7 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
@@ -296,6 +300,15 @@
         saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources);
         saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage);
 
+        // At this point, we can abort the build if we have to, as we have computed
+        // our resource delta and stored the result.
+        
+        // check if we have finished loading the SDK.
+        if (AdtPlugin.getDefault().getSdkLoadStatus(javaProject) != LoadStatus.LOADED) {
+            // we exit silently
+            return referencedProjects;
+        }
+
         // Now check the compiler compliance level, not displaying the error
         // message since this is not the first builder.
         if (ProjectHelper.checkCompilerCompliance(getProject())
@@ -502,7 +515,8 @@
             commandArray.add(osAssetsPath);
         }
         commandArray.add("-I"); //$NON-NLS-1$
-        commandArray.add(AdtPlugin.getOsAbsoluteFramework());
+        commandArray.add(
+                Sdk.getCurrent().getTarget(project).getPath(IAndroidTarget.ANDROID_JAR));
         commandArray.add("-F"); //$NON-NLS-1$
         commandArray.add(osOutFilePath);
 
@@ -584,16 +598,9 @@
         DexWrapper wrapper = DexWrapper.getWrapper();
         
         if (wrapper == null) {
-            if (DexWrapper.getStatus() == DexWrapper.LoadStatus.FAILED) {
+            if (DexWrapper.getStatus() == LoadStatus.FAILED) {
                 throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
                         Messages.ApkBuilder_UnableBuild_Dex_Not_loaded));
-            } else {
-                // means we haven't loaded the dex jar yet.
-                // We set the project to be recompiled after dex is loaded. 
-                AdtPlugin.getDefault().addPostDexProject(javaProject);
-                
-                // and we exit silently
-                return false;
             }
         }
 
@@ -677,7 +684,7 @@
             }
             
             // TODO: get the store type from somewhere else.
-            DebugKeyProvider provider = new DebugKeyProvider(null /* storeType */,
+            DebugKeyProvider provider = new DebugKeyProvider(osKeyPath, null /* storeType */,
                     new IKeyGenOutput() {
                         public void err(String message) {
                             AdtPlugin.printErrorToConsole(javaProject.getProject(),
@@ -747,9 +754,18 @@
                 }
             }
 
+            // now write the native libraries.
+            // First look if the lib folder is there.
+            IResource libFolder = javaProject.getProject().findMember(
+                    AndroidConstants.FD_NATIVE_LIBS);
+            if (libFolder != null && libFolder.exists() &&
+                    libFolder.getType() == IResource.FOLDER) {
+                // look inside and put .so in lib/* by keeping the relative folder path.
+                writeNativeLibraries(libFolder.getFullPath().segmentCount(), builder, libFolder);
+            }
+
             // close the jar file and write the manifest and sign it.
             builder.close();
-
         } catch (GeneralSecurityException e1) {
             // mark project and return
             String msg = String.format(Messages.Final_Archive_Error_s, e1.getMessage());
@@ -784,6 +800,12 @@
 
             // and also output it in the console
             AdtPlugin.printErrorToConsole(javaProject.getProject(), msg);
+        } catch (CoreException e) {
+            // mark project and return
+            String msg = String.format(Messages.Final_Archive_Error_s, e.getMessage());
+            AdtPlugin.printErrorToConsole(javaProject.getProject(), msg);
+            markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
+            return false;
         } finally {
             if (fos != null) {
                 try {
@@ -798,6 +820,48 @@
     }
     
     /**
+     * Writes native libraries into a {@link SignedJarBuilder}.
+     * <p/>This recursively go through folder and writes .so files. 
+     * The path in the archive is based on the root folder containing the libraries in the project.
+     * Its segment count is passed to the method to compute the resources path relative to the root
+     * folder.
+     * Native libraries in the archive must be in a "lib" folder. Everything in the project native
+     * lib folder directly goes in this "lib" folder in the archive.
+     * 
+     *  
+     * @param rooSegmentCount The number of segment of the path of the folder containing the
+     * libraries. This is used to compute the path in the archive.
+     * @param jarBuilder the {@link SignedJarBuilder} used to create the archive.
+     * @param resource the IResource to write.
+     * @throws CoreException
+     * @throws IOException 
+     */
+    private void writeNativeLibraries(int rootSegmentCount, SignedJarBuilder jarBuilder,
+            IResource resource) throws CoreException, IOException {
+        if (resource.getType() == IResource.FILE) {
+            IPath path = resource.getFullPath();
+
+            // check the extension.
+            if (path.getFileExtension().equalsIgnoreCase(AndroidConstants.EXT_NATIVE_LIB)) {
+                // remove the first segment to build the path inside the archive.
+                path = path.removeFirstSegments(rootSegmentCount);
+                
+                // add it to the archive.
+                IPath apkPath = new Path(AndroidConstants.FD_APK_NATIVE_LIBS);
+                apkPath = apkPath.append(path);
+                
+                // writes the file in the apk.
+                jarBuilder.writeFile(resource.getLocation().toFile(), apkPath.toString());
+            }
+        } else if (resource.getType() == IResource.FOLDER) {
+            IResource[] members = ((IFolder)resource).members();
+            for (IResource member : members) {
+                writeNativeLibraries(rootSegmentCount, jarBuilder, member);
+            }
+        }
+    }
+
+    /**
      * Writes the standard resources of a project and its referenced projects
      * into a {@link SignedJarBuilder}.
      * Standard resources are non java/aidl files placed in the java package folders.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java
index fb60fdb..47ef626 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java
@@ -42,6 +42,7 @@
  * <li>Any change to the classes.dex inside the output folder</li>
  * <li>Any change to the packaged resources file inside the output folder</li>
  * <li>Any change to a non java/aidl file inside the source folders</li>
+ * <li>Any change to .so file inside the lib (native library) folder</li>
  * </ul>
  */
 public class ApkDeltaVisitor extends BaseDeltaVisitor
@@ -79,6 +80,8 @@
 
     private IPath mResPath;
 
+    private IPath mLibFolder;
+
     /**
      * Builds the object with a specified output folder.
      * @param builder the xml builder using this object to visit the
@@ -104,6 +107,11 @@
         if (resFolder != null) {
             mResPath = resFolder.getFullPath();
         }
+        
+        IResource libFolder = builder.getProject().findMember(AndroidConstants.FD_NATIVE_LIBS);
+        if (libFolder != null) {
+            mLibFolder = libFolder.getFullPath();
+        }
     }
 
     public boolean getConvertToDex() {
@@ -161,6 +169,7 @@
         
         // check the other folders.
         if (mOutputPath != null && mOutputPath.isPrefixOf(path)) {
+            // a resource changed inside the output folder.
             if (type == IResource.FILE) {
                 // just check this is a .class file. Any modification will
                 // trigger a change in the classes.dex file
@@ -217,6 +226,17 @@
             mPackageResources = true;
             mMakeFinalPackage = true;
             return false;
+        } else if (mLibFolder != null && mLibFolder.isPrefixOf(path)) {
+            // inside the native library folder. Test if the changed resource is a .so file.
+            if (type == IResource.FILE &&
+                    path.getFileExtension().equalsIgnoreCase(AndroidConstants.EXT_NATIVE_LIB)) {
+                mMakeFinalPackage = true;
+                return false; // return false for file.
+            }
+
+            // for folders, return true only if we don't already know we have to make the
+            // final package.
+            return mMakeFinalPackage == false;
         } else {
             // we are in a folder that is neither the resource folders, nor the output.
             // check against all the source folders, unless we already know we need to do
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
index f79be3d..f94bdc7 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
@@ -806,12 +806,6 @@
                     // get the IPath
                     IPath path = e.getPath();
 
-                    // get the file name. if it's the framework jar, we ignore that file.
-                    // since we now use classpath container, this is here for legacy purpose only.
-                    if (AndroidConstants.FN_FRAMEWORK_LIBRARY.equals(path.lastSegment())) {
-                        continue;
-                    }
-
                     // check the name ends with .jar
                     if (AndroidConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
                         boolean local = false;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java
index 9ba4026..cba8ad7 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java
@@ -17,6 +17,7 @@
 package com.android.ide.eclipse.adt.build;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
 
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IStatus;
@@ -47,9 +48,6 @@
     
     private static DexWrapper sWrapper;
 
-    /** Status for the Loading of the dex jar file */
-    public enum LoadStatus { LOADING, LOADED, FAILED }
-    
     private static LoadStatus sLoadStatus = LoadStatus.LOADING;
 
     private Method mRunMethod;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
index 850a79a..1a4aa8c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
@@ -18,14 +18,16 @@
 
 import com.android.ide.eclipse.adt.AdtConstants;
 import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor;
 import com.android.ide.eclipse.adt.project.FixLaunchConfig;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidManifestHelper;
 import com.android.ide.eclipse.common.project.AndroidManifestParser;
 import com.android.ide.eclipse.common.project.BaseProjectHelper;
 import com.android.ide.eclipse.common.project.XmlErrorHandler.BasicXmlErrorListener;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
@@ -44,7 +46,6 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.ui.ide.IDE;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -130,7 +131,6 @@
                             mSource);
                     try {
                         mNewFile.setDerived(true);
-                        IDE.setDefaultEditor(mNewFile, ReadOnlyJavaEditor.ID);
                     } catch (CoreException e) {
                         // This really shouldn't happen since we check that the resource exist.
                         // Worst case scenario, the resource isn't marked as derived.
@@ -266,8 +266,14 @@
 
                 // record the state
                 mCompileResources |= dv.getCompileResources();
-                mergeAidlFileModifications(dv.getAidlToCompile(),
-                        dv.getAidlToRemove());
+                
+                // handle aidl modification
+                if (dv.getFullAidlRecompilation()) {
+                    buildAidlCompilationList(project, sourceList);
+                } else {
+                    mergeAidlFileModifications(dv.getAidlToCompile(),
+                            dv.getAidlToRemove());
+                }
 
                 // if there was some XML errors, we just return w/o doing
                 // anything since we've put some markers in the files anyway.
@@ -290,6 +296,12 @@
         // At this point we have stored what needs to be build, so we can
         // do some high level test and abort if needed.
 
+        // check if we have finished loading the SDK.
+        if (AdtPlugin.getDefault().getSdkLoadStatus(javaProject) != LoadStatus.LOADED) {
+            // we exit silently
+            return null;
+        }
+
         // check the compiler compliance level, not displaying the error message
         // since this is not the first builder.
         if (ProjectHelper.checkCompilerCompliance(getProject())
@@ -302,13 +314,19 @@
         // Check that the SDK directory has been setup.
         String osSdkFolder = AdtPlugin.getOsSdkFolder();
 
-        if (osSdkFolder.length() == 0) {
+        if (osSdkFolder == null || osSdkFolder.length() == 0) {
             AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
                     Messages.No_SDK_Setup_Error);
             markProject(AdtConstants.MARKER_ADT, Messages.No_SDK_Setup_Error,
                     IMarker.SEVERITY_ERROR);
             return null;
         }
+        
+        IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
+        if (projectTarget == null) {
+            // no target. error has been output by the container initializer: exit silently.
+            return null;
+        }
 
         // get the manifest file
         IFile manifest = AndroidManifestHelper.getManifest(project);
@@ -448,7 +466,7 @@
                 array.add("-S"); //$NON-NLS-1$
                 array.add(osResPath);
                 array.add("-I"); //$NON-NLS-1$
-                array.add(AdtPlugin.getOsAbsoluteFramework());
+                array.add(projectTarget.getPath(IAndroidTarget.ANDROID_JAR));
 
                 if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
                     StringBuilder sb = new StringBuilder();
@@ -563,6 +581,8 @@
             deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
                     mManifestPackageSourceFolder, mManifestPackage);
         }
+        
+        // FIXME: delete all java generated from aidl.
     }
 
     @Override
@@ -736,12 +756,14 @@
         if (mAidlToCompile.size() == 0 && mAidlToRemove.size() == 0) {
             return false;
         }
+        
 
         // create the command line
         String[] command = new String[4 + sourceFolders.size() + (folderAidlPath != null ? 1 : 0)];
         int index = 0;
+        int aidlIndex;
         command[index++] = AdtPlugin.getOsAbsoluteAidl();
-        command[index++] = "-p" + AdtPlugin.getOsAbsoluteFrameworkAidl(); //$NON-NLS-1$
+        command[aidlIndex = index++] = "-p"; //$NON-NLS-1$
         if (folderAidlPath != null) {
             command[index++] = "-p" + folderAidlPath; //$NON-NLS-1$
         }
@@ -813,6 +835,8 @@
             prepareFileForExternalModification(javaFile);
 
             // finish to set the command line.
+            command[aidlIndex] = "-p" + Sdk.getCurrent().getTarget(aidlFile.getProject()).getPath(
+                    IAndroidTarget.ANDROID_AIDL); //$NON-NLS-1$
             command[index] = osPath;
             command[index + 1] = osJavaPath;
 
@@ -922,7 +946,8 @@
     }
 
     /**
-     * Goes through the buildpath and fills the list of aidl files to compile.
+     * Goes through the build paths and fills the list of aidl files to compile
+     * ({@link #mAidlToCompile}).
      * @param project The project.
      * @param buildPaths The list of build paths.
      */
@@ -977,7 +1002,7 @@
                        scanContainerForAidl((IFolder)r);
                        break;
                    default:
-                       // this would mean it's a project or the workspaceroot
+                       // this would mean it's a project or the workspace root
                        // which is unlikely to happen. we do nothing
                        break;
                }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
index 9c3bc5c..33d5fa6 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
@@ -42,6 +42,7 @@
 class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
         IResourceDeltaVisitor {
 
+    // Result fields.
     /**
      * Compile flag. This is set to true if one of the changed/added/removed
      * file is a resource file. Upon visiting all the delta resources, if
@@ -50,6 +51,22 @@
      */
     private boolean mCompileResources = false;
 
+    /** List of .aidl files found that are modified or new. */
+    private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
+
+    /** List of .aidl files that have been removed. */
+    private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
+    
+    /** Aidl forced recompilation flag. This is set to true if project.aidl is modified. */
+    private boolean mFullAidlCompilation = false;
+
+    /** Manifest check/parsing flag. */
+    private boolean mCheckedManifestXml = false;
+
+    /** Application Pacakge, gathered from the parsing of the manifest */
+    private String mJavaPackage = null;
+
+    // Internal usage fields.
     /**
      * In Resource folder flag. This allows us to know if we're in the
      * resource folder.
@@ -65,14 +82,6 @@
     /** List of source folders. */
     private ArrayList<IPath> mSourceFolders;
 
-    /** List of .aidl files found that are modified or new. */
-    private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
-
-    /** List of .aidl files that have been removed. */
-    private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
-
-    private boolean mCheckedManifestXml = false;
-    private String mJavaPackage = null;
 
     public PreCompilerDeltaVisitor(BaseBuilder builder, ArrayList<IPath> sourceFolders) {
         super(builder);
@@ -90,6 +99,10 @@
     public ArrayList<IFile> getAidlToRemove() {
         return mAidlToRemove;
     }
+    
+    public boolean getFullAidlRecompilation() {
+        return mFullAidlCompilation;
+    }
 
     /**
      * Returns whether the manifest file was parsed/checked for error during the resource delta
@@ -100,7 +113,7 @@
     }
     
     /**
-     * Returns the manifest package if the manifest was checked.
+     * Returns the manifest package if the manifest was checked/parsed.
      * <p/>
      * This can return null in two cases:
      * <ul>
@@ -169,11 +182,14 @@
                 // we don't want to go to the children, not like they are
                 // any for this resource anyway.
                 return false;
+            } else if (AndroidConstants.FN_PROJECT_AIDL.equalsIgnoreCase(segments[1])) {
+                // need to force recompilation of all the aidl files
+                mFullAidlCompilation = true;
             }
         }
 
         // at this point we can either be in the source folder or in the
-        // resource foler or in a different folder that contains a source
+        // resource folder or in a different folder that contains a source
         // folder.
         // This is due to not all source folder being src/. Some could be
         // something/somethingelse/src/
@@ -227,7 +243,8 @@
                                     PreCompilerBuilder.PROPERTY_ANDROID_CONFLICT, true);
                         }
 
-                        // we add it anyway so that we can try to compile it every time.
+                        // we add it anyway so that we can try to compile it at every compilation
+                        // until the conflict is fixed.
                         mAidlToCompile.add(file);
 
                     } else {
@@ -245,6 +262,8 @@
 
             boolean outputMessage = false;
 
+            // Special case of R.java/Manifest.java.
+            // FIXME: This does not check the package. Any modification of R.java/Manifest.java in another project will trigger a new recompilation of the resources.
             if (AndroidConstants.FN_RESOURCE_CLASS.equals(fileName) ||
                     AndroidConstants.FN_MANIFEST_CLASS.equals(fileName)) {
                 // if it was removed, there's a possibility that it was removed due to a
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
index 1de1438..1219aac 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
@@ -62,13 +62,10 @@
         switch (res) {
             case ProjectHelper.COMPILER_COMPLIANCE_LEVEL:
                 errorMessage = Messages.Requires_Compiler_Compliance_5;
-                return null;
             case ProjectHelper.COMPILER_COMPLIANCE_SOURCE:
                 errorMessage = Messages.Requires_Source_Compatibility_5;
-                return null;
             case ProjectHelper.COMPILER_COMPLIANCE_CODEGEN_TARGET:
                 errorMessage = Messages.Requires_Class_Compatibility_5;
-                return null;
         }
 
         if (errorMessage != null) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
index 10be077..48ec7c3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
@@ -30,9 +30,9 @@
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.debug.launching.DeviceChooserDialog.DeviceChooserResponse;
 import com.android.ide.eclipse.adt.debug.ui.EmulatorConfigTab;
-import com.android.ide.eclipse.adt.debug.ui.SkinRepository;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
 import com.android.ide.eclipse.common.project.AndroidManifestHelper;
+import com.android.sdklib.SdkConstants;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
@@ -102,6 +102,9 @@
         /** Debuggable attribute of the manifest file. */
         Boolean mDebuggable = null;
         
+        /** Required ApiVersionNumber by the app. 0 means no requirements */
+        int mRequiredApiVersionNumber = 0;
+        
         InstallRetryMode mRetryMode = InstallRetryMode.NEVER;
         
         /**
@@ -126,8 +129,8 @@
 
         /** Basic constructor with activity and package info. */
         public DelayedLaunchInfo(IProject project, String packageName, String activity,
-                IFile pack, Boolean debuggable, int launchAction, AndroidLaunch launch,
-                IProgressMonitor monitor) {
+                IFile pack, Boolean debuggable, int requiredApiVersionNumber, int launchAction,
+                AndroidLaunch launch, IProgressMonitor monitor) {
             mProject = project;
             mPackageName = packageName;
             mActivity = activity;
@@ -136,6 +139,7 @@
             mLaunch = launch;
             mMonitor = monitor;
             mDebuggable = debuggable;
+            mRequiredApiVersionNumber = requiredApiVersionNumber;
         }
     }
     
@@ -256,13 +260,10 @@
             try {
                 mSkin = config.getAttribute(LaunchConfigDelegate.ATTR_SKIN, mSkin);
                 if (mSkin == null) {
-                    mSkin = SkinRepository.getInstance().checkSkin(
-                            LaunchConfigDelegate.DEFAULT_SKIN);
-                } else {
-                    mSkin = SkinRepository.getInstance().checkSkin(mSkin);
+                    mSkin = SdkConstants.SKIN_DEFAULT;
                 }
             } catch (CoreException e) {
-                mSkin = SkinRepository.getInstance().checkSkin(LaunchConfigDelegate.DEFAULT_SKIN);
+                mSkin = SdkConstants.SKIN_DEFAULT;
             }
 
             int index = LaunchConfigDelegate.DEFAULT_SPEED;
@@ -539,7 +540,7 @@
                         LaunchConfigDelegate.DEFAULT_DELAY);
                 
                 // default skin
-                wc.setAttribute(LaunchConfigDelegate.ATTR_SKIN, LaunchConfigDelegate.DEFAULT_SKIN);
+                wc.setAttribute(LaunchConfigDelegate.ATTR_SKIN, SdkConstants.SKIN_DEFAULT);
                 
                 // default wipe data mode
                 wc.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA,
@@ -599,13 +600,14 @@
      *      defined by <code>ILaunchManager</code> - <code>RUN_MODE</code> or
      *      <code>DEBUG_MODE</code>.
      * @param apk the resource to the apk to launch.
-     * @param debuggable 
+     * @param debuggable the debuggable value of the app, or null if not set.
+     * @param requiredApiVersionNumber the api version required by the app, or -1 if none.
      * @param activity the class to provide to am to launch
      * @param config the launch configuration
      * @param launch the launch object
      */
     public void launch(final IProject project, String mode, IFile apk,
-            String packageName, Boolean debuggable, String activity,
+            String packageName, Boolean debuggable, int requiredApiVersionNumber, String activity,
             final AndroidLaunchConfiguration config, final AndroidLaunch launch,
             IProgressMonitor monitor) {
         
@@ -619,7 +621,8 @@
 
         // create the launch info
         final DelayedLaunchInfo launchInfo = new DelayedLaunchInfo(project, packageName,
-                activity, apk, debuggable, config.mLaunchAction, launch, monitor);
+                activity, apk, debuggable, requiredApiVersionNumber, config.mLaunchAction,
+                launch, monitor);
 
         // set the debug mode
         launchInfo.mDebugMode = mode.equals(ILaunchManager.DEBUG_MODE);
@@ -711,6 +714,7 @@
             
                             // stop the launch and return
                             mWaitingForEmulatorLaunches.remove(launchInfo);
+                            AdtPlugin.printErrorToConsole(project, "Launch canceled!");
                             launch.stopLaunch();
                             return;
                         }
@@ -761,31 +765,63 @@
         }
     }
     
-    private void checkBuildInfo(DelayedLaunchInfo launchInfo, Device device) {
+    /**
+     * Checks the build information, and returns whether the launch should continue.
+     * <p/>The value tested are:
+     * <ul>
+     * <li>Minimum API version requested by the application. If the target device does not match,
+     * the launch is canceled.</li>
+     * <li>Debuggable attribute of the application and whether or not the device requires it. If
+     * the device requires it and it is not set in the manifest, the launch will be forced to
+     * "release" mode instead of "debug"</li>
+     * <ul>
+     * @param launchInfo
+     * @param device
+     * @return
+     */
+    private boolean checkBuildInfo(DelayedLaunchInfo launchInfo, Device device) {
         if (device != null) {
-            // get the SDK build
-            String sdkBuild = AdtPlugin.getSdkApiVersion();
-
-            // can only complain if the sdkBuild is known
-            if (sdkBuild != null) {
-                
-                String deviceVersion = device.getProperty(Device.PROP_BUILD_VERSION);
-
-                if (deviceVersion == null) {
-                    AdtPlugin.printToConsole(launchInfo.mProject, "WARNING: Unknown device API version!");
-                } else {
-                    if (sdkBuild.equals(deviceVersion) == false) {
-                        // TODO do a proper check, including testing the content of the uses-sdk string in the manifest to detect real incompatibility.
-                        String msg = String.format(
-                                "WARNING: Device API version (%1$s) does not match SDK API version (%2$s)",
-                                deviceVersion, sdkBuild);
-                        AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
-                    }
-                }
-            } else {
-                AdtPlugin.printToConsole(launchInfo.mProject, "WARNING: Unknown SDK API version!");
+            // check the app required API level versus the target device API level
+            
+            String deviceApiVersionName = device.getProperty(Device.PROP_BUILD_VERSION);
+            String value = device.getProperty(Device.PROP_BUILD_VERSION_NUMBER);
+            int deviceApiVersionNumber = 0;
+            try {
+                deviceApiVersionNumber = Integer.parseInt(value);
+            } catch (NumberFormatException e) {
+                // pass, we'll keep the deviceVersionNumber value at 0.
             }
             
+            if (launchInfo.mRequiredApiVersionNumber == 0) {
+                // warn the API level requirement is not set.
+                AdtPlugin.printErrorToConsole(launchInfo.mProject,
+                        "WARNING: Application does not specify an API level requirement!");
+
+                // and display the target device API level (if known)
+                if (deviceApiVersionName == null || deviceApiVersionNumber == 0) {
+                    AdtPlugin.printErrorToConsole(launchInfo.mProject,
+                            "WARNING: Unknown device API version!");
+                } else {
+                    AdtPlugin.printErrorToConsole(launchInfo.mProject, String.format(
+                            "Device API version is %1$d (Android %2$s)", deviceApiVersionNumber,
+                            deviceApiVersionName));
+                }
+            } else { // app requires a specific API level
+                if (deviceApiVersionName == null || deviceApiVersionNumber == 0) {
+                    AdtPlugin.printToConsole(launchInfo.mProject,
+                            "WARNING: Unknown device API version!");
+                } else if (deviceApiVersionNumber < launchInfo.mRequiredApiVersionNumber) {
+                    String msg = String.format(
+                            "ERROR: Application requires API version %1$d. Device API version is %2$d (Android %3$s).",
+                            launchInfo.mRequiredApiVersionNumber, deviceApiVersionNumber,
+                            deviceApiVersionName);
+                    AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
+                    
+                    // abort the launch
+                    return false;
+                }
+            }
+
             // now checks that the device/app can be debugged (if needed)
             if (device.isEmulator() == false && launchInfo.mDebugMode) {
                 String debuggableDevice = device.getProperty(Device.PROP_DEBUGGABLE);
@@ -818,6 +854,8 @@
                 }
             }
         }
+        
+        return true;
     }
 
     /**
@@ -829,10 +867,16 @@
      * @return true if succeed
      */
     private boolean simpleLaunch(DelayedLaunchInfo launchInfo, Device device) {
-        checkBuildInfo(launchInfo, device);
+        // API level check
+        if (checkBuildInfo(launchInfo, device) == false) {
+            AdtPlugin.printErrorToConsole(launchInfo.mProject, "Launch canceled!");
+            launchInfo.mLaunch.stopLaunch();
+            return false;
+        }
 
         // sync the app
         if (syncApp(launchInfo, device) == false) {
+            AdtPlugin.printErrorToConsole(launchInfo.mProject, "Launch canceled!");
             launchInfo.mLaunch.stopLaunch();
             return false;
         }
@@ -1127,6 +1171,8 @@
         } catch (IOException e) {
             // something went wrong trying to launch the app.
             // lets stop the Launch
+            AdtPlugin.printErrorToConsole(info.mProject,
+                    String.format("Launch error: %s", e.getMessage()));
             info.mLaunch.stopLaunch();
 
             // and remove it from the list of app waiting for debuggers
@@ -1139,25 +1185,20 @@
     private boolean launchEmulator(AndroidLaunchConfiguration config) {
 
         // split the custom command line in segments
-        String[] segs;
+        ArrayList<String> customArgs = new ArrayList<String>();
         boolean has_wipe_data = false;
         if (config.mEmulatorCommandLine != null && config.mEmulatorCommandLine.length() > 0) {
-            segs = config.mEmulatorCommandLine.split("\\s+"); //$NON-NLS-1$
+            String[] segments = config.mEmulatorCommandLine.split("\\s+"); //$NON-NLS-1$
 
             // we need to remove the empty strings
-            ArrayList<String> array = new ArrayList<String>();
-            for (String s : segs) {
+            for (String s : segments) {
                 if (s.length() > 0) {
-                    array.add(s);
+                    customArgs.add(s);
                     if (!has_wipe_data && s.equals(FLAG_WIPE_DATA)) {
                         has_wipe_data = true;
                     }
                 }
             }
-
-            segs = array.toArray(new String[array.size()]);
-        } else {
-            segs = new String[0];
         }
 
         boolean needs_wipe_data = config.mWipeData && !has_wipe_data;
@@ -1167,29 +1208,37 @@
             }
         }
         
-        boolean needs_no_boot_anim = config.mNoBootAnim;
+        // build the command line based on the available parameters.
+        ArrayList<String> list = new ArrayList<String>();
+
+        list.add(AdtPlugin.getOsAbsoluteEmulator());
+        if (config.mSkin != null) {
+            list.add(FLAG_SKIN);
+            list.add(config.mSkin);
+        }
         
-        // get the command line
-        String[] command = new String[7 + segs.length +
-                                      (needs_wipe_data ? 1 : 0) +
-                                      (needs_no_boot_anim ? 1 : 0)];
-        int index = 0;
-        command[index++] = AdtPlugin.getOsAbsoluteEmulator();
-        command[index++] = FLAG_SKIN; //$NON-NLS-1$
-        command[index++] = config.mSkin;
-        command[index++] = FLAG_NETSPEED; //$NON-NLS-1$
-        command[index++] = config.mNetworkSpeed;
-        command[index++] = FLAG_NETDELAY; //$NON-NLS-1$
-        command[index++] = config.mNetworkDelay;
+        if (config.mNetworkSpeed != null) {
+            list.add(FLAG_NETSPEED);
+            list.add(config.mNetworkSpeed);
+        }
+        
+        if (config.mNetworkDelay != null) {
+            list.add(FLAG_NETDELAY);
+            list.add(config.mNetworkDelay);
+        }
+        
         if (needs_wipe_data) {
-            command[index++] = FLAG_WIPE_DATA;
+            list.add(FLAG_WIPE_DATA);
         }
-        if (needs_no_boot_anim) {
-            command[index++] = FLAG_NO_BOOT_ANIM;
+
+        if (config.mNoBootAnim) {
+            list.add(FLAG_NO_BOOT_ANIM);
         }
-        for (String s : segs) {
-            command[index++] = s;
-        }
+
+        list.addAll(customArgs);
+        
+        // convert the list into an array for the call to exec.
+        String[] command = list.toArray(new String[list.size()]);
 
         // launch the emulator
         try {
@@ -1278,12 +1327,11 @@
     /**
      * Launch a new thread that connects a remote debugger on the specified port.
      * @param debugPort The port to connect the debugger to
-     * @param launch The associated AndroidLaunch object.
+     * @param androidLaunch The associated AndroidLaunch object.
      * @param monitor A Progress monitor
      * @see connectRemoveDebugger()
      */
-    public static void launchRemoteDebugger(final ILaunchConfiguration config,
-            final int debugPort, final AndroidLaunch androidLaunch,
+    public static void launchRemoteDebugger( final int debugPort, final AndroidLaunch androidLaunch,
             final IProgressMonitor monitor) {
         new Thread("Debugger connection") { //$NON-NLS-1$
             @Override
@@ -1342,13 +1390,14 @@
         synchronized (sListLock) {
             // look if there's an app waiting for a device
             if (mWaitingForEmulatorLaunches.size() > 0) {
-                // remove first item from the list
+                // get/remove first launch item from the list
+                // FIXME: what if we have multiple launches waiting?
                 DelayedLaunchInfo launchInfo = mWaitingForEmulatorLaunches.get(0);
                 mWaitingForEmulatorLaunches.remove(0);
-                
-                // give it its device
+
+                // give the launch item its device for later use.
                 launchInfo.mDevice = device;
-                
+
                 // and move it to the other list
                 mWaitingForReadyEmulatorList.add(launchInfo);
                 
@@ -1433,12 +1482,23 @@
                     
                     // look for application waiting for home
                     synchronized (sListLock) {
-                        boolean foundMatch = false;
                         for (int i = 0 ; i < mWaitingForReadyEmulatorList.size() ;) {
                             DelayedLaunchInfo launchInfo = mWaitingForReadyEmulatorList.get(i);
                             if (launchInfo.mDevice == device) {
                                 // it's match, remove from the list
                                 mWaitingForReadyEmulatorList.remove(i);
+                                
+                                // We couldn't check earlier the API level of the device
+                                // (it's asynchronous when the device boot, and usually
+                                // deviceConnected is called before it's queried for its build info)
+                                // so we check now
+                                if (checkBuildInfo(launchInfo, device) == false) {
+                                    // device is not the proper API!
+                                    AdtPlugin.printErrorToConsole(launchInfo.mProject,
+                                            "Launch canceled!");
+                                    launchInfo.mLaunch.stopLaunch();
+                                    return;
+                                }
         
                                 AdtPlugin.printToConsole(launchInfo.mProject,
                                         String.format("HOME is up on device '%1$s'",
@@ -1448,16 +1508,14 @@
                                 if (syncApp(launchInfo, device)) {
                                     // application package is sync'ed, lets attempt to launch it.
                                     launchApp(launchInfo, device);
-                                    
-                                    // if we haven't checked the device build info, lets do it here
-                                    if (foundMatch == false) {
-                                        foundMatch = true;
-                                        checkBuildInfo(launchInfo, device);
-                                    }
                                 } else {
                                     // failure! Cancel and return
+                                    AdtPlugin.printErrorToConsole(launchInfo.mProject,
+                                    "Launch canceled!");
                                     launchInfo.mLaunch.stopLaunch();
                                 }
+                                
+                                break;
                             } else {
                                 i++;
                             }
@@ -1530,6 +1588,8 @@
                                     }
                                 } catch (CoreException e) {
                                     // well something went wrong.
+                                    AdtPlugin.printErrorToConsole(launchInfo.mProject,
+                                            String.format("Launch error: %s", e.getMessage()));
                                     // stop the launch
                                     launchInfo.mLaunch.stopLaunch();
                                 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
index e5ccb2b..5d3e349 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
@@ -83,11 +83,6 @@
     /** Skin to be used to launch the emulator */
     public static final String ATTR_SKIN = AdtPlugin.PLUGIN_ID + ".skin"; //$NON-NLS-1$
 
-    /**
-     * Name of the default Skin.
-     */
-    public static final String DEFAULT_SKIN = "HVGA"; //$NON-NLS-1$
-
     public static final String ATTR_SPEED = AdtPlugin.PLUGIN_ID + ".speed"; //$NON-NLS-1$
 
     /**
@@ -138,8 +133,7 @@
         // if we have a valid debug port, this means we're debugging an app
         // that's already launched.
         if (debugPort != INVALID_DEBUG_PORT) {
-            AndroidLaunchController.launchRemoteDebugger(configuration,
-                    debugPort, androidLaunch, monitor);
+            AndroidLaunchController.launchRemoteDebugger(debugPort, androidLaunch, monitor);
             return;
         }
 
@@ -302,7 +296,8 @@
         // everything seems fine, we ask the launch controller to handle
         // the rest
         controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
-                manifestParser.getDebuggable(), activityName, config, androidLaunch, monitor);
+                manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
+                activityName, config, androidLaunch, monitor);
     }
     
     @Override
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
index 1d36add..c7b340c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
@@ -18,13 +18,19 @@
 
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate;
-import com.android.ide.eclipse.adt.debug.ui.SkinRepository.Skin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.ide.eclipse.common.project.BaseProjectHelper;
 import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
 import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ModifyEvent;
@@ -82,6 +88,8 @@
 
     private Button mNoBootAnimButton;
 
+    private IAndroidTarget mTarget;
+
     /**
      * Returns the emulator ready speed option value.
      * @param value The index of the combo selection.
@@ -169,12 +177,6 @@
         new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Screen Size:");
 
         mSkinCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY);
-        Skin[] skins = SkinRepository.getInstance().getSkins();
-        if (skins != null) {
-            for (Skin skin : skins) {
-                mSkinCombo.add(skin.getDescription());
-            }
-        }
         mSkinCombo.addSelectionListener(new SelectionAdapter() {
             // called when selection changes
             @Override
@@ -182,7 +184,6 @@
                 updateLaunchConfigurationDialog();
             }
         });
-        mSkinCombo.pack();
 
         // network options
         new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Speed:");
@@ -287,6 +288,42 @@
         }
         mAutoTargetButton.setSelection(value);
         mManualTargetButton.setSelection(!value);
+        
+        // look for the project name to get its target.
+        String projectName = "";
+        try {
+            projectName = configuration.getAttribute(
+                    IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectName);
+        } catch (CoreException ce) {
+        }
+
+        IProject project = null;
+
+        // get the list of existing Android projects from the workspace.
+        IJavaProject[] projects = BaseProjectHelper.getAndroidProjects();
+        if (projects != null) {
+            // look for the project whose name we read from the configuration.
+            for (IJavaProject p : projects) {
+                if (p.getElementName().equals(projectName)) {
+                    project = p.getProject();
+                    break;
+                }
+            }
+        }
+
+        mSkinCombo.removeAll();
+        if (project != null) {
+            mTarget = Sdk.getCurrent().getTarget(project);
+            if (mTarget != null) {
+                String[] skins = mTarget.getSkins();
+                if (skins != null) {
+                    for (String skin : skins) {
+                        mSkinCombo.add(skin);
+                    }
+                    mSkinCombo.pack();
+                }
+            }
+        }
 
         value = LaunchConfigDelegate.DEFAULT_WIPE_DATA;
         try {
@@ -307,16 +344,18 @@
         int index = -1;
         try {
             String skin = configuration.getAttribute(LaunchConfigDelegate.ATTR_SKIN, (String)null);
-            if (skin != null) {
-                index = getSkinIndex(skin);
+            if (skin == null) {
+                skin = SdkConstants.SKIN_DEFAULT;
             }
+
+            index = getSkinIndex(skin);
         } catch (CoreException e) {
-            index = getSkinIndex(SkinRepository.getInstance().checkSkin(
-                    LaunchConfigDelegate.DEFAULT_SKIN));
+            index = getSkinIndex(SdkConstants.SKIN_DEFAULT);
         }
 
         if (index == -1) {
-            mSkinCombo.clearSelection();
+            mSkinCombo.select(0);
+            updateLaunchConfigurationDialog();
         } else {
             mSkinCombo.select(index);
         }
@@ -387,7 +426,7 @@
         configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
                 LaunchConfigDelegate.DEFAULT_TARGET_MODE);
         configuration.setAttribute(LaunchConfigDelegate.ATTR_SKIN,
-                LaunchConfigDelegate.DEFAULT_SKIN);
+                SdkConstants.SKIN_DEFAULT);
         configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED,
                 LaunchConfigDelegate.DEFAULT_SPEED);
         configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY,
@@ -403,11 +442,31 @@
    }
 
     private String getSkinNameByIndex(int index) {
-        return SkinRepository.getInstance().getSkinNameByIndex(index);
+        if (mTarget != null && index > 0) {
+            String[] skins = mTarget.getSkins();
+            if (skins != null && index < skins.length) {
+                return skins[index];
+            }
+        }
+        
+        return null;
     }
 
     private int getSkinIndex(String name) {
-        return SkinRepository.getInstance().getSkinIndex(name);
+        if (mTarget != null) {
+            String[] skins = mTarget.getSkins();
+            if (skins != null) {
+                int index = 0;
+                for (String skin : skins) {
+                    if (skin.equalsIgnoreCase(name)) {
+                        return index;
+                    }
+                    index++;
+                }
+            }
+        }
+        
+        return -1;
     }
 
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java
deleted file mode 100644
index a813026..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/SkinRepository.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2007 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.debug.ui;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-
-import java.io.File;
-import java.util.ArrayList;
-
-/**
- * Repository for the emulator skins. This class is responsible for parsing the skin folder.
- */
-public class SkinRepository {
-
-    private final static SkinRepository sInstance = new SkinRepository();
-
-    private Skin[] mSkins;
-
-    public static class Skin {
-
-        String mName;
-
-        public Skin(String name) {
-            mName = name;
-        }
-
-        public String getName() {
-            return mName;
-        }
-
-        /**
-         * Returns the human readable description of the skin.
-         */
-        public String getDescription() {
-            // TODO: parse the skin and output the description.
-            return mName;
-        }
-    }
-
-    /**
-     * Returns the singleton instance.
-     */
-    public static SkinRepository getInstance() {
-        return sInstance;
-    }
-
-    /**
-     * Parse the skin folder and build the skin list.
-     * @param osPath The path of the skin folder.
-     */
-    public void parseFolder(String osPath) {
-        File skinFolder = new File(osPath);
-
-        if (skinFolder.isDirectory()) {
-            ArrayList<Skin> skinList = new ArrayList<Skin>();
-
-            File[] files = skinFolder.listFiles();
-
-            for (File skin : files) {
-                if (skin.isDirectory()) {
-                    // check for layout file
-                    File layout = new File(skin.getPath() + File.separator
-                            + AndroidConstants.FN_LAYOUT);
-
-                    if (layout.isFile()) {
-                        // for now we don't parse the content of the layout and
-                        // simply add the directory to the list.
-                        skinList.add(new Skin(skin.getName()));
-                    }
-                }
-            }
-
-            mSkins = skinList.toArray(new Skin[skinList.size()]);
-        } else {
-            mSkins = new Skin[0];
-        }
-    }
-
-    public Skin[] getSkins() {
-        return mSkins;
-    }
-
-    /**
-     * Returns a valid skin folder name. If <code>skin</code> is valid, then it is returned,
-     * otherwise the first valid skin name is returned.
-     * @param skin the Skin name to check
-     * @return a valid skin name or null if there aren't any.
-     */
-    public String checkSkin(String skin) {
-        if (mSkins != null) {
-            for (Skin s : mSkins) {
-                if (s.getName().equals(skin)) {
-                    return skin;
-                }
-            }
-
-            if (mSkins.length > 0) {
-                return mSkins[0].getName();
-            }
-        }
-
-        return null;
-    }
-
-
-    /**
-     * Returns the name of a skin by index.
-     * @param index The index of the skin to return
-     * @return the skin name of null if the index is invalid.
-     */
-    public String getSkinNameByIndex(int index) {
-        if (mSkins != null) {
-            if (index >= 0 && index < mSkins.length) {
-                return mSkins[index].getName();
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns the index (0 based) of the skin matching the name.
-     * @param name The name of the skin to look for.
-     * @return the index of the skin or -1 if the skin was not found.
-     */
-    public int getSkinIndex(String name) {
-        if (mSkins != null) {
-            int count = mSkins.length;
-            for (int i = 0 ; i < count ; i++) {
-                Skin s = mSkins[i];
-                if (s.mName.equals(name)) {
-                    return i;
-                }
-            }
-        }
-
-        return -1;
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java
deleted file mode 100644
index 1c9a569..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/editors/java/ReadOnlyJavaEditor.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 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.editors.java;
-
-import org.eclipse.jdt.ui.PreferenceConstants;
-import org.eclipse.jdt.ui.text.IJavaPartitions;
-import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration;
-import org.eclipse.jdt.ui.text.JavaTextTools;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
-
-/**
- * Read only java editors. This looks like the regular Java editor, except that it
- * prevents editing the files. This is used for automatically generated java classes.
- */
-public class ReadOnlyJavaEditor extends AbstractDecoratedTextEditor {
-    
-    public final static String ID =
-        "com.android.ide.eclipse.adt.editors.java.ReadOnlyJavaEditor"; //$NON-NLS-1$
-
-    public ReadOnlyJavaEditor() {
-        IPreferenceStore javaUiStore = PreferenceConstants.getPreferenceStore();
-        JavaTextTools jtt = new JavaTextTools(javaUiStore);
-
-        JavaSourceViewerConfiguration jsvc = new JavaSourceViewerConfiguration(
-                jtt.getColorManager(), javaUiStore, this,  IJavaPartitions.JAVA_PARTITIONING);
-
-        setSourceViewerConfiguration(jsvc);
-    }
-
-    @Override
-    public boolean isEditable() {
-        return false;
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java
index 136c0f3..434269c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/preferences/BuildPreferencePage.java
@@ -18,6 +18,9 @@
 
 import com.android.ide.eclipse.adt.AdtConstants;
 import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.jarutils.DebugKeyProvider;
+import com.android.jarutils.DebugKeyProvider.KeytoolException;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
 
 import org.eclipse.jface.preference.BooleanFieldEditor;
 import org.eclipse.jface.preference.FieldEditorPreferencePage;
@@ -29,6 +32,13 @@
 import org.eclipse.ui.IWorkbench;
 import org.eclipse.ui.IWorkbenchPreferencePage;
 
+import java.io.File;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
 /**
  * Preference page for build options.
  *
@@ -75,7 +85,7 @@
         addField(new ReadOnlyFieldEditor(AdtPlugin.PREFS_DEFAULT_DEBUG_KEYSTORE,
                 Messages.BuildPreferencePage_Default_KeyStore, getFieldEditorParent()));
 
-        addField(new FileFieldEditor(AdtPlugin.PREFS_CUSTOM_DEBUG_KEYSTORE,
+        addField(new KeystoreFieldEditor(AdtPlugin.PREFS_CUSTOM_DEBUG_KEYSTORE,
                 Messages.BuildPreferencePage_Custom_Keystore, getFieldEditorParent()));
 
     }
@@ -105,4 +115,103 @@
             control.setEditable(false);
         }
     }
+    
+    /**
+     * Custom {@link FileFieldEditor} that checks that the keystore is valid.
+     */
+    private static class KeystoreFieldEditor extends FileFieldEditor {
+        public KeystoreFieldEditor(String name, String label, Composite parent) {
+            super(name, label, parent);
+            setValidateStrategy(VALIDATE_ON_KEY_STROKE);
+        }
+        
+        @Override
+        protected boolean checkState() {
+            String fileName = getTextControl().getText();
+            fileName = fileName.trim();
+            
+            // empty values are considered ok.
+            if (fileName.length() > 0) {
+                File file = new File(fileName);
+                if (file.isFile()) {
+                    // attempt to load the debug key.
+                    try {
+                        DebugKeyProvider provider = new DebugKeyProvider(fileName,
+                                null /* storeType */, null /* key gen output */);
+                        PrivateKey key = provider.getDebugKey();
+                        X509Certificate certificate = (X509Certificate)provider.getCertificate();
+                        
+                        if (key == null || certificate == null) {
+                            showErrorMessage("Unable to find debug key in keystore!");
+                            return false;
+                        }
+                        
+                        Date today = new Date();
+                        if (certificate.getNotAfter().compareTo(today) < 0) {
+                            showErrorMessage("Certificate is expired!");
+                            return false;
+                        }
+                        
+                        if (certificate.getNotBefore().compareTo(today) > 0) {
+                            showErrorMessage("Certificate validity is in the future!");
+                            return false;
+                        }
+
+                        // we're good!
+                        clearErrorMessage();
+                        return true;
+                    } catch (GeneralSecurityException e) {
+                        handleException(e);
+                        return false;
+                    } catch (IOException e) {
+                        handleException(e);
+                        return false;
+                    } catch (KeytoolException e) {
+                        handleException(e);
+                        return false;
+                    } catch (AndroidLocationException e) {
+                        handleException(e);
+                        return false;
+                    }
+
+            
+                } else {
+                    // file does not exist.
+                    showErrorMessage("Not a valid keystore path.");
+                    return false;  // Apply/OK must be disabled
+                }
+            }
+
+            clearErrorMessage();
+            return true;
+        }
+        
+        @Override
+        public Text getTextControl(Composite parent) {
+            setValidateStrategy(VALIDATE_ON_KEY_STROKE);
+            return super.getTextControl(parent);
+        }
+
+        /**
+         * Set the error message from a {@link Throwable}. If the exception has no message, try
+         * to get the message from the cause.
+         * @param t the Throwable.
+         */
+        private void handleException(Throwable t) {
+            String msg = t.getMessage();
+            if (t == null) {
+                Throwable cause = t.getCause();
+                if (cause != null) {
+                    handleException(cause);
+                } else {
+                    setErrorMessage("Uknown error when getting the debug key!");
+                }
+                
+                return;
+            }
+
+            // valid text, display it.
+            showErrorMessage(msg);
+        }
+    }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
index efbbf94..a1b3c38 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
@@ -17,6 +17,7 @@
 package com.android.ide.eclipse.adt.project;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
@@ -117,7 +118,7 @@
             // create the file with the parcelables
             if (parcelables.size() > 0) {
                 IPath path = project.getLocation();
-                path = path.append("/project.aidl"); //$NON-NLS-1$
+                path = path.append(AndroidConstants.FN_PROJECT_AIDL);
                 
                 File f = new File(path.toOSString());
                 if (f.exists() == false) {
@@ -194,7 +195,7 @@
         
         IType[] superInterfaces = typeHierarchy.getAllSuperInterfaces(type);
         for (IType superInterface : superInterfaces) {
-            if ("android.os.Parcelable".equals(superInterface.getFullyQualifiedName())) { //$NON-NLS-1$
+            if (AndroidConstants.CLASS_PARCELABLE.equals(superInterface.getFullyQualifiedName())) {
                 parcelables.add(type.getFullyQualifiedName());
             }
         }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
new file mode 100644
index 0000000..1ca89cd
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2008 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.project;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ILightweightLabelDecorator;
+
+/**
+ * A {@link ILabelDecorator} associated with an org.eclipse.ui.decorators extension.
+ * This is used to add android icons in some special folders in the package explorer.
+ */
+public class FolderDecorator implements ILightweightLabelDecorator {
+    
+    private ImageDescriptor mDescriptor;
+
+    public FolderDecorator() {
+        mDescriptor = AdtPlugin.getImageDescriptor("/icons/android_project.png");
+    }
+
+    public void decorate(Object element, IDecoration decoration) {
+        if (element instanceof IFolder) {
+            IFolder folder = (IFolder)element;
+            
+            // get the project and make sure this is an android project
+            IProject project = folder.getProject();
+
+            try {
+                if (project.hasNature(AndroidConstants.NATURE)) {
+                    // check the folder is directly under the project.
+                    if (folder.getParent().getType() == IResource.PROJECT) {
+                        String name = folder.getName();
+                        if (name.equals(AndroidConstants.FD_ASSETS)) {
+                            decorate(decoration, " [Android assets]");
+                            decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+                        } else if (name.equals(AndroidConstants.FD_RESOURCES)) {
+                            decorate(decoration, " [Android resources]");
+                            decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+                        } else if (name.equals(AndroidConstants.FD_NATIVE_LIBS)) {
+                            decorate(decoration, " [Native Libraries]");
+                        }
+                    }
+                }
+            } catch (CoreException e) {
+                // log the error
+                AdtPlugin.log(e, "Unable to get nature of project '%s'.", project.getName());
+            }
+        }
+    }
+    
+    public void decorate(IDecoration decoration, String suffix) {
+        decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+
+        // this is broken as it changes the color of the whole text, not only of the decoration.
+        // TODO: figure out how to change the color of the decoration only.
+//        decoration.addSuffix(suffix);
+//        ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();
+//        ColorRegistry registry = theme.getColorRegistry();
+//        decoration.setForegroundColor(registry.get("org.eclipse.jdt.ui.ColoredLabels.decorations"));
+
+    }
+
+    public boolean isLabelProperty(Object element, String property) {
+        // at this time return false.
+        return false;
+    }
+
+    public void addListener(ILabelProviderListener listener) {
+        // No state change will affect the rendering.
+    }
+
+
+
+    public void removeListener(ILabelProviderListener listener) {
+        // No state change will affect the rendering.
+    }
+
+    public void dispose() {
+        // nothind to dispose
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java
new file mode 100644
index 0000000..c117b4e
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 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.project;
+
+import com.android.ide.eclipse.editors.wizards.NewXmlFileWizard;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPart;
+
+public class NewXmlFileWizardAction implements IObjectActionDelegate {
+
+    private ISelection mSelection;
+    private IWorkbench mWorkbench;
+
+    /**
+     * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
+     */
+    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+        mWorkbench = targetPart.getSite().getWorkbenchWindow().getWorkbench();
+    }
+
+    public void run(IAction action) {
+        if (mSelection instanceof IStructuredSelection) {
+            IStructuredSelection selection = (IStructuredSelection)mSelection;
+
+            // call the new xml file wizard on the current selection.
+            NewXmlFileWizard wizard = new NewXmlFileWizard();
+            wizard.init(mWorkbench, selection);
+            WizardDialog dialog = new WizardDialog(mWorkbench.getDisplay().getActiveShell(),
+                    wizard);
+            dialog.open();
+        }
+    }
+
+    public void selectionChanged(IAction action, ISelection selection) {
+        this.mSelection = selection;
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
index 24132b6..8678923 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
@@ -33,7 +33,6 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.jdt.core.IClasspathAttribute;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
@@ -178,31 +177,6 @@
     }
 
     /**
-     * Check the validity of the javadoc attributes in a classpath entry.
-     * @param frameworkEntry the classpath entry to check.
-     * @return true if the javadoc attributes is valid, false otherwise.
-     */
-    public static boolean checkJavaDocPath(IClasspathEntry frameworkEntry) {
-        // get the list of extra attributes
-        IClasspathAttribute[] attributes = frameworkEntry.getExtraAttributes();
-
-        // and search for the one about the javadoc
-        for (IClasspathAttribute att : attributes) {
-            if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.
-                    equals(att.getName())) {
-                // we found a javadoc attribute. Now we test its value.
-                // get the expect value
-                String validJavaDoc = getJavaDocPath(AdtPlugin.getOsAbsoluteFramework());
-
-                // now compare and return
-                return validJavaDoc.equals(att.getValue());
-            }
-        }
-
-        return false;
-    }
-
-    /**
      * Fix the project. This checks the SDK location.
      * @param project The project to fix.
      * @throws JavaModelException
@@ -264,14 +238,7 @@
                     continue;
                 }
             } else if (kind == IClasspathEntry.CPE_CONTAINER) {
-                IPath containerPath = entry.getPath();
-                
-                if (AndroidClasspathContainerInitializer.checkOldPath(containerPath)) {
-                    entries = ProjectHelper.removeEntryFromClasspath(entries, i);
-
-                    // continue, to skip the i++;
-                    continue;
-                } else if (AndroidClasspathContainerInitializer.checkPath(containerPath)) {
+                if (AndroidClasspathContainerInitializer.checkPath(entry.getPath())) {
                     foundContainer = true;
                 }
             }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java
index 1f51d09..de4b339 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ExportWizard.java
@@ -18,7 +18,10 @@
 
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.jarutils.KeystoreHelper;
 import com.android.jarutils.SignedJarBuilder;
+import com.android.jarutils.DebugKeyProvider.IKeyGenOutput;
+import com.android.jarutils.DebugKeyProvider.KeytoolException;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
@@ -27,28 +30,38 @@
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.wizard.Wizard;
 import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.IExportWizard;
 import org.eclipse.ui.IWorkbench;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
+import java.security.KeyStore;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
+import java.security.KeyStore.PrivateKeyEntry;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Export wizard to export an apk signed with a release key/certificate. 
  */
-public class ExportWizard extends Wizard implements IExportWizard {
+public final class ExportWizard extends Wizard implements IExportWizard {
 
     private static final String PROJECT_LOGO_LARGE = "icons/android_large.png"; //$NON-NLS-1$
     
-    private static final String PAGE_PRE = "preExportPage"; //$NON-NLS-1$
-    private static final String PAGE_SIGNING = "signingExportPage"; //$NON-NLS-1$
-    private static final String PAGE_FINAL = "finalExportPage"; //$NON-NLS-1$
+    private static final String PAGE_PROJECT_CHECK = "Page_ProjectCheck"; //$NON-NLS-1$
+    private static final String PAGE_KEYSTORE_SELECTION = "Page_KeystoreSelection"; //$NON-NLS-1$
+    private static final String PAGE_KEY_CREATION = "Page_KeyCreation"; //$NON-NLS-1$
+    private static final String PAGE_KEY_SELECTION = "Page_KeySelection"; //$NON-NLS-1$
+    private static final String PAGE_KEY_CHECK = "Page_KeyCheck"; //$NON-NLS-1$
     
     static final String PROPERTY_KEYSTORE = "keystore"; //$NON-NLS-1$
     static final String PROPERTY_ALIAS = "alias"; //$NON-NLS-1$
@@ -59,7 +72,41 @@
      */
     static abstract class ExportWizardPage extends WizardPage {
         
-        protected boolean mNewProjectReference = true;
+        /** bit mask constant for project data change event */
+        protected static final int DATA_PROJECT = 0x001;
+        /** bit mask constant for keystore data change event */
+        protected static final int DATA_KEYSTORE = 0x002;
+        /** bit mask constant for key data change event */
+        protected static final int DATA_KEY = 0x004;
+
+        protected static final VerifyListener sPasswordVerifier = new VerifyListener() {
+            public void verifyText(VerifyEvent e) {
+                // verify the characters are valid for password.
+                int len = e.text.length();
+                
+                // first limit to 127 characters max
+                if (len + ((Text)e.getSource()).getText().length() > 127) {
+                    e.doit = false;
+                    return;
+                }
+                
+                // now only take non control characters
+                for (int i = 0 ; i < len ; i++) {
+                    if (e.text.charAt(i) < 32) {
+                        e.doit = false;
+                        return;
+                    }
+                }
+            }
+        };
+        
+        /**
+         * Bit mask indicating what changed while the page was hidden.
+         * @see #DATA_PROJECT
+         * @see #DATA_KEYSTORE
+         * @see #DATA_KEY
+         */
+        protected int mProjectDataChanged = 0;
         
         ExportWizardPage(String name) {
             super(name);
@@ -72,23 +119,38 @@
             super.setVisible(visible);
             if (visible) {
                 onShow();
-                mNewProjectReference = false;
+                mProjectDataChanged = 0;
             }
         }
         
-        void newProjectReference() {
-            mNewProjectReference = true;
+        final void projectDataChanged(int changeMask) {
+            mProjectDataChanged |= changeMask;
+        }
+        
+        /**
+         * Calls {@link #setErrorMessage(String)} and {@link #setPageComplete(boolean)} based on a
+         * {@link Throwable} object.
+         */
+        protected final void onException(Throwable t) {
+            String message = getExceptionMessage(t);
+            
+            setErrorMessage(message);
+            setPageComplete(false);
         }
     }
     
-    private ExportWizardPage mPages[] = new ExportWizardPage[3];
+    private ExportWizardPage mPages[] = new ExportWizardPage[5];
 
     private IProject mProject;
 
     private String mKeystore;
+    private String mKeystorePassword;
+    private boolean mKeystoreCreationMode;
+
     private String mKeyAlias;
-    private char[] mKeystorePassword;
-    private char[] mKeyPassword;
+    private String mKeyPassword;
+    private int mValidity;
+    private String mDName;
 
     private PrivateKey mPrivateKey;
     private X509Certificate mCertificate;
@@ -97,6 +159,15 @@
     private String mApkFilePath;
     private String mApkFileName;
 
+    private ExportWizardPage mKeystoreSelectionPage;
+    private ExportWizardPage mKeyCreationPage;
+    private ExportWizardPage mKeySelectionPage;
+    private ExportWizardPage mKeyCheckPage;
+
+    private boolean mKeyCreationMode;
+
+    private List<String> mExistingAliases;
+
     public ExportWizard() {
         setHelpAvailable(false); // TODO have help
         setWindowTitle("Export Android Application");
@@ -105,46 +176,101 @@
     
     @Override
     public void addPages() {
-        addPage(mPages[0] = new PreExportPage(this, PAGE_PRE));
-        addPage(mPages[1] = new SigningExportPage(this, PAGE_SIGNING));
-        addPage(mPages[2] = new FinalExportPage(this, PAGE_FINAL));
+        addPage(mPages[0] = new ProjectCheckPage(this, PAGE_PROJECT_CHECK));
+        addPage(mKeystoreSelectionPage = mPages[1] = new KeystoreSelectionPage(this,
+                PAGE_KEYSTORE_SELECTION));
+        addPage(mKeyCreationPage = mPages[2] = new KeyCreationPage(this, PAGE_KEY_CREATION));
+        addPage(mKeySelectionPage = mPages[3] = new KeySelectionPage(this, PAGE_KEY_SELECTION));
+        addPage(mKeyCheckPage = mPages[4] = new KeyCheckPage(this, PAGE_KEY_CHECK));
     }
 
     @Override
     public boolean performFinish() {
+        // first we make sure export is fine if the destination file already exists
+        File f = new File(mDestinationPath);
+        if (f.isFile()) {
+            if (AdtPlugin.displayPrompt("Export Wizard",
+                    "File already exists. Do you want to overwrite it?") == false) {
+                return false;
+            }
+        }
+        
         // save the properties
         ProjectHelper.saveStringProperty(mProject, PROPERTY_KEYSTORE, mKeystore);
         ProjectHelper.saveStringProperty(mProject, PROPERTY_ALIAS, mKeyAlias);
         ProjectHelper.saveStringProperty(mProject, PROPERTY_DESTINATION, mDestinationPath);
         
         try {
-            FileOutputStream fos = new FileOutputStream(mDestinationPath);
-            SignedJarBuilder builder = new SignedJarBuilder(fos, mPrivateKey, mCertificate);
-            
-            // get the input file.
-            FileInputStream fis = new FileInputStream(mApkFilePath);
-            try {
-                builder.writeZip(fis, null /* filter */);
-            } finally {
+            if (mKeystoreCreationMode || mKeyCreationMode) {
+                final ArrayList<String> output = new ArrayList<String>();
+                if (KeystoreHelper.createNewStore(
+                        mKeystore,
+                        null /*storeType*/,
+                        mKeystorePassword,
+                        mKeyAlias,
+                        mKeyPassword,
+                        mDName,
+                        mValidity,
+                        new IKeyGenOutput() {
+                            public void err(String message) {
+                                output.add(message);
+                            }
+                            public void out(String message) {
+                                output.add(message);
+                            }
+                        }) == false) {
+                    // keystore creation error!
+                    displayError(output.toArray(new String[output.size()]));
+                    return false;
+                }
+                
+                // keystore is created, now load the private key and certificate.
+                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream fis = new FileInputStream(mKeystore);
+                keyStore.load(fis, mKeystorePassword.toCharArray());
                 fis.close();
+                PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
+                        mKeyAlias, new KeyStore.PasswordProtection(mKeyPassword.toCharArray()));
+                
+                if (entry != null) {
+                    mPrivateKey = entry.getPrivateKey();
+                    mCertificate = (X509Certificate)entry.getCertificate();
+                } else {
+                    // this really shouldn't happen since we now let the user choose the key
+                    // from a list read from the store.
+                    displayError("Could not find key");
+                    return false;
+                }
             }
-
-            builder.close();
-            fos.close();
             
-            return true;
+            // check the private key/certificate again since it may have been created just above.
+            if (mPrivateKey != null && mCertificate != null) {
+                FileOutputStream fos = new FileOutputStream(mDestinationPath);
+                SignedJarBuilder builder = new SignedJarBuilder(fos, mPrivateKey, mCertificate);
+                
+                // get the input file.
+                FileInputStream fis = new FileInputStream(mApkFilePath);
+                try {
+                    builder.writeZip(fis, null /* filter */);
+                } finally {
+                    fis.close();
+                }
+    
+                builder.close();
+                fos.close();
+                
+                return true;
+            }
         } catch (FileNotFoundException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
+            displayError(e);
         } catch (NoSuchAlgorithmException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
+            displayError(e);
         } catch (IOException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
+            displayError(e);
         } catch (GeneralSecurityException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
+            displayError(e);
+        } catch (KeytoolException e) {
+            displayError(e);
         }
 
         return false;
@@ -152,8 +278,13 @@
     
     @Override
     public boolean canFinish() {
+        // check if we have the apk to resign, the destination location, and either
+        // a private key/certificate or the creation mode. In creation mode, unless
+        // all the key/keystore info is valid, the user cannot reach the last page, so there's
+        // no need to check them again here.
         return mApkFilePath != null &&
-                mPrivateKey != null && mCertificate != null &&
+                ((mPrivateKey != null && mCertificate != null)
+                        || mKeystoreCreationMode || mKeyCreationMode) &&
                 mDestinationPath != null;
     }
     
@@ -175,6 +306,22 @@
         }
     }
     
+    ExportWizardPage getKeystoreSelectionPage() {
+        return mKeystoreSelectionPage;
+    }
+    
+    ExportWizardPage getKeyCreationPage() {
+        return mKeyCreationPage;
+    }
+    
+    ExportWizardPage getKeySelectionPage() {
+        return mKeySelectionPage;
+    }
+    
+    ExportWizardPage getKeyCheckPage() {
+        return mKeyCheckPage;
+    }
+
     /**
      * Returns an image descriptor for the wizard logo.
      */
@@ -192,10 +339,7 @@
         mApkFilePath = apkFilePath;
         mApkFileName = filename;
         
-        // indicate to the page that the project was changed.
-        for (ExportWizardPage page : mPages) {
-            page.newProjectReference();
-        }
+        updatePageOnChange(ExportWizardPage.DATA_PROJECT);
     }
     
     String getApkFilename() {
@@ -206,42 +350,95 @@
         mKeystore = path;
         mPrivateKey = null;
         mCertificate = null;
+        
+        updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
     }
     
     String getKeystore() {
         return mKeystore;
     }
     
+    void setKeystoreCreationMode(boolean createStore) {
+        mKeystoreCreationMode = createStore;
+        updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
+    }
+    
+    boolean getKeystoreCreationMode() {
+        return mKeystoreCreationMode;
+    }
+    
+    
+    void setKeystorePassword(String password) {
+        mKeystorePassword = password;
+        mPrivateKey = null;
+        mCertificate = null;
+
+        updatePageOnChange(ExportWizardPage.DATA_KEYSTORE);
+    }
+    
+    String getKeystorePassword() {
+        return mKeystorePassword;
+    }
+
+    void setKeyCreationMode(boolean createKey) {
+        mKeyCreationMode = createKey;
+        updatePageOnChange(ExportWizardPage.DATA_KEY);
+    }
+    
+    boolean getKeyCreationMode() {
+        return mKeyCreationMode;
+    }
+    
+    void setExistingAliases(List<String> aliases) {
+        mExistingAliases = aliases;
+    }
+    
+    List<String> getExistingAliases() {
+        return mExistingAliases;
+    }
+
     void setKeyAlias(String name) {
         mKeyAlias = name;
         mPrivateKey = null;
         mCertificate = null;
+
+        updatePageOnChange(ExportWizardPage.DATA_KEY);
     }
     
     String getKeyAlias() {
         return mKeyAlias;
     }
-    
-    void setKeystorePassword(char[] password) {
-        mKeystorePassword = password;
-        mPrivateKey = null;
-        mCertificate = null;
-    }
-    
-    char[] getKeystorePassword() {
-        return mKeystorePassword;
-    }
-    
-    void setKeyPassword(char[] password) {
+
+    void setKeyPassword(String password) {
         mKeyPassword = password;
         mPrivateKey = null;
         mCertificate = null;
+
+        updatePageOnChange(ExportWizardPage.DATA_KEY);
     }
     
-    char[] getKeyPassword() {
+    String getKeyPassword() {
         return mKeyPassword;
     }
 
+    void setValidity(int validity) {
+        mValidity = validity;
+        updatePageOnChange(ExportWizardPage.DATA_KEY);
+    }
+    
+    int getValidity() {
+        return mValidity;
+    }
+
+    void setDName(String dName) {
+        mDName = dName;
+        updatePageOnChange(ExportWizardPage.DATA_KEY);
+    }
+    
+    String getDName() {
+        return mDName;
+    }
+
     void setSigningInfo(PrivateKey privateKey, X509Certificate certificate) {
         mPrivateKey = privateKey;
         mCertificate = certificate;
@@ -251,4 +448,54 @@
         mDestinationPath = path;
     }
     
+    void updatePageOnChange(int changeMask) {
+        for (ExportWizardPage page : mPages) {
+            page.projectDataChanged(changeMask);
+        }
+    }
+    
+    private void displayError(String... messages) {
+        String message = null;
+        if (messages.length == 1) {
+            message = messages[0];
+        } else {
+            StringBuilder sb = new StringBuilder(messages[0]);
+            for (int i = 1;  i < messages.length; i++) {
+                sb.append('\n');
+                sb.append(messages[i]);
+            }
+            
+            message = sb.toString();
+        }
+
+        AdtPlugin.displayError("Export Wizard", message);
+    }
+    
+    private void displayError(Exception e) {
+        String message = getExceptionMessage(e);
+        displayError(message);
+        
+        AdtPlugin.log(e, "Export Wizard Error");
+    }
+    
+    /**
+     * Returns the {@link Throwable#getMessage()}. If the {@link Throwable#getMessage()} returns
+     * <code>null</code>, the method is called again on the cause of the Throwable object.
+     * <p/>If no Throwable in the chain has a valid message, the canonical name of the first
+     * exception is returned.
+     */
+    private static String getExceptionMessage(Throwable t) {
+        String message = t.getMessage();
+        if (message == null) {
+            Throwable cause = t.getCause();
+            if (cause != null) {
+                return getExceptionMessage(cause);
+            }
+
+            // no more cause and still no message. display the first exception.
+            return cause.getClass().getCanonicalName();
+        }
+        
+        return message;
+    }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java
deleted file mode 100644
index 206e3aa..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/FinalExportPage.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2008 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.project.export;
-
-import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.FormText;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.UnrecoverableEntryException;
-import java.security.KeyStore.PrivateKeyEntry;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.Calendar;
-
-public class FinalExportPage extends ExportWizardPage {
-
-    private final ExportWizard mWizard;
-    private PrivateKey mPrivateKey;
-    private X509Certificate mCertificate;
-    private Text mDestination;
-    private Button mBrowseButton;
-    private boolean mFatalSigningError;
-    private FormText mDetailText;
-
-    protected FinalExportPage(ExportWizard wizard, String pageName) {
-        super(pageName);
-        mWizard = wizard;
-        
-        setTitle("Application Export");
-        setDescription("Export the signed Application package.");
-    }
-
-    public void createControl(Composite parent) {
-        setErrorMessage(null);
-        setMessage(null);
-
-        // build the ui.
-        Composite composite = new Composite(parent, SWT.NULL);
-        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
-        GridLayout gl = new GridLayout(3, false);
-        gl.verticalSpacing *= 3;
-        composite.setLayout(gl);
-        
-        GridData gd;
-
-        new Label(composite, SWT.NONE).setText("Destination APK file:");
-        mDestination = new Text(composite, SWT.BORDER);
-        mDestination.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-        mDestination.addModifyListener(new ModifyListener() {
-            public void modifyText(ModifyEvent e) {
-                onDestinationChange();
-            }
-        });
-        mBrowseButton = new Button(composite, SWT.PUSH);
-        mBrowseButton.setText("Browse...");
-        mBrowseButton.addSelectionListener(new SelectionAdapter() {
-            @Override
-            public void widgetSelected(SelectionEvent e) {
-                FileDialog fileDialog = new FileDialog(mBrowseButton.getShell(), SWT.SAVE);
-                
-                fileDialog.setText("Destination file name");
-                fileDialog.setFileName(mWizard.getApkFilename());
-        
-                String saveLocation = fileDialog.open();
-                if (saveLocation != null) {
-                    mDestination.setText(saveLocation);
-                }
-            }
-        });
-        
-        mDetailText = new FormText(composite, SWT.NONE);
-        mDetailText.setLayoutData(gd = new GridData(GridData.FILL_BOTH));
-        gd.horizontalSpan = 3;
-        
-        setControl(composite);
-    }
-    
-    @Override
-    void onShow() {
-        // fill the texts with information loaded from the project.
-        if (mNewProjectReference) {
-            // reset the destination from the content of the project
-            IProject project = mWizard.getProject();
-            
-            String destination = ProjectHelper.loadStringProperty(project,
-                    ExportWizard.PROPERTY_DESTINATION);
-            if (destination != null) {
-                mDestination.setText(destination);
-            }
-        }
-
-        // reset the wizard with no key/cert to make it not finishable, unless a valid
-        // key/cert is found.
-        mWizard.setSigningInfo(null, null);
-
-        try {
-            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
-            FileInputStream fis = new FileInputStream(mWizard.getKeystore());
-            keyStore.load(fis, mWizard.getKeystorePassword());
-            fis.close();
-            PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
-                    mWizard.getKeyAlias(),
-                    new KeyStore.PasswordProtection(mWizard.getKeyPassword()));
-            
-            if (entry != null) {
-                mPrivateKey = entry.getPrivateKey();
-                mCertificate = (X509Certificate)entry.getCertificate();
-            } else {
-                setErrorMessage("Unable to find key");
-                
-                setPageComplete(false);
-            }
-        } catch (FileNotFoundException e) {
-            // this was checked at the first previous step and will not happen here, unless
-            // the file was removed during the export wizard execution.
-            onException(e);
-        } catch (KeyStoreException e) {
-            onException(e);
-        } catch (NoSuchAlgorithmException e) {
-            onException(e);
-        } catch (UnrecoverableEntryException e) {
-            onException(e);
-        } catch (CertificateException e) {
-            onException(e);
-        } catch (IOException e) {
-            onException(e);
-        }
-        
-        if (mPrivateKey != null && mCertificate != null) {
-            mFatalSigningError = false;
-            
-            Calendar expirationCalendar = Calendar.getInstance();
-            expirationCalendar.setTime(mCertificate.getNotAfter());
-            Calendar today = Calendar.getInstance();
-            
-            if (expirationCalendar.before(today)) {
-                mDetailText.setText(String.format("<form><p>Certificate expired on %s</p></form>",
-                        mCertificate.getNotAfter().toString()),
-                        true /* parseTags */, true /* expandURLs */);
-                
-                // fatal error = nothing can make the page complete.
-                mFatalSigningError = true;
-
-                setErrorMessage("Certificate is expired!");
-                setPageComplete(false);
-            } else {
-                // valid, key/cert: put it in the wizard so that it can be finished
-                mWizard.setSigningInfo(mPrivateKey, mCertificate);
-
-                StringBuilder sb = new StringBuilder(String.format("<form><p>Certificate expires on %s.</p>",
-                    mCertificate.getNotAfter().toString()));
-                
-                int expirationYear = expirationCalendar.get(Calendar.YEAR);
-                int thisYear = today.get(Calendar.YEAR);
-                
-                if (thisYear + 25 < expirationYear) {
-                    // do nothing
-                } else {
-                    if (expirationYear == thisYear) {
-                        sb.append("<p>The certificate expires this year!</p>");
-                    } else {
-                        int count = expirationYear-thisYear;
-                        sb.append(String.format("<p>The Certificate expires in %1$s %2$s!</p>",
-                                count, count == 1 ? "year" : "years"));
-                    }
-                    
-                    sb.append("<p>Make sure the certificate is valid for the planned lifetime of the product.</p>");
-                    sb.append("<p>If the certificate expires, you will be forced to sign your application with a different one.</p>");
-                    sb.append("<p>Applications cannot be upgraded if their certificate changes from one version to another, ");
-                    sb.append("forcing a full uninstall/install, which will make the user lose his/her data.</p>");
-                    sb.append("<p>Android Market currently requires certificates to be valid until 2033.</p>");
-                    
-                    sb.append("</form>");
-                }
-                
-                mDetailText.setText(sb.toString(), true /* parseTags */, true /* expandURLs */);
-            }
-            mDetailText.getParent().layout();
-        } else {
-            // fatal error = nothing can make the page complete.
-            mFatalSigningError = true;
-        }
-        
-        onDestinationChange();
-    }
-    
-    private void onDestinationChange() {
-        if (mFatalSigningError == false) {
-            String path = mDestination.getText().trim();
-            if (path.length() == 0) {
-                setErrorMessage("Enter destination for the APK file.");
-                mWizard.setDestination(null); // this is to reset canFinish in the wizard
-                setPageComplete(false);
-            } else {
-                File file = new File(path);
-                if (file.isDirectory()) {
-                    setErrorMessage("Destination is a directory!");
-                    mWizard.setDestination(null); // this is to reset canFinish in the wizard
-                    setPageComplete(false);
-                } else {
-                    File parentFile = file.getParentFile();
-                    if (parentFile == null || parentFile.isDirectory() == false) {
-                        setErrorMessage("Not a valid directory.");
-                        mWizard.setDestination(null); // this is to reset canFinish in the wizard
-                        setPageComplete(false);
-                    } else {
-                        mWizard.setDestination(path);
-                        setErrorMessage(null);
-                        setPageComplete(true);
-                    }
-                }
-            }
-        }
-    }
-    
-    /**
-     * Calls {@link #setErrorMessage(String)} and {@link #setPageComplete(boolean)} based on a
-     * {@link Throwable} object. If the {@link Throwable#getMessage()} returns <code>null</code>,
-     * the method is called again on the cause of the Throwable.
-     */
-    private void onException(Throwable t) {
-        String message = t.getMessage();
-        if (message == null) {
-            Throwable cause = t.getCause();
-            if (cause != null) {
-                onException(cause);
-            } else {
-                // no more cause and still no message. display the first exception.
-                setErrorMessage(cause.getClass().getCanonicalName());
-                setPageComplete(false);
-            }
-            return;
-        }
-        
-        setErrorMessage(message);
-        setPageComplete(false);
-    }
-
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java
new file mode 100644
index 0000000..c64bf10
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCheckPage.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2008 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.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.FormText;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableEntryException;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+
+/**
+ * Final page of the wizard that checks the key and ask for the ouput location.
+ */
+final class KeyCheckPage extends ExportWizardPage {
+
+    private final ExportWizard mWizard;
+    private PrivateKey mPrivateKey;
+    private X509Certificate mCertificate;
+    private Text mDestination;
+    private boolean mFatalSigningError;
+    private FormText mDetailText;
+
+    protected KeyCheckPage(ExportWizard wizard, String pageName) {
+        super(pageName);
+        mWizard = wizard;
+        
+        setTitle("Destination and key/certificate checks");
+        setDescription(""); // TODO
+    }
+
+    public void createControl(Composite parent) {
+        setErrorMessage(null);
+        setMessage(null);
+
+        // build the ui.
+        Composite composite = new Composite(parent, SWT.NULL);
+        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+        GridLayout gl = new GridLayout(3, false);
+        gl.verticalSpacing *= 3;
+        composite.setLayout(gl);
+        
+        GridData gd;
+
+        new Label(composite, SWT.NONE).setText("Destination APK file:");
+        mDestination = new Text(composite, SWT.BORDER);
+        mDestination.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        mDestination.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                onDestinationChange();
+            }
+        });
+        final Button browseButton = new Button(composite, SWT.PUSH);
+        browseButton.setText("Browse...");
+        browseButton.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                FileDialog fileDialog = new FileDialog(browseButton.getShell(), SWT.SAVE);
+                
+                fileDialog.setText("Destination file name");
+                fileDialog.setFileName(mWizard.getApkFilename());
+        
+                String saveLocation = fileDialog.open();
+                if (saveLocation != null) {
+                    mDestination.setText(saveLocation);
+                }
+            }
+        });
+        
+        mDetailText = new FormText(composite, SWT.NONE);
+        mDetailText.setLayoutData(gd = new GridData(GridData.FILL_BOTH));
+        gd.horizontalSpan = 3;
+        
+        setControl(composite);
+    }
+    
+    @Override
+    void onShow() {
+        // fill the texts with information loaded from the project.
+        if ((mProjectDataChanged & DATA_PROJECT) != 0) {
+            // reset the destination from the content of the project
+            IProject project = mWizard.getProject();
+            
+            String destination = ProjectHelper.loadStringProperty(project,
+                    ExportWizard.PROPERTY_DESTINATION);
+            if (destination != null) {
+                mDestination.setText(destination);
+            }
+        }
+        
+        // if anything change we basically reload the data.
+        if (mProjectDataChanged != 0) {
+            mFatalSigningError = false;
+
+            // reset the wizard with no key/cert to make it not finishable, unless a valid
+            // key/cert is found.
+            mWizard.setSigningInfo(null, null);
+    
+            if (mWizard.getKeystoreCreationMode() || mWizard.getKeyCreationMode()) {
+                int validity = mWizard.getValidity();
+                StringBuilder sb = new StringBuilder(
+                        String.format("<form><p>Certificate expires in %d years.</p>",
+                        validity));
+
+                if (validity < 25) {
+                    sb.append("<p>Make sure the certificate is valid for the planned lifetime of the product.</p>");
+                    sb.append("<p>If the certificate expires, you will be forced to sign your application with a different one.</p>");
+                    sb.append("<p>Applications cannot be upgraded if their certificate changes from one version to another, ");
+                    sb.append("forcing a full uninstall/install, which will make the user lose his/her data.</p>");
+                    sb.append("<p>Android Market currently requires certificates to be valid until 2033.</p>");
+                }
+
+                sb.append("</form>");
+                mDetailText.setText(sb.toString(), true /* parseTags */, true /* expandURLs */);
+            } else {
+                try {
+                    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+                    FileInputStream fis = new FileInputStream(mWizard.getKeystore());
+                    keyStore.load(fis, mWizard.getKeystorePassword().toCharArray());
+                    fis.close();
+                    PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(
+                            mWizard.getKeyAlias(),
+                            new KeyStore.PasswordProtection(
+                                    mWizard.getKeyPassword().toCharArray()));
+                    
+                    if (entry != null) {
+                        mPrivateKey = entry.getPrivateKey();
+                        mCertificate = (X509Certificate)entry.getCertificate();
+                    } else {
+                        setErrorMessage("Unable to find key.");
+                        
+                        setPageComplete(false);
+                    }
+                } catch (FileNotFoundException e) {
+                    // this was checked at the first previous step and will not happen here, unless
+                    // the file was removed during the export wizard execution.
+                    onException(e);
+                } catch (KeyStoreException e) {
+                    onException(e);
+                } catch (NoSuchAlgorithmException e) {
+                    onException(e);
+                } catch (UnrecoverableEntryException e) {
+                    onException(e);
+                } catch (CertificateException e) {
+                    onException(e);
+                } catch (IOException e) {
+                    onException(e);
+                }
+                
+                if (mPrivateKey != null && mCertificate != null) {
+                    Calendar expirationCalendar = Calendar.getInstance();
+                    expirationCalendar.setTime(mCertificate.getNotAfter());
+                    Calendar today = Calendar.getInstance();
+                    
+                    if (expirationCalendar.before(today)) {
+                        mDetailText.setText(String.format(
+                                "<form><p>Certificate expired on %s</p></form>",
+                                mCertificate.getNotAfter().toString()),
+                                true /* parseTags */, true /* expandURLs */);
+                        
+                        // fatal error = nothing can make the page complete.
+                        mFatalSigningError = true;
+        
+                        setErrorMessage("Certificate is expired.");
+                        setPageComplete(false);
+                    } else {
+                        // valid, key/cert: put it in the wizard so that it can be finished
+                        mWizard.setSigningInfo(mPrivateKey, mCertificate);
+        
+                        StringBuilder sb = new StringBuilder(String.format(
+                                "<form><p>Certificate expires on %s.</p>",
+                                mCertificate.getNotAfter().toString()));
+                        
+                        int expirationYear = expirationCalendar.get(Calendar.YEAR);
+                        int thisYear = today.get(Calendar.YEAR);
+                        
+                        if (thisYear + 25 < expirationYear) {
+                            // do nothing
+                        } else {
+                            if (expirationYear == thisYear) {
+                                sb.append("<p>The certificate expires this year.</p>");
+                            } else {
+                                int count = expirationYear-thisYear;
+                                sb.append(String.format(
+                                        "<p>The Certificate expires in %1$s %2$s.</p>",
+                                        count, count == 1 ? "year" : "years"));
+                            }
+                            
+                            sb.append("<p>Make sure the certificate is valid for the planned lifetime of the product.</p>");
+                            sb.append("<p>If the certificate expires, you will be forced to sign your application with a different one.</p>");
+                            sb.append("<p>Applications cannot be upgraded if their certificate changes from one version to another, ");
+                            sb.append("forcing a full uninstall/install, which will make the user lose his/her data.</p>");
+                            sb.append("<p>Android Market currently requires certificates to be valid until 2033.</p>");
+                        }
+                        
+                        sb.append("</form>");
+        
+                        mDetailText.setText(sb.toString(), true /* parseTags */, true /* expandURLs */);
+                    }
+                    mDetailText.getParent().layout();
+                } else {
+                    // fatal error = nothing can make the page complete.
+                    mFatalSigningError = true;
+                }
+            }
+        }
+
+        onDestinationChange();
+    }
+    
+    private void onDestinationChange() {
+        if (mFatalSigningError == false) {
+            // reset messages for now.
+            setErrorMessage(null);
+            setMessage(null);
+
+            String path = mDestination.getText().trim();
+
+            if (path.length() == 0) {
+                setErrorMessage("Enter destination for the APK file.");
+                mWizard.setDestination(null); // this is to reset canFinish in the wizard
+                setPageComplete(false);
+                return;
+            }
+
+            File file = new File(path);
+            if (file.isDirectory()) {
+                setErrorMessage("Destination is a directory.");
+                mWizard.setDestination(null); // this is to reset canFinish in the wizard
+                setPageComplete(false);
+                return;
+            }
+
+            File parentFile = file.getParentFile();
+            if (parentFile == null || parentFile.isDirectory() == false) {
+                setErrorMessage("Not a valid directory.");
+                mWizard.setDestination(null); // this is to reset canFinish in the wizard
+                setPageComplete(false);
+                return;
+            }
+
+            // no error, set the destination in the wizard.
+            mWizard.setDestination(path);
+            setPageComplete(true);
+            
+            // However, we should also test if the file already exists.
+            if (file.isFile()) {
+                setMessage("Destination file already exists.", WARNING);
+            }
+        }
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java
new file mode 100644
index 0000000..d7365f7
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeyCreationPage.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2008 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.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import java.util.List;
+
+/**
+ * Key creation page. 
+ */
+final class KeyCreationPage extends ExportWizardPage {
+
+    private final ExportWizard mWizard;
+    private Text mAlias;
+    private Text mKeyPassword;
+    private Text mKeyPassword2;
+    private Text mCnField;
+    private boolean mDisableOnChange = false;
+    private Text mOuField;
+    private Text mOField;
+    private Text mLField;
+    private Text mStField;
+    private Text mCField;
+    private String mDName;
+    private int mValidity = 0;
+    private List<String> mExistingAliases;
+
+    
+    protected KeyCreationPage(ExportWizard wizard, String pageName) {
+        super(pageName);
+        mWizard = wizard;
+
+        setTitle("Key Creation");
+        setDescription(""); // TODO?
+    }
+
+    public void createControl(Composite parent) {
+        Composite composite = new Composite(parent, SWT.NULL);
+        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+        GridLayout gl = new GridLayout(2, false);
+        composite.setLayout(gl);
+        
+        GridData gd;
+
+        new Label(composite, SWT.NONE).setText("Alias:");
+        mAlias = new Text(composite, SWT.BORDER);
+        mAlias.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+        new Label(composite, SWT.NONE).setText("Password:");
+        mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+        mKeyPassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        mKeyPassword.addVerifyListener(sPasswordVerifier);
+
+        new Label(composite, SWT.NONE).setText("Confirm:");
+        mKeyPassword2 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+        mKeyPassword2.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        mKeyPassword2.addVerifyListener(sPasswordVerifier);
+
+        new Label(composite, SWT.NONE).setText("Validity (years):");
+        final Text validityText = new Text(composite, SWT.BORDER);
+        validityText.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        validityText.addVerifyListener(new VerifyListener() {
+            public void verifyText(VerifyEvent e) {
+                // check for digit only.
+                for (int i = 0 ; i < e.text.length(); i++) {
+                    char letter = e.text.charAt(i);
+                    if (letter < '0' || letter > '9') {
+                        e.doit = false;
+                        return;
+                    }
+                }
+            }
+        });
+
+        new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(
+                gd = new GridData(GridData.FILL_HORIZONTAL));
+        gd.horizontalSpan = 2;
+        
+        new Label(composite, SWT.NONE).setText("First and Last Name:");
+        mCnField = new Text(composite, SWT.BORDER);
+        mCnField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+        new Label(composite, SWT.NONE).setText("Organizational Unit:");
+        mOuField = new Text(composite, SWT.BORDER);
+        mOuField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+        new Label(composite, SWT.NONE).setText("Organization:");
+        mOField = new Text(composite, SWT.BORDER);
+        mOField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+        new Label(composite, SWT.NONE).setText("City or Locality:");
+        mLField = new Text(composite, SWT.BORDER);
+        mLField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+        new Label(composite, SWT.NONE).setText("State or Province:");
+        mStField = new Text(composite, SWT.BORDER);
+        mStField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        
+        new Label(composite, SWT.NONE).setText("Country Code (XX):");
+        mCField = new Text(composite, SWT.BORDER);
+        mCField.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+        // Show description the first time
+        setErrorMessage(null);
+        setMessage(null);
+        setControl(composite);
+        
+        mAlias.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                mWizard.setKeyAlias(mAlias.getText().trim());
+                onChange();
+            }
+        });
+        mKeyPassword.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                mWizard.setKeyPassword(mKeyPassword.getText());
+                onChange();
+            }
+        });
+        mKeyPassword2.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                onChange();
+            }
+        });
+        
+        validityText.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                try {
+                    mValidity = Integer.parseInt(validityText.getText());
+                } catch (NumberFormatException e2) {
+                    // this should only happen if the text field is empty due to the verifyListener.
+                    mValidity = 0;
+                }
+                mWizard.setValidity(mValidity);
+                onChange();
+            }
+        });
+
+        ModifyListener dNameListener = new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                onDNameChange();
+            }
+        };
+        
+        mCnField.addModifyListener(dNameListener);
+        mOuField.addModifyListener(dNameListener);
+        mOField.addModifyListener(dNameListener);
+        mLField.addModifyListener(dNameListener);
+        mStField.addModifyListener(dNameListener);
+        mCField.addModifyListener(dNameListener);
+    }
+    
+    @Override
+    void onShow() {
+        // fill the texts with information loaded from the project.
+        if ((mProjectDataChanged & (DATA_PROJECT | DATA_KEYSTORE)) != 0) {
+            // reset the keystore/alias from the content of the project
+            IProject project = mWizard.getProject();
+            
+            // disable onChange for now. we'll call it once at the end.
+            mDisableOnChange = true;
+            
+            String alias = ProjectHelper.loadStringProperty(project, ExportWizard.PROPERTY_ALIAS);
+            if (alias != null) {
+                mAlias.setText(alias);
+            }
+            
+            // get the existing list of keys if applicable
+            if (mWizard.getKeyCreationMode()) {
+                mExistingAliases = mWizard.getExistingAliases();
+            } else {
+                mExistingAliases = null;
+            }
+            
+            // reset the passwords
+            mKeyPassword.setText(""); //$NON-NLS-1$
+            mKeyPassword2.setText(""); //$NON-NLS-1$
+            
+            // enable onChange, and call it to display errors and enable/disable pageCompleted.
+            mDisableOnChange = false;
+            onChange();
+        }
+    }
+
+    @Override
+    public IWizardPage getPreviousPage() {
+        if (mWizard.getKeyCreationMode()) { // this means we create a key from an existing store
+            return mWizard.getKeySelectionPage();
+        }
+        
+        return mWizard.getKeystoreSelectionPage();
+    }
+
+    @Override
+    public IWizardPage getNextPage() {
+        return mWizard.getKeyCheckPage();
+    }
+
+    /**
+     * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
+     */
+    private void onChange() {
+        if (mDisableOnChange) {
+            return;
+        }
+
+        setErrorMessage(null);
+        setMessage(null);
+
+        if (mAlias.getText().trim().length() == 0) {
+            setErrorMessage("Enter key alias.");
+            setPageComplete(false);
+            return;
+        } else if (mExistingAliases != null) {
+            // we cannot use indexOf, because we need to do a case-insensitive check
+            String keyAlias = mAlias.getText().trim();
+            for (String alias : mExistingAliases) {
+                if (alias.equalsIgnoreCase(keyAlias)) {
+                    setErrorMessage("Key alias already exists in keystore.");
+                    setPageComplete(false);
+                    return;
+                }
+            }
+        }
+
+        String value = mKeyPassword.getText();
+        if (value.length() == 0) {
+            setErrorMessage("Enter key password.");
+            setPageComplete(false);
+            return;
+        } else if (value.length() < 6) {
+            setErrorMessage("Key password is too short - must be at least 6 characters.");
+            setPageComplete(false);
+            return;
+        }
+
+        if (value.equals(mKeyPassword2.getText()) == false) {
+            setErrorMessage("Key passwords don't match.");
+            setPageComplete(false);
+            return;
+        }
+
+        if (mValidity == 0) {
+            setErrorMessage("Key certificate validity is required.");
+            setPageComplete(false);
+            return;
+        } else if (mValidity < 25) {
+            setMessage("A 25 year certificate validity is recommended.", WARNING);
+        } else if (mValidity > 1000) {
+            setErrorMessage("Key certificate validity must be between 1 and 1000 years.");
+            setPageComplete(false);
+            return;
+        }
+
+        if (mDName == null || mDName.length() == 0) {
+            setErrorMessage("At least one Certificate issuer field is required to be non-empty.");
+            setPageComplete(false);
+            return;
+        }
+
+        setPageComplete(true);
+    }
+    
+    /**
+     * Handles changes in the DName fields.
+     */
+    private void onDNameChange() {
+        StringBuilder sb = new StringBuilder();
+        
+        buildDName("CN", mCnField, sb);
+        buildDName("OU", mOuField, sb);
+        buildDName("O", mOField, sb);
+        buildDName("L", mLField, sb);
+        buildDName("ST", mStField, sb);
+        buildDName("C", mCField, sb);
+        
+        mDName = sb.toString();
+        mWizard.setDName(mDName);
+
+        onChange();
+    }
+    
+    /**
+     * Builds the distinguished name string with the provided {@link StringBuilder}.
+     * @param prefix the prefix of the entry.
+     * @param textField The {@link Text} field containing the entry value.
+     * @param sb the string builder containing the dname.
+     */
+    private void buildDName(String prefix, Text textField, StringBuilder sb) {
+        if (textField != null) {
+            String value = textField.getText().trim();
+            if (value.length() > 0) {
+                if (sb.length() > 0) {
+                    sb.append(",");
+                }
+                
+                sb.append(prefix);
+                sb.append('=');
+                sb.append(value);
+            }
+        }
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java
new file mode 100644
index 0000000..2fcd757
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeySelectionPage.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2008 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.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+/**
+ * Key Selection Page. This is used when an existing keystore is used. 
+ */
+final class KeySelectionPage extends ExportWizardPage {
+
+    private final ExportWizard mWizard;
+    private Label mKeyAliasesLabel;
+    private Combo mKeyAliases;
+    private Label mKeyPasswordLabel;
+    private Text mKeyPassword;
+    private boolean mDisableOnChange = false;
+    private Button mUseExistingKey;
+    private Button mCreateKey;
+
+    protected KeySelectionPage(ExportWizard wizard, String pageName) {
+        super(pageName);
+        mWizard = wizard;
+
+        setTitle("Key alias selection");
+        setDescription(""); // TODO
+    }
+
+    public void createControl(Composite parent) {
+        Composite composite = new Composite(parent, SWT.NULL);
+        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+        GridLayout gl = new GridLayout(3, false);
+        composite.setLayout(gl);
+
+        GridData gd;
+
+        mUseExistingKey = new Button(composite, SWT.RADIO);
+        mUseExistingKey.setText("Use existing key");
+        mUseExistingKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        gd.horizontalSpan = 3;
+        mUseExistingKey.setSelection(true);
+
+        new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+        gd.heightHint = 0;
+        gd.widthHint = 50;
+        mKeyAliasesLabel = new Label(composite, SWT.NONE);
+        mKeyAliasesLabel.setText("Alias:");
+        mKeyAliases = new Combo(composite, SWT.READ_ONLY);
+        mKeyAliases.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        
+        new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+        gd.heightHint = 0;
+        gd.widthHint = 50;
+        mKeyPasswordLabel = new Label(composite, SWT.NONE);
+        mKeyPasswordLabel.setText("Password:");
+        mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+        mKeyPassword.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+        mCreateKey = new Button(composite, SWT.RADIO);
+        mCreateKey.setText("Create new key");
+        mCreateKey.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        gd.horizontalSpan = 3;
+
+        // Show description the first time
+        setErrorMessage(null);
+        setMessage(null);
+        setControl(composite);
+        
+        mUseExistingKey.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                mWizard.setKeyCreationMode(!mUseExistingKey.getSelection());
+                enableWidgets();
+                onChange();
+            }
+        });
+        
+        mKeyAliases.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                mWizard.setKeyAlias(mKeyAliases.getItem(mKeyAliases.getSelectionIndex()));
+                onChange();
+            }
+        });
+        
+        mKeyPassword.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                mWizard.setKeyPassword(mKeyPassword.getText());
+                onChange();
+            }
+        });
+    }
+    
+    @Override
+    void onShow() {
+        // fill the texts with information loaded from the project.
+        if ((mProjectDataChanged & (DATA_PROJECT | DATA_KEYSTORE)) != 0) {
+            // disable onChange for now. we'll call it once at the end.
+            mDisableOnChange = true;
+
+            // reset the alias from the content of the project
+            try {
+                // reset to using a key
+                mWizard.setKeyCreationMode(false);
+                mUseExistingKey.setSelection(true);
+                mCreateKey.setSelection(false);
+                enableWidgets();
+
+                // remove the content of the alias combo always and first, in case the
+                // keystore password is wrong
+                mKeyAliases.removeAll();
+
+                // get the alias list (also used as a keystore password test)
+                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+                FileInputStream fis = new FileInputStream(mWizard.getKeystore());
+                keyStore.load(fis, mWizard.getKeystorePassword().toCharArray());
+                fis.close();
+                
+                Enumeration<String> aliases = keyStore.aliases();
+
+                // get the alias from the project previous export, and look for a match as
+                // we add the aliases to the combo.
+                IProject project = mWizard.getProject();
+
+                String keyAlias = ProjectHelper.loadStringProperty(project,
+                        ExportWizard.PROPERTY_ALIAS);
+                
+                ArrayList<String> aliasList = new ArrayList<String>();
+
+                int selection = -1;
+                int count = 0;
+                while (aliases.hasMoreElements()) {
+                    String alias = aliases.nextElement();
+                    mKeyAliases.add(alias);
+                    aliasList.add(alias);
+                    if (selection == -1 && alias.equalsIgnoreCase(keyAlias)) {
+                        selection = count;
+                    }
+                    count++;
+                }
+                
+                mWizard.setExistingAliases(aliasList);
+
+                if (selection != -1) {
+                    mKeyAliases.select(selection);
+
+                    // since a match was found and is selected, we need to give it to
+                    // the wizard as well
+                    mWizard.setKeyAlias(keyAlias);
+                } else {
+                    mKeyAliases.clearSelection();
+                }
+
+                // reset the password
+                mKeyPassword.setText(""); //$NON-NLS-1$
+
+                // enable onChange, and call it to display errors and enable/disable pageCompleted.
+                mDisableOnChange = false;
+                onChange();
+            } catch (KeyStoreException e) {
+                onException(e);
+            } catch (FileNotFoundException e) {
+                onException(e);
+            } catch (NoSuchAlgorithmException e) {
+                onException(e);
+            } catch (CertificateException e) {
+                onException(e);
+            } catch (IOException e) {
+                onException(e);
+            } finally {
+                // in case we exit with an exception, we need to reset this
+                mDisableOnChange = false;
+            }
+        }
+    }
+    
+    @Override
+    public IWizardPage getPreviousPage() {
+        return mWizard.getKeystoreSelectionPage();
+    }
+
+    @Override
+    public IWizardPage getNextPage() {
+        if (mWizard.getKeyCreationMode()) {
+            return mWizard.getKeyCreationPage();
+        }
+        
+        return mWizard.getKeyCheckPage();
+    }
+
+    /**
+     * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
+     */
+    private void onChange() {
+        if (mDisableOnChange) {
+            return;
+        }
+
+        setErrorMessage(null);
+        setMessage(null);
+
+        if (mWizard.getKeyCreationMode() == false) {
+            if (mKeyAliases.getSelectionIndex() == -1) {
+                setErrorMessage("Select a key alias.");
+                setPageComplete(false);
+                return;
+            }
+    
+            if (mKeyPassword.getText().trim().length() == 0) {
+                setErrorMessage("Enter key password.");
+                setPageComplete(false);
+                return;
+            }
+        }
+
+        setPageComplete(true);
+    }
+    
+    private void enableWidgets() {
+        boolean useKey = !mWizard.getKeyCreationMode();
+        mKeyAliasesLabel.setEnabled(useKey);
+        mKeyAliases.setEnabled(useKey);
+        mKeyPassword.setEnabled(useKey);
+        mKeyPasswordLabel.setEnabled(useKey);
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeystoreSelectionPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeystoreSelectionPage.java
new file mode 100644
index 0000000..c5a4d47
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/KeystoreSelectionPage.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2008 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.project.export;
+
+import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import java.io.File;
+
+/**
+ * Keystore selection page. This page allows to choose to create a new keystore or use an
+ * existing one. 
+ */
+final class KeystoreSelectionPage extends ExportWizardPage {
+
+    private final ExportWizard mWizard;
+    private Button mUseExistingKeystore;
+    private Button mCreateKeystore;
+    private Text mKeystore;
+    private Text mKeystorePassword;
+    private Label mConfirmLabel;
+    private Text mKeystorePassword2;
+    private boolean mDisableOnChange = false;
+
+    protected KeystoreSelectionPage(ExportWizard wizard, String pageName) {
+        super(pageName);
+        mWizard = wizard;
+
+        setTitle("Keystore selection");
+        setDescription(""); //TODO
+    }
+
+    public void createControl(Composite parent) {
+        Composite composite = new Composite(parent, SWT.NULL);
+        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+        GridLayout gl = new GridLayout(3, false);
+        composite.setLayout(gl);
+        
+        GridData gd;
+        
+        mUseExistingKeystore = new Button(composite, SWT.RADIO);
+        mUseExistingKeystore.setText("Use existing keystore");
+        mUseExistingKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        gd.horizontalSpan = 3;
+        mUseExistingKeystore.setSelection(true);
+
+        mCreateKeystore = new Button(composite, SWT.RADIO);
+        mCreateKeystore.setText("Create new keystore");
+        mCreateKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        gd.horizontalSpan = 3;
+
+        new Label(composite, SWT.NONE).setText("Location:");
+        mKeystore = new Text(composite, SWT.BORDER);
+        mKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        final Button browseButton = new Button(composite, SWT.PUSH);
+        browseButton.setText("Browse...");
+        browseButton.addSelectionListener(new SelectionAdapter() {
+           @Override
+           public void widgetSelected(SelectionEvent e) {
+               FileDialog fileDialog;
+               if (mUseExistingKeystore.getSelection()) {
+                   fileDialog = new FileDialog(browseButton.getShell(),SWT.OPEN);
+                   fileDialog.setText("Load Keystore");
+               } else {
+                   fileDialog = new FileDialog(browseButton.getShell(),SWT.SAVE);
+                   fileDialog.setText("Select Keystore Name");
+               }
+
+               String fileName = fileDialog.open();
+               if (fileName != null) {
+                   mKeystore.setText(fileName);
+               }
+           }
+        });
+
+        new Label(composite, SWT.NONE).setText("Password:");
+        mKeystorePassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+        mKeystorePassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        mKeystorePassword.addVerifyListener(sPasswordVerifier);
+        new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+        gd.heightHint = gd.widthHint = 0;
+
+        mConfirmLabel = new Label(composite, SWT.NONE);
+        mConfirmLabel.setText("Confirm:");
+        mKeystorePassword2 = new Text(composite, SWT.BORDER | SWT.PASSWORD);
+        mKeystorePassword2.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+        mKeystorePassword2.addVerifyListener(sPasswordVerifier);
+        new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
+        gd.heightHint = gd.widthHint = 0;
+        mKeystorePassword2.setEnabled(false);
+
+        // Show description the first time
+        setErrorMessage(null);
+        setMessage(null);
+        setControl(composite);
+        
+        mUseExistingKeystore.addSelectionListener(new SelectionAdapter() {
+           @Override
+           public void widgetSelected(SelectionEvent e) {
+               boolean createStore = !mUseExistingKeystore.getSelection();
+               mKeystorePassword2.setEnabled(createStore);
+               mConfirmLabel.setEnabled(createStore);
+               mWizard.setKeystoreCreationMode(createStore);
+               onChange();
+            }
+        });
+        
+        mKeystore.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                mWizard.setKeystore(mKeystore.getText().trim());
+                onChange();
+            }
+        });
+
+        mKeystorePassword.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                mWizard.setKeystorePassword(mKeystorePassword.getText());
+                onChange();
+            }
+        });
+
+        mKeystorePassword2.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                onChange();
+            }
+        });
+    }
+    
+    @Override
+    public IWizardPage getNextPage() {
+        if (mUseExistingKeystore.getSelection()) {
+            return mWizard.getKeySelectionPage();
+        }
+        
+        return mWizard.getKeyCreationPage();
+    }
+    
+    @Override
+    void onShow() {
+        // fill the texts with information loaded from the project.
+        if ((mProjectDataChanged & DATA_PROJECT) != 0) {
+            // reset the keystore/alias from the content of the project
+            IProject project = mWizard.getProject();
+            
+            // disable onChange for now. we'll call it once at the end.
+            mDisableOnChange = true;
+            
+            String keystore = ProjectHelper.loadStringProperty(project,
+                    ExportWizard.PROPERTY_KEYSTORE);
+            if (keystore != null) {
+                mKeystore.setText(keystore);
+            }
+            
+            // reset the passwords
+            mKeystorePassword.setText(""); //$NON-NLS-1$
+            mKeystorePassword2.setText(""); //$NON-NLS-1$
+            
+            // enable onChange, and call it to display errors and enable/disable pageCompleted.
+            mDisableOnChange = false;
+            onChange();
+        }
+    }
+
+    /**
+     * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
+     */
+    private void onChange() {
+        if (mDisableOnChange) {
+            return;
+        }
+
+        setErrorMessage(null);
+        setMessage(null);
+
+        boolean createStore = !mUseExistingKeystore.getSelection();
+
+        // checks the keystore path is non null.
+        String keystore = mKeystore.getText().trim();
+        if (keystore.length() == 0) {
+            setErrorMessage("Enter path to keystore.");
+            setPageComplete(false);
+            return;
+        } else {
+            File f = new File(keystore);
+            if (f.exists() == false) {
+                if (createStore == false) {
+                    setErrorMessage("Keystore does not exist.");
+                    setPageComplete(false);
+                    return;
+                }
+            } else if (f.isDirectory()) {
+                setErrorMessage("Keystore path is a directory.");
+                setPageComplete(false);
+                return;
+            } else if (f.isFile()) {
+                if (createStore) {
+                    setErrorMessage("File already exists.");
+                    setPageComplete(false);
+                    return;
+                }
+            }
+        }
+        
+        String value = mKeystorePassword.getText();
+        if (value.length() == 0) {
+            setErrorMessage("Enter keystore password.");
+            setPageComplete(false);
+            return;
+        } else if (createStore && value.length() < 6) {
+            setErrorMessage("Keystore password is too short - must be at least 6 characters.");
+            setPageComplete(false);
+            return;
+        }
+
+        if (createStore) {
+            if (mKeystorePassword2.getText().length() == 0) {
+                setErrorMessage("Confirm keystore password.");
+                setPageComplete(false);
+                return;
+            }
+            
+            if (mKeystorePassword.getText().equals(mKeystorePassword2.getText()) == false) {
+                setErrorMessage("Keystore passwords do not match.");
+                setPageComplete(false);
+                return;
+            }
+        }
+
+        setPageComplete(true);
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/PreExportPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ProjectCheckPage.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/PreExportPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ProjectCheckPage.java
index 5fc204d..3614be3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/PreExportPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/ProjectCheckPage.java
@@ -47,7 +47,7 @@
 /**
  * First Export Wizard Page. Display warning/errors. 
  */
-public class PreExportPage extends ExportWizardPage {
+final class ProjectCheckPage extends ExportWizardPage {
     private final static String IMG_ERROR = "error.png"; //$NON-NLS-1$
     private final static String IMG_WARNING = "warning.png"; //$NON-NLS-1$
 
@@ -60,12 +60,13 @@
     private Composite mErrorComposite;
     private Text mProjectText;
     private ProjectChooserHelper mProjectChooserHelper;
+    private boolean mFirstOnShow = true;
 
-    protected PreExportPage(ExportWizard wizard, String pageName) {
+    protected ProjectCheckPage(ExportWizard wizard, String pageName) {
         super(pageName);
         mWizard = wizard;
 
-        setTitle("Pre Export Checks");
+        setTitle("Project Checks");
         setDescription("Performs a set of checks to make sure the application can be exported.");
     }
 
@@ -123,10 +124,14 @@
 
     @Override
     void onShow() {
-        // get the project and init the ui
-        IProject project = mWizard.getProject();
-        if (project != null) {
-            mProjectText.setText(project.getName());
+        if (mFirstOnShow) {
+            // get the project and init the ui
+            IProject project = mWizard.getProject();
+            if (project != null) {
+                mProjectText.setText(project.getName());
+            }
+            
+            mFirstOnShow = false;
         }
     }
     
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/SigningExportPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/SigningExportPage.java
deleted file mode 100644
index 5e7ed0f..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/export/SigningExportPage.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2008 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.project.export;
-
-import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.project.export.ExportWizard.ExportWizardPage;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-
-import java.io.File;
-
-/**
- * Second export wizard page. 
- */
-public class SigningExportPage extends ExportWizardPage {
-
-    private final ExportWizard mWizard;
-    private Text mKeystore;
-    private Text mAlias;
-    private Text mKeystorePassword;
-    private Text mKeyPassword;
-    private boolean mDisableOnChange = false;
-
-    protected SigningExportPage(ExportWizard wizard, String pageName) {
-        super(pageName);
-        mWizard = wizard;
-
-        setTitle("Application Signing");
-        setDescription("Defines which store, key and certificate to use to sign the Android Application.");
-    }
-
-    public void createControl(Composite parent) {
-        Composite composite = new Composite(parent, SWT.NULL);
-        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
-        GridLayout gl = new GridLayout(3, false);
-        composite.setLayout(gl);
-        
-        GridData gd;
-
-        new Label(composite, SWT.NONE).setText("Keystore:");
-        mKeystore = new Text(composite, SWT.BORDER);
-        mKeystore.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-        final Button browseButton = new Button(composite, SWT.PUSH);
-        browseButton.setText("Browse...");
-        browseButton.addSelectionListener(new SelectionAdapter() {
-           @Override
-           public void widgetSelected(SelectionEvent e) {
-               FileDialog fileDialog = new FileDialog(browseButton.getShell(), SWT.OPEN);
-               fileDialog.setText("Load Keystore");
-
-               String fileName = fileDialog.open();
-               if (fileName != null) {
-                   mKeystore.setText(fileName);
-               }
-           }
-        });
-        
-        new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
-        gd.horizontalSpan = 2;
-        gd.heightHint = 0;
-        new Button(composite, SWT.PUSH).setText("New...");
-
-        new Label(composite, SWT.NONE).setText("Key Alias:");
-        mAlias = new Text(composite, SWT.BORDER);
-        mAlias.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-
-        new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-        gd.horizontalSpan = 3;
-
-        new Label(composite, SWT.NONE).setText("Store password:");
-        mKeystorePassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
-        mKeystorePassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-        new Composite(composite, SWT.NONE).setLayoutData(gd = new GridData());
-        gd.heightHint = gd.widthHint = 0;
-
-        new Label(composite, SWT.NONE).setText("Key password:");
-        mKeyPassword = new Text(composite, SWT.BORDER | SWT.PASSWORD);
-        mKeyPassword.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-
-        // Show description the first time
-        setErrorMessage(null);
-        setMessage(null);
-        setControl(composite);
-        
-        mKeystore.addModifyListener(new ModifyListener() {
-            public void modifyText(ModifyEvent e) {
-                mWizard.setKeystore(mKeystore.getText().trim());
-                onChange();
-            }
-        });
-        mAlias.addModifyListener(new ModifyListener() {
-            public void modifyText(ModifyEvent e) {
-                mWizard.setKeyAlias(mAlias.getText().trim());
-                onChange();
-            }
-        });
-        mKeystorePassword.addModifyListener(new ModifyListener() {
-            public void modifyText(ModifyEvent e) {
-                mWizard.setKeystorePassword(mKeystorePassword.getText().trim().toCharArray());
-                onChange();
-            }
-        });
-        mKeyPassword.addModifyListener(new ModifyListener() {
-            public void modifyText(ModifyEvent e) {
-                mWizard.setKeyPassword(mKeyPassword.getText().trim().toCharArray());
-                onChange();
-            }
-        });
-    }
-    
-    @Override
-    void onShow() {
-        // fill the texts with information loaded from the project.
-        if (mNewProjectReference) {
-            // reset the keystore/alias from the content of the project
-            IProject project = mWizard.getProject();
-            
-            // disable onChange for now. we'll call it once at the end.
-            mDisableOnChange = true;
-            
-            String keystore = ProjectHelper.loadStringProperty(project,
-                    ExportWizard.PROPERTY_KEYSTORE);
-            if (keystore != null) {
-                mKeystore.setText(keystore);
-            }
-            
-            String alias = ProjectHelper.loadStringProperty(project, ExportWizard.PROPERTY_ALIAS);
-            if (alias != null) {
-                mAlias.setText(alias);
-            }
-            
-            // reset the passwords
-            mKeystorePassword.setText(""); //$NON-NLS-1$
-            mKeyPassword.setText(""); //$NON-NLS-1$
-            
-            // enable onChange, and call it to display errors and enable/disable pageCompleted.
-            mDisableOnChange = false;
-            onChange();
-        }
-    }
-
-    /**
-     * Handles changes and update the error message and calls {@link #setPageComplete(boolean)}.
-     */
-    private void onChange() {
-        if (mDisableOnChange) {
-            return;
-        }
-
-        setErrorMessage(null);
-        setMessage(null);
-
-        // checks the keystore path is non null.
-        String keystore = mKeystore.getText().trim();
-        if (keystore.length() == 0) {
-            setErrorMessage("Enter path to keystore.");
-            setPageComplete(false);
-            return;
-        } else {
-            File f = new File(keystore);
-            if (f.exists() == false) {
-                setErrorMessage("Keystore does not exists!");
-                setPageComplete(false);
-                return;
-            } else if (f.isDirectory()) {
-                setErrorMessage("Keystore is a directory!");
-                setPageComplete(false);
-                return;
-            }
-        }
-        
-        if (mAlias.getText().trim().length() == 0) {
-            setErrorMessage("Enter key alias.");
-            setPageComplete(false);
-            return;
-        }
-
-        if (mKeystorePassword.getText().trim().length() == 0) {
-            setErrorMessage("Enter keystore password.");
-            setPageComplete(false);
-            return;
-        }
-
-        if (mKeyPassword.getText().trim().length() == 0) {
-            setErrorMessage("Enter key password.");
-            setPageComplete(false);
-            return;
-        }
-
-        setPageComplete(true);
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java
index d7b290b..945fe52 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainer.java
@@ -27,16 +27,19 @@
     
     private IClasspathEntry[] mClasspathEntry;
     private IPath mContainerPath;
+    private String mName;
     
     /**
      * Constructs the container with the {@link IClasspathEntry} representing the android
      * framework jar file and the container id
      * @param entry the entry representing the android framework.
      * @param path the path containing the classpath container id.
+     * @param name the name of the container to display.
      */
-    AndroidClasspathContainer(IClasspathEntry entry, IPath path) {
+    AndroidClasspathContainer(IClasspathEntry entry, IPath path, String name) {
         mClasspathEntry = new IClasspathEntry[] { entry };
         mContainerPath = path;
+        mName = name;
     }
     
     public IClasspathEntry[] getClasspathEntries() {
@@ -44,7 +47,7 @@
     }
 
     public String getDescription() {
-        return "Android Library";
+        return mName;
     }
 
     public int getKind() {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java
index 5dca350..2cafa01 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java
@@ -16,10 +16,16 @@
 
 package com.android.ide.eclipse.adt.project.internal;
 
+import com.android.ide.eclipse.adt.AdtConstants;
 import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.ide.eclipse.common.project.BaseProjectHelper;
+import com.android.sdklib.IAndroidTarget;
 
+import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.NullProgressMonitor;
@@ -38,10 +44,6 @@
  * {@link IProject}s. This removes the hard-coded path to the android.jar.
  */
 public class AndroidClasspathContainerInitializer extends ClasspathContainerInitializer {
-    /** The old container id */
-    private final static String OLD_CONTAINER_ID =
-        "com.android.ide.eclipse.adt.project.AndroidClasspathContainerInitializer"; //$NON-NLS-1$
-
     /** The container id for the android framework jar file */
     private final static String CONTAINER_ID =
         "com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"; //$NON-NLS-1$
@@ -58,17 +60,10 @@
      */
     @Override
     public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
-        String id = null;
-        if (OLD_CONTAINER_ID.equals(containerPath.toString())) {
-            id = OLD_CONTAINER_ID;
-        } else if (CONTAINER_ID.equals(containerPath.toString())) {
-            id = CONTAINER_ID;
-        }
-        
-        if (id != null) {
-            JavaCore.setClasspathContainer(new Path(id),
+        if (CONTAINER_ID.equals(containerPath.toString())) {
+            JavaCore.setClasspathContainer(new Path(CONTAINER_ID),
                     new IJavaProject[] { project },
-                    new IClasspathContainer[] { allocateAndroidContainer(id) },
+                    new IClasspathContainer[] { allocateAndroidContainer(CONTAINER_ID, project) },
                     new NullProgressMonitor());
         }
     }
@@ -82,15 +77,6 @@
     }
 
     /**
-     * Checks the {@link IPath} objects against the old android framework container id and
-     * returns <code>true</code> if they are identical.
-     * @param path the <code>IPath</code> to check.
-     */
-    public static boolean checkOldPath(IPath path) {
-        return OLD_CONTAINER_ID.equals(path.toString());
-    }
-    
-    /**
      * Checks the {@link IPath} objects against the android framework container id and
      * returns <code>true</code> if they are identical.
      * @param path the <code>IPath</code> to check.
@@ -106,41 +92,18 @@
      * @return <code>true</code> if success, <code>false</code> otherwise.
      */
     public static boolean updateProjects(IJavaProject[] androidProjects) {
-        
         try {
-            // because those projects could have the old id, we are going to fix
-            // them dynamically here.
-            for (IJavaProject javaProject: androidProjects) {
-                IClasspathEntry[] entries = javaProject.getRawClasspath();
-    
-                int containerIndex = ProjectHelper.findClasspathEntryByPath(entries,
-                        OLD_CONTAINER_ID,
-                        IClasspathEntry.CPE_CONTAINER);
-                if (containerIndex != -1) {
-                    // the project has the old container, we remove it
-                    entries = ProjectHelper.removeEntryFromClasspath(entries, containerIndex);
-                    
-                    // we add the new one instead
-                    entries = ProjectHelper.addEntryToClasspath(entries, getContainerEntry());
-
-                    // and give the new entries to the project
-                    javaProject.setRawClasspath(entries, new NullProgressMonitor());
-                }
-            }
-            
             // Allocate a new AndroidClasspathContainer, and associate it to the android framework 
             // container id for each projects.
             // By providing a new association between a container id and a IClasspathContainer,
             // this forces the JDT to query the IClasspathContainer for new IClasspathEntry (with
             // IClasspathContainer#getClasspathEntries()), and therefore force recompilation of 
             // the projects.
-            // TODO: We could only do that for the projects haven't fixed above
-            // (this isn't something that will happen a lot though)
             int projectCount = androidProjects.length;
 
             IClasspathContainer[] containers = new IClasspathContainer[projectCount];
             for (int i = 0 ; i < projectCount; i++) {
-                containers[i] = allocateAndroidContainer(CONTAINER_ID);
+                containers[i] = allocateAndroidContainer(CONTAINER_ID, androidProjects[i]);
             }
 
             // give each project their new container in one call.
@@ -158,23 +121,123 @@
      * Allocates and returns an {@link AndroidClasspathContainer} object with the proper
      * path to the framework jar file.
      * @param containerId the container id to be used.
+     * @param javaProject The java project that will receive the container.
      */
-    private static IClasspathContainer allocateAndroidContainer(String containerId) {
-        return new AndroidClasspathContainer(createFrameworkClasspath(), new Path(containerId));
+    private static IClasspathContainer allocateAndroidContainer(String containerId,
+            IJavaProject javaProject) {
+        IProject iProject = javaProject.getProject();
+
+        // remove potential MARKER_TARGETs.
+        try {
+            if (iProject.exists()) {
+                iProject.deleteMarkers(AdtConstants.MARKER_TARGET, true,
+                        IResource.DEPTH_INFINITE);
+            }
+        } catch (CoreException ce) {
+            // just log the error
+            AdtPlugin.log(ce, "Error removing target marker.");
+        }
+
+        
+        // first we check if the SDK has been loaded
+        boolean sdkIsLoaded = AdtPlugin.getDefault().getSdkLoadStatus(javaProject) ==
+            LoadStatus.LOADED;
+
+        // then we check if the project has a valid target.
+        IAndroidTarget target = null;
+        if (sdkIsLoaded) {
+            target = Sdk.getCurrent().getTarget(iProject);
+        }
+
+        // if we are loaded and the target is non null, we create a valid ClassPathContainer
+        if (sdkIsLoaded && target != null) {
+            String targetName = null;
+            if (target.isPlatform()) {
+                targetName = target.getName();
+            } else {
+                targetName = String.format("%1$s (%2$s)", target.getName(),
+                        target.getApiVersionName());
+            }
+    
+            return new AndroidClasspathContainer(createFrameworkClasspath(target),
+                    new Path(containerId), targetName);
+        }
+
+        // else we put a marker on the project, and return a dummy container (to replace the
+        // previous one if there was one.)
+        
+        // Get the project's target's hash string (if it exists)
+        String hashString = Sdk.getProjectTargetHashString(iProject);
+        
+        String message = null;
+        boolean outputToConsole = true;
+        if (hashString == null || hashString.length() == 0) {
+            message = String.format(
+                    "Project has no target set. Edit the project properties to set one.");
+        } else if (sdkIsLoaded) {
+            message = String.format(
+                    "Unable to resolve target '%s'", hashString);
+        } else {
+            // this is the case where there is a hashString but the SDK is not yet
+            // loaded and therefore we can't get the target yet.
+            message = String.format(
+                    "Unable to resolve target '%s' until the SDK is loaded.", hashString);
+            
+            // let's not log this one to the console as it will happen at every boot,
+            // and it's expected. (we do keep the error marker though).
+            outputToConsole = false;
+        }
+
+        // log the error and put the marker on the project
+        if (outputToConsole) {
+            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_ALWAYS, iProject, message);
+        }
+        IMarker marker = BaseProjectHelper.addMarker(iProject, AdtConstants.MARKER_TARGET, message,
+                IMarker.SEVERITY_ERROR);
+        
+        // add a marker priority as this is an more important error than the error that will
+        // spring from the lack of library
+        try {
+            marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
+        } catch (CoreException e) {
+            // just log the error
+            AdtPlugin.log(e, "Error changing target marker priority.");
+        }
+        
+        // return a dummy container to replace the one we may have had before.
+        return new IClasspathContainer() {
+            public IClasspathEntry[] getClasspathEntries() {
+                return new IClasspathEntry[0];
+            }
+
+            public String getDescription() {
+                return "Unable to get system library for the project";
+            }
+
+            public int getKind() {
+                return IClasspathContainer.K_DEFAULT_SYSTEM;
+            }
+
+            public IPath getPath() {
+                return null;
+            }
+        };
     }
 
     /**
-     * Creates and returns a new {@link IClasspathEntry} object for the android framework.
-     * <p/>This references the OS path to the android.jar and the java doc directory. This is
-     * dynamically created when a project is opened, and never saved in the project itself, so
-     * there's no risk of storing an obsolete path. 
+     * Creates and returns a new {@link IClasspathEntry} object for the android
+     * framework. <p/>This references the OS path to the android.jar and the
+     * java doc directory. This is dynamically created when a project is opened,
+     * and never saved in the project itself, so there's no risk of storing an
+     * obsolete path.
+     * 
+     * @param target The target that contains the libraries.
      */
-    private static IClasspathEntry createFrameworkClasspath() {
+    private static IClasspathEntry createFrameworkClasspath(IAndroidTarget target) {
         // now add the android framework to the class path.
         // create the path object.
-        IPath android_lib = new Path(AdtPlugin.getOsAbsoluteFramework());
-
-        IPath android_src = new Path(AdtPlugin.getOsAbsoluteAndroidSources());
+        IPath android_lib = new Path(target.getPath(IAndroidTarget.ANDROID_JAR));
+        IPath android_src = new Path(target.getPath(IAndroidTarget.SOURCES));
         
         // create the java doc link.
         IClasspathAttribute cpAttribute = JavaCore.newClasspathAttribute(
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java
new file mode 100644
index 0000000..584dd0d
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/properties/AndroidPropertyPage.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 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.project.properties;
+
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdkuilib.SdkTargetSelector;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbenchPropertyPage;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+/**
+ * Property page for "Android" project.
+ * This is accessible from the Package Explorer when right clicking a project and choosing
+ * "Properties".
+ *
+ */
+public class AndroidPropertyPage extends PropertyPage implements IWorkbenchPropertyPage {
+
+    private IProject mProject;
+    private SdkTargetSelector mSelector;
+
+    public AndroidPropertyPage() {
+        // pass
+    }
+
+    @Override
+    protected Control createContents(Composite parent) {
+        // get the element (this is not yet valid in the constructor).
+        mProject = (IProject)getElement();
+        
+        Composite top = new Composite(parent, SWT.NONE);
+        top.setLayoutData(new GridData(GridData.FILL_BOTH));
+        top.setLayout(new GridLayout(1, false));
+
+        Label l = new Label(top, SWT.NONE);
+        l.setText("Project Target");
+        
+        // get the targets from the sdk
+        IAndroidTarget[] targets = null;
+        if (Sdk.getCurrent() != null) {
+            targets = Sdk.getCurrent().getTargets();
+        }
+        
+        // build the UI.
+        mSelector = new SdkTargetSelector(top, targets, false /*allowMultipleSelection*/);
+
+        if (Sdk.getCurrent() != null) {
+            IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
+            if (target != null) {
+                mSelector.setSelection(target);
+            }
+        }
+
+        mSelector.setSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                // look for the selection and validate the page if there is a selection
+                IAndroidTarget target = mSelector.getFirstSelected();
+                setValid(target != null);
+            }
+        });
+
+        return top;
+    }
+
+    @Override
+    public boolean performOk() {
+        if (Sdk.getCurrent() != null) {
+            Sdk.getCurrent().setProject(mProject, mSelector.getFirstSelected());
+        }
+        
+        return true;
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/AndroidJarLoader.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidJarLoader.java
similarity index 92%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/AndroidJarLoader.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidJarLoader.java
index 8c37f05..fad4f19 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/AndroidJarLoader.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidJarLoader.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
 
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
 import com.android.ide.eclipse.common.AndroidConstants;
 
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -35,9 +34,12 @@
 /**
  * Custom class loader able to load a class from the SDK jar file.
  */
-public class AndroidJarLoader extends ClassLoader implements IAndroidLoader {
+public class AndroidJarLoader extends ClassLoader implements IAndroidClassLoader {
     
-    public final static class ClassWrapper implements IClass {
+    /**
+     * Wrapper around a {@link Class} to provide the methods of {@link IClassDescriptor}.
+     */
+    public final static class ClassWrapper implements IClassDescriptor {
         private Class<?> mClass;
 
         public ClassWrapper(Class<?> clazz) {
@@ -48,9 +50,9 @@
             return mClass.getCanonicalName();
         }
 
-        public IClass[] getDeclaredClasses() {
+        public IClassDescriptor[] getDeclaredClasses() {
             Class<?>[] classes = mClass.getDeclaredClasses();
-            IClass[] iclasses = new IClass[classes.length];
+            IClassDescriptor[] iclasses = new IClassDescriptor[classes.length];
             for (int i = 0 ; i < classes.length ; i++) {
                 iclasses[i] = new ClassWrapper(classes[i]);
             }
@@ -58,7 +60,7 @@
             return iclasses;
         }
 
-        public IClass getEnclosingClass() {
+        public IClassDescriptor getEnclosingClass() {
             return new ClassWrapper(mClass.getEnclosingClass());
         }
 
@@ -66,7 +68,7 @@
             return mClass.getSimpleName();
         }
 
-        public IClass getSuperclass() {
+        public IClassDescriptor getSuperclass() {
             return new ClassWrapper(mClass.getSuperclass());
         }
         
@@ -131,17 +133,18 @@
      * @param packageFilter The package that contains all the class data to preload, using a fully
      *                    qualified binary name (.e.g "com.my.package."). The matching algorithm
      *                    is simple "startsWith". Use an empty string to include everything.
+     * @param taskLabel An optional task name for the sub monitor. Can be null.
      * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
      * @throws IOException
      * @throws InvalidAttributeValueException
      * @throws ClassFormatError
      */
-    public void preLoadClasses(String packageFilter, IProgressMonitor monitor)
+    public void preLoadClasses(String packageFilter, String taskLabel, IProgressMonitor monitor)
         throws IOException, InvalidAttributeValueException, ClassFormatError {
         // Transform the package name into a zip entry path
         String pathFilter = packageFilter.replaceAll("\\.", "/"); //$NON-NLS-1$ //$NON-NLS-2$
         
-        SubMonitor progress = SubMonitor.convert(monitor, 100);
+        SubMonitor progress = SubMonitor.convert(monitor, taskLabel == null ? "" : taskLabel, 100);
         
         // create streams to read the intermediary archive
         FileInputStream fis = new FileInputStream(mOsFrameworkLocation);
@@ -174,6 +177,7 @@
             // advance 5% of whatever is allocated on the progress bar
             progress.setWorkRemaining(100);
             progress.worked(5);
+            progress.subTask(String.format("Preload %1$s", className));
         }
     }
 
@@ -193,17 +197,18 @@
      * @throws InvalidAttributeValueException
      * @throws ClassFormatError
      */
-    public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(
+    public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
             String packageFilter,
             String[] superClasses)
             throws IOException, InvalidAttributeValueException, ClassFormatError {
 
         packageFilter = packageFilter.replaceAll("\\.", "/"); //$NON-NLS-1$ //$NON-NLS-2$
 
-        HashMap<String, ArrayList<IClass>> mClassesFound = new HashMap<String, ArrayList<IClass>>();
+        HashMap<String, ArrayList<IClassDescriptor>> mClassesFound =
+                new HashMap<String, ArrayList<IClassDescriptor>>();
 
         for (String className : superClasses) {
-            mClassesFound.put(className, new ArrayList<IClass>());
+            mClassesFound.put(className, new ArrayList<IClassDescriptor>());
         }
 
         // create streams to read the intermediary archive
@@ -415,7 +420,7 @@
      * @param className the fully-qualified name of the class to return.
      * @throws ClassNotFoundException
      */
-    public IClass getClass(String className) throws ClassNotFoundException {
+    public IClassDescriptor getClass(String className) throws ClassNotFoundException {
         try {
             return new ClassWrapper(loadClass(className));
         } catch (ClassNotFoundException e) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java
new file mode 100644
index 0000000..60561ab
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2007 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.sdk;
+
+import com.android.ide.eclipse.common.resources.IResourceRepository;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
+import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
+import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
+import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
+import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
+import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
+import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.layoutlib.api.ILayoutBridge;
+import com.android.sdklib.IAndroidTarget;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * This class contains the data of an Android Target as loaded from the SDK.
+ */
+public class AndroidTargetData {
+    
+    public final static int DESCRIPTOR_MANIFEST = 1;
+    public final static int DESCRIPTOR_LAYOUT = 2;
+    public final static int DESCRIPTOR_MENU = 3;
+    public final static int DESCRIPTOR_XML = 4;
+    public final static int DESCRIPTOR_RESOURCES = 5;
+    public final static int DESCRIPTOR_SEARCHABLE = 6;
+    public final static int DESCRIPTOR_PREFERENCES = 7;
+    
+    public final static class LayoutBridge {
+        /** Link to the layout bridge */
+        public ILayoutBridge bridge;
+
+        public LoadStatus status = LoadStatus.LOADING;
+        
+        public ClassLoader classLoader;
+    }
+
+    private final IAndroidTarget mTarget;
+
+    /**
+     * mAttributeValues is a map { key => list [ values ] }.
+     * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)".
+     * The attribute namespace prefix must be:
+     * - "android" for AndroidConstants.NS_RESOURCES
+     * - "xmlns" for the XMLNS URI.
+     * 
+     * This is used for attributes that do not have a unique name, but still need to be populated
+     * with values in the UI. Uniquely named attributes have their values in {@link #mEnumValueMap}.
+     */
+    private final Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>();
+    
+    private IResourceRepository mSystemResourceRepository;
+
+    private final AndroidManifestDescriptors mManifestDescriptors;
+    private final LayoutDescriptors mLayoutDescriptors;
+    private final MenuDescriptors mMenuDescriptors;
+    private final XmlDescriptors mXmlDescriptors;
+
+    private final Map<String, Map<String, Integer>> mEnumValueMap;
+
+    private final ProjectResources mFrameworkResources;
+    private final LayoutBridge mLayoutBridge;
+
+    private boolean mLayoutBridgeInit = false;
+
+    /**
+     * Creates an AndroidTargetData object.
+     */
+    AndroidTargetData(IAndroidTarget androidTarget,
+            IResourceRepository systemResourceRepository,
+            AndroidManifestDescriptors manifestDescriptors,
+            LayoutDescriptors layoutDescriptors,
+            MenuDescriptors menuDescriptors,
+            XmlDescriptors xmlDescriptors,
+            Map<String, Map<String, Integer>> enumValueMap,
+            String[] permissionValues,
+            String[] activityIntentActionValues,
+            String[] broadcastIntentActionValues,
+            String[] serviceIntentActionValues,
+            String[] intentCategoryValues,
+            ProjectResources resources,
+            LayoutBridge layoutBridge) {
+        
+        mTarget = androidTarget;
+        mSystemResourceRepository = systemResourceRepository;
+        mManifestDescriptors = manifestDescriptors;
+        mLayoutDescriptors = layoutDescriptors;
+        mMenuDescriptors = menuDescriptors;
+        mXmlDescriptors = xmlDescriptors;
+        mEnumValueMap = enumValueMap;
+        mFrameworkResources = resources;
+        mLayoutBridge = layoutBridge;
+
+        setPermissions(permissionValues);
+        setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues,
+                serviceIntentActionValues, intentCategoryValues);
+    }
+    
+    public IResourceRepository getSystemResources() {
+        return mSystemResourceRepository;
+    }
+    
+    /**
+     * Returns an {@link IDescriptorProvider} from a given Id.
+     * The Id can be one of {@link #DESCRIPTOR_MANIFEST}, {@link #DESCRIPTOR_LAYOUT},
+     * {@link #DESCRIPTOR_MENU}, or {@link #DESCRIPTOR_XML}.
+     * All other values will throw an {@link IllegalArgumentException}.
+     */
+    public IDescriptorProvider getDescriptorProvider(int descriptorId) {
+        switch (descriptorId) {
+            case DESCRIPTOR_MANIFEST:
+                return mManifestDescriptors;
+            case DESCRIPTOR_LAYOUT:
+                return mLayoutDescriptors;
+            case DESCRIPTOR_MENU:
+                return mMenuDescriptors;
+            case DESCRIPTOR_XML:
+                return mXmlDescriptors;
+            case DESCRIPTOR_RESOURCES:
+                // FIXME: since it's hard-coded the Resources Descriptors are not platform dependent.
+                return ResourcesDescriptors.getInstance();
+            case DESCRIPTOR_PREFERENCES:
+                return mXmlDescriptors.getPreferencesProvider();
+            case DESCRIPTOR_SEARCHABLE:
+                return mXmlDescriptors.getSearchableProvider();
+            default :
+                 throw new IllegalArgumentException();
+        }
+    }
+    
+    /**
+     * Returns the manifest descriptors.
+     */
+    public AndroidManifestDescriptors getManifestDescriptors() {
+        return mManifestDescriptors;
+    }
+    
+    /**
+     * Returns the layout Descriptors.
+     */
+    public LayoutDescriptors getLayoutDescriptors() {
+        return mLayoutDescriptors;
+    }
+    
+    /**
+     * Returns the menu descriptors.
+     */
+    public MenuDescriptors getMenuDescriptors() {
+        return mMenuDescriptors;
+    }
+
+    /**
+     * Returns the XML descriptors
+     */
+    public XmlDescriptors getXmlDescriptors() {
+        return mXmlDescriptors;
+    }
+
+    /**
+     * Returns this list of possible values for an XML attribute.
+     * <p/>This should only be called for attributes for which possible values depend on the
+     * parent element node.
+     * <p/>For attributes that have the same values no matter the parent node, use
+     * {@link #getEnumValueMap()}.  
+     * @param elementName the name of the element containing the attribute.
+     * @param attributeName the name of the attribute
+     * @return an array of String with the possible values, or <code>null</code> if no values were
+     * found.
+     */
+    public String[] getAttributeValues(String elementName, String attributeName) {
+        String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$
+        return mAttributeValues.get(key);
+    }
+
+    /**
+     * Returns this list of possible values for an XML attribute.
+     * <p/>This should only be called for attributes for which possible values depend on the
+     * parent and great-grand-parent element node.
+     * <p/>The typical example of this is for the 'name' attribute under
+     * activity/intent-filter/action
+     * <p/>For attributes that have the same values no matter the parent node, use
+     * {@link #getEnumValueMap()}.  
+     * @param elementName the name of the element containing the attribute.
+     * @param attributeName the name of the attribute
+     * @param greatGrandParentElementName the great-grand-parent node.
+     * @return an array of String with the possible values, or <code>null</code> if no values were
+     * found.
+     */
+    public String[] getAttributeValues(String elementName, String attributeName,
+            String greatGrandParentElementName) {
+        if (greatGrandParentElementName != null) {
+            String key = String.format("(%1$s,%2$s,%3$s)", //$NON-NLS-1$
+                    greatGrandParentElementName, elementName, attributeName); 
+            String[] values = mAttributeValues.get(key);
+            if (values != null) {
+                return values;
+            }
+        }
+        
+        return getAttributeValues(elementName, attributeName);
+    }
+
+    /**
+     * Returns the enum values map.
+     * <p/>The map defines the possible values for XML attributes. The key is the attribute name
+     * and the value is a map of (string, integer) in which the key (string) is the name of
+     * the value, and the Integer is the numerical value in the compiled binary XML files.
+     */
+    public Map<String, Map<String, Integer>> getEnumValueMap() {
+        return mEnumValueMap;
+    }
+    
+    /**
+     * Returns the {@link ProjectResources} containing the Framework Resources.
+     */
+    public ProjectResources getFrameworkResources() {
+        return mFrameworkResources;
+    }
+    
+    /**
+     * Returns a {@link LayoutBridge} object possibly containing a {@link ILayoutBridge} object.
+     * <p/>If {@link LayoutBridge#bridge} is <code>null</code>, {@link LayoutBridge#status} will
+     * contain the reason (either {@link LoadStatus#LOADING} or {@link LoadStatus#FAILED}).
+     * <p/>Valid {@link ILayoutBridge} objects are always initialized before being returned.
+     */
+    public synchronized LayoutBridge getLayoutBridge() {
+        if (mLayoutBridgeInit == false && mLayoutBridge.bridge != null) {
+            mLayoutBridge.bridge.init(mTarget.getPath(IAndroidTarget.FONTS),
+                    getEnumValueMap());
+            mLayoutBridgeInit = true;
+        }
+        return mLayoutBridge;
+    }
+    
+    /**
+     * Sets the permission values
+     * @param permissionValues the list of permissions
+     */
+    private void setPermissions(String[] permissionValues) {
+        setValues("(uses-permission,android:name)", permissionValues); //$NON-NLS-1$
+        setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$
+        setValues("(activity,android:permission)", permissionValues); //$NON-NLS-1$
+        setValues("(receiver,android:permission)", permissionValues); //$NON-NLS-1$
+        setValues("(service,android:permission)", permissionValues); //$NON-NLS-1$
+        setValues("(provider,android:permission)", permissionValues); //$NON-NLS-1$
+    }
+    
+    private void setIntentFilterActionsAndCategories(String[] activityIntentActions,
+            String[] broadcastIntentActions, String[] serviceIntentActions,
+            String[] intentCategoryValues) {
+        setValues("(activity,action,android:name)", activityIntentActions); //$NON-NLS-1$
+        setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$
+        setValues("(service,action,android:name)", serviceIntentActions); //$NON-NLS-1$
+        setValues("(category,android:name)", intentCategoryValues); //$NON-NLS-1$
+    }
+
+    /**
+     * Sets a (name, values) pair in the hash map.
+     * <p/>
+     * If the name is already present in the map, it is first removed.
+     * @param name the name associated with the values.
+     * @param values The values to add.
+     */
+    private void setValues(String name, String[] values) {
+        mAttributeValues.remove(name);
+        mAttributeValues.put(name, values);
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java
similarity index 68%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java
index 703efcf..232b9e8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceParser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2008 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.
@@ -14,19 +14,29 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData.LayoutBridge;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.resources.AttrsXmlParser;
 import com.android.ide.eclipse.common.resources.DeclareStyleableInfo;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.common.resources.IResourceRepository;
 import com.android.ide.eclipse.common.resources.ResourceItem;
 import com.android.ide.eclipse.common.resources.ResourceType;
 import com.android.ide.eclipse.common.resources.ViewClassInfo;
+import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
+import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
+import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
+import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
+import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.layoutlib.api.ILayoutBridge;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.SubMonitor;
 
 import java.io.BufferedReader;
@@ -34,10 +44,11 @@
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.net.MalformedURLException;
 import java.net.URL;
+import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -48,7 +59,7 @@
 import javax.management.InvalidAttributeValueException;
 
 /**
- * Parser for the framework library.
+ * Parser for the platform data in an SDK.
  * <p/>
  * This gather the following information:
  * <ul>
@@ -57,14 +68,16 @@
  * <li></li>
  * </ul> 
  */
-public final class FrameworkResourceParser {
+public final class AndroidTargetParser {
     
     private static final String TAG = "Framework Resource Parser";
+    private final IAndroidTarget mAndroidTarget;
 
     /**
-     * Creates a framework resource parser.
+     * Creates a platform data parser.
      */
-    public FrameworkResourceParser() {
+    public AndroidTargetParser(IAndroidTarget platformTarget) {
+        mAndroidTarget = platformTarget;
     }
     
     /**
@@ -77,34 +90,29 @@
      * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
      * @return True if the SDK path was valid and parsing has been attempted.
      */
-    public boolean parse(String osSdkPath, FrameworkResourceManager resourceManager,
-            IProgressMonitor monitor) {    
-        if (osSdkPath == null || osSdkPath.length() == 0) {
-            return false;
-        }
-
+    public IStatus run(IProgressMonitor monitor) {
         try {
-            SubMonitor progress = SubMonitor.convert(monitor, 100);
+            SubMonitor progress = SubMonitor.convert(monitor,
+                    String.format("Parsing SDK %1$s", mAndroidTarget.getName()),
+                    120);
             
             AndroidJarLoader classLoader =
-                new AndroidJarLoader(osSdkPath + AndroidConstants.FN_FRAMEWORK_LIBRARY);
+                new AndroidJarLoader(mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
             
-            progress.subTask("Preloading");
-            preload(classLoader, progress.newChild(40));
-            progress.setWorkRemaining(60);
+            preload(classLoader, progress.newChild(40, SubMonitor.SUPPRESS_NONE));
+            progress.setWorkRemaining(80);
             
             if (progress.isCanceled()) {
-                return false;
+                return Status.CANCEL_STATUS;
             }
             
             // get the resource Ids.
             progress.subTask("Resource IDs");
-            FrameworkResourceRepository systemResourceRepository = new FrameworkResourceRepository(
-                    collectResourceIds(classLoader));
+            IResourceRepository frameworkRepository = collectResourceIds(classLoader);
             progress.worked(5);
 
             if (progress.isCanceled()) {
-                return false;
+                return Status.CANCEL_STATUS;
             }
 
             // get the permissions
@@ -113,56 +121,59 @@
             progress.worked(5);
 
             if (progress.isCanceled()) {
-                return false;
+                return Status.CANCEL_STATUS;
             }
 
-            String osLibPath = osSdkPath + AndroidConstants.OS_SDK_LIBS_FOLDER;
-
             // get the action and category values for the Intents.
             progress.subTask("Intents");
             ArrayList<String> activity_actions = new ArrayList<String>();
             ArrayList<String> broadcast_actions = new ArrayList<String>();
             ArrayList<String> service_actions = new ArrayList<String>();
             ArrayList<String> categories = new ArrayList<String>();
-            collectIntentFilterActionsAndCategories(osLibPath,
-                    activity_actions, broadcast_actions, service_actions, categories);
+            collectIntentFilterActionsAndCategories(activity_actions, broadcast_actions,
+                    service_actions, categories);
             progress.worked(5);
 
             if (progress.isCanceled()) {
-                return false;
+                return Status.CANCEL_STATUS;
             }
 
-            progress.subTask("Layouts");
+            // gather the attribute definition
+            progress.subTask("Attributes definitions");
             AttrsXmlParser attrsXmlParser = new AttrsXmlParser(
-                    osSdkPath + AndroidConstants.OS_SDK_ATTRS_XML);
+                    mAndroidTarget.getPath(IAndroidTarget.ATTRIBUTES));
             attrsXmlParser.preload();
 
+            progress.subTask("Manifest definitions");
             AttrsXmlParser attrsManifestXmlParser = new AttrsXmlParser(
-                    osSdkPath + AndroidConstants.OS_SDK_ATTRS_MANIFEST_XML,
+                    mAndroidTarget.getPath(IAndroidTarget.MANIFEST_ATTRIBUTES),
                     attrsXmlParser);
             attrsManifestXmlParser.preload();
 
             Collection<ViewClassInfo> mainList = new ArrayList<ViewClassInfo>();
             Collection<ViewClassInfo> groupList = new ArrayList<ViewClassInfo>();
 
-            collectLayoutClasses(osLibPath, classLoader, attrsXmlParser, mainList, groupList,
+            // collect the layout/widgets classes
+            progress.subTask("Widgets and layouts");
+            collectLayoutClasses(classLoader, attrsXmlParser, mainList, groupList,
                     progress.newChild(40));
             
             if (progress.isCanceled()) {
-                return false;
+                return Status.CANCEL_STATUS;
             }
 
             ViewClassInfo[] layoutViewsInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
             ViewClassInfo[] layoutGroupsInfo = groupList.toArray(
                     new ViewClassInfo[groupList.size()]);
             
+            // collect the preferences classes.
             mainList.clear();
             groupList.clear();
             collectPreferenceClasses(classLoader, attrsXmlParser, mainList, groupList,
                     progress.newChild(5));
 
             if (progress.isCanceled()) {
-                return false;
+                return Status.CANCEL_STATUS;
             }
 
             ViewClassInfo[] preferencesInfo = mainList.toArray(new ViewClassInfo[mainList.size()]);
@@ -177,34 +188,77 @@
             Map<String, Map<String, Integer>> enumValueMap = attrsXmlParser.getEnumFlagValues();
 
             if (progress.isCanceled()) {
-                return false;
+                return Status.CANCEL_STATUS;
             }
             
-            String docBaseUrl = getDocumentationBaseUrl(
-                    osSdkPath + AndroidConstants.OS_SDK_DOCS_FOLDER);
+            // From the information that was collected, create the pieces that will be put in
+            // the PlatformData object.
+            AndroidManifestDescriptors manifestDescriptors = new AndroidManifestDescriptors(); 
+            manifestDescriptors.updateDescriptors(manifestMap);
+            progress.worked(10);
 
-            FrameworkResourceManager.getInstance().setResources(systemResourceRepository,
-                    layoutViewsInfo,
-                    layoutGroupsInfo,
-                    preferencesInfo,
-                    preferenceGroupsInfo,
-                    xmlMenuMap,
-                    xmlSearchableMap,
-                    manifestMap,
+            if (progress.isCanceled()) {
+                return Status.CANCEL_STATUS;
+            }
+
+            LayoutDescriptors layoutDescriptors = new LayoutDescriptors();
+            layoutDescriptors.updateDescriptors(layoutViewsInfo, layoutGroupsInfo);
+            progress.worked(10);
+
+            if (progress.isCanceled()) {
+                return Status.CANCEL_STATUS;
+            }
+
+            MenuDescriptors menuDescriptors = new MenuDescriptors();
+            menuDescriptors.updateDescriptors(xmlMenuMap);
+            progress.worked(10);
+
+            if (progress.isCanceled()) {
+                return Status.CANCEL_STATUS;
+            }
+
+            XmlDescriptors xmlDescriptors = new XmlDescriptors();
+            xmlDescriptors.updateDescriptors(xmlSearchableMap, preferencesInfo,
+                    preferenceGroupsInfo);
+            progress.worked(10);
+            
+            // load the framework resources.
+            ProjectResources resources = ResourceManager.getInstance().loadFrameworkResources(
+                    mAndroidTarget);
+            progress.worked(10);
+            
+            // now load the layout lib bridge
+            LayoutBridge layoutBridge = loadLayoutBridge();
+            progress.worked(10);
+            
+            // and finally create the PlatformData with all that we loaded.
+            AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget,
+                    frameworkRepository,
+                    manifestDescriptors,
+                    layoutDescriptors,
+                    menuDescriptors,
+                    xmlDescriptors,
                     enumValueMap,
                     permissionValues,
                     activity_actions.toArray(new String[activity_actions.size()]),
                     broadcast_actions.toArray(new String[broadcast_actions.size()]),
                     service_actions.toArray(new String[service_actions.size()]),
                     categories.toArray(new String[categories.size()]),
-                    docBaseUrl);
+                    resources,
+                    layoutBridge);
+            
+            Sdk.getCurrent().setTargetData(mAndroidTarget, targetData);
 
-            return true;
+            return Status.OK_STATUS;
         } catch (Exception e) {
             AdtPlugin.logAndPrintError(e, TAG, "SDK parser failed"); //$NON-NLS-1$
+            AdtPlugin.printToConsole("SDK parser failed", e.getMessage());
+            return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "SDK parser failed", e);
+        } finally {
+            if (monitor != null) {
+                monitor.done();
+            }
         }
-        
-        return false;
     }
 
     /**
@@ -217,7 +271,9 @@
      */
     private void preload(AndroidJarLoader classLoader, IProgressMonitor monitor) {
         try {
-            classLoader.preLoadClasses("" /* all classes */, monitor);  //$NON-NLS-1$
+            classLoader.preLoadClasses("" /* all classes */,        //$NON-NLS-1$
+                    mAndroidTarget.getName(),                       // monitor task label
+                    monitor);
         } catch (InvalidAttributeValueException e) {
             AdtPlugin.log(e, "Problem preloading classes"); //$NON-NLS-1$
         } catch (IOException e) {
@@ -226,24 +282,27 @@
     }
 
     /**
-     * Collects the resources IDs found in the SDK.
+     * Creates an IResourceRepository for the framework resources.
      * 
      * @param classLoader The framework SDK jar classloader
      * @return a map of the resources, or null if it failed.
      */
-    private Map<ResourceType, List<ResourceItem>> collectResourceIds(
+    private IResourceRepository collectResourceIds(
             AndroidJarLoader classLoader) {
         try {
             Class<?> r = classLoader.loadClass(AndroidConstants.CLASS_R);
             
             if (r != null) {
-                return parseRClass(r);
+                Map<ResourceType, List<ResourceItem>> map = parseRClass(r);
+                if (map != null) {
+                    return new FrameworkResourceRepository(map);
+                }
             }
         } catch (ClassNotFoundException e) {
             AdtPlugin.logAndPrintError(e, TAG,
                     "Collect resource IDs failed, class %1$s not found in %2$s", //$NON-NLS-1$
                     AndroidConstants.CLASS_R, 
-                    classLoader.getSource());
+                    mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
         }
         
         return null;
@@ -331,7 +390,7 @@
             AdtPlugin.logAndPrintError(e, TAG,
                     "Collect permissions failed, class %1$s not found in %2$s", //$NON-NLS-1$
                     AndroidConstants.CLASS_MANIFEST_PERMISSION, 
-                    classLoader.getSource());
+                    mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR));
         }
         
         return new String[0];
@@ -347,13 +406,17 @@
      * @param serviceActions the list which will receive the service action values.
      * @param categories the list which will receive the category values.
      */
-    private void collectIntentFilterActionsAndCategories(String osLibPath,
-            ArrayList<String> activityActions, ArrayList<String> broadcastActions,
+    private void collectIntentFilterActionsAndCategories(ArrayList<String> activityActions,
+            ArrayList<String> broadcastActions,
             ArrayList<String> serviceActions, ArrayList<String> categories)  {
-        collectValues(osLibPath + "activity_actions.txt" , activityActions);
-        collectValues(osLibPath + "broadcast_actions.txt" , broadcastActions);
-        collectValues(osLibPath + "service_actions.txt" , serviceActions);
-        collectValues(osLibPath + "categories.txt" , categories);
+        collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_ACTIVITY),
+                activityActions);
+        collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_BROADCAST),
+                broadcastActions);
+        collectValues(mAndroidTarget.getPath(IAndroidTarget.ACTIONS_SERVICE),
+                serviceActions);
+        collectValues(mAndroidTarget.getPath(IAndroidTarget.CATEGORIES),
+                categories);
     }
 
     /**
@@ -400,21 +463,21 @@
      * Collects all layout classes information from the class loader and the
      * attrs.xml and sets the corresponding structures in the resource manager.
      * 
-     * @param osLibPath The OS path to the SDK tools/lib folder, ending with a separator.
-     * @param classLoader The framework SDK jar classloader
+     * @param classLoader The framework SDK jar classloader in case we cannot get the widget from
+     * the platform directly
      * @param attrsXmlParser The parser of the attrs.xml file
      * @param mainList the Collection to receive the main list of {@link ViewClassInfo}.
      * @param groupList the Collection to receive the group list of {@link ViewClassInfo}.
      * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
      */
-    private void collectLayoutClasses(String osLibPath,
-            AndroidJarLoader classLoader,
+    private void collectLayoutClasses(AndroidJarLoader classLoader,
             AttrsXmlParser attrsXmlParser,
             Collection<ViewClassInfo> mainList, Collection<ViewClassInfo> groupList, 
             IProgressMonitor monitor) {
         LayoutParamsParser ldp = null;
         try {
-            WidgetListLoader loader = new WidgetListLoader(osLibPath + "widgets.txt");
+            WidgetClassLoader loader = new WidgetClassLoader(
+                    mAndroidTarget.getPath(IAndroidTarget.WIDGETS));
             if (loader.parseWidgetList(monitor)) {
                 ldp = new LayoutParamsParser(loader, attrsXmlParser);
             }
@@ -465,12 +528,13 @@
             }
         } catch (NoClassDefFoundError e) {
             AdtPlugin.logAndPrintError(e, TAG,
-                    "Collect preferences failed, class %1$s not found in %2$s", //$NON-NLS-1$
+                    "Collect preferences failed, class %1$s not found in %2$s",
                     e.getMessage(), 
                     classLoader.getSource());
         } catch (Throwable e) {
             AdtPlugin.log(e, "Android Framework Parser: failed to collect preference classes"); //$NON-NLS-1$
-            AdtPlugin.printErrorToConsole("Android Framework Parser", "failed to collect preference classes");
+            AdtPlugin.printErrorToConsole("Android Framework Parser",
+                    "failed to collect preference classes");
         }
     }
 
@@ -537,40 +601,51 @@
     }
 
     /**
-     * Returns the URL to the local documentation.
-     * Can return null if no documentation is found in the current SDK.
-     * 
-     * @param osDocsPath Path to the documentation folder in the current SDK.
-     *  The folder may not actually exist.
-     * @return A file:// URL on the local documentation folder if it exists or null.
+     * Loads the layout bridge from the dynamically loaded layoutlib.jar
      */
-    private String getDocumentationBaseUrl(String osDocsPath) {
-        File f = new File(osDocsPath);
+    private LayoutBridge loadLayoutBridge() {
+        LayoutBridge layoutBridge = new LayoutBridge();
 
-        if (f.isDirectory()) {
-            try {
-                // Note: to create a file:// URL, one would typically use something like
-                // f.toURI().toURL().toString(). However this generates a broken path on
-                // Windows, namely "C:\\foo" is converted to "file:/C:/foo" instead of
-                // "file:///C:/foo" (i.e. there should be 3 / after "file:"). So we'll
-                // do the correct thing manually.
+        try {
+            // get the URL for the file.
+            File f = new File(mAndroidTarget.getPath(IAndroidTarget.LAYOUT_LIB));
+            if (f.isFile() == false) {
+                AdtPlugin.log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$
+            } else {
+                URL url = f.toURL();
                 
-                String path = f.getAbsolutePath();
-                if (File.separatorChar != '/') {
-                    path = path.replace(File.separatorChar, '/');
+                // create a class loader. Because this jar reference interfaces
+                // that are in the editors plugin, it's important to provide 
+                // a parent class loader.
+                layoutBridge.classLoader = new URLClassLoader(new URL[] { url },
+                        this.getClass().getClassLoader());
+   
+                // load the class
+                Class<?> clazz = layoutBridge.classLoader.loadClass(AndroidConstants.CLASS_BRIDGE);
+                if (clazz != null) {
+                    // instantiate an object of the class.
+                    Constructor<?> constructor = clazz.getConstructor();
+                    if (constructor != null) {
+                        Object bridge = constructor.newInstance();
+                        if (bridge instanceof ILayoutBridge) {
+                            layoutBridge.bridge = (ILayoutBridge)bridge;
+                        }
+                    }
                 }
                 
-                // For some reason the URL class doesn't add the mandatory "//" after
-                // the "file:" protocol name, so it has to be hacked into the path.
-                URL url = new URL("file", null, "//" + path);  //$NON-NLS-1$ //$NON-NLS-2$
-                String result = url.toString();
-                return result;
-            } catch (MalformedURLException e) {
-                // ignore malformed URLs
+                if (layoutBridge.bridge == null) {
+                    layoutBridge.status = LoadStatus.FAILED;
+                    AdtPlugin.log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$
+                } else {
+                    layoutBridge.status = LoadStatus.LOADED;
+                }
             }
+        } catch (Throwable t) {
+            layoutBridge.status = LoadStatus.FAILED;
+            // log the error.
+            AdtPlugin.log(t, "Failed to load the LayoutLib");
         }
-
-        return null;
+        
+        return layoutBridge;
     }
-
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceRepository.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/FrameworkResourceRepository.java
similarity index 92%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceRepository.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/FrameworkResourceRepository.java
index 19a7de3..f4b10df 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/FrameworkResourceRepository.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/FrameworkResourceRepository.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
 
 import com.android.ide.eclipse.common.resources.IResourceRepository;
 import com.android.ide.eclipse.common.resources.ResourceItem;
@@ -26,9 +26,9 @@
 
 /**
  * Implementation of the {@link IResourceRepository} interface to hold the system resource Ids
- * parsed by {@link FrameworkResourceParser}. 
+ * parsed by {@link AndroidTargetParser}. 
  */
-public final class FrameworkResourceRepository implements IResourceRepository {
+final class FrameworkResourceRepository implements IResourceRepository {
     
     private Map<ResourceType, List<ResourceItem>> mResourcesMap; 
     
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/IAndroidLoader.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/IAndroidClassLoader.java
similarity index 77%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/IAndroidLoader.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/IAndroidClassLoader.java
index f0f48ca..50d319e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/IAndroidLoader.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/IAndroidClassLoader.java
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.resources;
-
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
+package com.android.ide.eclipse.adt.sdk;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -28,7 +26,25 @@
  * Classes which implements this interface provide methods to access framework resource
  * data loaded from the SDK.
  */
-public interface IAndroidLoader {
+public interface IAndroidClassLoader {
+    
+    /**
+     * Classes which implement this interface provide methods to describe a class.
+     */
+    public interface IClassDescriptor {
+
+        String getCanonicalName();
+
+        IClassDescriptor getSuperclass();
+
+        String getSimpleName();
+
+        IClassDescriptor getEnclosingClass();
+
+        IClassDescriptor[] getDeclaredClasses();
+        
+        boolean isInstantiable();
+    }
 
     /**
      * Finds and loads all classes that derive from a given set of super classes.
@@ -43,7 +59,7 @@
      * @throws InvalidAttributeValueException
      * @throws ClassFormatError
      */
-    public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(
+    public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
             String rootPackage, String[] superClasses)
         throws IOException, InvalidAttributeValueException, ClassFormatError;
 
@@ -52,7 +68,7 @@
      * @param className the fully-qualified name of the class to return.
      * @throws ClassNotFoundException
      */
-    public IClass getClass(String className) throws ClassNotFoundException;
+    public IClassDescriptor getClass(String className) throws ClassNotFoundException;
 
     /**
      * Returns a string indicating the source of the classes, typically for debugging
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/LayoutParamsParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LayoutParamsParser.java
similarity index 82%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/LayoutParamsParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LayoutParamsParser.java
index ee71b60..dc600d7 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/LayoutParamsParser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LayoutParamsParser.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor;
 import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
 import com.android.ide.eclipse.common.resources.AttrsXmlParser;
 import com.android.ide.eclipse.common.resources.ViewClassInfo;
 import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -52,23 +53,10 @@
 public class LayoutParamsParser {
     
     /**
-     * Classes which implement this interface provide methods to describe a class.
+     * Class extending {@link ViewClassInfo} by adding the notion of instantiability.
+     * {@link LayoutParamsParser#getViews()} and {@link LayoutParamsParser#getGroups()} should
+     * only return classes that can be instantiated.
      */
-    public interface IClass {
-
-        public String getCanonicalName();
-
-        public IClass getSuperclass();
-
-        public String getSimpleName();
-
-        public IClass getEnclosingClass();
-
-        public IClass[] getDeclaredClasses();
-        
-        public boolean isInstantiable();
-    }
-    
     final static class ExtViewClassInfo extends ViewClassInfo {
 
         private boolean mIsInstantiable;
@@ -87,16 +75,16 @@
     /* Note: protected members/methods are overridden in unit tests */
     
     /** Reference to android.view.View */
-    protected IClass mTopViewClass;
+    protected IClassDescriptor mTopViewClass;
     /** Reference to android.view.ViewGroup */
-    protected IClass mTopGroupClass;
+    protected IClassDescriptor mTopGroupClass;
     /** Reference to android.view.ViewGroup$LayoutParams */
-    protected IClass mTopLayoutParamsClass;
+    protected IClassDescriptor mTopLayoutParamsClass;
     
     /** Input list of all classes deriving from android.view.View */
-    protected ArrayList<IClass> mViewList;
+    protected ArrayList<IClassDescriptor> mViewList;
     /** Input list of all classes deriving from android.view.ViewGroup */
-    protected ArrayList<IClass> mGroupList;
+    protected ArrayList<IClassDescriptor> mGroupList;
     
     /** Output map of FQCN => info on View classes */
     protected TreeMap<String, ExtViewClassInfo> mViewMap;
@@ -109,14 +97,14 @@
     protected AttrsXmlParser mAttrsXmlParser;
 
     /** The android.jar class loader */
-    protected IAndroidLoader mClassLoader;
+    protected IAndroidClassLoader mClassLoader;
 
     /**
      * Instantiate a new LayoutParamsParser.
      * @param classLoader The android.jar class loader
      * @param attrsXmlParser The parser of the attrs.xml file
      */
-    public LayoutParamsParser(IAndroidLoader classLoader,
+    public LayoutParamsParser(IAndroidClassLoader classLoader,
             AttrsXmlParser attrsXmlParser) {
         mClassLoader = classLoader;
         mAttrsXmlParser = attrsXmlParser;
@@ -135,8 +123,8 @@
     /**
      * TODO: doc here.
      * <p/>
-     * Note: on output we should have NO dependency on IClass, otherwise we wouldn't be able
-     * to unload the class loader later.
+     * Note: on output we should have NO dependency on {@link IClassDescriptor},
+     * otherwise we wouldn't be able to unload the class loader later.
      * <p/>
      * Note on Vocabulary: FQCN=Fully Qualified Class Name (e.g. "my.package.class$innerClass")
      * @param monitor A progress monitor. Can be null. Caller is responsible for calling done.
@@ -168,8 +156,8 @@
             if (paramsClassName != null) {
                 superClasses[2] = paramsClassName;
             }
-            HashMap<String, ArrayList<IClass>> found = mClassLoader.findClassesDerivingFrom(
-                    "android.", superClasses);
+            HashMap<String, ArrayList<IClassDescriptor>> found =
+                    mClassLoader.findClassesDerivingFrom("android.", superClasses);
             mTopViewClass = mClassLoader.getClass(rootClassName);
             mTopGroupClass = mClassLoader.getClass(groupClassName);
             if (paramsClassName != null) {
@@ -196,26 +184,26 @@
 
             progress.setWorkRemaining(mGroupList.size() + mViewList.size());
             
-            for (IClass groupChild : mGroupList) {
+            for (IClassDescriptor groupChild : mGroupList) {
                 addGroup(groupChild);
                 progress.worked(1);
             }
 
-            for (IClass viewChild : mViewList) {
+            for (IClassDescriptor viewChild : mViewList) {
                 if (viewChild != mTopGroupClass) {
                     addView(viewChild);
                 }
                 progress.worked(1);
             }
         } catch (ClassNotFoundException e) {
-            CommonPlugin.log(e, "Problem loading class %1$s or %2$s",  //$NON-NLS-1$
+            AdtPlugin.log(e, "Problem loading class %1$s or %2$s",  //$NON-NLS-1$
                     rootClassName, groupClassName);
         } catch (InvalidAttributeValueException e) {
-            CommonPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
+            AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
         } catch (ClassFormatError e) {
-            CommonPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
+            AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
         } catch (IOException e) {
-            CommonPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
+            AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
         }
     }
 
@@ -223,7 +211,7 @@
      * Parses a View class and adds a ExtViewClassInfo for it in mViewMap.
      * It calls itself recursively to handle super classes which are also Views.
      */
-    private ExtViewClassInfo addView(IClass viewClass) {
+    private ExtViewClassInfo addView(IClassDescriptor viewClass) {
         String fqcn = viewClass.getCanonicalName();
         if (mViewMap.containsKey(fqcn)) {
             return mViewMap.get(fqcn);
@@ -238,7 +226,7 @@
         // All view classes derive from mTopViewClass by design.
         // Do not lookup the super class for mTopViewClass itself.
         if (viewClass.equals(mTopViewClass) == false) {
-            IClass superClass = viewClass.getSuperclass(); 
+            IClassDescriptor superClass = viewClass.getSuperclass(); 
             ExtViewClassInfo superClassInfo = addView(superClass);
             info.setSuperClass(superClassInfo);
         }
@@ -251,7 +239,7 @@
      * Parses a ViewGroup class and adds a ExtViewClassInfo for it in mGroupMap.
      * It calls itself recursively to handle super classes which are also ViewGroups.
      */
-    private ExtViewClassInfo addGroup(IClass groupClass) {
+    private ExtViewClassInfo addGroup(IClassDescriptor groupClass) {
         String fqcn = groupClass.getCanonicalName();
         if (mGroupMap.containsKey(fqcn)) {
             return mGroupMap.get(fqcn);
@@ -265,7 +253,7 @@
         // android.view.View (i.e. mTopViewClass here). So the only group that can have View as
         // its super class is the ViewGroup base class and we don't try to resolve it since groups
         // are loaded before views.
-        IClass superClass = groupClass.getSuperclass(); 
+        IClassDescriptor superClass = groupClass.getSuperclass(); 
         
         // Assertion: at this point, we should have
         //   superClass != mTopViewClass || fqcn.equals(AndroidConstants.CLASS_VIEWGROUP);
@@ -291,15 +279,15 @@
      * 
      * @return The {@link LayoutParamsInfo} for the ViewGroup class or null.
      */
-    private LayoutParamsInfo addLayoutParams(IClass groupClass) {
+    private LayoutParamsInfo addLayoutParams(IClassDescriptor groupClass) {
 
         // Is there a LayoutParams in this group class?
-        IClass layoutParamsClass = findLayoutParams(groupClass);
+        IClassDescriptor layoutParamsClass = findLayoutParams(groupClass);
 
         // if there's no layout data in the group class, link to the one from the
         // super class.
         if (layoutParamsClass == null) {
-            for (IClass superClass = groupClass.getSuperclass();
+            for (IClassDescriptor superClass = groupClass.getSuperclass();
                     layoutParamsClass == null &&
                         superClass != null &&
                         superClass.equals(mTopViewClass) == false;
@@ -319,7 +307,7 @@
      * Parses a LayoutParams class and returns a LayoutParamsInfo object for it.
      * It calls itself recursively to handle the super class of the LayoutParams.
      */
-    private LayoutParamsInfo getLayoutParamsInfo(IClass layoutParamsClass) {
+    private LayoutParamsInfo getLayoutParamsInfo(IClassDescriptor layoutParamsClass) {
         String fqcn = layoutParamsClass.getCanonicalName();
         LayoutParamsInfo layoutParamsInfo = mLayoutParamsMap.get(fqcn);
 
@@ -330,7 +318,7 @@
         // Find the link on the LayoutParams super class 
         LayoutParamsInfo superClassInfo = null;
         if (layoutParamsClass.equals(mTopLayoutParamsClass) == false) {
-            IClass superClass = layoutParamsClass.getSuperclass(); 
+            IClassDescriptor superClass = layoutParamsClass.getSuperclass(); 
             superClassInfo = getLayoutParamsInfo(superClass);
         }
         
@@ -355,9 +343,9 @@
      * @param groupClass The ViewGroup derived class
      * @return The Class of the inner LayoutParams or null if none is declared.
      */
-    private IClass findLayoutParams(IClass groupClass) {
-        IClass[] innerClasses = groupClass.getDeclaredClasses();
-        for (IClass innerClass : innerClasses) {
+    private IClassDescriptor findLayoutParams(IClassDescriptor groupClass) {
+        IClassDescriptor[] innerClasses = groupClass.getDeclaredClasses();
+        for (IClassDescriptor innerClass : innerClasses) {
             if (innerClass.getSimpleName().equals(AndroidConstants.CLASS_LAYOUTPARAMS)) {
                 return innerClass;
             }
@@ -365,12 +353,16 @@
         return null;
     }
     
+    /**
+     * Computes and return a list of ViewClassInfo from a map by filtering out the class that
+     * cannot be instantiated.
+     */
     private List<ViewClassInfo> getInstantiables(SortedMap<String, ExtViewClassInfo> map) {
         Collection<ExtViewClassInfo> values = map.values();
         ArrayList<ViewClassInfo> list = new ArrayList<ViewClassInfo>();
         
         for (ExtViewClassInfo info : values) {
-            if (info.mIsInstantiable) {
+            if (info.isInstantiable()) {
                 list.add(info);
             }
         }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java
new file mode 100644
index 0000000..6bf0272
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/LoadStatus.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 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.sdk;
+
+/**
+ * Enum for loading status of various SDK parts.
+ */
+public enum LoadStatus {
+    LOADING, LOADED, FAILED;
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java
new file mode 100644
index 0000000..3b9d10e
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2008 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.sdk;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.project.ProjectProperties;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Central point to load, manipulate and deal with the Android SDK. Only one SDK can be used
+ * at the same time.
+ * 
+ * To start using an SDK, call {@link #loadSdk(String)} which returns the instance of
+ * the Sdk object.
+ * 
+ * To get the list of platforms present in the SDK, call {@link #getPlatforms()}.
+ * To get the list of add-ons present in the SDK, call {@link #getAddons()}.
+ * 
+ */
+public class Sdk {
+    private final static String PROPERTY_PROJECT_TARGET = "androidTarget"; //$NON-NLS-1$
+    
+    private static Sdk sCurrentSdk = null;
+
+    private final SdkManager mManager;
+    private final HashMap<IProject, IAndroidTarget> mProjectMap =
+            new HashMap<IProject, IAndroidTarget>();
+    private final HashMap<IAndroidTarget, AndroidTargetData> mTargetMap = 
+            new HashMap<IAndroidTarget, AndroidTargetData>();
+    private final String mDocBaseUrl;
+    
+    /**
+     * Loads an SDK and returns an {@link Sdk} object if success.
+     * @param sdkLocation the OS path to the SDK.
+     */
+    public static Sdk loadSdk(String sdkLocation) {
+        if (sCurrentSdk != null) {
+            // manual unload?
+            sCurrentSdk = null;
+        }
+
+        final ArrayList<String> logMessages = new ArrayList<String>();
+        ISdkLog log = new ISdkLog() {
+            public void error(String errorFormat, Object... arg) {
+                logMessages.add(String.format(errorFormat, arg));
+            }
+            public void warning(String warningFormat, Object... arg) {
+                logMessages.add(String.format(warningFormat, arg));
+            }
+        };
+
+        // get an SdkManager object for the location
+        SdkManager manager = SdkManager.createManager(sdkLocation, log);
+        if (manager != null) {
+            sCurrentSdk = new Sdk(manager);
+            return sCurrentSdk;
+        } else {
+            StringBuilder sb = new StringBuilder("Error Loading the SDK:\n");
+            for (String msg : logMessages) {
+                sb.append('\n');
+                sb.append(msg);
+            }
+            AdtPlugin.displayError("Android SDK", sb.toString());
+        }
+        return null;
+    }
+
+    /**
+     * Returns the current {@link Sdk} object.
+     */
+    public static Sdk getCurrent() {
+        return sCurrentSdk;
+    }
+    
+    /**
+     * Returns the URL to the local documentation.
+     * Can return null if no documentation is found in the current SDK.
+     * 
+     * @return A file:// URL on the local documentation folder if it exists or null.
+     */
+    public String getDocumentationBaseUrl() {
+        return mDocBaseUrl;
+    }
+
+    /**
+     * Returns the list of targets that are available in the SDK.
+     */
+    public IAndroidTarget[] getTargets() {
+        return mManager.getTargets();
+    }
+    
+    /**
+     * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}.
+     * @param hash the hash
+     */
+    public IAndroidTarget getTargetFromHashString(String hash) {
+        return mManager.getTargetFromHashString(hash);
+    }
+    
+    /**
+     * Associates an {@link IProject} and an {@link IAndroidTarget}.
+     */
+    public void setProject(IProject project, IAndroidTarget target) {
+        synchronized (mProjectMap) {
+            // look for the current target of the project
+            IAndroidTarget previousTarget = mProjectMap.get(project);
+            
+            if (target != previousTarget) {
+                // save the target hash string in the project persistent property
+                setProjectTargetHashString(project, target.hashString());
+                
+                // put it in a local map for easy access.
+                mProjectMap.put(project, target);
+
+                // recompile the project if needed.
+                IJavaProject javaProject = JavaCore.create(project);
+                AndroidClasspathContainerInitializer.updateProjects(
+                        new IJavaProject[] { javaProject });
+            }
+        }
+    }
+    
+    /**
+     * Returns the {@link IAndroidTarget} object associated with the given {@link IProject}.
+     */
+    public IAndroidTarget getTarget(IProject project) {
+        synchronized (mProjectMap) {
+            IAndroidTarget target = mProjectMap.get(project);
+            if (target == null) {
+                // get the value from the project persistent property.
+                String targetHashString = getProjectTargetHashString(project);
+
+                if (targetHashString != null) {
+                    target = mManager.getTargetFromHashString(targetHashString);
+                }
+            }
+
+            return target;
+        }
+    }
+    
+    /**
+     * Returns the hash string uniquely identifying the target of a project. This methods reads
+     * the string from the project persistent preferences/properties.
+     * <p/>The string is equivalent to the return of {@link IAndroidTarget#hashString()}.
+     * @param project The project for which to return the target hash string.
+     * @return the hash string or null if the project does not have a target set.
+     */
+    public static String getProjectTargetHashString(IProject project) {
+        // load the default.properties from the project folder.
+        ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString());
+        if (properties == null) {
+            AdtPlugin.log(IStatus.ERROR, "Failed to load properties file for project '%s'",
+                    project.getName());
+            return null;
+        }
+        
+        return properties.getProperty(ProjectProperties.PROPERTY_TARGET);
+    }
+
+    /**
+     * Sets a target hash string in a project's persistent preferences/property storage.
+     * @param project The project in which to save the hash string.
+     * @param targetHashString The target hash string to save. This must be the result from
+     * {@link IAndroidTarget#hashString()}.
+     */
+    public static void setProjectTargetHashString(IProject project, String targetHashString) {
+        // because we don't want to erase other properties from default.properties, we first load
+        // them
+        ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString());
+        if (properties == null) {
+            // doesn't exist yet? we create it.
+            properties = ProjectProperties.create(project.getLocation().toOSString());
+        }
+        
+        // add/change the target hash string.
+        properties.setProperty(ProjectProperties.PROPERTY_TARGET, targetHashString);
+        
+        // and rewrite the file.
+        try {
+            properties.save();
+        } catch (IOException e) {
+            AdtPlugin.log(e, "Failed to save default.properties for project '%s'",
+                    project.getName());
+        }
+    }
+    /**
+     * Return the {@link PlatformData} for a given {@link IAndroidTarget}.
+     */
+    public AndroidTargetData getTargetData(IAndroidTarget target) {
+        synchronized (mTargetMap) {
+            return mTargetMap.get(target);
+        }
+    }
+    
+    private Sdk(SdkManager manager) {
+        mManager = manager;
+        
+        // pre-compute some paths
+        mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() +
+                SdkConstants.OS_SDK_DOCS_FOLDER);
+    }
+    
+    void setTargetData(IAndroidTarget target, AndroidTargetData data) {
+        synchronized (mTargetMap) {
+            mTargetMap.put(target, data);
+        }
+    }
+    
+    /**
+     * Returns the URL to the local documentation.
+     * Can return null if no documentation is found in the current SDK.
+     * 
+     * @param osDocsPath Path to the documentation folder in the current SDK.
+     *  The folder may not actually exist.
+     * @return A file:// URL on the local documentation folder if it exists or null.
+     */
+    private String getDocumentationBaseUrl(String osDocsPath) {
+        File f = new File(osDocsPath);
+
+        if (f.isDirectory()) {
+            try {
+                // Note: to create a file:// URL, one would typically use something like
+                // f.toURI().toURL().toString(). However this generates a broken path on
+                // Windows, namely "C:\\foo" is converted to "file:/C:/foo" instead of
+                // "file:///C:/foo" (i.e. there should be 3 / after "file:"). So we'll
+                // do the correct thing manually.
+                
+                String path = f.getAbsolutePath();
+                if (File.separatorChar != '/') {
+                    path = path.replace(File.separatorChar, '/');
+                }
+                
+                // For some reason the URL class doesn't add the mandatory "//" after
+                // the "file:" protocol name, so it has to be hacked into the path.
+                URL url = new URL("file", null, "//" + path);  //$NON-NLS-1$ //$NON-NLS-2$
+                String result = url.toString();
+                return result;
+            } catch (MalformedURLException e) {
+                // ignore malformed URLs
+            }
+        }
+
+        return null;
+    }
+
+}
+
+
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/WidgetListLoader.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/WidgetClassLoader.java
similarity index 90%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/WidgetListLoader.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/WidgetClassLoader.java
index c85a50e..8db09f2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/resources/WidgetListLoader.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/WidgetClassLoader.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
 
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
 import com.android.ide.eclipse.common.AndroidConstants;
 
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -42,18 +41,19 @@
  * where code is a single letter (W for widget, L for layout, P for layout params), and class names
  * are the fully qualified name of the classes.
  */
-public final class WidgetListLoader implements IAndroidLoader {
+public final class WidgetClassLoader implements IAndroidClassLoader {
     
     /**
      * Basic class containing the class descriptions found in the text file. 
      */
-    private final static class ClassDescriptor implements IClass {
+    private final static class ClassDescriptor implements IClassDescriptor {
         
         private String mName;
         private String mSimpleName;
         private ClassDescriptor mSuperClass;
         private ClassDescriptor mEnclosingClass;
-        private final ArrayList<IClass> mDeclaredClasses = new ArrayList<IClass>();
+        private final ArrayList<IClassDescriptor> mDeclaredClasses =
+                new ArrayList<IClassDescriptor>();
         private boolean mIsInstantiable = false;
 
         ClassDescriptor(String fqcn) {
@@ -69,15 +69,15 @@
             return mSimpleName;
         }
 
-        public IClass[] getDeclaredClasses() {
-            return mDeclaredClasses.toArray(new IClass[mDeclaredClasses.size()]);
+        public IClassDescriptor[] getDeclaredClasses() {
+            return mDeclaredClasses.toArray(new IClassDescriptor[mDeclaredClasses.size()]);
         }
 
         private void addDeclaredClass(ClassDescriptor declaredClass) {
             mDeclaredClasses.add(declaredClass);
         }
 
-        public IClass getEnclosingClass() {
+        public IClassDescriptor getEnclosingClass() {
             return mEnclosingClass;
         }
         
@@ -93,7 +93,7 @@
             mName = enclosingClass.mName + "$" + mName.substring(enclosingClass.mName.length() + 1);
         }
 
-        public IClass getSuperclass() {
+        public IClassDescriptor getSuperclass() {
             return mSuperClass;
         }
         
@@ -147,7 +147,7 @@
      * @param osFilePath the OS path of the file to load.
      * @throws FileNotFoundException if the file is not found.
      */
-    WidgetListLoader(String osFilePath) throws FileNotFoundException {
+    WidgetClassLoader(String osFilePath) throws FileNotFoundException {
         mOsFilePath = osFilePath;
         mReader = new BufferedReader(new FileReader(osFilePath));
     }
@@ -301,20 +301,21 @@
      * @throws InvalidAttributeValueException
      * @throws ClassFormatError
      */
-    public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(String rootPackage,
+    public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(String rootPackage,
             String[] superClasses) throws IOException, InvalidAttributeValueException,
             ClassFormatError {
-        HashMap<String, ArrayList<IClass>> map = new HashMap<String, ArrayList<IClass>>();
+        HashMap<String, ArrayList<IClassDescriptor>> map =
+                new HashMap<String, ArrayList<IClassDescriptor>>();
         
-        ArrayList<IClass> list = new ArrayList<IClass>();
+        ArrayList<IClassDescriptor> list = new ArrayList<IClassDescriptor>();
         list.addAll(mWidgetMap.values());
         map.put(AndroidConstants.CLASS_VIEW, list);
         
-        list = new ArrayList<IClass>();
+        list = new ArrayList<IClassDescriptor>();
         list.addAll(mLayoutMap.values());
         map.put(AndroidConstants.CLASS_VIEWGROUP, list);
 
-        list = new ArrayList<IClass>();
+        list = new ArrayList<IClassDescriptor>();
         list.addAll(mLayoutParamsMap.values());
         map.put(AndroidConstants.CLASS_VIEWGROUP_LAYOUTPARAMS, list);
 
@@ -326,7 +327,7 @@
      * @param className the fully-qualified name of the class to return.
      * @throws ClassNotFoundException
      */
-    public IClass getClass(String className) throws ClassNotFoundException {
+    public IClassDescriptor getClass(String className) throws ClassNotFoundException {
         return mMap.get(className);
     }
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectCreationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectCreationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
index d395905..8044bcb 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectCreationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
@@ -20,11 +20,13 @@
  * org.eclipse.jdt.internal.ui.wizards.JavaProjectWizardFirstPage
  */
 
-package com.android.ide.eclipse.adt.project.internal;
+package com.android.ide.eclipse.adt.wizards.newproject;
 
-import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidManifestHelper;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdkuilib.SdkTargetSelector;
 
 import org.eclipse.core.filesystem.URIUtil;
 import org.eclipse.core.resources.IProject;
@@ -120,6 +122,7 @@
     private boolean mInternalActivityNameUpdate;
     protected boolean mProjectNameModifiedByUser;
     protected boolean mApplicationNameModifiedByUser;
+    private SdkTargetSelector mSdkTargetSelector;
 
 
     /**
@@ -133,7 +136,9 @@
         if (sCustomLocationOsPath == null ||
                 sCustomLocationOsPath.length() == 0 ||
                 !new File(sCustomLocationOsPath).isDirectory()) {
-            sCustomLocationOsPath = AdtPlugin.getOsSdkSamplesFolder();
+            // FIXME location of samples is pretty much impossible here.
+            //sCustomLocationOsPath = AdtPlugin.getOsSdkSamplesFolder();
+            sCustomLocationOsPath = File.listRoots()[0].getAbsolutePath();
         }
     }
 
@@ -200,6 +205,11 @@
             return mSourceFolder;
         }
     }
+    
+    /** Returns the current sdk target or null if none has been selected yet. */
+    public IAndroidTarget getSdkTarget() {
+        return mSdkTargetSelector == null ? null : mSdkTargetSelector.getFirstSelected();
+    }
 
     /**
      * Overrides @DialogPage.setVisible(boolean) to put the focus in the project name when
@@ -232,15 +242,19 @@
 
         createProjectNameGroup(composite);
         createLocationGroup(composite);
+        createTargetGroup(composite);
         createPropertiesGroup(composite);
 
         // Update state the first time
         enableLocationWidgets();
-        setPageComplete(validatePage());
+
         // Show description the first time
         setErrorMessage(null);
         setMessage(null);
         setControl(composite);
+
+        // Validate. This will complain about the first empty field.
+        setPageComplete(validatePage());
     }
 
     /**
@@ -357,6 +371,33 @@
     }
 
     /**
+     * Creates the target group.
+     * It only contains an SdkTargetSelector.
+     */
+    private void createTargetGroup(Composite parent) {
+        Group group = new Group(parent, SWT.SHADOW_ETCHED_IN);
+        // Layout has 1 column
+        group.setLayout(new GridLayout());
+        group.setLayoutData(new GridData(GridData.FILL_BOTH));
+        group.setFont(parent.getFont());
+        group.setText("Target");
+        
+        // get the targets from the sdk
+        IAndroidTarget[] targets = null;
+        if (Sdk.getCurrent() != null) {
+            targets = Sdk.getCurrent().getTargets();
+        }
+
+        mSdkTargetSelector = new SdkTargetSelector(group, targets, false /*multi-selection*/);
+        mSdkTargetSelector.setSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                setPageComplete(validatePage());
+            }
+        });
+    }
+
+    /**
      * Display a directory browser and update the location path field with the selected path
      */
     private void openDirectoryBrowser() {
@@ -755,6 +796,9 @@
             status |= validateLocationPath(workspace);
         }
         if ((status & MSG_ERROR) == 0) {
+            status |= validateSdkTarget();
+        }
+        if ((status & MSG_ERROR) == 0) {
             status |= validatePackageField();
         }
         if ((status & MSG_ERROR) == 0) {
@@ -894,6 +938,18 @@
     }
 
     /**
+     * Validates the sdk target choice.
+     * 
+     * @return The wizard message type, one of MSG_ERROR, MSG_WARNING or MSG_NONE.
+     */
+    private int validateSdkTarget() {
+        if (getSdkTarget() == null) {
+            return setStatus("An SDK Target must be specified.", MSG_ERROR);
+        }
+        return MSG_NONE;
+    }
+
+    /**
      * Validates the activity name field.
      *
      * @return The wizard message type, one of MSG_ERROR, MSG_WARNING or MSG_NONE.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectWizard.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectWizard.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectWizard.java
index a67f5ed..a582217 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/NewProjectWizard.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectWizard.java
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.project.internal;
+package com.android.ide.eclipse.adt.wizards.newproject;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.project.AndroidNature;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
@@ -60,6 +62,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import java.util.Map.Entry;
 
 /**
  * A "New Android Project" Wizard.
@@ -81,6 +84,7 @@
     private static final String PARAM_STRING_CONTENT = "STRING_CONTENT"; //$NON-NLS-1$
     private static final String PARAM_IS_NEW_PROJECT = "IS_NEW_PROJECT"; //$NON-NLS-1$
     private static final String PARAM_SRC_FOLDER = "SRC_FOLDER"; //$NON-NLS-1$
+    private static final String PARAM_SDK_TARGET = "SDK_TARGET"; //$NON-NLS-1$
 
     private static final String PH_ACTIVITIES = "ACTIVITIES"; //$NON-NLS-1$
     private static final String PH_INTENT_FILTERS = "INTENT_FILTERS"; //$NON-NLS-1$
@@ -223,13 +227,14 @@
         final IProject project = workspace.getRoot().getProject(mMainPage.getProjectName());
         final IProjectDescription description = workspace.newProjectDescription(project.getName());
 
-        final Map<String, String> parameters = new HashMap<String, String>();
+        final Map<String, Object> parameters = new HashMap<String, Object>();
         parameters.put(PARAM_PROJECT, mMainPage.getProjectName());
         parameters.put(PARAM_PACKAGE, mMainPage.getPackageName());
         parameters.put(PARAM_APPLICATION, STRING_RSRC_PREFIX + STRING_APP_NAME);
         parameters.put(PARAM_SDK_TOOLS_DIR, AdtPlugin.getOsSdkToolsFolder());
-        parameters.put(PARAM_IS_NEW_PROJECT, Boolean.toString(mMainPage.isNewProject()));
+        parameters.put(PARAM_IS_NEW_PROJECT, mMainPage.isNewProject());
         parameters.put(PARAM_SRC_FOLDER, mMainPage.getSourceFolder());
+        parameters.put(PARAM_SDK_TARGET, mMainPage.getSdkTarget());
 
         if (mMainPage.isCreateActivity()) {
             // An activity name can be of the form ".package.Class" or ".Class".
@@ -315,7 +320,7 @@
      *         to create or modify the project or if it is canceled by the user.
      */
     private void createProjectAsync(IProject project, IProjectDescription description,
-            IProgressMonitor monitor, Map<String, String> parameters,
+            IProgressMonitor monitor, Map<String, Object> parameters,
             Map<String, String> stringDictionary)
             throws InvocationTargetException {
         monitor.beginTask("Create Android Project", 100);
@@ -330,7 +335,7 @@
 
             // Create folders in the project if they don't already exist
             addDefaultDirectories(project, AndroidConstants.WS_ROOT, DEFAULT_DIRECTORIES, monitor);
-            String[] sourceFolder = new String[] { parameters.get(PARAM_SRC_FOLDER) };
+            String[] sourceFolder = new String[] { (String) parameters.get(PARAM_SRC_FOLDER) };
             addDefaultDirectories(project, AndroidConstants.WS_ROOT, sourceFolder, monitor);
 
             // Create the resource folders in the project if they don't already exist.
@@ -340,7 +345,7 @@
             IJavaProject javaProject = JavaCore.create(project);
             setupSourceFolder(javaProject, sourceFolder[0], monitor);
 
-            if (Boolean.parseBoolean(parameters.get(PARAM_IS_NEW_PROJECT))) {
+            if (((Boolean) parameters.get(PARAM_IS_NEW_PROJECT)).booleanValue()) {
                 // Create files in the project if they don't already exist
                 addManifest(project, parameters, stringDictionary, monitor);
 
@@ -360,6 +365,8 @@
                         monitor);
             }
 
+            Sdk.getCurrent().setProject(project, (IAndroidTarget) parameters.get(PARAM_SDK_TARGET));
+            
             // Fix the project to make sure all properties are as expected.
             // Necessary for existing projects and good for new ones to.
             ProjectHelper.fixProject(project);
@@ -409,7 +416,7 @@
      * @throws IOException if the method fails to create the files in the
      *         project.
      */
-    private void addManifest(IProject project, Map<String, String> parameters,
+    private void addManifest(IProject project, Map<String, Object> parameters,
             Map<String, String> stringDictionary, IProgressMonitor monitor)
             throws CoreException, IOException {
 
@@ -543,16 +550,16 @@
      *         project.
      */
     private void addSampleCode(IProject project, String sourceFolder,
-            Map<String, String> parameters, Map<String, String> stringDictionary,
+            Map<String, Object> parameters, Map<String, String> stringDictionary,
             IProgressMonitor monitor) throws CoreException, IOException {
         // create the java package directories.
         IFolder pkgFolder = project.getFolder(sourceFolder);
-        String packageName = parameters.get(PARAM_PACKAGE);
+        String packageName = (String) parameters.get(PARAM_PACKAGE);
         
         // The PARAM_ACTIVITY key will be absent if no activity should be created,
         // in which case activityName will be null.
-        String activityName = parameters.get(PARAM_ACTIVITY);
-        Map<String, String> java_activity_parameters = parameters;
+        String activityName = (String) parameters.get(PARAM_ACTIVITY);
+        Map<String, Object> java_activity_parameters = parameters;
         if (activityName != null) {
             if (activityName.indexOf('.') >= 0) {
                 // There are package names in the activity name. Transform packageName to add
@@ -564,7 +571,7 @@
                 
                 // Also update the values used in the JAVA_FILE_TEMPLATE below
                 // (but not the ones from the manifest so don't change the caller's dictionary)
-                java_activity_parameters = new HashMap<String, String>(parameters);
+                java_activity_parameters = new HashMap<String, Object>(parameters);
                 java_activity_parameters.put(PARAM_PACKAGE, packageName);
                 java_activity_parameters.put(PARAM_ACTIVITY, activityName);
             }
@@ -665,7 +672,7 @@
      *         length.
      */
     private void copyFile(String resourceFilename, IFile destFile,
-            Map<String, String> parameters, IProgressMonitor monitor)
+            Map<String, Object> parameters, IProgressMonitor monitor)
             throws CoreException, IOException {
 
         // Read existing file.
@@ -692,13 +699,14 @@
      * Replaces placeholders found in a string with values.
      *
      * @param str the string to search for placeholders.
-     * @param parameters a map of <placeholder, Value> to search for in the
-     *        string
+     * @param parameters a map of <placeholder, Value> to search for in the string
      * @return A new String object with the placeholder replaced by the values.
      */
-    private String replaceParameters(String str, Map<String, String> parameters) {
-        for (String key : parameters.keySet()) {
-            str = str.replaceAll(key, parameters.get(key));
+    private String replaceParameters(String str, Map<String, Object> parameters) {
+        for (Entry<String, Object> entry : parameters.entrySet()) {
+            if (entry.getValue() instanceof String) {
+                str = str.replaceAll(entry.getKey(), (String) entry.getValue());
+            }
         }
 
         return str;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/AndroidConstants.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
similarity index 72%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/AndroidConstants.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
index 02cef2d..f3f7b79 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/AndroidConstants.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
@@ -16,6 +16,8 @@
 
 package com.android.ide.eclipse.common;
 
+import com.android.sdklib.SdkConstants;
+
 import java.io.File;
 
 /**
@@ -38,8 +40,11 @@
  *
  */
 public class AndroidConstants {
-    /** The Editors Plugin ID */
-    public static final String EDITORS_PLUGIN_ID = "com.android.ide.eclipse.editors"; // $NON-NLS-1$
+    /**
+     * The old Editors Plugin ID. It is still used in some places for compatibility.
+     * Please do not use for new features.
+     */
+    public static final String EDITORS_NAMESPACE = "com.android.ide.eclipse.editors"; // $NON-NLS-1$
 
     /** Nature of android projects */
     public final static String NATURE = "com.android.ide.eclipse.adt.AndroidNature"; //$NON-NLS-1$
@@ -72,6 +77,8 @@
     public final static String EXT_JAR = "jar"; //$NON-NLS-1$
     /** Extension of aidl files, i.e. "aidl" */
     public final static String EXT_AIDL = "aidl"; //$NON-NLS-1$
+    /** Extension of native libraries, i.e. "so" */
+    public final static String EXT_NATIVE_LIB = "so"; //$NON-NLS-1$
 
     private final static String DOT = "."; //$NON-NLS-1$
 
@@ -90,17 +97,8 @@
 
     /** Name of the manifest file, i.e. "AndroidManifest.xml". */
     public static final String FN_ANDROID_MANIFEST = "AndroidManifest.xml"; //$NON-NLS-1$
+    public static final String FN_PROJECT_AIDL = "project.aidl"; //$NON-NLS-1$
 
-    /** Name of the framework library, i.e. "android.jar" */
-    public static final String FN_FRAMEWORK_LIBRARY = "android.jar"; //$NON-NLS-1$
-    /** Name of the layout attributes, i.e. "attrs.xml" */
-    public static final String FN_ATTRS_XML = "attrs.xml"; //$NON-NLS-1$
-    /** Name of the layout attributes, i.e. "attrs_manifest.xml" */
-    public static final String FN_ATTRS_MANIFEST_XML = "attrs_manifest.xml"; //$NON-NLS-1$
-    /** framework aidl import file */
-    public static final String FN_FRAMEWORK_AIDL = "framework.aidl"; //$NON-NLS-1$
-    /** layoutlib.jar file */
-    public static final String FN_LAYOUTLIB_JAR = "layoutlib.jar"; //$NON-NLS-1$
     /** dex.jar file */
     public static final String FN_DX_JAR = "dx.jar"; //$NON-NLS-1$
     /** Name of the android sources directory */
@@ -116,10 +114,6 @@
     public final static String FN_CLASSES_DEX = "classes.dex"; //$NON-NLS-1$
     /** Temporary packaged resources file name, i.e. "resources.ap_" */
     public final static String FN_RESOURCES_AP_ = "resources.ap_"; //$NON-NLS-1$
-    /** build properties file */
-    public final static String FN_BUILD_PROP = "build.prop"; //$NON-NLS-1$
-    /** plugin properties file */
-    public final static String FN_PLUGIN_PROP = "plugin.prop"; //$NON-NLS-1$
 
     public final static String FN_ADB = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
             "adb.exe" : "adb"; //$NON-NLS-1$ //$NON-NLS-2$
@@ -136,15 +130,21 @@
     public final static String FN_TRACEVIEW = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
             "traceview.exe" : "traceview"; //$NON-NLS-1$ //$NON-NLS-2$
 
-    /** Skin layout file */
-    public final static String FN_LAYOUT = "layout";//$NON-NLS-1$
+    /** Folder Names for Android Projects . */
 
-    /** Resources folder name, i.e. "res". */
+    /* Resources folder name, i.e. "res". */
     public final static String FD_RESOURCES = "res"; //$NON-NLS-1$
     /** Assets folder name, i.e. "assets" */
     public final static String FD_ASSETS = "assets"; //$NON-NLS-1$
     /** Default source folder name, i.e. "src" */
     public final static String FD_SOURCES = "src"; //$NON-NLS-1$
+    /** Default native library folder name inside the project, i.e. "libs"
+     * While the folder inside the .apk is "lib", we call that one libs because
+     * that's what we use in ant for both .jar and .so and we need to make the 2 development ways
+     * compatible. */
+    public final static String FD_NATIVE_LIBS = "libs"; //$NON-NLS-1$
+    /** Native lib folder inside the APK: "lib" */
+    public final static String FD_APK_NATIVE_LIBS = "lib"; //$NON-NLS-1$
     /** Default bin folder name, i.e. "bin" */
     public final static String FD_BINARIES = "bin"; //$NON-NLS-1$
     /** Default anim resource folder name, i.e. "anim" */
@@ -163,22 +163,6 @@
     public final static String FD_XML = "xml"; //$NON-NLS-1$
     /** Default raw resource folder name, i.e. "raw" */
     public final static String FD_RAW = "raw"; //$NON-NLS-1$
-    /** Name of the tools folder. */
-    public final static String FD_TOOLS = "tools"; //$NON-NLS-1$
-    /** Name of the libs folder. */
-    public final static String FD_LIBS = "lib"; //$NON-NLS-1$
-    /** Name of the docs folder. */
-    public final static String FD_DOCS = "docs"; //$NON-NLS-1$
-    /** Name of the images folder. */
-    public final static String FD_IMAGES = "images"; //$NON-NLS-1$
-    /** Name of the skins folder. */
-    public final static String FD_SKINS = "skins"; //$NON-NLS-1$
-    /** Name of the samples folder. */
-    public final static String FD_SAMPLES = "samples"; //$NON-NLS-1$
-    /** Name of the folder containing the default framework resources. */
-    public final static String FD_DEFAULT_RES = "default"; //$NON-NLS-1$
-    /** SDK font folder name, i.e. "fonts" */
-    public final static String FD_FONTS = "fonts"; //$NON-NLS-1$
 
     /** Absolute path of the workspace root, i.e. "/" */
     public final static String WS_ROOT = WS_SEP;
@@ -190,57 +174,16 @@
     public final static String WS_ASSETS = WS_SEP + FD_ASSETS;
 
     /** Leaf of the javaDoc folder. Does not start with a separator. */
-    public final static String WS_JAVADOC_FOLDER_LEAF = FD_DOCS + "/reference"; //$NON-NLS-1$
-
-    /** Path of the documentation directory relative to the sdk folder.
-     *  This is an OS path, ending with a separator. */
-    public final static String OS_SDK_DOCS_FOLDER = FD_DOCS + File.separator;
-
-    /** Path of the tools directory relative to the sdk folder.
-     *  This is an OS path, ending with a separator. */
-    public final static String OS_SDK_TOOLS_FOLDER = FD_TOOLS + File.separator;
+    public final static String WS_JAVADOC_FOLDER_LEAF = SdkConstants.FD_DOCS + "/reference"; //$NON-NLS-1$
 
     /** Path of the samples directory relative to the sdk folder.
-     *  This is an OS path, ending with a separator. */
-    public final static String OS_SDK_SAMPLES_FOLDER = FD_SAMPLES + File.separator;
-
-    /** Path of the lib directory relative to the sdk folder.
-     *  This is an OS path, ending with a separator. */
-    public final static String OS_SDK_LIBS_FOLDER =
-        OS_SDK_TOOLS_FOLDER + FD_LIBS + File.separator;
-
-    /** Path of the resources directory relative to the sdk folder.
-     *  This is an OS path, ending with a separator. */
-    public final static String OS_SDK_RESOURCES_FOLDER =
-        OS_SDK_LIBS_FOLDER + FD_RESOURCES + File.separator;
-
-    /** Path of the resources directory relative to the sdk folder.
-     *  This is an OS path, ending with a separator. */
-    public final static String OS_SDK_FONTS_FOLDER =
-        OS_SDK_LIBS_FOLDER + FD_FONTS + File.separator;
-
-    /** Path of the skin directory relative to the sdk folder.
-     *  This is an OS path, ending with a separator. */
-    public final static String OS_SDK_SKINS_FOLDER =
-        OS_SDK_LIBS_FOLDER + FD_IMAGES + File.separator + FD_SKINS + File.separator;
-
-    /** Path of the attrs.xml file relative to the sdk folder. */
-    public final static String OS_SDK_ATTRS_XML =
-        OS_SDK_RESOURCES_FOLDER + File.separator + FD_DEFAULT_RES + File.separator +
-        FD_VALUES + File.separator + FN_ATTRS_XML;
-
-    /** Path of the attrs_manifest.xml file relative to the sdk folder. */
-    public final static String OS_SDK_ATTRS_MANIFEST_XML =
-        OS_SDK_RESOURCES_FOLDER + File.separator + FD_DEFAULT_RES + File.separator +
-        FD_VALUES + File.separator + FN_ATTRS_MANIFEST_XML;
-
-    /** Path of the layoutlib.jar file relative to the sdk folder. */
-    public final static String OS_SDK_LIBS_LAYOUTLIB_JAR =
-        OS_SDK_LIBS_FOLDER + FN_LAYOUTLIB_JAR;
+     *  This is an OS path, ending with a separator.
+     *  FIXME: remove once the NPW is fixed. */
+    public final static String OS_SDK_SAMPLES_FOLDER = SdkConstants.FD_SAMPLES + File.separator;
 
     /** Path of the dx.jar file relative to the sdk folder. */
     public final static String OS_SDK_LIBS_DX_JAR =
-        OS_SDK_LIBS_FOLDER + FN_DX_JAR;
+        SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + FN_DX_JAR;
 
     /** Regexp for single dot */
     public final static String RE_DOT = "\\."; //$NON-NLS-1$
@@ -255,17 +198,20 @@
     /** Namespace pattern for the custom resource XML, i.e. "http://schemas.android.com/apk/res/%s" */
     public final static String NS_CUSTOM_RESOURCES = "http://schemas.android.com/apk/res/%1$s"; //$NON-NLS-1$
 
+    /** The old common plug-in ID. Please do not use for new features. */
+    public static final String COMMON_PLUGIN_ID = "com.android.ide.eclipse.common"; //$NON-NLS-1$
+
     /** aapt marker error. */
-    public final static String MARKER_AAPT = CommonPlugin.PLUGIN_ID + ".aaptProblem"; //$NON-NLS-1$
+    public final static String MARKER_AAPT = COMMON_PLUGIN_ID + ".aaptProblem"; //$NON-NLS-1$
 
     /** XML marker error. */
-    public final static String MARKER_XML = CommonPlugin.PLUGIN_ID + ".xmlProblem"; //$NON-NLS-1$
+    public final static String MARKER_XML = COMMON_PLUGIN_ID + ".xmlProblem"; //$NON-NLS-1$
 
     /** aidl marker error. */
-    public final static String MARKER_AIDL = CommonPlugin.PLUGIN_ID + ".aidlProblem"; //$NON-NLS-1$
+    public final static String MARKER_AIDL = COMMON_PLUGIN_ID + ".aidlProblem"; //$NON-NLS-1$
     
     /** android marker error */
-    public final static String MARKER_ANDROID = CommonPlugin.PLUGIN_ID + ".androidProblem"; //$NON-NLS-1$
+    public final static String MARKER_ANDROID = COMMON_PLUGIN_ID + ".androidProblem"; //$NON-NLS-1$
     
     /** Name for the "type" marker attribute */
     public final static String MARKER_ATTR_TYPE = "android.type"; //$NON-NLS-1$
@@ -301,6 +247,7 @@
     public final static String CLASS_PREFERENCES =
         "android.preference." + CLASS_PREFERENCE_SCREEN; //$NON-NLS-1$
     public final static String CLASS_PREFERENCEGROUP = "android.preference.PreferenceGroup"; //$NON-NLS-1$
+    public final static String CLASS_PARCELABLE = "android.os.Parcelable"; //$NON-NLS-1$
     
     public final static String CLASS_BRIDGE = "com.android.layoutlib.bridge.Bridge"; //$NON-NLS-1$
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/EclipseUiHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/EclipseUiHelper.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/EclipseUiHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/EclipseUiHelper.java
index 8dd8e60..6dc8562 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/EclipseUiHelper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/EclipseUiHelper.java
@@ -53,7 +53,7 @@
                 try {
                     IViewPart part = page.showView(viewId,
                             null /* secondaryId */,
-                            activate ? page.VIEW_ACTIVATE : page.VIEW_VISIBLE);
+                            activate ? IWorkbenchPage.VIEW_ACTIVATE : IWorkbenchPage.VIEW_VISIBLE);
                 } catch (PartInitException e) {
                     // ignore
                 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/Messages.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/Messages.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/Messages.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/Messages.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/SdkStatsHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/SdkStatsHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/SdkStatsHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/SdkStatsHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/StreamHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/StreamHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/StreamHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/StreamHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/messages.properties b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/messages.properties
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/messages.properties
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/messages.properties
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/preferences/UsagePreferencePage.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
index 42f2a8b..cb98525 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
@@ -44,6 +44,7 @@
     private final static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$
     private final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
     private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
+    private final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
     private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
     private final static String NODE_APPLICATION = "application"; //$NON-NLS-1$
     private final static String NODE_ACTIVITY = "activity"; //$NON-NLS-1$
@@ -53,6 +54,7 @@
     private final static String NODE_INTENT = "intent-filter"; //$NON-NLS-1$
     private final static String NODE_ACTION = "action"; //$NON-NLS-1$
     private final static String NODE_CATEGORY = "category"; //$NON-NLS-1$
+    private final static String NODE_USES_SDK = "uses-sdk"; //$NON-NLS-1$
 
     private final static int LEVEL_MANIFEST = 0;
     private final static int LEVEL_APPLICATION = 1;
@@ -77,6 +79,8 @@
         private Set<String> mProcesses = null;
         /** debuggable attribute value. If null, the attribute is not present. */
         private Boolean mDebuggable = null;
+        /** API level requirement. if 0 the attribute was not present. */
+        private int mApiLevelRequirement = 0;
 
         //--- temporary data/flags used during parsing
         private IJavaProject mJavaProject;
@@ -142,12 +146,19 @@
         }
         
         /**
-         * Returns the debuggable attribute value or null if it is not set.
+         * Returns the <code>debuggable</code> attribute value or null if it is not set.
          */
         Boolean getDebuggable() {
             return mDebuggable;
         }
         
+        /**
+         * Returns the <code>minSdkVersion</code> attribute, or 0 if it's not set. 
+         */
+        int getApiLevelRequirement() {
+            return mApiLevelRequirement;
+        }
+        
         /* (non-Javadoc)
          * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator)
          */
@@ -171,7 +182,7 @@
 
                 // if we're at a valid level
                 if (mValidLevel == mCurrentLevel) {
-                    String processName;
+                    String value;
                     switch (mValidLevel) {
                         case LEVEL_MANIFEST:
                             if (NODE_MANIFEST.equals(localName)) {
@@ -183,19 +194,28 @@
                             break;
                         case LEVEL_APPLICATION:
                             if (NODE_APPLICATION.equals(localName)) {
-                                processName = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
+                                value = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
                                         true /* hasNamespace */);
-                                if (processName != null) {
-                                    addProcessName(processName);
+                                if (value != null) {
+                                    addProcessName(value);
                                 }
                                 
-                                String debuggable = getAttributeValue(attributes,
-                                        ATTRIBUTE_DEBUGGABLE, true /* hasNamespace*/);
-                                if (debuggable != null) {
-                                    mDebuggable = Boolean.parseBoolean(debuggable);
+                                value = getAttributeValue(attributes, ATTRIBUTE_DEBUGGABLE,
+                                        true /* hasNamespace*/);
+                                if (value != null) {
+                                    mDebuggable = Boolean.parseBoolean(value);
                                 }
                                 
                                 mValidLevel++;
+                            } else if (NODE_USES_SDK.equals(localName)) {
+                                value = getAttributeValue(attributes, ATTRIBUTE_MIN_SDK_VERSION,
+                                        true /* hasNamespace */);
+                                
+                                try {
+                                    mApiLevelRequirement = Integer.parseInt(value);
+                                } catch (NumberFormatException e) {
+                                    handleError(e, -1 /* lineNumber */);
+                                }
                             }
                             break;
                         case LEVEL_ACTIVITY:
@@ -301,7 +321,7 @@
         @Override
         public void error(SAXParseException e) throws SAXException {
             if (mMarkErrors) {
-                super.error(e);
+                handleError(e, e.getLineNumber());
             }
         }
 
@@ -311,7 +331,7 @@
         @Override
         public void fatalError(SAXParseException e) throws SAXException {
             if (mMarkErrors) {
-                super.fatalError(e);
+                handleError(e, e.getLineNumber());
             }
         }
 
@@ -457,6 +477,7 @@
     private final String mLauncherActivity;
     private final String[] mProcesses;
     private final Boolean mDebuggable;
+    private final int mApiLevelRequirement;
 
     static {
         sParserFactory = SAXParserFactory.newInstance();
@@ -491,7 +512,8 @@
             
             return new AndroidManifestParser(manifestHandler.getPackage(),
                     manifestHandler.getActivities(), manifestHandler.getLauncherActivity(),
-                    manifestHandler.getProcesses(), manifestHandler.getDebuggable());
+                    manifestHandler.getProcesses(), manifestHandler.getDebuggable(),
+                    manifestHandler.getApiLevelRequirement());
         } catch (ParserConfigurationException e) {
         } catch (SAXException e) {
         } catch (IOException e) {
@@ -530,7 +552,8 @@
                 // get the result from the handler
                 return new AndroidManifestParser(manifestHandler.getPackage(),
                         manifestHandler.getActivities(), manifestHandler.getLauncherActivity(),
-                        manifestHandler.getProcesses(), manifestHandler.getDebuggable());
+                        manifestHandler.getProcesses(), manifestHandler.getDebuggable(),
+                        manifestHandler.getApiLevelRequirement());
             }
         } catch (ParserConfigurationException e) {
         } catch (SAXException e) {
@@ -610,6 +633,14 @@
     }
     
     /**
+     * Returns the <code>minSdkVersion</code> attribute, or 0 if it's not set. 
+     */
+    public int getApiLevelRequirement() {
+        return mApiLevelRequirement;
+    }
+
+    
+    /**
      * Private constructor to enforce using
      * {@link #parse(IJavaProject, XmlErrorListener, boolean, boolean)},
      * {@link #parse(IJavaProject, IFile, XmlErrorListener, boolean, boolean)},
@@ -619,14 +650,17 @@
      * @param activities the list of activities parsed from the manifest.
      * @param launcherActivity the launcher activity parser from the manifest.
      * @param processes the list of custom processes declared in the manifest.
-     * @param debuggable the debuggable attribute.
+     * @param debuggable the debuggable attribute, or null if not set.
+     * @param apiLevelRequirement the minSdkVersion attribute value or 0 if not set.
      */
     private AndroidManifestParser(String javaPackage, String[] activities,
-            String launcherActivity, String[] processes, Boolean debuggable) {
+            String launcherActivity, String[] processes, Boolean debuggable,
+            int apiLevelRequirement) {
         mJavaPackage = javaPackage;
         mActivities = activities;
         mLauncherActivity = launcherActivity;
         mProcesses = processes;
         mDebuggable = debuggable;
+        mApiLevelRequirement = apiLevelRequirement;
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidXPathFactory.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
index 57ca496..c69e875 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/BaseProjectHelper.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.common.project;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
 import com.android.ide.eclipse.common.project.XmlErrorHandler.XmlErrorListener;
 
 import org.eclipse.core.resources.IFile;
@@ -108,7 +108,7 @@
 
             return marker;
         } catch (CoreException e) {
-            CommonPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
+            AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
                     markerId, file.getFullPath());
         }
         
@@ -117,10 +117,9 @@
 
     /**
      * Adds a marker to a resource.
-     * @param file the file to be marked
+     * @param resource the file to be marked
      * @param markerId The id of the marker to add.
      * @param message the message associated with the mark
-     * @param lineNumber the line number where to put the mark
      * @param severity the severity of the marker.
      * @return the IMarker that was added or null if it failed to add one.
      */
@@ -138,7 +137,7 @@
 
             return marker;
         } catch (CoreException e) {
-            CommonPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
+            AdtPlugin.log(e, "Failed to add marker '%1$s' to '%2$s'",
                     markerId, resource.getFullPath());
         }
         
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ExportHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ExportHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ExportHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ExportHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/ProjectChooserHelper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
similarity index 77%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
index 3492cb4..26fbf42 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/XmlErrorHandler.java
@@ -65,11 +65,7 @@
      */
     @Override
     public void error(SAXParseException exception) throws SAXException {
-        if (mErrorListener != null) {
-            mErrorListener.errorFound();
-        }
-        BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
-                exception.getLineNumber(), IMarker.SEVERITY_ERROR);
+        handleError(exception, exception.getLineNumber());
     }
 
     /**
@@ -77,13 +73,8 @@
      * @param exception the parsing exception
      */
     @Override
-    public void fatalError(SAXParseException exception)
-            throws SAXException {
-        if (mErrorListener != null) {
-            mErrorListener.errorFound();
-        }
-        BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
-                exception.getLineNumber(), IMarker.SEVERITY_ERROR);
+    public void fatalError(SAXParseException exception) throws SAXException {
+        handleError(exception, exception.getLineNumber());
     }
 
     /**
@@ -99,4 +90,23 @@
     protected final IFile getFile() {
         return mFile;
     }
+    
+    /**
+     * Handles a parsing error and an optional line number.
+     * @param exception
+     * @param lineNumber
+     */
+    protected void handleError(Exception exception, int lineNumber) {
+        if (mErrorListener != null) {
+            mErrorListener.errorFound();
+        }
+        
+        if (lineNumber != -1) {
+            BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
+                    lineNumber, IMarker.SEVERITY_ERROR);
+        } else {
+            BaseProjectHelper.addMarker(mFile, AndroidConstants.MARKER_XML, exception.getMessage(),
+                    IMarker.SEVERITY_ERROR);
+        }
+    }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
index 43260c0..3176c8e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/AttrsXmlParser.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.common.resources;
 
-import com.android.ide.eclipse.common.CommonPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo;
 import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo.Format;
 import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -106,7 +106,7 @@
         Document doc = getDocument();
 
         if (doc == null) {
-            CommonPlugin.log(IStatus.WARNING, "Failed to find %1$s", //$NON-NLS-1$
+            AdtPlugin.log(IStatus.WARNING, "Failed to find %1$s", //$NON-NLS-1$
                     mOsAttrsXmlPath);
             return this;
         }
@@ -119,7 +119,7 @@
         }
         
         if (res == null) {
-            CommonPlugin.log(IStatus.WARNING, "Failed to find a <resources> node in %1$s", //$NON-NLS-1$
+            AdtPlugin.log(IStatus.WARNING, "Failed to find a <resources> node in %1$s", //$NON-NLS-1$
                     mOsAttrsXmlPath);
             return this;
         }
@@ -189,13 +189,13 @@
                 DocumentBuilder builder = factory.newDocumentBuilder();
                 mDocument = builder.parse(new File(mOsAttrsXmlPath));
             } catch (ParserConfigurationException e) {
-                CommonPlugin.log(e, "Failed to create XML document builder for %1$s", //$NON-NLS-1$
+                AdtPlugin.log(e, "Failed to create XML document builder for %1$s", //$NON-NLS-1$
                         mOsAttrsXmlPath);
             } catch (SAXException e) {
-                CommonPlugin.log(e, "Failed to parse XML document %1$s", //$NON-NLS-1$
+                AdtPlugin.log(e, "Failed to parse XML document %1$s", //$NON-NLS-1$
                         mOsAttrsXmlPath);
             } catch (IOException e) {
-                CommonPlugin.log(e, "Failed to read XML document %1$s", //$NON-NLS-1$
+                AdtPlugin.log(e, "Failed to read XML document %1$s", //$NON-NLS-1$
                         mOsAttrsXmlPath);
             }
         }
@@ -340,7 +340,7 @@
                         formats.add(format);
                     }
                 } catch (IllegalArgumentException e) {
-                    CommonPlugin.log(e, "Unknown format name '%s' in <attr name=\"%s\">, file '%s'.", //$NON-NLS-1$
+                    AdtPlugin.log(e, "Unknown format name '%s' in <attr name=\"%s\">, file '%s'.", //$NON-NLS-1$
                             f, name, getOsAttrsXmlPath());
                 }
             }
@@ -389,7 +389,7 @@
             if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(filter)) {
                 Node nameNode = child.getAttributes().getNamedItem("name");  //$NON-NLS-1$
                 if (nameNode == null) {
-                    CommonPlugin.log(IStatus.WARNING,
+                    AdtPlugin.log(IStatus.WARNING,
                             "Missing name attribute in <attr name=\"%s\"><%s></attr>", //$NON-NLS-1$
                             attrName, filter);
                 } else {
@@ -401,7 +401,7 @@
                     
                     Node valueNode = child.getAttributes().getNamedItem("value");  //$NON-NLS-1$
                     if (valueNode == null) {
-                        CommonPlugin.log(IStatus.WARNING,
+                        AdtPlugin.log(IStatus.WARNING,
                                 "Missing value attribute in <attr name=\"%s\"><%s name=\"%s\"></attr>", //$NON-NLS-1$
                                 attrName, filter, name);
                     } else {
@@ -419,7 +419,7 @@
                             map.put(name, Integer.valueOf(i));
                             
                         } catch(NumberFormatException e) {
-                            CommonPlugin.log(e,
+                            AdtPlugin.log(e,
                                     "Value in <attr name=\"%s\"><%s name=\"%s\" value=\"%s\"></attr> is not a valid decimal or hexadecimal", //$NON-NLS-1$
                                     attrName, filter, name, value);
                         }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/DeclareStyleableInfo.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IIdResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IPathChangedListener.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IResourceRepository.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IResourceRepository.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/IResourceRepository.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/IResourceRepository.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceType.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceType.java
similarity index 83%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceType.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceType.java
index 3d64e5d..60c471e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ResourceType.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ResourceType.java
@@ -21,7 +21,7 @@
  */
 public enum ResourceType {
     ANIM("anim", "Animation"), //$NON-NLS-1$
-    ARRAY("array", "Array"), //$NON-NLS-1$
+    ARRAY("array", "Array", "string-array", "integer-array"), //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-4$
     ATTR("attr", "Attr"), //$NON-NLS-1$
     COLOR("color", "Color"), //$NON-NLS-1$
     DIMEN("dimen", "Dimension"), //$NON-NLS-1$
@@ -35,12 +35,14 @@
     STYLEABLE("styleable", "Styleable"), //$NON-NLS-1$
     XML("xml", "XML"); //$NON-NLS-1$
 
-    private String mName;
-    private String mDisplayName;
+    private final String mName;
+    private final String mDisplayName;
+    private final String[] mAlternateXmlNames;
 
-    ResourceType(String name, String displayName) {
+    ResourceType(String name, String displayName, String... alternateXmlNames) {
         mName = name;
         mDisplayName = displayName;
+        mAlternateXmlNames = alternateXmlNames;
     }
     
     /**
@@ -66,6 +68,13 @@
         for (ResourceType rType : values()) {
             if (rType.mName.equals(name)) {
                 return rType;
+            } else if (rType.mAlternateXmlNames != null) {
+                // if there are alternate Xml Names, we test those too
+                for (String alternate : rType.mAlternateXmlNames) {
+                    if (alternate.equals(name)) {
+                        return rType;
+                    }
+                }
             }
         }
         return null;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/resources/ViewClassInfo.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
index 1dd0c27..d1b4547 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidContentAssist.java
@@ -16,11 +16,12 @@
 
 package com.android.ide.eclipse.editors;
 
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
 import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor;
@@ -80,15 +81,20 @@
     protected final static String ROOT_ELEMENT = "";
 
     /** Descriptor of the root of the XML hierarchy. This a "fake" ElementDescriptor which
-     *  is used to list all the possible roots given by actual implementations. */
+     *  is used to list all the possible roots given by actual implementations.
+     *  DO NOT USE DIRECTLY. Call {@link #getRootDescriptor()} instead. */
     private ElementDescriptor mRootDescriptor;
 
+    private final int mDescriptorId;
+    
+    private AndroidEditor mEditor;
+
     /**
      * Constructor for AndroidContentAssist 
      * @param rootElementDescriptors The valid root elements of the XML hierarchy
      */
-    public AndroidContentAssist(ElementDescriptor[] rootElementDescriptors) {
-        mRootDescriptor = new ElementDescriptor("", rootElementDescriptors);
+    public AndroidContentAssist(int descriptorId) {
+        mDescriptorId = descriptorId;
     }
 
     /**
@@ -104,8 +110,11 @@
      */
     public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
       
-        AndroidEditor editor = getAndroidEditor(viewer);
-        UiElementNode rootUiNode = editor.getUiRootNode();
+        if (mEditor == null) {
+            mEditor = getAndroidEditor(viewer);
+        }
+
+        UiElementNode rootUiNode = mEditor.getUiRootNode();
         
         Object[] choices = null; /* An array of ElementDescriptor, or AttributeDescriptor
                                     or String or null */
@@ -245,7 +254,7 @@
         if (current_node.getParentNode().getNodeType() == Node.ELEMENT_NODE) {
             grandparent = getDescriptor(current_node.getParentNode().getNodeName());
         } else if (current_node.getParentNode().getNodeType() == Node.DOCUMENT_NODE) {
-            grandparent = mRootDescriptor;
+            grandparent = getRootDescriptor();
         }
         if (grandparent != null) {
             for (ElementDescriptor e : grandparent.getChildren()) {
@@ -339,8 +348,11 @@
                         greatGrandParentName = greatGrandParent.getLocalName();
                     }
                 }
-                choices = FrameworkResourceManager.getInstance().getValues(
-                        parent, attrInfo.name, greatGrandParentName);
+                
+                AndroidTargetData data = mEditor.getTargetData();
+                if (data != null) {
+                    choices = data.getAttributeValues(parent, attrInfo.name, greatGrandParentName);
+                }
             }
         } else {
             // Editing an attribute's name... Get attributes valid for the parent node.
@@ -378,7 +390,7 @@
         } else if (parent_node.getNodeType() == Node.DOCUMENT_NODE) {
             // We're editing a text node at the first level (i.e. root node).
             // Limit content assist to the only valid root elements.
-            choices = mRootDescriptor.getChildren();
+            choices = getRootDescriptor().getChildren();
         }
         return choices;
     }
@@ -509,7 +521,7 @@
      * is returned.
      */
     private ElementDescriptor getDescriptor(String nodeName) {
-        return mRootDescriptor.findChildrenDescriptor(nodeName, true /* recursive */);
+        return getRootDescriptor().findChildrenDescriptor(nodeName, true /* recursive */);
     }
 
     public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
@@ -539,8 +551,8 @@
 
     public String getErrorMessage() {
         return null;
-    }   
-
+    }
+    
     /**
      * Heuristically extracts the prefix used for determining template relevance
      * from the viewer's document. The default implementation returns the String from
@@ -710,6 +722,26 @@
     }
     
     /**
+     * Computes (if needed) and returns the root descriptor.
+     * @return
+     */
+    private ElementDescriptor getRootDescriptor() {
+        if (mRootDescriptor == null) {
+            AndroidTargetData data = mEditor.getTargetData();
+            if (data != null) {
+                IDescriptorProvider descriptorProvider = data.getDescriptorProvider(mDescriptorId);
+                
+                if (descriptorProvider != null) {
+                    mRootDescriptor = new ElementDescriptor("",
+                            descriptorProvider.getRootElementDescriptors());
+                }
+            }
+        }
+        
+        return mRootDescriptor;
+    }
+    
+    /**
      * Returns the active {@link AndroidEditor} matching this source viewer.
      */
     private AndroidEditor getAndroidEditor(ITextViewer viewer) {
@@ -729,5 +761,7 @@
 
         return null;
     }
+    
+    
 
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidEditor.java
similarity index 74%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidEditor.java
index 74eca96..78e0401 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidEditor.java
@@ -16,10 +16,14 @@
 
 package com.android.ide.eclipse.editors;
 
-import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceChangeEvent;
 import org.eclipse.core.resources.IResourceChangeListener;
@@ -29,15 +33,18 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.dialogs.ErrorDialog;
 import org.eclipse.jface.text.source.ISourceViewer;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IActionBars;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IEditorSite;
 import org.eclipse.ui.IFileEditorInput;
 import org.eclipse.ui.IWorkbenchPage;
 import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.actions.ActionFactory;
 import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
 import org.eclipse.ui.forms.IManagedForm;
 import org.eclipse.ui.forms.editor.FormEditor;
@@ -71,7 +78,7 @@
  * source editor. This can be a no-op if desired.
  */
 public abstract class AndroidEditor extends FormEditor implements IResourceChangeListener {
-
+    
     /** Preference name for the current page of this file */
     private static final String PREF_CURRENT_PAGE = "_current_page";
 
@@ -87,9 +94,11 @@
     /** Page index of the text editor (always the last page) */
     private int mTextPageIndex;
     /** The text editor */
-    private StructuredTextEditor mEditor;
+    private StructuredTextEditor mTextEditor;
     /** Listener for the XML model from the StructuredEditor */
     private XmlModelStateListener mXmlModelStateListener;
+    /** Listener to update the root node if the resource framework changes */
+    private Runnable mResourceRefreshListener;
 
     /**
      * Creates a form editor.
@@ -97,6 +106,16 @@
     public AndroidEditor() {
         super();
         ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
+        
+        mResourceRefreshListener = new Runnable() {
+            public void run() {
+                commitPages(false /* onSave */);
+
+                // recreate the ui root node always
+                initUiRootNode(true /*force*/);
+            }
+        };
+        AdtPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
     }
 
     // ---- Abstract Methods ----
@@ -113,6 +132,12 @@
      * Derived classes must implement this to add their own specific tabs.
      */
     abstract protected void createFormPages();
+    
+    /**
+     * Creates the initial UI Root Node, including the known mandatory elements.
+     * @param force if true, a new UiManifestNode is recreated even if it already exists.
+     */
+    abstract protected void initUiRootNode(boolean force);
 
     /**
      * Subclasses should override this method to process the new XML Model, which XML
@@ -143,6 +168,26 @@
     protected void createAndroidPages() {
         createFormPages();
         createTextEditor();
+
+        createUndoRedoActions();
+    }
+
+    /**
+     * Creates undo redo actions for the editor site (so that it works for any page of this
+     * multi-page editor) by re-using the actions defined by the {@link StructuredTextEditor}
+     * (aka the XML text editor.)
+     */
+    private void createUndoRedoActions() {
+        IActionBars bars = getEditorSite().getActionBars();
+        if (bars != null) {
+            IAction action = mTextEditor.getAction(ActionFactory.UNDO.getId());
+            bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), action);
+
+            action = mTextEditor.getAction(ActionFactory.REDO.getId());
+            bars.setGlobalActionHandler(ActionFactory.REDO.getId(), action);
+            
+            bars.updateActionBars();
+        }
     }
 
     /**
@@ -155,7 +200,7 @@
             if (getEditorInput() instanceof IFileEditorInput) {
                 IFile file = ((IFileEditorInput) getEditorInput()).getFile();
     
-                QualifiedName qname = new QualifiedName(AndroidConstants.EDITORS_PLUGIN_ID,
+                QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID,
                         getClass().getSimpleName() + PREF_CURRENT_PAGE);
                 String pageId;
                 try {
@@ -177,7 +222,7 @@
                 // AssertionError from setActivePage when the index is out of bounds.
                 // Generally speaking we just want to ignore any exception and fall back on the
                 // first page rather than crash the editor load. Logging the error is enough.
-                EditorsPlugin.log(e, "Selecting page '%s' in AndroidEditor failed", defaultPageId);
+                AdtPlugin.log(e, "Selecting page '%s' in AndroidEditor failed", defaultPageId);
             }
         }
     }
@@ -224,7 +269,7 @@
         if (getEditorInput() instanceof IFileEditorInput) {
             IFile file = ((IFileEditorInput) getEditorInput()).getFile();
 
-            QualifiedName qname = new QualifiedName(AndroidConstants.EDITORS_PLUGIN_ID,
+            QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID,
                     getClass().getSimpleName() + PREF_CURRENT_PAGE);
             try {
                 file.setPersistentProperty(qname, Integer.toString(newPageIndex));
@@ -248,10 +293,10 @@
                     IWorkbenchPage[] pages = getSite().getWorkbenchWindow()
                             .getPages();
                     for (int i = 0; i < pages.length; i++) {
-                        if (((FileEditorInput)mEditor.getEditorInput())
+                        if (((FileEditorInput)mTextEditor.getEditorInput())
                                 .getFile().getProject().equals(
                                         event.getResource())) {
-                            IEditorPart editorPart = pages[i].findEditor(mEditor
+                            IEditorPart editorPart = pages[i].findEditor(mTextEditor
                                     .getEditorInput());
                             pages[i].closeEditor(editorPart, true);
                         }
@@ -294,6 +339,12 @@
             }
         }
         ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+
+        if (mResourceRefreshListener != null) {
+            AdtPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
+            mResourceRefreshListener = null;
+        }
+
         super.dispose();
     }
     
@@ -447,13 +498,13 @@
      */
     private void createTextEditor() {
         try {
-            mEditor = new StructuredTextEditor();
-            int index = addPage(mEditor, getEditorInput());
+            mTextEditor = new StructuredTextEditor();
+            int index = addPage(mTextEditor, getEditorInput());
             mTextPageIndex = index;
-            setPageText(index, mEditor.getTitle());
+            setPageText(index, mTextEditor.getTitle());
 
-            if (!(mEditor.getTextViewer().getDocument() instanceof IStructuredDocument)) {
-                Status status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+            if (!(mTextEditor.getTextViewer().getDocument() instanceof IStructuredDocument)) {
+                Status status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
                         "Error opening the Android XML editor. Is the document an XML file?");
                 throw new RuntimeException("Android XML Editor Error", new CoreException(status));
             }
@@ -464,6 +515,8 @@
                     mXmlModelStateListener = new XmlModelStateListener();
                     xml_model.addModelStateListener(mXmlModelStateListener);
                     mXmlModelStateListener.modelChanged(xml_model);
+                } catch (Exception e) {
+                    AdtPlugin.log(e, "Error while loading editor"); //$NON-NLS-1$
                 } finally {
                     xml_model.releaseFromRead();
                 }
@@ -478,11 +531,11 @@
      * Returns the ISourceViewer associated with the Structured Text editor. 
      */
     public final ISourceViewer getStructuredSourceViewer() {
-        if (mEditor != null) {
+        if (mTextEditor != null) {
             // We can't access mEditor.getSourceViewer() because it is protected,
             // however getTextViewer simply returns the SourceViewer casted, so we
             // can use it instead.
-            return mEditor.getTextViewer();
+            return mTextEditor.getTextViewer();
         }
         return null;
     }
@@ -492,8 +545,8 @@
      * Editor) or null if not available.
      */
     public final IStructuredDocument getStructuredDocument() {
-        if (mEditor != null && mEditor.getTextViewer() != null) {
-            return (IStructuredDocument) mEditor.getTextViewer().getDocument();
+        if (mTextEditor != null && mTextEditor.getTextViewer() != null) {
+            return (IStructuredDocument) mTextEditor.getTextViewer().getDocument();
         }
         return null;
     }
@@ -539,14 +592,17 @@
     /**
      * Helper class to perform edits on the XML model whilst making sure the
      * model has been prepared to be changed.
+     * <p/>
+     * It first gets a model for edition using {@link #getModelForEdit()},
+     * then calls {@link IStructuredModel#aboutToChangeModel()},
+     * then performs the requested action
+     * and finally calls {@link IStructuredModel#changedModel()}
+     * and {@link IStructuredModel#releaseFromEdit()}.
+     * <p/>
+     * The method is synchronous. As soon as the {@link IStructuredModel#changedModel()} method
+     * is called, XML model listeners will be triggered.
      * 
-     * It first gets a model for edition, then calls aboutToChangeModel, then performs the
-     * requested action and finally calls changedModel and releaseFromEdit.
-     * 
-     * The method is synchronous. As soon as the changedModel method is called, XML model
-     * listeners will be triggered.
-     * 
-     * @param edit_action Something that will change 
+     * @param edit_action Something that will change the XML.
      */
     public final void editXmlModel(Runnable edit_action) {
         IStructuredModel model = getModelForEdit();
@@ -561,11 +617,81 @@
     }
     
     /**
+     * Starts an "undo recording" session. This is managed by the underlying undo manager
+     * associated to the structured XML model.
+     * <p/>
+     * There <em>must</em> be a corresponding call to {@link #endUndoRecording()}.
+     * <p/>
+     * beginUndoRecording/endUndoRecording calls can be nested (inner calls are ignored, only one
+     * undo operation is recorded.)
+     * 
+     * @param label The label for the undo operation. Can be null but we should really try to put
+     *              something meaningful if possible.
+     * @return True if the undo recording actually started, false if any kind of error occured.
+     *         {@link #endUndoRecording()} should only be called if True is returned.
+     */
+    private final boolean beginUndoRecording(String label) {
+        IStructuredDocument document = getStructuredDocument();
+        if (document != null) {
+            IModelManager mm = StructuredModelManager.getModelManager();
+            if (mm != null) {
+                IStructuredModel model = mm.getModelForEdit(document);
+                if (model != null) {
+                    model.beginRecording(this, label);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * Ends an "undo recording" session.
+     * <p/>
+     * This is the counterpart call to {@link #beginUndoRecording(String)} and should only be
+     * used if the initial call returned true.
+     */
+    private final void endUndoRecording() {
+        IStructuredDocument document = getStructuredDocument();
+        if (document != null) {
+            IModelManager mm = StructuredModelManager.getModelManager();
+            if (mm != null) {
+                IStructuredModel model = mm.getModelForEdit(document);
+                if (model != null) {
+                    model.endRecording(this);
+                }
+            }
+        }
+    }
+    
+    /**
+     * Creates an "undo recording" session by calling the undoableAction runnable
+     * using {@link #beginUndoRecording(String)} and {@link #endUndoRecording()}.
+     * <p>
+     * You can nest several calls to {@link #wrapUndoRecording(String, Runnable)}, only one
+     * recording session will be created.
+     * 
+     * @param label The label for the undo operation. Can be null. Ideally we should really try
+     *              to put something meaningful if possible.
+     */
+    public void wrapUndoRecording(String label, Runnable undoableAction) {
+        boolean recording = false;
+        try {
+            recording = beginUndoRecording(label);
+            undoableAction.run();
+        } finally {
+            if (recording) {
+                endUndoRecording();
+            }
+        }
+    }
+    
+    /**
      * Returns the XML {@link Document} or null if we can't get it
      */
     protected final Document getXmlDocument(IStructuredModel model) {
         if (model == null) {
-            EditorsPlugin.log(IStatus.WARNING, "Android Editor: No XML model for root node."); //$NON-NLS-1$
+            AdtPlugin.log(IStatus.WARNING, "Android Editor: No XML model for root node."); //$NON-NLS-1$
             return null;
         }
 
@@ -577,6 +703,45 @@
     }
     
     /**
+     * Returns the {@link IProject} for the edited file.
+     */
+    public IProject getProject() {
+        if (mTextEditor != null) {
+            IEditorInput input = mTextEditor.getEditorInput();
+            if (input instanceof FileEditorInput) {
+                FileEditorInput fileInput = (FileEditorInput)input;
+                IFile inputFile = fileInput.getFile();
+                
+                if (inputFile != null) {
+                    return inputFile.getProject();
+                }
+            }
+        }
+        
+        return null;
+    }
+    
+    /**
+     * Returns the {@link PlatformData} for the edited file.
+     */
+    public AndroidTargetData getTargetData() {
+        IProject project = getProject();
+        if (project != null) {
+            Sdk currentSdk = Sdk.getCurrent();
+            if (currentSdk != null) {
+                IAndroidTarget target = currentSdk.getTarget(project);
+                
+                if (target != null) {
+                    return currentSdk.getTargetData(target);
+                }
+            }
+        }
+        
+        return null;
+    }
+
+    
+    /**
      * Listen to changes in the underlying XML model in the structured editor.
      */
     private class XmlModelStateListener implements IModelStateListener {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/AndroidSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/FirstElementParser.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/FirstElementParser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/FirstElementParser.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java
similarity index 97%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java
index 9e3b733..e3de3af 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/IconFactory.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java
@@ -17,6 +17,7 @@
 
 package com.android.ide.eclipse.editors;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
 
 import org.eclipse.jface.resource.ImageDescriptor;
@@ -100,8 +101,6 @@
      *        one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT.
      */
     public Image getIcon(String osName, int color, int shape) {
-        EditorsPlugin plugin = EditorsPlugin.getDefault();
-        
         String key = Character.toString((char) shape) + Integer.toString(color) + osName;
         Image icon = mIconMap.get(key);
         if (icon == null && !mIconMap.containsKey(key)) {
@@ -143,13 +142,11 @@
      *        one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT.
      */
     public ImageDescriptor getImageDescriptor(String osName, int color, int shape) {
-        EditorsPlugin plugin = EditorsPlugin.getDefault();
-
         String key = Character.toString((char) shape) + Integer.toString(color) + osName;
         ImageDescriptor id = mImageDescMap.get(key);
         if (id == null && !mImageDescMap.containsKey(key)) {
-            id = plugin.imageDescriptorFromPlugin(
-                    AndroidConstants.EDITORS_PLUGIN_ID,
+            id = AdtPlugin.imageDescriptorFromPlugin(
+                    AdtPlugin.PLUGIN_ID,
                     String.format("/icons/%1$s.png", osName)); //$NON-NLS-1$
 
             if (id == null) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
similarity index 82%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
index 48fa903..2c779b2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptor.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.descriptors;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.IconFactory;
 import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -61,30 +61,6 @@
     public final String getNamespaceUri() {
         return mNsUri;
     }
-
-    /**
-     * Returns the XML qualified name of the attribute (case sensitive, with namespace prefix
-     * if present)
-     * 
-     * @deprecated
-     */
-    private final String getXmlName() {
-        return mXmlLocalName;
-    }
-    
-    /**
-     * Returns the namespace of the attribute.
-     * 
-     * @deprecated
-     */
-    private final String getNamespace() {
-        // For now we hard-code the prefix as being "android"
-        if (mXmlLocalName.startsWith("android:")) { //$NON-NLs-1$
-            return AndroidConstants.NS_RESOURCES;
-        }
-        
-        return ""; //$NON-NLs-1$
-    }
     
     final void setParent(ElementDescriptor parent) {
         mParent = parent;
@@ -107,7 +83,7 @@
         IconFactory factory = IconFactory.getInstance();
         Image icon;
         icon = factory.getIcon(getXmlLocalName(), IconFactory.COLOR_RED, IconFactory.SHAPE_CIRCLE);
-        return icon != null ? icon : EditorsPlugin.getAndroidLogo();
+        return icon != null ? icon : AdtPlugin.getAndroidLogo();
     }
     
     /**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/AttributeDescriptorLabelProvider.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/BooleanAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
similarity index 85%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
index f848d79..c84bf57 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DescriptorsUtils.java
@@ -20,6 +20,8 @@
 import com.android.ide.eclipse.common.resources.ResourceType;
 import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo;
 import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo.Format;
+import com.android.ide.eclipse.editors.layout.LayoutConstants;
+import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
 
 import org.eclipse.swt.graphics.Image;
@@ -29,6 +31,7 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -39,6 +42,8 @@
  */
 public final class DescriptorsUtils {
 
+    private static final String DEFAULT_WIDGET_PREFIX = "widget";
+
     private static final int JAVADOC_BREAK_LENGTH = 60;
 
     /**
@@ -458,7 +463,8 @@
         
         Image icon = elementDescriptor.getIcon();
         if (icon != null) {
-            sb.append("<form><li style=\"image\" value=\"" + IMAGE_KEY + "\">"); //$NON-NLS-1$ //$NON-NLS-2$
+            sb.append("<form><li style=\"image\" value=\"" +        //$NON-NLS-1$
+                    IMAGE_KEY + "\">");                             //$NON-NLS-1$
         } else {
             sb.append("<form><p>");                                 //$NON-NLS-1$
         }
@@ -573,13 +579,13 @@
         // Detects {@link <base>#<name> <text>} where all 3 are optional
         Pattern p_link = Pattern.compile("\\{@link\\s+([^#\\}\\s]*)(?:#([^\\s\\}]*))?(?:\\s*([^\\}]*))?\\}(.*)"); //$NON-NLS-1$
         // Detects <code>blah</code> 
-        Pattern p_code = Pattern.compile("<code>(.+?)</code>(.*)"); //$NON-NLS-1$
+        Pattern p_code = Pattern.compile("<code>(.+?)</code>(.*)");                 //$NON-NLS-1$
         // Detects @blah@, used in hard-coded tooltip descriptors
-        Pattern p_elem = Pattern.compile("@([\\w -]+)@(.*)"); //$NON-NLS-1$
+        Pattern p_elem = Pattern.compile("@([\\w -]+)@(.*)");                       //$NON-NLS-1$
         // Detects a buffer that starts by @ < or { (one that was not matched above)
-        Pattern p_open = Pattern.compile("([@<\\{])(.*)"); //$NON-NLS-1$
+        Pattern p_open = Pattern.compile("([@<\\{])(.*)");                          //$NON-NLS-1$
         // Detects everything till the next potential separator, i.e. @ < or {
-        Pattern p_text = Pattern.compile("([^@<\\{]+)(.*)"); //$NON-NLS-1$
+        Pattern p_text = Pattern.compile("([^@<\\{]+)(.*)");                        //$NON-NLS-1$
 
         int currentLength = 0;
         String text = null;
@@ -668,28 +674,55 @@
      * <p/>
      * This does not override attributes which are not empty.
      */
-    public static void setDefaultLayoutAttributes(UiElementNode ui_node) {
-        ui_node.setAttributeValue("layout_width", "wrap_content", false /* override */);    //$NON-NLS-1$ $NON-NLS-2$
-        ui_node.setAttributeValue("layout_height", "wrap_content", false /* override */);   //$NON-NLS-1$ $NON-NLS-2$
+    public static void setDefaultLayoutAttributes(UiElementNode ui_node, boolean updateLayout) {
+        // if this ui_node is a layout and we're adding it to a document, use fill_parent for
+        // both W/H. Otherwise default to wrap_layout.
+        boolean fill = ui_node.getDescriptor().hasChildren() &&
+                       ui_node.getUiParent() instanceof UiDocumentNode;
+        ui_node.setAttributeValue(LayoutConstants.ATTR_LAYOUT_WIDTH,
+                fill ? LayoutConstants.VALUE_FILL_PARENT : LayoutConstants.VALUE_WRAP_CONTENT,
+                false /* override */);
+        ui_node.setAttributeValue(LayoutConstants.ATTR_LAYOUT_HEIGHT,
+                fill ? LayoutConstants.VALUE_FILL_PARENT : LayoutConstants.VALUE_WRAP_CONTENT,
+                false /* override */);
 
         String widget_id = getFreeWidgetId(ui_node.getUiRoot(),
-                new Object[] {ui_node.getDescriptor().getXmlLocalName(), 1, null });
+                new Object[] { ui_node.getDescriptor().getXmlLocalName(), null, null, null });
         if (widget_id != null) {
-            ui_node.setAttributeValue("id", "@+id/" + widget_id, false /* override */);   //$NON-NLS-1$ $NON-NLS-2$
+            ui_node.setAttributeValue(LayoutConstants.ATTR_ID, "@+id/" + widget_id, //$NON-NLS-1$
+                    false /* override */);
         }
+
+        ui_node.setAttributeValue(LayoutConstants.ATTR_TEXT, widget_id, false /*override*/);
         
-        UiElementNode ui_parent = ui_node.getUiParent();
-        if (ui_parent != null && ui_parent.getDescriptor().getXmlLocalName().equals("RelativeLayout")) { //$NON-NLS-1$
-            UiElementNode ui_previous = ui_node.getUiPreviousSibling();
-            if (ui_previous != null) {
-                String id = ui_previous.getAttributeValue("id"); //$NON-NLS-1$
-                if (id != null && id.length() > 0) {
-                    id = id.replace("@+", "@");
-                    ui_node.setAttributeValue("layout_below", id, false /* override */);
+        if (updateLayout) {
+            UiElementNode ui_parent = ui_node.getUiParent();
+            if (ui_parent != null &&
+                    ui_parent.getDescriptor().getXmlLocalName().equals(
+                            LayoutConstants.RELATIVE_LAYOUT)) {
+                UiElementNode ui_previous = ui_node.getUiPreviousSibling();
+                if (ui_previous != null) {
+                    String id = ui_previous.getAttributeValue(LayoutConstants.ATTR_ID);
+                    if (id != null && id.length() > 0) {
+                        id = id.replace("@+", "@");                     //$NON-NLS-1$ //$NON-NLS-2$
+                        ui_node.setAttributeValue(LayoutConstants.ATTR_LAYOUT_BELOW, id,
+                                false /* override */);
+                    }
                 }
             }
         }
-        
+    }
+
+    /**
+     * Given a UI root node, returns the first available id that matches the
+     * pattern "prefix%02d".
+     *  
+     * @param uiNode The UI node that gives the prefix to match.
+     * @return A suitable generated id
+     */
+    public static String getFreeWidgetId(UiElementNode uiNode) {
+        return getFreeWidgetId(uiNode.getUiRoot(),
+                new Object[] { uiNode.getDescriptor().getXmlLocalName(), null, null, null });
     }
 
     /**
@@ -698,19 +731,34 @@
      * 
      * For recursion purposes, a "context" is given. Since Java doesn't have in-out parameters
      * in methods and we're not going to do a dedicated type, we just use an object array which
-     * must contain the following items:
-     * - prefix(String): The prefix of the generated id, i.e. "widget"
-     * - index(Integer): The minimum index of the generated id
-     * - generated(String) The generated widget currently being searched. Must start with null.
+     * must contain one initial item and several are built on the fly just for internal storage:
+     * <ul>
+     * <li> prefix(String): The prefix of the generated id, i.e. "widget". Cannot be null.
+     * <li> index(Integer): The minimum index of the generated id. Must start with null.
+     * <li> generated(String): The generated widget currently being searched. Must start with null.
+     * <li> map(Set<String>): A set of the ids collected so far when walking through the widget
+     *                        hierarchy. Must start with null.
+     * </ul>
      *  
-     * @param uiRoot The Ui root node where to start searching recusrively.
-     * @param params An in-out context of parameters used during recursion, as explaine above.
+     * @param uiRoot The Ui root node where to start searching recursively. For the initial call
+     *               you want to pass the document root.
+     * @param params An in-out context of parameters used during recursion, as explained above.
      * @return A suitable generated id
      */
-    private static String getFreeWidgetId(UiElementNode uiRoot, Object[] params) {
+    @SuppressWarnings("unchecked")
+    private static String getFreeWidgetId(UiElementNode uiRoot,
+            Object[] params) {
+
+        Set<String> map = (Set<String>)params[3];
+        if (map == null) {
+            params[3] = map = new HashSet<String>();
+        }
+
+        int num = params[1] == null ? 0 : ((Integer)params[1]).intValue();
+
         String generated = (String) params[2];
+        String prefix = (String) params[0];
         if (generated == null) {
-            String prefix = (String) params[0];
             int pos = prefix.indexOf('.');
             if (pos >= 0) {
                 prefix = prefix.substring(pos + 1);
@@ -719,32 +767,42 @@
             if (pos >= 0) {
                 prefix = prefix.substring(pos + 1);
             }
-            prefix = prefix.replaceAll("[^a-zA-Z]", ""); //$NON-NLS-1$ $NON-NLS-2$
+            prefix = prefix.replaceAll("[^a-zA-Z]", "");                //$NON-NLS-1$ $NON-NLS-2$
             if (prefix.length() == 0) {
-                prefix = "widget";
+                prefix = DEFAULT_WIDGET_PREFIX;
             }
-            generated = String.format("%1$s%2$02d", prefix, ((Integer)params[1]).intValue());
+
+            do {
+                num++;
+                generated = String.format("%1$s%2$02d", prefix, num);   //$NON-NLS-1$
+            } while (map.contains(generated));
+
             params[0] = prefix;
+            params[1] = num;
             params[2] = generated;
         }
 
-        String id = uiRoot.getAttributeValue("id"); //$NON-NLS-1$
+        String id = uiRoot.getAttributeValue(LayoutConstants.ATTR_ID);
         if (id != null) {
-            id = id.replace("@+id/", ""); //$NON-NLS-1$ $NON-NLS-2$
-            id = id.replace("@id/", ""); //$NON-NLS-1$ $NON-NLS-2$
-            if (id.equals(generated)) {
-                // switch to next value
-                int num = ((Integer)params[1]).intValue() + 1;
-                generated = String.format("%1$s%2$02d", params[0], num);
+            id = id.replace("@+id/", "");                               //$NON-NLS-1$ $NON-NLS-2$
+            id = id.replace("@id/", "");                                //$NON-NLS-1$ $NON-NLS-2$
+            if (map.add(id) && map.contains(generated)) {
+
+                do {
+                    num++;
+                    generated = String.format("%1$s%2$02d", prefix, num);   //$NON-NLS-1$
+                } while (map.contains(generated));
+
                 params[1] = num;
                 params[2] = generated;
             }
         }
-            
+
         for (UiElementNode uiChild : uiRoot.getUiChildren()) {
             getFreeWidgetId(uiChild, params);
         }
         
+        // Note: return params[2] (not "generated") since it could have changed during recursion.
         return (String) params[2];
     }
     
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/DocumentDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
index 12ebc38..7d7b1c9 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ElementDescriptor.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.descriptors;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.IconFactory;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
 
@@ -173,7 +173,7 @@
         int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN;
         int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE;
         Image icon = factory.getIcon(mXmlName, color, shape);
-        return icon != null ? icon : EditorsPlugin.getAndroidLogo();
+        return icon != null ? icon : AdtPlugin.getAndroidLogo();
     }
 
     /** 
@@ -190,7 +190,7 @@
         int color = hasChildren() ? IconFactory.COLOR_BLUE : IconFactory.COLOR_GREEN;
         int shape = hasChildren() ? IconFactory.SHAPE_RECT : IconFactory.SHAPE_CIRCLE;
         ImageDescriptor id = factory.getImageDescriptor(mXmlName, color, shape);
-        return id != null ? id : EditorsPlugin.getAndroidLogoDesc();
+        return id != null ? id : AdtPlugin.getAndroidLogoDesc();
     }
 
     /* Returns the list of allowed attributes. */
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/EnumAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/FlagAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java
new file mode 100644
index 0000000..4c115e9
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/IDescriptorProvider.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 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.editors.descriptors;
+
+public interface IDescriptorProvider {
+
+    ElementDescriptor[] getRootElementDescriptors();
+    
+    ElementDescriptor getDescriptor();
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ListAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/ReferenceAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/SeparatorAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/TextValueDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/descriptors/XmlnsAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java
new file mode 100644
index 0000000..c512625
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/BasePullParser.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+import com.android.layoutlib.api.IXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * Base implementation of an {@link IXmlPullParser} for cases where the parser is not sitting
+ * on top of an actual XML file.
+ * <p/>It's designed to work on layout files, and will most likely not work on other resource
+ * files.
+ */
+public abstract class BasePullParser implements IXmlPullParser {
+    
+    protected int mParsingState = START_DOCUMENT;
+    
+    public BasePullParser() {
+    }
+    
+    // --- new methods to override ---
+    
+    public abstract void onNextFromStartDocument();
+    public abstract void onNextFromStartTag();
+    public abstract void onNextFromEndTag();
+    
+    // --- basic implementation of IXmlPullParser ---
+    
+    public void setFeature(String name, boolean state) throws XmlPullParserException {
+        if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
+            return;
+        }
+        if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
+            return;
+        }
+        throw new XmlPullParserException("Unsupported feature: " + name);
+    }
+
+    public boolean getFeature(String name) {
+        if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
+            return true;
+        }
+        if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
+            return true;
+        }
+        return false;
+    }
+
+    public void setProperty(String name, Object value) throws XmlPullParserException {
+        throw new XmlPullParserException("setProperty() not supported");
+    }
+
+    public Object getProperty(String name) {
+        return null;
+    }
+
+    public void setInput(Reader in) throws XmlPullParserException {
+        throw new XmlPullParserException("setInput() not supported");
+    }
+
+    public void setInput(InputStream inputStream, String inputEncoding)
+            throws XmlPullParserException {
+        throw new XmlPullParserException("setInput() not supported");
+    }
+
+    public void defineEntityReplacementText(String entityName, String replacementText)
+            throws XmlPullParserException {
+        throw new XmlPullParserException("defineEntityReplacementText() not supported");
+    }
+
+    public String getNamespacePrefix(int pos) throws XmlPullParserException {
+        throw new XmlPullParserException("getNamespacePrefix() not supported");
+    }
+
+    public String getInputEncoding() {
+        return null;
+    }
+
+    public String getNamespace(String prefix) {
+        throw new RuntimeException("getNamespace() not supported");
+    }
+
+    public int getNamespaceCount(int depth) throws XmlPullParserException {
+        throw new XmlPullParserException("getNamespaceCount() not supported");
+    }
+
+    public String getNamespaceUri(int pos) throws XmlPullParserException {
+        throw new XmlPullParserException("getNamespaceUri() not supported");
+    }
+
+    public int getColumnNumber() {
+        return -1;
+    }
+
+    public int getLineNumber() {
+        return -1;
+    }
+
+    public String getAttributeType(int arg0) {
+        return "CDATA";
+    }
+
+    public int getEventType() {
+        return mParsingState;
+    }
+
+    public String getText() {
+        return null;
+    }
+
+    public char[] getTextCharacters(int[] arg0) {
+        return null;
+    }
+
+    public boolean isAttributeDefault(int arg0) {
+        return false;
+    }
+
+    public boolean isWhitespace() {
+        return false;
+    }
+    
+    public int next() throws XmlPullParserException {
+        switch (mParsingState) {
+            case END_DOCUMENT:
+                throw new XmlPullParserException("Nothing after the end");
+            case START_DOCUMENT:
+                onNextFromStartDocument();
+                break;
+            case START_TAG:
+                onNextFromStartTag();
+                break;
+            case END_TAG:
+                onNextFromEndTag();
+                break;
+            case TEXT:
+                // not used
+                break;
+            case CDSECT:
+                // not used
+                break;
+            case ENTITY_REF:
+                // not used
+                break;
+            case IGNORABLE_WHITESPACE:
+                // not used
+                break;
+            case PROCESSING_INSTRUCTION:
+                // not used
+                break;
+            case COMMENT:
+                // not used
+                break;
+            case DOCDECL:
+                // not used
+                break;
+        }
+        
+        return mParsingState;
+    }
+
+    public int nextTag() throws XmlPullParserException, IOException {
+        int eventType = next();
+        if (eventType != START_TAG && eventType != END_TAG) {
+            throw new XmlPullParserException("expected start or end tag", this, null);
+        }
+        return eventType;
+    }
+
+    public String nextText() throws XmlPullParserException, IOException {
+        if (getEventType() != START_TAG) {
+            throw new XmlPullParserException("parser must be on START_TAG to read next text", this,
+                    null);
+        }
+        int eventType = next();
+        if (eventType == TEXT) {
+            String result = getText();
+            eventType = next();
+            if (eventType != END_TAG) {
+                throw new XmlPullParserException(
+                        "event TEXT it must be immediately followed by END_TAG", this, null);
+            }
+            return result;
+        } else if (eventType == END_TAG) {
+            return "";
+        } else {
+            throw new XmlPullParserException("parser must be on START_TAG or TEXT to read text",
+                    this, null);
+        }
+    }
+
+    public int nextToken() throws XmlPullParserException, IOException {
+        return next();
+    }
+
+    public void require(int type, String namespace, String name) throws XmlPullParserException {
+        if (type != getEventType() || (namespace != null && !namespace.equals(getNamespace()))
+                || (name != null && !name.equals(getName())))
+            throw new XmlPullParserException("expected " + TYPES[type] + getPositionDescription());
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
similarity index 75%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
index 278b921..77467cd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
@@ -16,12 +16,18 @@
 
 package com.android.ide.eclipse.editors.layout;
 
-import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.sdk.Sdk;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData.LayoutBridge;
 import com.android.ide.eclipse.common.resources.ResourceType;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.IconFactory;
-import com.android.ide.eclipse.editors.EditorsPlugin.LayoutBridge;
+import com.android.ide.eclipse.editors.layout.LayoutEditor.UiEditorActions;
 import com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListener;
+import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
+import com.android.ide.eclipse.editors.layout.parts.ElementCreateCommand;
+import com.android.ide.eclipse.editors.layout.parts.UiElementEditPart;
 import com.android.ide.eclipse.editors.layout.parts.UiElementsEditPartFactory;
 import com.android.ide.eclipse.editors.resources.configurations.CountryCodeQualifier;
 import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration;
@@ -44,6 +50,8 @@
 import com.android.ide.eclipse.editors.resources.manager.ResourceFile;
 import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
 import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.ui.tree.CopyCutAction;
+import com.android.ide.eclipse.editors.ui.tree.PasteAction;
 import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
 import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.DensityVerifier;
@@ -55,6 +63,7 @@
 import com.android.layoutlib.api.IResourceValue;
 import com.android.layoutlib.api.IStyleResourceValue;
 import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
@@ -67,14 +76,22 @@
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.draw2d.geometry.Rectangle;
 import org.eclipse.gef.DefaultEditDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
 import org.eclipse.gef.GraphicalViewer;
 import org.eclipse.gef.SelectionManager;
 import org.eclipse.gef.dnd.TemplateTransferDragSourceListener;
 import org.eclipse.gef.dnd.TemplateTransferDropTargetListener;
 import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
 import org.eclipse.gef.palette.PaletteRoot;
-import org.eclipse.gef.ui.parts.GraphicalEditor;
+import org.eclipse.gef.requests.CreationFactory;
+import org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
 import org.eclipse.gef.ui.parts.SelectionSynchronizer;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
 import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.swt.SWT;
@@ -85,6 +102,8 @@
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
@@ -98,6 +117,9 @@
 import org.eclipse.ui.ide.IDE;
 import org.eclipse.ui.part.FileEditorInput;
 
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.awt.image.Raster;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -105,6 +127,7 @@
 import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -112,20 +135,25 @@
 
 /**
  * Graphical layout editor, based on GEF.
+ * <p/>
+ * To understand GEF: http://www.ibm.com/developerworks/opensource/library/os-gef/
+ * <p/>
+ * To understand Drag'n'drop: http://www.eclipse.org/articles/Article-Workbench-DND/drag_drop.html
  */
-public class GraphicalLayoutEditor extends GraphicalEditor/*WithPalette*/
+public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
         implements ILayoutReloadListener {
     
     private final static String THEME_SEPARATOR = "----------"; //$NON-NLS-1$
 
     /** Reference to the layout editor */
     private final LayoutEditor mLayoutEditor;
-    
+
     /** reference to the file being edited. */
     private IFile mEditedFile;
 
     private Clipboard mClipboard;
     private Composite mParent;
+    private PaletteRoot mPaletteRoot;
 
     private Text mCountry;
     private Text mNetwork;
@@ -141,7 +169,7 @@
     private Text mSize2;
     private Combo mThemeCombo;
     private Button mCreateButton;
-    
+
     private Label mCountryIcon;
     private Label mNetworkIcon;
     private Label mLanguageIcon;
@@ -153,18 +181,18 @@
     private Label mTextInputIcon;
     private Label mNavigationIcon;
     private Label mSizeIcon;
-    
+
     private Label mCurrentLayoutLabel;
 
     private Image mWarningImage;
     private Image mMatchImage;
     private Image mErrorImage;
-    
+
     /** The {@link FolderConfiguration} representing the state of the UI controls */
     private FolderConfiguration mCurrentConfig = new FolderConfiguration();
     /** The {@link FolderConfiguration} being edited. */
     private FolderConfiguration mEditedConfig;
-    
+
     private Map<String, Map<String, IResourceValue>> mConfiguredFrameworkRes;
     private Map<String, Map<String, IResourceValue>> mConfiguredProjectRes;
     private ProjectCallback mProjectCallback;
@@ -173,6 +201,7 @@
     private boolean mNeedsRecompute = false;
     private int mPlatformThemeCount = 0;
     private boolean mDisableUpdates = false;
+    private boolean mActive = false;
 
     private Runnable mFrameworkResourceChangeListener = new Runnable() {
         public void run() {
@@ -180,6 +209,7 @@
             mConfiguredFrameworkRes = null;
             
             updateUIFromResources();
+
             mThemeCombo.getParent().layout();
 
             // updateUiFromFramework will reset language/region combo, so we must call
@@ -191,21 +221,21 @@
             // make sure we remove the custom view loader, since its parent class loader is the
             // bridge class loader.
             mProjectCallback = null;
-            
+
             recomputeLayout();
         }
     };
-    
+
     private final Runnable mConditionalRecomputeRunnable = new Runnable() {
         public void run() {
-            if (mLayoutEditor.isGraphicalEditorActive()) {
+            if (mActive) {
                 recomputeLayout();
             } else {
                 mNeedsRecompute = true;
             }
         }
     };
-    
+
     private final Runnable mUiUpdateFromResourcesRunnable = new Runnable() {
         public void run() {
             updateUIFromResources();
@@ -217,19 +247,19 @@
         mLayoutEditor = layoutEditor;
         setEditDomain(new DefaultEditDomain(this));
         setPartName("Layout");
-        
+
         IconFactory factory = IconFactory.getInstance();
         mWarningImage = factory.getIcon("warning"); //$NON-NLS-1$
         mMatchImage = factory.getIcon("match"); //$NON-NLS-1$
         mErrorImage = factory.getIcon("error"); //$NON-NLS-1$
-        
-        EditorsPlugin.getDefault().addResourceChangedListener(mFrameworkResourceChangeListener);
+
+        AdtPlugin.getDefault().addResourceChangedListener(mFrameworkResourceChangeListener);
     }
-    
+
     // ------------------------------------
     // Methods overridden from base classes
     //------------------------------------
-    
+
     @Override
     public void createPartControl(Composite parent) {
         mParent = parent;
@@ -237,13 +267,13 @@
         GridData gd;
 
         mClipboard = new Clipboard(parent.getDisplay());
-        
+
         parent.setLayout(gl = new GridLayout(1, false));
         gl.marginHeight = gl.marginWidth = 0;
-        
+
         // create the top part for the configuration control
         int cols = 10;
-        
+
         Composite topParent = new Composite(parent, SWT.NONE);
         topParent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
         topParent.setLayout(gl = new GridLayout(cols, false));
@@ -339,9 +369,9 @@
            @Override
             public void widgetSelected(SelectionEvent e) {
                onOrientationChange();
-            } 
+            }
         });
-        
+
         new Label(topParent, SWT.NONE).setText("Density");
         mDensityIcon = createControlComposite(topParent, true /* grab_horizontal */);
         mDensity = new Text(mDensityIcon.getParent(), SWT.BORDER);
@@ -437,7 +467,7 @@
         gl.marginWidth = gl.marginHeight = 0;
         labelParent.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
         gd.horizontalSpan = cols;
-        
+
         new Label(labelParent, SWT.NONE).setText("Editing config:");
         mCurrentLayoutLabel = new Label(labelParent, SWT.NONE);
         mCurrentLayoutLabel.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
@@ -449,7 +479,7 @@
         sizeParent.setLayout(gl = new GridLayout(3, false));
         gl.marginWidth = gl.marginHeight = 0;
         gl.horizontalSpacing = 0;
-        
+
         mSize1 = new Text(sizeParent, SWT.BORDER);
         mSize1.setLayoutData(gd = new GridData());
         gd.widthHint = 30;
@@ -457,11 +487,11 @@
         mSize2 = new Text(sizeParent, SWT.BORDER);
         mSize2.setLayoutData(gd = new GridData());
         gd.widthHint = 30;
-        
+
         DimensionVerifier verifier = new DimensionVerifier();
         mSize1.addVerifyListener(verifier);
         mSize2.addVerifyListener(verifier);
-        
+
         SelectionListener sl = new SelectionListener() {
             public void widgetDefaultSelected(SelectionEvent e) {
                 onSizeChange();
@@ -470,7 +500,7 @@
                 onSizeChange();
             }
         };
-        
+
         mSize1.addSelectionListener(sl);
         mSize2.addSelectionListener(sl);
         
@@ -488,7 +518,7 @@
         separator.setLayoutData(gd = new GridData(
                 GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL));
         gd.heightHint = 0;
-        
+
         mThemeCombo = new Combo(labelParent, SWT.READ_ONLY | SWT.DROP_DOWN);
         mThemeCombo.setEnabled(false);
         updateUIFromResources();
@@ -521,7 +551,7 @@
                 }
             }
         });
-        
+
         // create a new composite that will contain the standard editor controls.
         Composite editorParent = new Composite(parent, SWT.NONE);
         editorParent.setLayoutData(new GridData(GridData.FILL_BOTH));
@@ -532,28 +562,31 @@
     @Override
     public void dispose() {
         if (mFrameworkResourceChangeListener != null) {
-            EditorsPlugin.getDefault().removeResourceChangedListener(
+            AdtPlugin.getDefault().removeResourceChangedListener(
                     mFrameworkResourceChangeListener);
             mFrameworkResourceChangeListener = null;
         }
-        
+
         LayoutReloadMonitor.getMonitor().removeListener(mEditedFile.getProject(), this);
 
         if (mClipboard != null) {
             mClipboard.dispose();
             mClipboard = null;
         }
-        
+
         super.dispose();
     }
-    
+
     /* (non-Javadoc)
      * Creates the palette root.
      */
+    @Override
     protected PaletteRoot getPaletteRoot() {
-        return PaletteFactory.createPaletteRoot();
+        mPaletteRoot = PaletteFactory.createPaletteRoot(mPaletteRoot,
+                mLayoutEditor.getTargetData()); 
+        return mPaletteRoot;
     }
-    
+
     public Clipboard getClipboard() {
         return mClipboard;
     }
@@ -577,22 +610,60 @@
         firePropertyChange(PROP_DIRTY);
     }
     
+    @Override
+    protected void configurePaletteViewer() {
+        super.configurePaletteViewer();
+
+        // Create a drag source listener on an edit part that is a viewer.
+        // What this does is use DND with a TemplateTransfer type which is actually
+        // the PaletteTemplateEntry held in the PaletteRoot.
+        TemplateTransferDragSourceListener dragSource =
+            new TemplateTransferDragSourceListener(getPaletteViewer());
+        
+        // Create a drag source on the palette viewer.
+        // See the drag target associated with the GraphicalViewer in configureGraphicalViewer.
+        getPaletteViewer().addDragSourceListener(dragSource);
+    }
+
     /* (non-javadoc)
      * Configure the graphical viewer before it receives its contents.
      */
     @Override
     protected void configureGraphicalViewer() {
         super.configureGraphicalViewer();
-        
+
         GraphicalViewer viewer = getGraphicalViewer();
         viewer.setEditPartFactory(new UiElementsEditPartFactory(mParent.getDisplay()));
         viewer.setRootEditPart(new ScalableFreeformRootEditPart());
 
-        // TODO: viewer.setKeyHandler()
-        // TODO: custom ContextMenuProvider => viewer.setContextMenu & registerContextMenu
+        // Disable the following -- we don't drag *from* the GraphicalViewer yet: 
+        // viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
+        
+        viewer.addDropTargetListener(new DropListener(viewer));
+    }
+    
+    class DropListener extends TemplateTransferDropTargetListener {
+        public DropListener(EditPartViewer viewer) {
+            super(viewer);
+        }
 
-        viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
-        viewer.addDropTargetListener(new TemplateTransferDropTargetListener(viewer));
+        // TODO explain
+        @Override
+        protected CreationFactory getFactory(final Object template) {
+            return new CreationFactory() {
+                public Object getNewObject() {
+                    // We don't know the newly created EditPart since "creating" new
+                    // elements is done by ElementCreateCommand.execute() directly by
+                    // manipulating the XML elements..
+                    return null;
+                }
+
+                public Object getObjectType() {
+                    return template;
+                }
+                
+            };
+        }
     }
 
     /* (non-javadoc)
@@ -602,31 +673,184 @@
     protected void initializeGraphicalViewer() {
         GraphicalViewer viewer = getGraphicalViewer();
         viewer.setContents(getModel());
-        
+
         IEditorInput input = getEditorInput();
         if (input instanceof FileEditorInput) {
             FileEditorInput fileInput = (FileEditorInput)input;
             mEditedFile = fileInput.getFile();
-            
+
             updateUIFromResources();
 
             LayoutReloadMonitor.getMonitor().addListener(mEditedFile.getProject(), this);
         } else {
             // really this shouldn't happen! Log it in case it happens
             mEditedFile = null;
-            EditorsPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
+            AdtPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
                     input.toString());
         }
     }
     
+    /* (non-javadoc)
+     * Sets the graphicalViewer for this EditorPart.
+     * @param viewer the graphical viewer
+     */
+    @Override
+    protected void setGraphicalViewer(GraphicalViewer viewer) {
+        super.setGraphicalViewer(viewer);
+
+        // TODO: viewer.setKeyHandler()
+        viewer.setContextMenu(createContextMenu(viewer));
+    }
+
+    /**
+     * Used by LayoutEditor.UiEditorActions.selectUiNode to select a new UI Node
+     * created by  {@link ElementCreateCommand#execute()}.
+     * 
+     * @param uiNodeModel The {@link UiElementNode} to select.
+     */
+    public void selectModel(UiElementNode uiNodeModel) {
+        GraphicalViewer viewer = getGraphicalViewer();
+        
+        // Give focus to the graphical viewer (in case the outline has it)
+        viewer.getControl().forceFocus();
+        
+        Object editPart = viewer.getEditPartRegistry().get(uiNodeModel);
+        
+        if (editPart instanceof EditPart) {
+            viewer.select((EditPart)editPart);
+        }
+    }
+
+
     //--------------
     // Local methods
     //--------------
-    
+
     public LayoutEditor getLayoutEditor() {
         return mLayoutEditor;
     }
 
+    private MenuManager createContextMenu(GraphicalViewer viewer) {
+        MenuManager menuManager = new MenuManager();
+        menuManager.setRemoveAllWhenShown(true);
+        menuManager.addMenuListener(new ActionMenuListener(viewer));
+        
+        return menuManager;
+    }
+
+    private class ActionMenuListener implements IMenuListener {
+        private final GraphicalViewer mViewer;
+
+        public ActionMenuListener(GraphicalViewer viewer) {
+            mViewer = viewer;
+        }
+
+        /**
+         * The menu is about to be shown. The menu manager has already been
+         * requested to remove any existing menu item. This method gets the
+         * tree selection and if it is of the appropriate type it re-creates
+         * the necessary actions.
+         */
+       public void menuAboutToShow(IMenuManager manager) {
+           ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
+
+           // filter selected items and only keep those we can handle
+           for (Object obj : mViewer.getSelectedEditParts()) {
+               if (obj instanceof UiElementEditPart) {
+                   UiElementEditPart part = (UiElementEditPart) obj;
+                   UiElementNode uiNode = part.getUiNode();
+                   if (uiNode != null) {
+                       selected.add(uiNode);
+                   }
+               }
+           }
+           
+           if (selected.size() > 0) {
+               doCreateMenuAction(manager, mViewer, selected);
+           }
+        }
+    }
+    
+    private void doCreateMenuAction(IMenuManager manager,
+            final GraphicalViewer viewer,
+            final ArrayList<UiElementNode> selected) {
+        if (selected != null) {
+            boolean hasXml = false;
+            for (UiElementNode uiNode : selected) {
+                if (uiNode.getXmlNode() != null) {
+                    hasXml = true;
+                    break;
+                }
+            }
+
+            if (hasXml) {
+                manager.add(new CopyCutAction(mLayoutEditor, getClipboard(),
+                        null, selected, true /* cut */));
+                manager.add(new CopyCutAction(mLayoutEditor, getClipboard(),
+                        null, selected, false /* cut */));
+
+                // Can't paste with more than one element selected (the selection is the target)
+                if (selected.size() <= 1) {
+                    // Paste is not valid if it would add a second element on a terminal element
+                    // which parent is a document -- an XML document can only have one child. This
+                    // means paste is valid if the current UI node can have children or if the
+                    // parent is not a document.
+                    UiElementNode ui_root = selected.get(0).getUiRoot();
+                    if (ui_root.getDescriptor().hasChildren() ||
+                            !(ui_root.getUiParent() instanceof UiDocumentNode)) {
+                        manager.add(new PasteAction(mLayoutEditor, getClipboard(),
+                                                    selected.get(0)));
+                    }
+                }
+                manager.add(new Separator());
+            }
+        }
+
+        // Append "add" and "remove" actions. They do the same thing as the add/remove
+        // buttons on the side.
+        IconFactory factory = IconFactory.getInstance();
+        
+        final UiEditorActions uiActions = mLayoutEditor.getUiEditorActions();
+
+        // "Add" makes sense only if there's 0 or 1 item selected since the
+        // one selected item becomes the target.
+        if (selected == null || selected.size() <= 1) {
+            manager.add(new Action("Add...", factory.getImageDescriptor("add")) { //$NON-NLS-2$
+                @Override
+                public void run() {
+                    UiElementNode node = selected != null && selected.size() > 0 ? selected.get(0)
+                                                                                 : null;
+                    uiActions.doAdd(node, viewer.getControl().getShell());
+                }
+            });
+        }
+
+        if (selected != null) {
+            manager.add(new Action("Remove", factory.getImageDescriptor("delete")) { //$NON-NLS-2$
+                @Override
+                public void run() {
+                    uiActions.doRemove(selected, viewer.getControl().getShell());
+                }
+            });
+
+            manager.add(new Separator());
+            
+            manager.add(new Action("Up", factory.getImageDescriptor("up")) { //$NON-NLS-2$
+                @Override
+                public void run() {
+                    uiActions.doUp(selected);
+                }
+            });
+            manager.add(new Action("Down", factory.getImageDescriptor("down")) { //$NON-NLS-2$
+                @Override
+                public void run() {
+                    uiActions.doDown(selected);
+                }
+            });
+        }
+        
+    } 
+
     /**
      * Sets the UI for the edition of a new file.
      * @param configuration the configuration of the new file.
@@ -669,7 +893,7 @@
             s1 = s2;
             s2 = tmp;
         }
-            
+
         switch (orientation) {
             default:
             case PORTRAIT:
@@ -680,6 +904,105 @@
                 return new Rectangle(0, 0, s1, s1);
         }
     }
+    
+    /**
+     * Renders an Android View described by a {@link ViewElementDescriptor}.
+     * <p/>This uses the <code>wrap_content</code> mode for both <code>layout_width</code> and
+     * <code>layout_height</code>, and use the class name for the <code>text</code> attribute.
+     * @param descriptor the descriptor for the class to render.
+     * @return an ImageData containing the rendering or <code>null</code> if rendering failed.
+     */
+    public ImageData renderWidget(ViewElementDescriptor descriptor) {
+        if (mEditedFile == null) {
+            return null;
+        }
+        
+        IAndroidTarget target = Sdk.getCurrent().getTarget(mEditedFile.getProject());
+        if (target == null) {
+            return null;
+        }
+        
+        AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+        if (data == null) {
+            return null;
+        }
+        
+        LayoutBridge bridge = data.getLayoutBridge();
+
+        if (bridge.bridge != null) { // bridge can never be null.
+            ResourceManager resManager = ResourceManager.getInstance();
+
+            ProjectCallback projectCallback = null;
+            Map<String, Map<String, IResourceValue>> configuredProjectResources = null;
+            if (mEditedFile != null) {
+                ProjectResources projectRes = resManager.getProjectResources(
+                        mEditedFile.getProject());
+                projectCallback = new ProjectCallback(bridge.classLoader,
+                        projectRes, mEditedFile.getProject());
+
+                // get the configured resources for the project
+                // get the resources of the file's project.
+                if (mConfiguredProjectRes == null && projectRes != null) {
+                    // make sure they are loaded
+                    projectRes.loadAll();
+
+                    // get the project resource values based on the current config
+                    mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
+                }
+                
+                configuredProjectResources = mConfiguredProjectRes;
+            } else {
+                // we absolutely need a Map of configured project resources.
+                configuredProjectResources = new HashMap<String, Map<String, IResourceValue>>();
+            }
+
+            // get the framework resources
+            Map<String, Map<String, IResourceValue>> frameworkResources =
+                    getConfiguredFrameworkResources();
+
+            if (configuredProjectResources != null && frameworkResources != null) {
+                // get the selected theme
+                int themeIndex = mThemeCombo.getSelectionIndex();
+                if (themeIndex != -1) {
+                    String theme = mThemeCombo.getItem(themeIndex);
+                    
+                    // change the string if it's a custom theme to make sure we can
+                    // differentiate them
+                    if (themeIndex >= mPlatformThemeCount) {
+                        theme = "*" + theme; //$NON-NLS-1$
+                    }
+
+                    // Render a single object as described by the ViewElementDescriptor.
+                    WidgetPullParser parser = new WidgetPullParser(descriptor);
+                    ILayoutResult result = bridge.bridge.computeLayout(parser,
+                            null /* projectKey */,
+                            300 /* width */, 300 /* height */, theme,
+                            configuredProjectResources, frameworkResources, projectCallback,
+                            null /* logger */);
+
+                    // update the UiElementNode with the layout info.
+                    if (result.getSuccess() == ILayoutResult.SUCCESS) {
+                        BufferedImage largeImage = result.getImage();
+
+                        // we need to resize it to the actual widget size, and convert it into
+                        // an SWT image object.
+                        int width = result.getRootView().getRight();
+                        int height = result.getRootView().getBottom();
+                        Raster raster = largeImage.getData(new java.awt.Rectangle(width, height));
+                        int[] imageDataBuffer = ((DataBufferInt)raster.getDataBuffer()).getData();
+                        
+                        ImageData imageData = new ImageData(width, height, 32,
+                                new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF));
+
+                        imageData.setPixels(0, 0, imageDataBuffer.length, imageDataBuffer, 0);
+                        
+                        return imageData;
+                    }
+                }
+            }
+        }
+        return null;
+    }
 
     /**
      * Reloads this editor, by getting the new model from the {@link LayoutEditor}.
@@ -690,41 +1013,41 @@
 
         IEditorInput input = mLayoutEditor.getEditorInput();
         setInput(input);
-        
+
         if (input instanceof FileEditorInput) {
             FileEditorInput fileInput = (FileEditorInput)input;
             mEditedFile = fileInput.getFile();
         } else {
             // really this shouldn't happen! Log it in case it happens
             mEditedFile = null;
-            EditorsPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
+            AdtPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
                     input.toString());
         }
     }
-    
+
     /**
      * Update the layout editor when the Xml model is changed.
      */
     void onXmlModelChanged() {
         GraphicalViewer viewer = getGraphicalViewer();
-        
+
         // try to preserve the selection before changing the content
         SelectionManager selMan = viewer.getSelectionManager();
         ISelection selection = selMan.getSelection();
-        
+
         try {
             viewer.setContents(getModel());
         } finally {
             selMan.setSelection(selection);
-        }       
-        
+        }
+
         if (mLayoutEditor.isGraphicalEditorActive()) {
             recomputeLayout();
         } else {
             mNeedsRecompute = true;
         }
     }
-    
+
     /**
      * Update the UI controls state with a given {@link FolderConfiguration}.
      * <p/>If a qualifier is not present in the {@link FolderConfiguration} object, the UI control
@@ -745,7 +1068,7 @@
         } else if (mCountry.getText().length() > 0) {
             mCountryIcon.setImage(mWarningImage);
         }
-        
+
         mNetworkIcon.setImage(mMatchImage);
         NetworkCodeQualifier networkQualifier = config.getNetworkCodeQualifier();
         if (networkQualifier != null) {
@@ -754,7 +1077,7 @@
         } else if (mNetwork.getText().length() > 0) {
             mNetworkIcon.setImage(mWarningImage);
         }
-        
+
         mLanguageIcon.setImage(mMatchImage);
         LanguageQualifier languageQualifier = config.getLanguageQualifier();
         if (languageQualifier != null) {
@@ -763,7 +1086,7 @@
         } else if (mLanguage.getText().length() > 0) {
             mLanguageIcon.setImage(mWarningImage);
         }
-        
+
         mRegionIcon.setImage(mMatchImage);
         RegionQualifier regionQualifier = config.getRegionQualifier();
         if (regionQualifier != null) {
@@ -772,7 +1095,7 @@
         } else if (mRegion.getText().length() > 0) {
             mRegionIcon.setImage(mWarningImage);
         }
-        
+
         mOrientationIcon.setImage(mMatchImage);
         ScreenOrientationQualifier orientationQualifier = config.getScreenOrientationQualifier();
         if (orientationQualifier != null) {
@@ -782,7 +1105,7 @@
         } else if (mOrientation.getSelectionIndex() != 0) {
             mOrientationIcon.setImage(mWarningImage);
         }
-        
+
         mDensityIcon.setImage(mMatchImage);
         PixelDensityQualifier densityQualifier = config.getPixelDensityQualifier();
         if (densityQualifier != null) {
@@ -791,7 +1114,7 @@
         } else if (mDensity.getText().length() > 0) {
             mDensityIcon.setImage(mWarningImage);
         }
-        
+
         mTouchIcon.setImage(mMatchImage);
         TouchScreenQualifier touchQualifier = config.getTouchTypeQualifier();
         if (touchQualifier != null) {
@@ -800,7 +1123,7 @@
         } else if (mTouch.getSelectionIndex() != 0) {
             mTouchIcon.setImage(mWarningImage);
         }
-        
+
         mKeyboardIcon.setImage(mMatchImage);
         KeyboardStateQualifier keyboardQualifier = config.getKeyboardStateQualifier();
         if (keyboardQualifier != null) {
@@ -818,7 +1141,7 @@
         } else if (mTextInput.getSelectionIndex() != 0) {
             mTextInputIcon.setImage(mWarningImage);
         }
-        
+
         mNavigationIcon.setImage(mMatchImage);
         NavigationMethodQualifier navigationQualifiter = config.getNavigationMethodQualifier();
         if (navigationQualifiter != null) {
@@ -828,7 +1151,7 @@
         } else if (mNavigation.getSelectionIndex() != 0) {
             mNavigationIcon.setImage(mWarningImage);
         }
-        
+
         mSizeIcon.setImage(mMatchImage);
         ScreenDimensionQualifier sizeQualifier = config.getScreenDimensionQualifier();
         if (sizeQualifier != null) {
@@ -838,7 +1161,7 @@
         } else if (mSize1.getText().length() > 0 && mSize2.getText().length() > 0) {
             mSizeIcon.setImage(mWarningImage);
         }
-        
+
         // update the string showing the folder name
         String current = config.toDisplayString();
         mCurrentLayoutLabel.setText(current != null ? current : "(Default)");
@@ -927,6 +1250,10 @@
         return mLayoutEditor.getUiRootNode();
     }
     
+    void reloadPalette() {
+        PaletteFactory.createPaletteRoot(mPaletteRoot, mLayoutEditor.getTargetData());
+    }
+
     private void onCountryCodeChange() {
         // because mCountry triggers onCountryCodeChange at each modification, calling setText()
         // will trigger notifications, and we don't want that.
@@ -936,7 +1263,7 @@
 
         // update the current config
         String value = mCountry.getText();
-        
+
         // empty string, means no qualifier.
         if (value.length() == 0) {
             mCurrentConfig.setCountryCodeQualifier(null);
@@ -959,7 +1286,7 @@
                 mCountryIcon.setImage(mErrorImage);
             }
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
@@ -973,7 +1300,7 @@
 
         // update the current config
         String value = mNetwork.getText();
-        
+
         // empty string, means no qualifier.
         if (value.length() == 0) {
             mCurrentConfig.setNetworkCodeQualifier(null);
@@ -996,7 +1323,7 @@
                 mNetworkIcon.setImage(mErrorImage);
             }
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
@@ -1013,9 +1340,9 @@
 
         // update the current config
         String value = mLanguage.getText();
-        
+
         updateRegionUi(null /* projectResources */, null /* frameworkResources */);
-        
+
         // empty string, means no qualifier.
         if (value.length() == 0) {
             mCurrentConfig.setLanguageQualifier(null);
@@ -1034,11 +1361,11 @@
                 mLanguageIcon.setImage(mErrorImage);
             }
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
-    
+
     private void onRegionChange() {
         // because mRegion triggers onRegionChange at each modification, the filling
         // of the combo with data will trigger notifications, and we don't want that.
@@ -1048,7 +1375,7 @@
 
         // update the current config
         String value = mRegion.getText();
-        
+
         // empty string, means no qualifier.
         if (value.length() == 0) {
             mCurrentConfig.setRegionQualifier(null);
@@ -1067,11 +1394,11 @@
                 mRegionIcon.setImage(mErrorImage);
             }
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
-    
+
     private void onOrientationChange() {
         // update the current config
         int index = mOrientation.getSelectionIndex();
@@ -1081,11 +1408,11 @@
         } else {
             mCurrentConfig.setScreenOrientationQualifier(null);
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
-    
+
     private void onDensityChange() {
         // because mDensity triggers onDensityChange at each modification, calling setText()
         // will trigger notifications, and we don't want that.
@@ -1095,7 +1422,7 @@
 
         // update the current config
         String value = mDensity.getText();
-        
+
         // empty string, means no qualifier.
         if (value.length() == 0) {
             mCurrentConfig.setPixelDensityQualifier(null);
@@ -1122,7 +1449,7 @@
         // look for a file to open/create
         onConfigurationChange();
     }
-    
+
     private void onTouchChange() {
         // update the current config
         int index = mTouch.getSelectionIndex();
@@ -1132,7 +1459,7 @@
         } else {
             mCurrentConfig.setTouchTypeQualifier(null);
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
@@ -1146,11 +1473,11 @@
         } else {
             mCurrentConfig.setKeyboardStateQualifier(null);
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
-    
+
     private void onTextInputChange() {
         // update the current config
         int index = mTextInput.getSelectionIndex();
@@ -1160,11 +1487,11 @@
         } else {
             mCurrentConfig.setTextInputMethodQualifier(null);
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
-    
+
     private void onNavigationChange() {
         // update the current config
         int index = mNavigation.getSelectionIndex();
@@ -1174,11 +1501,11 @@
         } else {
             mCurrentConfig.setNavigationMethodQualifier(null);
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
-    
+
     private void onSizeChange() {
         // because mSize1 and mSize2 trigger onSizeChange at each modification, calling setText()
         // will trigger notifications, and we don't want that.
@@ -1189,7 +1516,7 @@
         // update the current config
         String size1 = mSize1.getText();
         String size2 = mSize2.getText();
-        
+
         // if only one of the strings is empty, do nothing
         if ((size1.length() == 0) ^ (size2.length() == 0)) {
             mSizeIcon.setImage(mErrorImage);
@@ -1209,12 +1536,12 @@
                 return;
             }
         }
-        
+
         // look for a file to open/create
         onConfigurationChange();
     }
 
-    
+
     /**
      * Looks for a file matching the new {@link FolderConfiguration} and attempts to open it.
      * <p/>If there is no match, notify the user.
@@ -1237,7 +1564,7 @@
                                               ResourceFolderType.LAYOUT,
                                               mCurrentConfig);
         }
-        
+
         if (match != null) {
             if (match.getFile().equals(mEditedFile) == false) {
                 try {
@@ -1279,7 +1606,7 @@
             showErrorInEditor(message);
         }
     }
-    
+
     private void onThemeChange() {
         int themeIndex = mThemeCombo.getSelectionIndex();
         if (themeIndex != -1) {
@@ -1314,10 +1641,10 @@
         // create the label
         Label icon = new Label(composite, SWT.NONE);
         icon.setImage(mMatchImage);
-        
+
         return icon;
     }
-    
+
     /**
      * Recomputes the layout with the help of layoutlib.
      */
@@ -1328,7 +1655,7 @@
             // return false;
             if (mEditedFile.exists() == false) {
                 String message = String.format("Resource '%1$s' does not exist.",
-                        mEditedFile.getFullPath().toString()); 
+                        mEditedFile.getFullPath().toString());
 
                 showErrorInEditor(message);
 
@@ -1339,126 +1666,156 @@
 
             if (mEditedFile.isSynchronized(IResource.DEPTH_ZERO) == false) {
                 String message = String.format("%1$s is out of sync. Please refresh.",
-                        mEditedFile.getName()); 
+                        mEditedFile.getName());
 
                 showErrorInEditor(message);
 
                 // also print it in the error console.
-                EditorsPlugin.printErrorToConsole(iProject.getName(), message);
+                AdtPlugin.printErrorToConsole(iProject.getName(), message);
                 return;
             }
 
-            // check there is actually a model (maybe the file is empty).
-            UiDocumentNode model = getModel();
-            
-            if (model.getUiChildren().size() == 0) {
-                showErrorInEditor("No Xml content. Go to the Outline view and add nodes.");
-                return;
-            }
-
-            EditorsPlugin plugin = EditorsPlugin.getDefault();
-            LayoutBridge bridge = plugin.getLayoutBridge();
-
-            if (bridge.bridge != null) { // bridge can never be null.
-                ResourceManager resManager = ResourceManager.getInstance();
-
-                ProjectResources projectRes = resManager.getProjectResources(iProject);
-                if (projectRes == null) {
+            Sdk currentSdk = Sdk.getCurrent();
+            if (currentSdk != null) {
+                IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject());
+                if (target == null) {
+                    showErrorInEditor("The project target is not set.");
+                    return;
+                }
+                
+                AndroidTargetData data = currentSdk.getTargetData(target);
+                if (data == null) {
+                    // It can happen that the workspace refreshes while the SDK is loading its
+                    // data, which could trigger a redraw of the opened layout if some resources
+                    // changed while Eclipse is closed.
+                    // In this case data could be null, but this is not an error.
+                    // We can just silently return, as all the opened editors are automatically
+                    // refreshed once the SDK finishes loading.
+                    if (AdtPlugin.getDefault().getSdkLoadStatus(null) != LoadStatus.LOADING) {
+                        showErrorInEditor(String.format(
+                                "The project target (%s) was not properly loaded.",
+                                target.getName()));
+                    }
                     return;
                 }
 
-                // get the resources of the file's project.
-                if (mConfiguredProjectRes == null) {
-                    // make sure they are loaded
-                    projectRes.loadAll();
+                // check there is actually a model (maybe the file is empty).
+                UiDocumentNode model = getModel();
 
-                    // get the project resource values based on the current config
-                    mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
+                if (model.getUiChildren().size() == 0) {
+                    showErrorInEditor("No Xml content. Go to the Outline view and add nodes.");
+                    return;
                 }
 
-                // get the framework resources
-                Map<String, Map<String, IResourceValue>> frameworkResources =
-                    getConfiguredFrameworkResources();
+                LayoutBridge bridge = data.getLayoutBridge();
 
-                if (mConfiguredProjectRes != null && frameworkResources != null) {
-                    if (mProjectCallback == null) {
-                        mProjectCallback = new ProjectCallback(
-                                plugin.getLayoutlibBridgeClassLoader(), projectRes, iProject);
+                if (bridge.bridge != null) { // bridge can never be null.
+                    ResourceManager resManager = ResourceManager.getInstance();
+    
+                    ProjectResources projectRes = resManager.getProjectResources(iProject);
+                    if (projectRes == null) {
+                        return;
                     }
-
-                    if (mLogger == null) {
-                        mLogger = new ILayoutLog() {
-                            public void error(String message) {
-                                EditorsPlugin.printErrorToConsole(mEditedFile.getName(), message);
-                            }
-
-                            public void error(Throwable error) {
-                                String message = error.getMessage();
-                                if (message == null) {
-                                    message = error.getClass().getName();
+    
+                    // get the resources of the file's project.
+                    if (mConfiguredProjectRes == null) {
+                        // make sure they are loaded
+                        projectRes.loadAll();
+    
+                        // get the project resource values based on the current config
+                        mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
+                    }
+    
+                    // get the framework resources
+                    Map<String, Map<String, IResourceValue>> frameworkResources =
+                        getConfiguredFrameworkResources();
+    
+                    if (mConfiguredProjectRes != null && frameworkResources != null) {
+                        if (mProjectCallback == null) {
+                            mProjectCallback = new ProjectCallback(
+                                    bridge.classLoader, projectRes, iProject);
+                        }
+    
+                        if (mLogger == null) {
+                            mLogger = new ILayoutLog() {
+                                public void error(String message) {
+                                    AdtPlugin.printErrorToConsole(mEditedFile.getName(), message);
                                 }
-
-                                PrintStream ps = new PrintStream(EditorsPlugin.getErrorStream());
-                                error.printStackTrace(ps);
-                            }
-
-                            public void warning(String message) {
-                                EditorsPlugin.printToConsole(mEditedFile.getName(), message);
-                            }
-                        };
-                    }
-
-                    // get the selected theme
-                    int themeIndex = mThemeCombo.getSelectionIndex();
-                    if (themeIndex != -1) {
-                        String theme = mThemeCombo.getItem(themeIndex);
-                        
-                        // change the string if it's a custom theme to make sure we can
-                        // differentiate them
-                        if (themeIndex >= mPlatformThemeCount) {
-                            theme = "*" + theme; //$NON-NLS-1$
+    
+                                public void error(Throwable error) {
+                                    String message = error.getMessage();
+                                    if (message == null) {
+                                        message = error.getClass().getName();
+                                    }
+    
+                                    PrintStream ps = new PrintStream(AdtPlugin.getErrorStream());
+                                    error.printStackTrace(ps);
+                                }
+    
+                                public void warning(String message) {
+                                    AdtPlugin.printToConsole(mEditedFile.getName(), message);
+                                }
+                            };
                         }
-
-                        // Compute the layout
-                        UiElementPullParser parser = new UiElementPullParser(getModel());
-                        Rectangle rect = getBounds();
-                        ILayoutResult result = bridge.bridge.computeLayout(parser, iProject,
-                                rect.width, rect.height, theme,
-                                mConfiguredProjectRes, frameworkResources, mProjectCallback,
-                                mLogger);
-
-                        // update the UiElementNode with the layout info.
-                        if (result.getSuccess() == ILayoutResult.SUCCESS) {
-                            model.setEditData(result.getImage());
-
-                            updateNodeWithBounds(result.getRootView());
-                        } else {
-                            String message = result.getErrorMessage();
-
-                            // Reset the edit data for all the nodes.
-                            resetNodeBounds(model);
-
-                            if (message != null) {
-                                // set the error in the top element.
-                                model.setEditData(message);
+    
+                        // get the selected theme
+                        int themeIndex = mThemeCombo.getSelectionIndex();
+                        if (themeIndex != -1) {
+                            String theme = mThemeCombo.getItem(themeIndex);
+                            
+                            // change the string if it's a custom theme to make sure we can
+                            // differentiate them
+                            if (themeIndex >= mPlatformThemeCount) {
+                                theme = "*" + theme; //$NON-NLS-1$
                             }
+    
+                            // Compute the layout
+                            UiElementPullParser parser = new UiElementPullParser(getModel());
+                            Rectangle rect = getBounds();
+                            ILayoutResult result = bridge.bridge.computeLayout(parser,
+                                    iProject /* projectKey */,
+                                    rect.width, rect.height, theme,
+                                    mConfiguredProjectRes, frameworkResources, mProjectCallback,
+                                    mLogger);
+    
+                            // update the UiElementNode with the layout info.
+                            if (result.getSuccess() == ILayoutResult.SUCCESS) {
+                                model.setEditData(result.getImage());
+    
+                                updateNodeWithBounds(result.getRootView());
+                            } else {
+                                String message = result.getErrorMessage();
+    
+                                // Reset the edit data for all the nodes.
+                                resetNodeBounds(model);
+    
+                                if (message != null) {
+                                    // set the error in the top element.
+                                    model.setEditData(message);
+                                }
+                            }
+    
+                            model.refreshUi();
                         }
-
-                        model.refreshUi();
                     }
+                } else {
+                    // SDK is loaded but not the layout library!
+                    String message = null;
+                    // check whether the bridge managed to load, or not
+                    if (bridge.status == LoadStatus.LOADING) {
+                        message = String.format(
+                                "Eclipse is loading framework information and the Layout library from the SDK folder.\n%1$s will refresh automatically once the process is finished.",
+                                mEditedFile.getName());
+                    } else {
+                        message = String.format("Eclipse failed to load the framework information and the Layout library!");
+                    }
+                    showErrorInEditor(message);
                 }
             } else {
-                String message = null;
+                String message = String.format(
+                        "Eclipse is loading the SDK.\n%1$s will refresh automatically once the process is finished.",
+                        mEditedFile.getName());
 
-                // check whether the bridge managed to load, or not
-                if (bridge.status == LayoutBridge.LoadStatus.LOADING) {
-                    message = String.format(
-                            "Eclipse is loading framework information and the Layout library from the SDK folder.\n%1$s will refresh automatically once the process is finished.",
-                            mEditedFile.getName()); 
-                } else {
-                    message = String.format("Eclipse failed to load the framework information and the Layout library!"); 
-                }
-                
                 showErrorInEditor(message);
             }
         } finally {
@@ -1482,10 +1839,10 @@
 
         model.refreshUi();
     }
-    
+
     private void resetNodeBounds(UiElementNode node) {
         node.setEditData(null);
-        
+
         List<UiElementNode> children = node.getUiChildren();
         for (UiElementNode child : children) {
             resetNodeBounds(child);
@@ -1499,10 +1856,10 @@
             if (viewKey instanceof UiElementNode) {
                 Rectangle bounds = new Rectangle(r.getLeft(), r.getTop(),
                         r.getRight()-r.getLeft(), r.getBottom() - r.getTop());
-                
+
                 ((UiElementNode)viewKey).setEditData(bounds);
             }
-            
+
             // and then its children.
             ILayoutViewInfo[] children = r.getChildren();
             if (children != null) {
@@ -1512,11 +1869,11 @@
             }
         }
     }
-    
+
     /*
      * (non-Javadoc)
      * @see com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListener#reloadLayout(boolean, boolean, boolean)
-     * 
+     *
      * Called when the file changes triggered a redraw of the layout
      */
     public void reloadLayout(boolean codeChange, boolean rChange, boolean resChange) {
@@ -1525,19 +1882,25 @@
         if (resChange) {
             recompute = true;
 
-            // TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache. 
+            // TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache.
 
             // force a reparse in case a value XML file changed.
             mConfiguredProjectRes = null;
-            
-            // clear the cache in the bridge in case a bitmap/9-patch changed.
-            EditorsPlugin plugin = EditorsPlugin.getDefault();
-            LayoutBridge bridge = plugin.getLayoutBridge();
 
-            if (bridge.bridge != null) {
-                bridge.bridge.clearCaches(mEditedFile.getProject());
+            // clear the cache in the bridge in case a bitmap/9-patch changed.
+            IAndroidTarget target = Sdk.getCurrent().getTarget(mEditedFile.getProject());
+            if (target != null) {
+                
+                AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+                if (data != null) {
+                    LayoutBridge bridge = data.getLayoutBridge();
+        
+                    if (bridge.bridge != null) {
+                        bridge.bridge.clearCaches(mEditedFile.getProject());
+                    }
+                }
             }
-            
+
             mParent.getDisplay().asyncExec(mUiUpdateFromResourcesRunnable);
         }
 
@@ -1548,7 +1911,7 @@
                 recompute = true;
             }
         }
-        
+
         if (recompute) {
             mParent.getDisplay().asyncExec(mConditionalRecomputeRunnable);
         }
@@ -1558,11 +1921,19 @@
      * Responds to a page change that made the Graphical editor page the activated page.
      */
     void activated() {
+    	mActive = true;
         if (mNeedsRecompute) {
             recomputeLayout();
         }
     }
-    
+
+    /**
+     * Responds to a page change that made the Graphical editor page the deactivated page
+     */
+    void deactivated() {
+    	mActive = false;
+    }
+
     /**
      * Updates the UI from values in the resources, such as languages, regions, themes, etc...
      * This must be called from the UI thread.
@@ -1570,8 +1941,8 @@
     private void updateUIFromResources() {
 
         ResourceManager manager = ResourceManager.getInstance();
-        
-        ProjectResources frameworkProject = manager.getFrameworkResources();
+
+        ProjectResources frameworkProject = getFrameworkResources();
 
         mDisableUpdates = true;
         
@@ -1615,7 +1986,6 @@
                 mPlatformThemeCount = themes.size();
                 themes.clear();
             }
-            
             // now get the languages from the framework.
             Set<String> frameworkLanguages = frameworkProject.getLanguages();
             if (frameworkLanguages != null) {
@@ -1627,7 +1997,7 @@
         ProjectResources project = null;
         if (mEditedFile != null) {
             project = manager.getProjectResources(mEditedFile.getProject());
-            
+
             // in cases where the opened file is not linked to a project, this could be null.
             if (project != null) {
                 // get the configured resources for the project 
@@ -1706,7 +2076,7 @@
      * This is done by making sure the parent is a theme.
      * @param value the style to check
      * @param styleMap the map of styles for the current project. Key is the style name.
-     * @return
+     * @return True if the given <var>style</var> is a theme.
      */
     private boolean isTheme(IResourceValue value, Map<String, IResourceValue> styleMap) {
         if (value instanceof IStyleResourceValue) {
@@ -1767,15 +2137,15 @@
             projectResources = ResourceManager.getInstance().getProjectResources(
                     mEditedFile.getProject());
         }
-        
+
         if (frameworkResources == null) {
-            frameworkResources = ResourceManager.getInstance().getFrameworkResources();
+            frameworkResources = getFrameworkResources();
         }
-        
+
         String currentLanguage = mLanguage.getText();
-        
+
         Set<String> set = null;
-        
+
         if (projectResources != null) {
             set = projectResources.getRegions(currentLanguage);
         }
@@ -1803,10 +2173,10 @@
     
     private Map<String, Map<String, IResourceValue>> getConfiguredFrameworkResources() {
         if (mConfiguredFrameworkRes == null) {
-            ProjectResources frameworkRes = ResourceManager.getInstance().getFrameworkResources();
+            ProjectResources frameworkRes = getFrameworkResources();
 
             if (frameworkRes == null) {
-                EditorsPlugin.log(IStatus.ERROR, "Failed to get ProjectResource for the framework");
+                AdtPlugin.log(IStatus.ERROR, "Failed to get ProjectResource for the framework");
             }
 
             // get the framework resource values based on the current config
@@ -1821,19 +2191,19 @@
      * The synchronizer can be used to sync the selection of 2 or more EditPartViewers.
      * <p/>
      * This is changed from protected to public so that the outline can use it.
-     * 
+     *
      * @return the synchronizer
      */
     @Override
     public SelectionSynchronizer getSelectionSynchronizer() {
         return super.getSelectionSynchronizer();
     }
-    
+
     /**
      * Returns the edit domain.
      * <p/>
      * This is changed from protected to public so that the outline can use it.
-     * 
+     *
      * @return the edit domain
      */
     @Override
@@ -1865,10 +2235,9 @@
                         String message = String.format("File 'res/%1$s' is in the way!",
                                 folderName);
                         
-                        EditorsPlugin.displayError("Layout Creation", message);
+                        AdtPlugin.displayError("Layout Creation", message);
                         
-                        return new Status(IStatus.ERROR,
-                                AndroidConstants.EDITORS_PLUGIN_ID, message);
+                        return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, message);
                     } else if (newLayoutFolder.exists() == false) {
                         // create it.
                         newLayoutFolder.mkdir();
@@ -1903,7 +2272,7 @@
                             mParent.getDisplay().asyncExec(new Runnable() {
                                 public void run() {
                                     onConfigurationChange();
-                                };  
+                                }
                             });
                         }
 
@@ -1941,16 +2310,16 @@
                             "Failed to create File 'res/%1$s/%2$s' : %3$s",
                             folderName, mEditedFile.getName(), e2.getMessage());
                     
-                    EditorsPlugin.displayError("Layout Creation", message);
+                    AdtPlugin.displayError("Layout Creation", message);
                     
-                    return new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+                    return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
                             message, e2);
                 } catch (CoreException e2) {
                     String message = String.format(
                             "Failed to create File 'res/%1$s/%2$s' : %3$s",
                             folderName, mEditedFile.getName(), e2.getMessage());
                     
-                    EditorsPlugin.displayError("Layout Creation", message);
+                    AdtPlugin.displayError("Layout Creation", message);
 
                     return e2.getStatus();
                 }
@@ -1960,4 +2329,27 @@
             }
         }.schedule();
     }
+    
+    /**
+     * Returns a {@link ProjectResources} for the framework resources.
+     * @return the framework resources or null if not found.
+     */
+    private ProjectResources getFrameworkResources() {
+        if (mEditedFile != null) {
+            Sdk currentSdk = Sdk.getCurrent();
+            if (currentSdk != null) {
+                IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject());
+    
+                if (target != null) {
+                    AndroidTargetData data = currentSdk.getTargetData(target);
+                    
+                    if (data != null) {
+                        return data.getFrameworkResources();
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java
new file mode 100644
index 0000000..d4ec5e1
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutConstants.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+/**
+ * A bunch of constants that map to either:
+ * <ul>
+ * <li>Android Layouts XML element names (Linear, Relative, Absolute, etc.)
+ * <li>Attributes for layout XML elements. 
+ * <li>Values for attributes.
+ * </ul>
+ */
+public class LayoutConstants {
+
+    public static final String RELATIVE_LAYOUT = "RelativeLayout";      //$NON-NLS-1$
+    public static final String LINEAR_LAYOUT   = "LinearLayout";        //$NON-NLS-1$
+    public static final String ABSOLUTE_LAYOUT = "AbsoluteLayout";      //$NON-NLS-1$
+
+    public static final String ATTR_TEXT = "text";                      //$NON-NLS-1$
+    public static final String ATTR_ID = "id";                          //$NON-NLS-1$
+
+    public static final String ATTR_LAYOUT_HEIGHT = "layout_height";    //$NON-NLS-1$
+    public static final String ATTR_LAYOUT_WIDTH = "layout_width";      //$NON-NLS-1$
+
+    public static final String ATTR_LAYOUT_ALIGN_PARENT_TOP = "layout_alignParentTop"; //$NON-NLS-1$
+    public static final String ATTR_LAYOUT_ALIGN_PARENT_BOTTOM = "layout_alignParentBottom"; //$NON-NLS-1$
+    public static final String ATTR_LAYOUT_ALIGN_PARENT_LEFT = "layout_alignParentLeft";//$NON-NLS-1$
+    public static final String ATTR_LAYOUT_ALIGN_PARENT_RIGHT = "layout_alignParentRight";   //$NON-NLS-1$
+    
+    public static final String ATTR_LAYOUT_ALIGN_BASELINE = "layout_alignBaseline"; //$NON-NLS-1$
+
+    public static final String ATTR_LAYOUT_CENTER_VERTICAL = "layout_centerVertical"; //$NON-NLS-1$
+    public static final String ATTR_LAYOUT_CENTER_HORIZONTAL = "layout_centerHorizontal"; //$NON-NLS-1$
+    
+    public static final String ATTR_LAYOUT_TO_RIGHT_OF = "layout_toRightOf";    //$NON-NLS-1$
+    public static final String ATTR_LAYOUT_TO_LEFT_OF = "layout_toLeftOf";      //$NON-NLS-1$
+    
+    public static final String ATTR_LAYOUT_BELOW = "layout_below";              //$NON-NLS-1$
+    public static final String ATTR_LAYOUT_ABOVE = "layout_above";              //$NON-NLS-1$
+    
+    public static final String ATTR_LAYOUT_Y = "layout_y";                      //$NON-NLS-1$
+    public static final String ATTR_LAYOUT_X = "layout_x";                      //$NON-NLS-1$
+
+    public static final String VALUE_WRAP_CONTENT = "wrap_content";             //$NON-NLS-1$
+    public static final String VALUE_FILL_PARENT = "fill_parent";               //$NON-NLS-1$
+    public static final String VALUE_TRUE = "true";                             //$NON-NLS-1$
+    public static final String VALUE_N_DIP = "%ddip";                           //$NON-NLS-1$
+
+    private LayoutConstants() {
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
similarity index 86%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
index dfec17a..9f39495 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutContentAssist.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.layout;
 
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
 
 /**
  * Content Assist Processor for /res/layout XML files
@@ -28,6 +28,6 @@
      * Constructor for LayoutContentAssist 
      */
     public LayoutContentAssist() {
-        super(LayoutDescriptors.getInstance().getDescriptor().getChildren());
+        super(AndroidTargetData.DESCRIPTOR_LAYOUT);
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutCreatorDialog.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
similarity index 79%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
index f1bedcb..880ee2b 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
@@ -16,14 +16,17 @@
 
 package com.android.ide.eclipse.editors.layout;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.EclipseUiHelper;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
 import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
 import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
+import com.android.ide.eclipse.editors.ui.tree.UiActions;
 import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -47,12 +50,10 @@
  */
 public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPartListener {
 
-    public static final String ID = "com.android.ide.eclipse.editors.layout.LayoutEditor"; //$NON-NLS-1$
+    public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".layout.LayoutEditor"; //$NON-NLS-1$
 
     /** Root node of the UI element hierarchy */
     private UiDocumentNode mUiRootNode;
-    /** Listener to update the root node if the resource framework changes */
-    private Runnable mResourceRefreshListener;
     
     private GraphicalLayoutEditor mGraphicalEditor;
     private int mGraphicalEditorIndex;
@@ -61,13 +62,13 @@
     /** Custom implementation of {@link IPropertySheetPage} for this editor */
     private UiPropertySheetPage mPropertyPage;
 
+    private UiEditorActions mUiEditorActions;
    
     /**
      * Creates the form editor for resources XML files.
      */
     public LayoutEditor() {
         super();
-        initUiRootNode();
     }
 
     /**
@@ -82,10 +83,6 @@
 
     @Override
     public void dispose() {
-        if (mResourceRefreshListener != null) {
-            EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
-            mResourceRefreshListener = null;
-        }
         getSite().getPage().removePartListener(this);
 
         super.dispose();
@@ -155,7 +152,7 @@
                 getSite().getPage().addPartListener(this);
             }
         } catch (PartInitException e) {
-            EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+            AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
         }
      }
 
@@ -222,6 +219,9 @@
      */
     @Override
     protected void xmlModelChanged(Document xml_doc) {
+        // init the ui root on demand
+        initUiRootNode(false /*force*/);
+
         mUiRootNode.loadFromXmlNode(xml_doc);
 
         // update the model first, since it is used by the viewers.
@@ -293,7 +293,11 @@
     }
 
     public void partDeactivated(IWorkbenchPart part) {
-        // pass
+        if (part == this) {
+            if (mGraphicalEditor != null && getActivePage() == mGraphicalEditorIndex) {
+                mGraphicalEditor.deactivated();
+            }
+        }
     }
 
     public void partOpened(IWorkbenchPart part) {
@@ -301,6 +305,32 @@
         EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID, false /* activate */);
     }
     
+    public class UiEditorActions extends UiActions {
+
+        @Override
+        protected UiDocumentNode getRootNode() {
+            return mUiRootNode;
+        }
+
+        // Select the new item
+        @Override
+        protected void selectUiNode(UiElementNode uiNodeToSelect) {
+            mGraphicalEditor.selectModel(uiNodeToSelect);
+        }
+
+        @Override
+        public void commitPendingXmlChanges() {
+            // Pass. There is nothing to commit before the XML is changed here.
+        }
+    }
+    
+    public UiEditorActions getUiEditorActions() {
+        if (mUiEditorActions == null) {
+            mUiEditorActions = new UiEditorActions();
+        }
+        return mUiEditorActions;
+    }
+    
     // ---- Local Methods ----
     
     /**
@@ -321,38 +351,50 @@
         return false;
     }
 
-    /**
-     * Creates the initial UI Root Node, including the known mandatory elements.
-     */
-    private void initUiRootNode() {
+    @Override
+    protected void initUiRootNode(boolean force) {
         // The root UI node is always created, even if there's no corresponding XML node.
-        if (mUiRootNode == null) {
-            DocumentDescriptor desc = LayoutDescriptors.getInstance().getDescriptor();
+        if (mUiRootNode == null || force) {
+            // get the target data from the opened file (and its project)
+            AndroidTargetData data = getTargetData();
+            
+            Document doc = null;
+            if (mUiRootNode != null) {
+                doc = mUiRootNode.getXmlDocument();
+            }
+            
+            DocumentDescriptor desc;
+            if (data == null) {
+                desc = new DocumentDescriptor("temp", null /*children*/);
+            } else {
+                desc = data.getLayoutDescriptors().getDescriptor();
+            }
+
+            // get the descriptors from the data.
             mUiRootNode = (UiDocumentNode) desc.createUiNode();
             mUiRootNode.setEditor(this);
 
-            // Add a listener to refresh the root node if the resource framework changes
-            // by forcing it to parse its own XML
-            mResourceRefreshListener = new Runnable() {
-                public void run() {
-                    commitPages(false /* onSave */);
-
-                    mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlDocument());
-                    
-                    if (mOutline != null) {
-                        mOutline.reloadModel();
-                    }
-                    
-                    if (mGraphicalEditor != null) {
-                        mGraphicalEditor.recomputeLayout();
-                    }
-                }
-            };
-            EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
-            mResourceRefreshListener.run();
+            onDescriptorsChanged(doc);
         }
     }
     
+    private void onDescriptorsChanged(Document document) {
+        if (document != null) {
+            mUiRootNode.loadFromXmlNode(document);
+        } else {
+            mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlDocument());
+        }
+        
+        if (mOutline != null) {
+            mOutline.reloadModel();
+        }
+        
+        if (mGraphicalEditor != null) {
+            mGraphicalEditor.reloadEditor();
+            mGraphicalEditor.reloadPalette();
+            mGraphicalEditor.recomputeLayout();
+        }
+    }
 
     /**
      * Handles a new input, and update the part name.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutReloadMonitor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/MatchingStrategy.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
new file mode 100644
index 0000000..94df28f
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+
+import org.eclipse.gef.palette.PaletteDrawer;
+import org.eclipse.gef.palette.PaletteGroup;
+import org.eclipse.gef.palette.PaletteRoot;
+import org.eclipse.gef.palette.PaletteTemplateEntry;
+
+import java.util.List;
+
+/**
+ * Factory that creates the palette for the {@link GraphicalLayoutEditor}.
+ */
+public class PaletteFactory {
+
+    /** Static factory, nothing to instantiate here. */
+    private PaletteFactory() {
+    }
+
+    public static PaletteRoot createPaletteRoot(PaletteRoot currentPalette,
+            AndroidTargetData targetData) {
+        
+        if (currentPalette == null) {
+            currentPalette = new PaletteRoot();
+        }
+
+        for (int n = currentPalette.getChildren().size() - 1; n >= 0; n--) {
+            currentPalette.getChildren().remove(n);
+        }
+        
+        if (targetData != null) {
+            addTools(currentPalette);
+            addViews(currentPalette, "Layouts",
+                    targetData.getLayoutDescriptors().getLayoutDescriptors());
+            addViews(currentPalette, "Views",
+                    targetData.getLayoutDescriptors().getViewDescriptors());
+        }
+
+        return currentPalette;
+    }
+
+    private static void addTools(PaletteRoot paletteRoot) {
+        PaletteGroup group = new PaletteGroup("Tools");
+        
+        // Default tools: selection.
+        // Do not use the MarqueeToolEntry since we don't support multiple selection.
+        /* -- Do not put the selection tool. It's the unique tool so it looks useless.
+              Leave this piece of code here in case we want it back later.
+        PanningSelectionToolEntry entry = new PanningSelectionToolEntry();
+        group.add(entry);
+        paletteRoot.setDefaultEntry(entry);
+        */
+
+        paletteRoot.add(group);
+    }
+
+    private static void addViews(PaletteRoot paletteRoot, String groupName,
+            List<ElementDescriptor> descriptors) {
+        PaletteDrawer group = new PaletteDrawer(groupName);
+        
+        for (ElementDescriptor desc : descriptors) {
+            PaletteTemplateEntry entry = new PaletteTemplateEntry(
+                    desc.getUiName(),           // label
+                    desc.getTooltip(),          // short description
+                    desc,                       // template
+                    desc.getImageDescriptor(),  // small icon
+                    desc.getImageDescriptor()   // large icon
+                    );
+            
+            group.add(entry);
+        }
+        
+        paletteRoot.add(group);
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
similarity index 88%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
index d91ecbc..81fd2ed 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/ProjectCallback.java
@@ -16,6 +16,7 @@
 
 package com.android.ide.eclipse.editors.layout;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidManifestHelper;
 import com.android.ide.eclipse.editors.resources.manager.ProjectClassLoader;
@@ -65,12 +66,17 @@
         
         // load the class.
         ProjectClassLoader loader = new ProjectClassLoader(mParentClassLoader, mProject);
-        clazz = loader.loadClass(className);
-        
-        if (clazz != null) {
-            mUsed = true;
-            mLoadedClasses.put(className, clazz);
-            return instantiateClass(clazz, constructorSignature, constructorParameters);
+        try {
+            clazz = loader.loadClass(className);
+            
+            if (clazz != null) {
+                mUsed = true;
+                mLoadedClasses.put(className, clazz);
+                return instantiateClass(clazz, constructorSignature, constructorParameters);
+            }
+        } catch (Error e) {
+            // Log this error with the class name we're trying to load and abort.
+            AdtPlugin.log(e, "ProjectCallback.loadView failed to find class %1$s", className); //$NON-NLS-1$
         }
         
         return null;
@@ -142,7 +148,7 @@
      * @param clazz the class to instantiate
      * @param constructorSignature the signature of the constructor to use
      * @param constructorParameters the parameters to use in the constructor.
-     * @return
+     * @return A new class object, created using a specific constructor and parameters.
      * @throws Exception 
      */
     @SuppressWarnings("unchecked")
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
similarity index 79%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
index 05f8370..3e0f5d8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
@@ -60,7 +60,10 @@
 import org.eclipse.swt.widgets.TreeItem;
 import org.eclipse.ui.IActionBars;
 
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Implementation of the {@link ContentOutlinePage} to display {@link UiElementNode}.
@@ -84,7 +87,8 @@
         mAddAction = new Action("Add...") {
             @Override
             public void run() {
-                UiElementNode node = getModelSelection();
+                List<UiElementNode> nodes = getModelSelections();
+                UiElementNode node = nodes != null && nodes.size() > 0 ? nodes.get(0) : null;
                 
                 mUiActions.doAdd(node, viewer.getControl().getShell());
             }
@@ -95,9 +99,9 @@
         mDeleteAction = new Action("Remove...") {
             @Override
             public void run() {
-                UiElementNode node = getModelSelection();
+                List<UiElementNode> nodes = getModelSelections();
                 
-                mUiActions.doRemove(node, viewer.getControl().getShell());
+                mUiActions.doRemove(nodes, viewer.getControl().getShell());
             }
         };
         mDeleteAction.setToolTipText("Removes an existing selected element.");
@@ -106,9 +110,9 @@
         mUpAction = new Action("Up") {
             @Override
             public void run() {
-                UiElementNode node = getModelSelection();
+                List<UiElementNode> nodes = getModelSelections();
                 
-                mUiActions.doUp(node);
+                mUiActions.doUp(nodes);
             }
         };
         mUpAction.setToolTipText("Moves the selected element up");
@@ -117,9 +121,9 @@
         mDownAction = new Action("Down") {
             @Override
             public void run() {
-                UiElementNode node = getModelSelection();
+                List<UiElementNode> nodes = getModelSelections();
                 
-                mUiActions.doDown(node);
+                mUiActions.doDown(nodes);
             }
         };
         mDownAction.setToolTipText("Moves the selected element down");
@@ -250,7 +254,7 @@
              * the necessary actions.
              */
            public void menuAboutToShow(IMenuManager manager) {
-               UiElementNode selected = getModelSelection();
+               List<UiElementNode> selected = getModelSelections();
                
                if (selected != null) {
                    doCreateMenuAction(manager, selected);
@@ -269,49 +273,74 @@
      * the tree view.
      * 
      * @param manager The context menu manager
-     * @param ui_node The UI node selected in the tree. Can be null, in which case the root
+     * @param selected The UI node selected in the tree. Can be null, in which case the root
      *                is to be modified.
      */
-    private void doCreateMenuAction(IMenuManager manager, UiElementNode ui_node) {
-        if (ui_node != null && ui_node.getXmlNode() != null) {
-            manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
-                    null, ui_node, true /* cut */));
-            manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
-                    null, ui_node, false /* cut */));
-            // Paste is not valid if it would add a second element on a terminal element
-            // which parent is a document -- an XML document can only have one child. This
-            // means paste is valid if the current UI node can have children or if the parent
-            // is not a document.
-            UiElementNode ui_root = ui_node.getUiRoot();
-            if (ui_root.getDescriptor().hasChildren() ||
-                    !(ui_root.getUiParent() instanceof UiDocumentNode)) {
-                manager.add(new PasteAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
-                        ui_node));
+    private void doCreateMenuAction(IMenuManager manager, List<UiElementNode> selected) {
+        
+        if (selected != null) {
+            boolean hasXml = false;
+            for (UiElementNode uiNode : selected) {
+                if (uiNode.getXmlNode() != null) {
+                    hasXml = true;
+                    break;
+                }
             }
-            manager.add(new Separator());
+
+            if (hasXml) {
+                manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
+                        null, selected, true /* cut */));
+                manager.add(new CopyCutAction(mEditor.getLayoutEditor(), mEditor.getClipboard(),
+                        null, selected, false /* cut */));
+
+                // Can't paste with more than one element selected (the selection is the target)
+                if (selected.size() <= 1) {
+                    // Paste is not valid if it would add a second element on a terminal element
+                    // which parent is a document -- an XML document can only have one child. This
+                    // means paste is valid if the current UI node can have children or if the parent
+                    // is not a document.
+                    UiElementNode ui_root = selected.get(0).getUiRoot();
+                    if (ui_root.getDescriptor().hasChildren() ||
+                            !(ui_root.getUiParent() instanceof UiDocumentNode)) {
+                        manager.add(new PasteAction(mEditor.getLayoutEditor(),
+                                mEditor.getClipboard(),
+                                selected.get(0)));
+                    }
+                }
+                manager.add(new Separator());
+            }
         }
 
         // Append "add" and "remove" actions. They do the same thing as the add/remove
         // buttons on the side.
-        manager.add(mAddAction);
-        manager.add(mDeleteAction);        
+        //
+        // "Add" makes sense only if there's 0 or 1 item selected since the
+        // one selected item becomes the target.
+        if (selected == null || selected.size() <= 1) {
+            manager.add(mAddAction);
+        }
 
-        manager.add(new Separator());
-        
-        manager.add(mUpAction);
-        manager.add(mDownAction);
-        
-        manager.add(new Separator());
-        
-        Action propertiesAction = new Action("Properties") {
-            @Override
-            public void run() {
-                EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID,
-                        true /* activate */);
-            }
-        };
-        propertiesAction.setToolTipText("Displays properties of the selected element.");
-        manager.add(propertiesAction);
+        if (selected != null) {
+            manager.add(mDeleteAction);
+            manager.add(new Separator());
+            
+            manager.add(mUpAction);
+            manager.add(mDownAction);
+        }
+
+        if (selected != null && selected.size() == 1) {
+            manager.add(new Separator());
+            
+            Action propertiesAction = new Action("Properties") {
+                @Override
+                public void run() {
+                    EclipseUiHelper.showView(EclipseUiHelper.PROPERTY_SHEET_VIEW_ID,
+                            true /* activate */);
+                }
+            };
+            propertiesAction.setToolTipText("Displays properties of the selected element.");
+            manager.add(propertiesAction);
+        }
     }
 
     /**
@@ -321,18 +350,20 @@
      */
     public void reloadModel() {
         // Attemps to preserve the UiNode selection, if any
-        UiElementNode uiNode = null;
+        List<UiElementNode> uiNodes = null;
         try {
             // get current selection using the model rather than the edit part as
             // reloading the content may change the actual edit part.
-            uiNode = getModelSelection();
+            uiNodes = getModelSelections();
 
             // perform the update
             getViewer().setContents(mEditor.getModel());
 
         } finally {
             // restore selection
-            setModelSelection(uiNode);
+            if (uiNodes != null) {
+                setModelSelection(uiNodes.get(0));
+            }
         }
     }
 
@@ -344,17 +375,24 @@
      * When there is no actual selection, this might still return the root node,
      * which is of type {@link UiDocumentTreeEditPart}.
      */
-    private UiElementTreeEditPart getViewerSelection() {
+    @SuppressWarnings("unchecked")
+    private List<UiElementTreeEditPart> getViewerSelections() {
         ISelection selection = getSelection();
         if (selection instanceof StructuredSelection) {
             StructuredSelection structuredSelection = (StructuredSelection)selection;
             
-            if (structuredSelection.size() == 1) {
-                Object selectedObj = structuredSelection.getFirstElement();
+            if (structuredSelection.size() > 0) {
+                ArrayList<UiElementTreeEditPart> selected = new ArrayList<UiElementTreeEditPart>();
                 
-                if (selectedObj instanceof UiElementTreeEditPart) {
-                    return (UiElementTreeEditPart) selectedObj;
+                for (Iterator it = structuredSelection.iterator(); it.hasNext(); ) {
+                    Object selectedObj = it.next();
+                
+                    if (selectedObj instanceof UiElementTreeEditPart) {
+                        selected.add((UiElementTreeEditPart) selectedObj);
+                    }
                 }
+                
+                return selected.size() > 0 ? selected : null;
             }
         }
         
@@ -368,13 +406,22 @@
      * Returns null if there is no selection or if the implicit root is "selected"
      * (which actually represents the lack of a real element selection.)
      */
-    private UiElementNode getModelSelection() {
+    private List<UiElementNode> getModelSelections() {
 
-        UiElementTreeEditPart part = getViewerSelection();
+        List<UiElementTreeEditPart> parts = getViewerSelections();
 
-        if (part instanceof UiViewTreeEditPart || part instanceof UiLayoutTreeEditPart) {
-            return (UiElementNode) part.getModel();
+        if (parts != null) {
+            ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
+            
+            for (UiElementTreeEditPart part : parts) {
+                if (part instanceof UiViewTreeEditPart || part instanceof UiLayoutTreeEditPart) {
+                    selected.add((UiElementNode) part.getModel());
+                }
+            }
+            
+            return selected.size() > 0 ? selected : null;
         }
+        
         return null;
     }
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
new file mode 100644
index 0000000..b0e6fdb
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import com.android.layoutlib.api.IXmlPullParser;
+
+import org.w3c.dom.Node;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link IXmlPullParser} implementation on top of {@link UiElementNode}.
+ * <p/>It's designed to work on layout files, and will most likely not work on other resource
+ * files.
+ */
+public final class UiElementPullParser extends BasePullParser {
+    
+    private final ArrayList<UiElementNode> mNodeStack = new ArrayList<UiElementNode>();
+    private UiElementNode mRoot;
+    
+    public UiElementPullParser(UiElementNode top) {
+        super();
+        mRoot = top;
+        push(mRoot);
+    }
+    
+    private UiElementNode getCurrentNode() {
+        if (mNodeStack.size() > 0) {
+            return mNodeStack.get(mNodeStack.size()-1);
+        }
+        
+        return null;
+    }
+    
+    private Node getAttribute(int i) {
+        if (mParsingState != START_TAG) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        // get the current uiNode
+        UiElementNode uiNode = getCurrentNode();
+        
+        // get its xml node
+        Node xmlNode = uiNode.getXmlNode();
+
+        if (xmlNode != null) {
+            return xmlNode.getAttributes().item(i);
+        }
+
+        return null;
+    }
+    
+    private void push(UiElementNode node) {
+        mNodeStack.add(node);
+    }
+    
+    private UiElementNode pop() {
+        return mNodeStack.remove(mNodeStack.size()-1);
+    }
+
+    // ------------- IXmlPullParser --------
+
+    /**
+     * {@inheritDoc}
+     * 
+     * This implementation returns the underlying DOM node.
+     */
+    public Object getViewKey() {
+        return getCurrentNode();
+    }
+
+    // ------------- XmlPullParser --------
+
+    public String getPositionDescription() {
+        return "XML DOM element depth:" + mNodeStack.size();
+    }
+
+    public int getAttributeCount() {
+        UiElementNode node = getCurrentNode();
+        if (node != null) {
+            return node.getUiAttributes().size();
+        }
+
+        return 0;
+    }
+
+    public String getAttributeName(int i) {
+        Node attribute = getAttribute(i);
+        if (attribute != null) {
+            return attribute.getLocalName();
+        }
+
+        return null;
+    }
+
+    public String getAttributeNamespace(int i) {
+        Node attribute = getAttribute(i);
+        if (attribute != null) {
+            return attribute.getNamespaceURI();
+        }
+        return ""; //$NON-NLS-1$
+    }
+
+    public String getAttributePrefix(int i) {
+        Node attribute = getAttribute(i);
+        if (attribute != null) {
+            return attribute.getPrefix();
+        }
+        return null;
+    }
+
+    public String getAttributeValue(int i) {
+        Node attribute = getAttribute(i);
+        if (attribute != null) {
+            return attribute.getNodeValue();
+        }
+        
+        return null;
+    }
+
+    public String getAttributeValue(String namespace, String localName) {
+        // get the current uiNode
+        UiElementNode uiNode = getCurrentNode();
+        
+        // get its xml node
+        Node xmlNode = uiNode.getXmlNode();
+        
+        if (xmlNode != null) {
+            Node attribute = xmlNode.getAttributes().getNamedItemNS(namespace, localName);
+            if (attribute != null) {
+                return attribute.getNodeValue();
+            }
+        }
+
+        return null;
+    }
+
+    public int getDepth() {
+        return mNodeStack.size();
+    }
+
+    public String getName() {
+        if (mParsingState == START_TAG || mParsingState == END_TAG) {
+            return getCurrentNode().getDescriptor().getXmlLocalName();
+        }
+
+        return null;
+    }
+
+    public String getNamespace() {
+        if (mParsingState == START_TAG || mParsingState == END_TAG) {
+            return getCurrentNode().getDescriptor().getNamespace();
+        }
+
+        return null;
+    }
+
+    public String getPrefix() {
+        if (mParsingState == START_TAG || mParsingState == END_TAG) {
+            // FIXME will NEVER work
+            if (getCurrentNode().getDescriptor().getXmlLocalName().startsWith("android:")) { //$NON-NLS-1$
+                return "android"; //$NON-NLS-1$
+            }
+        }
+
+        return null;
+    }
+
+    public boolean isEmptyElementTag() throws XmlPullParserException {
+        if (mParsingState == START_TAG) {
+            return getCurrentNode().getUiChildren().size() == 0;
+        }
+        
+        throw new XmlPullParserException("Call to isEmptyElementTag while not in START_TAG",
+                this, null);
+    }
+    
+    @Override
+    public void onNextFromStartDocument() {
+        onNextFromStartTag();
+    }
+    
+    @Override
+    public void onNextFromStartTag() {
+        // get the current node, and look for text or children (children first)
+        UiElementNode node = getCurrentNode();
+        List<UiElementNode> children = node.getUiChildren();
+        if (children.size() > 0) {
+            // move to the new child, and don't change the state.
+            push(children.get(0));
+            
+            // in case the current state is CURRENT_DOC, we set the proper state.
+            mParsingState = START_TAG;
+        } else {
+            if (mParsingState == START_DOCUMENT) {
+                // this handles the case where there's no node.
+                mParsingState = END_DOCUMENT;
+            } else {
+                mParsingState = END_TAG;
+            }
+        }
+    }
+    
+    @Override
+    public void onNextFromEndTag() {
+        // look for a sibling. if no sibling, go back to the parent
+        UiElementNode node = getCurrentNode();
+        node = node.getUiNextSibling();
+        if (node != null) {
+            // to go to the sibling, we need to remove the current node,
+            pop();
+            // and add its sibling.
+            push(node);
+            mParsingState = START_TAG;
+        } else {
+            // move back to the parent
+            pop();
+            
+            // we have only one element left (mRoot), then we're done with the document.
+            if (mNodeStack.size() == 1) {
+                mParsingState = END_DOCUMENT;
+            } else {
+                mParsingState = END_TAG;
+            }
+        }
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiPropertySheetPage.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java
new file mode 100644
index 0000000..75d10ed
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/WidgetPullParser.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2008 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.editors.layout;
+
+import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
+import com.android.layoutlib.api.IXmlPullParser;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * {@link IXmlPullParser} implementation to render android widget bitmap.
+ * <p/>The parser emulates a layout that contains just one widget, described by the
+ * {@link ViewElementDescriptor} passed in the constructor.
+ */
+public class WidgetPullParser extends BasePullParser {
+    
+    private final ViewElementDescriptor mDescriptor;
+    private String[][] mAttributes = new String[][] {
+            { "text", null },
+            { "layout_width", "wrap_content" },
+            { "layout_height", "wrap_content" },
+    };
+
+    public WidgetPullParser(ViewElementDescriptor descriptor) {
+        mDescriptor = descriptor;
+        
+        String[] segments = mDescriptor.getCanonicalClassName().split(AndroidConstants.RE_DOT);
+        mAttributes[0][1] = segments[segments.length-1];
+    }
+
+    public Object getViewKey() {
+        // we need a viewKey or the ILayoutResult will not contain any ILayoutViewInfo
+        return mDescriptor;
+    }
+
+    public int getAttributeCount() {
+        return mAttributes.length; // text attribute
+    }
+
+    public String getAttributeName(int index) {
+        if (index < mAttributes.length) {
+            return mAttributes[index][0];
+        }
+        
+        return null;
+    }
+
+    public String getAttributeNamespace(int index) {
+        return AndroidConstants.NS_RESOURCES;
+    }
+
+    public String getAttributePrefix(int index) {
+        // pass
+        return null;
+    }
+
+    public String getAttributeValue(int index) {
+        if (index < mAttributes.length) {
+            return mAttributes[index][1];
+        }
+        
+        return null;
+    }
+
+    public String getAttributeValue(String ns, String name) {
+        if (AndroidConstants.NS_RESOURCES.equals(ns)) {
+            for (String[] attribute : mAttributes) {
+                if (name.equals(attribute[0])) {
+                    return attribute[1];
+                }
+            }
+        }
+        
+        return null;
+    }
+
+    public int getDepth() {
+        // pass
+        return 0;
+    }
+
+    public String getName() {
+        return mDescriptor.getXmlLocalName();
+    }
+
+    public String getNamespace() {
+        // pass
+        return null;
+    }
+
+    public String getPositionDescription() {
+        // pass
+        return null;
+    }
+
+    public String getPrefix() {
+        // pass
+        return null;
+    }
+
+    public boolean isEmptyElementTag() throws XmlPullParserException {
+        if (mParsingState == START_TAG) {
+            return true;
+        }
+        
+        throw new XmlPullParserException("Call to isEmptyElementTag while not in START_TAG",
+                this, null);
+    }
+
+    @Override
+    public void onNextFromStartDocument() {
+        // just go to start_tag
+        mParsingState = START_TAG;
+    }
+
+    @Override
+    public void onNextFromStartTag() {
+        // since we have no children, just go to end_tag
+        mParsingState = END_TAG;
+    }
+
+    @Override
+    public void onNextFromEndTag() {
+        // just one tag. we are done.
+        mParsingState = END_DOCUMENT;
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
similarity index 92%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
index c3e9b70..0f388f4 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/CustomViewDescriptorService.java
@@ -16,9 +16,12 @@
 
 package com.android.ide.eclipse.editors.layout.descriptors;
 
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.resources.ViewClassInfo;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.NullProgressMonitor;
@@ -192,15 +195,24 @@
     private ViewElementDescriptor getDescriptor(IType type, IProject project,
             ITypeHierarchy typeHierarchy) {
         // check if the type is a built-in View class.
-        List<ElementDescriptor> builtInList = LayoutDescriptors.getInstance().getViewDescriptors();
-        
+        List<ElementDescriptor> builtInList = null;
+
+        Sdk currentSdk = Sdk.getCurrent();
+        IAndroidTarget target = currentSdk.getTarget(project);
+        if (target != null) {
+            AndroidTargetData data = currentSdk.getTargetData(target);
+            builtInList = data.getLayoutDescriptors().getViewDescriptors();
+        }
+
         String canonicalName = type.getFullyQualifiedName();
         
-        for (ElementDescriptor desc : builtInList) {
-            if (desc instanceof ViewElementDescriptor) {
-                ViewElementDescriptor viewDescriptor = (ViewElementDescriptor)desc;
-                if (canonicalName.equals(viewDescriptor.getCanonicalClassName())) {
-                    return viewDescriptor;
+        if (builtInList != null) {
+            for (ElementDescriptor desc : builtInList) {
+                if (desc instanceof ViewElementDescriptor) {
+                    ViewElementDescriptor viewDescriptor = (ViewElementDescriptor)desc;
+                    if (canonicalName.equals(viewDescriptor.getCanonicalClassName())) {
+                        return viewDescriptor;
+                    }
                 }
             }
         }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
index 8ad2382..cad9ccf 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
@@ -24,6 +24,7 @@
 import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
 import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
 import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
 
 import java.util.ArrayList;
@@ -34,31 +35,26 @@
 /**
  * Complete description of the layout structure.
  */
-public class LayoutDescriptors {
+public final class LayoutDescriptors implements IDescriptorProvider {
 
     // Public attributes names, attributes descriptors and elements descriptors
     public static final String ID_ATTR = "id"; //$NON-NLS-1$
 
-    /** Singleton instance */
-    private static LayoutDescriptors sThis;
-
     /** The document descriptor. Contains all layouts and views linked together. */
     private DocumentDescriptor mDescriptor =
         new DocumentDescriptor("layout_doc", null); //$NON-NLS-1$
 
     /** The list of all known ViewLayout descriptors. */
     private ArrayList<ElementDescriptor> mLayoutDescriptors = new ArrayList<ElementDescriptor>();
-    
+
+    /** Read-Only list of View Descriptors. */
+    private List<ElementDescriptor> mROLayoutDescriptors;
+
     /** The list of all known View (not ViewLayout) descriptors. */
     private ArrayList<ElementDescriptor> mViewDescriptors = new ArrayList<ElementDescriptor>();
     
-    /** Returns a singleton instance of the {@link LayoutDescriptors}. */
-    public static synchronized LayoutDescriptors getInstance() {
-        if (sThis == null) {
-            sThis = new LayoutDescriptors();
-        }
-        return sThis;
-    }
+    /** Read-Only list of View Descriptors. */
+    private List<ElementDescriptor> mROViewDescriptors;
     
     /** @return the document descriptor. Contains all layouts and views linked together. */
     public DocumentDescriptor getDescriptor() {
@@ -67,12 +63,16 @@
     
     /** @return The read-only list of all known ViewLayout descriptors. */
     public List<ElementDescriptor> getLayoutDescriptors() {
-        return Collections.unmodifiableList(mLayoutDescriptors);
+        return mROLayoutDescriptors;
     }
     
     /** @return The read-only list of all known View (not ViewLayout) descriptors. */
     public List<ElementDescriptor> getViewDescriptors() {
-        return Collections.unmodifiableList(mViewDescriptors);
+        return mROViewDescriptors;
+    }
+    
+    public ElementDescriptor[] getRootElementDescriptors() {
+        return mDescriptor.getChildren();
     }
 
     /**
@@ -118,6 +118,9 @@
         mViewDescriptors = newViews;
         mLayoutDescriptors  = newLayouts;
         mDescriptor.setChildren(newArray);
+        
+        mROLayoutDescriptors = Collections.unmodifiableList(mLayoutDescriptors);
+        mROViewDescriptors = Collections.unmodifiableList(mViewDescriptors);
     }
 
     /**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/ViewElementDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java
new file mode 100644
index 0000000..6e79d64
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/DropFeedback.java
@@ -0,0 +1,761 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.layout.LayoutConstants;
+import com.android.ide.eclipse.editors.layout.LayoutEditor.UiEditorActions;
+import com.android.ide.eclipse.editors.layout.parts.UiLayoutEditPart.HighlightInfo;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+/**
+ * Utility methods used when dealing with dropping EditPart on the GLE.
+ * <p/>
+ * This class uses some temporary static storage to avoid excessive allocations during
+ * drop operations. It is expected to only be invoked from the main UI thread with no
+ * concurrent access.
+ */
+class DropFeedback {
+
+    private static final int TOP    = 0;
+    private static final int LEFT   = 1;
+    private static final int BOTTOM = 2;
+    private static final int RIGHT  = 3;
+    private static final int MAX_DIR = RIGHT;
+    
+    private static final int sOppositeDirection[] = { BOTTOM, RIGHT, TOP, LEFT };
+
+    private static final UiElementEditPart sTempClosests[] = new UiElementEditPart[4];
+    private static final int sTempMinDists[] = new int[4];
+    
+
+    /**
+     * Target information computed from a drop on a RelativeLayout.
+     * We need only one instance of this and it is sRelativeInfo.
+     */
+    private static class RelativeInfo {
+        /** The two target parts 0 and 1. They can be null, meaning a border is used.
+         *  The direction from part 0 to 1 is always to-the-right or to-the-bottom. */
+        final UiElementEditPart targetParts[] = new UiElementEditPart[2];
+        /** Direction from the anchor part to the drop point. */
+        int direction;
+        /** The index of the "anchor" part, i.e. the closest one selected by the drop.
+         *  This can be either 0 or 1. The corresponding part can be null. */
+        int anchorIndex;
+    }
+
+    /** The single RelativeInfo used to compute results from a drop on a RelativeLayout */
+    private static final RelativeInfo sRelativeInfo = new RelativeInfo();
+    /** A temporary array of 2 {@link UiElementEditPart} to avoid allocations. */
+    private static final UiElementEditPart sTempTwoParts[] = new UiElementEditPart[2];
+    
+
+    private DropFeedback() {
+    }
+
+    
+    //----- Package methods called by users of this helper class -----
+    
+    
+    /**
+     * This method is used by {@link ElementCreateCommand#execute()} when a new item
+     * needs to be "dropped" in the current XML document. It creates the new item using
+     * the given descriptor as a child of the given parent part.
+     * 
+     * @param parentPart The parent part.
+     * @param descriptor The descriptor for the new XML element.
+     * @param where      The drop location (in parent coordinates)
+     * @param actions    The helper that actually modifies the XML model.
+     */
+    static void addElementToXml(UiElementEditPart parentPart,
+            ElementDescriptor descriptor, Point where,
+            UiEditorActions actions) {
+        
+        String layoutXmlName = getXmlLocalName(parentPart);
+        RelativeInfo info = null;
+        UiElementEditPart sibling = null;
+        
+        if (LayoutConstants.LINEAR_LAYOUT.equals(layoutXmlName)) {
+            sibling = findLinearTarget(parentPart, where)[1];
+            
+        } else if (LayoutConstants.RELATIVE_LAYOUT.equals(layoutXmlName)) {
+            info = findRelativeTarget(parentPart, where, sRelativeInfo);
+            if (info != null) {
+                sibling = info.targetParts[info.anchorIndex];
+                sibling = getNextUiSibling(sibling);
+            }
+        }
+
+        if (actions != null) {
+            UiElementNode uiSibling = sibling != null ? sibling.getUiNode() : null;
+            UiElementNode uiParent = parentPart.getUiNode();
+            UiElementNode uiNode = actions.addElement(uiParent, uiSibling, descriptor,
+                    false /*updateLayout*/);
+            
+            if (LayoutConstants.ABSOLUTE_LAYOUT.equals(layoutXmlName)) {
+                adjustAbsoluteAttributes(uiNode, where);
+            } else if (LayoutConstants.RELATIVE_LAYOUT.equals(layoutXmlName)) {
+                adustRelativeAttributes(uiNode, info);
+            }
+        }
+    }
+
+    /**
+     * This method is used by {@link UiLayoutEditPart#showDropTarget(Point)} to compute
+     * highlight information when a drop target is moved over a valid drop area.
+     * <p/>
+     * Since there are no "out" parameters in Java, all the information is returned
+     * via the {@link HighlightInfo} structure passed as parameter. 
+     * 
+     * @param parentPart    The parent part, always a layout.
+     * @param highlightInfo A structure where result is stored to perform highlight.
+     * @param where         The target drop point, in parent's coordinates
+     * @return The {@link HighlightInfo} structured passed as a parameter, for convenience.
+     */
+    static HighlightInfo computeDropFeedback(UiLayoutEditPart parentPart,
+            HighlightInfo highlightInfo,
+            Point where) {
+        String layoutType = getXmlLocalName(parentPart);
+        
+        if (LayoutConstants.ABSOLUTE_LAYOUT.equals(layoutType)) {
+            highlightInfo.anchorPoint = where;
+            
+        } else if (LayoutConstants.LINEAR_LAYOUT.equals(layoutType)) {
+            boolean isVertical = isVertical(parentPart);
+
+            highlightInfo.childParts = findLinearTarget(parentPart, where);
+            computeLinearLine(parentPart, isVertical, highlightInfo);
+            
+        } else if (LayoutConstants.RELATIVE_LAYOUT.equals(layoutType)) {
+
+            RelativeInfo info = findRelativeTarget(parentPart, where, sRelativeInfo);
+            if (info != null) {
+                highlightInfo.childParts = sRelativeInfo.targetParts;
+                computeRelativeLine(parentPart, info, highlightInfo);
+            }
+        }
+        
+        return highlightInfo;
+    }
+    
+    
+    //----- Misc utilities -----
+    
+    /**
+     * Returns the next UI sibling of this part, i.e. the element which is just after in
+     * the UI/XML order in the same parent. Returns null if there's no such part.
+     * <p/>
+     * Note: by "UI sibling" here we mean the sibling in the UiNode hierarchy. By design the
+     * UiNode model has the <em>exact</em> same order as the XML model. This has nothing to do
+     * with the "user interface" order that you see on the rendered Android layouts (e.g. for
+     * LinearLayout they are the same but for AbsoluteLayout or RelativeLayout the UI/XML model
+     * order can be vastly different from the user interface order.)
+     */
+    private static UiElementEditPart getNextUiSibling(UiElementEditPart part) {
+        if (part != null) {
+            UiElementNode uiNode = part.getUiNode();
+            if (uiNode != null) {
+                uiNode = uiNode.getUiNextSibling();
+            }
+            if (uiNode != null) {
+                for (Object childPart : part.getParent().getChildren()) {
+                    if (childPart instanceof UiElementEditPart &&
+                            ((UiElementEditPart) childPart).getUiNode() == uiNode) {
+                        return (UiElementEditPart) childPart;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the XML local name of the ui node associated with this edit part or null.
+     */
+    private static String getXmlLocalName(UiElementEditPart editPart) {
+        UiElementNode uiNode = editPart.getUiNode();
+        if (uiNode != null) {
+            ElementDescriptor desc = uiNode.getDescriptor();
+            if (desc != null) {
+                return desc.getXmlLocalName();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Adjusts the attributes of a new node dropped in an AbsoluteLayout.
+     * 
+     * @param uiNode The new node being dropped.
+     * @param where  The drop location (in parent coordinates)
+     */
+    private static void adjustAbsoluteAttributes(final UiElementNode uiNode, final Point where) {
+        if (where == null) {
+            return;
+        }
+        uiNode.getEditor().editXmlModel(new Runnable() {
+            public void run() {
+                uiNode.setAttributeValue(LayoutConstants.ATTR_LAYOUT_X,
+                        String.format(LayoutConstants.VALUE_N_DIP, where.x),
+                        false /* override */);
+                uiNode.setAttributeValue(LayoutConstants.ATTR_LAYOUT_Y,
+                        String.format(LayoutConstants.VALUE_N_DIP, where.y),
+                        false /* override */);
+
+                uiNode.commitDirtyAttributesToXml();
+            }
+        });
+    }
+
+    /**
+     * Adjusts the attributes of a new node dropped in a RelativeLayout:
+     * <ul>
+     * <li> anchor part: the one the user selected (or the closest) and to which the new one
+     *      will "attach". The anchor part can be null, either because the layout is currently
+     *      empty or the user is attaching to an existing empty border.
+     * <li> direction: the direction from the anchor part to the drop point. That's also the
+     *      direction from the anchor part to the new part. 
+     * <li> the new node; it is created either after the anchor for right or top directions
+     *      or before the anchor for left or bottom directions. This means the new part can 
+     *      reference the id of the anchor part. 
+     * </ul>
+     * 
+     * Several cases:
+     * <ul>
+     * <li> set:  layout_above/below/toLeftOf/toRightOf to point to the anchor.
+     * <li> copy: layout_centerHorizontal for top/bottom directions
+     * <li> copy: layout_centerVertical for left/right directions.
+     * <li> copy: layout_above/below/toLeftOf/toRightOf for the orthogonal direction
+     *            (i.e. top/bottom or left/right.)
+     * </ul>
+     * 
+     * @param uiNode The new node being dropped.
+     * @param info   The context computed by {@link #findRelativeTarget(UiElementEditPart, Point, RelativeInfo)}.
+     */
+    private static void adustRelativeAttributes(final UiElementNode uiNode, RelativeInfo info) {
+        if (uiNode == null || info == null) {
+            return;
+        }
+        
+        final UiElementEditPart anchorPart = info.targetParts[info.anchorIndex];  // can be null       
+        final int direction = info.direction;
+        
+        uiNode.getEditor().editXmlModel(new Runnable() {
+            public void run() {
+                HashMap<String, String> map = new HashMap<String, String>();
+
+                UiElementNode anchorUiNode = anchorPart != null ? anchorPart.getUiNode() : null;
+                String anchorId = anchorUiNode != null
+                                    ? anchorUiNode.getAttributeValue("id")          //$NON-NLS-1$
+                                    : null;
+
+                if (anchorId == null) {
+                    anchorId = DescriptorsUtils.getFreeWidgetId(anchorUiNode);
+                    anchorUiNode.setAttributeValue("id", anchorId, true /*override*/); //$NON-NLS-1$
+                }
+                
+                if (anchorId != null) {
+                    switch(direction) {
+                    case TOP:
+                        map.put(LayoutConstants.ATTR_LAYOUT_ABOVE, anchorId);
+                        break;
+                    case BOTTOM:
+                        map.put(LayoutConstants.ATTR_LAYOUT_BELOW, anchorId);
+                        break;
+                    case LEFT:
+                        map.put(LayoutConstants.ATTR_LAYOUT_TO_LEFT_OF, anchorId);
+                        break;
+                    case RIGHT:
+                        map.put(LayoutConstants.ATTR_LAYOUT_TO_RIGHT_OF, anchorId);
+                        break;
+                    }
+
+                    switch(direction) {
+                    case TOP:
+                    case BOTTOM:
+                        map.put(LayoutConstants.ATTR_LAYOUT_CENTER_HORIZONTAL,
+                                anchorUiNode.getAttributeValue(
+                                        LayoutConstants.ATTR_LAYOUT_CENTER_HORIZONTAL));
+
+                        map.put(LayoutConstants.ATTR_LAYOUT_TO_LEFT_OF,
+                                anchorUiNode.getAttributeValue(
+                                        LayoutConstants.ATTR_LAYOUT_TO_LEFT_OF));
+                        map.put(LayoutConstants.ATTR_LAYOUT_TO_RIGHT_OF,
+                                anchorUiNode.getAttributeValue(
+                                        LayoutConstants.ATTR_LAYOUT_TO_RIGHT_OF));
+                        break;
+                    case LEFT:
+                    case RIGHT:
+                        map.put(LayoutConstants.ATTR_LAYOUT_CENTER_VERTICAL,
+                                anchorUiNode.getAttributeValue(
+                                        LayoutConstants.ATTR_LAYOUT_CENTER_VERTICAL));
+                        map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_BASELINE,
+                                anchorUiNode.getAttributeValue(
+                                        LayoutConstants.ATTR_LAYOUT_ALIGN_BASELINE));
+                        
+                        map.put(LayoutConstants.ATTR_LAYOUT_ABOVE,
+                                anchorUiNode.getAttributeValue(LayoutConstants.ATTR_LAYOUT_ABOVE));
+                        map.put(LayoutConstants.ATTR_LAYOUT_BELOW,
+                                anchorUiNode.getAttributeValue(LayoutConstants.ATTR_LAYOUT_BELOW));
+                        break;
+                    }
+                } else {
+                    // We don't have an anchor node. Assume we're targeting a border and align
+                    // to the parent.
+                    switch(direction) {
+                    case TOP:
+                        map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_TOP,
+                                LayoutConstants.VALUE_TRUE);
+                        break;
+                    case BOTTOM:
+                        map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_BOTTOM,
+                                LayoutConstants.VALUE_TRUE);
+                        break;
+                    case LEFT:
+                        map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_LEFT,
+                                LayoutConstants.VALUE_TRUE);
+                        break;
+                    case RIGHT:
+                        map.put(LayoutConstants.ATTR_LAYOUT_ALIGN_PARENT_RIGHT,
+                                LayoutConstants.VALUE_TRUE);
+                        break;
+                    }
+                }
+                
+                for (Entry<String, String> entry : map.entrySet()) {
+                    uiNode.setAttributeValue(entry.getKey(), entry.getValue(), true /* override */);
+                }
+                uiNode.commitDirtyAttributesToXml();
+            }
+        });
+    }
+
+
+    //----- LinearLayout --------
+
+    /**
+     * For a given parent edit part that MUST represent a LinearLayout, finds the
+     * element before which the location points.
+     * <p/>
+     * This computes the edit part that corresponds to what will be the "next sibling" of the new
+     * element.
+     * <p/>
+     * It returns null if it can't be determined, in which case the element will be added at the
+     * end of the parent child list.
+     * 
+     * @return The edit parts that correspond to what will be the "prev" and "next sibling" of the
+     *         new element. The previous sibling can be null if adding before the first element.
+     *         The next sibling can be null if adding after the last element.
+     */
+    private static UiElementEditPart[] findLinearTarget(UiElementEditPart parent, Point point) {
+        // default orientation is horizontal
+        boolean isVertical = isVertical(parent);
+        
+        int target = isVertical ? point.y : point.x;
+        
+        UiElementEditPart prev = null;
+        UiElementEditPart next = null;
+
+        for (Object child : parent.getChildren()) {
+            if (child instanceof UiElementEditPart) {
+                UiElementEditPart childPart = (UiElementEditPart) child;
+                Point p = childPart.getBounds().getCenter();
+                int middle = isVertical ? p.y : p.x;
+                if (target < middle) {
+                    next = childPart;
+                    break;
+                }
+                prev = childPart;
+            }
+        }
+        
+        sTempTwoParts[0] = prev;
+        sTempTwoParts[1] = next;
+        return sTempTwoParts;
+    }
+
+    /**
+     * Computes the highlight line between two parts.
+     * <p/>
+     * The two parts are listed in HighlightInfo.childParts[2]. Any of the parts
+     * can be null.
+     * The result is stored in HighlightInfo.
+     * <p/>
+     * Caller must clear the HighlightInfo as appropriate before this call.
+     * 
+     * @param parentPart    The parent part, always a layout.
+     * @param isVertical    True for vertical parts, thus computing an horizontal line.
+     * @param highlightInfo The in-out highlight info.
+     */
+    private static void computeLinearLine(UiLayoutEditPart parentPart,
+            boolean isVertical, HighlightInfo highlightInfo) {
+        Rectangle r = parentPart.getBounds();
+
+        if (isVertical) {
+            Point p = null;
+            UiElementEditPart part = highlightInfo.childParts[0];
+            if (part != null) {
+                p = part.getBounds().getBottom();
+            } else {
+                part = highlightInfo.childParts[1];
+                if (part != null) {
+                    p = part.getBounds().getTop();
+                }
+            }
+            if (p != null) {
+                // horizontal line with middle anchor point
+                highlightInfo.tempPoints[0].setLocation(0, p.y);
+                highlightInfo.tempPoints[1].setLocation(r.width, p.y);
+                highlightInfo.linePoints = highlightInfo.tempPoints;
+                highlightInfo.anchorPoint = p.setLocation(r.width / 2, p.y);
+            }
+        } else {
+            Point p = null;
+            UiElementEditPart part = highlightInfo.childParts[0];
+            if (part != null) {
+                p = part.getBounds().getRight();
+            } else {
+                part = highlightInfo.childParts[1];
+                if (part != null) {
+                    p = part.getBounds().getLeft();
+                }
+            }
+            if (p != null) {
+                // vertical line with middle anchor point
+                highlightInfo.tempPoints[0].setLocation(p.x, 0);
+                highlightInfo.tempPoints[1].setLocation(p.x, r.height);
+                highlightInfo.linePoints = highlightInfo.tempPoints;
+                highlightInfo.anchorPoint = p.setLocation(p.x, r.height / 2);
+            }
+        }
+    }
+
+    /**
+     * Returns true if the linear layout is marked as vertical.
+     * 
+     * @param parent The a layout part that must be a LinearLayout 
+     * @return True if the linear layout has a vertical orientation attribute.
+     */
+    private static boolean isVertical(UiElementEditPart parent) {
+        String orientation = parent.getStringAttr("orientation");     //$NON-NLS-1$
+        boolean isVertical = "vertical".equals(orientation) ||        //$NON-NLS-1$ 
+                             "1".equals(orientation);                 //$NON-NLS-1$
+        return isVertical;
+    }
+
+    
+    //----- RelativeLayout --------
+
+    /**
+     * Finds the "target" relative layout item for the drop operation & feedback.
+     * <p/>
+     * If the drop point is exactly on a current item, simply returns the side the drop will occur
+     * compared to the center of that element. For the actual XML, we'll need to insert *after*
+     * that element to make sure that referenced are defined in the right order.
+     * In that case the result contains two elements, the second one always being on the right or
+     * bottom side of the first one. When insert in XML, we want to insert right before that
+     * second element or at the end of the child list if the second element is null.
+     * <p/>
+     * If the drop point is not exactly on a current element, find the closest in each
+     * direction and align with the two closest of these.
+     * 
+     * @return null if we fail to find anything (such as there are currently no items to compare
+     *         with); otherwise fills the {@link RelativeInfo} and return it.
+     */
+    private static RelativeInfo findRelativeTarget(UiElementEditPart parent,
+            Point point,
+            RelativeInfo outInfo) {
+        
+        for (int i = 0; i < 4; i++) {
+            sTempMinDists[i] = Integer.MAX_VALUE;
+            sTempClosests[i] = null;
+        }
+
+        
+        for (Object child : parent.getChildren()) {
+            if (child instanceof UiElementEditPart) {
+                UiElementEditPart childPart = (UiElementEditPart) child;
+                Rectangle r = childPart.getBounds();
+                if (r.contains(point)) {
+                    
+                    float rx = ((float)(point.x - r.x) / (float)r.width ) - 0.5f;
+                    float ry = ((float)(point.y - r.y) / (float)r.height) - 0.5f;
+
+                    /*   TOP
+                     *  \   /
+                     *   \ /
+                     * L  X  R
+                     *   / \
+                     *  /   \
+                     *   BOT
+                     */
+
+                    int index = 0;
+                    if (Math.abs(rx) >= Math.abs(ry)) {
+                        if (rx < 0) {
+                            outInfo.direction = LEFT;
+                            index = 1;
+                        } else {
+                            outInfo.direction = RIGHT;
+                        }
+                    } else {
+                        if (ry < 0) {
+                            outInfo.direction = TOP;
+                            index = 1;
+                        } else {
+                            outInfo.direction = BOTTOM;
+                        }
+                    }
+
+                    outInfo.anchorIndex = index;
+                    outInfo.targetParts[index] = childPart;
+                    outInfo.targetParts[1 - index] = findClosestPart(childPart,
+                            outInfo.direction);
+
+                    return outInfo;
+                }
+                
+                computeClosest(point, childPart, sTempClosests, sTempMinDists, TOP);
+                computeClosest(point, childPart, sTempClosests, sTempMinDists, LEFT);
+                computeClosest(point, childPart, sTempClosests, sTempMinDists, BOTTOM);
+                computeClosest(point, childPart, sTempClosests, sTempMinDists, RIGHT);
+            }
+        }
+        
+        UiElementEditPart closest = null;
+        int minDist = Integer.MAX_VALUE;
+        int minDir = -1;
+        
+        for (int i = 0; i <= MAX_DIR; i++) {
+            if (sTempClosests[i] != null && sTempMinDists[i] < minDist) {
+                closest = sTempClosests[i];
+                minDist = sTempMinDists[i];
+                minDir = i;
+            }
+        }
+        
+        if (closest != null) {
+            int index = 0;
+            switch(minDir) {
+            case TOP:
+            case LEFT:
+                index = 0;
+                break;
+            case BOTTOM:
+            case RIGHT:
+                index = 1;
+                break;
+            }
+            outInfo.anchorIndex = index;
+            outInfo.targetParts[index] = closest;
+            outInfo.targetParts[1 - index] = findClosestPart(closest, sOppositeDirection[minDir]);
+            outInfo.direction = sOppositeDirection[minDir];
+            return outInfo;
+        }
+
+        return null;
+    }
+
+    /**
+     * Computes the highlight line for a drop on a RelativeLayout.
+     * <p/>
+     * The line is always placed on the side of the anchor part indicated by the
+     * direction. The direction always point from the anchor part to the drop point.
+     * <p/>
+     * If there's no anchor part, use the other one with a reversed direction.
+     * <p/>
+     * On output, this updates the {@link HighlightInfo}.
+     */
+    private static void computeRelativeLine(UiLayoutEditPart parentPart,
+            RelativeInfo relInfo,
+            HighlightInfo highlightInfo) {
+
+        UiElementEditPart[] parts = relInfo.targetParts;
+        int dir = relInfo.direction;
+        int index = relInfo.anchorIndex;
+        UiElementEditPart part = parts[index];
+
+        if (part == null) {
+            dir = sOppositeDirection[dir];
+            part = parts[1 - index];
+        }
+        if (part == null) {
+            // give up if both parts are null
+            return;
+        }
+
+        Rectangle r = part.getBounds();
+        Point p = null;
+        switch(dir) {
+        case TOP:
+            p = r.getTop();
+            break;
+        case BOTTOM:
+            p = r.getBottom();
+            break;
+        case LEFT:
+            p = r.getLeft();
+            break;
+        case RIGHT:
+            p = r.getRight();
+            break;
+        }
+
+        highlightInfo.anchorPoint = p;
+
+        r = parentPart.getBounds();
+        switch(dir) {
+        case TOP:
+        case BOTTOM:
+            // horizontal line with middle anchor point
+            highlightInfo.tempPoints[0].setLocation(0, p.y);
+            highlightInfo.tempPoints[1].setLocation(r.width, p.y);
+            highlightInfo.linePoints = highlightInfo.tempPoints;
+            highlightInfo.anchorPoint = p;
+            break;
+        case LEFT:
+        case RIGHT:
+            // vertical line with middle anchor point
+            highlightInfo.tempPoints[0].setLocation(p.x, 0);
+            highlightInfo.tempPoints[1].setLocation(p.x, r.height);
+            highlightInfo.linePoints = highlightInfo.tempPoints;
+            highlightInfo.anchorPoint = p;
+            break;
+        }
+    }
+
+    /**
+     * Given a certain reference point (drop point), computes the distance to the given
+     * part in the given direction. For example if direction is top, only accepts parts which
+     * bottom is above the reference point, computes their distance and then updates the
+     * current minimal distances and current closest parts arrays accordingly.
+     */
+    private static void computeClosest(Point refPoint,
+            UiElementEditPart compareToPart,
+            UiElementEditPart[] currClosests,
+            int[] currMinDists,
+            int direction) {
+        Rectangle r = compareToPart.getBounds();
+
+        Point p = null;
+        boolean usable = false;
+        
+        switch(direction) {
+        case TOP:
+            p = r.getBottom();
+            usable = p.y <= refPoint.y;
+            break;
+        case BOTTOM:
+            p = r.getTop();
+            usable = p.y >= refPoint.y;
+            break;
+        case LEFT:
+            p = r.getRight();
+            usable = p.x <= refPoint.x;
+            break;
+        case RIGHT:
+            p = r.getLeft();
+            usable = p.x >= refPoint.x;
+            break;
+        }
+
+        if (usable) {
+            int d = p.getDistance2(refPoint);
+            if (d < currMinDists[direction]) {
+                currMinDists[direction] = d;
+                currClosests[direction] = compareToPart;
+            }
+        }
+    }
+
+    /**
+     * Given a reference parts, finds the closest part in the parent in the given direction.
+     * For example if direction is top, finds the closest sibling part which is above the
+     * reference part and non-overlapping (they can touch.)
+     */
+    private static UiElementEditPart findClosestPart(UiElementEditPart referencePart,
+            int direction) {
+        if (referencePart == null || referencePart.getParent() == null) {
+            return null;
+        }
+        
+        Rectangle r = referencePart.getBounds();
+        Point ref = null;
+        switch(direction) {
+        case TOP:
+            ref = r.getTop();
+            break;
+        case BOTTOM:
+            ref = r.getBottom();
+            break;
+        case LEFT:
+            ref = r.getLeft();
+            break;
+        case RIGHT:
+            ref = r.getRight();
+            break;
+        }
+        
+        int minDist = Integer.MAX_VALUE;
+        UiElementEditPart closestPart = null;
+        
+        for (Object childPart : referencePart.getParent().getChildren()) {
+            if (childPart != referencePart && childPart instanceof UiElementEditPart) {
+                r = ((UiElementEditPart) childPart).getBounds();
+                Point p = null;
+                boolean usable = false;
+                
+                switch(direction) {
+                case TOP:
+                    p = r.getBottom();
+                    usable = p.y <= ref.y;
+                    break;
+                case BOTTOM:
+                    p = r.getTop();
+                    usable = p.y >= ref.y;
+                    break;
+                case LEFT:
+                    p = r.getRight();
+                    usable = p.x <= ref.x;
+                    break;
+                case RIGHT:
+                    p = r.getLeft();
+                    usable = p.x >= ref.x;
+                    break;
+                }
+
+                if (usable) {
+                    int d = p.getDistance2(ref);
+                    if (d < minDist) {
+                        minDist = d;
+                        closestPart = (UiElementEditPart) childPart;
+                    }
+                }
+            }
+        }
+        
+        return closestPart;
+    }
+
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java
new file mode 100644
index 0000000..d36d9f7
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementCreateCommand.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.AndroidEditor;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.layout.LayoutEditor;
+import com.android.ide.eclipse.editors.layout.LayoutEditor.UiEditorActions;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.commands.Command;
+
+/**
+ * A command that knows how to instantiate a new element based on a given {@link ElementDescriptor},
+ * the parent {@link UiElementEditPart} and an optional target location.
+ */
+public class ElementCreateCommand extends Command {
+
+    /** Descriptor of the new element to create */
+    private final ElementDescriptor mDescriptor;
+    /** The edit part that hosts the new edit part */
+    private final UiElementEditPart mParentPart;
+    /** The drop location in parent coordinates */
+    private final Point mTargetPoint;
+
+    /**
+     * Creates a new {@link ElementCreateCommand}.
+     * 
+     * @param descriptor Descriptor of the new element to create
+     * @param targetPart The edit part that hosts the new edit part
+     * @param targetPoint The drop location in parent coordinates
+     */
+    public ElementCreateCommand(ElementDescriptor descriptor,
+            UiElementEditPart targetPart, Point targetPoint) {
+                mDescriptor = descriptor;
+                mParentPart = targetPart;
+                mTargetPoint = targetPoint;
+    }
+    
+    // --- Methods inherited from Command ---
+
+    @Override
+    public boolean canExecute() {
+        return mDescriptor != null &&
+            mParentPart != null &&
+            mParentPart.getUiNode() != null &&
+            mParentPart.getUiNode().getEditor() instanceof LayoutEditor;
+    }
+
+    @Override
+    public void execute() {
+        super.execute();
+        UiElementNode uiParent = mParentPart.getUiNode();
+        if (uiParent != null) {
+            final AndroidEditor editor = uiParent.getEditor();
+            if (editor instanceof LayoutEditor) {
+                ((LayoutEditor) editor).wrapUndoRecording(
+                        String.format("Create %1$s", mDescriptor.getXmlLocalName()),
+                        new Runnable() {
+                    public void run() {
+                        UiEditorActions actions = ((LayoutEditor) editor).getUiEditorActions();
+                        if (actions != null) {
+                            DropFeedback.addElementToXml(mParentPart, mDescriptor, mTargetPoint,
+                                    actions);
+                        }
+                    }
+                });
+            }
+        }        
+    }
+
+    @Override
+    public void redo() {
+        throw new UnsupportedOperationException("redo not supported by this command"); //$NON-NLS-1$
+    }
+    
+    @Override
+    public void undo() {
+        throw new UnsupportedOperationException("undo not supported by this command"); //$NON-NLS-1$
+    }
+
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java
new file mode 100644
index 0000000..f863037
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/ElementFigure.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWT;
+
+    
+/**
+ * The figure used to draw basic elements.
+ * <p/>
+ * The figure is totally empty and transparent except for the selection border.
+ */
+class ElementFigure extends Figure {
+
+    private boolean mIsSelected;
+    private Rectangle mInnerBounds;
+
+    public ElementFigure() {
+        setOpaque(false);
+    }
+    
+    public void setSelected(boolean isSelected) {
+        if (isSelected != mIsSelected) {
+            mIsSelected = isSelected;
+            repaint();
+        }
+    }
+    
+    @Override
+    public void setBounds(Rectangle rect) {
+        super.setBounds(rect);
+        
+        mInnerBounds = getBounds().getCopy();
+        if (mInnerBounds.width > 0) {
+            mInnerBounds.width--;
+        }
+        if (mInnerBounds.height > 0) {
+            mInnerBounds.height--;
+        }
+    }
+    
+    public Rectangle getInnerBounds() {
+        return mInnerBounds;
+    }
+    
+    @Override
+    protected void paintBorder(Graphics graphics) {
+        super.paintBorder(graphics);
+
+        if (mIsSelected) {
+            graphics.setLineWidth(1);
+            graphics.setLineStyle(SWT.LINE_SOLID);
+            graphics.setForegroundColor(ColorConstants.red);
+            graphics.drawRectangle(getInnerBounds());
+        }
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java
new file mode 100644
index 0000000..55ed39b
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/LayoutFigure.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.layout.parts.UiLayoutEditPart.HighlightInfo;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWT;
+
+/**
+ * The figure used to draw the feedback on a layout.
+ * <p/>
+ * By default the figure is transparent and empty.
+ * The base {@link ElementFigure} knows how to draw the selection border.
+ * This figure knows how to draw the drop feedback.
+ */
+class LayoutFigure extends ElementFigure {
+
+    private HighlightInfo mHighlightInfo;
+    
+    public LayoutFigure() {
+        super();
+    }
+
+    public void setHighlighInfo(HighlightInfo highlightInfo) {
+        mHighlightInfo = highlightInfo;
+        repaint();
+    }
+
+    /**
+     * Paints the "border" for this figure.
+     * <p/>
+     * The parent {@link Figure#paint(Graphics)} calls {@link #paintFigure(Graphics)} then
+     * {@link #paintClientArea(Graphics)} then {@link #paintBorder(Graphics)}. Here we thus
+     * draw the actual highlight border but also the highlight anchor lines and points so that
+     * we can make sure they are all drawn on top of the border. 
+     * <p/>
+     * Note: This method doesn't really need to restore its graphic state. The parent
+     * Figure will do it for us.
+     * <p/>
+     * 
+     * @param graphics The Graphics object used for painting
+     */
+    @Override
+    protected void paintBorder(Graphics graphics) {
+        super.paintBorder(graphics);
+
+        if (mHighlightInfo == null) {
+            return;
+        }
+
+        // Draw the border. We want other highlighting to be drawn on top of the border.
+        if (mHighlightInfo.drawDropBorder) {
+            graphics.setLineWidth(3);
+            graphics.setLineStyle(SWT.LINE_SOLID);
+            graphics.setForegroundColor(ColorConstants.green);
+            graphics.drawRectangle(getInnerBounds().getCopy().shrink(1, 1));
+        }
+
+        Rectangle bounds = getBounds();
+        int bx = bounds.x;
+        int by = bounds.y;
+        int w = bounds.width;
+        int h = bounds.height;
+
+        // Draw frames of target child parts, if any
+        if (mHighlightInfo.childParts != null) {
+            graphics.setLineWidth(2);
+            graphics.setLineStyle(SWT.LINE_DOT);
+            graphics.setForegroundColor(ColorConstants.lightBlue);
+            for (UiElementEditPart part : mHighlightInfo.childParts) {
+                if (part != null) {
+                    graphics.drawRectangle(part.getBounds().getCopy().translate(bx, by));
+                }
+            }
+        }
+
+        // Draw the target line, if any
+        if (mHighlightInfo.linePoints != null) {
+            int x1 = mHighlightInfo.linePoints[0].x;
+            int y1 = mHighlightInfo.linePoints[0].y;
+            int x2 = mHighlightInfo.linePoints[1].x;
+            int y2 = mHighlightInfo.linePoints[1].y;
+            
+            // if the line is right to the edge, draw it one pixel more inside so that the
+            // full 2-pixel width be visible.
+            if (x1 <= 0) x1++;
+            if (x2 <= 0) x2++;
+            if (y1 <= 0) y1++;
+            if (y2 <= 0) y2++;
+
+            if (x1 >= w - 1) x1--;
+            if (x2 >= w - 1) x2--;
+            if (y1 >= h - 1) y1--;
+            if (y2 >= h - 1) y2--;
+            
+            x1 += bx;
+            x2 += bx;
+            y1 += by;
+            y2 += by;
+            
+            graphics.setLineWidth(2);
+            graphics.setLineStyle(SWT.LINE_DASH);
+            graphics.setLineCap(SWT.CAP_ROUND);
+            graphics.setForegroundColor(ColorConstants.orange);
+            graphics.drawLine(x1, y1, x2, y2);
+        }
+
+        // Draw the anchor point, if any
+        if (mHighlightInfo.anchorPoint != null) {
+            int x = mHighlightInfo.anchorPoint.x;
+            int y = mHighlightInfo.anchorPoint.y;
+
+            // If the point is right on the edge, draw it one pixel inside so that it
+            // matches the highlight line. It makes it slightly more visible that way.
+            if (x <= 0) x++;
+            if (y <= 0) y++;
+            if (x >= w - 1) x--;
+            if (y >= h - 1) y--;
+            x += bx;
+            y += by;
+
+            graphics.setLineWidth(2);
+            graphics.setLineStyle(SWT.LINE_SOLID);
+            graphics.setLineCap(SWT.CAP_ROUND);
+            graphics.setForegroundColor(ColorConstants.orange);
+            graphics.drawLine(x-5, y-5, x+5, y+5);
+            graphics.drawLine(x-5, y+5, x+5, y-5);
+            // 7 * cos(45) == 5 so we use 8 for the circle radius (it looks slightly better than 7)
+            graphics.setLineWidth(1);
+            graphics.drawOval(x-8, y-8, 16, 16);
+        }
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
similarity index 66%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
index 53a87f5..2f7636d 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentEditPart.java
@@ -27,7 +27,14 @@
 import org.eclipse.draw2d.IFigure;
 import org.eclipse.draw2d.Label;
 import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.Point;
 import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.editpolicies.RootComponentEditPolicy;
+import org.eclipse.gef.requests.DropRequest;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.ImageData;
 import org.eclipse.swt.graphics.PaletteData;
@@ -149,4 +156,57 @@
     protected void showSelection() {
         // no selection at this level.
     }
+    
+    @Override
+    protected void createEditPolicies() {
+        super.createEditPolicies();
+
+        // This policy indicates this a root component that cannot be removed
+        installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
+
+        installLayoutEditPolicy(this);
+    }
+
+    /**
+     * Returns the EditPart that should be used as the target for the specified Request. 
+     * For instance this is called during drag'n'drop with a CreateRequest.
+     * <p/>
+     * For the root document, we want the first child edit part to the be the target
+     * since an XML document can have only one root element.
+     * 
+     * {@inheritDoc}
+     */
+    @Override
+    public EditPart getTargetEditPart(Request request) {
+        if (request != null && request.getType() == RequestConstants.REQ_CREATE) {
+            // We refuse the drop if it's not in the bounds of the document.
+            if (request instanceof DropRequest) {
+                Point where = ((DropRequest) request).getLocation().getCopy();
+                UiElementNode uiNode = getUiNode();
+                if (uiNode instanceof UiDocumentNode) {
+                    // Take the bounds of the background image as the valid drop zone
+                    Object editData = uiNode.getEditData();
+                    if (editData instanceof BufferedImage) {
+                        BufferedImage image = (BufferedImage)editData;
+                        int w = image.getWidth();
+                        int h = image.getHeight();
+                        if (where.x > w || where.y > h) {
+                            return null;
+                        }
+                    }
+                    
+                }
+            }
+
+            // For the root document, we want the first child edit part to the be the target
+            // since an XML document can have only one root element.
+            if (getChildren().size() > 0) {
+                Object o = getChildren().get(0);
+                if (o instanceof EditPart) {
+                    return ((EditPart) o).getTargetEditPart(request);
+                }
+            }
+        }
+        return super.getTargetEditPart(request);
+    }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiDocumentTreeEditPart.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
new file mode 100644
index 0000000..d873005
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.gef.editpolicies.LayoutEditPolicy;
+import org.eclipse.gef.editpolicies.SelectionEditPolicy;
+import org.eclipse.gef.requests.CreateRequest;
+import org.eclipse.gef.requests.DropRequest;
+import org.eclipse.gef.tools.SelectEditPartTracker;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * An {@link EditPart} for a {@link UiElementNode}.
+ */
+public abstract class UiElementEditPart extends AbstractGraphicalEditPart
+    implements IUiUpdateListener {
+    
+    public UiElementEditPart(UiElementNode uiElementNode) {
+        setModel(uiElementNode);
+    }
+
+    //-------------------------
+    // Derived classes must define these
+
+    abstract protected void hideSelection();
+    abstract protected void showSelection();
+
+    //-------------------------
+    // Base class overrides
+    
+    @Override
+    public DragTracker getDragTracker(Request request) {
+        return new SelectEditPartTracker(this);
+    }
+
+    @Override
+    protected void createEditPolicies() {
+        /*
+         * This is no longer needed, as a selection edit policy is set by the parent layout.
+         * Leave this code commented out right now, I'll want to play with this later.
+         * 
+        installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE,
+                new NonResizableSelectionEditPolicy(this));
+         */
+    }
+    
+    /* (non-javadoc)
+     * Returns a List containing the children model objects.
+     * Must not return null, instead use the super which returns an empty list.
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    protected List getModelChildren() {
+        return getUiNode().getUiChildren();
+    }
+
+    @Override
+    public void activate() {
+        super.activate();
+        getUiNode().addUpdateListener(this);
+    }
+    
+    @Override
+    public void deactivate() {
+        super.deactivate();
+        getUiNode().removeUpdateListener(this);
+    }
+
+    @Override
+    protected void refreshVisuals() {
+        if (getFigure().getParent() != null) {
+            ((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), getBounds());
+        }
+        
+        // update the visuals of the children as well
+        refreshChildrenVisuals();
+    }
+    
+    protected void refreshChildrenVisuals() {
+        if (children != null) {
+            for (Object child : children) {
+                if (child instanceof UiElementEditPart) {
+                    UiElementEditPart childPart = (UiElementEditPart)child;
+                    childPart.refreshVisuals();
+                }
+            }
+        }
+    }
+
+    //-------------------------
+    // IUiUpdateListener implementation
+
+    public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
+        // TODO: optimize by refreshing only when needed
+        switch(state) {
+        case ATTR_UPDATED:
+            refreshVisuals();
+            break;
+        case CHILDREN_CHANGED:
+            refreshChildren();
+            
+            // new children list, need to update the layout
+            refreshVisuals();
+            break;
+        case CREATED:
+            refreshVisuals();
+            break;
+        case DELETED:
+            // pass
+            break;
+        }
+    }
+
+    //-------------------------
+    // Local methods
+
+    /** @return The object model casted to an {@link UiElementNode} */
+    public final UiElementNode getUiNode() {
+        return (UiElementNode) getModel();
+    }
+    
+    protected final ElementDescriptor getDescriptor() {
+        return getUiNode().getDescriptor();
+    }
+    
+    protected final UiElementEditPart getEditPartParent() {
+        EditPart parent = getParent();
+        if (parent instanceof UiElementEditPart) {
+            return (UiElementEditPart)parent; 
+        }
+        return null;
+    }
+    
+    /**
+     * Returns a given XML attribute.
+     * @param attrName The local name of the attribute.
+     * @return the attribute as a {@link String}, if it exists, or <code>null</code>
+     */
+    protected final String getStringAttr(String attrName) {
+        UiElementNode uiNode = getUiNode();
+        if (uiNode.getXmlNode() != null) {
+            Node xmlNode = uiNode.getXmlNode();
+            if (xmlNode != null) {
+                NamedNodeMap nodeAttributes = xmlNode.getAttributes();
+                if (nodeAttributes != null) {
+                    Node attr = nodeAttributes.getNamedItemNS(
+                            AndroidConstants.NS_RESOURCES, attrName);
+                    if (attr != null) {
+                        return attr.getNodeValue();
+                    }
+                }
+            }
+        }
+        return null;
+    }
+    
+    protected final Rectangle getBounds() {
+        UiElementNode model = (UiElementNode)getModel();
+        
+        Object editData = model.getEditData();
+
+        if (editData != null) {
+            // assert with fully qualified class name to prevent import changes to another
+            // Rectangle class.
+            assert (editData instanceof org.eclipse.draw2d.geometry.Rectangle);
+    
+            return (Rectangle)editData;
+        }
+
+        // return a dummy rect
+        return new Rectangle(0, 0, 0, 0);
+    }
+
+    /**
+     * Returns the EditPart that should be used as the target for the specified Request. 
+     * <p/>
+     * For instance this is called during drag'n'drop with a CreateRequest.
+     * <p/>
+     * Reject being a target for elements which descriptor does not allow children.
+     * 
+     * {@inheritDoc}
+     */
+    @Override
+    public EditPart getTargetEditPart(Request request) {
+        if (request != null && request.getType() == RequestConstants.REQ_CREATE) {
+            // Reject being a target for elements which descriptor does not allow children.
+            if (!getUiNode().getDescriptor().hasChildren()) {
+                return null;
+            }
+        }
+        return super.getTargetEditPart(request);
+    }
+
+    /**
+     * Used by derived classes {@link UiDocumentEditPart} and {@link UiLayoutEditPart}
+     * to accept drag'n'drop of new items from the palette.
+     * 
+     * @param layoutEditPart The layout edit part where this policy is installed. It can
+     *        be either a {@link UiDocumentEditPart} or a {@link UiLayoutEditPart}.
+     */
+    protected void installLayoutEditPolicy(final UiElementEditPart layoutEditPart) {
+        // This policy indicates how elements can be constrained by the layout.
+        // TODO Right now we use the XY layout policy since our constraints are
+        // handled by the android rendering engine rather than GEF. Tweak as
+        // appropriate.
+        installEditPolicy(EditPolicy.LAYOUT_ROLE,  new LayoutEditPolicy() {
+
+            /**
+             * We don't allow layout children to be resized yet.
+             * <p/>
+             * Typical choices would be:
+             * <ul>
+             * <li> ResizableEditPolicy, to allow for selection, move and resize.
+             * <li> NonResizableEditPolicy, to allow for selection, move but not resize.
+             * <li> SelectionEditPolicy to allow for only selection.
+             * </ul>
+             * <p/>
+             * TODO: make this depend on the part layout. For an AbsoluteLayout we should
+             * probably use a NonResizableEditPolicy and SelectionEditPolicy for the rest.
+             * Whether to use ResizableEditPolicy or NonResizableEditPolicy should depend
+             * on the child in an AbsoluteLayout.
+             */
+            @Override
+            protected EditPolicy createChildEditPolicy(EditPart child) {
+                if (child instanceof UiElementEditPart) {
+                    return new NonResizableSelectionEditPolicy((UiElementEditPart) child);
+                }
+                return null;
+            }
+
+            @Override
+            protected Command getCreateCommand(CreateRequest request) {
+                // We store the ElementDescriptor in the request.factory.type
+                Object newType = request.getNewObjectType();
+                if (newType instanceof ElementDescriptor) {
+                    Point where = request.getLocation().getCopy();
+                    Point origin = getLayoutContainer().getClientArea().getLocation();
+                    where.translate(origin.getNegated());
+                    
+                    // The host is the EditPart where this policy is installed,
+                    // e.g. this UiElementEditPart.
+                    EditPart host = getHost();
+                    if (host instanceof UiElementEditPart) {
+                        
+                        return new ElementCreateCommand((ElementDescriptor) newType,
+                                (UiElementEditPart) host,
+                                where);
+                    }
+                }
+                
+                return null;
+            }
+
+            @Override
+            protected Command getMoveChildrenCommand(Request request) {
+                // TODO Auto-generated method stub
+                return null;
+            }
+            
+            @Override
+            public void showLayoutTargetFeedback(Request request) {
+                super.showLayoutTargetFeedback(request);
+                
+                // for debugging
+                // System.out.println("target: " + request.toString() + " -- " + layoutEditPart.getUiNode().getBreadcrumbTrailDescription(false));
+                
+                if (layoutEditPart instanceof UiLayoutEditPart &&
+                        request instanceof DropRequest) {
+                    Point where = ((DropRequest) request).getLocation().getCopy();
+                    Point origin = getLayoutContainer().getClientArea().getLocation();
+                    where.translate(origin.getNegated());
+
+                    ((UiLayoutEditPart) layoutEditPart).showDropTarget(where);
+                }
+            }
+
+            @Override
+            protected void eraseLayoutTargetFeedback(Request request) {
+                super.eraseLayoutTargetFeedback(request);
+                if (layoutEditPart instanceof UiLayoutEditPart) {
+                    ((UiLayoutEditPart) layoutEditPart).hideDropTarget();
+                }
+            }
+            
+            @Override
+            protected IFigure createSizeOnDropFeedback(CreateRequest createRequest) {
+                // TODO understand if this is useful for us or remove
+                return super.createSizeOnDropFeedback(createRequest);
+            }
+            
+        });
+    }
+    
+    protected static class NonResizableSelectionEditPolicy extends SelectionEditPolicy {
+        
+        private final UiElementEditPart mEditPart;
+
+        public NonResizableSelectionEditPolicy(UiElementEditPart editPart) {
+            mEditPart = editPart;
+        }
+        
+        @Override
+        protected void hideSelection() {
+            mEditPart.hideSelection();
+        }
+
+        @Override
+        protected void showSelection() {
+            mEditPart.showSelection();
+        }
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPart.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementTreeEditPartFactory.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiElementsEditPartFactory.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
new file mode 100644
index 0000000..43a70a5
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2008 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.editors.layout.parts;
+
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.XYLayout;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editpolicies.ContainerEditPolicy;
+import org.eclipse.gef.requests.CreateRequest;
+
+/**
+ * Graphical edit part for an {@link UiElementNode} that represents a ViewLayout.
+ * <p/>
+ * It acts as a simple container. 
+ */
+public final class UiLayoutEditPart extends UiElementEditPart {
+    
+    static class HighlightInfo {
+        public boolean drawDropBorder;
+        public UiElementEditPart[] childParts;
+        public Point anchorPoint;
+        public Point linePoints[];
+
+        public final Point tempPoints[] = new Point[] { new Point(), new Point() };
+
+        public void clear() {
+            drawDropBorder = false;
+            childParts = null;
+            anchorPoint = null;
+            linePoints = null;
+        }
+    }
+    
+    private final HighlightInfo mHighlightInfo = new HighlightInfo();
+    
+    public UiLayoutEditPart(UiElementNode uiElementNode) {
+        super(uiElementNode);
+    }
+    
+    @Override
+    protected void createEditPolicies() {
+        super.createEditPolicies();
+        
+        installEditPolicy(EditPolicy.CONTAINER_ROLE, new ContainerEditPolicy() {
+            @Override
+            protected Command getCreateCommand(CreateRequest request) {
+                return null;
+            }
+        });
+        
+        installLayoutEditPolicy(this);
+    }
+
+    @Override
+    protected IFigure createFigure() {
+        IFigure f = new LayoutFigure();
+        f.setLayoutManager(new XYLayout());
+        return f;
+    }
+
+    @Override
+    protected void showSelection() {
+        IFigure f = getFigure();
+        if (f instanceof ElementFigure) {
+            ((ElementFigure) f).setSelected(true);
+        }
+    }
+
+    @Override
+    protected void hideSelection() {
+        IFigure f = getFigure();
+        if (f instanceof ElementFigure) {
+            ((ElementFigure) f).setSelected(false);
+        }
+    }
+
+    public void showDropTarget(Point where) {
+        if (where != null) {
+            mHighlightInfo.clear();
+            mHighlightInfo.drawDropBorder = true;
+            DropFeedback.computeDropFeedback(this, mHighlightInfo, where);
+
+            IFigure f = getFigure();
+            if (f instanceof LayoutFigure) {
+                ((LayoutFigure) f).setHighlighInfo(mHighlightInfo);
+            }
+        }
+    }
+
+    public void hideDropTarget() {
+        mHighlightInfo.clear();
+        IFigure f = getFigure();
+        if (f instanceof LayoutFigure) {
+            ((LayoutFigure) f).setHighlighInfo(mHighlightInfo);
+        }
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutTreeEditPart.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
similarity index 80%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
index b427ead..05329f3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewEditPart.java
@@ -18,10 +18,8 @@
 
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
 
-import org.eclipse.draw2d.ColorConstants;
 import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.Label;
-import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.XYLayout;
 
 /**
  * Graphical edit part for an {@link UiElementNode} that represents a View.
@@ -31,26 +29,27 @@
     public UiViewEditPart(UiElementNode uiElementNode) {
         super(uiElementNode);
     }
-    
+
     @Override
     protected IFigure createFigure() {
-        Label f = new Label();
+        IFigure f = new ElementFigure();
+        f.setLayoutManager(new XYLayout());
         return f;
     }
-    
-    @Override
-    protected void hideSelection() {
-        IFigure f = getFigure();
-        if (f instanceof Label) {
-            f.setBorder(null);
-        }
-    }
 
     @Override
     protected void showSelection() {
         IFigure f = getFigure();
-        if (f instanceof Label) {
-            f.setBorder(new LineBorder(ColorConstants.red, 1));
+        if (f instanceof ElementFigure) {
+            ((ElementFigure) f).setSelected(true);
+        }
+    }
+
+    @Override
+    protected void hideSelection() {
+        IFigure f = getFigure();
+        if (f instanceof ElementFigure) {
+            ((ElementFigure) f).setSelected(false);
         }
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/parts/UiViewTreeEditPart.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
similarity index 76%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
index 75cf4b6..45cbc77 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/uimodel/UiViewElementNode.java
@@ -16,14 +16,20 @@
 
 package com.android.ide.eclipse.editors.layout.uimodel;
 
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
 import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
 import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import com.android.sdklib.IAndroidTarget;
+
+import org.eclipse.core.resources.IProject;
+
+import java.util.List;
 
 /**
  * Specialized version of {@link UiElementNode} for the {@link ViewElementDescriptor}s.
@@ -59,12 +65,26 @@
             // Limitation: right now the layout behaves as if everything was
             // owned by a FrameLayout.
             // TODO replace by something user-configurable.
-            for (ElementDescriptor desc : LayoutDescriptors.getInstance().getLayoutDescriptors()) {
-                if (desc instanceof ViewElementDescriptor &&
-                        desc.getXmlName().equals(AndroidConstants.CLASS_FRAMELAYOUT)) {
-                    layout_attrs = ((ViewElementDescriptor) desc).getLayoutAttributes();
-                    need_xmlns = true;
-                    break;
+
+            List<ElementDescriptor> layoutDescriptors = null;
+            IProject project = getEditor().getProject();
+            if (project != null) {
+                Sdk currentSdk = Sdk.getCurrent();
+                IAndroidTarget target = currentSdk.getTarget(project);
+                if (target != null) {
+                    AndroidTargetData data = currentSdk.getTargetData(target);
+                    layoutDescriptors = data.getLayoutDescriptors().getLayoutDescriptors();
+                }
+            }
+            
+            if (layoutDescriptors != null) {
+                for (ElementDescriptor desc : layoutDescriptors) {
+                    if (desc instanceof ViewElementDescriptor &&
+                            desc.getXmlName().equals(AndroidConstants.CLASS_FRAMELAYOUT)) {
+                        layout_attrs = ((ViewElementDescriptor) desc).getLayoutAttributes();
+                        need_xmlns = true;
+                        break;
+                    }
                 }
             }
         } else if (ui_parent instanceof UiViewElementNode){
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
similarity index 79%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
index e43c984..b40e458 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestContentAssist.java
@@ -16,9 +16,8 @@
 
 package com.android.ide.eclipse.editors.manifest;
 
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
 
 /**
  * Content Assist Processor for AndroidManifest.xml
@@ -29,6 +28,6 @@
      * Constructor for ManifestContentAssist 
      */
     public ManifestContentAssist() {
-        super(new ElementDescriptor[] { AndroidManifestDescriptors.MANIFEST_ELEMENT });
+        super(AndroidTargetData.DESCRIPTOR_MANIFEST);
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
similarity index 66%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
index 666a066..d0f8d7b 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditor.java
@@ -16,10 +16,11 @@
 
 package com.android.ide.eclipse.editors.manifest;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidXPathFactory;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
 import com.android.ide.eclipse.editors.manifest.pages.ApplicationPage;
@@ -59,19 +60,30 @@
     
     /** Root node of the UI element hierarchy */
     private UiElementNode mUiManifestNode;
-    /** Listener to update the root node if the resource framework changes */
-    private Runnable mResourceRefreshListener;
     /** The Application Page tab */
     private ApplicationPage mAppPage;
     /** The Overview Manifest Page tab */
     private OverviewPage mOverviewPage;
+    /** The Permission Page tab */
+    private PermissionPage mPermissionPage;
+    /** The Instrumentation Page tab */
+    private InstrumentationPage mInstrumentationPage;
+    
+    private IFileListener mMarkerMonitor;
+    
 
     /**
      * Creates the form editor for AndroidManifest.xml.
      */
     public ManifestEditor() {
         super();
-        initUiManifestNode();
+    }
+    
+    @Override
+    public void dispose() {
+        super.dispose();
+
+        ResourceMonitor.getMonitor().removeFileListener(mMarkerMonitor);
     }
 
     /**
@@ -83,16 +95,19 @@
         return mUiManifestNode;
     }
     
-    // ---- Base Class Overrides ----
-
-    @Override
-    public void dispose() {
-        if (mResourceRefreshListener != null) {
-            EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
-            mResourceRefreshListener = null;
+    /**
+     * Returns the Manifest descriptors for the file being edited.
+     */
+    public AndroidManifestDescriptors getManifestDescriptors() {
+        AndroidTargetData data = getTargetData();
+        if (data != null) {
+            return data.getManifestDescriptors();
         }
-        super.dispose();
+        
+        return null;
     }
+    
+    // ---- Base Class Overrides ----
 
     /**
      * Returns whether the "save as" operation is supported by this editor.
@@ -115,10 +130,10 @@
         try {
             addPage(mOverviewPage = new OverviewPage(this));
             addPage(mAppPage = new ApplicationPage(this));
-            addPage(new PermissionPage(this));
-            addPage(new InstrumentationPage(this));
+            addPage(mPermissionPage = new PermissionPage(this));
+            addPage(mInstrumentationPage = new InstrumentationPage(this));
         } catch (PartInitException e) {
-            EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+            AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
         }
     }
 
@@ -130,6 +145,7 @@
         super.setInput(input);
         IFile inputFile = getInputFile();
         if (inputFile != null) {
+            startMonitoringMarkers();
             setPartName(String.format("%1$s Manifest", inputFile.getProject().getName()));
         }
     }
@@ -141,29 +157,54 @@
      */
     @Override
     protected void xmlModelChanged(Document xml_doc) {
-        mUiManifestNode.setXmlDocument(xml_doc);
-        if (xml_doc != null) {
+        // create the ui root node on demand.
+        initUiRootNode(false /*force*/);
+        
+        loadFromXml(xml_doc);
+        
+        super.xmlModelChanged(xml_doc);
+    }
+    
+    private void loadFromXml(Document xmlDoc) {
+        mUiManifestNode.setXmlDocument(xmlDoc);
+        if (xmlDoc != null) {
             ElementDescriptor manifest_desc = mUiManifestNode.getDescriptor();
             try {
                 XPath xpath = AndroidXPathFactory.newXPath();
                 Node node = (Node) xpath.evaluate("/" + manifest_desc.getXmlName(),  //$NON-NLS-1$
-                        xml_doc,
+                        xmlDoc,
                         XPathConstants.NODE);
                 assert node != null && node.getNodeName().equals(manifest_desc.getXmlName());
 
                 // Refresh the manifest UI node and all its descendants 
                 mUiManifestNode.loadFromXmlNode(node);
-                
-                startMonitoringMarkers();
             } catch (XPathExpressionException e) {
-                EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+                AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
                         manifest_desc.getXmlName());
             }
         }
-        
-        super.xmlModelChanged(xml_doc);
     }
     
+    private void onDescriptorsChanged(UiElementNode oldManifestNode) {
+        mUiManifestNode.reloadFromXmlNode(oldManifestNode.getXmlNode());
+
+        if (mOverviewPage != null) {
+            mOverviewPage.refreshUiApplicationNode();
+        }
+
+        if (mAppPage != null) {
+            mAppPage.refreshUiApplicationNode();
+        }
+        
+        if (mPermissionPage != null) {
+            mPermissionPage.refreshUiNode();
+        }
+        
+        if (mInstrumentationPage != null) {
+            mInstrumentationPage.refreshUiNode();
+        }
+    }
+
     /**
      * Reads and processes the current markers and adds a listener for marker changes. 
      */
@@ -172,13 +213,15 @@
         if (inputFile != null) {
             updateFromExistingMarkers(inputFile);
             
-            ResourceMonitor.getMonitor().addFileListener(new IFileListener() {
+            mMarkerMonitor = new IFileListener() {
                 public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
                     if (file.equals(inputFile)) {
                         processMarkerChanges(markerDeltas);
                     }
                 }
-            }, IResourceDelta.CHANGED);
+            };
+            
+            ResourceMonitor.getMonitor().addFileListener(mMarkerMonitor, IResourceDelta.CHANGED);
         }
     }
 
@@ -192,14 +235,22 @@
             // get the markers for the file
             IMarker[] markers = inputFile.findMarkers(AndroidConstants.MARKER_ANDROID, true,
                     IResource.DEPTH_ZERO);
+            
+            AndroidManifestDescriptors desc = getManifestDescriptors();
+            if (desc != null) {
+                ElementDescriptor appElement = desc.getApplicationElement();
+                
+                if (appElement != null) {
+                    UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
+                            appElement.getXmlName());
+                    List<UiElementNode> children = app_ui_node.getUiChildren();
 
-            UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
-                    AndroidManifestDescriptors.APPLICATION_ELEMENT.getXmlName());
-            List<UiElementNode> children = app_ui_node.getUiChildren();
-
-            for (IMarker marker : markers) {
-                processMarker(marker, children, IResourceDelta.ADDED);
+                    for (IMarker marker : markers) {
+                        processMarker(marker, children, IResourceDelta.ADDED);
+                    }
+                }
             }
+            
         } catch (CoreException e) {
             // findMarkers can throw an exception, in which case, we'll do nothing.
         }
@@ -210,12 +261,15 @@
      * @param markerDeltas the list of {@link IMarkerDelta}
      */
     private void processMarkerChanges(IMarkerDelta[] markerDeltas) {
-        UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
-                AndroidManifestDescriptors.APPLICATION_ELEMENT.getXmlName());
-        List<UiElementNode> children = app_ui_node.getUiChildren();
-
-        for (IMarkerDelta markerDelta : markerDeltas) {
-            processMarker(markerDelta.getMarker(), children, markerDelta.getKind());
+        AndroidManifestDescriptors descriptors = getManifestDescriptors();
+        if (descriptors != null && descriptors.getApplicationElement() != null) {
+            UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
+                    descriptors.getApplicationElement().getXmlName());
+            List<UiElementNode> children = app_ui_node.getUiChildren();
+    
+            for (IMarkerDelta markerDelta : markerDeltas) {
+                processMarker(markerDelta.getMarker(), children, markerDelta.getKind());
+            }
         }
     }
 
@@ -259,56 +313,62 @@
 
     /**
      * Creates the initial UI Root Node, including the known mandatory elements.
+     * @param force if true, a new UiManifestNode is recreated even if it already exists.
      */
-    private void initUiManifestNode() {
+    @Override
+    protected void initUiRootNode(boolean force) {
         // The manifest UI node is always created, even if there's no corresponding XML node.
-        if (mUiManifestNode == null) {
-            ElementDescriptor manifest_desc = AndroidManifestDescriptors.MANIFEST_ELEMENT;   
-            mUiManifestNode = manifest_desc.createUiNode();
+        if (mUiManifestNode != null && force == false) {
+            return;
+        }
+
+        
+        AndroidManifestDescriptors manifestDescriptor = getManifestDescriptors();
+        
+        if (manifestDescriptor != null) {
+            // save the old manifest node if it exists
+            UiElementNode oldManifestNode = mUiManifestNode;
+
+            ElementDescriptor manifestElement = manifestDescriptor.getManifestElement();   
+            mUiManifestNode = manifestElement.createUiNode();
             mUiManifestNode.setEditor(this);
     
             // Similarly, always create the /manifest/application and /manifest/uses-sdk nodes
-            ElementDescriptor app_desc = AndroidManifestDescriptors.APPLICATION_ELEMENT;
+            ElementDescriptor appElement = manifestDescriptor.getApplicationElement();
             boolean present = false;
             for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) {
-                if (ui_node.getDescriptor() == app_desc) {
+                if (ui_node.getDescriptor() == appElement) {
                     present = true;
                     break;
                 }
             }
             if (!present) {
-                mUiManifestNode.appendNewUiChild(app_desc);
+                mUiManifestNode.appendNewUiChild(appElement);
             }
 
-            app_desc = AndroidManifestDescriptors.USES_SDK_ELEMENT;
+            appElement = manifestDescriptor.getUsesSdkElement();
             present = false;
             for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) {
-                if (ui_node.getDescriptor() == app_desc) {
+                if (ui_node.getDescriptor() == appElement) {
                     present = true;
                     break;
                 }
             }
             if (!present) {
-                mUiManifestNode.appendNewUiChild(app_desc);
+                mUiManifestNode.appendNewUiChild(appElement);
             }
 
-            // Add a listener to refresh the root node if the resource framework changes
-            // by forcing it to parse its own XML
-            mResourceRefreshListener = new Runnable() {
-                public void run() {
-                    commitPages(false /* onSave */);
-
-                    mUiManifestNode.reloadFromXmlNode(mUiManifestNode.getXmlNode());
-                    if (mOverviewPage != null) {
-                        mOverviewPage.refreshUiApplicationNode();
-                    }
-                    if (mAppPage != null) {
-                        mAppPage.refreshUiApplicationNode();
-                    }
-                }
-            };
-            EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
-            mResourceRefreshListener.run();
+            if (oldManifestNode != null) {
+                onDescriptorsChanged(oldManifestNode);
+            }
+        } else {
+            // create a dummy descriptor/uinode until we have real descriptors
+            ElementDescriptor desc = new ElementDescriptor("manifest", //$NON-NLS-1$
+                    "temporary descriptors due to missing decriptors", //$NON-NLS-1$
+                    null /*tooltip*/, null /*sdk_url*/, null /*attributes*/,
+                    null /*children*/, false /*mandatory*/);
+            mUiManifestNode = desc.createUiNode();
+            mUiManifestNode.setEditor(this);
         }
     }
     
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestEditorContributor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/ManifestSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
similarity index 88%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
index 171eaee..87a14ad 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/AndroidManifestDescriptors.java
@@ -16,17 +16,18 @@
 
 package com.android.ide.eclipse.editors.manifest.descriptors;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.resources.DeclareStyleableInfo;
 import com.android.ide.eclipse.common.resources.ResourceType;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
 import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.ReferenceAttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
 
 import org.eclipse.core.runtime.IStatus;
 
@@ -45,7 +46,7 @@
  * However their sub-elements and attributes are created only when the SDK changes or is
  * loaded the first time.
  */
-public class AndroidManifestDescriptors {
+public final class AndroidManifestDescriptors implements IDescriptorProvider {
 
     private static final String MANIFEST_NODE_NAME = "manifest";                //$NON-NLS-1$
     private static final String ANDROID_MANIFEST_STYLEABLE = "AndroidManifest"; //$NON-NLS-1$
@@ -57,28 +58,28 @@
     public static final String PACKAGE_ATTR       = "package";  //$NON-NLS-1$
 
     /** The {@link ElementDescriptor} for the root Manifest element. */
-    public static final ElementDescriptor MANIFEST_ELEMENT;
+    private final ElementDescriptor MANIFEST_ELEMENT;
     /** The {@link ElementDescriptor} for the root Application element. */
-    public static final ElementDescriptor APPLICATION_ELEMENT;
+    private final ElementDescriptor APPLICATION_ELEMENT;
 
     /** The {@link ElementDescriptor} for the root Instrumentation element. */
-    public static final ElementDescriptor INTRUMENTATION_ELEMENT;
+    private final ElementDescriptor INTRUMENTATION_ELEMENT;
     /** The {@link ElementDescriptor} for the root Permission element. */
-    public static final ElementDescriptor PERMISSION_ELEMENT;
+    private final ElementDescriptor PERMISSION_ELEMENT;
     /** The {@link ElementDescriptor} for the root UsesPermission element. */
-    public static final ElementDescriptor USES_PERMISSION_ELEMENT;
+    private final ElementDescriptor USES_PERMISSION_ELEMENT;
     /** The {@link ElementDescriptor} for the root UsesSdk element. */
-    public static final ElementDescriptor USES_SDK_ELEMENT;
+    private final ElementDescriptor USES_SDK_ELEMENT;
 
     /** The {@link ElementDescriptor} for the root PermissionGroup element. */
-    public static final ElementDescriptor PERMISSION_GROUP_ELEMENT;
+    private final ElementDescriptor PERMISSION_GROUP_ELEMENT;
     /** The {@link ElementDescriptor} for the root PermissionTree element. */
-    public static final ElementDescriptor PERMISSION_TREE_ELEMENT;
+    private final ElementDescriptor PERMISSION_TREE_ELEMENT;
 
     /** Private package attribute for the manifest element. Needs to be handled manually. */
-    private static final TextAttributeDescriptor PACKAGE_ATTR_DESC;
+    private final TextAttributeDescriptor PACKAGE_ATTR_DESC;
     
-    static {
+    public AndroidManifestDescriptors() {
         APPLICATION_ELEMENT = createElement("application", null, true); //$NON-NLS-1$ + no child & mandatory
         INTRUMENTATION_ELEMENT = createElement("instrumentation"); //$NON-NLS-1$
 
@@ -109,6 +110,46 @@
                 null /* nsUri */,
                 "This attribute gives a unique name for the package, using a Java-style naming convention to avoid name collisions.\nFor example, applications published by Google could have names of the form com.google.app.appname");
     }
+    
+    public ElementDescriptor[] getRootElementDescriptors() {
+        return new ElementDescriptor[] { MANIFEST_ELEMENT };
+    }
+    
+    public ElementDescriptor getDescriptor() {
+        return getManifestElement();
+    }
+    
+    public ElementDescriptor getApplicationElement() {
+        return APPLICATION_ELEMENT;
+    }
+    
+    public ElementDescriptor getManifestElement() {
+        return MANIFEST_ELEMENT;
+    }
+    
+    public ElementDescriptor getUsesSdkElement() {
+        return USES_SDK_ELEMENT;
+    }
+    
+    public ElementDescriptor getInstrumentationElement() {
+        return INTRUMENTATION_ELEMENT;
+    }
+    
+    public ElementDescriptor getPermissionElement() {
+        return PERMISSION_ELEMENT;
+    }
+    
+    public ElementDescriptor getUsesPermissionElement() {
+        return USES_PERMISSION_ELEMENT;
+    }
+    
+    public ElementDescriptor getPermissionGroupElement() {
+        return PERMISSION_GROUP_ELEMENT;
+    }
+    
+    public ElementDescriptor getPermissionTreeElement() {
+        return PERMISSION_TREE_ELEMENT;
+    }
 
     /**
      * Updates the document descriptor.
@@ -118,7 +159,7 @@
      * 
      * @param manifestMap The map style => attributes from the attrs_manifest.xml file
      */
-    public static synchronized void updateDescriptors(
+    public synchronized void updateDescriptors(
             Map<String, DeclareStyleableInfo> manifestMap) {
 
         XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(
@@ -177,7 +218,7 @@
         
         sanityCheck(manifestMap, MANIFEST_ELEMENT);
     }
-
+    
     /**
      * Sets up an attribute override for ANDROID_NAME_ATTR using a ClassAttributeDescriptor
      * with the specified class name.
@@ -223,7 +264,7 @@
      * <p/>
      * Creates an element with no attribute overrides.
      */
-    private static ElementDescriptor createElement(
+    private ElementDescriptor createElement(
             String xmlName,
             ElementDescriptor[] childrenElements,
             boolean mandatory) {
@@ -243,7 +284,7 @@
      * <p/>
      * This version creates an element not mandatory.
      */
-    private static ElementDescriptor createElement(String xmlName) {
+    private ElementDescriptor createElement(String xmlName) {
         // Creates an element with no child and not mandatory
         return createElement(xmlName, null, false);
     }
@@ -253,7 +294,7 @@
      * (based on the attribute XML name.)
      * The attribute is inserted at the beginning of the attribute list.
      */
-    private static void insertAttribute(ElementDescriptor element, AttributeDescriptor newAttr) {
+    private void insertAttribute(ElementDescriptor element, AttributeDescriptor newAttr) {
         AttributeDescriptor[] attributes = element.getAttributes();
         for (AttributeDescriptor attr : attributes) {
             if (attr.getXmlLocalName().equals(newAttr.getXmlLocalName())) {
@@ -285,7 +326,7 @@
      * @param styleName The name of the {@link ElementDescriptor} to inflate. Its XML local name
      *          will be guessed automatically from the style name. 
      */
-    private static void inflateElement(
+    private void inflateElement(
             Map<String, DeclareStyleableInfo> styleMap,
             Map<String, Object> overrides,
             HashMap<String, ElementDescriptor> existingElementDescs,
@@ -343,7 +384,7 @@
      * <p/>
      * Capitalizes the first letter and replace non-alphabet by a space followed by a capital.
      */
-    private static String getUiName(String xmlName) {
+    private String getUiName(String xmlName) {
         StringBuilder sb = new StringBuilder();
 
         boolean capitalize = true;
@@ -376,7 +417,7 @@
      * - application     => AndroidManifestApplication
      * - uses-permission => AndroidManifestUsesPermission
      */
-    private static String guessStyleName(String xmlName) {
+    private String guessStyleName(String xmlName) {
         StringBuilder sb = new StringBuilder();
 
         if (!xmlName.equals(MANIFEST_NODE_NAME)) {
@@ -403,7 +444,7 @@
      * manifestMap are actually defined in the actual element descriptors and reachable from
      * the manifestElement root node.
      */
-    private static void sanityCheck(Map<String, DeclareStyleableInfo> manifestMap,
+    private void sanityCheck(Map<String, DeclareStyleableInfo> manifestMap,
             ElementDescriptor manifestElement) {
         TreeSet<String> elementsDeclared = new TreeSet<String>();
         findAllElementNames(manifestElement, elementsDeclared);
@@ -434,8 +475,8 @@
                 }
             }
             
-            EditorsPlugin.log(IStatus.WARNING, "%s", sb.toString());
-            EditorsPlugin.printToConsole(null, sb);
+            AdtPlugin.log(IStatus.WARNING, "%s", sb.toString());
+            AdtPlugin.printToConsole((String)null, sb);
             sb.setLength(0);
         }
 
@@ -448,8 +489,8 @@
                 }
             }
 
-            EditorsPlugin.log(IStatus.WARNING, "%s", sb.toString());
-            EditorsPlugin.printToConsole(null, sb);
+            AdtPlugin.log(IStatus.WARNING, "%s", sb.toString());
+            AdtPlugin.printToConsole((String)null, sb);
         }
     }
 
@@ -459,7 +500,7 @@
      * 
      * @return The XML local name for a given style name. 
      */
-    private static String guessXmlName(String name) {
+    private String guessXmlName(String name) {
         StringBuilder sb = new StringBuilder();
         if (ANDROID_MANIFEST_STYLEABLE.equals(name)) {
             sb.append(MANIFEST_NODE_NAME);
@@ -486,7 +527,7 @@
      * <p/>
      * Note: this assumes no circular reference in the tree of {@link ElementDescriptor}s.
      */
-    private static void findAllElementNames(ElementDescriptor element, TreeSet<String> declared) {
+    private void findAllElementNames(ElementDescriptor element, TreeSet<String> declared) {
         declared.add(element.getXmlName());
         for (ElementDescriptor desc : element.getChildren()) {
             findAllElementNames(desc, declared);
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ApplicationAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ClassAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/InstrumentationAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ManifestElementDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PackageAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostActivityCreationAction.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/PostReceiverCreationAction.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/descriptors/ThemeAttributeDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiClassAttributeNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
similarity index 92%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
index 10ce50d..79295a8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiManifestElementNode.java
@@ -64,12 +64,15 @@
                 getXmlNode() instanceof Element &&
                 getXmlNode().hasAttributes()) {
 
+            AndroidManifestDescriptors manifestDescriptors =
+                    getAndroidTarget().getManifestDescriptors();
+            
             // Application and Manifest nodes have a special treatment: they are unique nodes
             // so we don't bother trying to differentiate their strings and we fall back to
             // just using the UI name below.
             ElementDescriptor desc = getDescriptor();
-            if (desc != AndroidManifestDescriptors.MANIFEST_ELEMENT &&
-                    desc != AndroidManifestDescriptors.APPLICATION_ELEMENT) {
+            if (desc != manifestDescriptors.getManifestElement() &&
+                    desc != manifestDescriptors.getApplicationElement()) {
                 Element elem = (Element) getXmlNode();
                 String attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES,
                                                   AndroidManifestDescriptors.ANDROID_NAME_ATTR);
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
index 5e02273..02fb44f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/model/UiPackageAttributeNode.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.manifest.model;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
 import com.android.ide.eclipse.editors.ui.SectionHelper;
@@ -184,7 +184,7 @@
                         JavaCore.create(project), 0);
                 dlg.setTitle("Select Android Package");
                 dlg.setMessage("Select the package for the Android project.");
-                dlg.setDefaultImage(EditorsPlugin.getAndroidLogo());
+                SelectionDialog.setDefaultImage(AdtPlugin.getAndroidLogo());
 
                 if (dlg.open() == Window.OK) {
                     Object[] results = dlg.getResult();
@@ -212,13 +212,13 @@
 
             IProject project = getProject();
             if (project == null) {
-                EditorsPlugin.log(IStatus.ERROR, "Failed to get project for UiPackageAttribute"); //$NON-NLS-1$
+                AdtPlugin.log(IStatus.ERROR, "Failed to get project for UiPackageAttribute"); //$NON-NLS-1$
                 return;
             }
 
             IWorkbenchPartSite site = getUiParent().getEditor().getSite();
             if (site == null) {
-                EditorsPlugin.log(IStatus.ERROR, "Failed to get editor site for UiPackageAttribute"); //$NON-NLS-1$
+                AdtPlugin.log(IStatus.ERROR, "Failed to get editor site for UiPackageAttribute"); //$NON-NLS-1$
                 return;
             }
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
index 25bdb0e..01b0f8f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationAttributesPart.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.manifest.pages;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
 import com.android.ide.eclipse.editors.manifest.ManifestEditor;
@@ -130,7 +130,7 @@
             } else {
                 // The XML has an extra attribute which wasn't declared in
                 // AndroidManifestDescriptors. This is not a problem, we just ignore it.
-                EditorsPlugin.log(IStatus.WARNING,
+                AdtPlugin.log(IStatus.WARNING,
                         "Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
                         attr_desc.getXmlLocalName(),
                         uiElementNode.getDescriptor().getXmlName());
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
similarity index 89%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
index 1823278..77527f0 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationPage.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.manifest.pages;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.manifest.ManifestEditor;
 import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -67,7 +67,7 @@
         super.createFormContent(managedForm);
         ScrolledForm form = managedForm.getForm();
         form.setText("Android Manifest Application");
-        form.setImage(EditorsPlugin.getAndroidLogo());
+        form.setImage(AdtPlugin.getAndroidLogo());
 
         UiElementNode appUiNode = getUiApplicationNode();
 
@@ -96,8 +96,14 @@
      * exists, even if there is no matching XML node.
      */
     private UiElementNode getUiApplicationNode() {
-        ElementDescriptor desc = AndroidManifestDescriptors.APPLICATION_ELEMENT;
-        return mEditor.getUiRootNode().findUiChildNode(desc.getXmlName());
+        AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+        if (manifestDescriptor != null) {
+            ElementDescriptor desc = manifestDescriptor.getApplicationElement();
+            return mEditor.getUiRootNode().findUiChildNode(desc.getXmlName());
+        } else {
+            // return the ui root node, as a dummy application root node.
+            return mEditor.getUiRootNode();
+        }
     }
 
     /**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
similarity index 86%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
index daec98c..139575d 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/ApplicationToggle.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.manifest.pages;
 
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
 import com.android.ide.eclipse.editors.manifest.ManifestEditor;
 import com.android.ide.eclipse.editors.ui.UiElementPart;
@@ -130,10 +130,10 @@
         if (tooltip != null) {
             tooltip = DescriptorsUtils.formatFormText(tooltip,
                     getUiElementNode().getDescriptor(),
-                    FrameworkResourceManager.getInstance().getDocumentationBaseUrl());
+                    Sdk.getCurrent().getDocumentationBaseUrl());
     
             mTooltipFormText.setText(tooltip, true /* parseTags */, true /* expandURLs */);
-            mTooltipFormText.setImage(DescriptorsUtils.IMAGE_KEY, EditorsPlugin.getAndroidLogo());
+            mTooltipFormText.setImage(DescriptorsUtils.IMAGE_KEY, AdtPlugin.getAndroidLogo());
             mTooltipFormText.addHyperlinkListener(getEditor().createHyperlinkListener());
             isVisible = true;
         }
@@ -156,23 +156,32 @@
         public void widgetSelected(SelectionEvent e) {
             super.widgetSelected(e);
             if (!mInternalModification && getUiElementNode() != null) {
-                getUiElementNode().getEditor().editXmlModel(new Runnable() {
-                    public void run() {
-                        if (mCheckbox.getSelection()) {
-                            // The user wants an <application> node. Either restore a previous one
-                            // or create a full new one.
-                            boolean create = true;
-                            if (mUndoXmlNode != null) {
-                                create = !restoreApplicationNode();
+                getUiElementNode().getEditor().wrapUndoRecording(
+                        mCheckbox.getSelection()
+                            ? "Create or restore Application node"
+                            : "Remove Application node",
+                        new Runnable() {
+                            public void run() {
+                                getUiElementNode().getEditor().editXmlModel(new Runnable() {
+                                    public void run() {
+                                        if (mCheckbox.getSelection()) {
+                                            // The user wants an <application> node.
+                                            // Either restore a previous one
+                                            // or create a full new one.
+                                            boolean create = true;
+                                            if (mUndoXmlNode != null) {
+                                                create = !restoreApplicationNode();
+                                            }
+                                            if (create) {
+                                                getUiElementNode().createXmlNode();
+                                            }
+                                        } else {
+                                            // Users no longer wants the <application> node.
+                                            removeApplicationNode();
+                                        }
+                                    }
+                                });
                             }
-                            if (create) {
-                                getUiElementNode().createXmlNode();
-                            }
-                        } else {
-                            // Users no longer wants the <application> node.
-                            removeApplicationNode();
-                        }
-                    }
                 });
             }
         }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
similarity index 65%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
index 8eb6765..86d0dd1 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/InstrumentationPage.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.manifest.pages;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.manifest.ManifestEditor;
 import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -37,6 +37,8 @@
     /** Container editor */
     ManifestEditor mEditor;
 
+    private UiTreeBlock mTreeBlock;
+
     public InstrumentationPage(ManifestEditor editor) {
         super(editor, PAGE_ID, "Instrumentation");  // tab's label, keep it short
         mEditor = editor;
@@ -52,14 +54,39 @@
         super.createFormContent(managedForm);
         ScrolledForm form = managedForm.getForm();
         form.setText("Android Manifest Instrumentation");
-        form.setImage(EditorsPlugin.getAndroidLogo());
+        form.setImage(AdtPlugin.getAndroidLogo());
 
         UiElementNode manifest = mEditor.getUiRootNode();
-        UiTreeBlock block = new UiTreeBlock(mEditor, manifest,
+        AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+        ElementDescriptor[] descriptorFilters = null;
+        if (manifestDescriptor != null) {
+            descriptorFilters = new ElementDescriptor[] {
+                    manifestDescriptor.getInstrumentationElement(),
+            };
+        }
+
+        mTreeBlock = new UiTreeBlock(mEditor, manifest,
                 true /* autoCreateRoot */,
-                new ElementDescriptor[] { AndroidManifestDescriptors.INTRUMENTATION_ELEMENT },
+                descriptorFilters,
                 "Instrumentation",
                 "List of instrumentations defined in the manifest");
-        block.createContent(managedForm);
+        mTreeBlock.createContent(managedForm);
+    }
+    
+    /**
+     * Changes and refreshes the Application UI node handled by the sub parts.
+     */
+    public void refreshUiNode() {
+        if (mTreeBlock != null) {
+            UiElementNode manifest = mEditor.getUiRootNode();
+            AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+            mTreeBlock.changeRootAndDescriptors(manifest,
+                    new ElementDescriptor[] {
+                        manifestDescriptor.getInstrumentationElement()
+                    },
+                    true /* refresh */);
+        }
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
index 4e6521c..66af84c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewExportPart.java
@@ -49,9 +49,12 @@
         
         StringBuffer buf = new StringBuffer();
         buf.append("<form><li><a href=\"wizard\">"); //$NON-NLS-1$
-        buf.append("Use the export wizard");
-        buf.append("</a></li><li><a href=\"manual\">"); //$NON-NLS-1$
-        buf.append("Export an unsigned apk");
+        buf.append("Use the Export Wizard");
+        buf.append("</a>"); //$NON-NLS-1$
+        buf.append(" to export and sign an APK");
+        buf.append("</li>"); //$NON-NLS-1$
+        buf.append("<li><a href=\"manual\">"); //$NON-NLS-1$
+        buf.append("Export an unsigned APK");
         buf.append("</a>"); //$NON-NLS-1$
         buf.append(" and sign it manually");
         buf.append("</li></form>"); //$NON-NLS-1$
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
similarity index 87%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
index 182c6f3..026b760 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java
@@ -49,12 +49,19 @@
      * and can't be null, by design, because it's a mandatory node.
      */
     private static UiElementNode getManifestUiNode(ManifestEditor editor) {
-        ElementDescriptor desc = AndroidManifestDescriptors.MANIFEST_ELEMENT;
-        if (editor.getUiRootNode().getDescriptor() == desc) {
-            return editor.getUiRootNode();
-        } else {
-            return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+        AndroidManifestDescriptors manifestDescriptors = editor.getManifestDescriptors();
+        if (manifestDescriptors != null) {
+            ElementDescriptor desc = manifestDescriptors.getManifestElement();
+            if (editor.getUiRootNode().getDescriptor() == desc) {
+                return editor.getUiRootNode();
+            } else {
+                return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+            }
         }
+        
+        // No manifest descriptor: we have a dummy UiRootNode, so we return that.
+        // The editor will be reloaded once we have the proper descriptors anyway.
+        return editor.getUiRootNode();
     }
 
     /**
@@ -62,8 +69,15 @@
      * exists, even if there is no matching XML node.
      */
     private UiElementNode getUsesSdkUiNode(ManifestEditor editor) {
-        ElementDescriptor desc = AndroidManifestDescriptors.USES_SDK_ELEMENT;
-        return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+        AndroidManifestDescriptors manifestDescriptors = editor.getManifestDescriptors();
+        if (manifestDescriptors != null) {
+            ElementDescriptor desc = manifestDescriptors.getUsesSdkElement();
+            return editor.getUiRootNode().findUiChildNode(desc.getXmlName());
+        }
+        
+        // No manifest descriptor: we have a dummy UiRootNode, so we return that.
+        // The editor will be reloaded once we have the proper descriptors anyway.
+        return editor.getUiRootNode();
     }
 
     /**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
similarity index 66%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
index 7675fa2..d637a8f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewLinksPart.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.manifest.pages;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.manifest.ManifestEditor;
 import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -33,8 +33,12 @@
  */
 final class OverviewLinksPart extends ManifestSectionPart {
 
+    private final ManifestEditor mEditor;
+    private FormText mFormText;
+
     public OverviewLinksPart(Composite body, FormToolkit toolkit, ManifestEditor editor) {
         super(body, toolkit, Section.TWISTIE | Section.EXPANDED, true /* description */);
+        mEditor = editor;
         Section section = getSection();
         section.setText("Links");
         section.setDescription("The content of the Android Manifest is made up of three sections. You can also edit the XML directly.");
@@ -75,13 +79,40 @@
         buf.append("</li>"); //$NON-NLS-1$
         buf.append("</form>"); //$NON-NLS-1$
 
-        FormText text = createFormText(table, toolkit, true, buf.toString(),
+        mFormText = createFormText(table, toolkit, true, buf.toString(),
                 false /* setupLayoutData */);
-        text.setImage("android_img", EditorsPlugin.getAndroidLogo());
-        text.setImage("app_img", getIcon(AndroidManifestDescriptors.APPLICATION_ELEMENT));
-        text.setImage("perm_img", getIcon(AndroidManifestDescriptors.PERMISSION_ELEMENT));
-        text.setImage("inst_img", getIcon(AndroidManifestDescriptors.INTRUMENTATION_ELEMENT));
-        text.addHyperlinkListener(editor.createHyperlinkListener());
+        
+        AndroidManifestDescriptors manifestDescriptor = editor.getManifestDescriptors();
+
+        Image androidLogo = AdtPlugin.getAndroidLogo();
+        mFormText.setImage("android_img", androidLogo); //$NON-NLS-1$
+        
+        if (manifestDescriptor != null) {
+            mFormText.setImage("app_img", getIcon(manifestDescriptor.getApplicationElement())); //$NON-NLS-1$
+            mFormText.setImage("perm_img", getIcon(manifestDescriptor.getPermissionElement())); //$NON-NLS-1$
+            mFormText.setImage("inst_img", getIcon(manifestDescriptor.getInstrumentationElement())); //$NON-NLS-1$
+        } else {
+            mFormText.setImage("app_img", androidLogo); //$NON-NLS-1$
+            mFormText.setImage("perm_img", androidLogo); //$NON-NLS-1$
+            mFormText.setImage("inst_img", androidLogo); //$NON-NLS-1$
+        }
+        mFormText.addHyperlinkListener(editor.createHyperlinkListener());
+    }
+    
+    /**
+     * Update the UI with information from the new descriptors.
+     * <p/>At this point, this only refreshes the icons.
+     * <p/>
+     * This is called by {@link OverviewPage#refreshUiApplicationNode()} when the
+     * SDK has changed.
+     */
+    public void onSdkChanged() {
+        AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+        if (manifestDescriptor != null) {
+            mFormText.setImage("app_img", getIcon(manifestDescriptor.getApplicationElement())); //$NON-NLS-1$
+            mFormText.setImage("perm_img", getIcon(manifestDescriptor.getPermissionElement())); //$NON-NLS-1$
+            mFormText.setImage("inst_img", getIcon(manifestDescriptor.getInstrumentationElement())); //$NON-NLS-1$
+        }
     }
     
     private Image getIcon(ElementDescriptor desc) {
@@ -89,6 +120,6 @@
             return desc.getIcon();
         }
         
-        return EditorsPlugin.getAndroidLogo();
+        return AdtPlugin.getAndroidLogo();
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
similarity index 87%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
index 9e8925a..62954bd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.manifest.pages;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.manifest.ManifestEditor;
 
 import org.eclipse.swt.widgets.Composite;
@@ -43,6 +43,8 @@
     ManifestEditor mEditor;
     /** Overview part (attributes for manifest) */
     private OverviewInfoPart mOverviewPart;
+    /** Overview link part */
+    private OverviewLinksPart mOverviewLinkPart;
     
     public OverviewPage(ManifestEditor editor) {
         super(editor, PAGE_ID, "Overview");  // tab's label, user visible, keep it short
@@ -59,7 +61,7 @@
         super.createFormContent(managedForm);
         ScrolledForm form = managedForm.getForm();
         form.setText("Android Manifest Overview");
-        form.setImage(EditorsPlugin.getAndroidLogo());
+        form.setImage(AdtPlugin.getAndroidLogo());
         
         Composite body = form.getBody();
         FormToolkit toolkit = managedForm.getToolkit();
@@ -69,7 +71,8 @@
         mOverviewPart = new OverviewInfoPart(body, toolkit, mEditor);
         managedForm.addPart(mOverviewPart);
         managedForm.addPart(new OverviewExportPart(this, body, toolkit, mEditor));
-        managedForm.addPart(new OverviewLinksPart(body, toolkit, mEditor));
+        mOverviewLinkPart = new OverviewLinksPart(body, toolkit, mEditor);
+        managedForm.addPart(mOverviewLinkPart);
     }
 
     /**
@@ -79,5 +82,9 @@
         if (mOverviewPart != null) {
             mOverviewPart.onSdkChanged();
         }
+        
+        if (mOverviewLinkPart != null) {
+            mOverviewLinkPart.onSdkChanged();
+        }
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
similarity index 60%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
index a7c0ad5..41ba22e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/PermissionPage.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.manifest.pages;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.manifest.ManifestEditor;
 import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
@@ -41,6 +41,8 @@
     /** Container editor */
     ManifestEditor mEditor;
 
+    private UiTreeBlock mTreeBlock;
+
     public PermissionPage(ManifestEditor editor) {
         super(editor, PAGE_ID, "Permissions");  // tab label, keep it short
         mEditor = editor;
@@ -56,19 +58,44 @@
         super.createFormContent(managedForm);
         ScrolledForm form = managedForm.getForm();
         form.setText("Android Manifest Permissions");
-        form.setImage(EditorsPlugin.getAndroidLogo());
+        form.setImage(AdtPlugin.getAndroidLogo());
 
         UiElementNode manifest = mEditor.getUiRootNode();
-        UiTreeBlock block = new UiTreeBlock(mEditor, manifest,
+        AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+        
+        ElementDescriptor[] descriptorFilters = null;
+        if (manifestDescriptor != null) {
+            descriptorFilters = new ElementDescriptor[] {
+                    manifestDescriptor.getPermissionElement(),
+                    manifestDescriptor.getUsesPermissionElement(),
+                    manifestDescriptor.getPermissionGroupElement(),
+                    manifestDescriptor.getPermissionTreeElement()
+            };
+        }
+        mTreeBlock = new UiTreeBlock(mEditor, manifest,
                 true /* autoCreateRoot */,
-                new ElementDescriptor[] {
-                    AndroidManifestDescriptors.PERMISSION_ELEMENT,
-                    AndroidManifestDescriptors.USES_PERMISSION_ELEMENT,
-                    AndroidManifestDescriptors.PERMISSION_GROUP_ELEMENT,
-                    AndroidManifestDescriptors.PERMISSION_TREE_ELEMENT
-                },
+                descriptorFilters,
                 "Permissions",
                 "List of permissions defined and used by the manifest");
-        block.createContent(managedForm);
+        mTreeBlock.createContent(managedForm);
+    }
+
+    /**
+     * Changes and refreshes the Application UI node handled by the sub parts.
+     */
+    public void refreshUiNode() {
+        if (mTreeBlock != null) {
+            UiElementNode manifest = mEditor.getUiRootNode();
+            AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors();
+
+            mTreeBlock.changeRootAndDescriptors(manifest,
+                    new ElementDescriptor[] {
+                        manifestDescriptor.getPermissionElement(),
+                        manifestDescriptor.getUsesPermissionElement(),
+                        manifestDescriptor.getPermissionGroupElement(),
+                        manifestDescriptor.getPermissionTreeElement()
+                    },
+                    true /* refresh */);
+        }
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
similarity index 86%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
index 57b9a42..bf76d53 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuContentAssist.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.menu;
 
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
 
 /**
  * Content Assist Processor for /res/menu XML files
@@ -28,6 +28,6 @@
      * Constructor for LayoutContentAssist 
      */
     public MenuContentAssist() {
-        super(MenuDescriptors.getInstance().getDescriptor().getChildren());
+        super(AndroidTargetData.DESCRIPTOR_MENU);
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
similarity index 73%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
index 4bf02fa..cff1746 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuEditor.java
@@ -16,11 +16,12 @@
 
 package com.android.ide.eclipse.editors.menu;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidXPathFactory;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
 
 import org.eclipse.core.resources.IFile;
@@ -40,19 +41,16 @@
  */
 public class MenuEditor extends AndroidEditor {
 
-    public static final String ID = "com.android.ide.eclipse.editors.menu.MenuEditor"; //$NON-NLS-1$
+    public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".menu.MenuEditor"; //$NON-NLS-1$
 
     /** Root node of the UI element hierarchy */
     private UiElementNode mUiRootNode;
-    /** Listener to update the root node if the resource framework changes */
-    private Runnable mResourceRefreshListener;
 
     /**
      * Creates the form editor for resources XML files.
      */
     public MenuEditor() {
         super();
-        initUiRootNode();
     }
 
     /**
@@ -66,15 +64,6 @@
 
     // ---- Base Class Overrides ----
 
-    @Override
-    public void dispose() {
-        if (mResourceRefreshListener != null) {
-            EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
-            mResourceRefreshListener = null;
-        }
-        super.dispose();
-    }
-    
     /**
      * Returns whether the "save as" operation is supported by this editor.
      * <p/>
@@ -96,7 +85,7 @@
         try {
             addPage(new MenuTreePage(this));
         } catch (PartInitException e) {
-            EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+            AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
         }
         
      }
@@ -121,6 +110,9 @@
      */
     @Override
     protected void xmlModelChanged(Document xml_doc) {
+        // init the ui root on demand
+        initUiRootNode(false /*force*/);
+
         mUiRootNode.setXmlDocument(xml_doc);
         if (xml_doc != null) {
             ElementDescriptor root_desc = mUiRootNode.getDescriptor();
@@ -139,38 +131,54 @@
                 
                 // TODO ? startMonitoringMarkers();
             } catch (XPathExpressionException e) {
-                EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+                AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
                         root_desc.getXmlName());
             }
         }
         
         super.xmlModelChanged(xml_doc);
     }
-
     
-    // ---- Local Methods ----
-
     /**
      * Creates the initial UI Root Node, including the known mandatory elements.
+     * @param force if true, a new UiRootNode is recreated even if it already exists.
      */
-    private void initUiRootNode() {
+    @Override
+    protected void initUiRootNode(boolean force) {
         // The root UI node is always created, even if there's no corresponding XML node.
-        if (mUiRootNode == null) {
-            ElementDescriptor desc = MenuDescriptors.getInstance().getDescriptor();
+        if (mUiRootNode == null || force) {
+            Document doc = null;
+            if (mUiRootNode != null) {
+                doc = mUiRootNode.getXmlDocument();
+            }
+            
+            // get the target data from the opened file (and its project)
+            AndroidTargetData data = getTargetData();
+
+            ElementDescriptor desc;
+            if (data == null) {
+                desc = new ElementDescriptor("temp", null /*children*/);
+            } else {
+                desc = data.getMenuDescriptors().getDescriptor();
+            }
+
             mUiRootNode = desc.createUiNode();
             mUiRootNode.setEditor(this);
 
-            // Add a listener to refresh the root node if the resource framework changes
-            // by forcing it to parse its own XML
-            mResourceRefreshListener = new Runnable() {
-                public void run() {
-                    commitPages(false /* onSave */);
+            onDescriptorsChanged(doc);
+        }
+    }
 
-                    mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
-                }
-            };
-            EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
-            mResourceRefreshListener.run();
+    // ---- Local Methods ----
+
+    /**
+     * Reloads the UI manifest node from the XML, and calls the pages to update.
+     */
+    private void onDescriptorsChanged(Document document) {
+        if (document != null) {
+            mUiRootNode.loadFromXmlNode(document);
+        } else {
+            mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
         }
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
index 994074e..edbfa5e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/MenuTreePage.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.menu;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
 
@@ -49,7 +49,7 @@
         super.createFormContent(managedForm);
         ScrolledForm form = managedForm.getForm();
         form.setText("Android Menu");
-        form.setImage(EditorsPlugin.getAndroidLogo());
+        form.setImage(AdtPlugin.getAndroidLogo());
 
         UiElementNode rootNode = mEditor.getUiRootNode();
         UiTreeBlock block = new UiTreeBlock(mEditor, rootNode,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
index 941f736..34c7bb2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/menu/descriptors/MenuDescriptors.java
@@ -21,6 +21,7 @@
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
 import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
 
 import java.util.ArrayList;
@@ -30,32 +31,22 @@
 /**
  * Complete description of the menu structure.
  */
-public class MenuDescriptors {
+public final class MenuDescriptors implements IDescriptorProvider {
 
     public static final String MENU_ROOT_ELEMENT = "menu"; //$NON-NLS-1$
 
-    
-    
-    /** Singleton instance */
-    private static MenuDescriptors sThis;
-
     /** The root element descriptor. */
     private ElementDescriptor mDescriptor = null;
 
-    /** Returns a singleton instance of the {@link MenuDescriptors}. */
-    public static synchronized MenuDescriptors getInstance() {
-        if (sThis == null) {
-            sThis = new MenuDescriptors();
-            sThis.updateDescriptors(null);
-        }
-        return sThis;
-    }
-    
     /** @return the root descriptor. */
     public ElementDescriptor getDescriptor() {
         return mDescriptor;
     }
-
+    
+    public ElementDescriptor[] getRootElementDescriptors() {
+        return mDescriptor.getChildren();
+    }
+    
     /**
      * Updates the document descriptor.
      * <p/>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
similarity index 80%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
index 9fe15ab..c9c8e17 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesContentAssist.java
@@ -16,9 +16,8 @@
 
 package com.android.ide.eclipse.editors.resources;
 
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
 
 /**
  * Content Assist Processor for /res/values and /res/drawable XML files
@@ -29,6 +28,6 @@
      * Constructor for ResourcesContentAssist 
      */
     public ResourcesContentAssist() {
-        super(new ElementDescriptor[] { ResourcesDescriptors.RESOURCES_ELEMENT });
+        super(AndroidTargetData.DESCRIPTOR_RESOURCES);
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
similarity index 78%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
index bad5699..46a9112 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesEditor.java
@@ -16,9 +16,10 @@
 
 package com.android.ide.eclipse.editors.resources;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidXPathFactory;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -41,7 +42,7 @@
  */
 public class ResourcesEditor extends AndroidEditor {
 
-    public static final String ID = "com.android.ide.eclipse.editors.resources.ResourcesEditor"; //$NON-NLS-1$
+    public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".resources.ResourcesEditor"; //$NON-NLS-1$
 
     /** Root node of the UI element hierarchy */
     private UiElementNode mUiResourcesNode;
@@ -52,7 +53,6 @@
      */
     public ResourcesEditor() {
         super();
-        initUiResourcesNode();
     }
 
     /**
@@ -87,8 +87,8 @@
         try {
             addPage(new ResourcesTreePage(this));
         } catch (PartInitException e) {
-            EditorsPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
-            EditorsPlugin.getDefault().getLog().log(e.getStatus());
+            AdtPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
+            AdtPlugin.getDefault().getLog().log(e.getStatus());
         }
      }
 
@@ -113,9 +113,13 @@
      */
     @Override
     protected void xmlModelChanged(Document xml_doc) {
+        // init the ui root on demand
+        initUiRootNode(false /*force*/);
+
         mUiResourcesNode.setXmlDocument(xml_doc);
         if (xml_doc != null) {
-            ElementDescriptor resources_desc = ResourcesDescriptors.RESOURCES_ELEMENT;
+            ElementDescriptor resources_desc =
+                    ResourcesDescriptors.getInstance().getElementDescriptor();
             try {
                 XPath xpath = AndroidXPathFactory.newXPath();
                 Node node = (Node) xpath.evaluate("/" + resources_desc.getXmlName(),  //$NON-NLS-1$
@@ -126,27 +130,35 @@
                 // Refresh the manifest UI node and all its descendants 
                 mUiResourcesNode.loadFromXmlNode(node);
             } catch (XPathExpressionException e) {
-                EditorsPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+                AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
                         resources_desc.getXmlName());
             }
         }
         
         super.xmlModelChanged(xml_doc);
     }
-
     
-    // ---- Local Methods ----
-
     /**
      * Creates the initial UI Root Node, including the known mandatory elements.
+     * @param force if true, a new UiRootNode is recreated even if it already exists.
      */
-    private void initUiResourcesNode() {
+    @Override
+    protected void initUiRootNode(boolean force) {
         // The manifest UI node is always created, even if there's no corresponding XML node.
-        if (mUiResourcesNode == null) {
-            ElementDescriptor resources_desc = ResourcesDescriptors.RESOURCES_ELEMENT;   
+        if (mUiResourcesNode == null || force) {
+            ElementDescriptor resources_desc =
+                    ResourcesDescriptors.getInstance().getElementDescriptor();   
             mUiResourcesNode = resources_desc.createUiNode();
             mUiResourcesNode.setEditor(this);
+            
+            onDescriptorsChanged();
         }
     }
 
+    // ---- Local Methods ----
+
+    private void onDescriptorsChanged() {
+        // nothing to be done, as the descriptor are static for now.
+        // FIXME Update when the descriptors are not static
+    }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
index 8cabeca..5c1b0e1 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/ResourcesTreePage.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.resources;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
 import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
 import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
@@ -72,7 +72,7 @@
             form.setText("Android Resources");
         }
 
-        form.setImage(EditorsPlugin.getAndroidLogo());
+        form.setImage(AdtPlugin.getAndroidLogo());
 
         UiElementNode resources = mEditor.getUiRootNode();
         UiTreeBlock block = new UiTreeBlock(mEditor, resources,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
index 7670fa2..1d01260 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/CountryCodeQualifier.java
@@ -92,7 +92,7 @@
     
     @Override
     public Image getIcon() {
-        return IconFactory.getInstance().getIcon("world"); //$NON-NLS-1$
+        return IconFactory.getInstance().getIcon("mcc"); //$NON-NLS-1$
     }
     
     @Override
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/FolderConfiguration.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/KeyboardStateQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/LanguageQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NavigationMethodQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/NetworkCodeQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/PixelDensityQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/RegionQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ResourceQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenDimensionQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/ScreenOrientationQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TextInputMethodQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/configurations/TouchScreenQualifier.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ColorValueDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ItemElementDescriptor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
similarity index 74%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
index 4769cef..1075897 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/descriptors/ResourcesDescriptors.java
@@ -20,16 +20,16 @@
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.descriptors.FlagAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
 import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.TextValueDescriptor;
 
 
 /**
- * Complete description of the AndroidManifest.xml structure.
+ * Complete description of the structure for resources XML files (under res/values/)
  */
-public class ResourcesDescriptors {
-
+public class ResourcesDescriptors implements IDescriptorProvider {
 
     // Public attributes names, attributes descriptors and elements descriptors
 
@@ -38,14 +38,33 @@
     public static final String NAME_ATTR = "name"; //$NON-NLS-1$
     public static final String TYPE_ATTR = "type"; //$NON-NLS-1$
 
-    /** The {@link ElementDescriptor} for the root Manifest element. */
-    public static final ElementDescriptor RESOURCES_ELEMENT;
-   
+    private static final ResourcesDescriptors sThis = new ResourcesDescriptors();
 
-    static {
+    /** The {@link ElementDescriptor} for the root Resources element. */
+    public final ElementDescriptor mResourcesElement;
+
+    public static ResourcesDescriptors getInstance() {
+        return sThis;
+    }
+    
+    /*
+     * @see com.android.ide.eclipse.editors.descriptors.IDescriptorProvider#getRootElementDescriptors()
+     */
+    public ElementDescriptor[] getRootElementDescriptors() {
+        return new ElementDescriptor[] { mResourcesElement };
+    }
+    
+    public ElementDescriptor getDescriptor() {
+        return mResourcesElement;
+    }
+    
+    public ElementDescriptor getElementDescriptor() {
+        return mResourcesElement;
+    }
+    
+    private ResourcesDescriptors() {
 
         // Common attributes used in many placed
-        
 
         // Elements
 
@@ -189,7 +208,61 @@
                 },
                 false /* not mandatory */);
 
-         RESOURCES_ELEMENT = new ElementDescriptor(
+         ElementDescriptor string_array_element = new ElementDescriptor(
+                 "string-array", //$NON-NLS-1$
+                 "String Array",
+                 "An array of strings. Strings are added as underlying item elements to the array.",
+                 null, // tooltips
+                 new AttributeDescriptor[] {
+                         new TextAttributeDescriptor(NAME_ATTR,
+                                 "Name*",
+                                 null /* nsUri */,
+                                 "The mandatory name used in referring to this string array."),
+                 },
+                 new ElementDescriptor[] {
+                     new ElementDescriptor(
+                         "item", //$NON-NLS-1$
+                         "Item", 
+                         "A string value to use in this string array.",
+                         null, // tooltip
+                         new AttributeDescriptor[] {
+                             new TextValueDescriptor(
+                                 "Value*",
+                                 "A mandatory string.")
+                         },
+                         null,  // no child nodes
+                         false /* not mandatory */)
+                 },
+                 false /* not mandatory */);
+
+         ElementDescriptor integer_array_element = new ElementDescriptor(
+                 "integer-array", //$NON-NLS-1$
+                 "Integer Array",
+                 "An array of integers. Integers are added as underlying item elements to the array.",
+                 null, // tooltips
+                 new AttributeDescriptor[] {
+                         new TextAttributeDescriptor(NAME_ATTR,
+                                 "Name*",
+                                 null /* nsUri */,
+                                 "The mandatory name used in referring to this integer array."),
+                 },
+                 new ElementDescriptor[] {
+                     new ElementDescriptor(
+                         "item", //$NON-NLS-1$
+                         "Item", 
+                         "An integer value to use in this integer array.",
+                         null, // tooltip
+                         new AttributeDescriptor[] {
+                             new TextValueDescriptor(
+                                 "Value*",
+                                 "A mandatory integer.")
+                         },
+                         null,  // no child nodes
+                         false /* not mandatory */)
+                 },
+                 false /* not mandatory */);
+
+         mResourcesElement = new ElementDescriptor(
                         ROOT_ELEMENT,
                         "Resources", 
                         null,
@@ -201,7 +274,9 @@
                                 dimen_element,
                                 drawable_element,
                                 style_element,
-                                item_element
+                                item_element,
+                                string_array_element,
+                                integer_array_element,
                         },
                         true /* mandatory */);
     }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
index cc7bec8..845db32 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.resources.explorer;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.resources.manager.ProjectResourceItem;
 import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
 import com.android.ide.eclipse.editors.resources.manager.ResourceFile;
@@ -73,10 +73,12 @@
 public class ResourceExplorerView extends ViewPart implements ISelectionListener,
         IResourceEventListener {
     
+    // Note: keep using the obsolete AndroidConstants.EDITORS_NAMESPACE (which used
+    // to be the Editors Plugin ID) to keep existing preferences functional.
     private final static String PREFS_COLUMN_RES =
-        AndroidConstants.EDITORS_PLUGIN_ID + "ResourceExplorer.Col1"; //$NON-NLS-1$
+        AndroidConstants.EDITORS_NAMESPACE + "ResourceExplorer.Col1"; //$NON-NLS-1$
     private final static String PREFS_COLUMN_2 =
-        AndroidConstants.EDITORS_PLUGIN_ID + "ResourceExplorer.Col2"; //$NON-NLS-1$
+        AndroidConstants.EDITORS_NAMESPACE + "ResourceExplorer.Col2"; //$NON-NLS-1$
 
     private Tree mTree;
     private TreeViewer mTreeViewer;
@@ -93,7 +95,7 @@
         mTree.setHeaderVisible(true);
         mTree.setLinesVisible(true);
 
-        final IPreferenceStore store = EditorsPlugin.getDefault().getPreferenceStore();
+        final IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
 
         // create 2 columns. The main one with the resources, and an "info" column.
         createTreeColumn(mTree, "Resources", SWT.LEFT,
@@ -156,7 +158,7 @@
         });
         
         // set up the resource manager to send us resource change notification
-        EditorsPlugin.getDefault().getResourceMonitor().addResourceEventListener(this);
+        AdtPlugin.getDefault().getResourceMonitor().addResourceEventListener(this);
     }
 
     @Override
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
similarity index 82%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
index 366f4fd..455c825 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
@@ -16,6 +16,7 @@
 
 package com.android.ide.eclipse.editors.resources.manager;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidManifestHelper;
 import com.android.ide.eclipse.common.resources.ResourceType;
@@ -124,24 +125,29 @@
                 ProjectClassLoader loader = new ProjectClassLoader(null /* parentClassLoader */,
                         project);
                 
-                Class<?> clazz = loader.loadClass(className);
-                
-                if (clazz != null) {
-                    // create the maps to store the result of the parsing
-                    Map<String, Map<String, Integer>> resourceValueMap =
-                        new HashMap<String, Map<String, Integer>>();
-                    Map<Integer, String[]> genericValueToNameMap =
-                        new HashMap<Integer, String[]>();
-                    Map<IntArrayWrapper, String> styleableValueToNameMap =
-                        new HashMap<IntArrayWrapper, String>();
+                try {
+                    Class<?> clazz = loader.loadClass(className);
                     
-                    // parse the class
-                    if (parseClass(clazz, genericValueToNameMap, styleableValueToNameMap,
-                            resourceValueMap)) {
-                        // now we associate the maps to the project.
-                        projectResources.setCompiledResources(genericValueToNameMap,
-                                styleableValueToNameMap, resourceValueMap);
+                    if (clazz != null) {
+                        // create the maps to store the result of the parsing
+                        Map<String, Map<String, Integer>> resourceValueMap =
+                            new HashMap<String, Map<String, Integer>>();
+                        Map<Integer, String[]> genericValueToNameMap =
+                            new HashMap<Integer, String[]>();
+                        Map<IntArrayWrapper, String> styleableValueToNameMap =
+                            new HashMap<IntArrayWrapper, String>();
+                        
+                        // parse the class
+                        if (parseClass(clazz, genericValueToNameMap, styleableValueToNameMap,
+                                resourceValueMap)) {
+                            // now we associate the maps to the project.
+                            projectResources.setCompiledResources(genericValueToNameMap,
+                                    styleableValueToNameMap, resourceValueMap);
+                        }
                     }
+                } catch (Error e) {
+                    // Log this error with the class name we're trying to load and abort.
+                    AdtPlugin.log(e, "loadAndParseRClass failed to find class %1$s", className); //$NON-NLS-1$
                 }
             }
         } catch (ClassNotFoundException e) {
@@ -155,7 +161,7 @@
      * @param genericValueToNameMap
      * @param styleableValueToNameMap
      * @param resourceValueMap
-     * @return
+     * @return True if we managed to parse the R class.
      */
     private boolean parseClass(Class<?> rClass, Map<Integer, String[]> genericValueToNameMap,
             Map<IntArrayWrapper, String> styleableValueToNameMap, Map<String,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ConfigurableResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/FolderTypeRelationship.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IdResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/IntArrayWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/MultiResourceFile.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
index 5658224..183af27 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectClassLoader.java
@@ -215,12 +215,6 @@
                     // get the IPath
                     IPath path = e.getPath();
 
-                    // get the file name. if it's the framework jar, we ignore that file.
-                    // since we now use classpath container, this is here for legacy purpose only.
-                    if (AndroidConstants.FN_FRAMEWORK_LIBRARY.equals(path.lastSegment())) {
-                        continue;
-                    }
-
                     // check the name ends with .jar
                     if (AndroidConstants.EXT_JAR.equalsIgnoreCase(path.getFileExtension())) {
                         boolean local = false;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResourceItem.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ProjectResources.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/Resource.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/Resource.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/Resource.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFile.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolder.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceFolderType.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
index 64942ed..9c5f0fc 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceManager.java
@@ -29,6 +29,7 @@
 import com.android.ide.eclipse.editors.resources.manager.files.IAbstractFolder;
 import com.android.ide.eclipse.editors.resources.manager.files.IFileWrapper;
 import com.android.ide.eclipse.editors.resources.manager.files.IFolderWrapper;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
@@ -57,8 +58,6 @@
     private final HashMap<IProject, ProjectResources> mMap =
         new HashMap<IProject, ProjectResources>();
     
-    private ProjectResources mFrameworkResources = null;
-    
     /**
      * Sets up the resource manager with the global resource monitor.
      * @param monitor The global resource monitor
@@ -89,14 +88,6 @@
     }
     
     /**
-     * Returns the resources of the framework.
-     * <p/>This could be <code>null</code> if the parsing failed.
-     */
-    public ProjectResources getFrameworkResources() {
-        return mFrameworkResources;
-    }
-    
-    /**
      * Processes folder event.
      */
     public void folderChanged(IFolder folder, int kind) {
@@ -277,24 +268,23 @@
     }
     
     /**
-     * Loads the framework resources.
+     * Loads and returns the resources for a given {@link IAndroidTarget}
      * @param osFilePath the path to the folder containing all the versions of the framework
      * resources
      */
-    public void loadFrameworkResources(String osResourcesPath) {
-        // for now only load the default framework resources
-        osResourcesPath += AndroidConstants.FD_DEFAULT_RES;
+    public ProjectResources loadFrameworkResources(IAndroidTarget androidTarget) {
+        String osResourcesPath = androidTarget.getPath(IAndroidTarget.RESOURCES);
         
         File frameworkRes = new File(osResourcesPath);
         if (frameworkRes.isDirectory()) {
-            mFrameworkResources = new ProjectResources(true /* isFrameworkRepository */);
+            ProjectResources resources = new ProjectResources(true /* isFrameworkRepository */);
 
             try {
                 File[] files = frameworkRes.listFiles();
                 for (File file : files) {
                     if (file.isDirectory()) {
                         ResourceFolder resFolder = processFolder(new FolderWrapper(file),
-                                mFrameworkResources);
+                                resources);
                         
                         if (resFolder != null) {
                             // now we process the content of the folder
@@ -311,13 +301,17 @@
                 }
                 
                 // now that we have loaded the files, we need to force load the resources from them
-                mFrameworkResources.loadAll();
+                resources.loadAll();
+                
+                return resources;
                 
             } catch (IOException e) {
                 // since we test that folders are folders, and files are files, this shouldn't
                 // happen. We can ignore it.
             }
         }
+        
+        return null;
     }
     
     /**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
index 45a020c..dc0f505 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java
@@ -257,6 +257,20 @@
         
         mFileListeners.add(bundle);
     }
+    
+    /**
+     * Removes an existing file listener.
+     * @param listener the listener to remove.
+     */
+    public synchronized void removeFileListener(IFileListener listener) {
+        for (int i = 0 ; i < mFileListeners.size() ; i++) {
+            FileListenerBundle bundle = mFileListeners.get(i);
+            if (bundle.listener == listener) {
+                mFileListeners.remove(i);
+                return;
+            }
+        }
+    }
 
     /**
      * Adds a folder listener.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/SingleResourceFile.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FileWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/FolderWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFile.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractFolder.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IAbstractResource.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFileWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/files/IFolderWrapper.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiColorValueNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/uimodel/UiItemElementNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/EditableDialogCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ErrorImageComposite.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/FlagValueCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ListValueCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/ResourceValueCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
index 7942024..409e92f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/SectionHelper.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.ui;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 
 import org.eclipse.jface.text.DefaultInformationControl;
 import org.eclipse.swt.events.MouseEvent;
@@ -173,7 +173,7 @@
                 reflow.setAccessible(true);
                 reflow.invoke(section);
             } catch (Exception e) {
-                EditorsPlugin.log(e, "Error when invoking Section.reflow");
+                AdtPlugin.log(e, "Error when invoking Section.reflow");
             }
             
             section.layout(true /* changed */, true /* all */);
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/TextValueCellEditor.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
similarity index 97%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
index 69adebd..66773bd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/UiElementPart.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.ui;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
 import com.android.ide.eclipse.editors.manifest.ManifestEditor;
@@ -60,7 +60,7 @@
         if (uiElementNode == null) {
             // This is serious and should never happen. Instead of crashing, simply abort.
             // There will be no UI, which will prevent further damage.
-            EditorsPlugin.log(IStatus.ERROR, "Missing node to edit!"); //$NON-NLS-1$
+            AdtPlugin.log(IStatus.ERROR, "Missing node to edit!"); //$NON-NLS-1$
             return;
         }
     }
@@ -222,7 +222,7 @@
             } else {
                 // The XML has an extra attribute which wasn't declared in
                 // AndroidManifestDescriptors. This is not a problem, we just ignore it.
-                EditorsPlugin.log(IStatus.WARNING,
+                AdtPlugin.log(IStatus.WARNING,
                         "Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
                         attr_desc.getXmlLocalName(),
                         uiNode.getDescriptor().getXmlName());
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
new file mode 100644
index 0000000..2aad217
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2008 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.editors.ui.tree;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.editors.AndroidEditor;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.apache.xml.serialize.Method;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.document.NodeContainer;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Provides Cut and Copy actions for the tree nodes.
+ */
+public class CopyCutAction extends Action {
+    private List<UiElementNode> mUiNodes;
+    private boolean mPerformCut;
+    private final AndroidEditor mEditor;
+    private final Clipboard mClipboard;
+    private final ICommitXml mXmlCommit;
+
+    /**
+     * Creates a new Copy or Cut action.
+     * 
+     * @param selected The UI node to cut or copy. It *must* have a non-null XML node.
+     * @param perform_cut True if the operation is cut, false if it is copy.
+     */
+    public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
+            UiElementNode selected, boolean perform_cut) {
+        this(editor, clipboard, xmlCommit, toList(selected), perform_cut);
+    }
+
+    /**
+     * Creates a new Copy or Cut action.
+     * 
+     * @param selected The UI nodes to cut or copy. They *must* have a non-null XML node.
+     *                 The list becomes owned by the {@link CopyCutAction}.
+     * @param perform_cut True if the operation is cut, false if it is copy.
+     */
+    public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
+            List<UiElementNode> selected, boolean perform_cut) {
+        super(perform_cut ? "Cut" : "Copy");
+        mEditor = editor;
+        mClipboard = clipboard;
+        mXmlCommit = xmlCommit;
+        
+        ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
+        if (perform_cut) {
+            setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
+            setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
+            setDisabledImageDescriptor(
+                    images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));
+        } else {
+            setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
+            setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
+            setDisabledImageDescriptor(
+                    images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));
+        }
+
+        mUiNodes = selected;
+        mPerformCut = perform_cut;
+    }
+
+    /**
+     * Performs the cut or copy action.
+     * First an XML serializer is used to turn the existing XML node into a valid
+     * XML fragment, which is added as text to the clipboard.
+     */
+    @Override
+    public void run() {
+        super.run();
+        if (mUiNodes == null || mUiNodes.size() < 1) {
+            return;
+        }
+
+        // Commit the current pages first, to make sure the XML is in sync.
+        // Committing may change the XML structure.
+        if (mXmlCommit != null) {
+            mXmlCommit.commitPendingXmlChanges();
+        }
+
+        StringBuilder allText = new StringBuilder();
+        ArrayList<UiElementNode> nodesToCut = mPerformCut ? new ArrayList<UiElementNode>() : null;
+
+        for (UiElementNode uiNode : mUiNodes) {
+            try {            
+                Node xml_node = uiNode.getXmlNode();
+                if (xml_node == null) {
+                    return;
+                }
+                
+                String data = getXmlTextFromEditor(xml_node);
+ 
+                // In the unlikely event that IStructuredDocument failed to extract the text
+                // directly from the editor, try to fall back on a direct XML serialization
+                // of the XML node. This uses the generic Node interface with no SSE tricks.
+                if (data == null) {
+                    data = getXmlTextFromSerialization(xml_node);
+                }
+                
+                if (data != null) {
+                    allText.append(data);
+                    if (mPerformCut) {
+                        // only remove notes to cut if we actually got some XML text from them
+                        nodesToCut.add(uiNode);
+                    }
+                }
+    
+            } catch (Exception e) {
+                AdtPlugin.log(e, "CopyCutAction failed for UI node %1$s", //$NON-NLS-1$
+                        uiNode.getBreadcrumbTrailDescription(true));
+            }
+        } // for uiNode
+
+        if (allText != null && allText.length() > 0) {
+            mClipboard.setContents(
+                    new Object[] { allText.toString() },
+                    new Transfer[] { TextTransfer.getInstance() });
+            if (mPerformCut) {
+                for (UiElementNode uiNode : nodesToCut) {
+                    uiNode.deleteXmlNode();
+                }
+            }
+        }
+    }
+
+    /** Get the data directly from the editor. */
+    private String getXmlTextFromEditor(Node xml_node) {
+        String data = null;
+        IStructuredModel model = mEditor.getModelForRead();
+        try {
+            IStructuredDocument sse_doc = mEditor.getStructuredDocument();
+            if (xml_node instanceof NodeContainer) {
+                // The easy way to get the source of an SSE XML node.
+                data = ((NodeContainer) xml_node).getSource();
+            } else  if (xml_node instanceof IndexedRegion && sse_doc != null) {
+                // Try harder.
+                IndexedRegion region = (IndexedRegion) xml_node;
+                int start = region.getStartOffset();
+                int end = region.getEndOffset();
+   
+                if (end > start) {
+                    data = sse_doc.get(start, end - start);
+                }
+            }
+        } catch (BadLocationException e) {
+            // the region offset was invalid. ignore.
+        } finally {
+            model.releaseFromRead();
+        }
+        return data;
+    }
+    
+    /**
+     * Direct XML serialization of the XML node.
+     * <p/>
+     * This uses the generic Node interface with no SSE tricks. It's however slower
+     * and doesn't respect formatting (since serialization is involved instead of reading
+     * the actual text buffer.)
+     */
+    private String getXmlTextFromSerialization(Node xml_node) throws IOException {
+        String data;
+        StringWriter sw = new StringWriter();
+        XMLSerializer serializer = new XMLSerializer(sw,
+                new OutputFormat(Method.XML,
+                        OutputFormat.Defaults.Encoding /* utf-8 */,
+                        true /* indent */));
+        // Serialize will throw an IOException if it fails.
+        serializer.serialize((Element) xml_node);
+        data = sw.toString();
+        return data;
+    }
+
+    /**
+     * Static helper class to wrap on node into a list for the constructors.
+     */
+    private static ArrayList<UiElementNode> toList(UiElementNode selected) {
+        ArrayList<UiElementNode> list = null;
+        if (selected != null) {
+            list = new ArrayList<UiElementNode>(1);
+            list.add(selected);
+        }
+        return list;
+    }
+}
+
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/ICommitXml.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
similarity index 97%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
index 00e44ab..772fb52 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
@@ -16,6 +16,7 @@
 
 package com.android.ide.eclipse.editors.ui.tree;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
@@ -90,19 +91,19 @@
             public IStatus validate(Object[] selection) {
                 if (selection.length == 1 && selection[0] instanceof ViewElementDescriptor) {
                     return new Status(IStatus.OK, // severity
-                            AndroidConstants.EDITORS_PLUGIN_ID, //plugin id
+                            AdtPlugin.PLUGIN_ID, //plugin id
                             IStatus.OK, // code
                             ((ViewElementDescriptor) selection[0]).getCanonicalClassName(), //msg 
                             null); // exception
                 } else if (selection.length == 1 && selection[0] instanceof ElementDescriptor) {
                     return new Status(IStatus.OK, // severity
-                            AndroidConstants.EDITORS_PLUGIN_ID, //plugin id
+                            AdtPlugin.PLUGIN_ID, //plugin id
                             IStatus.OK, // code
                             "", //$NON-NLS-1$ // msg
                             null); // exception
                 } else {
                     return new Status(IStatus.ERROR, // severity
-                            AndroidConstants.EDITORS_PLUGIN_ID, //plugin id
+                            AdtPlugin.PLUGIN_ID, //plugin id
                             IStatus.ERROR, // code
                             "Invalid selection", // msg, translatable 
                             null); // exception
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
index 68580b0..8bb4ad2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/PasteAction.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.ui.tree;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
 
@@ -113,7 +113,7 @@
                 }
 
             } catch (BadLocationException e) {
-                EditorsPlugin.log(e, "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$
+                AdtPlugin.log(e, "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$
                         mUiNode.getBreadcrumbTrailDescription(true), data);
             } finally {
                 model.releaseFromEdit();
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
new file mode 100644
index 0000000..21180b1
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.editors.ui.tree;
+
+import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
+import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.widgets.Shell;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * Performs basic actions on an XML tree: add node, remove node, move up/down.
+ */
+public abstract class UiActions implements ICommitXml {
+
+    public UiActions() {
+    }
+
+    //---------------------
+    // Actual implementations must override these to provide specific hooks
+
+    /** Returns the UiDocumentNode for the current model. */
+    abstract protected UiElementNode getRootNode();
+
+    /** Commits pending data before the XML model is modified. */
+    abstract public void commitPendingXmlChanges();
+
+    /**
+     * Utility method to select an outline item based on its model node
+     * 
+     * @param uiNode The node to select. Can be null (in which case nothing should happen)
+     */
+    abstract protected void selectUiNode(UiElementNode uiNode);
+
+    //---------------------
+
+    /**
+     * Called when the "Add..." button next to the tree view is selected.
+     * <p/>
+     * This simplified version of doAdd does not support descriptor filters and creates
+     * a new {@link UiModelTreeLabelProvider} for each call.
+     */
+    public void doAdd(UiElementNode uiNode, Shell shell) {
+        doAdd(uiNode, null /* descriptorFilters */, shell, new UiModelTreeLabelProvider());
+    }
+    
+    /**
+     * Called when the "Add..." button next to the tree view is selected.
+     * 
+     * Displays a selection dialog that lets the user select which kind of node
+     * to create, depending on the current selection.
+     */
+    public void doAdd(UiElementNode uiNode,
+            ElementDescriptor[] descriptorFilters,
+            Shell shell, ILabelProvider labelProvider) {
+        // If the root node is a document with already a root, use it as the root node
+        UiElementNode rootNode = getRootNode();
+        if (rootNode instanceof UiDocumentNode && rootNode.getUiChildren().size() > 0) {
+            rootNode = rootNode.getUiChildren().get(0);
+        }
+
+        NewItemSelectionDialog dlg = new NewItemSelectionDialog(
+                shell,
+                labelProvider,
+                descriptorFilters,
+                uiNode, rootNode);
+        dlg.open();
+        Object[] results = dlg.getResult();
+        if (results != null && results.length > 0) {
+            addElement(dlg.getChosenRootNode(), null, (ElementDescriptor) results[0],
+                    true /*updateLayout*/);
+        }
+    }
+
+    /**
+     * Adds a new XML element based on the {@link ElementDescriptor} to the given parent
+     * {@link UiElementNode}, and then select it.
+     * <p/>
+     * If the parent is a document root which already contains a root element, the inner
+     * root element is used as the actual parent. This ensure you can't create a broken
+     * XML file with more than one root element.
+     * <p/>
+     * If a sibling is given and that sibling has the same parent, the new node is added
+     * right after that sibling. Otherwise the new node is added at the end of the parent
+     * child list.
+     * 
+     * @param uiParent An existing UI node or null to add to the tree root
+     * @param uiSibling An existing UI node before which to insert the new node. Can be null.
+     * @param descriptor The descriptor of the element to add
+     * @param updateLayout True if layout attributes should be set
+     * @return The new {@link UiElementNode} or null.
+     */
+    public UiElementNode addElement(UiElementNode uiParent,
+            UiElementNode uiSibling,
+            ElementDescriptor descriptor,
+            boolean updateLayout) {
+        if (uiParent instanceof UiDocumentNode && uiParent.getUiChildren().size() > 0) {
+            uiParent = uiParent.getUiChildren().get(0);
+        }
+        if (uiSibling != null && uiSibling.getUiParent() != uiParent) {
+            uiSibling = null;
+        }
+
+        UiElementNode uiNew = addNewTreeElement(uiParent, uiSibling, descriptor, updateLayout);
+        selectUiNode(uiNew);
+        
+        return uiNew;
+    }
+
+    /**
+     * Called when the "Remove" button is selected.
+     * 
+     * If the tree has a selection, remove it.
+     * This simply deletes the XML node attached to the UI node: when the XML model fires the
+     * update event, the tree will get refreshed.
+     */
+    public void doRemove(final List<UiElementNode> nodes, Shell shell) {
+        
+        if (nodes == null || nodes.size() == 0) {
+            return;
+        }
+        
+        final int len = nodes.size();
+        
+        StringBuilder sb = new StringBuilder();
+        for (UiElementNode node : nodes) {
+            sb.append("\n- "); //$NON-NLS-1$
+            sb.append(node.getBreadcrumbTrailDescription(false /* include_root */));
+        }
+        
+        if (MessageDialog.openQuestion(shell,
+                len > 1 ? "Remove elements from Android XML"  // title
+                        : "Remove element from Android XML",
+                String.format("Do you really want to remove %1$s?", sb.toString()))) {
+            commitPendingXmlChanges();
+            getRootNode().getEditor().editXmlModel(new Runnable() {
+                public void run() {
+                    UiElementNode previous = null;
+                    UiElementNode parent = null;
+
+                    for (int i = len - 1; i >= 0; i--) {
+                        UiElementNode node = nodes.get(i);
+                        previous = node.getUiPreviousSibling();
+                        parent = node.getUiParent();
+                        
+                        // delete node
+                        node.deleteXmlNode();
+                    }
+                    
+                    // try to select the last previous sibling or the last parent
+                    if (previous != null) {
+                        selectUiNode(previous);
+                    } else if (parent != null) {
+                        selectUiNode(parent);
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * Called when the "Up" button is selected.
+     * <p/>
+     * If the tree has a selection, move it up, either in the child list or as the last child
+     * of the previous parent.
+     */
+    public void doUp(final List<UiElementNode> nodes) {
+        if (nodes == null || nodes.size() < 1) {
+            return;
+        }
+        
+        final Node[] select_xml_node = { null };
+        UiElementNode last_node = null;
+        UiElementNode search_root = null;
+        
+        for (int i = 0; i < nodes.size(); i++) {
+            final UiElementNode node = last_node = nodes.get(i);
+            
+            // the node will move either up to its parent or grand-parent
+            search_root = node.getUiParent();
+            if (search_root != null && search_root.getUiParent() != null) {
+                search_root = search_root.getUiParent();
+            }
+    
+            commitPendingXmlChanges();
+            getRootNode().getEditor().editXmlModel(new Runnable() {
+                public void run() {
+                    Node xml_node = node.getXmlNode();
+                    if (xml_node != null) {
+                        Node xml_parent = xml_node.getParentNode();
+                        if (xml_parent != null) {
+                            UiElementNode ui_prev = node.getUiPreviousSibling();
+                            if (ui_prev != null && ui_prev.getXmlNode() != null) {
+                                // This node is not the first one of the parent, so it can be
+                                // removed and then inserted before its previous sibling.
+                                // If the previous sibling can have children, though, then it
+                                // is inserted at the end of the children list.
+                                Node xml_prev = ui_prev.getXmlNode();
+                                if (ui_prev.getDescriptor().hasChildren()) {
+                                    xml_prev.appendChild(xml_parent.removeChild(xml_node));
+                                    select_xml_node[0] = xml_node;
+                                } else {
+                                    xml_parent.insertBefore(
+                                            xml_parent.removeChild(xml_node),
+                                            xml_prev);
+                                    select_xml_node[0] = xml_node;
+                                }
+                            } else if (!(xml_parent instanceof Document) &&
+                                    xml_parent.getParentNode() != null &&
+                                    !(xml_parent.getParentNode() instanceof Document)) {
+                                // If the node is the first one of the child list of its
+                                // parent, move it up in the hierarchy as previous sibling
+                                // to the parent. This is only possible if the parent of the
+                                // parent is not a document.
+                                Node grand_parent = xml_parent.getParentNode();
+                                grand_parent.insertBefore(xml_parent.removeChild(xml_node),
+                                        xml_parent);
+                                select_xml_node[0] = xml_node;
+                            }
+                        }
+                    }
+                }
+            });
+        }
+
+        if (select_xml_node[0] == null) {
+            // The XML node has not been moved, we can just select the same UI node
+            selectUiNode(last_node);
+        } else {
+            // The XML node has moved. At this point the UI model has been reloaded
+            // and the XML node has been affected to a new UI node. Find that new UI
+            // node and select it.
+            if (search_root == null) {
+                search_root = last_node.getUiRoot();
+            }
+            if (search_root != null) {
+                selectUiNode(search_root.findXmlNode(select_xml_node[0]));
+            }
+        }
+    }
+
+    /**
+     * Called when the "Down" button is selected.
+     * 
+     * If the tree has a selection, move it down, either in the same child list or as the
+     * first child of the next parent.
+     */
+    public void doDown(final List<UiElementNode> nodes) {
+        if (nodes == null || nodes.size() < 1) {
+            return;
+        }
+        
+        final Node[] select_xml_node = { null };
+        UiElementNode last_node = null;
+        UiElementNode search_root = null;
+
+        for (int i = nodes.size() - 1; i >= 0; i--) {
+            final UiElementNode node = last_node = nodes.get(i);
+            // the node will move either down to its parent or grand-parent
+            search_root = node.getUiParent();
+            if (search_root != null && search_root.getUiParent() != null) {
+                search_root = search_root.getUiParent();
+            }
+    
+            commitPendingXmlChanges();
+            getRootNode().getEditor().editXmlModel(new Runnable() {
+                public void run() {
+                    Node xml_node = node.getXmlNode();
+                    if (xml_node != null) {
+                        Node xml_parent = xml_node.getParentNode();
+                        if (xml_parent != null) {
+                            UiElementNode uiNext = node.getUiNextSibling();
+                            if (uiNext != null && uiNext.getXmlNode() != null) {
+                                // This node is not the last one of the parent, so it can be
+                                // removed and then inserted after its next sibling.
+                                // If the next sibling is a node that can have children, though,
+                                // then the node is inserted as the first child.
+                                Node xml_next = uiNext.getXmlNode();
+                                if (uiNext.getDescriptor().hasChildren()) {
+                                    // Note: insertBefore works as append if the ref node is
+                                    // null, i.e. when the node doesn't have children yet.
+                                    xml_next.insertBefore(xml_parent.removeChild(xml_node),
+                                            xml_next.getFirstChild());
+                                    select_xml_node[0] = xml_node;
+                                } else {
+                                    // Insert "before after next" ;-)
+                                    xml_parent.insertBefore(xml_parent.removeChild(xml_node),
+                                            xml_next.getNextSibling());
+                                    select_xml_node[0] = xml_node;
+                                }
+                            } else if (!(xml_parent instanceof Document) &&
+                                    xml_parent.getParentNode() != null &&
+                                    !(xml_parent.getParentNode() instanceof Document)) {
+                                // This node is the last node of its parent.
+                                // If neither the parent nor the grandparent is a document,
+                                // then the node can be insert right after the parent.
+                                Node grand_parent = xml_parent.getParentNode();
+                                grand_parent.insertBefore(xml_parent.removeChild(xml_node),
+                                        xml_parent.getNextSibling());
+                                select_xml_node[0] = xml_node;
+                            }
+                        }
+                    }
+                }
+            });
+        }
+
+        if (select_xml_node[0] == null) {
+            // The XML node has not been moved, we can just select the same UI node
+            selectUiNode(last_node);
+        } else {
+            // The XML node has moved. At this point the UI model has been reloaded
+            // and the XML node has been affected to a new UI node. Find that new UI
+            // node and select it.
+            if (search_root == null) {
+                search_root = last_node.getUiRoot();
+            }
+            if (search_root != null) {
+                selectUiNode(search_root.findXmlNode(select_xml_node[0]));
+            }
+        }
+    }
+
+    //---------------------
+    
+    /**
+     * Adds a new element of the given descriptor's type to the given UI parent node.
+     * 
+     * This actually creates the corresponding XML node in the XML model, which in turn
+     * will refresh the current tree view.
+     *  
+     * @param uiParent An existing UI node or null to add to the tree root
+     * @param uiSibling An existing UI node to insert right before. Can be null. 
+     * @param descriptor The descriptor of the element to add
+     * @param updateLayout True if layout attributes should be set
+     * @return The {@link UiElementNode} that has been added to the UI tree.
+     */
+    private UiElementNode addNewTreeElement(UiElementNode uiParent,
+            final UiElementNode uiSibling,
+            ElementDescriptor descriptor,
+            final boolean updateLayout) {
+        commitPendingXmlChanges();
+        
+        int index = 0;
+        for (UiElementNode uiChild : uiParent.getUiChildren()) {
+            if (uiChild == uiSibling) {
+                break;
+            }
+            index++;
+        }
+        
+        final UiElementNode uiNew = uiParent.insertNewUiChild(index, descriptor);
+        UiElementNode rootNode = getRootNode();
+
+        rootNode.getEditor().editXmlModel(new Runnable() {
+            public void run() {
+                DescriptorsUtils.setDefaultLayoutAttributes(uiNew, updateLayout);
+                Node xmlNode = uiNew.createXmlNode();
+            }
+        });
+        return uiNew;
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
similarity index 95%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
index 010e30e..15c67c3 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiElementDetail.java
@@ -16,14 +16,14 @@
 
 package com.android.ide.eclipse.editors.ui.tree;
 
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
+import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
 import com.android.ide.eclipse.editors.ui.SectionHelper;
 import com.android.ide.eclipse.editors.ui.SectionHelper.ManifestSectionPart;
 import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
@@ -130,7 +130,7 @@
             // Finally reset the dirty flag if everything was saved properly
             mIsDirty = false;
         } catch (Exception e) {
-            EditorsPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$
+            AdtPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$
         } finally {
             // Notify the model we're done modifying it. This must *always* be executed.
             model.changedModel();
@@ -260,9 +260,15 @@
             mCurrentUiElementNode = ui_node;
                 
             if (elem_desc.getTooltip() != null) {
-                String tooltip = DescriptorsUtils.formatFormText(elem_desc.getTooltip(),
-                        elem_desc,
-                        FrameworkResourceManager.getInstance().getDocumentationBaseUrl());
+                String tooltip;
+                if (Sdk.getCurrent() != null &&
+                        Sdk.getCurrent().getDocumentationBaseUrl() != null) {
+                    tooltip = DescriptorsUtils.formatFormText(elem_desc.getTooltip(),
+                            elem_desc,
+                            Sdk.getCurrent().getDocumentationBaseUrl());
+                } else {
+                    tooltip = elem_desc.getTooltip();
+                }
 
                 try {
                     FormText text = SectionHelper.createFormText(masterTable, toolkit,
@@ -275,7 +281,7 @@
                 } catch(Exception e) {
                     // The FormText parser is really really basic and will fail as soon as the
                     // HTML javadoc is ever so slightly malformatted.
-                    EditorsPlugin.log(e,
+                    AdtPlugin.log(e,
                             "Malformed javadoc, rejected by FormText for node %1$s: '%2$s'", //$NON-NLS-1$
                             ui_node.getDescriptor().getXmlName(),
                             tooltip);
@@ -320,7 +326,7 @@
                 } else {
                     // The XML has an extra unknown attribute.
                     // This is not expected to happen so it is ignored.
-                    EditorsPlugin.log(IStatus.INFO,
+                    AdtPlugin.log(IStatus.INFO,
                             "Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
                             attr_desc.getXmlLocalName(),
                             ui_node.getDescriptor().getXmlName());
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeContentProvider.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
index ff5f24c..273a30b 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiModelTreeLabelProvider.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.ui.tree;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.ui.ErrorImageComposite;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
@@ -62,7 +62,7 @@
                 }
             }
         }
-        return EditorsPlugin.getAndroidLogo();
+        return AdtPlugin.getAndroidLogo();
     }
 
     /**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
similarity index 74%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
index 7e7bd68..e3255d9 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/UiTreeBlock.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.ui.tree;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.IconFactory;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.ui.SectionHelper;
@@ -42,6 +42,7 @@
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.viewers.ViewerFilter;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.dnd.Clipboard;
 import org.eclipse.swt.events.DisposeEvent;
@@ -64,6 +65,8 @@
 import org.eclipse.ui.forms.widgets.FormToolkit;
 import org.eclipse.ui.forms.widgets.Section;
 
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.LinkedList;
 
 /**
@@ -117,9 +120,15 @@
     private IUiUpdateListener mUiRefreshListener;
     /** Listener to enable/disable the UI based on the application node's presence */
     private IUiUpdateListener mUiEnableListener;
-
+    /** An adapter/wrapper to use the add/remove/up/down tree edit actions. */
     private UiTreeActions mUiTreeActions;
-
+    /**
+     * True if the root node can be created on-demand (i.e. as needed as
+     * soon as children exist). False if an external entity controls the existence of the
+     * root node. In practise, this is false for the manifest application page (the actual
+     * "application" node is managed by the ApplicationToggle part) whereas it is true
+     * for all other tree pages.
+     */
     private final boolean mAutoCreateRoot;
 
 
@@ -192,10 +201,24 @@
 
     private void createSectionActions(Section section, FormToolkit toolkit) {
         ToolBarManager manager = new ToolBarManager(SWT.FLAT);
+        manager.removeAll();
+        
         ToolBar toolbar = manager.createControl(section);        
         section.setTextClient(toolbar);
         
+        ElementDescriptor[] descs = mDescriptorFilters;
+        if (descs == null && mUiRootNode != null) {
+            descs = mUiRootNode.getDescriptor().getChildren();
+        }
+        
+        if (descs != null && descs.length > 1) {
+            for (ElementDescriptor desc : descs) {
+                manager.add(new DescriptorFilterAction(desc));
+            }
+        }
+        
         manager.add(new TreeSortAction());
+
         manager.update(true /*force*/);
     }
 
@@ -207,7 +230,7 @@
             final IManagedForm managedForm) {
         // Note: we *could* use a FilteredTree instead of the Tree+TreeViewer here.
         // However the class must be adapted to create an adapted toolkit tree.
-        final Tree tree = toolkit.createTree(grid, SWT.SINGLE);
+        final Tree tree = toolkit.createTree(grid, SWT.MULTI);
         GridData gd = new GridData(GridData.FILL_BOTH);
         gd.widthHint = AndroidEditor.TEXT_WIDTH_HINT;
         gd.heightHint = TREE_HEIGHT_HINT;
@@ -283,7 +306,7 @@
         changeRootAndDescriptors(mUiRootNode, mDescriptorFilters, false /* refresh */);
 
         // Listen on resource framework changes to refresh the tree
-        EditorsPlugin.getDefault().addResourceChangedListener(resourceRefreshListener);
+        AdtPlugin.getDefault().addResourceChangedListener(resourceRefreshListener);
 
         // Remove listeners when the tree widget gets disposed.
         tree.addDisposeListener(new DisposeListener() {
@@ -295,7 +318,7 @@
                 node.removeUpdateListener(mUiRefreshListener);
                 mUiRootNode.removeUpdateListener(mUiEnableListener);
 
-                EditorsPlugin.getDefault().removeResourceChangedListener(resourceRefreshListener);
+                AdtPlugin.getDefault().removeResourceChangedListener(resourceRefreshListener);
                 if (mClipboard != null) {
                     mClipboard.dispose();
                     mClipboard = null;
@@ -350,6 +373,8 @@
         if (forceRefresh) {
             mTreeViewer.refresh();
         }
+
+        createSectionActions(mMasterPart.getSection(), mManagedForm.getToolkit());
     }
 
     /**
@@ -426,13 +451,9 @@
            public void menuAboutToShow(IMenuManager manager) {
                ISelection selection = mTreeViewer.getSelection();
                if (!selection.isEmpty() && selection instanceof ITreeSelection) {
-                   ITreeSelection tree_selection = (ITreeSelection) selection;
-                   Object first = tree_selection.getFirstElement();
-                   if (first != null && first instanceof UiElementNode) {
-                       UiElementNode ui_node = (UiElementNode) first;
-                       doCreateMenuAction(manager, ui_node);
-                       return;
-                   }
+                   ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+                   doCreateMenuAction(manager, selected);
+                   return;
                }
                doCreateMenuAction(manager, null /* ui_node */);
             } 
@@ -446,63 +467,78 @@
      * the tree view.
      * 
      * @param manager The context menu manager
-     * @param ui_node The UI node selected in the tree. Can be null, in which case the root
+     * @param selected The UI nodes selected in the tree. Can be null, in which case the root
      *                is to be modified.
      */
-    private void doCreateMenuAction(IMenuManager manager, UiElementNode ui_node) {
-        Action action;
-        
-        if (ui_node != null && ui_node.getXmlNode() != null) {
-            manager.add(new CopyCutAction(getEditor(), getClipboard(),
-                    this, ui_node, true /* cut */));
-            manager.add(new CopyCutAction(getEditor(), getClipboard(),
-                    this, ui_node, false /* cut */));
-            // Paste is not valid if it would add a second element on a terminal element
-            // which parent is a document -- an XML document can only have one child. This
-            // means paste is valid if the current UI node can have children or if the parent
-            // is not a document.
-            if (mUiRootNode.getDescriptor().hasChildren() ||
-                    !(mUiRootNode.getUiParent() instanceof UiDocumentNode)) {
-                manager.add(new PasteAction(getEditor(), getClipboard(), ui_node));
+    private void doCreateMenuAction(IMenuManager manager, ArrayList<UiElementNode> selected) {
+        if (selected != null) {
+            boolean hasXml = false;
+            for (UiElementNode uiNode : selected) {
+                if (uiNode.getXmlNode() != null) {
+                    hasXml = true;
+                    break;
+                }
             }
-            manager.add(new Separator());
+
+            if (hasXml) {
+                manager.add(new CopyCutAction(getEditor(), getClipboard(),
+                        null, selected, true /* cut */));
+                manager.add(new CopyCutAction(getEditor(), getClipboard(),
+                        null, selected, false /* cut */));
+
+                // Can't paste with more than one element selected (the selection is the target)
+                if (selected.size() <= 1) {
+                    // Paste is not valid if it would add a second element on a terminal element
+                    // which parent is a document -- an XML document can only have one child. This
+                    // means paste is valid if the current UI node can have children or if the
+                    // parent is not a document.
+                    UiElementNode ui_root = selected.get(0).getUiRoot();
+                    if (ui_root.getDescriptor().hasChildren() ||
+                            !(ui_root.getUiParent() instanceof UiDocumentNode)) {
+                        manager.add(new PasteAction(getEditor(), getClipboard(), selected.get(0)));
+                    }
+                }
+                manager.add(new Separator());
+            }
         }
 
         // Append "add" and "remove" actions. They do the same thing as the add/remove
         // buttons on the side.
-        
-        manager.add(new Action("Add...", EditorsPlugin.getAndroidLogoDesc()) {
-            @Override
-            public void run() {
-                super.run();
-                doTreeAdd();
-            }
-        });
-        
-        if (ui_node != null) {
-            manager.add(new Action("Remove", EditorsPlugin.getAndroidLogoDesc()) {
+        Action action;
+        IconFactory factory = IconFactory.getInstance();
+
+        // "Add" makes sense only if there's 0 or 1 item selected since the
+        // one selected item becomes the target.
+        if (selected == null || selected.size() <= 1) {
+            manager.add(new Action("Add...", factory.getImageDescriptor("add")) { //$NON-NLS-1$
                 @Override
                 public void run() {
                     super.run();
-                    doTreeRemove();
+                    doTreeAdd();
                 }
             });
         }
-        
-        manager.add(new Separator());
 
-        if (ui_node != null) {
-            manager.add(new Action("Up", EditorsPlugin.getAndroidLogoDesc()) {
+        if (selected != null) {
+            if (selected != null) {
+                manager.add(new Action("Remove", factory.getImageDescriptor("delete")) { //$NON-NLS-1$
+                    @Override
+                    public void run() {
+                        super.run();
+                        doTreeRemove();
+                    }
+                });
+            }
+            manager.add(new Separator());
+            
+            manager.add(new Action("Up", factory.getImageDescriptor("up")) { //$NON-NLS-1$
                 @Override
                 public void run() {
                     super.run();
                     doTreeUp();
                 }
             });
-        }
-        
-        if (ui_node != null) {
-            manager.add(new Action("Down", EditorsPlugin.getAndroidLogoDesc()) {
+            manager.add(new Action("Down", factory.getImageDescriptor("down")) { //$NON-NLS-1$
                 @Override
                 public void run() {
                     super.run();
@@ -555,6 +591,27 @@
     }
 
     /**
+     * Filters an ITreeSelection to only keep the {@link UiElementNode}s (in case there's
+     * something else in there).
+     * 
+     * @return A new list of {@link UiElementNode} with at least one item or null.
+     */
+    @SuppressWarnings("unchecked")
+    private ArrayList<UiElementNode> filterSelection(ITreeSelection selection) {
+        ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
+        
+        for (Iterator it = selection.iterator(); it.hasNext(); ) {
+            Object selectedObj = it.next();
+        
+            if (selectedObj instanceof UiElementNode) {
+                selected.add((UiElementNode) selectedObj);
+            }
+        }
+
+        return selected.size() > 0 ? selected : null;
+    }
+
+    /**
      * Called when the "Add..." button next to the tree view is selected.
      * 
      * Displays a selection dialog that lets the user select which kind of node
@@ -588,16 +645,11 @@
     protected void doTreeRemove() {
         ISelection selection = mTreeViewer.getSelection();
         if (!selection.isEmpty() && selection instanceof ITreeSelection) {
-            ITreeSelection tree_selection = (ITreeSelection) selection;
-            Object first = tree_selection.getFirstElement();
-            if (first instanceof UiElementNode) {
-                final UiElementNode ui_node = (UiElementNode) first;
-
-                mUiTreeActions.doRemove(ui_node, mTreeViewer.getControl().getShell());
-            }
+            ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+            mUiTreeActions.doRemove(selected, mTreeViewer.getControl().getShell());
         }
     }
-    
+
     /**
      * Called when the "Up" button is selected.
      * <p/>
@@ -607,13 +659,8 @@
     protected void doTreeUp() {
         ISelection selection = mTreeViewer.getSelection();
         if (!selection.isEmpty() && selection instanceof ITreeSelection) {
-            ITreeSelection tree_selection = (ITreeSelection) selection;
-            Object first = tree_selection.getFirstElement();
-            if (first instanceof UiElementNode) {
-                final UiElementNode ui_node = (UiElementNode) first;
-
-                mUiTreeActions.doUp(ui_node);
-            }
+            ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+            mUiTreeActions.doUp(selected);
         }
     }
     
@@ -626,13 +673,8 @@
     protected void doTreeDown() {
         ISelection selection = mTreeViewer.getSelection();
         if (!selection.isEmpty() && selection instanceof ITreeSelection) {
-            ITreeSelection tree_selection = (ITreeSelection) selection;
-            Object first = tree_selection.getFirstElement();
-            if (first instanceof UiElementNode) {
-                final UiElementNode ui_node = (UiElementNode) first;
-
-                mUiTreeActions.doDown(ui_node);
-            }
+            ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
+            mUiTreeActions.doDown(selected);
         }
     }
 
@@ -653,7 +695,7 @@
 
     @Override
     protected void createToolBarActions(IManagedForm managedForm) {
-        // pass
+        // Pass. Not used, toolbar actions are defined by createSectionActions().
     }
 
     @Override
@@ -686,14 +728,14 @@
     }
 
     /**
-     * Adds a sort action to the tree viewer.
+     * An alphabetic sort action for the tree viewer.
      */
     private class TreeSortAction extends Action {
         
         private ViewerComparator mComparator;
 
         public TreeSortAction() {
-            setToolTipText("Sorts elements alphabetically.");
+            super("Sorts elements alphabetically.", AS_CHECK_BOX);
             setImageDescriptor(IconFactory.getInstance().getImageDescriptor("az_sort")); //$NON-NLS-1$
  
             if (mTreeViewer != null) {
@@ -703,7 +745,7 @@
         }
 
         /**
-         * Called when the button is selected. Toggle the tree viewer comparator.
+         * Called when the button is selected. Toggles the tree viewer comparator.
          */
         @Override
         public void run() {
@@ -730,4 +772,97 @@
             notifyResult(true /*success*/);
         }
     }
+
+    /**
+     * A filter on descriptor for the tree viewer.
+     * <p/>
+     * The tree viewer will contain many of these actions and only one can be enabled at a
+     * given time. When no action is selected, everything is displayed.
+     * <p/>
+     * Since "radio"-like actions do not allow for unselecting all of them, we manually
+     * handle the exclusive radio button-like property: when an action is selected, it manually
+     * removes all other actions as needed.
+     */
+    private class DescriptorFilterAction extends Action {
+
+        private final ElementDescriptor mDescriptor;
+        private ViewerFilter mFilter;
+        
+        public DescriptorFilterAction(ElementDescriptor descriptor) {
+            super(String.format("Displays only %1$s elements.", descriptor.getUiName()),
+                    AS_CHECK_BOX);
+            
+            mDescriptor = descriptor;
+            setImageDescriptor(descriptor.getImageDescriptor());
+        }
+
+        /**
+         * Called when the button is selected.
+         * <p/>
+         * Find any existing {@link DescriptorFilter}s and remove them. Install ours.
+         */
+        @Override
+        public void run() {
+            super.run();
+            
+            if (isChecked()) {
+                if (mFilter == null) {
+                    // create filter when required
+                    mFilter = new DescriptorFilter(this);
+                }
+
+                // we add our filter first, otherwise the UI might show the full list
+                mTreeViewer.addFilter(mFilter);
+
+                // Then remove the any other filters except ours. There should be at most
+                // one other filter, since that's how the actions are made to look like
+                // exclusive radio buttons.
+                for (ViewerFilter filter : mTreeViewer.getFilters()) {
+                    if (filter instanceof DescriptorFilter && filter != mFilter) {
+                        DescriptorFilterAction action = ((DescriptorFilter) filter).getAction();
+                        action.setChecked(false);
+                        mTreeViewer.removeFilter(filter);
+                    }
+                }
+            } else if (mFilter != null){
+                mTreeViewer.removeFilter(mFilter);
+            }
+        }
+
+        /**
+         * Filters the tree viewer for the given descriptor.
+         * <p/>
+         * The filter is linked to the action so that an action can iterate through the list
+         * of filters and un-select the actions.
+         */
+        private class DescriptorFilter extends ViewerFilter {
+
+            private final DescriptorFilterAction mAction;
+
+            public DescriptorFilter(DescriptorFilterAction action) {
+                mAction = action;
+            }
+            
+            public DescriptorFilterAction getAction() {
+                return mAction;
+            }
+
+            /**
+             * Returns true if an element should be displayed, that if the element or
+             * any of its parent matches the requested descriptor.
+             */
+            @Override
+            public boolean select(Viewer viewer, Object parentElement, Object element) {
+                while (element instanceof UiElementNode) {
+                    UiElementNode uiNode = (UiElementNode)element;
+                    if (uiNode.getDescriptor() == mDescriptor) {
+                        return true;
+                    }
+                    element = uiNode.getUiParent();
+                }
+                return false;
+            }
+        }
+    }
+    
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
index 4c368d9..7fe44da 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiSettableAttributeNode.java
@@ -26,7 +26,7 @@
     /** Returns the current value of the node. */
     public String getCurrentValue();
     
-    /** Sets the current value of the node. */
+    /** Sets the current value of the node. Cannot be null (use an empty string). */
     public void setCurrentValue(String value);
 
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/IUiUpdateListener.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
index 17b077a..5908574 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAbstractTextAttributeNode.java
@@ -37,7 +37,7 @@
 
     /** Prevent internal listener from firing when internally modifying the text */
     private boolean mInternalTextModification;
-    /** Last value read from the XML model */
+    /** Last value read from the XML model. Cannot be null. */
     private String mCurrentValue = DEFAULT_VALUE;
 
     public UiAbstractTextAttributeNode(AttributeDescriptor attributeDescriptor,
@@ -51,7 +51,7 @@
         return mCurrentValue;
     }
     
-    /** Sets the current value of the node. */
+    /** Sets the current value of the node. Cannot be null (use an empty string). */
     public final void setCurrentValue(String value) {
         mCurrentValue = value;
     }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiAttributeNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiDocumentNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
index 22b68b3..e0e9a40 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiElementNode.java
@@ -16,9 +16,10 @@
 
 package com.android.ide.eclipse.editors.uimodel;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
@@ -29,6 +30,7 @@
 import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
 import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
 import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener.UiUpdateState;
+import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.ui.IEditorInput;
@@ -206,6 +208,10 @@
                                            AndroidManifestDescriptors.ANDROID_LABEL_ATTR);
             }
             if (attr == null || attr.length() == 0) {
+                attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES,
+                                           XmlDescriptors.PREF_KEY_ATTR);
+            }
+            if (attr == null || attr.length() == 0) {
                 attr = elem.getAttribute(ResourcesDescriptors.NAME_ATTR);
             }
             if (attr == null || attr.length() == 0) {
@@ -426,6 +432,13 @@
     public AndroidEditor getEditor() {
         return mUiParent == null ? mEditor : mUiParent.getEditor();
     }
+    
+    /**
+     * Returns the Android target data for the file being edited.
+     */
+    public AndroidTargetData getAndroidTarget() {
+        return getEditor().getTargetData();
+    }
 
     /**
      * @return A read-only version of the children collection.
@@ -447,7 +460,7 @@
         }
         return mReadOnlyUiAttributes;
     }
-    
+
     /**
      * @return A read-only version of the unknown attributes collection.
      */
@@ -564,7 +577,7 @@
         
         return null;
     }
-    
+
     /**
      * Returns the {@link UiAttributeNode} matching this attribute descriptor or
      * null if not found.
@@ -719,7 +732,16 @@
         }
 
         mXmlNode = doc.createElement(element_name);
-        parentXmlNode.appendChild(mXmlNode);
+        
+        Node xmlNextSibling = null;
+
+        UiElementNode uiNextSibling = getUiNextSibling();
+        if (uiNextSibling != null) {
+            xmlNextSibling = uiNextSibling.getXmlNode();
+        }
+
+        parentXmlNode.insertBefore(mXmlNode, xmlNextSibling);
+
         // Insert a separator after the tag, to make it easier to read
         Text sep = doc.createTextNode("\n");
         parentXmlNode.appendChild(sep);
@@ -736,7 +758,7 @@
                 attr.setPrefix(desc.getXmlNsPrefix());
                 mXmlNode.getAttributes().setNamedItemNS(attr);
             } else {
-                UiAttributeNode ui_attr = mUiAttributes.get(attr_desc);
+                UiAttributeNode ui_attr = getInternalUiAttributes().get(attr_desc);
                 commitAttributeToXml(ui_attr, ui_attr.getCurrentValue());
             }
         }
@@ -873,7 +895,7 @@
                                 false /* recursive */);
                         if (desc == null) {
                             // Unknown element. Simply ignore it.
-                            EditorsPlugin.log(IStatus.WARNING,
+                            AdtPlugin.log(IStatus.WARNING,
                                     "AndroidManifest: Ignoring unknown '%s' XML element", //$NON-NLS-1$
                                     element_name);
                         } else {
@@ -953,7 +975,7 @@
      * @param descriptor The {@link ElementDescriptor} that knows how to create the UI node.
      * @return The new UI node.
      */
-    private UiElementNode insertNewUiChild(int index, ElementDescriptor descriptor) {
+    public UiElementNode insertNewUiChild(int index, ElementDescriptor descriptor) {
         UiElementNode ui_node;
         ui_node = descriptor.createUiNode();
         mUiChildren.add(index, ui_node);
@@ -1064,7 +1086,7 @@
                     listener.uiElementNodeUpdated(this, state);
                 } catch (Exception e) {
                     // prevent a crashing listener from crashing the whole invocation chain
-                    EditorsPlugin.log(e, "UIElement Listener failed: %s, state=%s",  //$NON-NLS-1$
+                    AdtPlugin.log(e, "UIElement Listener failed: %s, state=%s",  //$NON-NLS-1$
                             getBreadcrumbTrailDescription(true),
                             state.toString());
                 }
@@ -1112,6 +1134,8 @@
      * Note that the caller MUST ensure that modifying the underlying XML model is
      * safe and must take care of marking the model as dirty if necessary.
      * 
+     * @see AndroidEditor#editXmlModel(Runnable)
+     * 
      * @param uiAttr The attribute node to commit. Must be a child of this UiElementNode.
      * @param newValue The new value to set.
      * @return True if the XML attribute was modified or removed, false if nothing changed.
@@ -1119,7 +1143,7 @@
     public boolean commitAttributeToXml(UiAttributeNode uiAttr, String newValue) {
         // Get (or create) the underlying XML element node that contains the attributes.
         Node element = prepareCommit();
-        if (element != null) {
+        if (element != null && uiAttr != null) {
             String attrLocalName = uiAttr.getDescriptor().getXmlLocalName();
             String attrNsUri = uiAttr.getDescriptor().getNamespaceUri();
             
@@ -1146,6 +1170,36 @@
     }
 
     /**
+     * Helper method to commit all dirty attributes values to XML.
+     * <p/>
+     * This method is useful if {@link #setAttributeValue(String, String, boolean)} has been
+     * called more than once and all the attributes marked as dirty must be commited to the
+     * XML. It calls {@link #commitAttributeToXml(UiAttributeNode, String)} on each dirty
+     * attribute.
+     * <p/>
+     * Note that the caller MUST ensure that modifying the underlying XML model is
+     * safe and must take care of marking the model as dirty if necessary.
+     * 
+     * @see AndroidEditor#editXmlModel(Runnable)
+     * 
+     * @return True if one or more values were actually modified or removed,
+     *         false if nothing changed.
+     */
+    public boolean commitDirtyAttributesToXml() {
+        boolean result = false;
+        HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();
+        
+        for (Entry<AttributeDescriptor, UiAttributeNode> entry : attributeMap.entrySet()) {
+            UiAttributeNode ui_attr = entry.getValue();
+            if (ui_attr.isDirty()) {
+                result |= commitAttributeToXml(ui_attr, ui_attr.getCurrentValue());
+                ui_attr.setDirty(false);
+            }
+        }
+        return result;
+    }
+
+    /**
      * Returns the namespace prefix matching the requested namespace URI.
      * If no such declaration is found, returns the default "android" prefix.
      *  
@@ -1226,13 +1280,21 @@
      * This does not commit to the XML model. It does mark the attribute node as dirty.
      * This is up to the caller.
      * 
+     * @see #commitAttributeToXml(UiAttributeNode, String)
+     * @see #commitDirtyAttributesToXml()
+     * 
      * @param attrXmlName The XML name of the attribute to modify
-     * @param value The new value for the attribute.
+     * @param value The new value for the attribute. If set to null, the attribute is removed.
      * @param override True if the value must be set even if one already exists.
+     * @return The {@link UiAttributeNode} that has been modified or null.
      */
-    public void setAttributeValue(String attrXmlName, String value, boolean override) {
+    public UiAttributeNode setAttributeValue(String attrXmlName, String value, boolean override) {
         HashMap<AttributeDescriptor, UiAttributeNode> attributeMap = getInternalUiAttributes();
         
+        if (value == null) {
+            value = ""; //$NON-NLS-1$ -- this removes an attribute
+        }
+        
         for (Entry<AttributeDescriptor, UiAttributeNode> entry : attributeMap.entrySet()) {
             AttributeDescriptor ui_desc = entry.getKey();
             if (ui_desc.getXmlLocalName().equals(attrXmlName)) {
@@ -1240,16 +1302,20 @@
                 // Not all attributes are editable, ignore those which are not
                 if (ui_attr instanceof IUiSettableAttributeNode) {
                     String current = ui_attr.getCurrentValue();
-                    if (override || current == null || current.length() == 0) {
+                    // Only update (and mark as dirty) if the attribute did not have any
+                    // value or if the value was different.
+                    if (override || current == null || !current.equals(value)) {
                         ((IUiSettableAttributeNode) ui_attr).setCurrentValue(value);
                         // mark the attribute as dirty since their internal content
                         // as been modified, but not the underlying XML model
                         ui_attr.setDirty(true);
+                        return ui_attr;
                     }
                 }
                 break;
             }
         }
+        return null;
     }
 
     /**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
index 4e0a8c7..ddcf0a0 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiFlagAttributeNode.java
@@ -16,7 +16,8 @@
 
 package com.android.ide.eclipse.editors.uimodel;
 
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.editors.AndroidEditor;
 import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
 import com.android.ide.eclipse.editors.descriptors.FlagAttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
@@ -138,8 +139,13 @@
         }
 
         if (values == null) {
-            // or from the framework resource manager
-            values = FrameworkResourceManager.getInstance().getValues(element_name, attr_name);
+            // or from the AndroidTargetData
+            UiElementNode uiNode = getUiParent();
+            AndroidEditor editor = uiNode.getEditor();
+            AndroidTargetData data = editor.getTargetData();
+            if (data != null) {
+                values = data.getAttributeValues(element_name, attr_name);
+            }
         }
         
         return values;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
similarity index 84%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
index 261e146..aaad0ce 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiListAttributeNode.java
@@ -16,9 +16,10 @@
 
 package com.android.ide.eclipse.editors.uimodel;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.editors.AndroidEditor;
 import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
 import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
@@ -110,7 +111,7 @@
         String[] values = getPossibleValues();
 
         if (values == null) {
-            EditorsPlugin.log(IStatus.ERROR,
+            AdtPlugin.log(IStatus.ERROR,
                     "FrameworkResourceManager did not provide values yet for %1$s",
                     getDescriptor().getXmlLocalName());
         } else {
@@ -150,21 +151,27 @@
         }
 
         if (values == null) {
-            // or from the framework resource manager
-            // get the great-grand-parent descriptor.
-            
-            // the parent should always exist.
-            UiElementNode grandParentNode = uiParent.getUiParent();
-
-            String greatGrandParentNodeName = null;
-            if (grandParentNode != null) {
-                UiElementNode greatGrandParentNode = grandParentNode.getUiParent();
-                if (greatGrandParentNode != null) {
-                    greatGrandParentNodeName = greatGrandParentNode.getDescriptor().getXmlName();
+            // or from the AndroidTargetData
+            UiElementNode uiNode = getUiParent();
+            AndroidEditor editor = uiNode.getEditor();
+            AndroidTargetData data = editor.getTargetData();
+            if (data != null) {
+                // get the great-grand-parent descriptor.
+                
+                // the parent should always exist.
+                UiElementNode grandParentNode = uiParent.getUiParent();
+    
+                String greatGrandParentNodeName = null;
+                if (grandParentNode != null) {
+                    UiElementNode greatGrandParentNode = grandParentNode.getUiParent();
+                    if (greatGrandParentNode != null) {
+                        greatGrandParentNodeName =
+                            greatGrandParentNode.getDescriptor().getXmlName();
+                    }
                 }
+            
+                values = data.getAttributeValues(element_name, attr_name, greatGrandParentNodeName);
             }
-            values = FrameworkResourceManager.getInstance().getValues(element_name, attr_name,
-                    greatGrandParentNodeName);
         }
         
         return values;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
similarity index 89%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
index 132ccc0..1c1e1bd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.uimodel;
 
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.common.resources.IResourceRepository;
 import com.android.ide.eclipse.common.resources.ResourceType;
 import com.android.ide.eclipse.editors.AndroidEditor;
@@ -28,7 +28,6 @@
 import com.android.ide.eclipse.editors.wizards.ReferenceChooserDialog;
 import com.android.ide.eclipse.editors.wizards.ResourceChooser;
 
-import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.jface.window.Window;
 import org.eclipse.swt.SWT;
@@ -41,8 +40,6 @@
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IFileEditorInput;
 import org.eclipse.ui.forms.IManagedForm;
 import org.eclipse.ui.forms.widgets.FormToolkit;
 import org.eclipse.ui.forms.widgets.TableWrapData;
@@ -118,22 +115,19 @@
      * containing the result.
      */
     public String showDialog(Shell shell, String currentValue) {
-        // we need to get the project of the manifest.
+        // we need to get the project of the file being edited.
         UiElementNode uiNode = getUiParent();
         AndroidEditor editor = uiNode.getEditor();
-        IEditorInput input = editor.getEditorInput();
-        if (input instanceof IFileEditorInput) {
-            // from the file editor we can get the IFile object, and from it, the IProject.
-            IFile file = ((IFileEditorInput)input).getFile();
-            IProject project = file.getProject();
-
+        IProject project = editor.getProject();
+        if (project != null) {
             // get the resource repository for this project and the system resources.
             IResourceRepository projectRepository =
                 ResourceManager.getInstance().getProjectResources(project);
             
             if (mType != null) {
-                IResourceRepository systemRepository =
-                    FrameworkResourceManager.getInstance().getSystemResources();
+                // get the Target Data to get the system resources
+                AndroidTargetData data = editor.getTargetData();
+                IResourceRepository systemRepository = data.getSystemResources();
 
                 // open a resource chooser dialog for specified resource type.
                 ResourceChooser dlg = new ResourceChooser(mType,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiSeparatorAttributeNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextAttributeNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiTextValueNode.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
index 39cfc58..b7dffdd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ConfigurationSelector.java
@@ -604,6 +604,8 @@
                     onTextChange();
                 }
             });
+            
+            new Label(this, SWT.NONE).setText("(3 digit code)");
         }
         
         private void onTextChange() {
@@ -666,6 +668,8 @@
                     onTextChange();
                 }
             });
+
+            new Label(this, SWT.NONE).setText("(1-3 digit code)");
         }
         
         private void onTextChange() {
@@ -731,6 +735,8 @@
                     onLanguageChange();
                 }
             });
+
+            new Label(this, SWT.NONE).setText("(2 letter code)");
         }
 
         private void onLanguageChange() {
@@ -797,6 +803,8 @@
                     onRegionChange();
                 }
             });
+
+            new Label(this, SWT.NONE).setText("(2 letter code)");
         }
 
         private void onRegionChange() {
@@ -1236,11 +1244,8 @@
             String size1 = mSize1.getText();
             String size2 = mSize2.getText();
             
-            // if only one of the strings is empty, do nothing
-            if ((size1.length() == 0) ^ (size2.length() == 0)) {
-                return;
-            } else if (size1.length() == 0 && size2.length() == 0) {
-                // empty size, means no qualifier.
+            if (size1.length() == 0 || size2.length() == 0) {
+                // if one of the strings is empty, reset to no qualifier.
                 // Since the qualifier classes are immutable, and we don't want to
                 // remove the qualifier from the configuration, we create a new default one.
                 mSelectedConfiguration.setScreenDimensionQualifier(new ScreenDimensionQualifier());
@@ -1251,9 +1256,11 @@
                 if (qualifier != null) {
                     mSelectedConfiguration.setScreenDimensionQualifier(qualifier);
                 } else {
-                    // Failure! Looks like the value is wrong.
-                    // we do nothing in this case.
-                    return;
+                    // Failure! Looks like the value is wrong, reset the qualifier
+                    // Since the qualifier classes are immutable, and we don't want to
+                    // remove the qualifier from the configuration, we create a new default one.
+                    mSelectedConfiguration.setScreenDimensionQualifier(
+                            new ScreenDimensionQualifier());
                 }
             }
    
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
similarity index 93%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
index 2f3209b..b27dd4f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java
@@ -17,18 +17,19 @@
 
 package com.android.ide.eclipse.editors.wizards;
 
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.ProjectChooserHelper;
 import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
 import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
 import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration;
 import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier;
 import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
 import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
 import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.ConfigurationState;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
@@ -184,7 +185,7 @@
                 "Layout",                                           // UI name
                 "An XML file that describes a screen layout.",      // tooltip
                 ResourceFolderType.LAYOUT,                          // folder type
-                LayoutDescriptors.getInstance().getDescriptor(),    // root seed
+                AndroidTargetData.DESCRIPTOR_LAYOUT,                // root seed
                 "LinearLayout",                                     // default root
                 AndroidConstants.NS_RESOURCES,                      // xmlns
                 "android:layout_width=\"wrap_content\"\n" +         // default attributes
@@ -209,7 +210,7 @@
         new TypeInfo("Preference",                                  // UI name
                 "An XML file that describes preferences.",          // tooltip
                 ResourceFolderType.XML,                             // folder type
-                XmlDescriptors.getInstance().getPreferencesDescriptor(), // root seed
+                AndroidTargetData.DESCRIPTOR_PREFERENCES,           // root seed
                 AndroidConstants.CLASS_PREFERENCE_SCREEN,           // default root
                 AndroidConstants.NS_RESOURCES,                      // xmlns
                 null                                                // default attributes
@@ -217,7 +218,7 @@
         new TypeInfo("Searchable",                                  // UI name
                 "An XML file that describes a searchable [TODO].",  // tooltip
                 ResourceFolderType.XML,                             // folder type
-                XmlDescriptors.getInstance().getSearchableDescriptor(), // root seed
+                AndroidTargetData.DESCRIPTOR_SEARCHABLE,            // root seed
                 null,                                               // default root
                 AndroidConstants.NS_RESOURCES,                      // xmlns
                 null                                                // default attributes
@@ -431,6 +432,11 @@
         mProjectTextField = new Text(parent, SWT.BORDER);
         mProjectTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
         mProjectTextField.setToolTipText(tooltip);
+        mProjectTextField.addModifyListener(new ModifyListener() {
+            public void modifyText(ModifyEvent e) {
+                onProjectFieldUpdated();
+            }
+        });
 
         mProjectBrowseButton = new Button(parent, SWT.NONE);
         mProjectBrowseButton.setText("Browse...");
@@ -655,9 +661,10 @@
      */
     private void initializeRootValues() {
         for (TypeInfo type : sTypes) {
+            // Clear all the roots for this type
             ArrayList<String> roots = type.getRoots();
             if (roots.size() > 0) {
-                continue;
+                roots.clear();
             }
             
             // depending of the type of the seed, initialize the root in different ways
@@ -671,13 +678,22 @@
                 for (String value : (String[]) rootSeed) {
                     roots.add(value);
                 }
-            } else if (rootSeed instanceof ElementDescriptor) {
-                // The seed is an element descriptor or a document descriptor.
+            } else if (rootSeed instanceof Integer && mProject != null) {
+                // The seed is a descriptor reference defined in AndroidTargetData.DESCRIPTOR_*
                 // In this case add all the children element descriptors defined, recursively,
                 // and avoid infinite recursion by keeping track of what has already been added.
+
+                // Note: if project is null, the root list will be empty since it has been
+                // cleared above.
+                
+                // get the AndroidTargetData from the project
+                IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
+                AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
+                ElementDescriptor descriptor = data.getDescriptorProvider(
+                        (Integer)rootSeed).getDescriptor();
                 
                 HashSet<ElementDescriptor> visited = new HashSet<ElementDescriptor>();
-                initRootElementDescriptor(roots, (ElementDescriptor) rootSeed, visited);
+                initRootElementDescriptor(roots, descriptor, visited);
 
                 // Sort alphabetically.
                 Collections.sort(roots);
@@ -708,6 +724,35 @@
             }
         }
     }
+    
+    /**
+     * Callback called when the user edits the project text field.
+     */
+    private void onProjectFieldUpdated() {
+        String project = mProjectTextField.getText();
+        
+        // Is this a valid project?
+        IJavaProject[] projects = mProjectChooserHelper.getAndroidProjects(null /*javaModel*/);
+        IProject found = null;
+        for (IJavaProject p : projects) {
+            if (p.getProject().getName().equals(project)) {
+                found = p.getProject();
+                break;
+            }
+        }
+
+        if (found != mProject) {
+            mProject = found;
+
+            // update the Type with the new descriptors.
+            initializeRootValues();
+            
+            // update the combo
+            updateRootCombo(getSelectedType());
+            
+            validatePage();
+        }
+    }
 
     /**
      * Callback called when the user uses the "Browse Projects" button.
@@ -717,6 +762,13 @@
         if (p != null) {
             mProject = p.getProject();
             mProjectTextField.setText(mProject.getName());
+            
+            // update the Type with the new descriptors.
+            initializeRootValues();
+            
+            // update the combo
+            updateRootCombo(getSelectedType());
+            
             validatePage();
         }
     } 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
similarity index 93%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
index 8318e4b..125102b 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java
@@ -18,7 +18,7 @@
 
 package com.android.ide.eclipse.editors.wizards;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.IconFactory;
 import com.android.ide.eclipse.editors.wizards.NewXmlFileCreationPage.TypeInfo;
 
@@ -116,7 +116,7 @@
                     try {
                         IDE.openEditor(page, file);
                     } catch (PartInitException e) {
-                        EditorsPlugin.log(e, "Failed to create %1$s: missing type",  //$NON-NLS-1$
+                        AdtPlugin.log(e, "Failed to create %1$s: missing type",  //$NON-NLS-1$
                                 file.getFullPath().toString());
                     }
                 }
@@ -133,7 +133,7 @@
         boolean need_delete = false;
 
         if (file.exists()) {
-            if (!EditorsPlugin.displayPrompt("New Android XML File",
+            if (!AdtPlugin.displayPrompt("New Android XML File",
                 String.format("Do you want to overwrite the file %1$s ?", name))) {
                 // abort if user selects cancel.
                 return null;
@@ -146,14 +146,14 @@
         TypeInfo type = mMainPage.getSelectedType();
         if (type == null) {
             // this is not expected to happen
-            EditorsPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing type", name);  //$NON-NLS-1$
+            AdtPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing type", name);  //$NON-NLS-1$
             return null;
         }
         String xmlns = type.getXmlns();
         String root = mMainPage.getRootElement();
         if (root == null) {
             // this is not expected to happen
-            EditorsPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing root element", //$NON-NLS-1$
+            AdtPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing root element", //$NON-NLS-1$
                     file.toString());
             return null;
         }
@@ -191,7 +191,7 @@
         }
 
         error = String.format("Failed to generate %1$s: %2$s", name, error);
-        EditorsPlugin.displayError("New Android XML File", error);
+        AdtPlugin.displayError("New Android XML File", error);
         return null;
     }
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
similarity index 97%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
index 446cc14..d3ff334 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ReferenceChooserDialog.java
@@ -16,6 +16,7 @@
 
 package com.android.ide.eclipse.editors.wizards;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.resources.IResourceRepository;
 import com.android.ide.eclipse.common.resources.ResourceItem;
@@ -187,16 +188,16 @@
         IStatus status;
         if (treeSelection != null) {
             if (treeSelection.getSegmentCount() == 2) {
-                status = new Status(IStatus.OK, AndroidConstants.EDITORS_PLUGIN_ID,
+                status = new Status(IStatus.OK, AdtPlugin.PLUGIN_ID,
                         IStatus.OK, "", //$NON-NLS-1$
                         null);
             } else {
-                status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+                status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
                         IStatus.ERROR, "You must select a Resource Item",
                         null);
             }
         } else {
-            status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
+            status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
                     IStatus.ERROR, "", //$NON-NLS-1$
                     null);
         }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceChooser.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceContentProvider.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/ResourceLabelProvider.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
similarity index 86%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
index bb010e3..f28b523 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlContentAssist.java
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.editors.xml;
 
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
 import com.android.ide.eclipse.editors.AndroidContentAssist;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
 
 /**
  * Content Assist Processor for /res/xml XML files
@@ -28,6 +28,6 @@
      * Constructor for LayoutContentAssist 
      */
     public XmlContentAssist() {
-        super(XmlDescriptors.getInstance().getDescriptor().getChildren());
+        super(AndroidTargetData.DESCRIPTOR_XML);
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
similarity index 61%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
index 40d655a..b1900ae 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlEditor.java
@@ -16,16 +16,19 @@
 
 package com.android.ide.eclipse.editors.xml;
 
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
 import com.android.ide.eclipse.editors.FirstElementParser;
 import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
 import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
+import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.PartInitException;
@@ -37,19 +40,16 @@
  */
 public class XmlEditor extends AndroidEditor {
 
-    public static final String ID = "com.android.ide.eclipse.editors.xml.XmlEditor"; //$NON-NLS-1$
+    public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".xml.XmlEditor"; //$NON-NLS-1$
 
     /** Root node of the UI element hierarchy */
     private UiDocumentNode mUiRootNode;
-    /** Listener to update the root node if the resource framework changes */
-    private Runnable mResourceRefreshListener;
 
     /**
      * Creates the form editor for resources XML files.
      */
     public XmlEditor() {
         super();
-        initUiRootNode();
     }
 
     /**
@@ -72,19 +72,25 @@
      * @return True if the {@link XmlEditor} can handle that file.
      */
     public static boolean canHandleFile(IFile file) {
-
-        FirstElementParser.Result result = FirstElementParser.parse(
-                file.getLocation().toOSString(),
-                AndroidConstants.NS_RESOURCES);
+        // we need the target of the file's project to access the descriptors.
+        IProject project = file.getProject();
+        IAndroidTarget target = Sdk.getCurrent().getTarget(project);
+        if (target != null) {
+            AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
         
-        if (result != null) {
-            String name = result.getElement(); 
-            if (name != null && result.getXmlnsPrefix() != null) {
-                DocumentDescriptor desc = XmlDescriptors.getInstance().getDescriptor();
-                for (ElementDescriptor elem : desc.getChildren()) {
-                    if (elem.getXmlName().equals(name)) {
-                        // This is an element that this document can handle
-                        return true;
+            FirstElementParser.Result result = FirstElementParser.parse(
+                    file.getLocation().toOSString(),
+                    AndroidConstants.NS_RESOURCES);
+            
+            if (result != null) {
+                String name = result.getElement(); 
+                if (name != null && result.getXmlnsPrefix() != null) {
+                    DocumentDescriptor desc = data.getXmlDescriptors().getDescriptor();
+                    for (ElementDescriptor elem : desc.getChildren()) {
+                        if (elem.getXmlName().equals(name)) {
+                            // This is an element that this document can handle
+                            return true;
+                        }
                     }
                 }
             }
@@ -95,15 +101,6 @@
 
     // ---- Base Class Overrides ----
 
-    @Override
-    public void dispose() {
-        if (mResourceRefreshListener != null) {
-            EditorsPlugin.getDefault().removeResourceChangedListener(mResourceRefreshListener);
-            mResourceRefreshListener = null;
-        }
-        super.dispose();
-    }
-    
     /**
      * Returns whether the "save as" operation is supported by this editor.
      * <p/>
@@ -125,10 +122,10 @@
         try {
             addPage(new XmlTreePage(this));
         } catch (PartInitException e) {
-            EditorsPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
+            AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
         }
         
-     }
+    }
 
     /* (non-java doc)
      * Change the tab/title name to include the project name.
@@ -150,35 +147,55 @@
      */
     @Override
     protected void xmlModelChanged(Document xml_doc) {
+        // init the ui root on demand
+        initUiRootNode(false /*force*/);
+
         mUiRootNode.loadFromXmlNode(xml_doc);
         
         super.xmlModelChanged(xml_doc);
     }
-
     
-    // ---- Local Methods ----
-
     /**
      * Creates the initial UI Root Node, including the known mandatory elements.
+     * @param force if true, a new UiRootNode is recreated even if it already exists.
      */
-    private void initUiRootNode() {
+    @Override
+    protected void initUiRootNode(boolean force) {
         // The root UI node is always created, even if there's no corresponding XML node.
-        if (mUiRootNode == null) {
-            DocumentDescriptor desc = XmlDescriptors.getInstance().getDescriptor();
+        if (mUiRootNode == null || force) {
+            Document doc = null;
+            if (mUiRootNode != null) {
+                doc = mUiRootNode.getXmlDocument();
+            }
+
+            // get the target data from the opened file (and its project)
+            AndroidTargetData data = getTargetData();
+
+            DocumentDescriptor desc;
+            if (data == null) {
+                desc = new DocumentDescriptor("temp", null /*children*/);
+            } else {
+                desc = data.getXmlDescriptors().getDescriptor();
+            }
+
             mUiRootNode = (UiDocumentNode) desc.createUiNode();
             mUiRootNode.setEditor(this);
 
-            // Add a listener to refresh the root node if the resource framework changes
-            // by forcing it to parse its own XML
-            mResourceRefreshListener = new Runnable() {
-                public void run() {
-                    commitPages(false /* onSave */);
-
-                    mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
-                }
-            };
-            EditorsPlugin.getDefault().addResourceChangedListener(mResourceRefreshListener);
-            mResourceRefreshListener.run();
+            onDescriptorsChanged(doc);
         }
     }
+
+    // ---- Local Methods ----
+
+    /**
+     * Reloads the UI manifest node from the XML, and calls the pages to update.
+     */
+    private void onDescriptorsChanged(Document document) {
+        if (document != null) {
+            mUiRootNode.loadFromXmlNode(document);
+        } else {
+            mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
+        }
+    }
+    
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java
similarity index 100%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlSourceViewerConfig.java
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
similarity index 94%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
index 5bb0f72..91ce6dd 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/XmlTreePage.java
@@ -16,7 +16,7 @@
 
 package com.android.ide.eclipse.editors.xml;
 
-import com.android.ide.eclipse.editors.EditorsPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
 import com.android.ide.eclipse.editors.uimodel.UiElementNode;
 
@@ -49,7 +49,7 @@
         super.createFormContent(managedForm);
         ScrolledForm form = managedForm.getForm();
         form.setText("Android Xml");
-        form.setImage(EditorsPlugin.getAndroidLogo());
+        form.setImage(AdtPlugin.getAndroidLogo());
 
         UiElementNode rootNode = mEditor.getUiRootNode();
         UiTreeBlock block = new UiTreeBlock(mEditor, rootNode,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
similarity index 90%
rename from tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
index 14cb9d6..31b4c61 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/xml/descriptors/XmlDescriptors.java
@@ -24,6 +24,7 @@
 import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
 import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
 import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
 import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
 import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
 import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
@@ -36,10 +37,11 @@
  * Description of the /res/xml structure.
  * Currently supports the <searchable> and <preferences> root nodes.
  */
-public class XmlDescriptors {
+public final class XmlDescriptors implements IDescriptorProvider {
 
-    /** Singleton instance */
-    private static XmlDescriptors sThis;
+    // Public attributes names, attributes descriptors and elements descriptors referenced
+    // elsewhere.
+    public static final String PREF_KEY_ATTR = "key"; //$NON-NLS-1$
 
     /** The root document descriptor for both searchable and preferences. */
     private DocumentDescriptor mDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ 
@@ -50,19 +52,15 @@
     /** The root document descriptor for preferences. */
     private DocumentDescriptor mPrefDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ 
 
-    /** Returns a singleton instance of the {@link XmlDescriptors}. */
-    public static synchronized XmlDescriptors getInstance() {
-        if (sThis == null) {
-            sThis = new XmlDescriptors();
-        }
-        return sThis;
-    }
-    
     /** @return the root descriptor for both searchable and preferences. */
     public DocumentDescriptor getDescriptor() {
         return mDescriptor;
     }
     
+    public ElementDescriptor[] getRootElementDescriptors() {
+        return mDescriptor.getChildren();
+    }
+    
     /** @return the root descriptor for searchable. */
     public DocumentDescriptor getSearchableDescriptor() {
         return mSearchDescriptor;
@@ -72,6 +70,30 @@
     public DocumentDescriptor getPreferencesDescriptor() {
         return mPrefDescriptor;
     }
+    
+    public IDescriptorProvider getSearchableProvider() {
+        return new IDescriptorProvider() {
+            public ElementDescriptor getDescriptor() {
+                return mSearchDescriptor;
+            }
+
+            public ElementDescriptor[] getRootElementDescriptors() {
+                return mSearchDescriptor.getChildren();
+            }
+        };
+    }
+
+    public IDescriptorProvider getPreferencesProvider() {
+        return new IDescriptorProvider() {
+            public ElementDescriptor getDescriptor() {
+                return mPrefDescriptor;
+            }
+
+            public ElementDescriptor[] getRootElementDescriptors() {
+                return mPrefDescriptor.getChildren();
+            }
+        };
+    }
 
     /**
      * Updates the document descriptor.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/.classpath b/tools/eclipse/plugins/com.android.ide.eclipse.common/.classpath
deleted file mode 100644
index a7b3dc1..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/.classpath
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-	<classpathentry kind="lib" path="androidprefs.jar"/>
-	<classpathentry kind="lib" path="sdkstats.jar"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/.project b/tools/eclipse/plugins/com.android.ide.eclipse.common/.project
deleted file mode 100644
index 510efb7..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>common</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.pde.ManifestBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.pde.SchemaBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.pde.PluginNature</nature>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF
deleted file mode 100644
index dad85a6..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,22 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Android Common Plugin
-Bundle-SymbolicName: com.android.ide.eclipse.common;singleton:=true
-Bundle-Version: 0.8.1.qualifier
-Bundle-ClassPath: .,
- sdkstats.jar,
- androidprefs.jar
-Bundle-Vendor: The Android Open Source Project
-Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.common,
- com.android.ide.eclipse.common.project,
- com.android.ide.eclipse.common.resources
-Require-Bundle: org.eclipse.core.resources,
- org.eclipse.core.runtime,
- org.eclipse.jdt.core,
- org.eclipse.ui.console,
- org.eclipse.ui,
- org.eclipse.jdt.ui,
- org.eclipse.jface.text,
- org.eclipse.ui.editors
-Bundle-Activator: com.android.ide.eclipse.common.CommonPlugin
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL b/tools/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL
deleted file mode 100644
index e69de29..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/MODULE_LICENSE_EPL
+++ /dev/null
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/NOTICE b/tools/eclipse/plugins/com.android.ide.eclipse.common/NOTICE
deleted file mode 100644
index 49c101d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/NOTICE
+++ /dev/null
@@ -1,224 +0,0 @@
-*Eclipse Public License - v 1.0*
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-*1. DEFINITIONS*
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and
-are distributed by that particular Contributor. A Contribution
-'originates' from a Contributor if it was added to the Program by such
-Contributor itself or anyone acting on such Contributor's behalf.
-Contributions do not include additions to the Program which: (i) are
-separate modules of software distributed in conjunction with the Program
-under their own license agreement, and (ii) are not derivative works of
-the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-*2. GRANT OF RIGHTS*
-
-a) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free copyright
-license to reproduce, prepare derivative works of, publicly display,
-publicly perform, distribute and sublicense the Contribution of such
-Contributor, if any, and such derivative works, in source code and
-object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free patent license
-under Licensed Patents to make, use, sell, offer to sell, import and
-otherwise transfer the Contribution of such Contributor, if any, in
-source code and object code form. This patent license shall apply to the
-combination of the Contribution and the Program if, at the time the
-Contribution is added by the Contributor, such addition of the
-Contribution causes such combination to be covered by the Licensed
-Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the
-licenses to its Contributions set forth herein, no assurances are
-provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright
-license set forth in this Agreement.
-
-*3. REQUIREMENTS*
-
-A Contributor may choose to distribute the Program in object code form
-under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties
-and conditions, express and implied, including warranties or conditions
-of title and non-infringement, and implied warranties or conditions of
-merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and
-consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are
-offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable
-manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained
-within the Program.
-
-Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.
-
-*4. COMMERCIAL DISTRIBUTION*
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program, the
-Contributor who includes the Program in a commercial product offering
-should do so in a manner which does not create potential liability for
-other Contributors. Therefore, if a Contributor includes the Program in
-a commercial product offering, such Contributor ("Commercial
-Contributor") hereby agrees to defend and indemnify every other
-Contributor ("Indemnified Contributor") against any losses, damages and
-costs (collectively "Losses") arising from claims, lawsuits and other
-legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the
-Program in a commercial product offering. The obligations in this
-section do not apply to any claims or Losses relating to any actual or
-alleged intellectual property infringement. In order to qualify, an
-Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial
-Contributor to control, and cooperate with the Commercial Contributor
-in, the defense and any related settlement negotiations. The Indemnified
-Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.
-
-*5. NO WARRANTY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
-ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
-OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR
-A PARTICULAR PURPOSE. Each Recipient is solely responsible for
-determining the appropriateness of using and distributing the Program
-and assumes all risks associated with its exercise of rights under this
-Agreement , including but not limited to the risks and costs of program
-errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-*6. DISCLAIMER OF LIABILITY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-*7. GENERAL*
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including
-a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails
-to comply with any of the material terms or conditions of this Agreement
-and does not cure such failure in a reasonable period of time after
-becoming aware of such noncompliance. If all Recipient's rights under
-this Agreement terminate, Recipient agrees to cease use and distribution
-of the Program as soon as reasonably practicable. However, Recipient's
-obligations under this Agreement and any licenses granted by Recipient
-relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and may
-only be modified in the following manner. The Agreement Steward reserves
-the right to publish new versions (including revisions) of this
-Agreement from time to time. No one other than the Agreement Steward has
-the right to modify this Agreement. The Eclipse Foundation is the
-initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is
-published, Contributor may elect to distribute the Program (including
-its Contributions) under the new version. Except as expressly stated in
-Sections 2(a) and 2(b) above, Recipient receives no rights or licenses
-to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in
-the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to
-this Agreement will bring a legal action under this Agreement more than
-one year after the cause of action arose. Each party waives its rights
-to a jury trial in any resulting litigation.
-
- 
-
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/build.properties b/tools/eclipse/plugins/com.android.ide.eclipse.common/build.properties
deleted file mode 100644
index 4c9981d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/build.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
-               .,\
-               sdkstats.jar,\
-               plugin.xml,\
-               androidprefs.jar
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.common/plugin.xml
deleted file mode 100644
index 115eb97..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/plugin.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
-   <extension
-         id="com.android.ide.eclipse.common.xmlProblem"
-         name="XML Problem"
-         point="org.eclipse.core.resources.markers">
-      <super type="org.eclipse.core.resources.problemmarker"/>
-      <super type="org.eclipse.core.resources.textmarker"/>
-      <persistent value="true"/>
-   </extension>
-   <extension
-         id="com.android.ide.eclipse.common.aaptProblem"
-         name="aapt Problem"
-         point="org.eclipse.core.resources.markers">
-      <super type="org.eclipse.core.resources.problemmarker"/>
-      <super type="org.eclipse.core.resources.textmarker"/>
-      <persistent value="true"/>
-   </extension>
-   <extension
-         id="com.android.ide.eclipse.common.aidlProblem"
-         name="aidl Problem"
-         point="org.eclipse.core.resources.markers">
-      <super type="org.eclipse.core.resources.problemmarker"/>
-      <super type="org.eclipse.core.resources.textmarker"/>
-      <persistent value="true"/>
-   </extension>
-   <extension
-        id="com.android.ide.eclipse.common.androidProblem"
-        name="Android Problem"
-        point="org.eclipse.core.resources.markers">
-      <super type="org.eclipse.core.resources.problemmarker"/>
-      <super type="org.eclipse.core.resources.textmarker"/>
-      <persistent value="true"/>
-   </extension>
-    <extension
-          point="org.eclipse.ui.preferencePages">
-        <page
-            category="com.android.ide.eclipse.preferences.main"
-            class="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
-            id="com.android.ide.eclipse.common.preferences.UsagePreferencePage"
-            name="Usage Stats"/>
-    </extension>
-</plugin>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java
deleted file mode 100644
index cfee50f..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/CommonPlugin.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2008 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.common;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.console.ConsolePlugin;
-import org.eclipse.ui.console.IConsole;
-import org.eclipse.ui.console.MessageConsole;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class CommonPlugin extends AbstractUIPlugin {
-
-    // The plug-in ID
-    public static final String PLUGIN_ID = "com.android.ide.eclipse.common"; // $NON-NLS-1$
-
-    // The shared instance
-    private static CommonPlugin sPlugin;
-
-    // The global android console
-    private MessageConsole mAndroidConsole;
-
-    /**
-     * The constructor
-     */
-    public CommonPlugin() {
-        // pass
-    }
-
-    /**
-     * Returns the shared instance
-     * 
-     * @return the shared instance
-     */
-    public static CommonPlugin getDefault() {
-        return sPlugin;
-    }
-
-    /** Returns the global android console */
-    public MessageConsole getAndroidConsole() {
-        return mAndroidConsole;
-    }
-    
-    /**
-     * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
-     * method refreshes the plug-in actions.  Subclasses may extend this method,
-     * but must send super <b>first</b>.
-     * 
-     * {@inheritDoc}
-     */
-    @Override
-    public void start(BundleContext context) throws Exception {
-        super.start(context);
-        sPlugin = this;
-        
-        /*
-         * WARNING: think before adding any initialization here as plugins are dynamically
-         * started and since no UI is being displayed by this plugin, it'll only start when
-         * another plugin accesses some of its code.
-         */
-        
-        // set the default android console.
-        mAndroidConsole = new MessageConsole("Android", null); //$NON-NLS-1$
-        ConsolePlugin.getDefault().getConsoleManager().addConsoles(
-                new IConsole[] { mAndroidConsole });
-    }
-
-    /**
-     * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
-     * method saves this plug-in's preference and dialog stores and shuts down 
-     * its image registry (if they are in use). Subclasses may extend this
-     * method, but must send super <b>last</b>. A try-finally statement should
-     * be used where necessary to ensure that <code>super.shutdown()</code> is
-     * always done.
-     * 
-     * {@inheritDoc}
-     */
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        sPlugin = null;
-        super.stop(context);
-    }
-
-    /**
-     * Logs a message to the default Eclipse log.
-     * 
-     * @param severity One of IStatus' severity codes: OK, ERROR, INFO, WARNING or CANCEL.
-     * @param format The format string, like for String.format().
-     * @param args The arguments for the format string, like for String.format().
-     */
-    public static void log(int severity, String format, Object ... args) {
-        String message = String.format(format, args);
-        Status status = new Status(severity, PLUGIN_ID, message);
-        getDefault().getLog().log(status);
-    }
-
-    /**
-     * Logs an exception to the default Eclipse log.
-     * <p/>
-     * The status severity is always set to ERROR.
-     * 
-     * @param exception The exception to log. Its call trace will be recorded.
-     * @param format The format string, like for String.format().
-     * @param args The arguments for the format string, like for String.format().
-     */
-    public static void log(Throwable exception, String format, Object ... args) {
-        String message = String.format(format, args);
-        Status status = new Status(IStatus.ERROR, PLUGIN_ID, message, exception);
-        getDefault().getLog().log(status);
-    }
-    
-    private static Display getDisplay() {
-        IWorkbench bench = sPlugin.getWorkbench();
-        if (bench!=null) {
-            return bench.getDisplay();
-        }
-        return null;
-    }
-
-    /**
-     * Display a yes/no question dialog box. This dialog is opened synchronously in the ui thread,
-     * therefore this message can be called from any thread.
-     * @param title The title of the dialog box
-     * @param message The error message
-     * @return true if OK was clicked.
-     */
-    public final static boolean displayPrompt(final String title, final String message) {
-        // get the current Display and Shell
-        final Display display = getDisplay();
-
-        // we need to ask the user what he wants to do.
-        final Boolean[] wrapper = new Boolean[] { new Boolean(false) };
-        display.syncExec(new Runnable() {
-            public void run() {
-                Shell shell = display.getActiveShell();
-                wrapper[0] = new Boolean(MessageDialog.openQuestion(shell, title, message));
-            }
-        });
-        return wrapper[0].booleanValue();
-    }
-
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java b/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java
deleted file mode 100644
index 3f8f029..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.common/src/com/android/ide/eclipse/common/resources/FrameworkResourceManager.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2007 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.common.resources;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
-
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.Map;
-
-/**
- * This is a communication between different plugins that don't know each other. It allows one
- * plugin to provide detailed information about the framework resources to another plugin.
- */
-public class FrameworkResourceManager {
-
-    private static String[] sBooleanValues = new String[] {
-        "true",     //$NON-NLS-1$
-        "false",    //$NON-NLS-1$
-    };
-    
-    private static FrameworkResourceManager sThis = new FrameworkResourceManager();
-    
-    private ArrayList<Runnable> mResourcesChangeListeners = new ArrayList<Runnable>();
-    
-    private Hashtable<String, String[]> mAttributeValues;
-    
-    private IResourceRepository mSystemResourceRepository;
-
-    private ViewClassInfo[] mLayoutViewsInfo;
-    private ViewClassInfo[] mLayoutGroupsInfo;
-    private ViewClassInfo[] mPreferencesInfo;
-    private ViewClassInfo[] mPreferenceGroupsInfo;
-    
-    private Map<String, DeclareStyleableInfo> mXmlMenuMap;
-    private Map<String, DeclareStyleableInfo> mXmlSearchableMap;
-    private Map<String, DeclareStyleableInfo> mManifestMap;
-    
-    /** Flags indicating whether we have some resources */
-    private boolean mHasResources = false;
-
-    private String mLayoutLibLocation;
-
-    private String mFrameworkResourcesLocation;
-
-    private Map<String, Map<String, Integer>> mEnumValueMap;
-
-    private String mFrameworkFontsLocation;
-
-    private String mDocBaseUrl;
-    
-    /**
-     * Creates a new Framework Resource Manager.
-     * 
-     * mAttributeValues is a map { key => list [ values ] }.
-     * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)".
-     * The attribute namespace prefix must be:
-     * - "android" for AndroidConstants.NS_RESOURCES
-     * - "xmlns" for the XMLNS URI.
-     */
-    private FrameworkResourceManager() {
-        /* TODO Attempt to load those values from android.jar */
-        mAttributeValues = new Hashtable<String, String[]>();
-        mAttributeValues.put("(manifest,xmlns:android)", new String[] { //$NON-NLS-1$
-                AndroidConstants.NS_RESOURCES
-                });
-        mAttributeValues.put("(permission,android:protectionLevel)", new String[] { //$NON-NLS-1$
-                "application",                                      //$NON-NLS-1$
-                "system"                                            //$NON-NLS-1$
-                });
-        mAttributeValues.put("(application,android:persistent)", new String[] { //$NON-NLS-1$
-                "true",                                             //$NON-NLS-1$
-                "false",                                            //$NON-NLS-1$
-                });
-        mAttributeValues.put("(activity,android:clearOnBackground)", sBooleanValues); //$NON-NLS-1$
-        mAttributeValues.put("(activity,android:configChanges)", new String[] { //$NON-NLS-1$
-                "fontScale",                                        //$NON-NLS-1$
-                "mcc",                                              //$NON-NLS-1$
-                "mnc",                                              //$NON-NLS-1$
-                "locale",                                           //$NON-NLS-1$
-                "touchscreen",                                      //$NON-NLS-1$
-                "keyboard",                                         //$NON-NLS-1$
-                "keyboardHidden",                                   //$NON-NLS-1$
-                "navigation",                                       //$NON-NLS-1$
-                "orientation",                                      //$NON-NLS-1$
-                });
-        mAttributeValues.put("(activity,android:launchMode)", new String[] { //$NON-NLS-1$
-                "multiple",                                         //$NON-NLS-1$
-                "singleTop",                                        //$NON-NLS-1$
-                "singleTask",                                       //$NON-NLS-1$
-                "singleInstance"                                    //$NON-NLS-1$
-                });
-        mAttributeValues.put("(activity,android:stateNotNeeded)", sBooleanValues); //$NON-NLS-1$
-        mAttributeValues.put("(provider,android:syncable)", sBooleanValues); //$NON-NLS-1$
-        mAttributeValues.put("(provider,android:multiprocess)", sBooleanValues); //$NON-NLS-1$
-        mAttributeValues.put("(instrumentation,android:functionalTest)", sBooleanValues); //$NON-NLS-1$
-        mAttributeValues.put("(instrumentation,android:handleProfiling)", sBooleanValues); //$NON-NLS-1$
-        
-    }
-
-    /**
-     * Returns the {@link FrameworkResourceManager} instance.
-     */
-    public static FrameworkResourceManager getInstance() {
-        return sThis;
-    }
-
-    /**
-     * Sets the resources and notifies the listeners
-     * @param documentationBaseUrl 
-     */
-    public synchronized void setResources(IResourceRepository systemResourceRepository,
-            ViewClassInfo[] layoutViewsInfo,
-            ViewClassInfo[] layoutGroupsInfo,
-            ViewClassInfo[] preferencesInfo,
-            ViewClassInfo[] preferenceGroupsInfo,
-            Map<String, DeclareStyleableInfo> xmlMenuMap,
-            Map<String, DeclareStyleableInfo> xmlSearchableMap,
-            Map<String, DeclareStyleableInfo> manifestMap,
-            Map<String, Map<String, Integer>> enumValueMap,
-            String[] permissionValues,
-            String[] activityIntentActionValues,
-            String[] broadcastIntentActionValues,
-            String[] serviceIntentActionValues,
-            String[] intentCategoryValues,
-            String documentationBaseUrl) {
-        mSystemResourceRepository = systemResourceRepository;
-        
-        mLayoutViewsInfo = layoutViewsInfo;
-        mLayoutGroupsInfo = layoutGroupsInfo; 
-
-        mPreferencesInfo = preferencesInfo;
-        mPreferenceGroupsInfo = preferenceGroupsInfo;
-        
-        mXmlMenuMap = xmlMenuMap;
-        mXmlSearchableMap = xmlSearchableMap;
-        mManifestMap = manifestMap;
-        mEnumValueMap = enumValueMap;
-        mDocBaseUrl = documentationBaseUrl;
-
-        setPermissions(permissionValues);
-        setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues,
-                serviceIntentActionValues, intentCategoryValues);
-
-        mHasResources = true;
-
-        notifyFrameworkResourcesChangeListeners();
-    }
-    
-    public synchronized IResourceRepository getSystemResources() {
-        return mSystemResourceRepository;
-    }
-
-    public synchronized String[] getValues(String elementName, String attributeName) {
-        String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$
-        return mAttributeValues.get(key);
-    }
-
-    public synchronized String[] getValues(String elementName, String attributeName,
-            String greatGrandParentElementName) {
-        if (greatGrandParentElementName != null) {
-            String key = String.format("(%1$s,%2$s,%3$s)", greatGrandParentElementName, //$NON-NLS-1$
-                    elementName, attributeName); 
-            String[] values = mAttributeValues.get(key);
-            if (values != null) {
-                return values;
-            }
-        }
-        
-        return getValues(elementName, attributeName);
-    }
-
-    public synchronized String[] getValues(String key) {
-        return mAttributeValues.get(key);
-    }
-    
-    public synchronized ViewClassInfo[] getLayoutViewsInfo() {
-        return mLayoutViewsInfo;
-    }
-
-    public synchronized ViewClassInfo[] getLayoutGroupsInfo() {
-        return mLayoutGroupsInfo;
-    }
-
-    public synchronized ViewClassInfo[] getPreferencesInfo() {
-        return mPreferencesInfo;
-    }
-
-    public synchronized ViewClassInfo[] getPreferenceGroupsInfo() {
-        return mPreferenceGroupsInfo;
-    }
-    
-    public synchronized Map<String, DeclareStyleableInfo> getXmlMenuDefinitions() {
-        return mXmlMenuMap;
-    }
-
-    public synchronized Map<String, DeclareStyleableInfo> getXmlSearchableDefinitions() {
-        return mXmlSearchableMap;
-    }
-
-    public synchronized Map<String, DeclareStyleableInfo> getManifestDefinitions() {
-        return mManifestMap;
-    }
-
-    public String getDocumentationBaseUrl() {
-        return mDocBaseUrl == null ? AndroidConstants.CODESITE_BASE_URL : mDocBaseUrl;
-    }
-    
-    /**
-     * Sets the permission values
-     * @param permissionValues the list of permissions
-     */
-    private void setPermissions(String[] permissionValues) {
-        setValues("(uses-permission,android:name)", permissionValues); //$NON-NLS-1$
-        setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$
-        setValues("(activity,android:permission)", permissionValues); //$NON-NLS-1$
-        setValues("(receiver,android:permission)", permissionValues); //$NON-NLS-1$
-        setValues("(service,android:permission)", permissionValues); //$NON-NLS-1$
-        setValues("(provider,android:permission)", permissionValues); //$NON-NLS-1$
-    }
-    
-    private void setIntentFilterActionsAndCategories(String[] activityIntentActions,
-            String[] broadcastIntentActions, String[] serviceIntentActions,
-            String[] intentCategoryValues) {
-        setValues("(activity,action,android:name)", activityIntentActions); //$NON-NLS-1$
-        setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$
-        setValues("(service,action,android:name)", serviceIntentActions); //$NON-NLS-1$
-        setValues("(category,android:name)", intentCategoryValues); //$NON-NLS-1$
-    }
-
-    /**
-     * Sets a (name, values) pair in the hash map.
-     * <p/>
-     * If the name is already present in the map, it is first removed.
-     * @param name the name associated with the values.
-     * @param values The values to add.
-     */
-    private void setValues(String name, String[] values) {
-        mAttributeValues.remove(name);
-        mAttributeValues.put(name, values);
-    }
-
-
-    /**
-     * Called by the ADT plugin when the SDK path has changed.
-     * This stores the path locally and then notifies all attached listeners.
-     */
-    private void notifyFrameworkResourcesChangeListeners() {
-        for (Runnable listener : mResourcesChangeListeners) {
-            try {
-                listener.run();
-            } catch (Exception e) {
-                CommonPlugin.log(e, "IPathChangedListener failed."); //$NON-NLS-1$
-            }
-        }
-    }
-
-    /** Adds a new listener that listens to framework resources changes.
-     * <p/>If resources have already been set, then the listener is automatically notified. */
-    public synchronized void addFrameworkResourcesChangeListener(Runnable listener) {
-        if (listener != null && mResourcesChangeListeners.indexOf(listener) == -1) {
-            mResourcesChangeListeners.add(listener);
-            
-            if (mHasResources) {
-                listener.run();
-            }
-        }
-    }
-
-    /** Removes a framework resources changes listener.
-     * <p/>Safe to call with null or with the same value. */
-    public synchronized void removeFrameworkResourcesChangeListener(Runnable listener) {
-        mResourcesChangeListeners.remove(listener);
-    }
-
-    public void setLayoutLibLocation(String osLocation) {
-        mLayoutLibLocation = osLocation;
-    }
-    
-    public String getLayoutLibLocation() {
-        return mLayoutLibLocation;
-    }
-    
-    public void setFrameworkResourcesLocation(String osLocation) {
-        mFrameworkResourcesLocation = osLocation;
-    }
-
-    public String getFrameworkResourcesLocation() {
-        return mFrameworkResourcesLocation;
-    }
-    
-    public Map<String, Map<String, Integer>> getEnumValueMap() {
-        return mEnumValueMap;
-    }
-
-    public void setFrameworkFontLocation(String osLocation) {
-        mFrameworkFontsLocation = osLocation;
-    }
-    
-    public String getFrameworkFontLocation() {
-        return mFrameworkFontsLocation;
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
index 2f315c5..09b8085 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Dalvik Debug Monitor Service
 Bundle-SymbolicName: com.android.ide.eclipse.ddms;singleton:=true
-Bundle-Version: 0.8.1.qualifier
+Bundle-Version: 0.9.0.qualifier
 Bundle-Activator: com.android.ide.eclipse.ddms.DdmsPlugin
 Bundle-Vendor: The Android Open Source Project
 Bundle-Localization: plugin
@@ -10,11 +10,13 @@
  org.eclipse.core.runtime,
  org.eclipse.ui.console
 Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.ddms,
- com.android.ide.eclipse.ddms.views,
- com.android.ddmlib,
+Export-Package: com.android.ddmlib,
+ com.android.ddmlib.log,
+ com.android.ddmlib.testrunner,
  com.android.ddmuilib,
- com.android.ddmuilib.console
+ com.android.ddmuilib.console,
+ com.android.ide.eclipse.ddms,
+ com.android.ide.eclipse.ddms.views
 Bundle-ClassPath: libs/jcommon-1.0.12.jar,
  libs/jfreechart-1.0.9.jar,
  libs/jfreechart-1.0.9-swt.jar,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/.classpath b/tools/eclipse/plugins/com.android.ide.eclipse.editors/.classpath
deleted file mode 100644
index 66dbeb3..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/.classpath
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
-		<accessrules>
-			<accessrule kind="accessible" pattern="org/eclipse/wst/**/internal/**"/>
-		</accessrules>
-	</classpathentry>
-	<classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
-	<classpathentry kind="lib" path="layoutlib_api.jar"/>
-	<classpathentry kind="lib" path="ninepatch.jar"/>
-	<classpathentry kind="lib" path="layoutlib_utils.jar"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/.project b/tools/eclipse/plugins/com.android.ide.eclipse.editors/.project
deleted file mode 100644
index 292c698..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>editors</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.pde.ManifestBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.pde.SchemaBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.pde.PluginNature</nature>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF
deleted file mode 100644
index 0bfaff9..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,56 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Android Editors
-Bundle-SymbolicName: com.android.ide.eclipse.editors;singleton:=true
-Bundle-Version: 0.8.1.qualifier
-Bundle-Activator: com.android.ide.eclipse.editors.EditorsPlugin
-Bundle-Vendor: The Android Open Source Project
-Require-Bundle: com.android.ide.eclipse.common,
- org.eclipse.ui,
- org.eclipse.core.runtime,
- org.eclipse.core.resources,
- org.eclipse.ui.editors,
- org.eclipse.jface.text,
- org.eclipse.ui.ide,
- org.eclipse.wst.sse.ui,
- org.eclipse.wst.xml.ui,
- org.eclipse.wst.xml.core,
- org.eclipse.wst.sse.core,
- org.eclipse.ui.forms,
- org.eclipse.jdt.core,
- org.eclipse.ui.browser,
- org.eclipse.jdt.ui,
- org.eclipse.gef,
- org.eclipse.ui.views,
- org.eclipse.ui.console
-Eclipse-LazyStart: true
-Export-Package: com.android.ide.eclipse.editors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout.parts;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.layout.uimodel;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest.model;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.manifest.pages;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.menu;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.menu.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.configurations;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.descriptors;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.explorer;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.manager;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.manager.files;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.resources.uimodel;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.ui;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.ui.tree;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.uimodel;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.wizards;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.xml;x-friends:="com.android.ide.eclipse.tests",
- com.android.ide.eclipse.editors.xml.descriptors;x-friends:="com.android.ide.eclipse.tests"
-Bundle-ClassPath: kxml2-2.3.0.jar,
- .,
- layoutlib_api.jar,
- ninepatch.jar,
- layoutlib_utils.jar
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL b/tools/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL
deleted file mode 100644
index e69de29..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/MODULE_LICENSE_EPL
+++ /dev/null
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE b/tools/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE
deleted file mode 100644
index 49c101d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/NOTICE
+++ /dev/null
@@ -1,224 +0,0 @@
-*Eclipse Public License - v 1.0*
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-*1. DEFINITIONS*
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and
-are distributed by that particular Contributor. A Contribution
-'originates' from a Contributor if it was added to the Program by such
-Contributor itself or anyone acting on such Contributor's behalf.
-Contributions do not include additions to the Program which: (i) are
-separate modules of software distributed in conjunction with the Program
-under their own license agreement, and (ii) are not derivative works of
-the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-*2. GRANT OF RIGHTS*
-
-a) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free copyright
-license to reproduce, prepare derivative works of, publicly display,
-publicly perform, distribute and sublicense the Contribution of such
-Contributor, if any, and such derivative works, in source code and
-object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free patent license
-under Licensed Patents to make, use, sell, offer to sell, import and
-otherwise transfer the Contribution of such Contributor, if any, in
-source code and object code form. This patent license shall apply to the
-combination of the Contribution and the Program if, at the time the
-Contribution is added by the Contributor, such addition of the
-Contribution causes such combination to be covered by the Licensed
-Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the
-licenses to its Contributions set forth herein, no assurances are
-provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright
-license set forth in this Agreement.
-
-*3. REQUIREMENTS*
-
-A Contributor may choose to distribute the Program in object code form
-under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties
-and conditions, express and implied, including warranties or conditions
-of title and non-infringement, and implied warranties or conditions of
-merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and
-consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are
-offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable
-manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained
-within the Program.
-
-Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.
-
-*4. COMMERCIAL DISTRIBUTION*
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program, the
-Contributor who includes the Program in a commercial product offering
-should do so in a manner which does not create potential liability for
-other Contributors. Therefore, if a Contributor includes the Program in
-a commercial product offering, such Contributor ("Commercial
-Contributor") hereby agrees to defend and indemnify every other
-Contributor ("Indemnified Contributor") against any losses, damages and
-costs (collectively "Losses") arising from claims, lawsuits and other
-legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the
-Program in a commercial product offering. The obligations in this
-section do not apply to any claims or Losses relating to any actual or
-alleged intellectual property infringement. In order to qualify, an
-Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial
-Contributor to control, and cooperate with the Commercial Contributor
-in, the defense and any related settlement negotiations. The Indemnified
-Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.
-
-*5. NO WARRANTY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
-ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
-OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR
-A PARTICULAR PURPOSE. Each Recipient is solely responsible for
-determining the appropriateness of using and distributing the Program
-and assumes all risks associated with its exercise of rights under this
-Agreement , including but not limited to the risks and costs of program
-errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-*6. DISCLAIMER OF LIABILITY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-*7. GENERAL*
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including
-a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails
-to comply with any of the material terms or conditions of this Agreement
-and does not cure such failure in a reasonable period of time after
-becoming aware of such noncompliance. If all Recipient's rights under
-this Agreement terminate, Recipient agrees to cease use and distribution
-of the Program as soon as reasonably practicable. However, Recipient's
-obligations under this Agreement and any licenses granted by Recipient
-relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and may
-only be modified in the following manner. The Agreement Steward reserves
-the right to publish new versions (including revisions) of this
-Agreement from time to time. No one other than the Agreement Steward has
-the right to modify this Agreement. The Eclipse Foundation is the
-initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is
-published, Contributor may elect to distribute the Program (including
-its Contributions) under the new version. Except as expressly stated in
-Sections 2(a) and 2(b) above, Recipient receives no rights or licenses
-to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in
-the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to
-this Agreement will bring a legal action under this Agreement more than
-one year after the cause of action arose. Each party waives its rights
-to a jury trial in any resulting litigation.
-
- 
-
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/build.properties b/tools/eclipse/plugins/com.android.ide.eclipse.editors/build.properties
deleted file mode 100644
index 0a7bc7d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/build.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
-               .,\
-               plugin.xml,\
-               icons/,\
-               layoutlib_api.jar,\
-               kxml2-2.3.0.jar,\
-               ninepatch.jar,\
-               layoutlib_utils.jar
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png b/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png
deleted file mode 100644
index 3779d4d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png b/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png
deleted file mode 100644
index 64e3601..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/android_large.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png b/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png
deleted file mode 100644
index 9cfb53f..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/region.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png b/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png
deleted file mode 100644
index afdc16c..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/icons/world.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml
deleted file mode 100644
index 2678a5d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/plugin.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
-   <extension
-         point="org.eclipse.ui.editors">
-      <editor
-            class="com.android.ide.eclipse.editors.manifest.ManifestEditor"
-            default="true"
-            filenames="AndroidManifest.xml"
-            icon="icons/android.png"
-            id="com.android.ide.eclipse.editors.manifest.ManifestEditor"
-            name="Android Manifest Editor">
-      </editor>
-      <editor
-            class="com.android.ide.eclipse.editors.resources.ResourcesEditor"
-            default="false"
-            extensions="xml"
-            icon="icons/android.png"
-            id="com.android.ide.eclipse.editors.resources.ResourcesEditor"
-            name="Android Resource Editor">
-      </editor>
-      <editor
-            class="com.android.ide.eclipse.editors.layout.LayoutEditor"
-            default="false"
-            extensions="xml"
-            icon="icons/android.png"
-            id="com.android.ide.eclipse.editors.layout.LayoutEditor"
-            matchingStrategy="com.android.ide.eclipse.editors.layout.MatchingStrategy"
-            name="Android Layout Editor">
-      </editor>
-      <editor
-            class="com.android.ide.eclipse.editors.menu.MenuEditor"
-            default="false"
-            extensions="xml"
-            icon="icons/android.png"
-            id="com.android.ide.eclipse.editors.menu.MenuEditor"
-            name="Android Menu Editor">
-      </editor>
-      <editor
-            class="com.android.ide.eclipse.editors.xml.XmlEditor"
-            default="false"
-            extensions="xml"
-            icon="icons/android.png"
-            id="com.android.ide.eclipse.editors.xml.XmlEditor"
-            name="Android Xml Resources Editor">
-      </editor>
-   </extension>
-   <extension
-         point="org.eclipse.wst.sse.ui.editorConfiguration">
-      <sourceViewerConfiguration
-            class="com.android.ide.eclipse.editors.manifest.ManifestSourceViewerConfig"
-            target="com.android.ide.eclipse.editors.manifest.ManifestEditor">
-      </sourceViewerConfiguration>
-      <sourceViewerConfiguration
-            class="com.android.ide.eclipse.editors.resources.ResourcesSourceViewerConfig"
-            target="com.android.ide.eclipse.editors.resources.ResourcesEditor">
-      </sourceViewerConfiguration>
-      <sourceViewerConfiguration
-            class="com.android.ide.eclipse.editors.layout.LayoutSourceViewerConfig"
-            target="com.android.ide.eclipse.editors.layout.LayoutEditor">
-      </sourceViewerConfiguration>
-      <sourceViewerConfiguration
-            class="com.android.ide.eclipse.editors.menu.MenuSourceViewerConfig"
-            target="com.android.ide.eclipse.editors.menu.MenuEditor">
-      </sourceViewerConfiguration>
-      <sourceViewerConfiguration
-            class="com.android.ide.eclipse.editors.xml.XmlSourceViewerConfig"
-            target="com.android.ide.eclipse.editors.xml.XmlEditor">
-      </sourceViewerConfiguration>
-   </extension>
-   <extension
-         point="org.eclipse.ui.views">
-      <view
-            allowMultiple="false"
-            category="com.android.ide.eclipse.ddms.views.category"
-            class="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
-            icon="icons/android.png"
-            id="com.android.ide.eclipse.editors.resources.explorer.ResourceExplorerView"
-            name="Resource Explorer">
-      </view>
-   </extension>
-   <extension
-         point="org.eclipse.ui.newWizards">
-      <wizard
-            canFinishEarly="false"
-            category="com.android.ide.eclipse.wizards.category"
-            class="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
-            finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
-            hasPages="true"
-            icon="icons/android.png"
-            id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
-            name="Android XML File"
-            preferredPerspectives="org.eclipse.jdt.ui.JavaPerspective"
-            project="false">
-      </wizard>
-   </extension>
-   <extension
-         point="org.eclipse.ui.perspectiveExtensions">
-      <perspectiveExtension
-            targetID="org.eclipse.jdt.ui.JavaPerspective">
-         <newWizardShortcut
-               id="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard">
-         </newWizardShortcut>
-      </perspectiveExtension>
-   </extension>
-
-</plugin>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java
deleted file mode 100644
index 354276a..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/EditorsPlugin.java
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * Copyright (C) 2007 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.editors;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.CommonPlugin;
-import com.android.ide.eclipse.common.SdkStatsHelper;
-import com.android.ide.eclipse.common.StreamHelper;
-import com.android.ide.eclipse.common.resources.FrameworkResourceManager;
-import com.android.ide.eclipse.editors.EditorsPlugin.LayoutBridge.LoadStatus;
-import com.android.ide.eclipse.editors.layout.LayoutEditor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
-import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
-import com.android.ide.eclipse.editors.menu.MenuEditor;
-import com.android.ide.eclipse.editors.menu.descriptors.MenuDescriptors;
-import com.android.ide.eclipse.editors.resources.ResourcesEditor;
-import com.android.ide.eclipse.editors.resources.manager.ProjectResources;
-import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
-import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType;
-import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
-import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor;
-import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener;
-import com.android.ide.eclipse.editors.xml.XmlEditor;
-import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
-import com.android.layoutlib.api.ILayoutBridge;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IMarkerDelta;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.QualifiedName;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.SubMonitor;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IEditorDescriptor;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.console.MessageConsole;
-import org.eclipse.ui.console.MessageConsoleStream;
-import org.eclipse.ui.ide.IDE;
-import org.eclipse.ui.part.FileEditorInput;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-
-import java.io.File;
-import java.io.OutputStream;
-import java.lang.reflect.Constructor;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class EditorsPlugin extends AbstractUIPlugin {
-    // The shared instance
-    private static EditorsPlugin sPlugin;
-    
-    private static Image sAndroidLogo;
-    private static ImageDescriptor sAndroidLogoDesc;
-    
-    private ResourceMonitor mResourceMonitor;
-    private SdkPathChangedListener mSdkPathChangedListener;
-    private ArrayList<Runnable> mResourceRefreshListener = new ArrayList<Runnable>();
-
-    private MessageConsoleStream mAndroidConsoleStream;
-    /** Stream to write error messages to the android console */
-    private MessageConsoleStream mAndroidConsoleErrorStream;
-    
-    public final static class LayoutBridge {
-        public enum LoadStatus { LOADING, LOADED, FAILED }
-
-        /** Link to the layout bridge */
-        public ILayoutBridge bridge;
-
-        public LoadStatus status = LoadStatus.LOADING;
-    }
-
-    private final LayoutBridge mLayoutBridge = new LayoutBridge();
-
-    private boolean mLayoutBridgeInit;
-
-    private ClassLoader mBridgeClassLoader;
-
-    private Color mRed;
-
-
-    /**
-     * The constructor
-     */
-    public EditorsPlugin() {
-    }
-
-    /**
-     * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
-     * method refreshes the plug-in actions.  Subclasses may extend this method,
-     * but must send super <b>first</b>.
-     * {@inheritDoc}
-     * 
-     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
-     */
-    @Override
-    public void start(BundleContext context) throws Exception {
-        super.start(context);
-        sPlugin = this;
-        sAndroidLogoDesc = imageDescriptorFromPlugin(AndroidConstants.EDITORS_PLUGIN_ID,
-                "/icons/android.png"); //$NON-NLS-1$
-        sAndroidLogo = sAndroidLogoDesc.createImage();
-        
-        // get the stream to write in the android console.
-        MessageConsole androidConsole = CommonPlugin.getDefault().getAndroidConsole();
-        mAndroidConsoleStream = androidConsole.newMessageStream();
-
-        mAndroidConsoleErrorStream = androidConsole.newMessageStream();
-        mRed = new Color(getDisplay(), 0xFF, 0x00, 0x00);
-
-        // because this can be run, in some cases, by a non ui thread, and beccause
-        // changing the console properties update the ui, we need to make this change
-        // in the ui thread.
-        getDisplay().asyncExec(new Runnable() {
-            public void run() {
-                mAndroidConsoleErrorStream.setColor(mRed);
-            }
-        });
-
-        // Add a resource listener to handle compiled resources.
-        IWorkspace ws = ResourcesPlugin.getWorkspace();
-        mResourceMonitor = ResourceMonitor.startMonitoring(ws);
-
-        if (mResourceMonitor != null) {
-            setupDefaultEditor(mResourceMonitor);
-            ResourceManager.setup(mResourceMonitor);
-        }
-        
-        // Setup the sdk location changed listener and invoke it the first time
-        mSdkPathChangedListener = new SdkPathChangedListener();
-        FrameworkResourceManager.getInstance().addFrameworkResourcesChangeListener(
-                mSdkPathChangedListener);
-        
-        // ping the usage server
-        pingUsageServer();
-    }
-
-    /**
-     * The <code>AbstractUIPlugin</code> implementation of this <code>Plugin</code>
-     * method saves this plug-in's preference and dialog stores and shuts down 
-     * its image registry (if they are in use). Subclasses may extend this
-     * method, but must send super <b>last</b>. A try-finally statement should
-     * be used where necessary to ensure that <code>super.shutdown()</code> is
-     * always done.
-     * 
-     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
-     */
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        sPlugin = null;
-        sAndroidLogo.dispose();
-        
-        IconFactory.getInstance().Dispose();
-        
-        // Remove the resource listener that handles compiled resources.
-        IWorkspace ws = ResourcesPlugin.getWorkspace();
-        ResourceMonitor.stopMonitoring(ws);
-
-        FrameworkResourceManager.getInstance().removeFrameworkResourcesChangeListener(
-                mSdkPathChangedListener);
-        mSdkPathChangedListener = null;
-        
-        mRed.dispose();
-
-        super.stop(context);
-    }
-
-    /**
-     * Returns the shared instance
-     * 
-     * @return the shared instance
-     */
-    public static EditorsPlugin getDefault() {
-        return sPlugin;
-    }
-
-    /**
-     * Returns an Image for the small Android logo.
-     * 
-     * Callers should not dispose it.
-     */
-    public static Image getAndroidLogo() {
-        return sAndroidLogo;
-    }
-
-    /**
-     * Returns an {@link ImageDescriptor} for the small Android logo.
-     * 
-     * Callers should not dispose it.
-     */
-    public static ImageDescriptor getAndroidLogoDesc() {
-        return sAndroidLogoDesc;
-    }
-
-    /**
-     * Logs a message to the default Eclipse log.
-     * 
-     * @param severity One of IStatus' severity codes: OK, ERROR, INFO, WARNING or CANCEL.
-     * @param format The format string, like for String.format().
-     * @param args The arguments for the format string, like for String.format().
-     */
-    public static void log(int severity, String format, Object ... args) {
-        String message = String.format(format, args);
-        Status status = new Status(severity, AndroidConstants.EDITORS_PLUGIN_ID, message);
-        getDefault().getLog().log(status);
-    }
-
-    /**
-     * Logs an exception to the default Eclipse log.
-     * <p/>
-     * The status severity is always set to ERROR.
-     * 
-     * @param exception The exception to log. Its call trace will be recorded.
-     * @param format The format string, like for String.format().
-     * @param args The arguments for the format string, like for String.format().
-     */
-    public static void log(Throwable exception, String format, Object ... args) {
-        String message = String.format(format, args);
-        Status status = new Status(IStatus.ERROR, AndroidConstants.EDITORS_PLUGIN_ID,
-                message, exception);
-        getDefault().getLog().log(status);
-    }
-    
-    /**
-     * Returns the ResourceMonitor object.
-     */
-    public ResourceMonitor getResourceMonitor() {
-        return mResourceMonitor;
-    }
-
-    
-    /**
-     * Sets up the editor to register default editors for resource files when needed.
-     * 
-     * This is called by the {@link EditorsPlugin} during initialization.
-     * 
-     * @param monitor The main Resource Monitor object.
-     */
-    public void setupDefaultEditor(ResourceMonitor monitor) {
-        monitor.addFileListener(new IFileListener() {
-
-            private static final String UNKNOWN_EDITOR = "unknown-editor"; //$NON-NLS-1$
-            
-            /* (non-Javadoc)
-             * Sent when a file changed.
-             * @param file The file that changed.
-             * @param markerDeltas The marker deltas for the file.
-             * @param kind The change kind. This is equivalent to
-             * {@link IResourceDelta#accept(IResourceDeltaVisitor)}
-             * 
-             * @see IFileListener#fileChanged
-             */
-            public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
-                if (AndroidConstants.EXT_XML.equals(file.getFileExtension())) {
-                    // The resources files must have a file path similar to
-                    //    project/res/.../*.xml
-                    // There is no support for sub folders, so the segment count must be 4
-                    if (file.getFullPath().segmentCount() == 4) {
-                        // check if we are inside the res folder.
-                        String segment = file.getFullPath().segment(1); 
-                        if (segment.equalsIgnoreCase(AndroidConstants.FD_RESOURCES)) {
-                            // we are inside a res/ folder, get the actual ResourceFolder
-                            ProjectResources resources = ResourceManager.getInstance().
-                                getProjectResources(file.getProject());
-
-                            // This happens when importing old Android projects in Eclipse
-                            // that lack the container (probably because resources fail to build
-                            // properly.)
-                            if (resources == null) {
-                                log(IStatus.INFO,
-                                        "getProjectResources failed for path %1$s in project %2$s", //$NON-NLS-1$
-                                        file.getFullPath().toOSString(),
-                                        file.getProject().getName());
-                                return;
-                            }
-
-                            ResourceFolder resFolder = resources.getResourceFolder(
-                                (IFolder)file.getParent());
-                        
-                            if (resFolder != null) {
-                                if (kind == IResourceDelta.ADDED) {
-                                    resourceAdded(file, resFolder.getType());
-                                } else if (kind == IResourceDelta.CHANGED) {
-                                    resourceChanged(file, resFolder.getType());
-                                }
-                            } else {
-                                // if the res folder is null, this means the name is invalid,
-                                // in this case we remove whatever android editors that was set
-                                // as the default editor.
-                                IEditorDescriptor desc = IDE.getDefaultEditor(file);
-                                String editorId = desc.getId();
-                                if (editorId.startsWith(AndroidConstants.EDITORS_PLUGIN_ID)) {
-                                    // reset the default editor.
-                                    IDE.setDefaultEditor(file, null);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            private void resourceAdded(IFile file, ResourceFolderType type) {
-                // set the default editor based on the type.
-                if (type == ResourceFolderType.LAYOUT) {
-                    IDE.setDefaultEditor(file, LayoutEditor.ID);
-                } else if (type == ResourceFolderType.DRAWABLE
-                        || type == ResourceFolderType.VALUES) {
-                    IDE.setDefaultEditor(file, ResourcesEditor.ID);
-                } else if (type == ResourceFolderType.MENU) {
-                    IDE.setDefaultEditor(file, MenuEditor.ID);
-                } else if (type == ResourceFolderType.XML) {
-                    if (XmlEditor.canHandleFile(file)) {
-                        IDE.setDefaultEditor(file, XmlEditor.ID);
-                    } else {
-                        // set a property to determine later if the XML can be handled
-                        QualifiedName qname = new QualifiedName(
-                                AndroidConstants.EDITORS_PLUGIN_ID,
-                                UNKNOWN_EDITOR);
-                        try {
-                            file.setPersistentProperty(qname, "1");
-                        } catch (CoreException e) {
-                            // pass
-                        }
-                    }
-                }
-            }
-
-            private void resourceChanged(IFile file, ResourceFolderType type) {
-                if (type == ResourceFolderType.XML) {
-                    IEditorDescriptor ed = IDE.getDefaultEditor(file);
-                    if (ed == null || ed.getId() != XmlEditor.ID) {
-                        QualifiedName qname = new QualifiedName(
-                                AndroidConstants.EDITORS_PLUGIN_ID,
-                                UNKNOWN_EDITOR);
-                        String prop = null;
-                        try {
-                            prop = file.getPersistentProperty(qname);
-                        } catch (CoreException e) {
-                            // pass
-                        }
-                        if (prop != null && XmlEditor.canHandleFile(file)) {
-                            try {
-                                // remove the property & set editor
-                                file.setPersistentProperty(qname, null);
-                                IWorkbenchPage page = PlatformUI.getWorkbench().
-                                                        getActiveWorkbenchWindow().getActivePage();
-                                
-                                IEditorPart oldEditor = page.findEditor(new FileEditorInput(file));
-                                if (oldEditor != null &&
-                                        CommonPlugin.displayPrompt("Android XML Editor",
-                                            String.format("The file you just saved as been recognized as a file that could be better handled using the Android XML Editor. Do you want to edit '%1$s' using the Android XML editor instead?",
-                                                    file.getFullPath()))) {
-                                    IDE.setDefaultEditor(file, XmlEditor.ID);
-                                    IEditorPart newEditor = page.openEditor(
-                                            new FileEditorInput(file),
-                                            XmlEditor.ID,
-                                            true, /* activate */
-                                            IWorkbenchPage.MATCH_NONE);
-                                
-                                    if (newEditor != null) {
-                                        page.closeEditor(oldEditor, true /* save */);
-                                    }
-                                }
-                            } catch (CoreException e) {
-                                // setPersistentProperty or page.openEditor may have failed
-                            }
-                        }
-                    }
-                }
-            }
-
-        }, IResourceDelta.ADDED | IResourceDelta.CHANGED);
-    }
-
-    /**
-     * Respond to notifications from the resource manager than the SDK resources have been updated.
-     * It gets the new resources from the {@link FrameworkResourceManager} and then try to update
-     * the layout descriptors from the new layout data.
-     */
-    private class SdkPathChangedListener implements Runnable {
-        public void run() {
-
-            // Perform the update in a thread (here an Eclipse runtime job)
-            // since this should never block the caller (especially the start method)
-            new Job("Editors: Load Framework Resource Parser") {
-
-                @Override
-                protected IStatus run(IProgressMonitor monitor) {
-                    try {
-                        SubMonitor progress = SubMonitor.convert(monitor, "Update Description",
-                                60);
-                        
-                        FrameworkResourceManager resourceManager = FrameworkResourceManager.getInstance();
-                        
-                        AndroidManifestDescriptors.updateDescriptors(
-                                resourceManager.getManifestDefinitions());
-                        progress.worked(10);
-
-                        if (progress.isCanceled()) {
-                            return Status.CANCEL_STATUS;
-                        }
-
-                        LayoutDescriptors.getInstance().updateDescriptors(
-                                resourceManager.getLayoutViewsInfo(),
-                                resourceManager.getLayoutGroupsInfo());
-                        progress.worked(10);
-
-                        if (progress.isCanceled()) {
-                            return Status.CANCEL_STATUS;
-                        }
-
-                        MenuDescriptors.getInstance().updateDescriptors(
-                                resourceManager.getXmlMenuDefinitions());
-                        progress.worked(10);
-
-                        if (progress.isCanceled()) {
-                            return Status.CANCEL_STATUS;
-                        }
-
-                        XmlDescriptors.getInstance().updateDescriptors(
-                                resourceManager.getXmlSearchableDefinitions(),
-                                resourceManager.getPreferencesInfo(),
-                                resourceManager.getPreferenceGroupsInfo());
-                        progress.worked(10);
-                        
-                        // load the layout lib bridge.
-                        if (System.getenv("ANDROID_DISABLE_LAYOUT") == null) {
-                            loadLayoutBridge();
-                            FrameworkResourceManager frMgr = FrameworkResourceManager.getInstance();
-                            ResourceManager rMgr = ResourceManager.getInstance(); 
-                            rMgr.loadFrameworkResources(frMgr.getFrameworkResourcesLocation());
-                        }
-                        progress.worked(10);
-
-                        // Notify resource changed listeners
-                        progress.subTask("Refresh UI");
-                        progress.setWorkRemaining(mResourceRefreshListener.size());
-                        
-                        // Clone the list before iterating, to avoid Concurrent Modification
-                        // exceptions
-                        @SuppressWarnings("unchecked")
-                        ArrayList<Runnable> listeners = (ArrayList<Runnable>)
-                                                            mResourceRefreshListener.clone();
-                        for (Runnable listener : listeners) {
-                            try {
-                                getDisplay().syncExec(listener);
-                            } catch (Exception e) {
-                                log(e, "ResourceRefreshListener Failed");  //$NON-NLS-1$
-                            } finally {
-                                progress.worked(1);
-                            }
-                        }
-                    } catch (Throwable e) {
-                        EditorsPlugin.log(e, "Load Framework Resource Parser failed");  //$NON-NLS-1$
-                        EditorsPlugin.printToConsole("Framework Resource Parser",
-                                "Failed to parse");
-                    } finally {
-                        if (monitor != null) {
-                            monitor.done();
-                        }
-                    }
-                    return Status.OK_STATUS;
-                }
-            }.schedule();
-        }        
-    }
-
-    public void addResourceChangedListener(Runnable resourceRefreshListener) {
-        mResourceRefreshListener.add(resourceRefreshListener);
-    }
-
-    public void removeResourceChangedListener(Runnable resourceRefreshListener) {
-        mResourceRefreshListener.remove(resourceRefreshListener);
-    }
-    
-    public static Display getDisplay() {
-        IWorkbench bench = sPlugin.getWorkbench();
-        if (bench != null) {
-            return bench.getDisplay();
-        }
-        return null;
-    }
-    
-    /**
-     * Pings the usage start server.
-     */
-    private void pingUsageServer() {
-        // In order to not block the plugin loading, so we spawn another thread.
-        new Thread("Ping!") { //$NON-NLS-1$
-            @Override
-            public void run() {
-                // get the version of the plugin
-                String versionString = (String) getBundle().getHeaders().get(
-                        Constants.BUNDLE_VERSION);
-                Version version = new Version(versionString);
-                
-                SdkStatsHelper.pingUsageServer("editors", version); //$NON-NLS-1$
-            }
-        }.start();
-
-    }
-
-    /**
-     * Prints one or more message to the android console.
-     * @param tag The tag to be associated with the message. Can be null.
-     * @param objects the objects to print through their <code>toString</code> method.
-     */
-    public static synchronized void printToConsole(String tag, Object... objects) {
-        StreamHelper.printToStream(sPlugin.mAndroidConsoleStream, tag, objects);
-    }
-
-    /**
-     * Prints one or more error messages to the android console.
-     * @param tag The tag to be associated with the message. Can be null.
-     * @param objects the objects to print through their <code>toString</code> method.
-     */
-    public static synchronized void printErrorToConsole(String tag, Object... objects) {
-        StreamHelper.printToStream(sPlugin.mAndroidConsoleErrorStream, tag, objects);
-    }
-    
-    public static synchronized OutputStream getErrorStream() {
-        return sPlugin.mAndroidConsoleErrorStream;
-    }
-    
-    /**
-     * Displays an error dialog box. This dialog box is ran asynchronously in the ui thread,
-     * therefore this method can be called from any thread.
-     * @param title The title of the dialog box
-     * @param message The error message
-     */
-    public final static void displayError(final String title, final String message) {
-        // get the current Display
-        final Display display = getDisplay();
-
-        // dialog box only run in ui thread..
-        display.asyncExec(new Runnable() {
-            public void run() {
-                Shell shell = display.getActiveShell();
-                MessageDialog.openError(shell, title, message);
-            }
-        });
-    }
-
-    /**
-     * Display a yes/no question dialog box. This dialog is opened synchronously in the ui thread,
-     * therefore this message can be called from any thread.
-     * @param title The title of the dialog box
-     * @param message The error message
-     * @return true if OK was clicked.
-     */
-    public final static boolean displayPrompt(final String title, final String message) {
-        // get the current Display and Shell
-        final Display display = getDisplay();
-
-        // we need to ask the user what he wants to do.
-        final boolean[] wrapper = new boolean[] { false };
-        display.syncExec(new Runnable() {
-            public void run() {
-                Shell shell = display.getActiveShell();
-                wrapper[0] = MessageDialog.openQuestion(shell, title, message);
-            }
-        });
-        return wrapper[0];
-    }
-
-    /**
-     * Returns a {@link LayoutBridge} object possibly containing a {@link ILayoutBridge} object.
-     * <p/>If {@link LayoutBridge#bridge} is <code>null</code>, {@link LayoutBridge#status} will
-     * contain the reason (either {@link LoadStatus#LOADING} or {@link LoadStatus#FAILED}).
-     * <p/>Valid {@link ILayoutBridge} objects are always initialized before being returned.
-     */
-    public synchronized LayoutBridge getLayoutBridge() {
-        if (mLayoutBridgeInit == false && mLayoutBridge.bridge != null) {
-            FrameworkResourceManager manager = FrameworkResourceManager.getInstance(); 
-            mLayoutBridge.bridge.init(
-                        manager.getFrameworkFontLocation() + AndroidConstants.FD_DEFAULT_RES,
-                        manager.getEnumValueMap());
-            mLayoutBridgeInit = true;
-        }
-        return mLayoutBridge;
-    }
-    
-    /**
-     * Loads the layout bridge from the dynamically loaded layoutlib.jar
-     */
-    private void loadLayoutBridge() {
-        try {
-            // reset to be sure we won't be using an obsolete version if we
-            // get an exception somewhere.
-            mLayoutBridge.bridge = null;
-            mLayoutBridge.status = LayoutBridge.LoadStatus.LOADING;
-            
-            // get the URL for the file.
-            File f = new File(
-                    FrameworkResourceManager.getInstance().getLayoutLibLocation());
-            if (f.isFile() == false) {
-                log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$
-            } else {
-                URL url = f.toURL();
-                
-                // create a class loader. Because this jar reference interfaces
-                // that are in the editors plugin, it's important to provide 
-                // a parent class loader.
-                mBridgeClassLoader = new URLClassLoader(new URL[] { url },
-                        this.getClass().getClassLoader());
-   
-                // load the class
-                Class<?> clazz = mBridgeClassLoader.loadClass(AndroidConstants.CLASS_BRIDGE);
-                if (clazz != null) {
-                    // instantiate an object of the class.
-                    Constructor<?> constructor = clazz.getConstructor();
-                    if (constructor != null) {
-                        Object bridge = constructor.newInstance();
-                        if (bridge instanceof ILayoutBridge) {
-                            mLayoutBridge.bridge = (ILayoutBridge)bridge;
-                        }
-                    }
-                }
-                
-                if (mLayoutBridge.bridge == null) {
-                    mLayoutBridge.status = LayoutBridge.LoadStatus.FAILED;
-                    log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$
-                } else {
-                    mLayoutBridge.status = LayoutBridge.LoadStatus.LOADED;
-                }
-            }
-        } catch (Throwable t) {
-            mLayoutBridge.status = LayoutBridge.LoadStatus.FAILED;
-            // log the error.
-            log(t, "Failed to load the LayoutLib");
-        }
-    }
-    
-    public ClassLoader getLayoutlibBridgeClassLoader() {
-        return mBridgeClassLoader;
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java
deleted file mode 100644
index c936be3..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/LayoutTreePage.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.layout;
-
-import com.android.ide.eclipse.editors.EditorsPlugin;
-import com.android.ide.eclipse.editors.resources.manager.ResourceFolder;
-import com.android.ide.eclipse.editors.resources.manager.ResourceManager;
-import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.editor.FormPage;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-import org.eclipse.ui.part.FileEditorInput;
-
-/**
- * Page for the layout tree-based form editor.
- * 
- * @deprecated This is being phased out. We use the GraphicalLayoutEditor instead.
- */
-public final class LayoutTreePage extends FormPage {
-    /** Page id used for switching tabs programmatically */
-    public final static String PAGE_ID = "layout_tree_page"; //$NON-NLS-1$
-
-    /** Container editor */
-    LayoutEditor mEditor;
-
-    public LayoutTreePage(LayoutEditor editor) {
-        super(editor, PAGE_ID, "Layout");  // tab's label, keep it short
-        mEditor = editor;
-    }
-
-    /**
-     * Creates the content in the form hosted in this page.
-     * 
-     * @param managedForm the form hosted in this page.
-     */
-    @Override
-    protected void createFormContent(IManagedForm managedForm) {
-        super.createFormContent(managedForm);
-        ScrolledForm form = managedForm.getForm();
-
-        String configText = null;
-        IEditorInput input = mEditor.getEditorInput();
-        if (input instanceof FileEditorInput) {
-            FileEditorInput fileInput = (FileEditorInput)input;
-            IFile iFile = fileInput.getFile();
-            
-            ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder(iFile);
-            if (resFolder != null) {
-                configText = resFolder.getConfiguration().toDisplayString();
-            }
-        }
-        
-        if (configText != null) {
-            form.setText(String.format("Android Layout (%1$s)", configText));
-        } else {
-            form.setText("Android Layout");
-        }
-
-        form.setImage(EditorsPlugin.getAndroidLogo());
-
-        UiElementNode rootNode = mEditor.getUiRootNode();
-        UiTreeBlock block = new UiTreeBlock(mEditor, rootNode,
-                true /* autoCreateRoot */,
-                null /* no element filters */,
-                "Layout Elements",
-                "List of all layout elements in this XML file.");
-        block.createContent(managedForm);
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
deleted file mode 100644
index 77b1df4..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/PaletteFactory.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.layout;
-
-import com.android.ide.eclipse.editors.EditorsPlugin;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors;
-
-import org.eclipse.gef.palette.CombinedTemplateCreationEntry;
-import org.eclipse.gef.palette.MarqueeToolEntry;
-import org.eclipse.gef.palette.PaletteDrawer;
-import org.eclipse.gef.palette.PaletteGroup;
-import org.eclipse.gef.palette.PaletteRoot;
-import org.eclipse.gef.palette.PanningSelectionToolEntry;
-import org.eclipse.gef.requests.CreationFactory;
-
-import java.util.List;
-
-/**
- * Factory that creates the palette for the {@link GraphicalLayoutEditor}.
- */
-public class PaletteFactory {
-
-    private static PaletteRoot sPaletteRoot;
-    private static Runnable sSdkChangedListener;
-
-    /** Static factory, nothing to instantiate here. */
-    private PaletteFactory() {
-    }
-
-    public static PaletteRoot createPaletteRoot() {
-        if (sSdkChangedListener == null) {
-            sSdkChangedListener = new Runnable() {
-                public void run() {
-                    if (sPaletteRoot != null) {
-                        // The SDK has changed. Remove the drawer groups and rebuild them.
-                        for (int n = sPaletteRoot.getChildren().size() - 1; n >= 0; n--) {
-                            sPaletteRoot.getChildren().remove(n);
-                        }
-                        
-                        addTools(sPaletteRoot);
-                        addViews(sPaletteRoot, "Layouts",
-                                LayoutDescriptors.getInstance().getLayoutDescriptors());
-                        addViews(sPaletteRoot, "Views",
-                                LayoutDescriptors.getInstance().getViewDescriptors());
-                    }
-                }
-            };
-            EditorsPlugin.getDefault().addResourceChangedListener(sSdkChangedListener);
-        }
-        
-        if (sPaletteRoot == null) {
-            sPaletteRoot = new PaletteRoot();
-            sSdkChangedListener.run();
-        }
-        return sPaletteRoot;
-    }
-
-    private static void addTools(PaletteRoot paletteRoot) {
-        PaletteGroup group = new PaletteGroup("Tools");
-        
-        // Default tools: selection and marquee selection
-        PanningSelectionToolEntry entry = new PanningSelectionToolEntry();
-        group.add(entry);
-        paletteRoot.setDefaultEntry(entry);
-
-        group.add(new MarqueeToolEntry());
-        
-        paletteRoot.add(group);
-    }
-
-    private static void addViews(PaletteRoot paletteRoot, String groupName,
-            List<ElementDescriptor> descriptors) {
-        PaletteDrawer group = new PaletteDrawer(groupName);
-        
-        for (ElementDescriptor desc : descriptors) {
-            CombinedTemplateCreationEntry entry = new CombinedTemplateCreationEntry(
-                    desc.getUiName(),           // label
-                    desc.getTooltip(),          // short description
-                    desc.getClass(),            // template
-                    new ElementFactory(desc),   // factory
-                    desc.getImageDescriptor(),  // small icon
-                    desc.getImageDescriptor()   // large icon
-                    );
-            group.add(entry);
-        }
-        
-        paletteRoot.add(group);
-    }
-
-    //------------------------------------------
-
-    public static class ElementFactory implements CreationFactory {
-
-        private final ElementDescriptor mDescriptor;
-
-        public ElementFactory(ElementDescriptor descriptor) {
-            mDescriptor = descriptor;
-        }
-
-        public Object getNewObject() {
-            return mDescriptor;
-        }
-
-        public Object getObjectType() {
-            return mDescriptor;
-        }
-
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
deleted file mode 100644
index 41d3747..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/UiElementPullParser.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.layout;
-
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-import com.android.layoutlib.api.IXmlPullParser;
-
-import org.w3c.dom.Node;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * XmlPullParser implementation on top of {@link UiElementNode}.
- * <p/>It's designed to work on layout files, and will most likely not work on other resource
- * files.
- */
-public final class UiElementPullParser implements IXmlPullParser {
-    
-    private final ArrayList<UiElementNode> mNodeStack = new ArrayList<UiElementNode>();
-    private int mParsingState = START_DOCUMENT;
-    private UiElementNode mRoot;
-    
-    public UiElementPullParser(UiElementNode top) {
-        mRoot = top;
-        push(mRoot);
-    }
-    
-    private UiElementNode getCurrentNode() {
-        if (mNodeStack.size() > 0) {
-            return mNodeStack.get(mNodeStack.size()-1);
-        }
-        
-        return null;
-    }
-    
-    private Node getAttribute(int i) {
-        if (mParsingState != START_TAG) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        // get the current uiNode
-        UiElementNode uiNode = getCurrentNode();
-        
-        // get its xml node
-        Node xmlNode = uiNode.getXmlNode();
-
-        if (xmlNode != null) {
-            return xmlNode.getAttributes().item(i);
-        }
-
-        return null;
-    }
-    
-    private void push(UiElementNode node) {
-        mNodeStack.add(node);
-    }
-    
-    private UiElementNode pop() {
-        return mNodeStack.remove(mNodeStack.size()-1);
-    }
-
-    // ------------- IXmlPullParser --------
-
-    /**
-     * {@inheritDoc}
-     * 
-     * This implementation returns the underlying DOM node.
-     */
-    public Object getViewKey() {
-        return getCurrentNode();
-    }
-
-    // ------------- XmlPullParser --------
-
-    public void setFeature(String name, boolean state) throws XmlPullParserException {
-        if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
-            return;
-        }
-        if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
-            return;
-        }
-        throw new XmlPullParserException("Unsupported feature: " + name);
-    }
-
-    public boolean getFeature(String name) {
-        if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
-            return true;
-        }
-        if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
-            return true;
-        }
-        return false;
-    }
-
-    public void setProperty(String name, Object value) throws XmlPullParserException {
-        throw new XmlPullParserException("setProperty() not supported");
-    }
-
-    public Object getProperty(String name) {
-        return null;
-    }
-
-    public void setInput(Reader in) throws XmlPullParserException {
-        throw new XmlPullParserException("setInput() not supported");
-    }
-
-    public void setInput(InputStream inputStream, String inputEncoding)
-            throws XmlPullParserException {
-        throw new XmlPullParserException("setInput() not supported");
-    }
-
-    public void defineEntityReplacementText(String entityName, String replacementText)
-            throws XmlPullParserException {
-        throw new XmlPullParserException("defineEntityReplacementText() not supported");
-    }
-
-    public String getNamespacePrefix(int pos) throws XmlPullParserException {
-        throw new XmlPullParserException("getNamespacePrefix() not supported");
-    }
-
-    public String getInputEncoding() {
-        return null;
-    }
-
-    public String getNamespace(String prefix) {
-        throw new RuntimeException("getNamespace() not supported");
-    }
-
-    public int getNamespaceCount(int depth) throws XmlPullParserException {
-        throw new XmlPullParserException("getNamespaceCount() not supported");
-    }
-
-    public String getPositionDescription() {
-        return "XML DOM element depth:" + mNodeStack.size();
-    }
-
-    public String getNamespaceUri(int pos) throws XmlPullParserException {
-        throw new XmlPullParserException("getNamespaceUri() not supported");
-    }
-
-    public int getColumnNumber() {
-        return -1;
-    }
-
-    public int getLineNumber() {
-        return -1;
-    }
-
-    public int getAttributeCount() {
-        UiElementNode node = getCurrentNode();
-        if (node != null) {
-            return node.getUiAttributes().size();
-        }
-
-        return 0;
-    }
-
-    public String getAttributeName(int i) {
-        Node attribute = getAttribute(i);
-        if (attribute != null) {
-            return attribute.getLocalName();
-        }
-
-        return null;
-    }
-
-    public String getAttributeNamespace(int i) {
-        Node attribute = getAttribute(i);
-        if (attribute != null) {
-            return attribute.getNamespaceURI();
-        }
-        return ""; //$NON-NLS-1$
-    }
-
-    public String getAttributePrefix(int i) {
-        Node attribute = getAttribute(i);
-        if (attribute != null) {
-            return attribute.getPrefix();
-        }
-        return null;
-    }
-
-    public String getAttributeType(int arg0) {
-        return "CDATA";
-    }
-
-    public String getAttributeValue(int i) {
-        Node attribute = getAttribute(i);
-        if (attribute != null) {
-            return attribute.getNodeValue();
-        }
-        
-        return null;
-    }
-
-    public String getAttributeValue(String namespace, String localName) {
-        // get the current uiNode
-        UiElementNode uiNode = getCurrentNode();
-        
-        // get its xml node
-        Node xmlNode = uiNode.getXmlNode();
-        
-        if (xmlNode != null) {
-            Node attribute = xmlNode.getAttributes().getNamedItemNS(namespace, localName);
-            if (attribute != null) {
-                return attribute.getNodeValue();
-            }
-        }
-
-        return null;
-    }
-
-    public int getDepth() {
-        return mNodeStack.size();
-    }
-
-    public int getEventType() throws XmlPullParserException {
-        return mParsingState;
-    }
-
-    public String getName() {
-        if (mParsingState == START_TAG || mParsingState == END_TAG) {
-            return getCurrentNode().getDescriptor().getXmlLocalName();
-        }
-
-        return null;
-    }
-
-    public String getNamespace() {
-        if (mParsingState == START_TAG || mParsingState == END_TAG) {
-            return getCurrentNode().getDescriptor().getNamespace();
-        }
-
-        return null;
-    }
-
-    public String getPrefix() {
-        if (mParsingState == START_TAG || mParsingState == END_TAG) {
-            // FIXME will NEVER work
-            if (getCurrentNode().getDescriptor().getXmlLocalName().startsWith("android:")) { //$NON-NLS-1$
-                return "android"; //$NON-NLS-1$
-            }
-        }
-
-        return null;
-    }
-
-    public String getText() {
-        return null;
-    }
-
-    public char[] getTextCharacters(int[] arg0) {
-        return null;
-    }
-
-    public boolean isAttributeDefault(int arg0) {
-        return false;
-    }
-
-    public boolean isEmptyElementTag() throws XmlPullParserException {
-        if (mParsingState == START_TAG) {
-            return getCurrentNode().getUiChildren().size() == 0;
-        }
-        
-        throw new XmlPullParserException("Must be on START_TAG");
-    }
-
-    public boolean isWhitespace() throws XmlPullParserException {
-        return false;
-    }
-
-    public int next() throws XmlPullParserException, IOException {
-        UiElementNode node;
-        switch (mParsingState) {
-            case END_DOCUMENT:
-                throw new XmlPullParserException("Nothing after the end");
-            case START_DOCUMENT:
-                /* intended fall-through */
-            case START_TAG:
-                // get the current node, and look for text or children (children first)
-                node = getCurrentNode();
-                List<UiElementNode> children = node.getUiChildren();
-                if (children.size() > 0) {
-                    // move to the new child, and don't change the state.
-                    push(children.get(0));
-                    
-                    // in case the current state is CURRENT_DOC, we set the proper state.
-                    mParsingState = START_TAG;
-                } else {
-                    if (mParsingState == START_DOCUMENT) {
-                        // this handles the case where there's no node.
-                        mParsingState = END_DOCUMENT;
-                    } else {
-                        mParsingState = END_TAG;
-                    }
-                }
-                break;
-            case END_TAG:
-                // look for a sibling. if no sibling, go back to the parent
-                node = getCurrentNode();
-                node = node.getUiNextSibling();
-                if (node != null) {
-                    // to go to the sibling, we need to remove the current node,
-                    pop();
-                    // and add its sibling.
-                    push(node);
-                    mParsingState = START_TAG;
-                } else {
-                    // move back to the parent
-                    pop();
-                    
-                    // we have only one element left (mRoot), then we're done with the document.
-                    if (mNodeStack.size() == 1) {
-                        mParsingState = END_DOCUMENT;
-                    } else {
-                        mParsingState = END_TAG;
-                    }
-                }
-                break;
-            case TEXT:
-                // not used
-                break;
-            case CDSECT:
-                // not used
-                break;
-            case ENTITY_REF:
-                // not used
-                break;
-            case IGNORABLE_WHITESPACE:
-                // not used
-                break;
-            case PROCESSING_INSTRUCTION:
-                // not used
-                break;
-            case COMMENT:
-                // not used
-                break;
-            case DOCDECL:
-                // not used
-                break;
-        }
-        
-        return mParsingState;
-    }
-
-    public int nextTag() throws XmlPullParserException, IOException {
-        int eventType = next();
-        if (eventType != START_TAG && eventType != END_TAG) {
-            throw new XmlPullParserException("expected start or end tag", this, null);
-        }
-        return eventType;
-    }
-
-    public String nextText() throws XmlPullParserException, IOException {
-        if (getEventType() != START_TAG) {
-            throw new XmlPullParserException("parser must be on START_TAG to read next text", this,
-                    null);
-        }
-        int eventType = next();
-        if (eventType == TEXT) {
-            String result = getText();
-            eventType = next();
-            if (eventType != END_TAG) {
-                throw new XmlPullParserException(
-                        "event TEXT it must be immediately followed by END_TAG", this, null);
-            }
-            return result;
-        } else if (eventType == END_TAG) {
-            return "";
-        } else {
-            throw new XmlPullParserException("parser must be on START_TAG or TEXT to read text",
-                    this, null);
-        }
-    }
-
-    public int nextToken() throws XmlPullParserException, IOException {
-        return next();
-    }
-
-    public void require(int type, String namespace, String name) throws XmlPullParserException,
-            IOException {
-        if (type != getEventType() || (namespace != null && !namespace.equals(getNamespace()))
-                || (name != null && !name.equals(getName())))
-            throw new XmlPullParserException("expected " + TYPES[type] + getPositionDescription());
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
deleted file mode 100644
index 548a3a2..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiElementEditPart.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.layout.parts;
-
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.draw2d.geometry.Rectangle;
-import org.eclipse.gef.DragTracker;
-import org.eclipse.gef.EditPart;
-import org.eclipse.gef.EditPolicy;
-import org.eclipse.gef.GraphicalEditPart;
-import org.eclipse.gef.Request;
-import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
-import org.eclipse.gef.editpolicies.SelectionEditPolicy;
-import org.eclipse.gef.tools.SelectEditPartTracker;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import java.util.List;
-
-/**
- * An {@link EditPart} for a {@link UiElementNode}.
- */
-public abstract class UiElementEditPart extends AbstractGraphicalEditPart
-    implements IUiUpdateListener {
-    
-    public UiElementEditPart(UiElementNode uiElementNode) {
-        setModel(uiElementNode);
-    }
-
-    //-------------------------
-    // Derived classes must define these
-
-    abstract protected void hideSelection();
-    abstract protected void showSelection();
-
-    //-------------------------
-    // Base class overrides
-    
-    @Override
-    public DragTracker getDragTracker(Request request) {
-        return new SelectEditPartTracker(this);
-    }
-
-    @Override
-    protected void createEditPolicies() {
-        installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, new SelectionEditPolicy() {
-            @Override
-            protected void hideSelection() {
-                UiElementEditPart.this.hideSelection();
-            }
-
-            @Override
-            protected void showSelection() {
-                UiElementEditPart.this.showSelection();
-            }
-        });
-        // TODO add editing policies
-    }
-    
-    /* (non-javadoc)
-     * Returns a List containing the children model objects.
-     * Must not return null, instead use the super which returns an empty list.
-     */
-    @SuppressWarnings("unchecked")
-    @Override
-    protected List getModelChildren() {
-        return getUiNode().getUiChildren();
-    }
-
-    @Override
-    public void activate() {
-        super.activate();
-        getUiNode().addUpdateListener(this);
-    }
-    
-    @Override
-    public void deactivate() {
-        super.deactivate();
-        getUiNode().removeUpdateListener(this);
-    }
-
-    @Override
-    protected void refreshVisuals() {
-        if (getFigure().getParent() != null) {
-            ((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), getBounds());
-        }
-        
-        // update the visuals of the children as well
-        refreshChildrenVisuals();
-    }
-    
-    protected void refreshChildrenVisuals() {
-        if (children != null) {
-            for (Object child : children) {
-                if (child instanceof UiElementEditPart) {
-                    UiElementEditPart childPart = (UiElementEditPart)child;
-                    childPart.refreshVisuals();
-                }
-            }
-        }
-    }
-    
-    //-------------------------
-    // IUiUpdateListener implementation
-
-    public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
-        // TODO: optimize by refreshing only when needed
-        switch(state) {
-        case ATTR_UPDATED:
-            refreshVisuals();
-            break;
-        case CHILDREN_CHANGED:
-            refreshChildren();
-            
-            // new children list, need to update the layout
-            refreshVisuals();
-            break;
-        case CREATED:
-            refreshVisuals();
-            break;
-        case DELETED:
-            // pass
-            break;
-        }
-    }
-
-    //-------------------------
-    // Local methods
-
-    /** @return The object model casted to an {@link UiElementNode} */
-    protected final UiElementNode getUiNode() {
-        return (UiElementNode) getModel();
-    }
-    
-    protected final ElementDescriptor getDescriptor() {
-        return getUiNode().getDescriptor();
-    }
-    
-    protected final UiElementEditPart getEditPartParent() {
-        EditPart parent = getParent();
-        if (parent instanceof UiElementEditPart) {
-            return (UiElementEditPart)parent; 
-        }
-        return null;
-    }
-    
-    /**
-     * Returns a given XML attribute.
-     * @param attrbName The local name of the attribute.
-     * @return the attribute as a {@link String}, if it exists, or <code>null</code>
-     */
-    protected final String getStringAttr(String attrName) {
-        UiElementNode uiNode = getUiNode();
-        if (uiNode.getXmlNode() != null) {
-            Node xmlNode = uiNode.getXmlNode();
-            if (xmlNode != null) {
-                NamedNodeMap nodeAttributes = xmlNode.getAttributes();
-                if (nodeAttributes != null) {
-                    Node attr = nodeAttributes.getNamedItemNS(
-                            AndroidConstants.NS_RESOURCES, attrName);
-                    if (attr != null) {
-                        return attr.getNodeValue();
-                    }
-                }
-            }
-        }
-        return null;
-    }
-    
-    protected final Rectangle getBounds() {
-        UiElementNode model = (UiElementNode)getModel();
-        
-        Object editData = model.getEditData();
-        if (editData instanceof Rectangle) {
-            return (Rectangle)editData;  // return a copy?
-        }
-
-        // return a dummy rect
-        return new Rectangle(0, 0, 0, 0);
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
deleted file mode 100644
index d9433ca..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/layout/parts/UiLayoutEditPart.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.layout.parts;
-
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.draw2d.ColorConstants;
-import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.Label;
-import org.eclipse.draw2d.LineBorder;
-import org.eclipse.draw2d.XYLayout;
-import org.eclipse.gef.EditPolicy;
-import org.eclipse.gef.commands.Command;
-import org.eclipse.gef.editpolicies.ContainerEditPolicy;
-import org.eclipse.gef.requests.CreateRequest;
-
-/**
- * Graphical edit part for an {@link UiElementNode} that represents a ViewLayout.
- * <p/>
- * It acts as a simple container. 
- */
-public final class UiLayoutEditPart extends UiElementEditPart {
-    
-    public UiLayoutEditPart(UiElementNode uiElementNode) {
-        super(uiElementNode);
-    }
-    
-    @Override
-    protected void createEditPolicies() {
-        super.createEditPolicies();
-        
-        installEditPolicy(EditPolicy.CONTAINER_ROLE, new ContainerEditPolicy() {
-            @Override
-            protected Command getCreateCommand(CreateRequest request) {
-                return null;
-            }
-        });
-    }
-
-    @Override
-    protected IFigure createFigure() {
-        Label f = new Label();
-        f.setLayoutManager(new XYLayout());
-        return f;
-    }
-
-    @Override
-    protected void hideSelection() {
-        IFigure f = getFigure();
-        if (f instanceof Label) {
-            f.setBorder(null);
-        }
-    }
-
-    @Override
-    protected void showSelection() {
-        IFigure f = getFigure();
-        if (f instanceof Label) {
-            f.setBorder(new LineBorder(ColorConstants.red, 1));
-        }
-    }
-    
-    public void showDropTarget() {
-        IFigure f = getFigure();
-        if (f instanceof Label) {
-            f.setBorder(new LineBorder(ColorConstants.blue, 1));
-        }
-    }
-
-    public void hideDropTarget() {
-        hideSelection();
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
deleted file mode 100644
index 7e38032..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/CopyCutAction.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2008 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.editors.ui.tree;
-
-import com.android.ide.eclipse.editors.AndroidEditor;
-import com.android.ide.eclipse.editors.EditorsPlugin;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.apache.xml.serialize.Method;
-import org.apache.xml.serialize.OutputFormat;
-import org.apache.xml.serialize.XMLSerializer;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.swt.dnd.Clipboard;
-import org.eclipse.swt.dnd.TextTransfer;
-import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
-import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
-import org.eclipse.wst.xml.core.internal.document.NodeContainer;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import java.io.StringWriter;
-
-
-/**
- * Provides Cut and Copy actions for the tree nodes.
- */
-public class CopyCutAction extends Action {
-    private UiElementNode mUiNode;
-    private boolean mPerformCut;
-    private final AndroidEditor mEditor;
-    private final Clipboard mClipboard;
-    private final ICommitXml mXmlCommit;
-
-    /**
-     * Creates a new Copy or Cut action.
-     * 
-     * @param ui_node The UI node to cut or copy. It *must* have a non-null XML node.
-     * @param perform_cut True if the operation is cut, false if it is copy.
-     */
-    public CopyCutAction(AndroidEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
-            UiElementNode ui_node, boolean perform_cut) {
-        super(perform_cut ? "Cut" : "Copy");
-        mEditor = editor;
-        mClipboard = clipboard;
-        mXmlCommit = xmlCommit;
-        
-        ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
-        if (perform_cut) {
-            setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
-            setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
-            setDisabledImageDescriptor(
-                    images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));
-        } else {
-            setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
-            setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
-            setDisabledImageDescriptor(
-                    images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));
-        }
-
-        mUiNode = ui_node;
-        mPerformCut = perform_cut;
-    }
-
-    /**
-     * Performs the cut or copy action.
-     * First an XML serializer is used to turn the existing XML node into a valid
-     * XML fragment, which is added as text to the clipboard.
-     */
-    @Override
-    public void run() {
-        super.run();
-        try {
-            String data = null;
-            
-            // Get the data directly from the editor.
-            
-            // Commit the current pages first, to make sure the XML is in sync.
-            if (mXmlCommit != null) {
-                mXmlCommit.commitPendingXmlChanges();
-            }
-
-            // Committing may change the XML structure.
-            Node xml_node = mUiNode.getXmlNode();
-            if (xml_node == null) {
-                return;
-            }
-
-            IStructuredModel model = mEditor.getModelForRead();
-            try {
-                IStructuredDocument sse_doc = mEditor.getStructuredDocument();
-                if (xml_node instanceof NodeContainer) {
-                    // The easy way to get the source of an SSE XML node.
-                    data = ((NodeContainer) xml_node).getSource();
-                } else  if (xml_node instanceof IndexedRegion && sse_doc != null) {
-                    // Try harder.
-                    IndexedRegion region = (IndexedRegion) xml_node;
-                    int start = region.getStartOffset();
-                    int end = region.getEndOffset();
-
-                    if (end > start) {
-                        data = sse_doc.get(start, end - start);
-                    }
-                }
-            } catch (BadLocationException e) {
-                // the region offset was invalid. ignore.
-                } finally {
-                    model.releaseFromRead();
-                }
- 
-                // In the unlikely event that IStructuredDocument failed to extract the text
-            // directly from the editor, try to fall back on a direct XML serialization
-            // of the XML node. This uses the generic Node interface with no SSE tricks.
-            if (data == null) {
-                StringWriter sw = new StringWriter();
-                XMLSerializer serializer = new XMLSerializer(sw,
-                        new OutputFormat(Method.XML,
-                                OutputFormat.Defaults.Encoding /* utf-8 */,
-                                true /* indent */));
-                // Serialize will throw an IOException if it fails.
-                serializer.serialize((Element) xml_node);
-                data = sw.toString();
-            }
-
-            if (data != null && data.length() > 0) {
-                mClipboard.setContents(
-                        new Object[] { data },
-                        new Transfer[] { TextTransfer.getInstance() });
-                if (mPerformCut) {
-                    mUiNode.deleteXmlNode();
-                }
-            }
-        } catch (Exception e) {
-            EditorsPlugin.log(e, "CopyCutAction failed for UI node %1$s", //$NON-NLS-1$
-                    mUiNode.getBreadcrumbTrailDescription(true));
-        }
-    }
-}
-
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java b/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
deleted file mode 100644
index b3d0755..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.editors/src/com/android/ide/eclipse/editors/ui/tree/UiActions.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.editors.ui.tree;
-
-import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
-import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.editors.uimodel.UiElementNode;
-
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.swt.widgets.Shell;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-
-/**
- * Performs basic actions on an XML tree: add node, remove node, move up/down.
- */
-public abstract class UiActions implements ICommitXml {
-
-    public UiActions() {
-    }
-
-    //---------------------
-    // Actual implementations must override these to provide specific hooks
-
-    /** Returns the UiDocumentNode for the current model. */
-    abstract protected UiElementNode getRootNode();
-
-    /** Commits pending data before the XML model is modified. */
-    abstract public void commitPendingXmlChanges();
-
-    /**
-     * Utility method to select an outline item based on its model node
-     * 
-     * @param ui_node The node to select. Can be null (in which case nothing should happen)
-     */
-    abstract protected void selectUiNode(UiElementNode ui_node);
-
-    //---------------------
-
-    /**
-     * Called when the "Add..." button next to the tree view is selected.
-     * <p/>
-     * This simplified version of doAdd does not support descriptor filters and creates
-     * a new {@link UiModelTreeLabelProvider} for each call.
-     */
-    public void doAdd(UiElementNode ui_node, Shell shell) {
-        doAdd(ui_node, null /* descriptorFilters */, shell, new UiModelTreeLabelProvider());
-    }
-    
-    /**
-     * Called when the "Add..." button next to the tree view is selected.
-     * 
-     * Displays a selection dialog that lets the user select which kind of node
-     * to create, depending on the current selection.
-     */
-    public void doAdd(UiElementNode ui_node,
-            ElementDescriptor[] descriptorFilters,
-            Shell shell, ILabelProvider labelProvider) {
-        // If the root node is a document with already a root, use it as the root node
-        UiElementNode root_node = getRootNode();
-        if (root_node instanceof UiDocumentNode && 
-                root_node.getUiChildren().size() > 0) {
-            root_node = root_node.getUiChildren().get(0);
-        }
-
-        NewItemSelectionDialog dlg = new NewItemSelectionDialog(
-                shell,
-                labelProvider,
-                descriptorFilters,
-                ui_node, root_node);
-        dlg.open();
-        Object[] results = dlg.getResult();
-        if (results != null && results.length > 0) {
-            UiElementNode ui_new = addNewTreeElement(dlg.getChosenRootNode(),
-                    (ElementDescriptor) results[0]);
-
-            selectUiNode(ui_new);
-        }
-    }
-
-    /**
-     * Called when the "Remove" button is selected.
-     * 
-     * If the tree has a selection, remove it.
-     * This simply deletes the XML node attached to the UI node: when the XML model fires the
-     * update event, the tree will get refreshed.
-     */
-    public void doRemove(final UiElementNode ui_node, Shell shell) {
-        if (MessageDialog.openQuestion(shell,
-                "Remove element from Android XML",  // title
-                String.format("Do you really want to remove %1$s?",
-                        ui_node.getBreadcrumbTrailDescription(false /* include_root */)))) {
-            commitPendingXmlChanges();
-            getRootNode().getEditor().editXmlModel(new Runnable() {
-                public void run() {
-                    UiElementNode previous = ui_node.getUiPreviousSibling();
-                    UiElementNode parent = ui_node.getUiParent();
-                    
-                    // delete node
-                    ui_node.deleteXmlNode();
-                    
-                    // try to select the previous sibling or the parent
-                    if (previous != null) {
-                        selectUiNode(previous);
-                    } else if (parent != null) {
-                        selectUiNode(parent);
-                    }
-                }
-            });
-        }
-    }
-
-    /**
-     * Called when the "Up" button is selected.
-     * <p/>
-     * If the tree has a selection, move it up, either in the child list or as the last child
-     * of the previous parent.
-     */
-    public void doUp(final UiElementNode ui_node) {
-        final Node[] select_xml_node = { null };
-        // the node will move either up to its parent or grand-parent
-        UiElementNode search_root = ui_node.getUiParent();
-        if (search_root != null && search_root.getUiParent() != null) {
-            search_root = search_root.getUiParent();
-        }
-
-        commitPendingXmlChanges();
-        getRootNode().getEditor().editXmlModel(new Runnable() {
-            public void run() {
-                Node xml_node = ui_node.getXmlNode();
-                if (xml_node != null) {
-                    Node xml_parent = xml_node.getParentNode();
-                    if (xml_parent != null) {
-                        UiElementNode ui_prev = ui_node.getUiPreviousSibling();
-                        if (ui_prev != null && ui_prev.getXmlNode() != null) {
-                            // This node is not the first one of the parent, so it can be
-                            // removed and then inserted before its previous sibling.
-                            // If the previous sibling can have children, though, then it
-                            // is inserted at the end of the children list.
-                            Node xml_prev = ui_prev.getXmlNode();
-                            if (ui_prev.getDescriptor().hasChildren()) {
-                                xml_prev.appendChild(xml_parent.removeChild(xml_node));
-                                select_xml_node[0] = xml_node;
-                            } else {
-                                xml_parent.insertBefore(
-                                        xml_parent.removeChild(xml_node),
-                                        xml_prev);
-                                select_xml_node[0] = xml_node;
-                            }
-                        } else if (!(xml_parent instanceof Document) &&
-                                xml_parent.getParentNode() != null &&
-                                !(xml_parent.getParentNode() instanceof Document)) {
-                            // If the node is the first one of the child list of its
-                            // parent, move it up in the hierarchy as previous sibling
-                            // to the parent. This is only possible if the parent of the
-                            // parent is not a document.
-                            Node grand_parent = xml_parent.getParentNode();
-                            grand_parent.insertBefore(xml_parent.removeChild(xml_node),
-                                    xml_parent);
-                            select_xml_node[0] = xml_node;
-                        }
-                    }
-                }
-            }
-        });
-
-        if (select_xml_node[0] == null) {
-            // The XML node has not been moved, we can just select the same UI node
-            selectUiNode(ui_node);
-        } else {
-            // The XML node has moved. At this point the UI model has been reloaded
-            // and the XML node has been affected to a new UI node. Find that new UI
-            // node and select it.
-            if (search_root == null) {
-                search_root = ui_node.getUiRoot();
-            }
-            if (search_root != null) {
-                selectUiNode(search_root.findXmlNode(select_xml_node[0]));
-            }
-        }
-    }
-
-    /**
-     * Called when the "Down" button is selected.
-     * 
-     * If the tree has a selection, move it down, either in the same child list or as the
-     * first child of the next parent.
-     */
-    public void doDown(final UiElementNode ui_node) {
-        final Node[] select_xml_node = { null };
-        // the node will move either down to its parent or grand-parent
-        UiElementNode search_root = ui_node.getUiParent();
-        if (search_root != null && search_root.getUiParent() != null) {
-            search_root = search_root.getUiParent();
-        }
-
-        commitPendingXmlChanges();
-        getRootNode().getEditor().editXmlModel(new Runnable() {
-            public void run() {
-                Node xml_node = ui_node.getXmlNode();
-                if (xml_node != null) {
-                    Node xml_parent = xml_node.getParentNode();
-                    if (xml_parent != null) {
-                        UiElementNode ui_next = ui_node.getUiNextSibling();
-                        if (ui_next != null && ui_next.getXmlNode() != null) {
-                            // This node is not the last one of the parent, so it can be
-                            // removed and then inserted after its next sibling.
-                            // If the next sibling is a node that can have children, though,
-                            // then the node is inserted as the first child.
-                            Node xml_next = ui_next.getXmlNode();
-                            if (ui_next.getDescriptor().hasChildren()) {
-                                // Note: insertBefore works as append if the ref node is
-                                // null, i.e. when the node doesn't have children yet.
-                                xml_next.insertBefore(xml_parent.removeChild(xml_node),
-                                        xml_next.getFirstChild());
-                                select_xml_node[0] = xml_node;
-                            } else {
-                                // Insert "before after next" ;-)
-                                xml_parent.insertBefore(xml_parent.removeChild(xml_node),
-                                        xml_next.getNextSibling());
-                                select_xml_node[0] = xml_node;
-                            }
-                        } else if (!(xml_parent instanceof Document) &&
-                                xml_parent.getParentNode() != null &&
-                                !(xml_parent.getParentNode() instanceof Document)) {
-                            // This node is the last node of its parent.
-                            // If neither the parent nor the grandparent is a document,
-                            // then the node can be insert right after the parent.
-                            Node grand_parent = xml_parent.getParentNode();
-                            grand_parent.insertBefore(xml_parent.removeChild(xml_node),
-                                    xml_parent.getNextSibling());
-                            select_xml_node[0] = xml_node;
-                        }
-                    }
-                }
-            }
-        });
-
-        if (select_xml_node[0] == null) {
-            // The XML node has not been moved, we can just select the same UI node
-            selectUiNode(ui_node);
-        } else {
-            // The XML node has moved. At this point the UI model has been reloaded
-            // and the XML node has been affected to a new UI node. Find that new UI
-            // node and select it.
-            if (search_root == null) {
-                search_root = ui_node.getUiRoot();
-            }
-            if (search_root != null) {
-                selectUiNode(search_root.findXmlNode(select_xml_node[0]));
-            }
-        }
-    }
-
-    //---------------------
-    
-    /**
-     * Adds a new element of the given descriptor's type to the given UI parent node.
-     * 
-     * This actually creates the corresponding XML node in the XML model, which in turn
-     * will refresh the current tree view.
-     *  
-     * @param ui_parent An existing UI node or null to add to the tree root
-     * @param elementDescriptor The descriptor of the element to add
-     * @return The {@link UiElementNode} that has been added to the UI tree.
-     */
-    private UiElementNode addNewTreeElement(UiElementNode ui_parent,
-            ElementDescriptor elementDescriptor) {
-        commitPendingXmlChanges();
-        final UiElementNode ui_new = ui_parent.appendNewUiChild(elementDescriptor);
-        UiElementNode root_node = getRootNode();
-
-        root_node.getEditor().editXmlModel(new Runnable() {
-            public void run() {
-                DescriptorsUtils.setDefaultLayoutAttributes(ui_new);
-                ui_new.createXmlNode();
-            }
-        });
-        return ui_new;
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/.classpath b/tools/eclipse/plugins/com.android.ide.eclipse.platform/.classpath
deleted file mode 100644
index 751c8f2..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/.classpath
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/.project b/tools/eclipse/plugins/com.android.ide.eclipse.platform/.project
deleted file mode 100644
index 145d97c..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/.project
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>platform</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.pde.ManifestBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.pde.SchemaBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.pde.PluginNature</nature>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF
deleted file mode 100644
index 178275a..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,15 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Android Platform Development Toolkit
-Bundle-SymbolicName: com.android.ide.eclipse.platform;singleton:=true
-Bundle-Version: 0.8.1.qualifier
-Bundle-ClassPath: .
-Bundle-Activator: com.android.ide.eclipse.platform.AndroidPlatformPlugin
-Bundle-Vendor: The Android Open Source Project
-Require-Bundle: org.eclipse.ui,
- org.eclipse.core.runtime,
- com.android.ide.eclipse.ddms,
- com.android.ide.eclipse.common,
- org.eclipse.core.resources,
- org.eclipse.jdt.core
-Eclipse-LazyStart: true
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL b/tools/eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL
deleted file mode 100644
index e69de29..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/MODULE_LICENSE_EPL
+++ /dev/null
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/NOTICE b/tools/eclipse/plugins/com.android.ide.eclipse.platform/NOTICE
deleted file mode 100644
index 49c101d..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/NOTICE
+++ /dev/null
@@ -1,224 +0,0 @@
-*Eclipse Public License - v 1.0*
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
-THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-*1. DEFINITIONS*
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and
-documentation distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-
-i) changes to the Program, and
-
-ii) additions to the Program;
-
-where such changes and/or additions to the Program originate from and
-are distributed by that particular Contributor. A Contribution
-'originates' from a Contributor if it was added to the Program by such
-Contributor itself or anyone acting on such Contributor's behalf.
-Contributions do not include additions to the Program which: (i) are
-separate modules of software distributed in conjunction with the Program
-under their own license agreement, and (ii) are not derivative works of
-the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents " mean patent claims licensable by a Contributor which
-are necessarily infringed by the use or sale of its Contribution alone
-or when combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-*2. GRANT OF RIGHTS*
-
-a) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free copyright
-license to reproduce, prepare derivative works of, publicly display,
-publicly perform, distribute and sublicense the Contribution of such
-Contributor, if any, and such derivative works, in source code and
-object code form.
-
-b) Subject to the terms of this Agreement, each Contributor hereby
-grants Recipient a non-exclusive, worldwide, royalty-free patent license
-under Licensed Patents to make, use, sell, offer to sell, import and
-otherwise transfer the Contribution of such Contributor, if any, in
-source code and object code form. This patent license shall apply to the
-combination of the Contribution and the Program if, at the time the
-Contribution is added by the Contributor, such addition of the
-Contribution causes such combination to be covered by the Licensed
-Patents. The patent license shall not apply to any other combinations
-which include the Contribution. No hardware per se is licensed hereunder.
-
-c) Recipient understands that although each Contributor grants the
-licenses to its Contributions set forth herein, no assurances are
-provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.
-
-d) Each Contributor represents that to its knowledge it has sufficient
-copyright rights in its Contribution, if any, to grant the copyright
-license set forth in this Agreement.
-
-*3. REQUIREMENTS*
-
-A Contributor may choose to distribute the Program in object code form
-under its own license agreement, provided that:
-
-a) it complies with the terms and conditions of this Agreement; and
-
-b) its license agreement:
-
-i) effectively disclaims on behalf of all Contributors all warranties
-and conditions, express and implied, including warranties or conditions
-of title and non-infringement, and implied warranties or conditions of
-merchantability and fitness for a particular purpose;
-
-ii) effectively excludes on behalf of all Contributors all liability for
-damages, including direct, indirect, special, incidental and
-consequential damages, such as lost profits;
-
-iii) states that any provisions which differ from this Agreement are
-offered by that Contributor alone and not by any other party; and
-
-iv) states that source code for the Program is available from such
-Contributor, and informs licensees how to obtain it in a reasonable
-manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-a) it must be made available under this Agreement; and
-
-b) a copy of this Agreement must be included with each copy of the Program.
-
-Contributors may not remove or alter any copyright notices contained
-within the Program.
-
-Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.
-
-*4. COMMERCIAL DISTRIBUTION*
-
-Commercial distributors of software may accept certain responsibilities
-with respect to end users, business partners and the like. While this
-license is intended to facilitate the commercial use of the Program, the
-Contributor who includes the Program in a commercial product offering
-should do so in a manner which does not create potential liability for
-other Contributors. Therefore, if a Contributor includes the Program in
-a commercial product offering, such Contributor ("Commercial
-Contributor") hereby agrees to defend and indemnify every other
-Contributor ("Indemnified Contributor") against any losses, damages and
-costs (collectively "Losses") arising from claims, lawsuits and other
-legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such
-Commercial Contributor in connection with its distribution of the
-Program in a commercial product offering. The obligations in this
-section do not apply to any claims or Losses relating to any actual or
-alleged intellectual property infringement. In order to qualify, an
-Indemnified Contributor must: a) promptly notify the Commercial
-Contributor in writing of such claim, and b) allow the Commercial
-Contributor to control, and cooperate with the Commercial Contributor
-in, the defense and any related settlement negotiations. The Indemnified
-Contributor may participate in any such claim at its own expense.
-
-For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.
-
-*5. NO WARRANTY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED
-ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
-OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR
-A PARTICULAR PURPOSE. Each Recipient is solely responsible for
-determining the appropriateness of using and distributing the Program
-and assumes all risks associated with its exercise of rights under this
-Agreement , including but not limited to the risks and costs of program
-errors, compliance with applicable laws, damage to or loss of data,
-programs or equipment, and unavailability or interruption of operations.
-
-*6. DISCLAIMER OF LIABILITY*
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
-ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-*7. GENERAL*
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including
-a cross-claim or counterclaim in a lawsuit) alleging that the Program
-itself (excluding combinations of the Program with other software or
-hardware) infringes such Recipient's patent(s), then such Recipient's
-rights granted under Section 2(b) shall terminate as of the date such
-litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails
-to comply with any of the material terms or conditions of this Agreement
-and does not cure such failure in a reasonable period of time after
-becoming aware of such noncompliance. If all Recipient's rights under
-this Agreement terminate, Recipient agrees to cease use and distribution
-of the Program as soon as reasonably practicable. However, Recipient's
-obligations under this Agreement and any licenses granted by Recipient
-relating to the Program shall continue and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement,
-but in order to avoid inconsistency the Agreement is copyrighted and may
-only be modified in the following manner. The Agreement Steward reserves
-the right to publish new versions (including revisions) of this
-Agreement from time to time. No one other than the Agreement Steward has
-the right to modify this Agreement. The Eclipse Foundation is the
-initial Agreement Steward. The Eclipse Foundation may assign the
-responsibility to serve as the Agreement Steward to a suitable separate
-entity. Each new version of the Agreement will be given a distinguishing
-version number. The Program (including Contributions) may always be
-distributed subject to the version of the Agreement under which it was
-received. In addition, after a new version of the Agreement is
-published, Contributor may elect to distribute the Program (including
-its Contributions) under the new version. Except as expressly stated in
-Sections 2(a) and 2(b) above, Recipient receives no rights or licenses
-to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in
-the Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to
-this Agreement will bring a legal action under this Agreement more than
-one year after the cause of action arose. Each party waives its rights
-to a jury trial in any resulting litigation.
-
- 
-
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/build.properties b/tools/eclipse/plugins/com.android.ide.eclipse.platform/build.properties
deleted file mode 100644
index 6c480f3..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/build.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
-               .,\
-               plugin.xml,\
-               icons/
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.png b/tools/eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.png
deleted file mode 100644
index 6171025..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/icons/android_project.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml
deleted file mode 100644
index 1c5d067..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/plugin.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.2"?>
-<plugin>
-   <extension
-         id="PlatformNature"
-         name="PlatformNature"
-         point="org.eclipse.core.resources.natures">
-      <runtime>
-         <run class="com.android.ide.eclipse.platform.project.PlatformNature"/>
-      </runtime>
-   </extension>
-   <extension
-         point="org.eclipse.ui.ide.projectNatureImages">
-      <image
-            icon="icons/android_project.png"
-            id="com.android.ide.eclipse.platform.PlatformNature.image"
-            natureId="com.android.ide.eclipse.platform.PlatformNature">
-      </image>
-   </extension>
-   <extension
-         point="org.eclipse.ui.preferencePages">
-      <page
-            class="com.android.ide.eclipse.platform.preferences.AndroidPreferencePage"
-            id="com.android.ide.eclipse.preferences.main"
-            name="Android"/>
-   </extension>
-   <extension
-         point="org.eclipse.jdt.core.classpathContainerInitializer">
-      <classpathContainerInitializer
-            class="com.android.ide.eclipse.platform.project.PlatformClasspathContainerInitializer"
-            id="com.android.ide.eclipse.platform.DUMMY_CONTAINER">
-      </classpathContainerInitializer>
-   </extension>
-   <extension
-         point="org.eclipse.ui.popupMenus">
-      <objectContribution
-            id="com.android.ide.eclipse.platform.contribution1"
-            nameFilter="*"
-            objectClass="org.eclipse.core.resources.IProject"
-            adaptable="true">
-         <menu
-               id="com.android.ide.eclipse.platform.AndroidTools"
-               label="Android Tools"
-               path="additions">
-            <separator name="group1"/>
-         </menu>
-         <visibility>
-            <not>
-            <or>
-            <objectState
-                name="projectNature"
-                value="com.android.ide.eclipse.platform.PlatformNature"/>
-            <objectState
-                name="open"
-                value="false"/>
-            </or>
-            </not>
-         </visibility>
-         <action
-               class="com.android.ide.eclipse.platform.project.ConvertToPlatformAction"
-               enablesFor="1"
-               id="com.android.ide.eclipse.platform.ConvertToPlatformAction"
-               label="Convert To Android Project"
-               menubarPath="com.android.ide.eclipse.platform.AndroidTools/group1"/>
-      </objectContribution>
-    </extension>   
-</plugin>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java
deleted file mode 100644
index 5fa8a29..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/AndroidPlatformPlugin.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2007 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.platform;
-
-import com.android.ddmuilib.StackTracePanel;
-import com.android.ddmuilib.StackTracePanel.ISourceRevealer;
-import com.android.ide.eclipse.common.AndroidConstants;
-import com.android.ide.eclipse.common.project.BaseProjectHelper;
-import com.android.ide.eclipse.ddms.DdmsPlugin;
-import com.android.ide.eclipse.platform.project.PlatformNature;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.Preferences;
-import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
-import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-import java.io.File;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class AndroidPlatformPlugin extends AbstractUIPlugin {
-
-    // The plug-in ID
-    public static final String PLUGIN_ID = "com.android.ide.eclipse.apdt"; //$NON-NLS-1$
-
-    public final static String PREFS_DEVICE_DIRECTORY = PLUGIN_ID + ".deviceDir"; //$NON-NLS-1$
-
-    // The shared instance
-    private static AndroidPlatformPlugin sPlugin;
-
-    private IPreferenceStore mStore;
-    private String mOsDeviceDirectory;
-
-    /**
-     * The constructor
-     */
-    public AndroidPlatformPlugin() {
-        sPlugin = this;
-    }
-    
-    /*
-     * (non-Javadoc)
-     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
-     */
-    @Override
-    public void start(BundleContext context) throws Exception {
-        super.start(context);
-        
-        // get the eclipse store
-        mStore = getPreferenceStore();
-        
-        // set the listener for the preference change
-        Preferences prefs = getPluginPreferences();
-        prefs.addPropertyChangeListener(new IPropertyChangeListener() {
-            public void propertyChange(PropertyChangeEvent event) {
-                // get the name of the property that changed.
-                String property = event.getProperty();
-
-                // if the SDK changed, we update the cached version
-                if (PREFS_DEVICE_DIRECTORY.equals(property)) {
-                    // get the new one from the preferences
-                    mOsDeviceDirectory = (String)event.getNewValue();
-
-                    // make sure it does not ends with a separator
-                    if (mOsDeviceDirectory.endsWith(File.separator)) {
-                        mOsDeviceDirectory = mOsDeviceDirectory.substring(0,
-                                mOsDeviceDirectory.length() - 1);
-                    }
-
-                    // finally restart adb, in case it's a different version
-                    String adbLocation = getOsAdbLocation();
-                    if (adbLocation != null) {
-                        DdmsPlugin.setAdb(adbLocation, true /* startAdb */);
-                    }
-                }
-            }
-        });
-
-
-        mOsDeviceDirectory = mStore.getString(PREFS_DEVICE_DIRECTORY);
-        
-        if (mOsDeviceDirectory.length() == 0) {
-            // get the current Display
-            final Display display = sPlugin.getWorkbench().getDisplay();
-
-            // dialog box only run in ui thread..
-            display.asyncExec(new Runnable() {
-                public void run() {
-                    Shell shell = display.getActiveShell();
-                    MessageDialog.openError(shell, "Android Preferences",
-                            "Location of the device directory is missing.");
-                }
-            });
-        } else {
-            // give the location of adb to ddms
-            String adbLocation = getOsAdbLocation();
-            if (adbLocation != null) {
-                DdmsPlugin.setAdb(adbLocation, true);
-            }
-        }
-        
-        // and give it the debug launcher for android projects
-        DdmsPlugin.setRunningAppDebugLauncher(new DdmsPlugin.IDebugLauncher() {
-            public boolean debug(String packageName, int port) {
-                return false;
-            }
-        });
-        
-        StackTracePanel.setSourceRevealer(new ISourceRevealer() {
-            public void reveal(String applicationName, String className, int line) {
-                IProject project = getDeviceProject();
-                if (project != null) {
-                    BaseProjectHelper.revealSource(project, className, line);
-                }
-            }
-        });
-
-    }
-
-    /*
-     * (non-Javadoc)
-     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
-     */
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        sPlugin = null;
-        super.stop(context);
-    }
-
-    /**
-     * Returns the shared instance
-     *
-     * @return the shared instance
-     */
-    public static AndroidPlatformPlugin getDefault() {
-        return sPlugin;
-    }
-    
-    /**
-     * Returns the Android project. This is the first project which has the PlatformNature.
-     * @return the <code>IProject</code> of the Android project, or <code>null</code> if it was
-     * not found.
-     */
-    public static IProject getDeviceProject() {
-        // Get the list of projects for the current workspace.
-        IWorkspace workspace = ResourcesPlugin.getWorkspace();
-        IProject[] projects = workspace.getRoot().getProjects();
-        
-        for (IProject project : projects) {
-            try {
-                if (project.hasNature(PlatformNature.ID)) {
-                    return project;
-                }
-            } catch (CoreException e) {
-                // Failed to get the nature for this project. Let's just ignore
-                // it and move on to the next one.
-            }
-        }
-        
-        return null;
-    }
-    
-    /**
-     * Returns the OS path of the adb location.
-     * @return the location of adb or null if it cannot be computed.
-     */
-    private String getOsAdbLocation() {
-        if (mOsDeviceDirectory == null || mOsDeviceDirectory.length() == 0) {
-            return null;
-        }
-
-        if (AndroidConstants.CURRENT_PLATFORM == AndroidConstants.PLATFORM_LINUX) {
-            return mOsDeviceDirectory + "/out/host/linux-x86/bin/adb"; //$NON-NLS-1$
-        } else if (AndroidConstants.CURRENT_PLATFORM == AndroidConstants.PLATFORM_DARWIN) {
-            return mOsDeviceDirectory + "/out/host/darwin-x86/bin/adb"; //$NON-NLS-1$
-        }
-        return null;
-    }
-
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java
deleted file mode 100644
index 8427bad..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/preferences/AndroidPreferencePage.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2007 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.platform.preferences;
-
-import com.android.ide.eclipse.platform.AndroidPlatformPlugin;
-
-import org.eclipse.jface.preference.DirectoryFieldEditor;
-import org.eclipse.jface.preference.FieldEditorPreferencePage;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchPreferencePage;
-
-/**
- * This class represents a preference page that is contributed to the
- * Preferences dialog. By subclassing <samp>FieldEditorPreferencePage</samp>,
- * we can use the field support built into JFace that allows us to create a page
- * that is small and knows how to save, restore and apply itself.
- * <p>
- * This page is used to modify preferences only. They are stored in the
- * preference store that belongs to the main plug-in class. That way,
- * preferences can be accessed directly via the preference store.
- */
-public class AndroidPreferencePage extends FieldEditorPreferencePage implements
-        IWorkbenchPreferencePage {
-
-    public AndroidPreferencePage() {
-        super(GRID);
-        setPreferenceStore(AndroidPlatformPlugin.getDefault().getPreferenceStore());
-        setDescription("Android Preferences");
-    }
-
-    /**
-     * Creates the field editors. Field editors are abstractions of the common
-     * GUI blocks needed to manipulate various types of preferences. Each field
-     * editor knows how to save and restore itself.
-     */
-    @Override
-    public void createFieldEditors() {
-        addField(new DirectoryFieldEditor(AndroidPlatformPlugin.PREFS_DEVICE_DIRECTORY,
-                "Location of //device", getFieldEditorParent()));
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
-     */
-    public void init(IWorkbench workbench) {
-    }
-
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java
deleted file mode 100644
index 58d55e5..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/ConvertToPlatformAction.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2008 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.platform.project;
-
-import com.android.ide.eclipse.platform.AndroidPlatformPlugin;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectDescription;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-
-import java.util.Iterator;
-
-/**
- * Converts a project created with the activity creator into an
- * Android project.
- */
-public class ConvertToPlatformAction implements IObjectActionDelegate {
-
-    private ISelection mSelection;
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
-     */
-    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
-        // pass
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see IActionDelegate#run(IAction)
-     */
-    public void run(IAction action) {
-        if (mSelection instanceof IStructuredSelection) {
-            for (Iterator<?> it = ((IStructuredSelection)mSelection).iterator(); it.hasNext();) {
-                Object element = it.next();
-                IProject project = null;
-                if (element instanceof IProject) {
-                    project = (IProject)element;
-                } else if (element instanceof IAdaptable) {
-                    project = (IProject)((IAdaptable)element).getAdapter(IProject.class);
-                }
-                if (project != null) {
-                    convertProject(project);
-                }
-            }
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see IActionDelegate#selectionChanged(IAction, ISelection)
-     */
-    public void selectionChanged(IAction action, ISelection selection) {
-        this.mSelection = selection;
-    }
-
-    /**
-     * Toggles sample nature on a project
-     * 
-     * @param project to have sample nature added or removed
-     */
-    private void convertProject(final IProject project) {
-        new Job("Convert Project") {
-            @Override
-            protected IStatus run(IProgressMonitor monitor) {
-                try {
-                    if (monitor != null) {
-                        monitor.beginTask(String.format(
-                                "Convert %1$s to Android", project.getName()), 5);
-                    }
-
-                    IProjectDescription description = project.getDescription();
-                    String[] natures = description.getNatureIds();
-
-                    // check if the project already has the android nature.
-                    for (int i = 0; i < natures.length; ++i) {
-                        if (PlatformNature.ID.equals(natures[i])) {
-                            // we shouldn't be here as the visibility of the item
-                            // is dependent on the project.
-                            return new Status(Status.WARNING, AndroidPlatformPlugin.PLUGIN_ID,
-                                    "Project is already an Android Platform Project");
-                        }
-                    }
-
-                    // add the platform nature
-                    String[] newNatures = new String[natures.length + 1];
-                    System.arraycopy(natures, 0, newNatures, 1, natures.length);
-                    newNatures[0] = PlatformNature.ID;
-
-                    // set the new nature list in the project
-                    description.setNatureIds(newNatures);
-                    project.setDescription(description, null);
-
-                    IJavaProject javaProject = JavaCore.create(project);
-                    IClasspathEntry[] entries = javaProject.getRawClasspath();
-                    
-                    int n = entries.length;
-                    IClasspathEntry[] newEntries = new IClasspathEntry[n + 1];
-                    System.arraycopy(entries, 0, newEntries, 0, n);
-                    newEntries[n] = PlatformClasspathContainerInitializer.getContainerEntry();
-                    
-                    javaProject.setRawClasspath(newEntries, monitor);
-
-                    return Status.OK_STATUS;
-                } catch (JavaModelException e) {
-                    return e.getJavaModelStatus();
-                } catch (CoreException e) {
-                    return e.getStatus();
-                } finally {
-                    if (monitor != null) {
-                        monitor.done();
-                    }
-                }
-            }
-        }.schedule();
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java
deleted file mode 100644
index a54713c..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformClasspathContainerInitializer.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2008 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.platform.project;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.ClasspathContainerInitializer;
-import org.eclipse.jdt.core.IClasspathContainer;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-
-/**
- * Classpath container initializer responsible for binding {@link PlatformClasspathContainer} to
- * {@link IProject}s. Because any projects with this container force Eclipse to load the
- * plugin, this is a hack to make sure the android platform plugin is launched as soon as an
- * android project is opened.
- */
-public class PlatformClasspathContainerInitializer extends ClasspathContainerInitializer {
-
-    /** The container id for the android framework jar file */
-    private final static String CONTAINER_ID = "com.android.ide.eclipse.platform.DUMMY_CONTAINER"; //$NON-NLS-1$
-
-    public PlatformClasspathContainerInitializer() {
-        // pass
-    }
-
-    /**
-     * Binds a classpath container  to a {@link IClasspathContainer} for a given project,
-     * or silently fails if unable to do so.
-     * @param containerPath the container path that is the container id.
-     * @param the project to bind
-     */
-    @Override
-    public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
-        // pass
-    }
-
-    /**
-     * Creates a new {@link IClasspathEntry} of type {@link IClasspathEntry#CPE_CONTAINER}
-     * linking to the Android Framework.
-     */
-    public static IClasspathEntry getContainerEntry() {
-        return JavaCore.newContainerEntry(new Path(CONTAINER_ID));
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java b/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java
deleted file mode 100644
index 884dc58..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.platform/src/com/android/ide/eclipse/platform/project/PlatformNature.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2008 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.platform.project;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectNature;
-import org.eclipse.core.runtime.CoreException;
-
-/**
- * Project nature for the Android Projects.
- */
-public class PlatformNature implements IProjectNature {
-    
-    public final static String ID = "com.android.ide.eclipse.platform.PlatformNature"; //$NON-NLS-1$
-
-    /** the project this nature object is associated with */
-    private IProject mProject;
-
-    /**
-     * Configures this nature for its project. This is called by the workspace
-     * when natures are added to the project using
-     * <code>IProject.setDescription</code> and should not be called directly
-     * by clients. The nature extension id is added to the list of natures
-     * before this method is called, and need not be added here.
-     *
-     * Exceptions thrown by this method will be propagated back to the caller of
-     * <code>IProject.setDescription</code>, but the nature will remain in
-     * the project description.
-     * 
-     * In this implementation there is nothing to be done, since there's no builder associated
-     * with this nature.
-     *
-     * @see org.eclipse.core.resources.IProjectNature#configure()
-     * @throws CoreException if configuration fails.
-     */
-    public void configure() throws CoreException {
-        // pass
-    }
-
-    /**
-     * De-configures this nature for its project. This is called by the
-     * workspace when natures are removed from the project using
-     * <code>IProject.setDescription</code> and should not be called directly
-     * by clients. The nature extension id is removed from the list of natures
-     * before this method is called, and need not be removed here.
-     *
-     * Exceptions thrown by this method will be propagated back to the caller of
-     * <code>IProject.setDescription</code>, but the nature will still be
-     * removed from the project description.
-     * 
-     * In this implementation there is nothing to be done, since there's no builder associated
-     * with this nature.
-     *
-     * @see org.eclipse.core.resources.IProjectNature#deconfigure()
-     * @throws CoreException if configuration fails.
-     */
-    public void deconfigure() throws CoreException {
-        // pass
-    }
-
-    /**
-     * Returns the project to which this project nature applies.
-     *
-     * @return the project handle
-     * @see org.eclipse.core.resources.IProjectNature#getProject()
-     */
-    public IProject getProject() {
-        return mProject;
-    }
-
-    /**
-     * Sets the project to which this nature applies. Used when instantiating
-     * this project nature runtime. This is called by
-     * <code>IProject.create()</code> or
-     * <code>IProject.setDescription()</code> and should not be called
-     * directly by clients.
-     *
-     * @param project the project to which this nature applies
-     * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
-     */
-    public void setProject(IProject project) {
-        mProject = project;
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
index a121266..266008c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
@@ -2,18 +2,17 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Android Plugin Tests
 Bundle-SymbolicName: com.android.ide.eclipse.tests
-Bundle-Version: 0.8.1.qualifier
+Bundle-Version: 0.9.0.qualifier
 Bundle-Activator: com.android.ide.eclipse.tests.AndroidTestPlugin
 Require-Bundle: org.eclipse.ui,
  org.eclipse.core.runtime,
  org.eclipse.core.resources,
  com.android.ide.eclipse.adt,
  org.junit,
- com.android.ide.eclipse.common,
- com.android.ide.eclipse.editors,
  org.eclipse.jdt.core,
  org.eclipse.jdt.launching,
- org.eclipse.ui.views
+ org.eclipse.ui.views,
+ com.android.ide.eclipse.ddms
 Eclipse-LazyStart: true
 Bundle-Vendor: The Android Open Source Project
 Bundle-ClassPath: kxml2-2.3.0.jar,
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectCreationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectCreationPage.java
similarity index 87%
rename from tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectCreationPage.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectCreationPage.java
index 3202c67..42f8df0 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectCreationPage.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectCreationPage.java
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 20078The Android Open Source Project
+ * Copyright (C) 2008 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
+ *      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
@@ -13,9 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.android.ide.eclipse.adt.project.internal;
-
-import com.android.ide.eclipse.adt.project.internal.NewProjectCreationPage;
+package com.android.ide.eclipse.adt.wizards.newproject;
 
 import java.io.File;
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectWizard.java
similarity index 91%
rename from tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectWizard.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectWizard.java
index 49a853d..40cd636 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/project/internal/StubSampleProjectWizard.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/wizards/newproject/StubSampleProjectWizard.java
@@ -5,7 +5,7 @@
  * 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
+ *      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
@@ -13,10 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.android.ide.eclipse.adt.project.internal;
-
-import com.android.ide.eclipse.adt.project.internal.NewProjectCreationPage;
-import com.android.ide.eclipse.adt.project.internal.NewProjectWizard;
+package com.android.ide.eclipse.adt.wizards.newproject;
 
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.jface.operation.IRunnableWithProgress;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
index 5315db8..98817c6 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
@@ -5,7 +5,7 @@
  * 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
+ *      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
@@ -16,10 +16,9 @@
 package com.android.ide.eclipse.tests.functests.sampleProjects;
 
 import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.project.internal.StubSampleProjectWizard;
+import com.android.ide.eclipse.adt.wizards.newproject.StubSampleProjectWizard;
 import com.android.ide.eclipse.tests.FuncTestCase;
 
-
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResourceChangeEvent;
 import org.eclipse.core.resources.IResourceChangeListener;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/AndroidJarLoaderTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/AndroidJarLoaderTest.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/AndroidJarLoaderTest.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/AndroidJarLoaderTest.java
index 9d89d18..f3d9b79 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/AndroidJarLoaderTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/AndroidJarLoaderTest.java
@@ -14,21 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
 
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
+import com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor;
 import com.android.ide.eclipse.tests.AdtTestData;
 
-import junit.framework.TestCase;
-
-import java.io.File;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 
+import junit.framework.TestCase;
+
 /**
  * Unit Test for {@link FrameworkClassLoader}.
  * 
@@ -51,7 +49,7 @@
 
     /** Preloads classes. They should load just fine. */
     public final void testPreLoadClasses() throws Exception {
-        mFrameworkClassLoader.preLoadClasses("jar.example.", null); //$NON-NLS-1$
+        mFrameworkClassLoader.preLoadClasses("jar.example.", null, null); //$NON-NLS-1$
         HashMap<String, Class<?>> map = getPrivateClassCache();
         assertEquals(0, map.size());
         HashMap<String,byte[]> data = getPrivateEntryCache();
@@ -64,7 +62,7 @@
 
     /** Preloads a class not in the JAR. Preloading does nothing in this case. */
     public final void testPreLoadClasses_classNotFound() throws Exception {
-        mFrameworkClassLoader.preLoadClasses("not.a.package.", null);  //$NON-NLS-1$
+        mFrameworkClassLoader.preLoadClasses("not.a.package.", null, null);  //$NON-NLS-1$
         HashMap<String, Class<?>> map = getPrivateClassCache();
         assertEquals(0, map.size());
         HashMap<String,byte[]> data = getPrivateEntryCache();
@@ -108,7 +106,7 @@
     }
     
     public final void testFindClassesDerivingFrom() throws Exception {
-        HashMap<String, ArrayList<IClass>> found =
+        HashMap<String, ArrayList<IClassDescriptor>> found =
             mFrameworkClassLoader.findClassesDerivingFrom("jar.example.", new String[] {  //$NON-NLS-1$
                 "jar.example.Class1",       //$NON-NLS-1$
                 "jar.example.Class2" });    //$NON-NLS-1$
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/LayoutParamsParserTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/LayoutParamsParserTest.java
similarity index 84%
rename from tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/LayoutParamsParserTest.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/LayoutParamsParserTest.java
index 1a2ff9b..b66fcd6 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/resources/LayoutParamsParserTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/sdk/LayoutParamsParserTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.resources;
+package com.android.ide.eclipse.adt.sdk;
 
-import com.android.ide.eclipse.adt.resources.AndroidJarLoader.ClassWrapper;
-import com.android.ide.eclipse.adt.resources.LayoutParamsParser.IClass;
+import com.android.ide.eclipse.adt.sdk.AndroidJarLoader.ClassWrapper;
+import com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor;
 import com.android.ide.eclipse.common.resources.AttrsXmlParser;
 import com.android.ide.eclipse.common.resources.ViewClassInfo;
 import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -32,7 +32,7 @@
 import junit.framework.TestCase;
 
 /**
- * Test the inner private methods of FrameworkResourceParser.
+ * Test the inner private methods of PlatformDataParser.
  * 
  * Convention: method names that start with an underscore are actually local wrappers
  * that call private methods from {@link FrameworkResourceParser} using reflection.
@@ -47,9 +47,9 @@
         }
         
         @Override
-        public HashMap<String, ArrayList<IClass>> findClassesDerivingFrom(
+        public HashMap<String, ArrayList<IClassDescriptor>> findClassesDerivingFrom(
                 String rootPackage, String[] superClasses) throws ClassFormatError {
-            return new HashMap<String, ArrayList<IClass>>();
+            return new HashMap<String, ArrayList<IClassDescriptor>>();
         }
     }
     
@@ -70,8 +70,8 @@
             mTopGroupClass = new ClassWrapper(mock_android.view.ViewGroup.class);
             mTopLayoutParamsClass = new ClassWrapper(mock_android.view.ViewGroup.LayoutParams.class);
 
-            mViewList = new ArrayList<IClass>();
-            mGroupList = new ArrayList<IClass>();
+            mViewList = new ArrayList<IClassDescriptor>();
+            mGroupList = new ArrayList<IClassDescriptor>();
             mViewMap = new TreeMap<String, ExtViewClassInfo>();
             mGroupMap = new TreeMap<String, ExtViewClassInfo>();
             mLayoutParamsMap = new HashMap<String, LayoutParamsInfo>();
@@ -131,16 +131,16 @@
     //---- access to private methods
     
     /** Calls the private constructor of the parser */
-    private FrameworkResourceParser _Constructor(String osJarPath) throws Exception {
-        Constructor<FrameworkResourceParser> constructor =
-            FrameworkResourceParser.class.getDeclaredConstructor(String.class);
+    private AndroidTargetParser _Constructor(String osJarPath) throws Exception {
+        Constructor<AndroidTargetParser> constructor =
+            AndroidTargetParser.class.getDeclaredConstructor(String.class);
         constructor.setAccessible(true);
         return constructor.newInstance(osJarPath);
     }
     
     /** calls the private getLayoutClasses() of the parser */
     private void _getLayoutClasses() throws Exception {
-        Method method = FrameworkResourceParser.class.getDeclaredMethod("getLayoutClasses");  //$NON-NLS-1$
+        Method method = AndroidTargetParser.class.getDeclaredMethod("getLayoutClasses");  //$NON-NLS-1$
         method.setAccessible(true);
         method.invoke(mParser);
     }
@@ -148,7 +148,7 @@
     /** calls the private addGroup() of the parser */
     private ViewClassInfo _addGroup(Class<?> groupClass) throws Exception {
         Method method = LayoutParamsParser.class.getDeclaredMethod("addGroup",  //$NON-NLS-1$
-                IClass.class);
+                IClassDescriptor.class);
         method.setAccessible(true);
         return (ViewClassInfo) method.invoke(mParser, new ClassWrapper(groupClass));
     }
@@ -156,7 +156,7 @@
     /** calls the private addLayoutParams() of the parser */
     private LayoutParamsInfo _addLayoutParams(Class<?> groupClass) throws Exception {
         Method method = LayoutParamsParser.class.getDeclaredMethod("addLayoutParams",   //$NON-NLS-1$
-                IClass.class);
+                IClassDescriptor.class);
         method.setAccessible(true);
         return (LayoutParamsInfo) method.invoke(mParser, new ClassWrapper(groupClass));
     }
@@ -164,17 +164,17 @@
     /** calls the private getLayoutParamsInfo() of the parser */
     private LayoutParamsInfo _getLayoutParamsInfo(Class<?> layoutParamsClass) throws Exception {
         Method method = LayoutParamsParser.class.getDeclaredMethod("getLayoutParamsInfo",   //$NON-NLS-1$
-                IClass.class);
+                IClassDescriptor.class);
         method.setAccessible(true);
         return (LayoutParamsInfo) method.invoke(mParser, new ClassWrapper(layoutParamsClass));
     }
     
     /** calls the private findLayoutParams() of the parser */
-    private IClass _findLayoutParams(Class<?> groupClass) throws Exception {
+    private IClassDescriptor _findLayoutParams(Class<?> groupClass) throws Exception {
         Method method = LayoutParamsParser.class.getDeclaredMethod("findLayoutParams",  //$NON-NLS-1$
-                IClass.class);
+                IClassDescriptor.class);
         method.setAccessible(true);
-        return (IClass) method.invoke(mParser, new ClassWrapper(groupClass));
+        return (IClassDescriptor) method.invoke(mParser, new ClassWrapper(groupClass));
     }
 
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java
index 521bb62..1427eee 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/layout/UiElementPullParserTest.java
@@ -216,9 +216,6 @@
         } catch (XmlPullParserException e) {
             e.printStackTrace();
             assertTrue(false);
-        } catch (IOException e) {
-            e.printStackTrace();
-            assertTrue(false);
         }
     }
 
diff --git a/tools/eclipse/doBuild.sh b/tools/eclipse/scripts/build_plugins.sh
similarity index 83%
rename from tools/eclipse/doBuild.sh
rename to tools/eclipse/scripts/build_plugins.sh
index a0d8606..5f94ca0 100755
--- a/tools/eclipse/doBuild.sh
+++ b/tools/eclipse/scripts/build_plugins.sh
@@ -2,7 +2,7 @@
 
 # build script for eclipse adt build on linux platform
 #
-# Usage: doBuild <build_version> 
+# Usage: development/tools/eclipse/scripts/build_plugins <build_version> 
 #
 # It expects environment variable ECLIPSE_HOME to be defined to point to _your_
 # version of Eclipse RCP (must have the WTP & GEF plugins available too.)
@@ -59,8 +59,10 @@
 HOST=`uname`
 [ "$HOST" == "Linux" ] || die "ERROR: This script is currently only supported on Linux platform"
 
-# Check which directory this is invoked from
-[ "${PWD: -13}" == "tools/eclipse" ] || dieWithUsage "Please run this script from the device/tools/eclipse directory"
+# Make sure this runs from the tools/eclipse plugin.
+D=`dirname "$0"`
+cd "$D/.."
+[ `basename "$PWD"` == "eclipse" ] || dieWithUsage "Please run this script from the device/tools/eclipse directory"
 
 # check for number of parameters
 [ $# -lt 1 ] && dieWithUsage "ERROR: Not enough parameters"
@@ -86,6 +88,8 @@
   [ -f "$PID_FILE" ] && ECLIPSE_PID=`cat "$PID_FILE"`
 fi
 
+echo "PWD=`pwd`"
+echo "ECLIPSE_HOME=$ECLIPSE_HOME"
 
 #
 # -- Site parameters and Build version --
@@ -124,7 +128,7 @@
 # The "configuration directory" will hold the workspace for this build.
 # If it contains old data the build may fail so we need to clean it first
 # and create it if it doesn't exist.
-CONFIG_DIR="../../out/eclipse-configuration-$BUILD_VERSION"
+CONFIG_DIR="../../../out/eclipse-configuration-$BUILD_VERSION"
 [ -d "$CONFIG_DIR" ] && rm -rfv "$CONFIG_DIR"
 mkdir -p "$CONFIG_DIR"
 
@@ -173,8 +177,18 @@
 echo "  Build Config: $BUILDCONFIG"
 echo "  Config Dir:   $CONFIG_DIR"
 
+# clean input directories to make sure there's nothing left from previous run
+
+rm -fv *.properties *.xml
+find . -name "@*" | xargs rm -rfv
+
+# Now execute the ant runner
+
+set +e  # don't stop on errors anymore, we want to catch there here
+
 java \
   -jar $LAUNCHER \
+  -data "$CONFIG_DIR" \
   -configuration "$CONFIG_DIR" \
   -application org.eclipse.ant.core.antRunner \
   -buildfile $BUILDFILE \
@@ -183,6 +197,21 @@
   -DforceContextQualifier=$BUILD_VERSION \
   -DECLIPSE_HOME=$ECLIPSE_HOME \
   $SITE_PARAM
+RESULT=$?
+
+if [ "0" != "$RESULT" ]; then
+    echo "JAVA died with error code $RESULT"
+    echo "Dump of build config logs:"
+    for i in "$CONFIG_DIR"/*.log; do
+        if [ -f "$i" ]; then
+            echo "----------------------"
+            echo "--- $i"
+            echo "----------------------"
+            cat "$i"
+            echo
+        fi
+    done
+fi
 
 #
 # -- Cleanup
diff --git a/tools/eclipse/scripts/build_server.sh b/tools/eclipse/scripts/build_server.sh
index e30dbb8..39c8dcd 100755
--- a/tools/eclipse/scripts/build_server.sh
+++ b/tools/eclipse/scripts/build_server.sh
@@ -46,9 +46,10 @@
 }
 
 function check_params() {
-  # This needs to run from //device
-  [ `basename "$PWD"` == "device" ] || \
-    die "Please execute $0 from the //device directory, not $PWD"
+  # This needs to run from the top android directory
+  # Automatically CD to the top android directory, whatever its name
+  D=`dirname "$0"`
+  cd "$D/../../../../" && echo "Switched to directory $PWD"
 
   # The current Eclipse build has some Linux dependency in its config files
   [ `uname` == "Linux" ] || die "This must run from a Linux box."
@@ -60,14 +61,12 @@
 
 function build_libs() {
   MAKE_OPT="-j8"
-  echo "*** Building: make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api"
-  make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api layoutlib_utils
+  echo "*** Building: make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api ninepatch sdklib sdkuilib"
+  make $MAKE_OPT dx ping ddms jarutils androidprefs layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib
 }
 
 function build_plugin {
-  cd tools/eclipse/scripts
-  ./create_all_symlinks.sh
-  cd .. # cd back to tools/eclipse
+  development/tools/eclipse/scripts/create_all_symlinks.sh
 
   # Qualifier is "v" followed by date/time in YYYYMMDDHHSS format and the optional
   # build number.
@@ -90,7 +89,7 @@
   [ -d "$DEST_DIR/$BUILD_PREFIX" ] || rm -rfv "$DEST_DIR/$BUILD_PREFIX"
 
   # Perform the Eclipse build and move the result in $DEST_DIR/android-build
-  ./doBuild.sh $QUALIFIER $INTERNAL_BUILD -d "$DEST_DIR" -a "$BUILD_PREFIX"
+  development/tools/eclipse/scripts/build_plugins.sh $QUALIFIER $INTERNAL_BUILD -d "$DEST_DIR" -a "$BUILD_PREFIX"
 
   # Cleanup
   [ -d "$QUALIFIER" ] && rm -rfv "$QUALIFIER"
diff --git a/tools/eclipse/scripts/create_adt_symlinks.sh b/tools/eclipse/scripts/create_adt_symlinks.sh
index 4974432..557c4d9 100755
--- a/tools/eclipse/scripts/create_adt_symlinks.sh
+++ b/tools/eclipse/scripts/create_adt_symlinks.sh
@@ -1,42 +1,50 @@
 #!/bin/bash
 function die() {
-  echo "Error: $*"
-  exit 1
+    echo "Error: $*"
+    exit 1
 }
 
 set -e # fail early
 
-# This may run either from the //device directory or from the
-# eclipse/script directory. Allow for both.
-D="device/tools/eclipse/scripts"
-[ -d "$D" ] && cd "$D"
-[ -d "../$D" ] && cd "../$D"
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
 
-cd ../plugins/com.android.ide.eclipse.adt
+DEST="development/tools/eclipse/plugins/com.android.ide.eclipse.adt"
+# computes "../.." from DEST to here (in /android)
+BACK=`echo $DEST | sed 's@[^/]*@..@g'`
+
+LIBS="sdkstats jarutils androidprefs layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib"
+
+echo "make java libs ..."
+make -j3 showcommands $LIBS || die "ADT: Fail to build one of $LIBS."
+
+echo "Copying java libs to $DEST"
+
 HOST=`uname`
 if [ "$HOST" == "Linux" ]; then
-  ln -svf ../../../../out/host/linux-x86/framework/jarutils.jar .
-  ln -svf ../../../../out/host/linux-x86/framework/androidprefs.jar .
+    for LIB in $LIBS; do
+        ln -svf $BACK/out/host/linux-x86/framework/$LIB.jar "$DEST/"
+    done
+    ln -svf $BACK/out/host/linux-x86/framework/kxml2-2.3.0.jar "$DEST/"
+  
 elif [ "$HOST" == "Darwin" ]; then
-  ln -svf ../../../../out/host/darwin-x86/framework/jarutils.jar .
-  ln -svf ../../../../out/host/darwin-x86/framework/androidprefs.jar .
+    for LIB in $LIBS; do
+        ln -svf $BACK/out/host/darwin-x86/framework/$LIB.jar "$DEST/"
+    done
+    ln -svf $BACK/out/host/darwin-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
 elif [ "${HOST:0:6}" == "CYGWIN" ]; then
+    for LIB in $LIBS; do
+        cp -vf  out/host/windows-x86/framework/$LIB.jar "$DEST/"
+    done
 
-  DEVICE_DIR="../../../.."
-  echo "make java libs ..."
-  ( cd "$DEVICE_DIR" &&
-      make -j3 showcommands jarutils androidprefs ) || \
-      die "Define javac and retry."
+    if [ ! -f "$DEST/kxml2-2.3.0.jar" ]; then
+        cp -v "prebuilt/common/kxml2/kxml2-2.3.0.jar" "$DEST/"
+    fi
 
-  for DIR in "$PWD" ; do
-      echo "Copying java libs to $DIR"
-      for JAR in jarutils.jar androidprefs.jar ; do
-          cp -vf  "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" "$DIR"
-      done
-  done
-
-  chmod a+rx *.jar
+    chmod -v a+rx "$DEST"/*.jar
 else
-  echo "Unsupported platform ($HOST). Nothing done."
+    echo "Unsupported platform ($HOST). Nothing done."
 fi
 
diff --git a/tools/eclipse/scripts/create_all_symlinks.sh b/tools/eclipse/scripts/create_all_symlinks.sh
index fc9766f..8508343 100755
--- a/tools/eclipse/scripts/create_all_symlinks.sh
+++ b/tools/eclipse/scripts/create_all_symlinks.sh
@@ -3,30 +3,25 @@
 echo "### $0 executing"
 
 function die() {
-  echo "Error: $*"
-  exit 1
+    echo "Error: $*"
+    exit 1
 }
 
-D="device/tools/eclipse/scripts"
-if [ -d "../$D" ]; then
-    cd "../$D"
-else
-  [ "${PWD: -28}" == "$D" ] || die "Please execute this from the $D directory"
-fi
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
+
+DEST="development/tools/eclipse/scripts"
 
 set -e # fail early
 
 echo ; echo "### ADT ###" ; echo
-./create_adt_symlinks.sh "$*"
-echo ; echo "### COMMON ###" ; echo
-./create_common_symlinks.sh "$*"
-echo ; echo "### EDITORS ###" ; echo
-./create_editors_symlinks.sh "$*"
+$DEST/create_adt_symlinks.sh "$*"
 echo ; echo "### DDMS ###" ; echo
-./create_ddms_symlinks.sh "$*"
+$DEST/create_ddms_symlinks.sh "$*"
 echo ; echo "### TEST ###" ; echo
-./create_test_symlinks.sh "$*"
+$DEST/create_test_symlinks.sh "$*"
 echo ; echo "### BRIDGE ###" ; echo
-./create_bridge_symlinks.sh "$*"
+$DEST/create_bridge_symlinks.sh "$*"
 
 echo "### $0 done"
diff --git a/tools/eclipse/scripts/create_bridge_symlinks.sh b/tools/eclipse/scripts/create_bridge_symlinks.sh
index f01a89e..605ef63 100755
--- a/tools/eclipse/scripts/create_bridge_symlinks.sh
+++ b/tools/eclipse/scripts/create_bridge_symlinks.sh
@@ -1,47 +1,38 @@
 #!/bin/bash
 function die() {
-  echo "Error: $*"
-  exit 1
+    echo "Error: $*"
+    exit 1
 }
 
 set -e # fail early
 
-# This may run either from the //device directory or from the
-# eclipse/script directory. Allow for both.
-D="device/tools/eclipse/scripts"
-[ -d "$D" ] && cd "$D"
-[ -d "../$D" ] && cd "../$D"
-
-cd ../../layoutlib
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
 
 HOST=`uname`
 if [ "$HOST" == "Linux" ]; then
-  echo # nothing to do
+    echo # nothing to do
+
 elif [ "$HOST" == "Darwin" ]; then
-  echo # nothing to do
+    echo # nothing to do
+
 elif [ "${HOST:0:6}" == "CYGWIN" ]; then
-  if [ "x$1" == "x" ]; then
-    echo "Usage: $0 sdk/tools/lib/"
-    echo "Argument 1 should be the path to the jars you want to copy. "
-    echo "  e.g. android_sdk_windows_NNN/tools/lib/ "
-    echo "This will be used to update layout.lib after it has been built here."
-    exit 1
-  fi
+    if [ "x$1" == "x" ] || [ `basename "$1"` != "layoutlib.jar" ]; then
+        echo "Usage: $0 sdk/platforms/xxx/data/layoutlib.jar"
+        echo "Argument 1 should be the path to the layoutlib.jar that should be updated."
+        exit 1
+    fi
 
-  DEVICE_DIR="../../"
-  echo "make java libs ..."
-  ( cd "$DEVICE_DIR" &&
-      make -j3 showcommands layoutlib ninepatch ) || \
-      die "Define javac and retry."
+    LIBS="layoutlib ninepatch"
+    echo "Make java libs: $LIBS"
+    make -j3 showcommands $LIBS || die "Bridge: Failed to build one of $LIBS."
 
-  for DIR in "$PWD" "$1" ; do
-      echo "Copying java libs to $DIR"
-      for JAR in ninepatch.jar layoutlib.jar ; do
-          cp -vf  "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" "$DIR"
-      done
-  done
+    echo "Updating your SDK in $1"
+    cp -vf  "out/host/windows-x86/framework/layoutlib.jar" "$1"
+    chmod -v a+rx "$1"
 
 else
-  echo "Unsupported platform ($HOST). Nothing done."
+    echo "Unsupported platform ($HOST). Nothing done."
 fi
 
diff --git a/tools/eclipse/scripts/create_common_symlinks.sh b/tools/eclipse/scripts/create_common_symlinks.sh
deleted file mode 100755
index 7726afc..0000000
--- a/tools/eclipse/scripts/create_common_symlinks.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-function die() {
-  echo "Error: $*"
-  exit 1
-}
-
-set -e # fail early
-
-# This may run either from the //device directory or from the
-# eclipse/script directory. Allow for both.
-D="device/tools/eclipse/scripts"
-[ -d "$D" ] && cd "$D"
-[ -d "../$D" ] && cd "../$D"
-
-cd ../plugins/com.android.ide.eclipse.common
-HOST=`uname`
-if [ "$HOST" == "Linux" ]; then
-  ln -svf ../../../../out/host/linux-x86/framework/sdkstats.jar .
-  ln -svf ../../../../out/host/linux-x86/framework/androidprefs.jar .
-elif [ "$HOST" == "Darwin" ]; then
-  ln -svf ../../../../out/host/darwin-x86/framework/sdkstats.jar .
-  ln -svf ../../../../out/host/darwin-x86/framework/androidprefs.jar .
-elif [ "${HOST:0:6}" == "CYGWIN" ]; then
-
-  DEVICE_DIR="../../../.."
-  echo "make java libs ..."
-  ( cd "$DEVICE_DIR" &&
-      make -j3 sdkstats androidprefs ) || \
-      die "Define javac and retry."
-
-  for DIR in "$PWD" ; do
-      echo "Copying java libs to $DIR"
-      for JAR in sdkstats.jar androidprefs.jar ; do
-          cp -vf  "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" "$DIR"
-          chmod a+rx "$DIR/$JAR"
-      done
-  done
-
-else
-  echo "Unsupported platform ($HOST). Nothing done."
-fi
-
diff --git a/tools/eclipse/scripts/create_ddms_symlinks.sh b/tools/eclipse/scripts/create_ddms_symlinks.sh
index 5b2e45b..276cf9b 100755
--- a/tools/eclipse/scripts/create_ddms_symlinks.sh
+++ b/tools/eclipse/scripts/create_ddms_symlinks.sh
@@ -4,58 +4,76 @@
 # Run this from device/tools/eclipse/scripts
 #----------------------------------------------------------------------------|
 
-CMD="ln -svf"
-DIR="ln -svf"
+set -e
+
 HOST=`uname`
 if [ "${HOST:0:6}" == "CYGWIN" ]; then
-  CMD="cp -rvf"
-  DIR="rsync -avW --delete-after"
+    # We can't use symlinks under Cygwin
+
+    function cpfile { # $1=dest $2=source
+        cp -fv $2 $1/
+    }
+
+    function cpdir() { # $1=dest $2=source
+        rsync -avW --delete-after $2 $1
+    }
+
+else
+    # For all other systems which support symlinks
+
+    # computes the "reverse" path, e.g. "a/b/c" => "../../.."
+    function back() {
+        echo $1 | sed 's@[^/]*@..@g'
+    }
+
+    function cpfile { # $1=dest $2=source
+        ln -svf `back $1`/$2 $1/
+    }
+
+    function cpdir() { # $1=dest $2=source
+        ln -svf `back $1`/$2 $1
+    }
 fi
 
-cd ../plugins/com.android.ide.eclipse.ddms
-mkdir -p libs
-cd libs
-$CMD ../../../../../prebuilt/common/jfreechart/jcommon-1.0.12.jar .
-$CMD ../../../../../prebuilt/common/jfreechart/jfreechart-1.0.9.jar .
-$CMD ../../../../../prebuilt/common/jfreechart/jfreechart-1.0.9-swt.jar .
-
-cd ../src/com/android
-$DIR ../../../../../../ddms/libs/ddmlib/src/com/android/ddmlib .
-$DIR ../../../../../../ddms/libs/ddmuilib/src/com/android/ddmuilib .
-
-# goes back to the icons directory
-cd ../../../icons/
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/debug-attach.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/debug-wait.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/debug-error.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/device.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/emulator.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/heap.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/thread.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/empty.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/warning.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/d.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/e.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/i.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/v.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/w.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/add.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/delete.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/edit.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/save.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/push.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/pull.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/clear.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/up.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/down.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/gc.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/halt.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/load.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/importBug.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/play.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/pause.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/forward.png .
-$CMD ../../../../ddms/libs/ddmuilib/src/resources/images/backward.png .
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
 
 
+BASE="development/tools/eclipse/plugins/com.android.ide.eclipse.ddms"
+
+DEST=$BASE/libs
+mkdir -p $DEST
+for i in prebuilt/common/jfreechart/*.jar; do
+  cpfile $DEST $i
+done
+
+DEST=$BASE/src/com/android
+mkdir -p $DEST
+for i in development/tools/ddms/libs/ddmlib/src/com/android/ddmlib \
+         development/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib ; do
+  cpdir $DEST $i
+done
+
+DEST=$BASE/icons
+mkdir -p $DEST
+for i in \
+    add.png \
+    backward.png \
+    clear.png \
+    d.png debug-attach.png debug-error.png debug-wait.png delete.png device.png down.png \
+    e.png edit.png empty.png emulator.png \
+    forward.png \
+    gc.png \
+    heap.png halt.png \
+    i.png importBug.png \
+    load.png \
+    pause.png play.png pull.png push.png \
+    save.png \
+    thread.png \
+    up.png \
+    v.png \
+    w.png warning.png ; do
+  cpfile $DEST development/tools/ddms/libs/ddmuilib/src/resources/images/$i
+done
 
diff --git a/tools/eclipse/scripts/create_editors_symlinks.sh b/tools/eclipse/scripts/create_editors_symlinks.sh
deleted file mode 100755
index 2f26ac4..0000000
--- a/tools/eclipse/scripts/create_editors_symlinks.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-function die() {
-  echo "Error: $*"
-  exit 1
-}
-
-cd ../plugins/com.android.ide.eclipse.editors
-HOST=`uname`
-if [ "$HOST" == "Linux" ]; then
-  ln -svf ../../../../out/host/linux-x86/framework/layoutlib_api.jar .
-  ln -svf ../../../../out/host/linux-x86/framework/layoutlib_utils.jar .
-  ln -svf ../../../../out/host/linux-x86/framework/kxml2-2.3.0.jar .
-  ln -svf ../../../../out/host/linux-x86/framework/ninepatch.jar .
-elif [ "$HOST" == "Darwin" ]; then
-  ln -svf ../../../../out/host/darwin-x86/framework/layoutlib_api.jar .
-  ln -svf ../../../../out/host/darwin-x86/framework/layoutlib_utils.jar .
-  ln -svf ../../../../out/host/darwin-x86/framework/kxml2-2.3.0.jar .
-  ln -svf ../../../../out/host/darwin-x86/framework/ninepatch.jar .
-elif [ "${HOST:0:6}" == "CYGWIN" ]; then
-  set -e # fail early
-  DEVICE_DIR="../../../../"
-  echo "make java libs ..."
-  ( cd "$DEVICE_DIR" &&
-      make -j3 showcommands layoutlib_api layoutlib_utils ninepatch ) || \
-      die "Define javac and 'make layoutlib_api ninepatch' from device."
-
-  echo "Copying java libs to $PWD"
-  for JAR in layoutlib_api.jar layoutlib_utils.jar ninepatch.jar ; do
-    cp -vf  "$DEVICE_DIR/out/host/windows-x86/framework/$JAR" .
-  done
-  if [ ! -f "./kxml2-2.3.0.jar" ]; then
-      cp -v $DEVICE_DIR/prebuilt/common/kxml2/kxml2-2.3.0.jar .
-      chmod -v a+rx *.jar
-  fi
-
-else
-  echo "Unsupported platform ($HOST). Nothing done."
-fi
-
diff --git a/tools/eclipse/scripts/create_test_symlinks.sh b/tools/eclipse/scripts/create_test_symlinks.sh
index 110539a..1479e04 100755
--- a/tools/eclipse/scripts/create_test_symlinks.sh
+++ b/tools/eclipse/scripts/create_test_symlinks.sh
@@ -1,24 +1,48 @@
 #!/bin/bash
-cd ../plugins/com.android.ide.eclipse.tests
+
+set -e
+
+# CD to the top android directory
+D=`dirname "$0"`
+cd "$D/../../../../"
+
+# computes relative ".." paths from $1 to here (in /android)
+function back() {
+  echo $1 | sed 's@[^/]*@..@g'
+}
+
+BASE="development/tools/eclipse/plugins/com.android.ide.eclipse.tests"
+DEST=$BASE
+BACK=`back $DEST`
+
+
 HOST=`uname`
 if [ "$HOST" == "Linux" ]; then
-  ln -svf ../../../../out/host/linux-x86/framework/kxml2-2.3.0.jar .
+    DIR="ln -svf"
+    ln -svf $BACK/out/host/linux-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
 elif [ "$HOST" == "Darwin" ]; then
-  ln -svf ../../../../out/host/darwin-x86/framework/kxml2-2.3.0.jar .
+    DIR="ln -svf"
+    ln -svf $BACK/out/host/darwin-x86/framework/kxml2-2.3.0.jar "$DEST/"
+
 elif [ "${HOST:0:6}" == "CYGWIN" ]; then
-  if [ "x$1" == "x" ]; then
-    echo "Usage: $0 <path to jars>"
-    echo "Argument 1 should be the path to the jars you want to copy. "
-    echo "  e.g. android_sdk_windows_NNN/tools/lib/ "
-    echo "(since you can't rebuild them under Windows, you need prebuilt ones "
-    echo " from an SDK drop or a Linux/Mac)"
-    exit 1
-  fi
-  if [ ! -f "kxml2-2.3.0.jar" ]; then
-    wget -O "kxml2-2.3.0.jar" "http://internap.dl.sourceforge.net/sourceforge/kxml/kxml2-2.3.0.jar"
-    chmod a+rx *.jar
-  fi
+    DIR="rsync -avW --delete-after"
+    JAR="kxml2-2.3.0.jar"
+    if [ ! -f "$DEST/$JAR" ]; then
+        # Get the jar from ADT if we can, otherwise download it.
+        if [ -f "$DEST/../com.android.ide.eclipse.adt/$JAR" ]; then
+            cp "$DEST/../com.android.ide.eclipse.adt/$JAR" "$DEST/$JAR"
+        else
+            wget -O "$DEST/$JAR" "http://internap.dl.sourceforge.net/sourceforge/kxml/$JAR"
+        fi
+        chmod a+rx "$DEST/$JAR"
+    fi
 else
-  echo "Unsupported platform ($HOST). Nothing done."
+    echo "Unsupported platform ($HOST). Nothing done."
 fi
 
+# create link to ddmlib tests
+DEST=$BASE/unittests/com/android
+BACK=`back $DEST`
+$DIR $BACK/development/tools/ddms/libs/ddmlib/tests/src/com/android/ddmlib $DEST/
+
diff --git a/tools/eclipse/scripts/update_version.sh b/tools/eclipse/scripts/update_version.sh
new file mode 100644
index 0000000..a288965
--- /dev/null
+++ b/tools/eclipse/scripts/update_version.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+OLD="$1"
+NEW="$2"
+
+# sanity check in input args
+if [ -z "$OLD" ] || [ -z "$NEW" ]; then
+    cat <<EOF
+Usage: $0 <old> <new>
+Changes the ADT plugin revision number.
+Example:
+  cd tools/eclipse
+  scripts/update_version.sh 0.1.2 0.2.3
+EOF
+    exit 1
+fi
+
+# sanity check on current dir
+if [ `basename "$PWD"` != "eclipse" ]; then
+    echo "Please run this from tools/eclipse."
+    exit 1
+fi
+
+# quote dots for regexps
+OLD="${OLD//./\.}"
+NEW="${NEW//./\.}"
+
+# Find all the files with the old pattern, except changes.txt and
+# p4 edit them. Skip that if there's no p4 in path.
+if which g4 1>/dev/null 2>/dev/null ; then
+    grep -rl "$OLD" * | grep -E "\.xml$|\.MF$" | xargs -n 5 g4 edit
+fi
+
+# Now find the same files but this time use sed to replace in-place with
+# the new pattern. Old files get backuped with the .old extension.
+grep -rl "$OLD" * | grep -E "\.xml$|\.MF$" | xargs -n 1 sed -i.old "s/$OLD/$NEW/g"
+
diff --git a/tools/eclipse/sites/external/site.xml b/tools/eclipse/sites/external/site.xml
index be123f6..e98a988 100644
--- a/tools/eclipse/sites/external/site.xml
+++ b/tools/eclipse/sites/external/site.xml
@@ -3,10 +3,7 @@
    <description url="https://dl-ssl.google.com/android/eclipse/">
       Update Site for Android Development Toolkit
    </description>
-   <feature url="features/com.android.ide.eclipse.adt_0.8.1.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.8.1.qualifier">
-      <category name="developer"/>
-   </feature>
-   <feature url="features/com.android.ide.eclipse.editors_0.8.1.qualifier.jar" id="com.android.ide.eclipse.editors" version="0.8.1.qualifier">
+   <feature url="features/com.android.ide.eclipse.adt_0.9.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.9.0.qualifier">
       <category name="developer"/>
    </feature>
    <category-def name="developer" label="Developer Tools">
diff --git a/tools/eclipse/sites/internal/site.xml b/tools/eclipse/sites/internal/site.xml
index 3263886..a7ef628 100644
--- a/tools/eclipse/sites/internal/site.xml
+++ b/tools/eclipse/sites/internal/site.xml
@@ -3,17 +3,10 @@
    <description url="https://android.corp.google.com/adt/">
       Update Site for Android Development Toolkit
    </description>
-   <feature url="features/com.android.ide.eclipse.adt_0.8.1.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.8.1.qualifier">
+   <feature url="features/com.android.ide.eclipse.adt_0.9.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="0.9.0.qualifier">
       <category name="developer"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.editors_0.8.1.qualifier.jar" id="com.android.ide.eclipse.editors" version="0.8.1.qualifier">
-      <category name="developer"/>
-      <category name="platform"/>
-   </feature>
-   <feature url="features/com.android.ide.eclipse.platform_0.8.1.qualifier.jar" id="com.android.ide.eclipse.platform" version="0.8.1.qualifier">
-      <category name="platform"/>
-   </feature>
-   <feature url="features/com.android.ide.eclipse.tests_0.8.1.qualifier.jar" id="com.android.ide.eclipse.tests" version="0.8.1.qualifier">
+   <feature url="features/com.android.ide.eclipse.tests_0.9.0.qualifier.jar" id="com.android.ide.eclipse.tests" version="0.9.0.qualifier">
       <category name="test"/>
    </feature>
    <category-def name="developer" label="Application Developer Tools">
@@ -21,11 +14,6 @@
          Features that add Android support to Eclipse for application developers.
       </description>
    </category-def>
-   <category-def name="platform" label="Platform Developer Tools">
-      <description>
-         Features that add Android support to Eclipse for platform developers.
-      </description>
-   </category-def>
    <category-def name="test" label="Plugin Developer Tests">
       <description>
          Tests for the other Android plugins