aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2011-08-25 13:13:34 -0700
committerTor Norbye <tnorbye@google.com>2011-09-01 13:56:48 -0700
commit59bddc5b09c091cfae54577ec36b16925b362b55 (patch)
tree6f23ab6c3e44ce59decd00667ab956bb306a9d0c /eclipse
parentb3ab7ef8a24a64bcd6f347e8e03bc647c12eb24b (diff)
downloadsdk-59bddc5b09c091cfae54577ec36b16925b362b55.zip
sdk-59bddc5b09c091cfae54577ec36b16925b362b55.tar.gz
sdk-59bddc5b09c091cfae54577ec36b16925b362b55.tar.bz2
Add support for remaining asset types in Asset Studio Wizard
This changeset ports the remaining graphic generators from the HTML5 version (notifications, tabs, action bar), and hooks up wizard support for them. It also adds unit tests for the generators which generates images and compares them to known good versions. I ran these tests comparing them to the output from the HTML5 version of Asset Studio and all but 3 of the images varied less than 5% (and I verified the remaining manually and they're all fine and the difference is due to the images being aligned slightly differently.) The icon wizard is now also hooked up to the "New" button in the Resource Chooser for drawable resources, and this changeset also fixes a few related issues ("New" didn't work for file-based resources, and newly created resources weren't showing up in the selection list.) Change-Id: I48c49f1d5de452aa5b78e491d9b07e7156397fa9
Diffstat (limited to 'eclipse')
-rw-r--r--eclipse/dictionary.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java36
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/AssetType.java88
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ChooseAssetTypePage.java172
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureAssetSetPage.java432
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureLauncherAssetsPanel.java37
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/CreateAssetSetWizard.java222
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/OpenCreateAssetSetWizardAction.java58
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectChooserHelper.java82
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java32
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java115
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java17
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java11
13 files changed, 933 insertions, 371 deletions
diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt
index 7843eb1..b6042cb 100644
--- a/eclipse/dictionary.txt
+++ b/eclipse/dictionary.txt
@@ -102,6 +102,8 @@ guava
hardcode
hardcoded
hardcodes
+hdpi
+helvetica
highlighter
holo
hotfix
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java
index 1db8fa0..38ecbe0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java
@@ -60,6 +60,42 @@ public class AdtUtils {
}
/**
+ * Strips off the last file extension from the given filename, e.g.
+ * "foo.backup.diff" will be turned into "foo.backup".
+ * <p>
+ * Note that dot files (e.g. ".profile") will be left alone.
+ *
+ * @param filename the filename to be stripped
+ * @return the filename without the last file extension.
+ */
+ public static String stripLastExtension(String filename) {
+ int dotIndex = filename.lastIndexOf('.');
+ if (dotIndex > 0) { // > 0 instead of != -1: Treat dot files (e.g. .profile) differently
+ return filename.substring(0, dotIndex);
+ } else {
+ return filename;
+ }
+ }
+
+ /**
+ * Strips off all extensions from the given filename, e.g. "foo.9.png" will
+ * be turned into "foo".
+ * <p>
+ * Note that dot files (e.g. ".profile") will be left alone.
+ *
+ * @param filename the filename to be stripped
+ * @return the filename without any file extensions
+ */
+ public static String stripAllExtensions(String filename) {
+ int dotIndex = filename.indexOf('.');
+ if (dotIndex > 0) { // > 0 instead of != -1: Treat dot files (e.g. .profile) differently
+ return filename.substring(0, dotIndex);
+ } else {
+ return filename;
+ }
+ }
+
+ /**
* Capitalizes the string, i.e. transforms the initial [a-z] into [A-Z].
* Returns the string unmodified if the first character is not [a-z].
*
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/AssetType.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/AssetType.java
new file mode 100644
index 0000000..29cb910
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/AssetType.java
@@ -0,0 +1,88 @@
+/*
+ * 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.assetstudio;
+
+/**
+ * The type of asset to create: launcher icon, menu icon, etc.
+ */
+enum AssetType {
+ /** Launcher icon to be shown in the application list */
+ LAUNCHER("Launcher Icons", "ic_launcher"), //$NON-NLS-2$
+
+ /** Icons shown in menus */
+ MENU("Menu Icons", "ic_menu_%s"), //$NON-NLS-2$
+
+ /** Icons shown in the action bar */
+ ACTIONBAR("Action Bar Icons (Android 3.0+)", "ic_action_%s"), //$NON-NLS-2$
+
+ /** Icons shown as part of tabs */
+ TAB("Tab Icons", "ic_tab_%s"), //$NON-NLS-2$
+
+ /** Icons shown in a notification message */
+ NOTIFICATION("Notification Icons", "ic_stat_%s"); //$NON-NLS-2$
+
+ /** Display name to show to the user in the asset type selection list */
+ private final String mDisplayName;
+
+ /** Default asset name format */
+ private String mDefaultNameFormat;
+
+ AssetType(String displayName, String defaultNameFormat) {
+ mDisplayName = displayName;
+ mDefaultNameFormat = defaultNameFormat;
+ }
+
+ /**
+ * Returns the display name of this asset type to show to the user in the
+ * asset wizard selection page etc
+ */
+ String getDisplayName() {
+ return mDisplayName;
+ }
+
+ /**
+ * Returns the default format to use to suggest a name for the asset
+ */
+ String getDefaultNameFormat() {
+ return mDefaultNameFormat;
+ }
+
+ /** Whether this asset type configures foreground scaling */
+ boolean needsForegroundScaling() {
+ return this == LAUNCHER;
+ }
+
+ /** Whether this asset type needs a shape parameter */
+ boolean needsShape() {
+ return this == LAUNCHER || this == NOTIFICATION;
+ }
+
+ /** Whether this asset type needs foreground and background color parameters */
+ boolean needsColors() {
+ return this == LAUNCHER;
+ }
+
+ /** Whether this asset type needs an effects parameter */
+ boolean needsEffects() {
+ return this == LAUNCHER;
+ }
+
+ /** Whether this asset type needs a theme parameter */
+ boolean needsTheme() {
+ return this == ACTIONBAR;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ChooseAssetTypePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ChooseAssetTypePage.java
index a5b0480..7b406eb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ChooseAssetTypePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ChooseAssetTypePage.java
@@ -16,12 +16,11 @@
package com.android.ide.eclipse.adt.internal.assetstudio;
-import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper;
+import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper.ProjectButton;
import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator;
import com.android.resources.ResourceFolderType;
import org.eclipse.core.resources.IProject;
-import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
@@ -36,20 +35,23 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
+/** Page for choosing the type of asset to create, as well as the target project */
public class ChooseAssetTypePage extends WizardPage implements SelectionListener, ModifyListener {
- private Text mProjectText;
- private Button mBrowseButton;
- private ProjectChooserHelper mProjectChooserHelper;
+ private ProjectButton mProjectButton;
+ private Button mClipboardButton;
private IProject mProject;
private Text mNameText;
+ private AssetType mType = AssetType.LAUNCHER;
+ private boolean mNameModified;
+ private Label mResourceName;
/**
* Create the wizard.
*/
public ChooseAssetTypePage() {
super("chooseAssetTypePage");
- setTitle("Choose Asset Set Type");
- setDescription("Select the type of asset set to create:");
+ setTitle("Choose Icon Set Type");
+ setDescription("Select the type of icon set to create:");
}
/**
@@ -57,39 +59,20 @@ public class ChooseAssetTypePage extends WizardPage implements SelectionListener
*
* @param parent the parent composite
*/
- @SuppressWarnings("unused")
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NULL);
setControl(container);
container.setLayout(new GridLayout(3, false));
- Button launcherIcons = new Button(container, SWT.RADIO);
- launcherIcons.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
- launcherIcons.setSelection(true);
- launcherIcons.setText("Launcher Icons");
-
- Button menuIcons = new Button(container, SWT.RADIO);
- menuIcons.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
- menuIcons.setEnabled(false);
- menuIcons.setText("Menu Icons");
-
- Button actionBarIcons = new Button(container, SWT.RADIO);
- actionBarIcons.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
- actionBarIcons.setEnabled(false);
- actionBarIcons.setText("Action Bar Icons (Android 3.0+)");
-
- Button tabIcons = new Button(container, SWT.RADIO);
- tabIcons.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
- tabIcons.setEnabled(false);
- tabIcons.setText("Tab Icons");
-
- Button notificationIcons = new Button(container, SWT.RADIO);
- notificationIcons.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
- notificationIcons.setEnabled(false);
- notificationIcons.setText("Notification Icons");
-
- mProjectChooserHelper = new ProjectChooserHelper(parent.getShell(), null /*filter*/);
+ for (AssetType type : AssetType.values()) {
+ Button button = new Button(container, SWT.RADIO);
+ button.setData(type);
+ button.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
+ button.setSelection(type == mType);
+ button.setText(type.getDisplayName());
+ button.addSelectionListener(this);
+ }
Label separator = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
GridData gdSeparator = new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1);
@@ -100,28 +83,33 @@ public class ChooseAssetTypePage extends WizardPage implements SelectionListener
projectLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
projectLabel.setText("Project:");
- mProjectText = new Text(container, SWT.BORDER);
- mProjectText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
- if (mProject != null) {
- mProjectText.setText(mProject.getName());
- }
- mProjectText.addModifyListener(this);
-
- mBrowseButton = new Button(container, SWT.FLAT);
- mBrowseButton.setText("Browse...");
- mBrowseButton.setToolTipText("Allows you to select the Android project to modify.");
+ mProjectButton = new ProjectButton(container, mProject);
+ mProjectButton.setAlignment(SWT.LEFT);
+ mProjectButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ mProjectButton.addSelectionListener(this);
Label assetLabel = new Label(container, SWT.NONE);
assetLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- assetLabel.setText("Asset Name:");
+ assetLabel.setText("Icon Name:");
mNameText = new Text(container, SWT.BORDER);
- mNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
- mNameText.setText("ic_launcher");
+ mNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
mNameText.addModifyListener(this);
- new Label(container, SWT.NONE);
- mBrowseButton.addSelectionListener(this);
+ Label resourceLabel = new Label(container, SWT.NONE);
+ resourceLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ resourceLabel.setText("Resource:");
+
+ mResourceName = new Label(container, SWT.NONE);
+ mResourceName.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
+
+ mClipboardButton = new Button(container, SWT.FLAT);
+ mClipboardButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ mClipboardButton.setText("Copy Name to Clipboard");
+
+ mClipboardButton.addSelectionListener(this);
+
+ updateAssetType();
validatePage();
parent.getDisplay().asyncExec(new Runnable() {
public void run() {
@@ -130,6 +118,29 @@ public class ChooseAssetTypePage extends WizardPage implements SelectionListener
});
}
+ private void updateAssetType() {
+ if (!mNameModified) {
+ // Default name suggestion, possibly as a suffix, e.g. "ic_menu_<name>"
+ String replace = "name";
+ String suggestedName = String.format(getAssetType().getDefaultNameFormat(), replace);
+ mNameText.setText(suggestedName);
+ updateResourceLabel();
+ mNameModified = false;
+ int start = suggestedName.indexOf(replace);
+ if (start != -1) {
+ mNameText.setSelection(start, start + replace.length());
+ } else {
+ mNameText.selectAll();
+ }
+ } else {
+ mNameText.selectAll();
+ }
+ }
+
+ private void updateResourceLabel() {
+ mResourceName.setText("@drawable/" + getOutputName()); //$NON-NLS-1$
+ }
+
void setProject(IProject project) {
mProject = project;
}
@@ -144,14 +155,17 @@ public class ChooseAssetTypePage extends WizardPage implements SelectionListener
}
public void widgetSelected(SelectionEvent e) {
- if (e.getSource() == mBrowseButton) {
- IJavaProject p = mProjectChooserHelper.chooseJavaProject(mProjectText.getText(),
- "Please select the target project");
- if (p != null) {
- changeProject(p.getProject());
- mProjectText.setText(mProject.getName());
+ Object source = e.getSource();
+ if (source == mProjectButton) {
+ mProject = mProjectButton.getSelectedProject();
+ validatePage();
+ } else if (source instanceof Button) {
+ // User selected a different asset type to be created
+ Object data = ((Button) source).getData();
+ if (data instanceof AssetType) {
+ mType = (AssetType) data;
+ updateAssetType();
}
-
}
}
@@ -159,56 +173,42 @@ public class ChooseAssetTypePage extends WizardPage implements SelectionListener
}
public void modifyText(ModifyEvent e) {
- String project = mProjectText.getText();
-
- // Is this a valid project?
- IJavaProject[] projects = mProjectChooserHelper.getAndroidProjects(null /*javaModel*/);
- IProject found = null;
- for (IJavaProject p : projects) {
- if (p.getProject().getName().equals(project)) {
- found = p.getProject();
- break;
- }
- }
-
- if (found != mProject) {
- changeProject(found);
+ Object source = e.getSource();
+ if (source == mNameText) {
+ mNameModified = true;
+ updateResourceLabel();
}
validatePage();
}
- private void changeProject(IProject newProject) {
- mProject = newProject;
- validatePage();
- }
-
String getOutputName() {
return mNameText.getText().trim();
}
+ AssetType getAssetType() {
+ return mType;
+ }
+
private void validatePage() {
String error = null;
- //String warning = null;
if (getProject() == null) {
error = "Please select an Android project.";
- }
-
- String outputName = getOutputName();
- if (outputName == null || outputName.length() == 0) {
- error = "Please enter a name";
} else {
- ResourceNameValidator validator =
- ResourceNameValidator.create(true, ResourceFolderType.DRAWABLE);
- error = validator.isValid(outputName);
+ String outputName = getOutputName();
+ if (outputName == null || outputName.length() == 0) {
+ error = "Please enter a name";
+ } else {
+ ResourceNameValidator validator =
+ ResourceNameValidator.create(true, ResourceFolderType.DRAWABLE);
+ error = validator.isValid(outputName);
+ }
}
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/assetstudio/ConfigureAssetSetPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureAssetSetPage.java
index 8804a47..e60d9f9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureAssetSetPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureAssetSetPage.java
@@ -16,25 +16,25 @@
package com.android.ide.eclipse.adt.internal.assetstudio;
-import static com.android.assetstudiolib.LauncherIconGenerator.Options.Shape.CIRCLE;
-import static com.android.assetstudiolib.LauncherIconGenerator.Options.Shape.SQUARE;
-
+import com.android.assetstudiolib.ActionBarIconGenerator;
import com.android.assetstudiolib.GraphicGenerator;
import com.android.assetstudiolib.GraphicGeneratorContext;
import com.android.assetstudiolib.LauncherIconGenerator;
-import com.android.assetstudiolib.LauncherIconGenerator.Options.Style;
+import com.android.assetstudiolib.MenuIconGenerator;
+import com.android.assetstudiolib.NotificationIconGenerator;
+import com.android.assetstudiolib.TabIconGenerator;
import com.android.assetstudiolib.TextRenderUtil;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageControl;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SwtUtils;
-import com.android.resources.Density;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.WizardPage;
@@ -54,6 +54,7 @@ import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.ColorDialog;
@@ -69,13 +70,12 @@ import org.eclipse.swt.widgets.Text;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
-import java.util.Arrays;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Map.Entry;
import javax.imageio.ImageIO;
@@ -87,7 +87,8 @@ import javax.imageio.ImageIO;
public class ConfigureAssetSetPage extends WizardPage implements SelectionListener,
GraphicGeneratorContext, ModifyListener {
- private Composite configurationArea;
+ private static final int PREVIEW_AREA_WIDTH = 120;
+ private Composite mConfigurationArea;
private Button mImageRadio;
private Button mClipartRadio;
private Button mTextRadio;
@@ -123,16 +124,26 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
private static String sImagePath;
private Button mChooseClipart;
private Composite mClipartPreviewPanel;
+ private Label mThemeLabel;
+ private Composite mThemeComposite;
+ private Button mHoloLightRadio;
+ private Button mHoloDarkRadio;
+ private Label mScalingLabel;
+ private Composite mScalingComposite;
+ private Label mShapeLabel;
+ private Composite mShapeComposite;
+ private Label mBgColorLabel;
+ private Label mFgColorLabel;
+ private Label mEffectsLabel;
+ private Composite mEffectsComposite;
/**
* Create the wizard.
- *
- * @param wizard the surrounding wizard
*/
public ConfigureAssetSetPage() {
super("configureAssetPage");
- setTitle("Configure Asset Set");
- setDescription("Configure the attributes of the asset set");
+ setTitle("Configure Icon Set");
+ setDescription("Configure the attributes of the icon set");
}
/**
@@ -157,18 +168,19 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
configurationScrollArea.setExpandHorizontal(true);
configurationScrollArea.setExpandVertical(true);
- configurationArea = new Composite(configurationScrollArea, SWT.NONE);
+ mConfigurationArea = new Composite(configurationScrollArea, SWT.NONE);
GridLayout glConfigurationArea = new GridLayout(3, false);
+ glConfigurationArea.horizontalSpacing = 0;
glConfigurationArea.marginRight = 15;
glConfigurationArea.marginWidth = 0;
glConfigurationArea.marginHeight = 0;
- configurationArea.setLayout(glConfigurationArea);
+ mConfigurationArea.setLayout(glConfigurationArea);
- Label foregroundLabel = new Label(configurationArea, SWT.NONE);
+ Label foregroundLabel = new Label(mConfigurationArea, SWT.NONE);
foregroundLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
foregroundLabel.setText("Foreground:");
- Composite foregroundComposite = new Composite(configurationArea, SWT.NONE);
+ Composite foregroundComposite = new Composite(mConfigurationArea, SWT.NONE);
foregroundComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
GridLayout glForegroundComposite = new GridLayout(5, false);
glForegroundComposite.horizontalSpacing = 0;
@@ -188,9 +200,9 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
mTextRadio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
mTextRadio.setText("Text");
mTextRadio.addSelectionListener(this);
- new Label(configurationArea, SWT.NONE);
+ new Label(mConfigurationArea, SWT.NONE);
- mForegroundArea = new Composite(configurationArea, SWT.NONE);
+ mForegroundArea = new Composite(mConfigurationArea, SWT.NONE);
mForegroundArea.setLayout(new StackLayout());
mForegroundArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
@@ -247,120 +259,133 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
mFontButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
mFontButton.addSelectionListener(this);
mFontButton.setText("Choose Font...");
- new Label(configurationArea, SWT.NONE);
+ new Label(mConfigurationArea, SWT.NONE);
- mTrimCheckBox = new Button(configurationArea, SWT.CHECK);
+ mTrimCheckBox = new Button(mConfigurationArea, SWT.CHECK);
mTrimCheckBox.setEnabled(false);
mTrimCheckBox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
- mTrimCheckBox.setSelection(true);
+ mTrimCheckBox.setSelection(false);
mTrimCheckBox.setText("Trim Surrounding Blank Space");
- new Label(configurationArea, SWT.NONE);
+ new Label(mConfigurationArea, SWT.NONE);
- Label paddingLabel = new Label(configurationArea, SWT.NONE);
+ Label paddingLabel = new Label(mConfigurationArea, SWT.NONE);
paddingLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
paddingLabel.setText("Additional Padding:");
- new Label(configurationArea, SWT.NONE);
+ new Label(mConfigurationArea, SWT.NONE);
- mPaddingSlider = new Slider(configurationArea, SWT.NONE);
+ mPaddingSlider = new Slider(mConfigurationArea, SWT.NONE);
mPaddingSlider.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
- mPaddingSlider.setEnabled(false);
// This doesn't work right -- not sure why. For now just use a plain slider
- // and subtract from it to get the real range.
+ // and subtract 10 from it to get the real range.
//mPaddingSlider.setValues(0, -10, 50, 0, 1, 10);
- mPaddingSlider.setSelection(10);
+ mPaddingSlider.setSelection(10 + 15);
mPaddingSlider.addSelectionListener(this);
- mPercentLabel = new Label(configurationArea, SWT.NONE);
- mPercentLabel.setText(" 0%"); // Enough available space for -10%
+ mPercentLabel = new Label(mConfigurationArea, SWT.NONE);
+ mPercentLabel.setText(" 15%"); // Enough available space for -10%
- Label scalingLabel = new Label(configurationArea, SWT.NONE);
- scalingLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- scalingLabel.setText("Foreground Scaling:");
+ mScalingLabel = new Label(mConfigurationArea, SWT.NONE);
+ mScalingLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ mScalingLabel.setText("Foreground Scaling:");
- Composite scalingComposite = new Composite(configurationArea, SWT.NONE);
- scalingComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
- GridLayout glScalingComposite = new GridLayout(5, false);
- glScalingComposite.horizontalSpacing = 0;
- scalingComposite.setLayout(glScalingComposite);
+ mScalingComposite = new Composite(mConfigurationArea, SWT.NONE);
+ mScalingComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
+ GridLayout gl_mScalingComposite = new GridLayout(5, false);
+ gl_mScalingComposite.horizontalSpacing = 0;
+ mScalingComposite.setLayout(gl_mScalingComposite);
- mCropRadio = new Button(scalingComposite, SWT.FLAT | SWT.TOGGLE);
+ mCropRadio = new Button(mScalingComposite, SWT.FLAT | SWT.TOGGLE);
mCropRadio.setSelection(true);
mCropRadio.setText("Crop");
mCropRadio.addSelectionListener(this);
- mCenterRadio = new Button(scalingComposite, SWT.FLAT | SWT.TOGGLE);
+ mCenterRadio = new Button(mScalingComposite, SWT.FLAT | SWT.TOGGLE);
mCenterRadio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
mCenterRadio.setText("Center");
mCenterRadio.addSelectionListener(this);
- Label shapeLabel = new Label(configurationArea, SWT.NONE);
- shapeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- shapeLabel.setText("Shape");
+ mShapeLabel = new Label(mConfigurationArea, SWT.NONE);
+ mShapeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ mShapeLabel.setText("Shape");
- Composite shapeComposite = new Composite(configurationArea, SWT.NONE);
- shapeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
- GridLayout glShapeComposite = new GridLayout(5, false);
- glShapeComposite.horizontalSpacing = 0;
- shapeComposite.setLayout(glShapeComposite);
+ mShapeComposite = new Composite(mConfigurationArea, SWT.NONE);
+ mShapeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
+ GridLayout gl_mShapeComposite = new GridLayout(5, false);
+ gl_mShapeComposite.horizontalSpacing = 0;
+ mShapeComposite.setLayout(gl_mShapeComposite);
- mSquareRadio = new Button(shapeComposite, SWT.FLAT | SWT.TOGGLE);
+ mSquareRadio = new Button(mShapeComposite, SWT.FLAT | SWT.TOGGLE);
mSquareRadio.setSelection(true);
mSquareRadio.setText("Square");
mSquareRadio.addSelectionListener(this);
- mCircleButton = new Button(shapeComposite, SWT.FLAT | SWT.TOGGLE);
+ mCircleButton = new Button(mShapeComposite, SWT.FLAT | SWT.TOGGLE);
mCircleButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
mCircleButton.setText("Circle");
mCircleButton.addSelectionListener(this);
- Label bgColorLabel = new Label(configurationArea, SWT.NONE);
- bgColorLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- bgColorLabel.setText("Background Color:");
+ mThemeLabel = new Label(mConfigurationArea, SWT.NONE);
+ mThemeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ mThemeLabel.setText("Theme");
+
+ mThemeComposite = new Composite(mConfigurationArea, SWT.NONE);
+ mThemeComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ GridLayout gl_mThemeComposite = new GridLayout(2, false);
+ gl_mThemeComposite.horizontalSpacing = 0;
+ mThemeComposite.setLayout(gl_mThemeComposite);
+
+ mHoloLightRadio = new Button(mThemeComposite, SWT.FLAT | SWT.TOGGLE);
+ mHoloLightRadio.setText("Holo Light");
+ mHoloLightRadio.setSelection(true);
+ mHoloLightRadio.addSelectionListener(this);
- mBgButton = new Button(configurationArea, SWT.FLAT);
+ mHoloDarkRadio = new Button(mThemeComposite, SWT.FLAT | SWT.TOGGLE);
+ mHoloDarkRadio.setText("Holo Dark");
+ mHoloDarkRadio.addSelectionListener(this);
+
+ mBgColorLabel = new Label(mConfigurationArea, SWT.NONE);
+ mBgColorLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ mBgColorLabel.setText("Background Color:");
+
+ mBgButton = new Button(mConfigurationArea, SWT.FLAT);
+ mBgButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
mBgButton.addSelectionListener(this);
mBgButton.setAlignment(SWT.CENTER);
- new Label(configurationArea, SWT.NONE);
- Label fgColorLabel = new Label(configurationArea, SWT.NONE);
- fgColorLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- fgColorLabel.setText("Foreground Color:");
+ mFgColorLabel = new Label(mConfigurationArea, SWT.NONE);
+ mFgColorLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ mFgColorLabel.setText("Foreground Color:");
- mFgButton = new Button(configurationArea, SWT.FLAT);
+ mFgButton = new Button(mConfigurationArea, SWT.FLAT);
+ mFgButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
mFgButton.setAlignment(SWT.CENTER);
mFgButton.addSelectionListener(this);
- new Label(configurationArea, SWT.NONE);
- Label effectsLabel = new Label(configurationArea, SWT.NONE);
- effectsLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- effectsLabel.setText("Foreground Effects:");
+ mEffectsLabel = new Label(mConfigurationArea, SWT.NONE);
+ mEffectsLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ mEffectsLabel.setText("Foreground Effects:");
- Composite effectsComposite = new Composite(configurationArea, SWT.NONE);
- effectsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
- GridLayout glEffectsComposite = new GridLayout(5, false);
- glEffectsComposite.horizontalSpacing = 0;
- effectsComposite.setLayout(glEffectsComposite);
+ mEffectsComposite = new Composite(mConfigurationArea, SWT.NONE);
+ mEffectsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
+ GridLayout gl_mEffectsComposite = new GridLayout(5, false);
+ gl_mEffectsComposite.horizontalSpacing = 0;
+ mEffectsComposite.setLayout(gl_mEffectsComposite);
- mSimpleRadio = new Button(effectsComposite, SWT.FLAT | SWT.TOGGLE);
- mSimpleRadio.setEnabled(false);
+ mSimpleRadio = new Button(mEffectsComposite, SWT.FLAT | SWT.TOGGLE);
mSimpleRadio.setSelection(true);
mSimpleRadio.setText("Simple");
mSimpleRadio.addSelectionListener(this);
- mFancyRadio = new Button(effectsComposite, SWT.FLAT | SWT.TOGGLE);
- mFancyRadio.setEnabled(false);
+ mFancyRadio = new Button(mEffectsComposite, SWT.FLAT | SWT.TOGGLE);
mFancyRadio.setText("Fancy");
mFancyRadio.addSelectionListener(this);
- mGlossyRadio = new Button(effectsComposite, SWT.FLAT | SWT.TOGGLE);
- mGlossyRadio.setEnabled(false);
+ mGlossyRadio = new Button(mEffectsComposite, SWT.FLAT | SWT.TOGGLE);
mGlossyRadio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
mGlossyRadio.setText("Glossy");
mGlossyRadio.addSelectionListener(this);
-
- new Label(configurationArea, SWT.NONE);
- configurationScrollArea.setContent(configurationArea);
- configurationScrollArea.setMinSize(configurationArea.computeSize(SWT.DEFAULT,
+ configurationScrollArea.setContent(mConfigurationArea);
+ configurationScrollArea.setMinSize(mConfigurationArea.computeSize(SWT.DEFAULT,
SWT.DEFAULT));
Label previewLabel = new Label(container, SWT.NONE);
@@ -369,8 +394,8 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
mPreviewArea = new Composite(container, SWT.BORDER);
- RowLayout rlPreviewAreaPreviewArea = new RowLayout(SWT.VERTICAL);
- rlPreviewAreaPreviewArea.wrap = false;
+ RowLayout rlPreviewAreaPreviewArea = new RowLayout(SWT.HORIZONTAL);
+ rlPreviewAreaPreviewArea.wrap = true;
rlPreviewAreaPreviewArea.pack = true;
rlPreviewAreaPreviewArea.center = true;
rlPreviewAreaPreviewArea.spacing = 0;
@@ -380,12 +405,13 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
rlPreviewAreaPreviewArea.marginLeft = 0;
mPreviewArea.setLayout(rlPreviewAreaPreviewArea);
GridData gdMPreviewArea = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
- gdMPreviewArea.widthHint = 120;
+ gdMPreviewArea.widthHint = PREVIEW_AREA_WIDTH;
mPreviewArea.setLayoutData(gdMPreviewArea);
// Initial color
Display display = parent.getDisplay();
- updateColor(display, new RGB(0xa4, 0xc6, 0x39), true /*background*/);
+ //updateColor(display, new RGB(0xa4, 0xc6, 0x39), true /*background*/);
+ updateColor(display, new RGB(0xff, 0x00, 0x00), true /*background*/);
updateColor(display, new RGB(0x00, 0x00, 0x00), false /*background*/);
// Start out showing the image form
@@ -395,10 +421,40 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
// initially and we still get images
mTextRadio.setSelection(true);
chooseForegroundTab(mTextRadio, mTextForm);
+ new Label(mConfigurationArea, SWT.NONE);
+ new Label(mConfigurationArea, SWT.NONE);
+ new Label(mConfigurationArea, SWT.NONE);
validatePage();
}
+ void configureAssetType(AssetType type) {
+ showGroup(type.needsForegroundScaling(), mScalingLabel, mScalingComposite);
+ showGroup(type.needsShape(), mShapeLabel, mShapeComposite);
+ showGroup(type.needsTheme(), mThemeLabel, mThemeComposite);
+ showGroup(type.needsColors(), mBgColorLabel, mBgButton);
+ showGroup(type.needsColors(), mFgColorLabel, mFgButton);
+ showGroup(type.needsEffects(), mEffectsLabel, mEffectsComposite);
+
+ Composite parent = mScalingLabel.getParent();
+ parent.pack();
+ parent.layout();
+ }
+
+ private static void showGroup(boolean show, Control control1, Control control2) {
+ showControl(show, control1);
+ showControl(show, control2);
+ }
+
+ private static void showControl(boolean show, Control control) {
+ Object data = control.getLayoutData();
+ if (data instanceof GridData) {
+ GridData gridData = (GridData) data;
+ gridData.exclude = !show;
+ }
+ control.setVisible(show);
+ }
+
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
@@ -407,10 +463,25 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
// that method is called when the wizard is created, and we want to wait until the
// user has chosen a project before attempting to look up the right default image to use
if (visible) {
+ // Clear out old previews - important if the user goes back to page one, changes
+ // asset type and steps into page 2 - at that point we arrive here and we might
+ // display the old previews for a brief period until the preview delay timer expires.
+ for (Control c : mPreviewArea.getChildren()) {
+ c.dispose();
+ }
+ mPreviewArea.layout(true);
+
+ // Update asset type configuration: will show/hide parameter controls depending
+ // on which asset type is chosen
+ CreateAssetSetWizard wizard = (CreateAssetSetWizard) getWizard();
+ AssetType type = wizard.getAssetType();
+ assert type != null;
+ configureAssetType(type);
+
// Initial image - use the most recently used image, or the default launcher
// icon created in our default projects, if there
if (sImagePath == null) {
- IProject project = ((CreateAssetSetWizard) getWizard()).getProject();
+ IProject project = wizard.getProject();
if (project != null) {
IResource icon = project.findMember("res/drawable-hdpi/icon.png"); //$NON-NLS-1$
if (icon != null) {
@@ -453,7 +524,6 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
error = "Enter text";
}
} else {
- //error = "Clipart not yet implemented";
assert mClipartRadio.getSelection();
if (mSelectedClipart == null) {
error = "Select clip art";
@@ -473,6 +543,12 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
return error == null;
}
+ @Override
+ public boolean isPageComplete() {
+ // Force user to reach second page before hitting Finish
+ return isCurrentPage();
+ }
+
// ---- Implements ModifyListener ----
public void modifyText(ModifyEvent e) {
@@ -517,25 +593,39 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
// Enforce Radio Groups
if (source == mCropRadio) {
+ mCropRadio.setSelection(true); // Ensure that you can't toggle it off
mCenterRadio.setSelection(false);
} else if (source == mCenterRadio) {
+ mCenterRadio.setSelection(true);
mCropRadio.setSelection(false);
}
if (source == mSquareRadio) {
+ mSquareRadio.setSelection(true);
mCircleButton.setSelection(false);
} else if (source == mCircleButton) {
+ mCircleButton.setSelection(true);
mSquareRadio.setSelection(false);
}
if (source == mSimpleRadio) {
+ mSimpleRadio.setSelection(true);
mGlossyRadio.setSelection(false);
mFancyRadio.setSelection(false);
} else if (source == mFancyRadio) {
+ mFancyRadio.setSelection(true);
mSimpleRadio.setSelection(false);
mGlossyRadio.setSelection(false);
} else if (source == mGlossyRadio) {
+ mGlossyRadio.setSelection(true);
mSimpleRadio.setSelection(false);
mFancyRadio.setSelection(false);
}
+ if (source == mHoloDarkRadio) {
+ mHoloDarkRadio.setSelection(true);
+ mHoloLightRadio.setSelection(false);
+ } else if (source == mHoloLightRadio) {
+ mHoloLightRadio.setSelection(true);
+ mHoloDarkRadio.setSelection(false);
+ }
if (source == mChooseClipart) {
MessageDialog dialog = new MessageDialog(mChooseClipart.getShell(),
@@ -646,12 +736,22 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
if (source == mFontButton) {
FontDialog dialog = new FontDialog(mFontButton.getShell());
+ FontData[] fontList;
+ if (mFontButton.getData() == null) {
+ fontList = mFontButton.getDisplay().getFontList("Helvetica", true /*scalable*/);
+ } else {
+ fontList = mFontButton.getFont().getFontData();
+ }
+ dialog.setFontList(fontList);
FontData data = dialog.open();
if (data != null) {
Font font = new Font(mFontButton.getDisplay(), dialog.getFontList());
mFontButton.setFont(font);
updateFontLabel(font);
mFontButton.getParent().pack();
+ // Mark the font on the button as custom (since the renderer needs to
+ // distinguish between this font and the default font it starts out with)
+ mFontButton.setData(Boolean.TRUE);
}
}
@@ -673,6 +773,19 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
}
private java.awt.Font getSelectedFont() {
+ // Always use a large font for the rendering, even though user is typically
+ // picking small font sizes in the font chooser
+ //int dpi = mFontButton.getDisplay().getDPI().y;
+ //int height = (int) Math.round(fontData.getHeight() * dpi / 72.0);
+ int fontHeight = new TextRenderUtil.Options().fontSize;
+
+ if (mFontButton.getData() == null) {
+ // The user has not yet picked a font; look up the default font to use
+ // (Helvetica Bold, not whatever font happened to be used for button widgets
+ // in SWT on this platform)
+ return new java.awt.Font("Helvetica", java.awt.Font.BOLD, fontHeight); //$NON-NLS-1$
+ }
+
Font font = mFontButton.getFont();
FontData fontData = font.getFontData()[0];
@@ -686,13 +799,7 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
awtStyle = java.awt.Font.BOLD;
}
- // Always use a large font for the rendering, even though user is typically
- // picking small font sizes in the font chooser
- //int dpi = mFontButton.getDisplay().getDPI().y;
- //int height = (int) Math.round(fontData.getHeight() * dpi / 72.0);
- int height = new TextRenderUtil.Options().fontSize;
-
- return new java.awt.Font(fontData.getName(), awtStyle, height);
+ return new java.awt.Font(fontData.getName(), awtStyle, fontHeight);
}
private int getPadding() {
@@ -700,7 +807,7 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
return mPaddingSlider.getSelection() - 10;
}
- public void chooseForegroundTab(Button newButton, Composite newArea) {
+ private void chooseForegroundTab(Button newButton, Composite newArea) {
if (newButton.getSelection()) {
mImageRadio.setSelection(false);
mClipartRadio.setSelection(false);
@@ -709,6 +816,10 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
StackLayout stackLayout = (StackLayout) mForegroundArea.getLayout();
stackLayout.topControl = newArea;
mForegroundArea.layout();
+ } else {
+ // Treat it as a radio button: you can't click to turn it off, you have to
+ // click on one of the other buttons
+ newButton.setSelection(true);
}
}
@@ -745,26 +856,39 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
return;
}
- Map<String, BufferedImage> map = generatePreviews();
- for (Map.Entry<String, BufferedImage> entry : map.entrySet()) {
- String id = entry.getKey();
- BufferedImage image = entry.getValue();
- Label nameLabel = new Label(mPreviewArea, SWT.NONE);
- nameLabel.setText(id);
-
- Image swtImage = SwtUtils.convertToSwt(display, image, true, -1);
- if (swtImage != null) {
- @SuppressWarnings("unused") // Has side effect
- ImageControl imageControl = new ImageControl(mPreviewArea, SWT.NONE, swtImage);
+ Map<String, Map<String, BufferedImage>> map = generateImages(true /*previewOnly*/);
+ for (Entry<String, Map<String, BufferedImage>> categoryEntry : map.entrySet()) {
+ String category = categoryEntry.getKey();
+ if (category.length() > 0) {
+ Label nameLabel = new Label(mPreviewArea, SWT.NONE);
+ nameLabel.setText(String.format("%1$s:", category));
+ RowData rowData = new RowData();
+ nameLabel.setLayoutData(rowData);
+ // Ensure these get their own rows
+ rowData.width = PREVIEW_AREA_WIDTH;
+ }
+
+ Map<String, BufferedImage> images = categoryEntry.getValue();
+ for (Entry<String, BufferedImage> entry : images.entrySet()) {
+ BufferedImage image = entry.getValue();
+ Image swtImage = SwtUtils.convertToSwt(display, image, true, -1);
+ if (swtImage != null) {
+ @SuppressWarnings("unused") // Has side effect
+ ImageControl imageControl = new ImageControl(mPreviewArea, SWT.NONE, swtImage);
+ }
}
}
mPreviewArea.layout(true);
}
- Map<String, BufferedImage> generatePreviews() {
+ Map<String, Map<String, BufferedImage>> generateImages(boolean previewOnly) {
// Map of ids to images: Preserve insertion order (the densities)
- Map<String, BufferedImage> imageMap = new LinkedHashMap<String, BufferedImage>();
+ Map<String, Map<String, BufferedImage>> categoryMap =
+ new LinkedHashMap<String, Map<String, BufferedImage>>();
+
+ CreateAssetSetWizard wizard = (CreateAssetSetWizard) getWizard();
+ AssetType type = wizard.getAssetType();
BufferedImage sourceImage = null;
if (mImageRadio.getSelection()) {
@@ -787,7 +911,14 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
String text = mText.getText();
TextRenderUtil.Options options = new TextRenderUtil.Options();
options.font = getSelectedFont();
- sourceImage = TextRenderUtil.renderTextImage(text, options);
+ int color;
+ if (type.needsColors()) {
+ color = 0xFF000000 | (mFgColor.red << 16) | (mFgColor.green << 8) | mFgColor.blue;
+ } else {
+ color = 0xFFFFFFFF;
+ }
+ options.foregroundColor = color;
+ sourceImage = TextRenderUtil.renderTextImage(text, getPadding(), options);
} else {
assert mClipartRadio.getSelection();
assert mSelectedClipart != null;
@@ -795,48 +926,69 @@ public class ConfigureAssetSetPage extends WizardPage implements SelectionListen
sourceImage = GraphicGenerator.getClipartImage(mSelectedClipart);
} catch (IOException e) {
AdtPlugin.log(e, null);
- return imageMap;
+ return categoryMap;
}
}
- LauncherIconGenerator.Options options = new LauncherIconGenerator.Options();
- options.shape = mCircleButton.getSelection() ? CIRCLE : SQUARE;
- options.crop = mCropRadio.getSelection();
-
- int color = (mBgColor.red << 16) | (mBgColor.green << 8) | mBgColor.blue;
- options.backgroundColor = color;
- options.sourceImage = sourceImage;
-
- Density[] densityValues = Density.values();
- // Sort density values into ascending order
- Arrays.sort(densityValues, new Comparator<Density>() {
- public int compare(Density d1, Density d2) {
- return d1.getDpiValue() - d2.getDpiValue();
+ GraphicGenerator generator = null;
+ GraphicGenerator.Options options = null;
+ switch (type) {
+ case LAUNCHER: {
+ generator = new LauncherIconGenerator();
+ LauncherIconGenerator.LauncherOptions launcherOptions =
+ new LauncherIconGenerator.LauncherOptions();
+ launcherOptions.shape = mCircleButton.getSelection()
+ ? GraphicGenerator.Shape.CIRCLE : GraphicGenerator.Shape.SQUARE;
+ launcherOptions.crop = mCropRadio.getSelection();
+ launcherOptions.style = mFancyRadio.getSelection() ?
+ GraphicGenerator.Style.FANCY : mGlossyRadio.getSelection()
+ ? GraphicGenerator.Style.GLOSSY : GraphicGenerator.Style.SIMPLE;
+ int color = (mBgColor.red << 16) | (mBgColor.green << 8) | mBgColor.blue;
+ launcherOptions.backgroundColor = color;
+ // Flag which tells the generator iterator to include a web graphic
+ launcherOptions.isWebGraphic = !previewOnly;
+ options = launcherOptions;
+
+ break;
}
-
- });
- Style[] styleValues = LauncherIconGenerator.Options.Style.values();
-
- for (Density density : densityValues) {
- if (!density.isValidValueForDevice()) {
- continue;
- }
- if (density == Density.TV) {
- // Not yet supported -- missing stencil image
- continue;
+ case MENU:
+ generator = new MenuIconGenerator();
+ options = new GraphicGenerator.Options();
+ break;
+ case ACTIONBAR: {
+ generator = new ActionBarIconGenerator();
+ ActionBarIconGenerator.ActionBarOptions actionBarOptions =
+ new ActionBarIconGenerator.ActionBarOptions();
+ actionBarOptions.theme = mHoloDarkRadio.getSelection()
+ ? ActionBarIconGenerator.Theme.HOLO_DARK
+ : ActionBarIconGenerator.Theme.HOLO_LIGHT;
+
+ options = actionBarOptions;
+ break;
}
- options.density = density;
- for (LauncherIconGenerator.Options.Style style : styleValues) {
- options.style = style;
- LauncherIconGenerator generator = new LauncherIconGenerator(this, options);
- BufferedImage image = generator.generate();
- if (image != null) {
- imageMap.put(density.getResourceValue(), image);
- }
+ case NOTIFICATION: {
+ generator = new NotificationIconGenerator();
+ NotificationIconGenerator.NotificationOptions notificationOptions =
+ new NotificationIconGenerator.NotificationOptions();
+ notificationOptions.shape = mCircleButton.getSelection()
+ ? GraphicGenerator.Shape.CIRCLE : GraphicGenerator.Shape.SQUARE;
+ options = notificationOptions;
+ break;
}
+ case TAB:
+ generator = new TabIconGenerator();
+ options = new TabIconGenerator.TabOptions();
+ break;
+ default:
+ AdtPlugin.log(IStatus.ERROR, "Unsupported asset type: %1$s", type);
+ return categoryMap;
}
- return imageMap;
+ options.sourceImage = sourceImage;
+ String baseName = wizard.getBaseName();
+ generator.generate(null, categoryMap, this, options, baseName);
+
+ return categoryMap;
}
private void updateColor(Display display, RGB color, boolean isBackground) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureLauncherAssetsPanel.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureLauncherAssetsPanel.java
deleted file mode 100644
index 930e93c..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureLauncherAssetsPanel.java
+++ /dev/null
@@ -1,37 +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.assetstudio;
-
-import org.eclipse.swt.widgets.Composite;
-
-public class ConfigureLauncherAssetsPanel extends Composite {
-
- /**
- * Create the composite.
- * @param parent
- * @param style
- */
- public ConfigureLauncherAssetsPanel(Composite parent, int style) {
- super(parent, style);
-
- }
-
- @Override
- protected void checkSubclass() {
- // Disable the check that prevents subclassing of SWT components
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/CreateAssetSetWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/CreateAssetSetWizard.java
index 4057824..b3d7348 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/CreateAssetSetWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/CreateAssetSetWizard.java
@@ -15,10 +15,6 @@
*/
package com.android.ide.eclipse.adt.internal.assetstudio;
-import static com.android.ide.eclipse.adt.AdtConstants.DOT_PNG;
-import static com.android.ide.eclipse.adt.AdtConstants.WS_RESOURCES;
-import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP;
-
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
@@ -67,99 +63,118 @@ import java.util.Map;
import javax.imageio.ImageIO;
+/**
+ * Wizard for creating a new icon set
+ */
public class CreateAssetSetWizard extends Wizard implements INewWizard {
- private ChooseAssetTypePage chooseAssetPage;
- private ConfigureAssetSetPage configureAssetPage;
+ private ChooseAssetTypePage mChooseAssetPage;
+ private ConfigureAssetSetPage mConfigureAssetPage;
private IProject mInitialProject;
+ private List<IResource> mCreatedFiles;
+ /** Creates a new asset set wizard */
public CreateAssetSetWizard() {
setWindowTitle("Create Asset Set");
}
@Override
public void addPages() {
- chooseAssetPage = new ChooseAssetTypePage();
- chooseAssetPage.setProject(mInitialProject);
- configureAssetPage = new ConfigureAssetSetPage();
+ mChooseAssetPage = new ChooseAssetTypePage();
+ mChooseAssetPage.setProject(mInitialProject);
+ mConfigureAssetPage = new ConfigureAssetSetPage();
+
+ addPage(mChooseAssetPage);
+ addPage(mConfigureAssetPage);
+ }
- addPage(chooseAssetPage);
- addPage(configureAssetPage);
+ String getBaseName() {
+ return mChooseAssetPage.getOutputName();
}
@Override
public boolean performFinish() {
- String name = chooseAssetPage.getOutputName();
- Map<String, BufferedImage> previews = configureAssetPage.generatePreviews();
+ Map<String, Map<String, BufferedImage>> categories =
+ mConfigureAssetPage.generateImages(false);
+
IProject project = getProject();
// Write out the images into the project
boolean yesToAll = false;
- List<IFile> createdFiles = new ArrayList<IFile>();
- for (Map.Entry<String, BufferedImage> entry : previews.entrySet()) {
- String id = entry.getKey();
-
- IPath dest = new Path(WS_RESOURCES + WS_SEP + "drawable-" //$NON-NLS-1$
- + id + WS_SEP + name + DOT_PNG);
- IFile file = project.getFile(dest);
- if (file.exists()) {
- // Warn that the file already exists and ask the user what to do
- if (!yesToAll) {
- MessageDialog dialog = new MessageDialog(null, "File Already Exists", null,
- String.format("%1$s already exists.\nWould you like to replace it?",
- file.getProjectRelativePath().toOSString()),
- MessageDialog.QUESTION, new String[] {
- // Yes will be moved to the end because it's the default
- "Yes", "No", "Cancel", "Yes to All"
- }, 0);
- int result = dialog.open();
- switch (result) {
- case 0:
- // Yes
- break;
- case 3:
- // Yes to all
- yesToAll = true;
- break;
- case 1:
- // No
- continue;
- case SWT.DEFAULT:
- case 2:
- // Cancel
- return false;
+ mCreatedFiles = new ArrayList<IResource>();
+
+ for (Map<String, BufferedImage> previews : categories.values()) {
+ for (Map.Entry<String, BufferedImage> entry : previews.entrySet()) {
+ String relativePath = entry.getKey();
+ IPath dest = new Path(relativePath);
+ IFile file = project.getFile(dest);
+ if (file.exists()) {
+ // Warn that the file already exists and ask the user what to do
+ if (!yesToAll) {
+ MessageDialog dialog = new MessageDialog(null, "File Already Exists", null,
+ String.format(
+ "%1$s already exists.\nWould you like to replace it?",
+ file.getProjectRelativePath().toOSString()),
+ MessageDialog.QUESTION, new String[] {
+ // Yes will be moved to the end because it's the default
+ "Yes", "No", "Cancel", "Yes to All"
+ }, 0);
+ int result = dialog.open();
+ switch (result) {
+ case 0:
+ // Yes
+ break;
+ case 3:
+ // Yes to all
+ yesToAll = true;
+ break;
+ case 1:
+ // No
+ continue;
+ case SWT.DEFAULT:
+ case 2:
+ // Cancel
+ return false;
+ }
+ }
+
+ try {
+ file.delete(true, new NullProgressMonitor());
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
}
}
+ NewXmlFileWizard.createWsParentDirectory(file.getParent());
+ BufferedImage image = entry.getValue();
+
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
- file.delete(true, new NullProgressMonitor());
+ ImageIO.write(image, "PNG", stream); //$NON-NLS-1$
+ byte[] bytes = stream.toByteArray();
+ InputStream is = new ByteArrayInputStream(bytes);
+ file.create(is, true /*force*/, null /*progress*/);
+ mCreatedFiles.add(file);
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
} catch (CoreException e) {
AdtPlugin.log(e, null);
}
- }
- NewXmlFileWizard.createWsParentDirectory(file.getParent());
- BufferedImage image = entry.getValue();
-
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- try {
- ImageIO.write(image, "PNG", stream); //$NON-NLS-1$
- byte[] bytes = stream.toByteArray();
- InputStream is = new ByteArrayInputStream(bytes);
- file.create(is, true /*force*/, null /*progress*/);
- createdFiles.add(file);
- } catch (IOException e) {
- AdtPlugin.log(e, null);
- } catch (CoreException e) {
- AdtPlugin.log(e, null);
- }
-
- try {
- file.getParent().refreshLocal(1, new NullProgressMonitor());
- } catch (CoreException e) {
- AdtPlugin.log(e, null);
+ try {
+ file.getParent().refreshLocal(1, new NullProgressMonitor());
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
+ }
}
}
+ // Finally select the files themselves
+ selectFiles(project, mCreatedFiles);
+
+ return true;
+ }
+
+ private void selectFiles(IProject project, List<? extends IResource> createdFiles) {
// Attempt to select the newly created files in the Package Explorer
IWorkbench workbench = AdtPlugin.getDefault().getWorkbench();
IWorkbenchPage page = workbench.getActiveWorkbenchWindow().getActivePage();
@@ -172,50 +187,85 @@ public class CreateAssetSetWizard extends Wizard implements INewWizard {
} catch (CoreException e) {
AdtPlugin.log(e, null);
}
- ISelectionProvider provider = site.getSelectionProvider();
+ final ISelectionProvider provider = site.getSelectionProvider();
if (provider != null) {
List<TreePath> pathList = new ArrayList<TreePath>();
- for (IFile file : createdFiles) {
+ for (IResource file : createdFiles) {
// Create a TreePath for the given file,
// which should be the JavaProject, followed by the folders down to
// the final file.
List<Object> segments = new ArrayList<Object>();
segments.add(file);
IContainer folder = file.getParent();
- segments.add(folder);
- // res folder
- folder = folder.getParent();
- segments.add(folder);
+ if (folder != null && !(folder instanceof IProject)) {
+ segments.add(folder);
+ // res folder
+ folder = folder.getParent();
+ if (folder != null && !(folder instanceof IProject)) {
+ segments.add(folder);
+ }
+ }
// project
segments.add(javaProject);
Collections.reverse(segments);
TreePath path = new TreePath(segments.toArray());
pathList.add(path);
+
+ // IDEA: Maybe normalize the files backwards (IFile objects aren't unique)
+ // by maybe using the package explorer icons instead
}
TreePath[] paths = pathList.toArray(new TreePath[pathList.size()]);
- provider.setSelection(new TreeSelection(paths));
+ final TreeSelection selection = new TreeSelection(paths);
+
+ provider.setSelection(selection);
+
+ // Workaround: The above doesn't always work; it will frequently select
+ // some siblings of the real files. I've tried a number of workarounds:
+ // normalizing the IFile objects by looking up the canonical ones via
+ // their relative paths from the project; deferring execution with
+ // Display.asyncRun; first calling select on the parents, etc.
+ // However, it turns out a simple workaround works best: Calling this
+ // method TWICE. The first call seems to expand all the necessary parents,
+ // and the second call ensures that the correct children are selected!
+ provider.setSelection(selection);
+
+ viewPart.setFocus();
}
}
-
- return true;
}
+ /**
+ * Returns the project to be used by the wizard (which may differ from the
+ * project initialized by {@link #init(IWorkbench, IStructuredSelection)} or
+ * set by {@link #setProject(IProject)} if the user changes the project
+ * in the first page of the wizard.
+ */
IProject getProject() {
- if (chooseAssetPage != null) {
- return chooseAssetPage.getProject();
+ if (mChooseAssetPage != null) {
+ return mChooseAssetPage.getProject();
} else {
return mInitialProject;
}
}
+ /** Sets the initial project to be used by the wizard */
+ void setProject(IProject project) {
+ mInitialProject = project;
+ }
+
+ /** Returns the {@link AssetType} to create */
+ AssetType getAssetType() {
+ return mChooseAssetPage.getAssetType();
+ }
+
public void init(IWorkbench workbench, IStructuredSelection selection) {
setHelpAvailable(false);
mInitialProject = guessProject(selection);
- if (chooseAssetPage != null) {
- chooseAssetPage.setProject(mInitialProject);
+ if (mChooseAssetPage != null) {
+ mChooseAssetPage.setProject(mInitialProject);
}
}
@@ -276,4 +326,14 @@ public class CreateAssetSetWizard extends Wizard implements INewWizard {
return null;
}
+
+ /**
+ * Returns the list of files created by the wizard. This method will return
+ * null if {@link #performFinish()} has not yet been called.
+ *
+ * @return a list of files created by the wizard, or null
+ */
+ List<IResource> getCreatedFiles() {
+ return mCreatedFiles;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/OpenCreateAssetSetWizardAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/OpenCreateAssetSetWizardAction.java
new file mode 100644
index 0000000..09cc325
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/OpenCreateAssetSetWizardAction.java
@@ -0,0 +1,58 @@
+/*
+ * 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.assetstudio;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.ui.actions.AbstractOpenWizardAction;
+import org.eclipse.ui.INewWizard;
+
+import java.util.List;
+
+/** An action for opening the Create Icon Set wizard */
+public class OpenCreateAssetSetWizardAction extends AbstractOpenWizardAction {
+ private IProject mProject;
+ private CreateAssetSetWizard mWizard;
+
+ /**
+ * Creates a new {@link #OpenCreateAssetSetWizardAction} instance
+ *
+ * @param project the initial project to associate with the wizard
+ */
+ public OpenCreateAssetSetWizardAction(IProject project) {
+ mProject = project;
+ }
+
+
+ @Override
+ protected INewWizard createWizard() throws CoreException {
+ mWizard = new CreateAssetSetWizard();
+ mWizard.setProject(mProject);
+ return mWizard;
+ }
+
+ /**
+ * Returns the list of files created by the wizard. Must only be called
+ * after this action's {@link #run()} method has been called. May return
+ * null if the user cancels out of the wizard.
+ *
+ * @return a list of files created by the wizard, or null
+ */
+ public List<IResource> getCreatedFiles() {
+ return mWizard.getCreatedFiles();
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectChooserHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectChooserHelper.java
index 27b26bf..ce996f9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectChooserHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectChooserHelper.java
@@ -29,7 +29,15 @@ import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
/**
@@ -194,4 +202,78 @@ public class ProjectChooserHelper {
}
return iproject;
}
+
+ /**
+ * A selector button for showing the currently selected project and for
+ * changing the selection
+ */
+ public static class ProjectButton extends Button implements SelectionListener {
+ /** Currently chosen project, or null when no project has been initialized or selected */
+ private IProject mProject;
+
+ /**
+ * Creates a new project selector button
+ *
+ * @param parent parent composite to add the button to
+ * @param initialProject the initial project to select, or null (which
+ * will show a "Please Choose Project..." label instead.)
+ */
+ public ProjectButton(Composite parent, IProject initialProject) {
+ super(parent, SWT.BORDER | SWT.FLAT);
+ mProject = initialProject;
+ setProjectLabel(initialProject);
+ addSelectionListener(this);
+ }
+
+ /**
+ * Returns the project selected by this chooser (or the initial project
+ * passed to the constructor if the user did not change it)
+ *
+ * @return the selected project
+ */
+ public IProject getSelectedProject() {
+ return mProject;
+ }
+
+ /** Updates the selection with the given project */
+ private void setProjectLabel(IProject project) {
+ ILabelProvider labelProvider = new JavaElementLabelProvider(
+ JavaElementLabelProvider.SHOW_DEFAULT);
+ if (project == null) {
+ setText("Choose Project...");
+ ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
+ Image errorImage = sharedImages.getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
+ setImage(errorImage);
+ } else {
+ setText(labelProvider.getText(project));
+ Image projectImage = labelProvider.getImage(project);
+ if (projectImage != null) {
+ setImage(projectImage);
+ }
+ }
+ }
+
+ /**
+ * Click handler for the button: Open the {@link ProjectChooserHelper}
+ * dialog for selecting a new project.
+ */
+ public void widgetSelected(SelectionEvent e) {
+ ProjectChooserHelper helper =
+ new ProjectChooserHelper(getShell(), null /* filter */);
+ IJavaProject p = helper.chooseJavaProject(getText(),
+ "Please select the target project");
+ if (p != null) {
+ mProject = p.getProject();
+ setProjectLabel(mProject);
+ }
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ @Override
+ protected void checkSubclass() {
+ // Disable the check that prevents subclassing of SWT components
+ }
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java
index 5228ff9..f9d915b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java
@@ -287,16 +287,30 @@ public class ResourceHelper {
return false;
}
- // We can create all value types
- if (isValueBasedResourceType(type)) {
- return true;
- }
+ return canCreateResourceType(type);
+ }
- // We can create -some- file-based types - those supported by the New XML wizard:
- for (ResourceFolderType folderType : FolderTypeRelationship.getRelatedFolders(type)) {
- if (NewXmlFileWizard.canCreateXmlFile(folderType)) {
- return true;
- }
+ return false;
+ }
+
+ /**
+ * Returns true if this class can create resources of the given resource
+ * type
+ *
+ * @param type the type of resource to be created
+ * @return true if the {@link #createResource} method can create resources
+ * of this type (provided the name parameter is also valid)
+ */
+ public static boolean canCreateResourceType(ResourceType type) {
+ // We can create all value types
+ if (isValueBasedResourceType(type)) {
+ return true;
+ }
+
+ // We can create -some- file-based types - those supported by the New XML wizard:
+ for (ResourceFolderType folderType : FolderTypeRelationship.getRelatedFolders(type)) {
+ if (NewXmlFileWizard.canCreateXmlFile(folderType)) {
+ return true;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
index 856928d..75b78f5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
@@ -20,6 +20,8 @@ package com.android.ide.eclipse.adt.internal.ui;
import com.android.ide.common.resources.ResourceItem;
import com.android.ide.common.resources.ResourceRepository;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AdtUtils;
+import com.android.ide.eclipse.adt.internal.assetstudio.OpenCreateAssetSetWizardAction;
import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring;
import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringWizard;
import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
@@ -29,10 +31,12 @@ import com.android.util.Pair;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.window.Window;
import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
@@ -57,6 +61,7 @@ import org.eclipse.ui.dialogs.SelectionStatusDialog;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -77,6 +82,7 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
private Button mProjectButton;
private Button mSystemButton;
private Button mNewButton;
+ private Button mNewIconButton;
private String mCurrentResource;
private final IProject mProject;
private IInputValidator mInputValidator;
@@ -191,7 +197,7 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
super.widgetSelected(e);
if (mProjectButton.getSelection()) {
setupResourceList();
- mNewButton.setEnabled(true);
+ updateNewButton(false /*isSystem*/);
updatePreview();
}
}
@@ -204,7 +210,7 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
super.widgetSelected(e);
if (mSystemButton.getSelection()) {
setupResourceList();
- mNewButton.setEnabled(false);
+ updateNewButton(true /*isSystem*/);
updatePreview();
}
}
@@ -219,28 +225,68 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
mNewButton = new Button(top, SWT.NONE);
String title = String.format("New %1$s...", mResourceType.getDisplayName());
+ if (mResourceType == ResourceType.DRAWABLE) {
+ title = "Create New Icon...";
+ }
mNewButton.setText(title);
- // We only support adding new values right now
- mNewButton.setEnabled(ResourceHelper.isValueBasedResourceType(mResourceType));
-
mNewButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
super.widgetSelected(e);
if (mResourceType == ResourceType.STRING) {
- createNewString();
- } else {
- assert ResourceHelper.isValueBasedResourceType(mResourceType);
- String newName = createNewValue(mResourceType);
- if (newName != null) {
+ // Special case: Use Extract String refactoring wizard UI
+ String newName = createNewString();
+ selectAddedItem(newName);
+ } else if (mResourceType == ResourceType.DRAWABLE) {
+ // Special case: Use the "Create Icon Set" wizard
+ OpenCreateAssetSetWizardAction action =
+ new OpenCreateAssetSetWizardAction(mProject);
+ action.run();
+ List<IResource> files = action.getCreatedFiles();
+ if (files != null && files.size() > 0) {
+ String newName = AdtUtils.stripAllExtensions(files.get(0).getName());
// Recompute the "current resource" to select the new id
ResourceItem[] items = setupResourceList();
selectItemName(newName, items);
}
+ } else {
+ if (ResourceHelper.isValueBasedResourceType(mResourceType)) {
+ String newName = createNewValue(mResourceType);
+ selectAddedItem(newName);
+ } else {
+ String newName = createNewFile(mResourceType);
+ selectAddedItem(newName);
+ }
}
}
+
+ private void selectAddedItem(String newName) {
+ // Recompute the "current resource" to select the new id
+ ResourceItem[] items = setupResourceList();
+
+ // Ensure that the name is in the list. There's a delay after
+ // an item is added (until the builder runs and processes the delta)
+ // so if it's not in the list, add it
+ boolean found = false;
+ for (ResourceItem item : items) {
+ if (newName.equals(item.getName())) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ResourceItem[] newItems = new ResourceItem[items.length + 1];
+ System.arraycopy(items, 0, newItems, 0, items.length);
+ newItems[items.length] = new ResourceItem(newName);
+ items = newItems;
+ Arrays.sort(items);
+ setListElements(items);
+ }
+
+ selectItemName(newName, items);
+ }
});
}
@@ -273,6 +319,38 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
}
}
+ private String createNewFile(ResourceType type) {
+ // Show a name/value dialog entering the key name and the value
+ Shell shell = AdtPlugin.getDisplay().getActiveShell();
+ if (shell == null) {
+ return null;
+ }
+
+ ResourceNameValidator validator = ResourceNameValidator.create(true /*allowXmlExtension*/,
+ mProject, mResourceType);
+ InputDialog d = new InputDialog(
+ AdtPlugin.getDisplay().getActiveShell(),
+ "Enter name", // title
+ "Enter name",
+ "", //$NON-NLS-1$
+ validator);
+ if (d.open() == Window.OK) {
+ String name = d.getValue().trim();
+ if (name.length() == 0) {
+ return null;
+ }
+
+ Pair<IFile, IRegion> resource = ResourceHelper.createResource(mProject, type, name,
+ null);
+ if (resource != null) {
+ return name;
+ }
+ }
+
+ return null;
+ }
+
+
private String createNewValue(ResourceType type) {
// Show a name/value dialog entering the key name and the value
Shell shell = AdtPlugin.getDisplay().getActiveShell();
@@ -298,7 +376,7 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
return null;
}
- private void createNewString() {
+ private String createNewString() {
ExtractStringRefactoring ref = new ExtractStringRefactoring(
mProject, true /*enforceNew*/);
RefactoringWizard wizard = new ExtractStringWizard(ref, mProject);
@@ -307,16 +385,13 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
IWorkbench w = PlatformUI.getWorkbench();
if (op.run(w.getDisplay().getActiveShell(), wizard.getDefaultPageTitle()) ==
IDialogConstants.OK_ID) {
-
- // Recompute the "current resource" to select the new id
- ResourceItem[] items = setupResourceList();
-
- // select it if possible
- selectItemName(ref.getXmlStringId(), items);
+ return ref.getXmlStringId();
}
} catch (InterruptedException ex) {
// Interrupted. Pass.
}
+
+ return null;
}
/**
@@ -389,7 +464,7 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
// Update the repository selection
mProjectButton.setSelection(!isSystem);
mSystemButton.setSelection(isSystem);
- mNewButton.setEnabled(!isSystem);
+ updateNewButton(isSystem);
// Update the list
ResourceItem[] items = setupResourceList();
@@ -400,6 +475,10 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
}
}
+ private void updateNewButton(boolean isSystem) {
+ mNewButton.setEnabled(!isSystem && ResourceHelper.canCreateResourceType(mResourceType));
+ }
+
/** Dialog asking for a Name/Value pair */
private class NameValueDialog extends SelectionStatusDialog implements Listener {
private org.eclipse.swt.widgets.Text mNameText;
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java
index 6f56f73..f4daf59 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java
@@ -17,6 +17,7 @@ package com.android.ide.eclipse.adt;
import junit.framework.TestCase;
+@SuppressWarnings("javadoc")
public class AdtUtilsTest extends TestCase {
public void testEndsWithIgnoreCase() {
assertTrue(AdtUtils.endsWithIgnoreCase("foo", "foo"));
@@ -36,6 +37,22 @@ public class AdtUtilsTest extends TestCase {
assertEquals("foobar", AdtUtils.stripWhitespace(" foo bar \n\t"));
}
+ public void testStripAllExtensions() {
+ assertEquals("", AdtUtils.stripAllExtensions(""));
+ assertEquals("foobar", AdtUtils.stripAllExtensions("foobar"));
+ assertEquals("foobar", AdtUtils.stripAllExtensions("foobar.png"));
+ assertEquals("foobar", AdtUtils.stripAllExtensions("foobar.9.png"));
+ assertEquals(".profile", AdtUtils.stripAllExtensions(".profile"));
+ }
+
+ public void testStripLastExtension() {
+ assertEquals("", AdtUtils.stripLastExtension(""));
+ assertEquals("foobar", AdtUtils.stripLastExtension("foobar"));
+ assertEquals("foobar", AdtUtils.stripLastExtension("foobar.png"));
+ assertEquals("foobar.9", AdtUtils.stripLastExtension("foobar.9.png"));
+ assertEquals(".profile", AdtUtils.stripLastExtension(".profile"));
+ }
+
public void testCapitalize() {
assertEquals("UPPER", AdtUtils.capitalize("UPPER"));
assertEquals("Lower", AdtUtils.capitalize("lower"));
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java
index d05e54f..6340528 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java
@@ -32,6 +32,7 @@ import junit.framework.TestCase;
/**
* Test ResourceHelper
*/
+@SuppressWarnings("javadoc")
public class ResourceHelperTest extends TestCase {
/**
@@ -170,6 +171,16 @@ public class ResourceHelperTest extends TestCase {
assertFalse(ResourceHelper.canCreateResource("@android:color/foo"));
}
+ public void testCanCreateResourceType() throws Exception {
+ assertTrue(ResourceHelper.canCreateResourceType(ResourceType.LAYOUT));
+ assertTrue(ResourceHelper.canCreateResourceType(ResourceType.STRING));
+ assertTrue(ResourceHelper.canCreateResourceType(ResourceType.DIMEN));
+ assertTrue(ResourceHelper.canCreateResourceType(ResourceType.COLOR));
+
+ assertFalse(ResourceHelper.canCreateResourceType(ResourceType.RAW));
+ assertFalse(ResourceHelper.canCreateResourceType(ResourceType.XML));
+ }
+
public void testStyleToTheme() throws Exception {
assertEquals("Foo", ResourceHelper.styleToTheme("Foo"));
assertEquals("Theme", ResourceHelper.styleToTheme("@android:style/Theme"));