Allow project templates to be bundled separately
This changeset moves the various FreeMarker templates out of the ADT
plugin and over into the tools install area. The code to instantiate
templates is simplified a bit now that it no longer needs to both
handle files on disk and files read out of the .jar.
There's a new first page to the various template wizards which is
shown if the tools are not up to date (specifically, if the
$SDK/tools/templates/ directory does not exist). This page explains
that the tools have to be updated, and the Next button is disabled
until they are up to date.
This CL also contains some other tweaks suggested by Roman to the
activity-to-layout name mapping and misc code changes.
Change-Id: I3bc65f54a6b79bbeedfb917a9d34ec0d312f3526
diff --git a/build/tools.atree b/build/tools.atree
index 16fdaf5..d5d6c08 100644
--- a/build/tools.atree
+++ b/build/tools.atree
@@ -146,6 +146,13 @@
prebuilts/tools/common/proguard/proguard4.7/bin/retrace.sh tools/proguard/bin/retrace.sh
prebuilts/tools/common/proguard/proguard4.7/src/proguard/ant/task.properties tools/proguard/ant/task.properties
+# Templates
+sdk/templates/projects/NewAndroidApplication tools/templates/projects/NewAndroidApplication
+sdk/templates/activities/BlankActivity tools/templates/activities/BlankActivity
+sdk/templates/activities/MasterDetailFlow tools/templates/activities/MasterDetailFlow
+sdk/templates/other/CustomView tools/templates/other/CustomView
+sdk/templates/resources tools/templates/resources
+
# SDK Controller
sdk/apps/SdkController tools/apps/SdkController
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
index 493f996..b0ae35e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
@@ -1510,6 +1510,9 @@
return null;
}
+ if (mConfigComposite.isDisposed()) {
+ return null;
+ }
assert mConfigComposite.getDisplay().getThread() == Thread.currentThread();
// attempt to get a target from the configuration selector.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java
index 9a61b4f..d9f650c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java
@@ -15,12 +15,12 @@
*/
package com.android.ide.eclipse.adt.internal.wizards.templates;
-import static com.android.ide.eclipse.adt.internal.wizards.templates.NewTemplateWizard.ACTIVITY_TEMPLATES;
import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_PADDING;
import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_WIDTH;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageControl;
+import com.google.common.io.Files;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
@@ -39,12 +39,16 @@
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
-import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
class ActivityPage extends WizardPage implements SelectionListener {
private final NewProjectWizardState mValues;
private List mList;
private Button mCreateToggle;
+ private java.util.List<File> mTemplates;
private boolean mIgnore;
private boolean mShown;
@@ -64,11 +68,15 @@
setDescription("Select whether to create an activity, and if so, what kind of activity.");
}
- @SuppressWarnings("unused") // SWT constructors have side effects and aren't unused
@Override
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NULL);
setControl(container);
+ }
+
+ @SuppressWarnings("unused") // SWT constructors have side effects and aren't unused
+ private void onEnter() {
+ Composite container = (Composite) getControl();
container.setLayout(new GridLayout(3, false));
mCreateToggle = new Button(container, SWT.CHECK);
@@ -79,20 +87,29 @@
mList = new List(container, SWT.BORDER | SWT.V_SCROLL);
mList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
- mList.setItems(ACTIVITY_TEMPLATES);
+
+
+ mTemplates = TemplateHandler.getTemplates("activities");
+ java.util.List<String> names = new ArrayList<String>(mTemplates.size());
+ File current = mValues.activityValues.getTemplateLocation();
int index = -1;
- for (int i = 0; i < ACTIVITY_TEMPLATES.length; i++) {
- if (ACTIVITY_TEMPLATES[i].equals(mValues.activityValues.getTemplateName())) {
+ for (int i = 0, n = mTemplates.size(); i < n; i++) {
+ File template = mTemplates.get(i);
+ names.add(template.getName());
+ if (template.equals(current)) {
index = i;
- break;
}
}
- if (index == -1) {
- mValues.activityValues.setTemplateName(ACTIVITY_TEMPLATES[0]);
+ String[] items = names.toArray(new String[names.size()]);
+ mList.setItems(items);
+ if (index == -1 && !mTemplates.isEmpty()) {
+ mValues.activityValues.setTemplateLocation(mTemplates.get(0));
index = 0;
}
- mList.setSelection(index);
- mList.addSelectionListener(this);
+ if (index >= 0) {
+ mList.setSelection(index);
+ mList.addSelectionListener(this);
+ }
// Preview
mPreview = new ImageControl(container, SWT.NONE, null);
@@ -113,26 +130,29 @@
mHeading.setFont(font);
}
- setPreview(mValues.activityValues.getTemplateName());
+ updatePreview();
}
- private void setPreview(String templateName) {
+ private void updatePreview() {
Image oldImage = mPreviewImage;
mPreviewImage = null;
String title = "";
String description = "";
- TemplateMetadata template = TemplateHandler.getTemplate(templateName);
+ TemplateHandler handler = mValues.activityValues.getTemplateHandler();
+ TemplateMetadata template = handler.getTemplate();
if (template != null) {
String thumb = template.getThumbnailPath();
if (thumb != null && !thumb.isEmpty()) {
- String filePath = TemplateHandler.getTemplatePath(templateName) + '/' + thumb;
- InputStream input = AdtPlugin.readEmbeddedFileAsStream(filePath);
- if (input != null) {
+ File file = new File(mValues.activityValues.getTemplateLocation(),
+ thumb.replace('/', File.separatorChar));
+ if (file != null) {
try {
+ byte[] bytes = Files.toByteArray(file);
+ ByteArrayInputStream input = new ByteArrayInputStream(bytes);
mPreviewImage = new Image(getControl().getDisplay(), input);
input.close();
- } catch (Exception e) {
+ } catch (IOException e) {
AdtPlugin.log(e, null);
}
}
@@ -167,6 +187,10 @@
@Override
public void setVisible(boolean visible) {
+ if (visible && !mShown) {
+ onEnter();
+ }
+
super.setVisible(visible);
if (visible) {
@@ -233,11 +257,10 @@
mList.setEnabled(mValues.createActivity);
} else if (source == mList) {
int index = mList.getSelectionIndex();
- String[] items = mList.getItems();
- if (index >= 0 && index < items.length) {
- String templateName = items[index];
- mValues.activityValues.setTemplateName(templateName);
- setPreview(templateName);
+ if (index >= 0 && index < mTemplates.size()) {
+ File template = mTemplates.get(index);
+ mValues.activityValues.setTemplateLocation(template);
+ updatePreview();
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmActivityToLayoutMethod.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmActivityToLayoutMethod.java
index a6f2a9e..fbd50e9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmActivityToLayoutMethod.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmActivityToLayoutMethod.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.adt.internal.wizards.templates;
import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectPage.ACTIVITY_NAME_SUFFIX;
+import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectPage.LAYOUT_NAME_PREFIX;
import com.android.ide.eclipse.adt.AdtUtils;
@@ -39,6 +40,10 @@
String activityName = args.get(0).toString();
+ if (activityName.isEmpty()) {
+ return new SimpleScalar("");
+ }
+
// Strip off the end portion of the activity name. The user might be typing
// the activity name such that only a portion has been entered so far (e.g.
// "MainActivi") and we want to chop off that portion too such that we don't
@@ -52,7 +57,7 @@
// Convert CamelCase convention used in activity class names to underlined convention
// used in layout name:
- String name = AdtUtils.camelCaseToUnderlines(activityName);
+ String name = LAYOUT_NAME_PREFIX + AdtUtils.camelCaseToUnderlines(activityName);
return new SimpleScalar(name);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmLayoutToActivityMethod.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmLayoutToActivityMethod.java
index f3dd9cd..6514959 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmLayoutToActivityMethod.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmLayoutToActivityMethod.java
@@ -17,6 +17,7 @@
import static com.android.ide.eclipse.adt.AdtUtils.extractClassName;
import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectPage.ACTIVITY_NAME_SUFFIX;
+import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectPage.LAYOUT_NAME_PREFIX;
import com.android.ide.eclipse.adt.AdtUtils;
@@ -39,6 +40,15 @@
}
String name = args.get(0).toString();
+
+ // Strip off the beginning portion of the layout name. The user might be typing
+ // the activity name such that only a portion has been entered so far (e.g.
+ // "MainActivi") and we want to chop off that portion too such that we don't
+ // offer a layout name partially containing the activity suffix (e.g. "main_activi").
+ if (name.startsWith(LAYOUT_NAME_PREFIX)) {
+ name = name.substring(LAYOUT_NAME_PREFIX.length());
+ }
+
name = AdtUtils.underlinesToCamelCase(name);
String className = extractClassName(name);
if (className == null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectPage.java
index 0c40fab..800366a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectPage.java
@@ -68,7 +68,9 @@
implements ModifyListener, SelectionListener, FocusListener {
private static final String SAMPLE_PACKAGE_PREFIX = "com.example."; //$NON-NLS-1$
/** Suffix added by default to activity names */
- static final String ACTIVITY_NAME_SUFFIX = "Activity"; //$NON-NLS-1$
+ static final String ACTIVITY_NAME_SUFFIX = "Activity"; //$NON-NLS-1$
+ /** Prefix added to default layout names */
+ static final String LAYOUT_NAME_PREFIX = "activity_"; //$NON-NLS-1$
private static final int INITIAL_MIN_SDK = 8;
private final NewProjectWizardState mValues;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java
index 60f7a9e..c23cedc 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java
@@ -70,6 +70,7 @@
private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$
private IWorkbench mWorkbench;
+ private UpdateToolsPage mUpdatePage;
private NewProjectPage mMainPage;
private AppSkeletonPage mAppSkeletonPage;
private NewTemplatePage mTemplatePage;
@@ -85,6 +86,10 @@
setHelpAvailable(false);
setImageDescriptor();
+ if (!UpdateToolsPage.isUpToDate()) {
+ mUpdatePage = new UpdateToolsPage();
+ }
+
mValues = new NewProjectWizardState();
mMainPage = new NewProjectPage(mValues);
mAppSkeletonPage = new AppSkeletonPage(mValues);
@@ -96,12 +101,24 @@
*/
@Override
public void addPages() {
+ if (mUpdatePage != null) {
+ addPage(mUpdatePage);
+ }
+
addPage(mMainPage);
addPage(mAppSkeletonPage);
addPage(mActivityPage);
}
@Override
+ public IWizardPage getStartingPage() {
+ if (mUpdatePage != null && mUpdatePage.isPageComplete()) {
+ return mMainPage;
+ }
+ return super.getStartingPage();
+ }
+
+ @Override
public IWizardPage getNextPage(IWizardPage page) {
// If you turn off creating an application, only one page
if (page == mMainPage) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizardState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizardState.java
index 48a781f..1dc81ca 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizardState.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizardState.java
@@ -19,19 +19,16 @@
import com.android.ide.eclipse.adt.internal.assetstudio.CreateAssetSetWizardState;
import com.android.sdklib.IAndroidTarget;
-import java.io.File;
-
/**
* Value object which holds the current state of the wizard pages for the
* {@link NewProjectWizard}
*/
public class NewProjectWizardState {
- private static final String TEMPLATE_NAME = "NewAndroidApplication"; //$NON-NLS-1$
+ private static final String TEMPLATE_NAME = "projects/NewAndroidApplication"; //$NON-NLS-1$
/** Creates a new {@link NewProjectWizardState} */
public NewProjectWizardState() {
- File inputPath = new File(TemplateHandler.getTemplatePath(TEMPLATE_NAME));
- template = TemplateHandler.createFromPath(inputPath);
+ template = TemplateHandler.createFromName(TEMPLATE_NAME);
}
/** The template handler instantiating the project */
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java
index a6fdf48..517a5c8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java
@@ -162,11 +162,11 @@
if (template != null) {
thumb = template.getThumbnailPath();
String title = template.getTitle();
- if (!title.isEmpty()) {
+ if (title != null && !title.isEmpty()) {
setTitle(title);
}
String description = template.getDescription();
- if (!description.isEmpty()) {
+ if (description != null && !description.isEmpty()) {
setDescription(description);
}
@@ -539,14 +539,18 @@
String optionId = optionIds[index];
editParameter(combo, optionId);
TemplateMetadata template = mValues.getTemplateHandler().getTemplate();
- setPreview(template.getThumbnailPath());
+ if (template != null) {
+ setPreview(template.getThumbnailPath());
+ }
}
} else if (source instanceof Button) {
Button button = (Button) source;
editParameter(button, button.getSelection());
TemplateMetadata template = mValues.getTemplateHandler().getTemplate();
- setPreview(template.getThumbnailPath());
+ if (template != null) {
+ setPreview(template.getThumbnailPath());
+ }
}
validatePage();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java
index b7ad998..143db78 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java
@@ -34,6 +34,7 @@
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
@@ -50,18 +51,16 @@
*/
public class NewTemplateWizard extends Wizard implements INewWizard {
/** Template name and location under /templates in the plugin */
- static final String BLANK_ACTIVITY = "BlankActivity"; //$NON-NLS-1$
+ static final String BLANK_ACTIVITY = "activities/BlankActivity"; //$NON-NLS-1$
/** Template name and location under /templates in the plugin */
- static final String MASTER_DETAIL_FLOW = "MasterDetailFlow"; //$NON-NLS-1$
+ static final String MASTER_DETAIL_FLOW = "activities/MasterDetailFlow"; //$NON-NLS-1$
/** Template name and location under /templates in the plugin */
- static final String CUSTOM_VIEW = "CustomView"; //$NON-NLS-1$
- /** Available activity-templates (included in a list in the new project template) */
- static final String[] ACTIVITY_TEMPLATES =
- new String[] { BLANK_ACTIVITY, MASTER_DETAIL_FLOW };
- private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$
+ static final String CUSTOM_VIEW = "other/CustomView"; //$NON-NLS-1$
+ private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$
protected IWorkbench mWorkbench;
protected NewTemplatePage mMainPage;
+ protected UpdateToolsPage mUpdatePage;
protected NewTemplateWizardState mValues;
private final String mTemplateName;
@@ -77,9 +76,15 @@
setImageDescriptor();
mValues = new NewTemplateWizardState();
- mValues.setTemplateName(mTemplateName);
+
+ File template = TemplateHandler.getTemplateLocation(mTemplateName);
+ mValues.setTemplateLocation(template);
hideBuiltinParameters();
+ if (!UpdateToolsPage.isUpToDate()) {
+ mUpdatePage = new UpdateToolsPage();
+ }
+
List<IProject> projects = AdtUtils.getSelectedProjects(selection);
if (projects.size() == 1) {
mValues.project = projects.get(0);
@@ -103,10 +108,27 @@
@Override
public void addPages() {
+ if (mUpdatePage != null) {
+ addPage(mUpdatePage);
+ }
+
addPage(mMainPage);
}
@Override
+ public IWizardPage getNextPage(IWizardPage page) {
+ return super.getNextPage(page);
+ }
+
+ @Override
+ public IWizardPage getStartingPage() {
+ if (mUpdatePage != null && mUpdatePage.isPageComplete()) {
+ return mMainPage;
+ }
+ return super.getStartingPage();
+ }
+
+ @Override
public boolean performFinish() {
try {
Map<String, Object> parameters = mValues.parameters;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java
index dc75a71..1fb73d8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java
@@ -33,9 +33,6 @@
* {@link NewTemplateWizard}
*/
public class NewTemplateWizardState {
- /** Name of the template being created */
- private String mTemplateName = BLANK_ACTIVITY;
-
/** Template handler responsible for instantiating templates and reading resources */
private TemplateHandler mTemplateHandler;
@@ -55,7 +52,7 @@
*/
public IProject project;
- /** Name of the template being created */
+ /** Location of the template being created */
private File mTemplateLocation;
/**
@@ -65,31 +62,14 @@
}
@NonNull
- String getTemplateName() {
- return mTemplateName;
- }
-
- /**
- * Sets the new template name to use
- *
- * @param templateName the name of the template to use
- */
- void setTemplateName(@NonNull String templateName) {
- if (!templateName.equals(mTemplateName)) {
- mTemplateName = templateName;
- mTemplateLocation = null;
- mTemplateHandler = null;
- }
- }
-
- @NonNull
TemplateHandler getTemplateHandler() {
if (mTemplateHandler == null) {
File inputPath;
if (mTemplateLocation != null) {
inputPath = mTemplateLocation;
} else {
- inputPath = new File(TemplateHandler.getTemplatePath(mTemplateName));
+ // Default
+ inputPath = TemplateHandler.getTemplateLocation(BLANK_ACTIVITY);
}
mTemplateHandler = TemplateHandler.createFromPath(inputPath);
}
@@ -97,12 +77,18 @@
return mTemplateHandler;
}
- // For template development/testing only
+ /** Sets the current template */
void setTemplateLocation(File file) {
if (!file.equals(mTemplateLocation)) {
mTemplateLocation = file;
- mTemplateName = null;
mTemplateHandler = null;
}
}
+
+ /** Returns the current template */
+ File getTemplateLocation() {
+ return mTemplateLocation;
+ }
+
+
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
index 4f107fb..760084d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
@@ -16,8 +16,9 @@
package com.android.ide.eclipse.adt.internal.wizards.templates;
import static com.android.ide.eclipse.adt.AdtConstants.DOT_FTL;
-import static com.android.ide.eclipse.adt.AdtConstants.DOT_JAR;
import static com.android.ide.eclipse.adt.AdtConstants.DOT_XML;
+import static com.android.sdklib.SdkConstants.FD_TEMPLATES;
+import static com.android.sdklib.SdkConstants.FD_TOOLS;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
@@ -27,11 +28,11 @@
import com.android.ide.eclipse.adt.internal.editors.formatting.XmlFormatStyle;
import com.android.ide.eclipse.adt.internal.editors.formatting.XmlPrettyPrinter;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
+import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.manifmerger.ManifestMerger;
import com.android.resources.ResourceFolderType;
import com.android.sdklib.SdkConstants;
import com.google.common.base.Charsets;
-import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import freemarker.cache.TemplateLoader;
@@ -54,22 +55,16 @@
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
-import java.net.URI;
import java.net.URL;
-import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
@@ -98,10 +93,7 @@
* Shared resource directory containing common resources shared among
* multiple templates
*/
- private static final String RESOURCE_ROOT = "res"; //$NON-NLS-1$
-
- /** Relative path within the ADT plugin where the templates are found */
- static final String TEMPLATE_PREFIX = "/templates/"; //$NON-NLS-1$
+ private static final String RESOURCE_ROOT = "resources"; //$NON-NLS-1$
/** Reserved filename which describes each template */
static final String TEMPLATE_XML = "template.xml"; //$NON-NLS-1$
@@ -132,6 +124,11 @@
static final String ATTR_FROM = "from"; //$NON-NLS-1$
static final String ATTR_CONSTRAINTS = "constraints";//$NON-NLS-1$
+ static final String CATEGORY_ACTIVITIES = "activities";//$NON-NLS-1$
+ static final String CATEGORY_PROJECTS = "projects"; //$NON-NLS-1$
+ static final String CATEGORY_OTHER = "other"; //$NON-NLS-1$
+
+
/** Default padding to apply in wizards around the thumbnail preview images */
static final int PREVIEW_PADDING = 10;
@@ -145,6 +142,7 @@
private final List<String> mOpen = Lists.newArrayList();
/** Path to the directory containing the templates */
+ @NonNull
private final File mRootPath;
/** The template loader which is responsible for finding (and sharing) template files */
@@ -172,6 +170,12 @@
return new TemplateHandler(rootPath);
}
+ /** Creates a new {@link TemplateHandler} for the template name, which should
+ * be relative to the templates directory */
+ static TemplateHandler createFromName(String relative) {
+ return new TemplateHandler(new File(getTemplateRootFolder(), relative));
+ }
+
private TemplateHandler(File rootPath) {
mRootPath = rootPath;
mLoader = new MyTemplateLoader();
@@ -244,26 +248,75 @@
@Nullable
public static TemplateMetadata getTemplate(String templateName) {
- String relative = getTemplatePath(templateName) + '/' +TEMPLATE_XML;
- String xml = AdtPlugin.readEmbeddedTextFile(relative);
- Document doc = DomUtilities.parseDocument(xml, true);
- if (doc != null && doc.getDocumentElement() != null) {
- return new TemplateMetadata(doc);
+ String relative = templateName + '/' + TEMPLATE_XML;
+
+ File templateFile = getTemplateLocation(relative);
+ if (templateFile != null) {
+ try {
+ String xml = Files.toString(templateFile, Charsets.UTF_8);
+ Document doc = DomUtilities.parseDocument(xml, true);
+ if (doc != null && doc.getDocumentElement() != null) {
+ return new TemplateMetadata(doc);
+ }
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ return null;
+ }
}
return null;
}
@NonNull
- public static String getTemplatePath(String templateName) {
- return TEMPLATE_PREFIX + templateName;
- }
-
- @NonNull
public String getResourcePath(String templateName) {
return new File(mRootPath.getPath(), templateName).getPath();
}
+ @Nullable
+ public static File getTemplateRootFolder() {
+ String location = AdtPrefs.getPrefs().getOsSdkFolder();
+ if (location != null) {
+ File folder = new File(location, FD_TOOLS + File.separator + FD_TEMPLATES);
+ if (folder.isDirectory()) {
+ return folder;
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ public static File getTemplateLocation(@NonNull File root, @NonNull String relativePath) {
+ File templateRoot = getTemplateRootFolder();
+ if (templateRoot != null) {
+ String rootPath = root.getPath();
+ File templateFile = new File(templateRoot,
+ rootPath.replace('/', File.separatorChar) + File.separator
+ + relativePath.replace('/', File.separatorChar));
+ if (templateFile.exists()) {
+ return templateFile;
+ }
+ }
+
+ return null;
+
+ }
+
+ @Nullable
+ public static File getTemplateLocation(@NonNull String relativePath) {
+ File templateRoot = getTemplateRootFolder();
+ if (templateRoot != null) {
+ File templateFile = new File(templateRoot,
+ relativePath.replace('/', File.separatorChar));
+ if (templateFile.exists()) {
+ return templateFile;
+ }
+ }
+
+ return null;
+
+ }
+
/**
* Load a text resource for the given relative path within the template
*
@@ -272,29 +325,23 @@
*/
@Nullable
public String readTemplateTextResource(@NonNull String relativePath) {
- if (mRootPath.getPath().startsWith(TEMPLATE_PREFIX)) {
- return AdtPlugin.readEmbeddedTextFile(getResourcePath(relativePath));
- } else {
- try {
- return Files.toString(new File(mRootPath, relativePath), Charsets.UTF_8);
- } catch (IOException e) {
- AdtPlugin.log(e, null);
- return null;
- }
+ try {
+ return Files.toString(new File(mRootPath,
+ relativePath.replace('/', File.separatorChar)), Charsets.UTF_8);
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ return null;
}
}
@Nullable
public String readTemplateTextResource(@NonNull File file) {
- if (mRootPath.getPath().startsWith(TEMPLATE_PREFIX)) {
- return AdtPlugin.readEmbeddedTextFile(file.getPath());
- } else {
- try {
- return Files.toString(file, Charsets.UTF_8);
- } catch (IOException e) {
- AdtPlugin.log(e, null);
- return null;
- }
+ assert file.isAbsolute();
+ try {
+ return Files.toString(file, Charsets.UTF_8);
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ return null;
}
}
@@ -306,15 +353,11 @@
*/
@Nullable
public byte[] readTemplateResource(@NonNull String relativePath) {
- if (mRootPath.getPath().startsWith(TEMPLATE_PREFIX)) {
- return AdtPlugin.readEmbeddedFile(getResourcePath(relativePath));
- } else {
- try {
- return Files.toByteArray(new File(mRootPath, relativePath));
- } catch (IOException e) {
- AdtPlugin.log(e, null);
- return null;
- }
+ try {
+ return Files.toByteArray(new File(mRootPath, relativePath));
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ return null;
}
}
@@ -326,6 +369,9 @@
if (file.endsWith(DOT_XML)) {
// Just read the file
xml = readTemplateTextResource(file);
+ if (xml == null) {
+ return;
+ }
} else {
mLoader.setTemplateFile(new File(mRootPath, file));
Template inputsTemplate = freemarker.getTemplate(file);
@@ -366,7 +412,8 @@
execute(freemarker, path, paramMap, outputPath);
}
} else if (!name.equals("template") && !name.equals("category")
- && !name.equals("option")) {
+ && !name.equals("option") && !name.equals(TAG_THUMBS) &&
+ !name.equals(TAG_THUMB)) {
System.err.println("WARNING: Unknown template directive " + name);
}
}
@@ -492,10 +539,12 @@
}
}
- private File getFullPath(String fromPath) {
+ @NonNull
+ private File getFullPath(@NonNull String fromPath) {
if (fromPath.startsWith(VALUE_TEMPLATE_DIR)) {
- return new File(mRootPath.getParentFile(), RESOURCE_ROOT
- + fromPath.substring(VALUE_TEMPLATE_DIR.length()));
+ return new File(getTemplateRootFolder(), RESOURCE_ROOT + File.separator
+ + fromPath.substring(VALUE_TEMPLATE_DIR.length() + 1).replace('/',
+ File.separatorChar));
}
return new File(mRootPath, DATA_ROOT + File.separator + fromPath);
}
@@ -616,37 +665,6 @@
}
}
- /**
- * Writes the given contents into the given file (unless that file already
- * contains the given contents), and if the file exists ask user whether
- * the file should be overwritten (unless the user has already answered "Yes to All"
- * or "Cancel" (no to all).
- */
- private void writeBytes(File destination, byte[] contents, boolean confirmOverwrite)
- throws IOException {
- // First make sure that the files aren't identical, in which case we can do
- // nothing (and not involve user)
- if (!(destination.exists() && isIdentical(contents, destination))) {
- // And if the file does exist (and is now known to be different),
- // ask user whether it should be replaced (canOverwrite will also
- // return true if the file doesn't exist)
- if (confirmOverwrite) {
- if (!canOverwrite(destination)) {
- return;
- }
- } else {
- if (destination.exists()) {
- if (mBackupMergedFiles) {
- makeBackup(destination);
- } else {
- destination.delete();
- }
- }
- }
- Files.write(contents, destination);
- }
- }
-
/** Merges the given resource file contents into the given resource file
* @param paramMap */
private boolean mergeResourceFile(Document currentManifest, Document fragment,
@@ -810,60 +828,11 @@
}
/** Copy a bundled resource (part of the plugin .jar file) into the given file system path */
- private final void copyBundledResource(String relativeFrom, File output) throws IOException {
+ private final void copyBundledResource(
+ @NonNull String relativeFrom,
+ @NonNull File output) throws IOException {
File from = getFullPath(relativeFrom);
-
- // Local file copy? (Only used for the template-development wizard)
- if (!mRootPath.getPath().startsWith(TEMPLATE_PREFIX)) {
- copy(from, output);
- return;
- }
-
- String resourcePath = from.getPath();
- CodeSource source = TemplateHandler.class.getProtectionDomain().getCodeSource();
- if (source != null) {
- URL location = source.getLocation();
- try {
- URI locationUri = location.toURI();
- File locationFile = new File(locationUri);
- if (!locationUri.getPath().endsWith(DOT_JAR)) {
- // Plain file; e.g. when running out of Eclipse plugin in
- // Eclipse; it uses the bin/ folder instead of running out of a jar
- File sourceFile = new File(locationFile, resourcePath);
- copy(sourceFile, output);
- return;
- }
-
- // Copy out of jar file
- JarFile jarFile = new JarFile(locationFile);
- int chopIndex = resourcePath.length() + 1;
- for (final Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements();) {
- final JarEntry entry = e.nextElement();
- if (entry.getName().startsWith(resourcePath)) {
- final String filename = entry.getName().substring(chopIndex);
- assert entry.getName().charAt(resourcePath.length()) == '/';
- final File file = new File(output, filename);
- if (!entry.isDirectory()) {
- // Copy stream
- InputStream in = jarFile.getInputStream(entry);
- try {
- byte[] data = ByteStreams.toByteArray(in);
- writeBytes(output, data, true);
- } finally {
- in.close();
- }
- } else {
- // Create directory
- if (!file.exists() && !file.mkdirs()) {
- throw new IOException("Could not create directory " + file);
- }
- }
- }
- }
- } catch (Exception e) {
- AdtPlugin.log(e, null);
- }
- }
+ copy(from, output);
}
/** Returns true if the given file contains the given bytes */
@@ -939,21 +908,36 @@
@Override
public Object findTemplateSource(String name) throws IOException {
String path = mPrefix != null ? mPrefix + '/' + name : name;
- URL resource = TemplateHandler.class.getResource(path);
-
- // Support for local files during template development
- if (resource == null && mPrefix != null && !mPrefix.startsWith(TEMPLATE_PREFIX)) {
- File file = new File(path);
- if (file.exists()) {
- return file.toURI().toURL();
- }
+ File file = new File(path);
+ if (file.exists()) {
+ return file.toURI().toURL();
}
-
- return resource;
+ return null;
}
@Override
public void closeTemplateSource(Object templateSource) throws IOException {
}
}
+
+ /** Returns all the templates with the given prefix
+ *
+ * @param folder the folder prefix
+ * @return the available templates
+ */
+ @NonNull
+ static List<File> getTemplates(@NonNull String folder) {
+ List<File> templates = new ArrayList<File>();
+ File root = getTemplateRootFolder();
+ if (root != null) {
+ File[] files = new File(root, folder).listFiles();
+ if (files != null) {
+ for (File file : files) {
+ templates.add(file);
+ }
+ }
+ }
+
+ return templates;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/UpdateToolsPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/UpdateToolsPage.java
new file mode 100644
index 0000000..72713b2
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/UpdateToolsPage.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ide.eclipse.adt.internal.wizards.templates;
+
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+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.Label;
+
+class UpdateToolsPage extends WizardPage implements SelectionListener {
+ private Button mInstallButton;
+ UpdateToolsPage() {
+ super("update");
+ setTitle("Update Tools");
+ validatePage();
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ setControl(container);
+ container.setLayout(new GridLayout(1, false));
+
+ Label label = new Label(container, SWT.WRAP);
+ GridData layoutData = new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1);
+ layoutData.widthHint = NewTemplatePage.WIZARD_PAGE_WIDTH - 50;
+ label.setLayoutData(layoutData);
+ label.setText(
+ "Your tools installation appears to be out of date (or not yet installed).\n" +
+ "\n" +
+ "This wizard depends on templates distributed with the Android SDK Tools.\n" +
+ "\n" +
+ "Please update the tools first (via Window > Android SDK Manager, or by " +
+ "using the \"android\" command in a terminal window). Note that on Windows " +
+ "you may need to restart the IDE, since there are some known problems where " +
+ "Windows locks the files held open by the running IDE, so the updater is " +
+ "unable to delete them in order to upgrade them.");
+
+ mInstallButton = new Button(container, SWT.NONE);
+ mInstallButton.setText("Check Again");
+ mInstallButton.addSelectionListener(this);
+ }
+
+ @Override
+ public boolean isPageComplete() {
+ return isUpToDate();
+ }
+
+ static boolean isUpToDate() {
+ return TemplateHandler.getTemplateRootFolder() != null;
+ }
+
+ private void validatePage() {
+ boolean ok = isUpToDate();
+ setPageComplete(ok);
+ if (ok) {
+ setErrorMessage(null);
+ setMessage(null);
+ } else {
+ setErrorMessage("The tools need to be updated via the SDK Manager");
+ }
+ }
+
+ // ---- Implements SelectionListener ----
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (e.getSource() == mInstallButton) {
+ validatePage();
+ }
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/globals.xml.ftl b/templates/activities/BlankActivity/globals.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/globals.xml.ftl
rename to templates/activities/BlankActivity/globals.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/recipe.xml.ftl b/templates/activities/BlankActivity/recipe.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/recipe.xml.ftl
rename to templates/activities/BlankActivity/recipe.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/AndroidManifest.xml.ftl b/templates/activities/BlankActivity/root/AndroidManifest.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/AndroidManifest.xml.ftl
rename to templates/activities/BlankActivity/root/AndroidManifest.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-hdpi/ic_action_search.png b/templates/activities/BlankActivity/root/res/drawable-hdpi/ic_action_search.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-hdpi/ic_action_search.png
rename to templates/activities/BlankActivity/root/res/drawable-hdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-mdpi/ic_action_search.png b/templates/activities/BlankActivity/root/res/drawable-mdpi/ic_action_search.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-mdpi/ic_action_search.png
rename to templates/activities/BlankActivity/root/res/drawable-mdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png b/templates/activities/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png
rename to templates/activities/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_fragment_container.xml b/templates/activities/BlankActivity/root/res/layout/activity_fragment_container.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_fragment_container.xml
rename to templates/activities/BlankActivity/root/res/layout/activity_fragment_container.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_pager.xml.ftl b/templates/activities/BlankActivity/root/res/layout/activity_pager.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_pager.xml.ftl
rename to templates/activities/BlankActivity/root/res/layout/activity_pager.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_simple.xml b/templates/activities/BlankActivity/root/res/layout/activity_simple.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_simple.xml
rename to templates/activities/BlankActivity/root/res/layout/activity_simple.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/menu/main.xml b/templates/activities/BlankActivity/root/res/menu/main.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/menu/main.xml
rename to templates/activities/BlankActivity/root/res/menu/main.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values-large/dimens.xml b/templates/activities/BlankActivity/root/res/values-large/dimens.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values-large/dimens.xml
rename to templates/activities/BlankActivity/root/res/values-large/dimens.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/dimens.xml b/templates/activities/BlankActivity/root/res/values/dimens.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/dimens.xml
rename to templates/activities/BlankActivity/root/res/values/dimens.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/strings.xml.ftl b/templates/activities/BlankActivity/root/res/values/strings.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/strings.xml.ftl
rename to templates/activities/BlankActivity/root/res/values/strings.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/DropdownActivity.java.ftl b/templates/activities/BlankActivity/root/src/app_package/DropdownActivity.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/DropdownActivity.java.ftl
rename to templates/activities/BlankActivity/root/src/app_package/DropdownActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/SimpleActivity.java.ftl b/templates/activities/BlankActivity/root/src/app_package/SimpleActivity.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/SimpleActivity.java.ftl
rename to templates/activities/BlankActivity/root/src/app_package/SimpleActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsActivity.java.ftl b/templates/activities/BlankActivity/root/src/app_package/TabsActivity.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsActivity.java.ftl
rename to templates/activities/BlankActivity/root/src/app_package/TabsActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl b/templates/activities/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl
rename to templates/activities/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml b/templates/activities/BlankActivity/template.xml
similarity index 98%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml
rename to templates/activities/BlankActivity/template.xml
index 302e2cc..10e6bc8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml
+++ b/templates/activities/BlankActivity/template.xml
@@ -20,7 +20,7 @@
type="string"
constraints="layout|unique"
suggest="${activityToLayout(activityClass)}"
- default="main"
+ default="activity_main"
help="The name of the layout to create for the activity" />
<parameter
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity.png b/templates/activities/BlankActivity/template_blank_activity.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity.png
rename to templates/activities/BlankActivity/template_blank_activity.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_dropdown.png b/templates/activities/BlankActivity/template_blank_activity_dropdown.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_dropdown.png
rename to templates/activities/BlankActivity/template_blank_activity_dropdown.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_pager.png b/templates/activities/BlankActivity/template_blank_activity_pager.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_pager.png
rename to templates/activities/BlankActivity/template_blank_activity_pager.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs.png b/templates/activities/BlankActivity/template_blank_activity_tabs.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs.png
rename to templates/activities/BlankActivity/template_blank_activity_tabs.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs_pager.png b/templates/activities/BlankActivity/template_blank_activity_tabs_pager.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs_pager.png
rename to templates/activities/BlankActivity/template_blank_activity_tabs_pager.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/globals.xml.ftl b/templates/activities/MasterDetailFlow/globals.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/globals.xml.ftl
rename to templates/activities/MasterDetailFlow/globals.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/recipe.xml.ftl b/templates/activities/MasterDetailFlow/recipe.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/recipe.xml.ftl
rename to templates/activities/MasterDetailFlow/recipe.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/AndroidManifest.xml.ftl b/templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/AndroidManifest.xml.ftl
rename to templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl b/templates/activities/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl
rename to templates/activities/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl b/templates/activities/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl
rename to templates/activities/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl b/templates/activities/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl
rename to templates/activities/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl b/templates/activities/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl
rename to templates/activities/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-large/refs.xml.ftl b/templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-large/refs.xml.ftl
rename to templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl b/templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl
rename to templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values/strings.xml.ftl b/templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values/strings.xml.ftl
rename to templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl
rename to templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl
rename to templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl
rename to templates/activities/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl
rename to templates/activities/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl
rename to templates/activities/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template.xml b/templates/activities/MasterDetailFlow/template.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template.xml
rename to templates/activities/MasterDetailFlow/template.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template_master_detail.png b/templates/activities/MasterDetailFlow/template_master_detail.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template_master_detail.png
rename to templates/activities/MasterDetailFlow/template_master_detail.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/globals.xml.ftl b/templates/other/CustomView/globals.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/globals.xml.ftl
rename to templates/other/CustomView/globals.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/recipe.xml.ftl b/templates/other/CustomView/recipe.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/recipe.xml.ftl
rename to templates/other/CustomView/recipe.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/layout/sample.xml.ftl b/templates/other/CustomView/root/res/layout/sample.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/layout/sample.xml.ftl
rename to templates/other/CustomView/root/res/layout/sample.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/values/attrs.xml.ftl b/templates/other/CustomView/root/res/values/attrs.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/values/attrs.xml.ftl
rename to templates/other/CustomView/root/res/values/attrs.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/src/app_package/CustomView.java.ftl b/templates/other/CustomView/root/src/app_package/CustomView.java.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/src/app_package/CustomView.java.ftl
rename to templates/other/CustomView/root/src/app_package/CustomView.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/template.xml b/templates/other/CustomView/template.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/template.xml
rename to templates/other/CustomView/template.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/globals.xml.ftl b/templates/projects/NewAndroidApplication/globals.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/globals.xml.ftl
rename to templates/projects/NewAndroidApplication/globals.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/recipe.xml.ftl b/templates/projects/NewAndroidApplication/recipe.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/recipe.xml.ftl
rename to templates/projects/NewAndroidApplication/recipe.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/AndroidManifest.xml.ftl b/templates/projects/NewAndroidApplication/root/AndroidManifest.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/AndroidManifest.xml.ftl
rename to templates/projects/NewAndroidApplication/root/AndroidManifest.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png b/templates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png
rename to templates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png b/templates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png
rename to templates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png b/templates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png
rename to templates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png b/templates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png
rename to templates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png b/templates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png
rename to templates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png b/templates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png
rename to templates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values-large/dimens.xml b/templates/projects/NewAndroidApplication/root/res/values-large/dimens.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values-large/dimens.xml
rename to templates/projects/NewAndroidApplication/root/res/values-large/dimens.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/dimens.xml b/templates/projects/NewAndroidApplication/root/res/values/dimens.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/dimens.xml
rename to templates/projects/NewAndroidApplication/root/res/values/dimens.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/strings.xml.ftl b/templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/strings.xml.ftl
rename to templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/styles.xml b/templates/projects/NewAndroidApplication/root/res/values/styles.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/styles.xml
rename to templates/projects/NewAndroidApplication/root/res/values/styles.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template.xml b/templates/projects/NewAndroidApplication/template.xml
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template.xml
rename to templates/projects/NewAndroidApplication/template.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template_new_project.png b/templates/projects/NewAndroidApplication/template_new_project.png
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template_new_project.png
rename to templates/projects/NewAndroidApplication/template_new_project.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/res/android-support-v4.jar.bin b/templates/resources/android-support-v4.jar.bin
similarity index 100%
rename from eclipse/plugins/com.android.ide.eclipse.adt/templates/res/android-support-v4.jar.bin
rename to templates/resources/android-support-v4.jar.bin
Binary files differ