aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java653
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/ChooseConfigurationPage.java282
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java1163
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileWizard.java431
4 files changed, 0 insertions, 2529 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java
deleted file mode 100644
index 0301b80fe..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * 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.newxmlfile;
-
-import static com.android.SdkConstants.FD_RES;
-import static com.android.SdkConstants.FD_RES_VALUES;
-import static com.android.SdkConstants.RES_QUALIFIER_SEP;
-
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.res2.ValueXmlHelper;
-import com.android.ide.common.resources.LocaleManager;
-import com.android.ide.common.resources.ResourceItem;
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.AdtUtils;
-import com.android.ide.eclipse.adt.internal.editors.layout.configuration.FlagManager;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageControl;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewManager;
-import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
-import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
-import com.android.resources.ResourceType;
-import com.google.common.base.Charsets;
-import com.google.common.collect.Maps;
-
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.viewers.ArrayContentProvider;
-import org.eclipse.jface.viewers.CellEditor;
-import org.eclipse.jface.viewers.CellLabelProvider;
-import org.eclipse.jface.viewers.ColumnViewer;
-import org.eclipse.jface.viewers.EditingSupport;
-import org.eclipse.jface.viewers.IBaseLabelProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.TextCellEditor;
-import org.eclipse.jface.viewers.ViewerCell;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.events.TraverseEvent;
-import org.eclipse.swt.events.TraverseListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-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.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.PlatformUI;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-
-/**
- * Dialog which adds a new translation to the project
- */
-public class AddTranslationDialog extends Dialog implements ControlListener, SelectionListener,
- TraverseListener {
- private static final int KEY_COLUMN = 0;
- private static final int DEFAULT_TRANSLATION_COLUMN = 1;
- private static final int NEW_TRANSLATION_COLUMN = 2;
- private final FolderConfiguration mConfiguration = new FolderConfiguration();
- private final IProject mProject;
- private String mTarget;
- private boolean mIgnore;
- private Map<String, String> mTranslations;
- private Set<String> mExistingLanguages;
- private String mSelectedLanguage;
- private String mSelectedRegion;
-
- private Table mTable;
- private Combo mLanguageCombo;
- private Combo mRegionCombo;
- private ImageControl mFlag;
- private Label mFile;
- private Button mOkButton;
- private Composite mErrorPanel;
- private Label mErrorLabel;
- private MyTableViewer mTableViewer;
-
- /**
- * Creates the dialog.
- * @param parentShell the parent shell
- * @param project the project to add translations into
- */
- public AddTranslationDialog(Shell parentShell, IProject project) {
- super(parentShell);
- setShellStyle(SWT.CLOSE | SWT.RESIZE | SWT.TITLE);
- mProject = project;
- }
-
- @Override
- protected Control createDialogArea(Composite parent) {
- Composite container = (Composite) super.createDialogArea(parent);
- GridLayout gl_container = new GridLayout(6, false);
- gl_container.horizontalSpacing = 0;
- container.setLayout(gl_container);
-
- Label languageLabel = new Label(container, SWT.NONE);
- languageLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- languageLabel.setText("Language:");
- mLanguageCombo = new Combo(container, SWT.READ_ONLY);
- GridData gd_mLanguageCombo = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
- gd_mLanguageCombo.widthHint = 150;
- mLanguageCombo.setLayoutData(gd_mLanguageCombo);
-
- Label regionLabel = new Label(container, SWT.NONE);
- GridData gd_regionLabel = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
- gd_regionLabel.horizontalIndent = 10;
- regionLabel.setLayoutData(gd_regionLabel);
- regionLabel.setText("Region:");
- mRegionCombo = new Combo(container, SWT.READ_ONLY);
- GridData gd_mRegionCombo = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
- gd_mRegionCombo.widthHint = 150;
- mRegionCombo.setLayoutData(gd_mRegionCombo);
- mRegionCombo.setEnabled(false);
-
- mFlag = new ImageControl(container, SWT.NONE, null);
- mFlag.setDisposeImage(false);
- GridData gd_mFlag = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
- gd_mFlag.exclude = true;
- gd_mFlag.widthHint = 32;
- gd_mFlag.horizontalIndent = 3;
- mFlag.setLayoutData(gd_mFlag);
-
- mFile = new Label(container, SWT.NONE);
- mFile.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
-
- mTableViewer = new MyTableViewer(container, SWT.BORDER | SWT.FULL_SELECTION);
- mTable = mTableViewer.getTable();
- mTable.setEnabled(false);
- mTable.setLinesVisible(true);
- mTable.setHeaderVisible(true);
- mTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 6, 2));
- mTable.addControlListener(this);
- mTable.addTraverseListener(this);
- // If you have difficulty opening up this form in WindowBuilder and it complains about
- // the next line, change the type of the mTableViewer field and the above
- // constructor call from MyTableViewer to TableViewer
- TableViewerColumn keyViewerColumn = new TableViewerColumn(mTableViewer, SWT.NONE);
- TableColumn keyColumn = keyViewerColumn.getColumn();
- keyColumn.setWidth(100);
- keyColumn.setText("Key");
- TableViewerColumn defaultViewerColumn = new TableViewerColumn(mTableViewer, SWT.NONE);
- TableColumn defaultColumn = defaultViewerColumn.getColumn();
- defaultColumn.setWidth(200);
- defaultColumn.setText("Default");
- TableViewerColumn translationViewerColumn = new TableViewerColumn(mTableViewer, SWT.NONE);
- TableColumn translationColumn = translationViewerColumn.getColumn();
- translationColumn.setWidth(200);
- translationColumn.setText("New Translation");
-
- mErrorPanel = new Composite(container, SWT.NONE);
- GridData gd_mErrorLabel = new GridData(SWT.FILL, SWT.CENTER, false, false, 6, 1);
- gd_mErrorLabel.exclude = true;
- mErrorPanel.setLayoutData(gd_mErrorLabel);
-
- translationViewerColumn.setEditingSupport(new TranslationEditingSupport(mTableViewer));
-
- fillLanguages();
- fillRegions();
- fillStrings();
- updateColumnWidths();
- validatePage();
-
- mLanguageCombo.addSelectionListener(this);
- mRegionCombo.addSelectionListener(this);
-
- return container;
- }
-
- /** Populates the table with keys and default strings */
- private void fillStrings() {
- ResourceManager manager = ResourceManager.getInstance();
- ProjectResources resources = manager.getProjectResources(mProject);
- mExistingLanguages = resources.getLanguages();
-
- Collection<ResourceItem> items = resources.getResourceItemsOfType(ResourceType.STRING);
-
- ResourceItem[] array = items.toArray(new ResourceItem[items.size()]);
- Arrays.sort(array);
-
- // TODO: Read in the actual XML files providing the default keys here
- // (they can be obtained via ResourceItem.getSourceFileList())
- // such that we can read all the attributes associated with each
- // item, and if it defines translatable=false, or the filename is
- // donottranslate.xml, we can ignore it, and in other cases just
- // duplicate all the attributes (such as "formatted=true", or other
- // local conventions such as "product=tablet", or "msgid="123123123",
- // etc.)
-
- mTranslations = Maps.newHashMapWithExpectedSize(items.size());
- IBaseLabelProvider labelProvider = new CellLabelProvider() {
- @Override
- public void update(ViewerCell cell) {
- Object element = cell.getElement();
- int index = cell.getColumnIndex();
- ResourceItem item = (ResourceItem) element;
- switch (index) {
- case KEY_COLUMN: {
- // Key
- cell.setText(item.getName());
- return;
- }
- case DEFAULT_TRANSLATION_COLUMN: {
- // Default translation
- ResourceValue value = item.getResourceValue(ResourceType.STRING,
- mConfiguration, false);
-
- if (value != null) {
- cell.setText(value.getValue());
- return;
- }
- break;
- }
- case NEW_TRANSLATION_COLUMN: {
- // New translation
- String translation = mTranslations.get(item.getName());
- if (translation != null) {
- cell.setText(translation);
- return;
- }
- break;
- }
- default:
- assert false : index;
- }
- cell.setText("");
- }
- };
-
- mTableViewer.setLabelProvider(labelProvider);
- mTableViewer.setContentProvider(new ArrayContentProvider());
- mTableViewer.setInput(array);
- }
-
- /** Populate the languages dropdown */
- private void fillLanguages() {
- List<String> languageCodes = LocaleManager.getLanguageCodes();
- List<String> labels = new ArrayList<String>();
- for (String code : languageCodes) {
- labels.add(code + ": " + LocaleManager.getLanguageName(code)); //$NON-NLS-1$
- }
- Collections.sort(labels);
- labels.add(0, "(Select)");
- mLanguageCombo.setItems(labels.toArray(new String[labels.size()]));
- mLanguageCombo.select(0);
- }
-
- /** Populate the regions dropdown */
- private void fillRegions() {
- // TODO: When you switch languages, offer some "default" usable options. For example,
- // when you choose English, offer the countries that use English, and so on. Unfortunately
- // we don't have good data about this, we'd just need to hardcode a few common cases.
- List<String> regionCodes = LocaleManager.getRegionCodes();
- List<String> labels = new ArrayList<String>();
- for (String code : regionCodes) {
- labels.add(code + ": " + LocaleManager.getRegionName(code)); //$NON-NLS-1$
- }
- Collections.sort(labels);
- labels.add(0, "Any");
- mRegionCombo.setItems(labels.toArray(new String[labels.size()]));
- mRegionCombo.select(0);
- }
-
- /** React to resizing by distributing the space evenly between the last two columns */
- private void updateColumnWidths() {
- Rectangle r = mTable.getClientArea();
- int availableWidth = r.width;
- // Distribute all available space to the last two columns
- int columnCount = mTable.getColumnCount();
- for (int i = 0; i < columnCount; i++) {
- TableColumn column = mTable.getColumn(i);
- availableWidth -= column.getWidth();
- }
- if (availableWidth != 0) {
- TableColumn column = mTable.getColumn(DEFAULT_TRANSLATION_COLUMN);
- column.setWidth(column.getWidth() + availableWidth / 2);
- column = mTable.getColumn(NEW_TRANSLATION_COLUMN);
- column.setWidth(column.getWidth() + availableWidth / 2 + availableWidth % 2);
- }
- }
-
- @Override
- protected void createButtonsForButtonBar(Composite parent) {
- mOkButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
- // Don't make the OK button default as in most dialogs, since when you press
- // Return thinking you might edit a value it dismisses the dialog instead
- false);
- createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
- mOkButton.setEnabled(false);
-
- validatePage();
- }
-
- /**
- * Return the initial size of the dialog.
- */
- @Override
- protected Point getInitialSize() {
- return new Point(800, 600);
- }
-
- private void updateTarget() {
- if (mSelectedLanguage == null) {
- mTarget = null;
- mFile.setText("");
- } else {
- String folder = FD_RES + '/' + FD_RES_VALUES + RES_QUALIFIER_SEP + mSelectedLanguage;
- if (mSelectedRegion != null) {
- folder = folder + RES_QUALIFIER_SEP + 'r' + mSelectedRegion;
- }
- mTarget = folder + "/strings.xml"; //$NON-NLS-1$
- mFile.setText(String.format("Creating %1$s", mTarget));
- }
- }
-
- private void updateFlag() {
- if (mSelectedLanguage == null) {
- // Nothing selected
- ((GridData) mFlag.getLayoutData()).exclude = true;
- } else {
- FlagManager manager = FlagManager.get();
- Image flag = manager.getFlag(mSelectedLanguage, mSelectedRegion);
- if (flag != null) {
- ((GridData) mFlag.getLayoutData()).exclude = false;
- mFlag.setImage(flag);
- }
- }
-
- mFlag.getParent().layout(true);
- mFlag.getParent().redraw();
- }
-
- /** Actually create the new translation file and write it to disk */
- private void createTranslation() {
- List<String> keys = new ArrayList<String>(mTranslations.keySet());
- Collections.sort(keys);
-
- StringBuilder sb = new StringBuilder(keys.size() * 120);
- sb.append("<resources>\n\n"); //$NON-NLS-1$
- for (String key : keys) {
- String value = mTranslations.get(key);
- if (value == null || value.trim().isEmpty()) {
- continue;
- }
- sb.append(" <string name=\""); //$NON-NLS-1$
- sb.append(key);
- sb.append("\">"); //$NON-NLS-1$
- sb.append(ValueXmlHelper.escapeResourceString(value));
- sb.append("</string>\n"); //$NON-NLS-1$
- }
- sb.append("\n</resources>"); //$NON-NLS-1$
-
- IFile file = mProject.getFile(mTarget);
-
- try {
- IContainer parent = file.getParent();
- AdtUtils.ensureExists(parent);
- InputStream source = new ByteArrayInputStream(sb.toString().getBytes(Charsets.UTF_8));
- file.create(source, true, new NullProgressMonitor());
- AdtPlugin.openFile(file, null, true /*showEditorTab*/);
-
- // Ensure that the project resources updates itself to notice the new language.
- // In theory, this shouldn't be necessary.
- ResourceManager manager = ResourceManager.getInstance();
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- IFolder folder = root.getFolder(parent.getFullPath());
- manager.getResourceFolder(folder);
- RenderPreviewManager.bumpRevision();
- } catch (CoreException e) {
- AdtPlugin.log(e, null);
- }
- }
-
- private void validatePage() {
- if (mOkButton == null) { // Early initialization
- return;
- }
-
- String message = null;
-
- if (mSelectedLanguage == null) {
- message = "Select a language";
- } else if (mExistingLanguages.contains(mSelectedLanguage)) {
- if (mSelectedRegion == null) {
- message = String.format("%1$s is already translated in this project",
- LocaleManager.getLanguageName(mSelectedLanguage));
- } else {
- ResourceManager manager = ResourceManager.getInstance();
- ProjectResources resources = manager.getProjectResources(mProject);
- SortedSet<String> regions = resources.getRegions(mSelectedLanguage);
- if (regions.contains(mSelectedRegion)) {
- message = String.format("%1$s (%2$s) is already translated in this project",
- LocaleManager.getLanguageName(mSelectedLanguage),
- LocaleManager.getRegionName(mSelectedRegion));
- }
- }
- } else {
- // Require all strings to be translated? No, some of these may not
- // be translatable (e.g. translatable=false, defined in donottranslate.xml, etc.)
- //int missing = mTable.getItemCount() - mTranslations.values().size();
- //if (missing > 0) {
- // message = String.format("Missing %1$d translations", missing);
- //}
- }
-
- boolean valid = message == null;
- mTable.setEnabled(message == null);
- mOkButton.setEnabled(valid);
- showError(message);
- }
-
- private void showError(String error) {
- GridData data = (GridData) mErrorPanel.getLayoutData();
-
- boolean show = error != null;
- if (show == data.exclude) {
- if (show) {
- if (mErrorLabel == null) {
- mErrorPanel.setLayout(new GridLayout(2, false));
- IWorkbench workbench = PlatformUI.getWorkbench();
- ISharedImages sharedImages = workbench.getSharedImages();
- String iconName = ISharedImages.IMG_OBJS_ERROR_TSK;
- Image image = sharedImages.getImage(iconName);
- @SuppressWarnings("unused")
- ImageControl icon = new ImageControl(mErrorPanel, SWT.NONE, image);
-
- mErrorLabel = new Label(mErrorPanel, SWT.NONE);
- mErrorLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
- 1, 1));
- }
- mErrorLabel.setText(error);
- }
- data.exclude = !show;
- mErrorPanel.getParent().layout(true);
- }
- }
-
- @Override
- protected void okPressed() {
- mTableViewer.applyEditorValue();
-
- super.okPressed();
- createTranslation();
- }
-
- // ---- Implements ControlListener ----
-
- @Override
- public void controlMoved(ControlEvent e) {
- }
-
- @Override
- public void controlResized(ControlEvent e) {
- if (mIgnore) {
- return;
- }
-
- updateColumnWidths();
- }
-
- // ---- Implements SelectionListener ----
-
- @Override
- public void widgetSelected(SelectionEvent e) {
- if (mIgnore) {
- return;
- }
-
- Object source = e.getSource();
- if (source == mLanguageCombo) {
- try {
- mIgnore = true;
- mRegionCombo.select(0);
- mSelectedRegion = null;
- } finally {
- mIgnore = false;
- }
-
- int languageIndex = mLanguageCombo.getSelectionIndex();
- if (languageIndex == 0) {
- mSelectedLanguage = null;
- mRegionCombo.setEnabled(false);
- } else {
- // This depends on the label format
- mSelectedLanguage = mLanguageCombo.getItem(languageIndex).substring(0, 2);
- mRegionCombo.setEnabled(true);
- }
-
- updateTarget();
- updateFlag();
- } else if (source == mRegionCombo) {
- int regionIndex = mRegionCombo.getSelectionIndex();
- if (regionIndex == 0) {
- mSelectedRegion = null;
- } else {
- mSelectedRegion = mRegionCombo.getItem(regionIndex).substring(0, 2);
- }
-
- updateTarget();
- updateFlag();
- }
-
- try {
- mIgnore = true;
- validatePage();
- } finally {
- mIgnore = false;
- }
- }
-
- @Override
- public void widgetDefaultSelected(SelectionEvent e) {
- }
-
- // ---- TraverseListener ----
-
- @Override
- public void keyTraversed(TraverseEvent e) {
- // If you press Return and we're not cell editing, start editing the current row
- if (e.detail == SWT.TRAVERSE_RETURN && !mTableViewer.isCellEditorActive()) {
- int index = mTable.getSelectionIndex();
- if (index != -1) {
- Object next = mTable.getItem(index).getData();
- mTableViewer.editElement(next, NEW_TRANSLATION_COLUMN);
- }
- }
- }
-
- /** Editing support for the translation column */
- private class TranslationEditingSupport extends EditingSupport {
- /**
- * When true, setValue is being called as part of a default action
- * (e.g. Return), not due to focus loss
- */
- private boolean mDefaultAction;
-
- private TranslationEditingSupport(ColumnViewer viewer) {
- super(viewer);
- }
-
- @Override
- protected void setValue(Object element, Object value) {
- ResourceItem item = (ResourceItem) element;
- mTranslations.put(item.getName(), value.toString());
- mTableViewer.update(element, null);
- validatePage();
-
- // If the user is pressing Return to finish editing a value (which is
- // not the only way this method can get called - for example, if you click
- // outside the cell while editing, the focus loss will also result in
- // this method getting called), then mDefaultAction is true, and we automatically
- // start editing the next row.
- if (mDefaultAction) {
- mTable.getDisplay().asyncExec(new Runnable() {
- @Override
- public void run() {
- if (!mTable.isDisposed() && !mTableViewer.isCellEditorActive()) {
- int index = mTable.getSelectionIndex();
- if (index != -1 && index < mTable.getItemCount() - 1) {
- Object next = mTable.getItem(index + 1).getData();
- mTableViewer.editElement(next, NEW_TRANSLATION_COLUMN);
- }
- }
- }
- });
- }
- }
-
- @Override
- protected Object getValue(Object element) {
- ResourceItem item = (ResourceItem) element;
- String value = mTranslations.get(item.getName());
- if (value == null) {
- return "";
- }
- return value;
- }
-
- @Override
- protected CellEditor getCellEditor(Object element) {
- return new TextCellEditor(mTable) {
- @Override
- protected void handleDefaultSelection(SelectionEvent event) {
- try {
- mDefaultAction = true;
- super.handleDefaultSelection(event);
- } finally {
- mDefaultAction = false;
- }
- }
- };
- }
-
- @Override
- protected boolean canEdit(Object element) {
- return true;
- }
- }
-
- private class MyTableViewer extends TableViewer {
- public MyTableViewer(Composite parent, int style) {
- super(parent, style);
- }
-
- // Make this public so we can call it to ensure values are applied before the dialog
- // is dismissed in {@link #okPressed}
- @Override
- public void applyEditorValue() {
- super.applyEditorValue();
- }
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/ChooseConfigurationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/ChooseConfigurationPage.java
deleted file mode 100644
index 1d6467e64..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/ChooseConfigurationPage.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2011 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.newxmlfile;
-
-import com.android.SdkConstants;
-import com.android.ide.common.resources.configuration.ResourceQualifier;
-import com.android.ide.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector;
-import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.ConfigurationState;
-import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.SelectorMode;
-import com.android.ide.eclipse.adt.internal.wizards.newxmlfile.NewXmlFileCreationPage.TypeInfo;
-import com.android.ide.eclipse.adt.internal.wizards.newxmlfile.NewXmlFileWizard.Values;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.jface.dialogs.IMessageProvider;
-import org.eclipse.jface.wizard.IWizardPage;
-import org.eclipse.jface.wizard.WizardPage;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-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;
-
-/**
- * Second page of the {@link NewXmlFileWizard}.
- * <p>
- * This page is used for choosing the current configuration or specific resource
- * folder.
- */
-public class ChooseConfigurationPage extends WizardPage {
- private Values mValues;
- private Text mWsFolderPathTextField;
- private ConfigurationSelector mConfigSelector;
- private boolean mInternalWsFolderPathUpdate;
- private boolean mInternalConfigSelectorUpdate;
-
- /** Absolute destination folder root, e.g. "/res/" */
- static final String RES_FOLDER_ABS = AdtConstants.WS_RESOURCES + AdtConstants.WS_SEP;
- /** Relative destination folder root, e.g. "res/" */
- static final String RES_FOLDER_REL = SdkConstants.FD_RESOURCES + AdtConstants.WS_SEP;
-
- /**
- * Create the wizard.
- *
- * @param values value object holding current wizard state
- */
- public ChooseConfigurationPage(NewXmlFileWizard.Values values) {
- super("chooseConfig");
- mValues = values;
- setTitle("Choose Configuration Folder");
- }
-
- @Override
- public void setVisible(boolean visible) {
- super.setVisible(visible);
- if (visible) {
- if (mValues.folderPath != null) {
- mWsFolderPathTextField.setText(mValues.folderPath);
- }
- }
- }
-
- @Override
- public void createControl(Composite parent) {
- // This UI is maintained with WindowBuilder.
-
- Composite composite = new Composite(parent, SWT.NULL);
- composite.setLayout(new GridLayout(2, false /* makeColumnsEqualWidth */));
- composite.setLayoutData(new GridData(GridData.FILL_BOTH));
-
- // label before configuration selector
- Label label = new Label(composite, SWT.NONE);
- label.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
- label.setText("Optional: Choose a specific configuration to limit the XML to:");
-
- // configuration selector
- mConfigSelector = new ConfigurationSelector(composite, SelectorMode.DEFAULT);
- GridData gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL);
- gd.verticalAlignment = SWT.FILL;
- gd.horizontalAlignment = SWT.FILL;
- gd.horizontalSpan = 2;
- gd.heightHint = ConfigurationSelector.HEIGHT_HINT;
- mConfigSelector.setLayoutData(gd);
- mConfigSelector.setOnChangeListener(new ConfigurationChangeListener());
-
- // Folder name: [text]
- String tooltip = "The folder where the file will be generated, relative to the project.";
-
- Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
- GridData gdSeparator = new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1);
- gdSeparator.heightHint = 10;
- separator.setLayoutData(gdSeparator);
- Label folderLabel = new Label(composite, SWT.NONE);
- folderLabel.setText("Folder:");
- folderLabel.setToolTipText(tooltip);
-
- mWsFolderPathTextField = new Text(composite, SWT.BORDER);
- mWsFolderPathTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mWsFolderPathTextField.setToolTipText(tooltip);
- mWsFolderPathTextField.addModifyListener(new ModifyListener() {
- @Override
- public void modifyText(ModifyEvent e) {
- onWsFolderPathUpdated();
- }
- });
-
- setControl(composite);
-
- mConfigSelector.setConfiguration(mValues.configuration);
- }
-
- /**
- * Callback called when the Folder text field is changed, either programmatically
- * or by the user.
- */
- private void onWsFolderPathUpdated() {
- if (mInternalWsFolderPathUpdate) {
- return;
- }
-
- String wsFolderPath = mWsFolderPathTextField.getText();
-
- // This is a custom path, we need to sanitize it.
- // First it should start with "/res/". Then we need to make sure there are no
- // relative paths, things like "../" or "./" or even "//".
- wsFolderPath = wsFolderPath.replaceAll("/+\\.\\./+|/+\\./+|//+|\\\\+|^/+", "/"); //$NON-NLS-1$ //$NON-NLS-2$
- wsFolderPath = wsFolderPath.replaceAll("^\\.\\./+|^\\./+", ""); //$NON-NLS-1$ //$NON-NLS-2$
- wsFolderPath = wsFolderPath.replaceAll("/+\\.\\.$|/+\\.$|/+$", ""); //$NON-NLS-1$ //$NON-NLS-2$
-
- // We get "res/foo" from selections relative to the project when we want a "/res/foo" path.
- if (wsFolderPath.startsWith(RES_FOLDER_REL)) {
- wsFolderPath = RES_FOLDER_ABS + wsFolderPath.substring(RES_FOLDER_REL.length());
-
- mInternalWsFolderPathUpdate = true;
- mWsFolderPathTextField.setText(wsFolderPath);
- mInternalWsFolderPathUpdate = false;
- }
-
- mValues.folderPath = wsFolderPath;
-
- if (wsFolderPath.startsWith(RES_FOLDER_ABS)) {
- wsFolderPath = wsFolderPath.substring(RES_FOLDER_ABS.length());
-
- int pos = wsFolderPath.indexOf(AdtConstants.WS_SEP_CHAR);
- if (pos >= 0) {
- wsFolderPath = wsFolderPath.substring(0, pos);
- }
-
- String[] folderSegments = wsFolderPath.split(SdkConstants.RES_QUALIFIER_SEP);
-
- if (folderSegments.length > 0) {
- String folderName = folderSegments[0];
-
- // update config selector
- mInternalConfigSelectorUpdate = true;
- mConfigSelector.setConfiguration(folderSegments);
- mInternalConfigSelectorUpdate = false;
-
- IWizardPage previous = ((NewXmlFileWizard) getWizard()).getPreviousPage(this);
- if (previous instanceof NewXmlFileCreationPage) {
- NewXmlFileCreationPage p = (NewXmlFileCreationPage) previous;
- p.selectTypeFromFolder(folderName);
- }
- }
- }
-
- validatePage();
- }
-
- /**
- * Callback called when the configuration has changed in the {@link ConfigurationSelector}.
- */
- private class ConfigurationChangeListener implements Runnable {
- @Override
- public void run() {
- if (mInternalConfigSelectorUpdate) {
- return;
- }
-
- resetFolderPath(true /*validate*/);
- }
- }
-
- /**
- * Reset the current Folder path based on the UI selection
- * @param validate if true, force a call to {@link #validatePage()}.
- */
- private void resetFolderPath(boolean validate) {
- TypeInfo type = mValues.type;
- if (type != null) {
- mConfigSelector.getConfiguration(mValues.configuration);
- StringBuilder sb = new StringBuilder(RES_FOLDER_ABS);
- sb.append(mValues.configuration.getFolderName(type.getResFolderType()));
-
- mInternalWsFolderPathUpdate = true;
- String newPath = sb.toString();
- mValues.folderPath = newPath;
- mWsFolderPathTextField.setText(newPath);
- mInternalWsFolderPathUpdate = false;
-
- if (validate) {
- validatePage();
- }
- }
- }
-
- /**
- * Returns the destination folder path relative to the project or an empty string.
- *
- * @return the currently edited folder
- */
- public String getWsFolderPath() {
- return mWsFolderPathTextField == null ? "" : mWsFolderPathTextField.getText(); //$NON-NLS-1$
- }
-
- /**
- * Validates the fields, displays errors and warnings.
- * Enables the finish button if there are no errors.
- */
- private void validatePage() {
- String error = null;
- String warning = null;
-
- // -- validate folder configuration
- if (error == null) {
- ConfigurationState state = mConfigSelector.getState();
- if (state == ConfigurationState.INVALID_CONFIG) {
- ResourceQualifier qual = mConfigSelector.getInvalidQualifier();
- if (qual != null) {
- error =
- String.format("The qualifier '%1$s' is invalid in the folder configuration.",
- qual.getName());
- }
- } else if (state == ConfigurationState.REGION_WITHOUT_LANGUAGE) {
- error = "The Region qualifier requires the Language qualifier.";
- }
- }
-
- // -- validate generated path
- if (error == null) {
- String wsFolderPath = getWsFolderPath();
- if (!wsFolderPath.startsWith(RES_FOLDER_ABS)) {
- error = String.format("Target folder must start with %1$s.", RES_FOLDER_ABS);
- }
- }
-
- // -- validate destination file doesn't exist
- if (error == null) {
- IFile file = mValues.getDestinationFile();
- if (file != null && file.exists()) {
- warning = "The destination file already exists";
- }
- }
-
- // -- update UI & enable finish if there's no error
- setPageComplete(error == null);
- if (error != null) {
- setMessage(error, IMessageProvider.ERROR);
- } else if (warning != null) {
- setMessage(warning, IMessageProvider.WARNING);
- } else {
- setErrorMessage(null);
- setMessage(null);
- }
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java
deleted file mode 100644
index 28fb8c032..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileCreationPage.java
+++ /dev/null
@@ -1,1163 +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.internal.wizards.newxmlfile;
-
-import static com.android.SdkConstants.DOT_XML;
-import static com.android.SdkConstants.HORIZONTAL_SCROLL_VIEW;
-import static com.android.SdkConstants.LINEAR_LAYOUT;
-import static com.android.SdkConstants.RES_QUALIFIER_SEP;
-import static com.android.SdkConstants.SCROLL_VIEW;
-import static com.android.SdkConstants.VALUE_FILL_PARENT;
-import static com.android.SdkConstants.VALUE_MATCH_PARENT;
-import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP_CHAR;
-import static com.android.ide.eclipse.adt.internal.wizards.newxmlfile.ChooseConfigurationPage.RES_FOLDER_ABS;
-
-import com.android.SdkConstants;
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-import com.android.ide.common.resources.configuration.ResourceQualifier;
-import com.android.ide.eclipse.adt.AdtConstants;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.AdtUtils;
-import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
-import com.android.ide.eclipse.adt.internal.editors.IconFactory;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.DocumentDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
-import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper;
-import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper.ProjectCombo;
-import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator;
-import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk.TargetChangeListener;
-import com.android.resources.ResourceFolderType;
-import com.android.sdklib.IAndroidTarget;
-import com.android.utils.Pair;
-import com.android.utils.SdkUtils;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jface.dialogs.IMessageProvider;
-import org.eclipse.jface.viewers.ArrayContentProvider;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.IBaseLabelProvider;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.wizard.WizardPage;
-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.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.part.FileEditorInput;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * This is the first page of the {@link NewXmlFileWizard} which provides the ability to create
- * skeleton XML resources files for Android projects.
- * <p/>
- * This page is used to select the project, resource type and file name.
- */
-class NewXmlFileCreationPage extends WizardPage {
-
- @Override
- public void setVisible(boolean visible) {
- super.setVisible(visible);
- // Ensure the initial focus is in the Name field; you usually don't need
- // to edit the default text field (the project name)
- if (visible && mFileNameTextField != null) {
- mFileNameTextField.setFocus();
- }
-
- validatePage();
- }
-
- /**
- * Information on one type of resource that can be created (e.g. menu, pref, layout, etc.)
- */
- static class TypeInfo {
- private final String mUiName;
- private final ResourceFolderType mResFolderType;
- private final String mTooltip;
- private final Object mRootSeed;
- private ArrayList<String> mRoots = new ArrayList<String>();
- private final String mXmlns;
- private final String mDefaultAttrs;
- private final String mDefaultRoot;
- private final int mTargetApiLevel;
-
- public TypeInfo(String uiName,
- String tooltip,
- ResourceFolderType resFolderType,
- Object rootSeed,
- String defaultRoot,
- String xmlns,
- String defaultAttrs,
- int targetApiLevel) {
- mUiName = uiName;
- mResFolderType = resFolderType;
- mTooltip = tooltip;
- mRootSeed = rootSeed;
- mDefaultRoot = defaultRoot;
- mXmlns = xmlns;
- mDefaultAttrs = defaultAttrs;
- mTargetApiLevel = targetApiLevel;
- }
-
- /** Returns the UI name for the resource type. Unique. Never null. */
- String getUiName() {
- return mUiName;
- }
-
- /** Returns the tooltip for the resource type. Can be null. */
- String getTooltip() {
- return mTooltip;
- }
-
- /**
- * Returns the name of the {@link ResourceFolderType}.
- * Never null but not necessarily unique,
- * e.g. two types use {@link ResourceFolderType#XML}.
- */
- String getResFolderName() {
- return mResFolderType.getName();
- }
-
- /**
- * Returns the matching {@link ResourceFolderType}.
- * Never null but not necessarily unique,
- * e.g. two types use {@link ResourceFolderType#XML}.
- */
- ResourceFolderType getResFolderType() {
- return mResFolderType;
- }
-
- /**
- * Returns the seed used to fill the root element values.
- * The seed might be either a String, a String array, an {@link ElementDescriptor},
- * a {@link DocumentDescriptor} or null.
- */
- Object getRootSeed() {
- return mRootSeed;
- }
-
- /**
- * Returns the default root element that should be selected by default. Can be
- * null.
- *
- * @param project the associated project, or null if not known
- */
- String getDefaultRoot(IProject project) {
- return mDefaultRoot;
- }
-
- /**
- * Returns the list of all possible root elements for the resource type.
- * This can be an empty ArrayList but not null.
- * <p/>
- * TODO: the root list SHOULD depend on the currently selected project, to include
- * custom classes.
- */
- ArrayList<String> getRoots() {
- return mRoots;
- }
-
- /**
- * If the generated resource XML file requires an "android" XMLNS, this should be set
- * to {@link SdkConstants#NS_RESOURCES}. When it is null, no XMLNS is generated.
- */
- String getXmlns() {
- return mXmlns;
- }
-
- /**
- * When not null, this represent extra attributes that must be specified in the
- * root element of the generated XML file. When null, no extra attributes are inserted.
- *
- * @param project the project to get the attributes for
- * @param root the selected root element string, never null
- */
- String getDefaultAttrs(IProject project, String root) {
- return mDefaultAttrs;
- }
-
- /**
- * When not null, represents an extra string that should be written inside
- * the element when constructed
- *
- * @param project the project to get the child content for
- * @param root the chosen root element
- * @return a string to be written inside the root element, or null if nothing
- */
- String getChild(IProject project, String root) {
- return null;
- }
-
- /**
- * The minimum API level required by the current SDK target to support this feature.
- *
- * @return the minimum API level
- */
- public int getTargetApiLevel() {
- return mTargetApiLevel;
- }
- }
-
- /**
- * TypeInfo, information for each "type" of file that can be created.
- */
- private static final TypeInfo[] sTypes = {
- new TypeInfo(
- "Layout", // UI name
- "An XML file that describes a screen layout.", // tooltip
- ResourceFolderType.LAYOUT, // folder type
- AndroidTargetData.DESCRIPTOR_LAYOUT, // root seed
- LINEAR_LAYOUT, // default root
- SdkConstants.NS_RESOURCES, // xmlns
- "", // not used, see below
- 1 // target API level
- ) {
-
- @Override
- String getDefaultRoot(IProject project) {
- // TODO: Use GridLayout by default for new SDKs
- // (when we've ironed out all the usability issues)
- //Sdk currentSdk = Sdk.getCurrent();
- //if (project != null && currentSdk != null) {
- // IAndroidTarget target = currentSdk.getTarget(project);
- // // fill_parent was renamed match_parent in API level 8
- // if (target != null && target.getVersion().getApiLevel() >= 13) {
- // return GRID_LAYOUT;
- // }
- //}
-
- return LINEAR_LAYOUT;
- };
-
- // The default attributes must be determined dynamically since whether
- // we use match_parent or fill_parent depends on the API level of the
- // project
- @Override
- String getDefaultAttrs(IProject project, String root) {
- Sdk currentSdk = Sdk.getCurrent();
- String fill = VALUE_FILL_PARENT;
- if (currentSdk != null) {
- IAndroidTarget target = currentSdk.getTarget(project);
- // fill_parent was renamed match_parent in API level 8
- if (target != null && target.getVersion().getApiLevel() >= 8) {
- fill = VALUE_MATCH_PARENT;
- }
- }
-
- // Only set "vertical" orientation of LinearLayouts by default;
- // for GridLayouts for example we want to rely on the real default
- // of the layout
- String size = String.format(
- "android:layout_width=\"%1$s\"\n" //$NON-NLS-1$
- + "android:layout_height=\"%2$s\"", //$NON-NLS-1$
- fill, fill);
- if (LINEAR_LAYOUT.equals(root)) {
- return "android:orientation=\"vertical\"\n" + size; //$NON-NLS-1$
- } else {
- return size;
- }
- }
-
- @Override
- String getChild(IProject project, String root) {
- // Create vertical linear layouts inside new scroll views
- if (SCROLL_VIEW.equals(root) || HORIZONTAL_SCROLL_VIEW.equals(root)) {
- return " <LinearLayout " //$NON-NLS-1$
- + getDefaultAttrs(project, root).replace('\n', ' ')
- + " android:orientation=\"vertical\"" //$NON-NLS-1$
- + "></LinearLayout>\n"; //$NON-NLS-1$
- }
- return null;
- }
- },
- new TypeInfo("Values", // UI name
- "An XML file with simple values: colors, strings, dimensions, etc.", // tooltip
- ResourceFolderType.VALUES, // folder type
- SdkConstants.TAG_RESOURCES, // root seed
- null, // default root
- null, // xmlns
- null, // default attributes
- 1 // target API level
- ),
- new TypeInfo("Drawable", // UI name
- "An XML file that describes a drawable.", // tooltip
- ResourceFolderType.DRAWABLE, // folder type
- AndroidTargetData.DESCRIPTOR_DRAWABLE, // root seed
- null, // default root
- SdkConstants.NS_RESOURCES, // xmlns
- null, // default attributes
- 1 // target API level
- ),
- new TypeInfo("Menu", // UI name
- "An XML file that describes an menu.", // tooltip
- ResourceFolderType.MENU, // folder type
- SdkConstants.TAG_MENU, // root seed
- null, // default root
- SdkConstants.NS_RESOURCES, // xmlns
- null, // default attributes
- 1 // target API level
- ),
- new TypeInfo("Color List", // UI name
- "An XML file that describes a color state list.", // tooltip
- ResourceFolderType.COLOR, // folder type
- AndroidTargetData.DESCRIPTOR_COLOR, // root seed
- "selector", //$NON-NLS-1$ // default root
- SdkConstants.NS_RESOURCES, // xmlns
- null, // default attributes
- 1 // target API level
- ),
- new TypeInfo("Property Animation", // UI name
- "An XML file that describes a property animation", // tooltip
- ResourceFolderType.ANIMATOR, // folder type
- AndroidTargetData.DESCRIPTOR_ANIMATOR, // root seed
- "set", //$NON-NLS-1$ // default root
- SdkConstants.NS_RESOURCES, // xmlns
- null, // default attributes
- 11 // target API level
- ),
- new TypeInfo("Tween Animation", // UI name
- "An XML file that describes a tween animation.", // tooltip
- ResourceFolderType.ANIM, // folder type
- AndroidTargetData.DESCRIPTOR_ANIM, // root seed
- "set", //$NON-NLS-1$ // default root
- null, // xmlns
- null, // default attributes
- 1 // target API level
- ),
- new TypeInfo("AppWidget Provider", // UI name
- "An XML file that describes a widget provider.", // tooltip
- ResourceFolderType.XML, // folder type
- AndroidTargetData.DESCRIPTOR_APPWIDGET_PROVIDER, // root seed
- null, // default root
- SdkConstants.NS_RESOURCES, // xmlns
- null, // default attributes
- 3 // target API level
- ),
- new TypeInfo("Preference", // UI name
- "An XML file that describes preferences.", // tooltip
- ResourceFolderType.XML, // folder type
- AndroidTargetData.DESCRIPTOR_PREFERENCES, // root seed
- SdkConstants.CLASS_NAME_PREFERENCE_SCREEN, // default root
- SdkConstants.NS_RESOURCES, // xmlns
- null, // default attributes
- 1 // target API level
- ),
- new TypeInfo("Searchable", // UI name
- "An XML file that describes a searchable.", // tooltip
- ResourceFolderType.XML, // folder type
- AndroidTargetData.DESCRIPTOR_SEARCHABLE, // root seed
- null, // default root
- SdkConstants.NS_RESOURCES, // xmlns
- null, // default attributes
- 1 // target API level
- ),
- // Still missing: Interpolator, Raw and Mipmap. Raw should probably never be in
- // this menu since it's not often used for creating XML files.
- };
-
- private NewXmlFileWizard.Values mValues;
- private ProjectCombo mProjectButton;
- private Text mFileNameTextField;
- private Combo mTypeCombo;
- private IStructuredSelection mInitialSelection;
- private ResourceFolderType mInitialFolderType;
- private boolean mInternalTypeUpdate;
- private TargetChangeListener mSdkTargetChangeListener;
- private Table mRootTable;
- private TableViewer mRootTableViewer;
-
- // --- UI creation ---
-
- /**
- * Constructs a new {@link NewXmlFileCreationPage}.
- * <p/>
- * Called by {@link NewXmlFileWizard#createMainPage}.
- */
- protected NewXmlFileCreationPage(String pageName, NewXmlFileWizard.Values values) {
- super(pageName);
- mValues = values;
- setPageComplete(false);
- }
-
- public void setInitialSelection(IStructuredSelection initialSelection) {
- mInitialSelection = initialSelection;
- }
-
- public void setInitialFolderType(ResourceFolderType initialType) {
- mInitialFolderType = initialType;
- }
-
- /**
- * Called by the parent Wizard to create the UI for this Wizard Page.
- *
- * {@inheritDoc}
- *
- * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
- */
- @Override
- @SuppressWarnings("unused") // SWT constructors have side effects, they aren't unused
- public void createControl(Composite parent) {
- // This UI is maintained with WindowBuilder.
-
- Composite composite = new Composite(parent, SWT.NULL);
- composite.setLayout(new GridLayout(2, false /*makeColumnsEqualWidth*/));
- composite.setLayoutData(new GridData(GridData.FILL_BOTH));
-
- // label before type radios
- Label typeLabel = new Label(composite, SWT.NONE);
- typeLabel.setText("Resource Type:");
-
- mTypeCombo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
- mTypeCombo.setToolTipText("What type of resource would you like to create?");
- mTypeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- if (mInitialFolderType != null) {
- mTypeCombo.setEnabled(false);
- }
- mTypeCombo.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- TypeInfo type = getSelectedType();
- if (type != null) {
- onSelectType(type);
- }
- }
- });
-
- // separator
- Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
- GridData gd2 = new GridData(GridData.GRAB_HORIZONTAL);
- gd2.horizontalAlignment = SWT.FILL;
- gd2.horizontalSpan = 2;
- separator.setLayoutData(gd2);
-
- // Project: [button]
- String tooltip = "The Android Project where the new resource file will be created.";
- Label projectLabel = new Label(composite, SWT.NONE);
- projectLabel.setText("Project:");
- projectLabel.setToolTipText(tooltip);
-
- ProjectChooserHelper helper =
- new ProjectChooserHelper(getShell(), null /* filter */);
-
- mProjectButton = new ProjectCombo(helper, composite, mValues.project);
- mProjectButton.setToolTipText(tooltip);
- mProjectButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mProjectButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- IProject project = mProjectButton.getSelectedProject();
- if (project != mValues.project) {
- changeProject(project);
- }
- };
- });
-
- // Filename: [text]
- Label fileLabel = new Label(composite, SWT.NONE);
- fileLabel.setText("File:");
- fileLabel.setToolTipText("The name of the resource file to create.");
-
- mFileNameTextField = new Text(composite, SWT.BORDER);
- mFileNameTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mFileNameTextField.setToolTipText(tooltip);
- mFileNameTextField.addModifyListener(new ModifyListener() {
- @Override
- public void modifyText(ModifyEvent e) {
- mValues.name = mFileNameTextField.getText();
- validatePage();
- }
- });
-
- // separator
- Label rootSeparator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
- GridData gd = new GridData(GridData.GRAB_HORIZONTAL);
- gd.horizontalAlignment = SWT.FILL;
- gd.horizontalSpan = 2;
- rootSeparator.setLayoutData(gd);
-
- // Root Element:
- // [TableViewer]
- Label rootLabel = new Label(composite, SWT.NONE);
- rootLabel.setText("Root Element:");
- new Label(composite, SWT.NONE);
-
- mRootTableViewer = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION);
- mRootTable = mRootTableViewer.getTable();
- GridData tableGridData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
- tableGridData.heightHint = 200;
- mRootTable.setLayoutData(tableGridData);
-
- setControl(composite);
-
- // Update state the first time
- setErrorMessage(null);
- setMessage(null);
-
- initializeFromSelection(mInitialSelection);
- updateAvailableTypes();
- initializeFromFixedType();
- initializeRootValues();
- installTargetChangeListener();
-
- initialSelectType();
- validatePage();
- }
-
- private void initialSelectType() {
- TypeInfo[] types = (TypeInfo[]) mTypeCombo.getData();
- int typeIndex = getTypeComboIndex(mValues.type);
- if (typeIndex == -1) {
- typeIndex = 0;
- } else {
- assert mValues.type == types[typeIndex];
- }
- mTypeCombo.select(typeIndex);
- onSelectType(types[typeIndex]);
- updateRootCombo(types[typeIndex]);
- }
-
- private void installTargetChangeListener() {
- mSdkTargetChangeListener = new TargetChangeListener() {
- @Override
- public IProject getProject() {
- return mValues.project;
- }
-
- @Override
- public void reload() {
- if (mValues.project != null) {
- changeProject(mValues.project);
- }
- }
- };
-
- AdtPlugin.getDefault().addTargetListener(mSdkTargetChangeListener);
- }
-
- @Override
- public void dispose() {
-
- if (mSdkTargetChangeListener != null) {
- AdtPlugin.getDefault().removeTargetListener(mSdkTargetChangeListener);
- mSdkTargetChangeListener = null;
- }
-
- super.dispose();
- }
-
- /**
- * Returns the selected root element string, if any.
- *
- * @return The selected root element string or null.
- */
- public String getRootElement() {
- int index = mRootTable.getSelectionIndex();
- if (index >= 0) {
- Object[] roots = (Object[]) mRootTableViewer.getInput();
- return roots[index].toString();
- }
- return null;
- }
-
- /**
- * Called by {@link NewXmlFileWizard} to initialize the page with the selection
- * received by the wizard -- typically the current user workbench selection.
- * <p/>
- * Things we expect to find out from the selection:
- * <ul>
- * <li>The project name, valid if it's an android nature.</li>
- * <li>The current folder, valid if it's a folder under /res</li>
- * <li>An existing filename, in which case the user will be asked whether to override it.</li>
- * </ul>
- * <p/>
- * The selection can also be set to a {@link Pair} of {@link IProject} and a workspace
- * resource path (where the resource path does not have to exist yet, such as res/anim/).
- *
- * @param selection The selection when the wizard was initiated.
- */
- private boolean initializeFromSelection(IStructuredSelection selection) {
- if (selection == null) {
- return false;
- }
-
- // Find the best match in the element list. In case there are multiple selected elements
- // select the one that provides the most information and assign them a score,
- // e.g. project=1 + folder=2 + file=4.
- IProject targetProject = null;
- String targetWsFolderPath = null;
- String targetFileName = null;
- int targetScore = 0;
- for (Object element : selection.toList()) {
- if (element instanceof IAdaptable) {
- IResource res = (IResource) ((IAdaptable) element).getAdapter(IResource.class);
- IProject project = res != null ? res.getProject() : null;
-
- // Is this an Android project?
- try {
- if (project == null || !project.hasNature(AdtConstants.NATURE_DEFAULT)) {
- continue;
- }
- } catch (CoreException e) {
- // checking the nature failed, ignore this resource
- continue;
- }
-
- int score = 1; // we have a valid project at least
-
- IPath wsFolderPath = null;
- String fileName = null;
- assert res != null; // Eclipse incorrectly thinks res could be null, so tell it no
- if (res.getType() == IResource.FOLDER) {
- wsFolderPath = res.getProjectRelativePath();
- } else if (res.getType() == IResource.FILE) {
- if (SdkUtils.endsWithIgnoreCase(res.getName(), DOT_XML)) {
- fileName = res.getName();
- }
- wsFolderPath = res.getParent().getProjectRelativePath();
- }
-
- // Disregard this folder selection if it doesn't point to /res/something
- if (wsFolderPath != null &&
- wsFolderPath.segmentCount() > 1 &&
- SdkConstants.FD_RESOURCES.equals(wsFolderPath.segment(0))) {
- score += 2;
- } else {
- wsFolderPath = null;
- fileName = null;
- }
-
- score += fileName != null ? 4 : 0;
-
- if (score > targetScore) {
- targetScore = score;
- targetProject = project;
- targetWsFolderPath = wsFolderPath != null ? wsFolderPath.toString() : null;
- targetFileName = fileName;
- }
- } else if (element instanceof Pair<?,?>) {
- // Pair of Project/String
- @SuppressWarnings("unchecked")
- Pair<IProject,String> pair = (Pair<IProject,String>)element;
- targetScore = 1;
- targetProject = pair.getFirst();
- targetWsFolderPath = pair.getSecond();
- targetFileName = "";
- }
- }
-
- if (targetProject == null) {
- // Try to figure out the project from the active editor
- IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- if (window != null) {
- IWorkbenchPage page = window.getActivePage();
- if (page != null) {
- IEditorPart activeEditor = page.getActiveEditor();
- if (activeEditor instanceof AndroidXmlEditor) {
- Object input = ((AndroidXmlEditor) activeEditor).getEditorInput();
- if (input instanceof FileEditorInput) {
- FileEditorInput fileInput = (FileEditorInput) input;
- targetScore = 1;
- IFile file = fileInput.getFile();
- targetProject = file.getProject();
- IPath path = file.getParent().getProjectRelativePath();
- targetWsFolderPath = path != null ? path.toString() : null;
- }
- }
- }
- }
- }
-
- if (targetProject == null) {
- // If we didn't find a default project based on the selection, check how many
- // open Android projects we can find in the current workspace. If there's only
- // one, we'll just select it by default.
- IJavaProject[] projects = AdtUtils.getOpenAndroidProjects();
- if (projects != null && projects.length == 1) {
- targetScore = 1;
- targetProject = projects[0].getProject();
- }
- }
-
- // Now set the UI accordingly
- if (targetScore > 0) {
- mValues.project = targetProject;
- mValues.folderPath = targetWsFolderPath;
- mProjectButton.setSelectedProject(targetProject);
- mFileNameTextField.setText(targetFileName != null ? targetFileName : ""); //$NON-NLS-1$
-
- // If the current selection context corresponds to a specific file type,
- // select it.
- if (targetWsFolderPath != null) {
- int pos = targetWsFolderPath.lastIndexOf(WS_SEP_CHAR);
- if (pos >= 0) {
- targetWsFolderPath = targetWsFolderPath.substring(pos + 1);
- }
- String[] folderSegments = targetWsFolderPath.split(RES_QUALIFIER_SEP);
- if (folderSegments.length > 0) {
- mValues.configuration = FolderConfiguration.getConfig(folderSegments);
- String folderName = folderSegments[0];
- selectTypeFromFolder(folderName);
- }
- }
- }
-
- return true;
- }
-
- private void initializeFromFixedType() {
- if (mInitialFolderType != null) {
- for (TypeInfo type : sTypes) {
- if (type.getResFolderType() == mInitialFolderType) {
- mValues.type = type;
- updateFolderPath(type);
- break;
- }
- }
- }
- }
-
- /**
- * Given a folder name, such as "drawable", select the corresponding type in
- * the dropdown.
- */
- void selectTypeFromFolder(String folderName) {
- List<TypeInfo> matches = new ArrayList<TypeInfo>();
- boolean selected = false;
-
- TypeInfo selectedType = getSelectedType();
- for (TypeInfo type : sTypes) {
- if (type.getResFolderName().equals(folderName)) {
- matches.add(type);
- selected |= type == selectedType;
- }
- }
-
- if (matches.size() == 1) {
- // If there's only one match, select it if it's not already selected
- if (!selected) {
- selectType(matches.get(0));
- }
- } else if (matches.size() > 1) {
- // There are multiple type candidates for this folder. This can happen
- // for /res/xml for example. Check to see if one of them is currently
- // selected. If yes, leave the selection unchanged. If not, deselect all type.
- if (!selected) {
- selectType(null);
- }
- } else {
- // Nothing valid was selected.
- selectType(null);
- }
- }
-
- /**
- * Initialize the root values of the type infos based on the current framework values.
- */
- private void initializeRootValues() {
- IProject project = mValues.project;
- for (TypeInfo type : sTypes) {
- // Clear all the roots for this type
- ArrayList<String> roots = type.getRoots();
- if (roots.size() > 0) {
- roots.clear();
- }
-
- // depending of the type of the seed, initialize the root in different ways
- Object rootSeed = type.getRootSeed();
-
- if (rootSeed instanceof String) {
- // The seed is a single string, Add it as-is.
- roots.add((String) rootSeed);
- } else if (rootSeed instanceof String[]) {
- // The seed is an array of strings. Add them as-is.
- for (String value : (String[]) rootSeed) {
- roots.add(value);
- }
- } else if (rootSeed instanceof Integer && project != 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 = null;
- AndroidTargetData data = null;
-
- target = Sdk.getCurrent().getTarget(project);
- if (target == null) {
- // A project should have a target. The target can be missing if the project
- // is an old project for which a target hasn't been affected or if the
- // target no longer exists in this SDK. Simply log the error and dismiss.
-
- AdtPlugin.log(IStatus.INFO,
- "NewXmlFile wizard: no platform target for project %s", //$NON-NLS-1$
- project.getName());
- continue;
- } else {
- data = Sdk.getCurrent().getTargetData(target);
-
- if (data == null) {
- // We should have both a target and its data.
- // However if the wizard is invoked whilst the platform is still being
- // loaded we can end up in a weird case where we have a target but it
- // doesn't have any data yet.
- // Lets log a warning and silently ignore this root.
-
- AdtPlugin.log(IStatus.INFO,
- "NewXmlFile wizard: no data for target %s, project %s", //$NON-NLS-1$
- target.getName(), project.getName());
- continue;
- }
- }
-
- IDescriptorProvider provider = data.getDescriptorProvider((Integer)rootSeed);
- ElementDescriptor descriptor = provider.getDescriptor();
- if (descriptor != null) {
- HashSet<ElementDescriptor> visited = new HashSet<ElementDescriptor>();
- initRootElementDescriptor(roots, descriptor, visited);
- }
-
- // Sort alphabetically.
- Collections.sort(roots);
- }
- }
- }
-
- /**
- * Helper method to recursively insert all XML names for the given {@link ElementDescriptor}
- * into the roots array list. Keeps track of visited nodes to avoid infinite recursion.
- * Also avoids inserting the top {@link DocumentDescriptor} which is generally synthetic
- * and not a valid root element.
- */
- private void initRootElementDescriptor(ArrayList<String> roots,
- ElementDescriptor desc, HashSet<ElementDescriptor> visited) {
- if (!(desc instanceof DocumentDescriptor)) {
- String xmlName = desc.getXmlName();
- if (xmlName != null && xmlName.length() > 0) {
- roots.add(xmlName);
- }
- }
-
- visited.add(desc);
-
- for (ElementDescriptor child : desc.getChildren()) {
- if (!visited.contains(child)) {
- initRootElementDescriptor(roots, child, visited);
- }
- }
- }
-
- /**
- * Changes mProject to the given new project and update the UI accordingly.
- * <p/>
- * Note that this does not check if the new project is the same as the current one
- * on purpose, which allows a project to be updated when its target has changed or
- * when targets are loaded in the background.
- */
- private void changeProject(IProject newProject) {
- mValues.project = newProject;
-
- // enable types based on new API level
- updateAvailableTypes();
- initialSelectType();
-
- // update the folder name based on API level
- updateFolderPath(mValues.type);
-
- // update the Type with the new descriptors.
- initializeRootValues();
-
- // update the combo
- updateRootCombo(mValues.type);
-
- validatePage();
- }
-
- private void onSelectType(TypeInfo type) {
- // Do nothing if this is an internal modification or if the widget has been
- // deselected.
- if (mInternalTypeUpdate) {
- return;
- }
-
- mValues.type = type;
-
- if (type == null) {
- return;
- }
-
- // update the combo
- updateRootCombo(type);
-
- // update the folder path
- updateFolderPath(type);
-
- validatePage();
- }
-
- /** Updates the selected type in the type dropdown control */
- private void setSelectedType(TypeInfo type) {
- TypeInfo[] types = (TypeInfo[]) mTypeCombo.getData();
- if (types != null) {
- for (int i = 0, n = types.length; i < n; i++) {
- if (types[i] == type) {
- mTypeCombo.select(i);
- break;
- }
- }
- }
- }
-
- /** Returns the selected type in the type dropdown control */
- private TypeInfo getSelectedType() {
- int index = mTypeCombo.getSelectionIndex();
- if (index != -1) {
- TypeInfo[] types = (TypeInfo[]) mTypeCombo.getData();
- return types[index];
- }
-
- return null;
- }
-
- /** Returns the selected index in the type dropdown control */
- private int getTypeComboIndex(TypeInfo type) {
- TypeInfo[] types = (TypeInfo[]) mTypeCombo.getData();
- for (int i = 0, n = types.length; i < n; i++) {
- if (type == types[i]) {
- return i;
- }
- }
-
- return -1;
- }
-
- /** Updates the folder path to reflect the given type */
- private void updateFolderPath(TypeInfo type) {
- String wsFolderPath = mValues.folderPath;
- String newPath = null;
- FolderConfiguration config = mValues.configuration;
- ResourceQualifier qual = config.getInvalidQualifier();
- if (qual == null) {
- // The configuration is valid. Reformat the folder path using the canonical
- // value from the configuration.
- newPath = RES_FOLDER_ABS + config.getFolderName(type.getResFolderType());
- } else {
- // The configuration is invalid. We still update the path but this time
- // do it manually on the string.
- if (wsFolderPath.startsWith(RES_FOLDER_ABS)) {
- wsFolderPath = wsFolderPath.replaceFirst(
- "^(" + RES_FOLDER_ABS +")[^-]*(.*)", //$NON-NLS-1$ //$NON-NLS-2$
- "\\1" + type.getResFolderName() + "\\2"); //$NON-NLS-1$ //$NON-NLS-2$
- } else {
- newPath = RES_FOLDER_ABS + config.getFolderName(type.getResFolderType());
- }
- }
-
- if (newPath != null && !newPath.equals(wsFolderPath)) {
- mValues.folderPath = newPath;
- }
- }
-
- /**
- * Helper method that fills the values of the "root element" combo box based
- * on the currently selected type radio button. Also disables the combo is there's
- * only one choice. Always select the first root element for the given type.
- *
- * @param type The currently selected {@link TypeInfo}, or null
- */
- private void updateRootCombo(TypeInfo type) {
- IBaseLabelProvider labelProvider = new ColumnLabelProvider() {
- @Override
- public Image getImage(Object element) {
- return IconFactory.getInstance().getIcon(element.toString());
- }
- };
- mRootTableViewer.setContentProvider(new ArrayContentProvider());
- mRootTableViewer.setLabelProvider(labelProvider);
-
- if (type != null) {
- // get the list of roots. The list can be empty but not null.
- ArrayList<String> roots = type.getRoots();
- mRootTableViewer.setInput(roots.toArray());
-
- int index = 0; // default is to select the first one
- String defaultRoot = type.getDefaultRoot(mValues.project);
- if (defaultRoot != null) {
- index = roots.indexOf(defaultRoot);
- }
- mRootTable.select(index < 0 ? 0 : index);
- mRootTable.showSelection();
- }
- }
-
- /**
- * Helper method to select the current type in the type dropdown
- *
- * @param type The TypeInfo matching the radio button to selected or null to deselect them all.
- */
- private void selectType(TypeInfo type) {
- mInternalTypeUpdate = true;
- mValues.type = type;
- if (type == null) {
- if (mTypeCombo.getSelectionIndex() != -1) {
- mTypeCombo.deselect(mTypeCombo.getSelectionIndex());
- }
- } else {
- setSelectedType(type);
- }
- updateRootCombo(type);
- mInternalTypeUpdate = false;
- }
-
- /**
- * Add the available types in the type combobox, based on whether they are available
- * for the current SDK.
- * <p/>
- * A type is available either if:
- * - if mProject is null, API level 1 is considered valid
- * - if mProject is !null, the project->target->API must be >= to the type's API level.
- */
- private void updateAvailableTypes() {
- IProject project = mValues.project;
- IAndroidTarget target = project != null ? Sdk.getCurrent().getTarget(project) : null;
- int currentApiLevel = 1;
- if (target != null) {
- currentApiLevel = target.getVersion().getApiLevel();
- }
-
- List<String> items = new ArrayList<String>(sTypes.length);
- List<TypeInfo> types = new ArrayList<TypeInfo>(sTypes.length);
- for (int i = 0, n = sTypes.length; i < n; i++) {
- TypeInfo type = sTypes[i];
- if (type.getTargetApiLevel() <= currentApiLevel) {
- items.add(type.getUiName());
- types.add(type);
- }
- }
- mTypeCombo.setItems(items.toArray(new String[items.size()]));
- mTypeCombo.setData(types.toArray(new TypeInfo[types.size()]));
- }
-
- /**
- * Validates the fields, displays errors and warnings.
- * Enables the finish button if there are no errors.
- */
- private void validatePage() {
- String error = null;
- String warning = null;
-
- // -- validate type
- TypeInfo type = mValues.type;
- if (error == null) {
- if (type == null) {
- error = "One of the types must be selected (e.g. layout, values, etc.)";
- }
- }
-
- // -- validate project
- if (mValues.project == null) {
- error = "Please select an Android project.";
- }
-
- // -- validate type API level
- if (error == null) {
- IAndroidTarget target = Sdk.getCurrent().getTarget(mValues.project);
- int currentApiLevel = 1;
- if (target != null) {
- currentApiLevel = target.getVersion().getApiLevel();
- }
-
- assert type != null;
- if (type.getTargetApiLevel() > currentApiLevel) {
- error = "The API level of the selected type (e.g. AppWidget, etc.) is not " +
- "compatible with the API level of the project.";
- }
- }
-
- // -- validate filename
- if (error == null) {
- String fileName = mValues.getFileName();
- assert type != null;
- ResourceFolderType folderType = type.getResFolderType();
- error = ResourceNameValidator.create(true, folderType).isValid(fileName);
- }
-
- // -- validate destination file doesn't exist
- if (error == null) {
- IFile file = mValues.getDestinationFile();
- if (file != null && file.exists()) {
- warning = "The destination file already exists";
- }
- }
-
- // -- update UI & enable finish if there's no error
- setPageComplete(error == null);
- if (error != null) {
- setMessage(error, IMessageProvider.ERROR);
- } else if (warning != null) {
- setMessage(warning, IMessageProvider.WARNING);
- } else {
- setErrorMessage(null);
- setMessage(null);
- }
- }
-
- /**
- * Returns the {@link TypeInfo} for the given {@link ResourceFolderType}, or null if
- * not found
- *
- * @param folderType the {@link ResourceFolderType} to look for
- * @return the corresponding {@link TypeInfo}
- */
- static TypeInfo getTypeInfo(ResourceFolderType folderType) {
- for (TypeInfo typeInfo : sTypes) {
- if (typeInfo.getResFolderType() == folderType) {
- return typeInfo;
- }
- }
-
- return null;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileWizard.java
deleted file mode 100644
index 16cd7b355..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/NewXmlFileWizard.java
+++ /dev/null
@@ -1,431 +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.internal.wizards.newxmlfile;
-
-import static com.android.SdkConstants.FQCN_GRID_LAYOUT;
-import static com.android.SdkConstants.GRID_LAYOUT;
-
-import com.android.SdkConstants;
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-import com.android.ide.common.xml.XmlFormatStyle;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.AdtUtils;
-import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
-import com.android.ide.eclipse.adt.internal.editors.IconFactory;
-import com.android.ide.eclipse.adt.internal.editors.formatting.EclipseXmlFormatPreferences;
-import com.android.ide.eclipse.adt.internal.editors.formatting.EclipseXmlPrettyPrinter;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewManager;
-import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
-import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
-import com.android.ide.eclipse.adt.internal.project.SupportLibraryHelper;
-import com.android.ide.eclipse.adt.internal.wizards.newxmlfile.NewXmlFileCreationPage.TypeInfo;
-import com.android.resources.ResourceFolderType;
-import com.android.utils.Pair;
-
-import org.eclipse.core.resources.IFile;
-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.IStatus;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.Region;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.wizard.Wizard;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.INewWizard;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.PartInitException;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-
-/**
- * The "New Android XML File Wizard" provides the ability to create skeleton XML
- * resources files for Android projects.
- * <p/>
- * The wizard has one page, {@link NewXmlFileCreationPage}, used to select the project,
- * the resource folder, resource type and file name. It then creates the XML file.
- */
-public class NewXmlFileWizard extends Wizard implements INewWizard {
- /** The XML header to write at the top of the XML file */
- public static final String XML_HEADER_LINE = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; //$NON-NLS-1$
-
- private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$
-
- protected static final String MAIN_PAGE_NAME = "newAndroidXmlFilePage"; //$NON-NLS-1$
-
- private NewXmlFileCreationPage mMainPage;
- private ChooseConfigurationPage mConfigPage;
- private Values mValues;
-
- @Override
- public void init(IWorkbench workbench, IStructuredSelection selection) {
- setHelpAvailable(false); // TODO have help
- setWindowTitle("New Android XML File");
- setImageDescriptor();
-
- mValues = new Values();
- mMainPage = createMainPage(mValues);
- mMainPage.setTitle("New Android XML File");
- mMainPage.setDescription("Creates a new Android XML file.");
- mMainPage.setInitialSelection(selection);
-
- mConfigPage = new ChooseConfigurationPage(mValues);
-
- // Trigger a check to see if the SDK needs to be reloaded (which will
- // invoke onSdkLoaded asynchronously as needed).
- AdtPlugin.getDefault().refreshSdk();
- }
-
- /**
- * Creates the wizard page.
- * <p/>
- * Please do NOT override this method.
- * <p/>
- * This is protected so that it can be overridden by unit tests.
- * However the contract of this class is private and NO ATTEMPT will be made
- * to maintain compatibility between different versions of the plugin.
- */
- protected NewXmlFileCreationPage createMainPage(NewXmlFileWizard.Values values) {
- return new NewXmlFileCreationPage(MAIN_PAGE_NAME, values);
- }
-
- // -- Methods inherited from org.eclipse.jface.wizard.Wizard --
- //
- // The Wizard class implements most defaults and boilerplate code needed by
- // IWizard
-
- /**
- * Adds pages to this wizard.
- */
- @Override
- public void addPages() {
- addPage(mMainPage);
- addPage(mConfigPage);
-
- }
-
- /**
- * Performs any actions appropriate in response to the user having pressed
- * the Finish button, or refuse if finishing now is not permitted: here, it
- * actually creates the workspace project and then switch to the Java
- * perspective.
- *
- * @return True
- */
- @Override
- public boolean performFinish() {
- final Pair<IFile, IRegion> created = createXmlFile();
- if (created == null) {
- return false;
- } else {
- // Open the file
- // This has to be delayed in order for focus handling to work correctly
- AdtPlugin.getDisplay().asyncExec(new Runnable() {
- @Override
- public void run() {
- IFile file = created.getFirst();
- IRegion region = created.getSecond();
- try {
- IEditorPart editor = AdtPlugin.openFile(file, null,
- false /*showEditorTab*/);
- if (editor instanceof AndroidXmlEditor) {
- final AndroidXmlEditor xmlEditor = (AndroidXmlEditor)editor;
- if (!xmlEditor.hasMultiplePages()) {
- xmlEditor.show(region.getOffset(), region.getLength(),
- true /* showEditorTab */);
- }
- }
- } catch (PartInitException e) {
- AdtPlugin.log(e, "Failed to create %1$s: missing type", //$NON-NLS-1$
- file.getFullPath().toString());
- }
- }});
-
- return true;
- }
- }
-
- // -- Custom Methods --
-
- private Pair<IFile, IRegion> createXmlFile() {
- IFile file = mValues.getDestinationFile();
- TypeInfo type = mValues.type;
- if (type == null) {
- // this is not expected to happen
- String name = file.getFullPath().toString();
- 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
- AdtPlugin.log(IStatus.ERROR, "Failed to create %1$s: missing root element", //$NON-NLS-1$
- file.toString());
- return null;
- }
-
- String attrs = type.getDefaultAttrs(mValues.project, root);
- String child = type.getChild(mValues.project, root);
- return createXmlFile(file, xmlns, root, attrs, child, type.getResFolderType());
- }
-
- /** Creates a new file using the given root element, namespace and root attributes */
- private static Pair<IFile, IRegion> createXmlFile(IFile file, String xmlns,
- String root, String rootAttributes, String child, ResourceFolderType folderType) {
- String name = file.getFullPath().toString();
- boolean need_delete = false;
-
- if (file.exists()) {
- 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;
- }
- need_delete = true;
- } else {
- AdtUtils.createWsParentDirectory(file.getParent());
- }
-
- StringBuilder sb = new StringBuilder(XML_HEADER_LINE);
-
- if (folderType == ResourceFolderType.LAYOUT && root.equals(GRID_LAYOUT)) {
- IProject project = file.getParent().getProject();
- int minSdk = ManifestInfo.get(project).getMinSdkVersion();
- if (minSdk < 14) {
- root = SupportLibraryHelper.getTagFor(project, FQCN_GRID_LAYOUT);
- if (root.equals(FQCN_GRID_LAYOUT)) {
- root = GRID_LAYOUT;
- }
- }
- }
-
- sb.append('<').append(root);
- if (xmlns != null) {
- sb.append('\n').append(" xmlns:android=\"").append(xmlns).append('"'); //$NON-NLS-1$
- }
-
- if (rootAttributes != null) {
- sb.append("\n "); //$NON-NLS-1$
- sb.append(rootAttributes.replace("\n", "\n ")); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- sb.append(">\n"); //$NON-NLS-1$
-
- if (child != null) {
- sb.append(child);
- }
-
- boolean autoFormat = AdtPrefs.getPrefs().getUseCustomXmlFormatter();
-
- // Insert an indented caret. Since the markup here will be reformatted, we need to
- // insert text tokens that the formatter will preserve, which we can then turn back
- // into indentation and a caret offset:
- final String indentToken = "${indent}"; //$NON-NLS-1$
- final String caretToken = "${caret}"; //$NON-NLS-1$
- sb.append(indentToken);
- sb.append(caretToken);
- if (!autoFormat) {
- sb.append('\n');
- }
-
- sb.append("</").append(root).append(">\n"); //$NON-NLS-1$ //$NON-NLS-2$
-
- EclipseXmlFormatPreferences formatPrefs = EclipseXmlFormatPreferences.create();
- String fileContents;
- if (!autoFormat) {
- fileContents = sb.toString();
- } else {
- XmlFormatStyle style = EclipseXmlPrettyPrinter.getForFolderType(folderType);
- fileContents = EclipseXmlPrettyPrinter.prettyPrint(sb.toString(), formatPrefs,
- style, null /*lineSeparator*/);
- }
-
- // Remove marker tokens and replace them with whitespace
- fileContents = fileContents.replace(indentToken, formatPrefs.getOneIndentUnit());
- int caretOffset = fileContents.indexOf(caretToken);
- if (caretOffset != -1) {
- fileContents = fileContents.replace(caretToken, ""); //$NON-NLS-1$
- }
-
- String error = null;
- try {
- byte[] buf = fileContents.getBytes("UTF8"); //$NON-NLS-1$
- InputStream stream = new ByteArrayInputStream(buf);
- if (need_delete) {
- file.delete(IResource.KEEP_HISTORY | IResource.FORCE, null /*monitor*/);
- }
- file.create(stream, true /*force*/, null /*progress*/);
- IRegion region = caretOffset != -1 ? new Region(caretOffset, 0) : null;
-
- // If you introduced a new locale, or new screen variations etc, ensure that
- // the list of render previews is updated if necessary
- if (file.getParent().getName().indexOf('-') != -1
- && (folderType == ResourceFolderType.LAYOUT
- || folderType == ResourceFolderType.VALUES)) {
- RenderPreviewManager.bumpRevision();
- }
-
- return Pair.of(file, region);
- } catch (UnsupportedEncodingException e) {
- error = e.getMessage();
- } catch (CoreException e) {
- error = e.getMessage();
- }
-
- error = String.format("Failed to generate %1$s: %2$s", name, error);
- AdtPlugin.displayError("New Android XML File", error);
- return null;
- }
-
- /**
- * Returns true if the New XML Wizard can create new files of the given
- * {@link ResourceFolderType}
- *
- * @param folderType the folder type to create a file for
- * @return true if this wizard can create new files for the given folder type
- */
- public static boolean canCreateXmlFile(ResourceFolderType folderType) {
- TypeInfo typeInfo = NewXmlFileCreationPage.getTypeInfo(folderType);
- return typeInfo != null && (typeInfo.getDefaultRoot(null /*project*/) != null ||
- typeInfo.getRootSeed() instanceof String);
- }
-
- /**
- * Creates a new XML file using the template according to the given folder type
- *
- * @param project the project to create the file in
- * @param file the file to be created
- * @param folderType the type of folder to look up a template for
- * @return the created file
- */
- public static Pair<IFile, IRegion> createXmlFile(IProject project, IFile file,
- ResourceFolderType folderType) {
- TypeInfo type = NewXmlFileCreationPage.getTypeInfo(folderType);
- String xmlns = type.getXmlns();
- String root = type.getDefaultRoot(project);
- if (root == null) {
- root = type.getRootSeed().toString();
- }
- String attrs = type.getDefaultAttrs(project, root);
- return createXmlFile(file, xmlns, root, attrs, null, folderType);
- }
-
- /**
- * Returns an image descriptor for the wizard logo.
- */
- private void setImageDescriptor() {
- ImageDescriptor desc = IconFactory.getInstance().getImageDescriptor(PROJECT_LOGO_LARGE);
- setDefaultPageImageDescriptor(desc);
- }
-
- /**
- * Specific New XML File wizard tied to the {@link ResourceFolderType#LAYOUT} type
- */
- public static class NewLayoutWizard extends NewXmlFileWizard {
- /** Creates a new {@link NewLayoutWizard} */
- public NewLayoutWizard() {
- }
-
- @Override
- public void init(IWorkbench workbench, IStructuredSelection selection) {
- super.init(workbench, selection);
- setWindowTitle("New Android Layout XML File");
- super.mMainPage.setTitle("New Android Layout XML File");
- super.mMainPage.setDescription("Creates a new Android Layout XML file.");
- super.mMainPage.setInitialFolderType(ResourceFolderType.LAYOUT);
- }
- }
-
- /**
- * Specific New XML File wizard tied to the {@link ResourceFolderType#VALUES} type
- */
- public static class NewValuesWizard extends NewXmlFileWizard {
- /** Creates a new {@link NewValuesWizard} */
- public NewValuesWizard() {
- }
-
- @Override
- public void init(IWorkbench workbench, IStructuredSelection selection) {
- super.init(workbench, selection);
- setWindowTitle("New Android Values XML File");
- super.mMainPage.setTitle("New Android Values XML File");
- super.mMainPage.setDescription("Creates a new Android Values XML file.");
- super.mMainPage.setInitialFolderType(ResourceFolderType.VALUES);
- }
- }
-
- /** Value object which holds the current state of the wizard pages */
- public static class Values {
- /** The currently selected project, or null */
- public IProject project;
- /** The root name of the XML file to create, or null */
- public String name;
- /** The type of XML file to create */
- public TypeInfo type;
- /** The path within the project to create the new file in */
- public String folderPath;
- /** The currently chosen configuration */
- public FolderConfiguration configuration = new FolderConfiguration();
-
- /**
- * Returns the destination filename or an empty string.
- *
- * @return the filename, never null.
- */
- public String getFileName() {
- String fileName;
- if (name == null) {
- fileName = ""; //$NON-NLS-1$
- } else {
- fileName = name.trim();
- if (fileName.length() > 0 && fileName.indexOf('.') == -1) {
- fileName = fileName + SdkConstants.DOT_XML;
- }
- }
-
- return fileName;
- }
-
- /**
- * Returns a {@link IFile} for the destination file.
- * <p/>
- * Returns null if the project, filename or folder are invalid and the
- * destination file cannot be determined.
- * <p/>
- * The {@link IFile} is a resource. There might or might not be an
- * actual real file.
- *
- * @return an {@link IFile} for the destination file
- */
- public IFile getDestinationFile() {
- String fileName = getFileName();
- if (project != null && folderPath != null && folderPath.length() > 0
- && fileName.length() > 0) {
- IPath dest = new Path(folderPath).append(fileName);
- IFile file = project.getFile(dest);
- return file;
- }
- return null;
- }
- }
-}