aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--assetstudio/.classpath4
-rw-r--r--assetstudio/src/com/android/assetstudiolib/ActionBarIconGenerator.java92
-rw-r--r--assetstudio/src/com/android/assetstudiolib/GraphicGenerator.java160
-rw-r--r--assetstudio/src/com/android/assetstudiolib/LauncherIconGenerator.java165
-rw-r--r--assetstudio/src/com/android/assetstudiolib/MenuIconGenerator.java100
-rw-r--r--assetstudio/src/com/android/assetstudiolib/NotificationIconGenerator.java175
-rw-r--r--assetstudio/src/com/android/assetstudiolib/TabIconGenerator.java188
-rw-r--r--assetstudio/src/com/android/assetstudiolib/TextRenderUtil.java45
-rw-r--r--assetstudio/src/com/android/assetstudiolib/Util.java2
-rw-r--r--assetstudio/src/images/notification_stencil/circle/hdpi.pngbin0 -> 1260 bytes
-rw-r--r--assetstudio/src/images/notification_stencil/circle/ldpi.pngbin0 -> 751 bytes
-rw-r--r--assetstudio/src/images/notification_stencil/circle/mdpi.pngbin0 -> 925 bytes
-rw-r--r--assetstudio/src/images/notification_stencil/circle/xhdpi.pngbin0 -> 2596 bytes
-rw-r--r--assetstudio/src/images/notification_stencil/square/hdpi.pngbin0 -> 519 bytes
-rw-r--r--assetstudio/src/images/notification_stencil/square/ldpi.pngbin0 -> 395 bytes
-rw-r--r--assetstudio/src/images/notification_stencil/square/mdpi.pngbin0 -> 491 bytes
-rw-r--r--assetstudio/src/images/notification_stencil/square/xhdpi.pngbin0 -> 1534 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/ActionBarIconGeneratorTest.java41
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/GeneratorTest.java225
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/LauncherIconGeneratorTest.java48
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/MenuIconGeneratorTest.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureLauncherAssetsPanel.java)24
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/NotificationIconGeneratorTest.java41
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/TabIconGeneratorTest.java31
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-hdpi/ic_action_dark.pngbin0 -> 1293 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-hdpi/ic_action_light.pngbin0 -> 646 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-ldpi/ic_action_dark.pngbin0 -> 548 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-ldpi/ic_action_light.pngbin0 -> 337 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-mdpi/ic_action_dark.pngbin0 -> 813 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-mdpi/ic_action_light.pngbin0 -> 481 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-xhdpi/ic_action_dark.pngbin0 -> 1975 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-xhdpi/ic_action_light.pngbin0 -> 859 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/blue_glossy_square-web.pngbin0 -> 65994 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/red_fancy_circle-web.pngbin0 -> 80075 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-hdpi/blue_glossy_square.pngbin0 -> 4931 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-hdpi/red_fancy_circle.pngbin0 -> 4686 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-ldpi/blue_glossy_square.pngbin0 -> 2018 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-ldpi/red_fancy_circle.pngbin0 -> 1876 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-mdpi/blue_glossy_square.pngbin0 -> 3061 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-mdpi/red_fancy_circle.pngbin0 -> 2731 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-xhdpi/blue_glossy_square.pngbin0 -> 6746 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-xhdpi/red_fancy_circle.pngbin0 -> 6903 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-hdpi/ic_menu_1.pngbin0 -> 1888 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-ldpi/ic_menu_1.pngbin0 -> 879 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-mdpi/ic_menu_1.pngbin0 -> 1186 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-xhdpi/ic_menu_1.pngbin0 -> 2525 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v11/ic_stat_circle.pngbin0 -> 550 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v11/ic_stat_square.pngbin0 -> 550 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v9/ic_stat_circle.pngbin0 -> 619 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v9/ic_stat_square.pngbin0 -> 619 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi/ic_stat_circle.pngbin0 -> 1406 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi/ic_stat_square.pngbin0 -> 1066 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v11/ic_stat_circle.pngbin0 -> 301 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v11/ic_stat_square.pngbin0 -> 301 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v9/ic_stat_circle.pngbin0 -> 343 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v9/ic_stat_square.pngbin0 -> 343 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi/ic_stat_circle.pngbin0 -> 647 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi/ic_stat_square.pngbin0 -> 503 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v11/ic_stat_circle.pngbin0 -> 399 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v11/ic_stat_square.pngbin0 -> 399 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v9/ic_stat_circle.pngbin0 -> 412 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v9/ic_stat_square.pngbin0 -> 412 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi/ic_stat_circle.pngbin0 -> 881 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi/ic_stat_square.pngbin0 -> 687 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v11/ic_stat_circle.pngbin0 -> 731 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v11/ic_stat_square.pngbin0 -> 731 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v9/ic_stat_circle.pngbin0 -> 735 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v9/ic_stat_square.pngbin0 -> 735 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi/ic_stat_circle.pngbin0 -> 1958 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi/ic_stat_square.pngbin0 -> 1506 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi-v5/ic_tab_1_selected.pngbin0 -> 1577 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi-v5/ic_tab_1_unselected.pngbin0 -> 724 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi/ic_tab_1_selected.pngbin0 -> 1667 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi/ic_tab_1_unselected.pngbin0 -> 1560 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi-v5/ic_tab_1_selected.pngbin0 -> 704 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi-v5/ic_tab_1_unselected.pngbin0 -> 403 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi/ic_tab_1_selected.pngbin0 -> 725 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi/ic_tab_1_unselected.pngbin0 -> 719 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi-v5/ic_tab_1_selected.pngbin0 -> 940 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi-v5/ic_tab_1_unselected.pngbin0 -> 501 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi/ic_tab_1_selected.pngbin0 -> 1003 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi/ic_tab_1_unselected.pngbin0 -> 968 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi-v5/ic_tab_1_selected.pngbin0 -> 2270 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi-v5/ic_tab_1_unselected.pngbin0 -> 978 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi/ic_tab_1_selected.pngbin0 -> 2289 bytes
-rw-r--r--assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi/ic_tab_1_unselected.pngbin0 -> 2159 bytes
-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/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
97 files changed, 2132 insertions, 476 deletions
diff --git a/assetstudio/.classpath b/assetstudio/.classpath
index ee79d96..53a77a1 100644
--- a/assetstudio/.classpath
+++ b/assetstudio/.classpath
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="tests/src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="output" path="bin"/>
<classpathentry combineaccessrules="false" kind="src" path="/common"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+ <classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/assetstudio/src/com/android/assetstudiolib/ActionBarIconGenerator.java b/assetstudio/src/com/android/assetstudiolib/ActionBarIconGenerator.java
new file mode 100644
index 0000000..b54aad5
--- /dev/null
+++ b/assetstudio/src/com/android/assetstudiolib/ActionBarIconGenerator.java
@@ -0,0 +1,92 @@
+/*
+ * 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.assetstudiolib;
+
+import com.android.assetstudiolib.Util.Effect;
+import com.android.assetstudiolib.Util.FillEffect;
+import com.android.assetstudiolib.Util.ShadowEffect;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+
+/**
+ * Generate icons for the action bar
+ */
+public class ActionBarIconGenerator extends GraphicGenerator {
+
+ /** Creates a new {@link ActionBarIconGenerator} */
+ public ActionBarIconGenerator() {
+ }
+
+ @Override
+ public BufferedImage generate(GraphicGeneratorContext context, Options options) {
+ Rectangle iconSizeHdpi = new Rectangle(0, 0, 48, 48);
+ Rectangle targetRectHdpi = new Rectangle(6, 6, 36, 36);
+ final float scaleFactor = GraphicGenerator.getHdpiScaleFactor(options.density);
+ Rectangle imageRect = Util.scaleRectangle(iconSizeHdpi, scaleFactor);
+ Rectangle targetRect = Util.scaleRectangle(targetRectHdpi, scaleFactor);
+ BufferedImage outImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height);
+ Graphics2D g = (Graphics2D) outImage.getGraphics();
+
+ BufferedImage tempImage = Util.newArgbBufferedImage(
+ imageRect.width, imageRect.height);
+ Graphics2D g2 = (Graphics2D) tempImage.getGraphics();
+ Util.drawCenterInside(g2, options.sourceImage, targetRect);
+
+ ActionBarOptions actionBarOptions = (ActionBarOptions) options;
+ if (actionBarOptions.theme == Theme.HOLO_LIGHT) {
+ Util.drawEffects(g, tempImage, 0, 0, new Effect[] {
+ new FillEffect(new Color(0x898989)),
+ });
+ } else {
+ assert actionBarOptions.theme == Theme.HOLO_DARK;
+ Util.drawEffects(g, tempImage, 0, 0, new Effect[] {
+ // TODO: should be white @ 60% opacity, but
+ // the fill then blends with the drop shadow
+ new FillEffect(new Color(0x909090)),
+ new ShadowEffect(
+ 0,
+ 0,
+ 3 * scaleFactor,
+ Color.BLACK,
+ 0.85,
+ false),
+ });
+ }
+
+ g.dispose();
+ g2.dispose();
+
+ return outImage;
+ }
+
+ /** Options specific to generating action bar icons */
+ public static class ActionBarOptions extends GraphicGenerator.Options {
+ /** The theme to generate icons for */
+ public Theme theme = Theme.HOLO_LIGHT;
+ }
+
+ /** The themes to generate action bar icons for */
+ public enum Theme {
+ /** Theme.Holo - a dark (and default) version of the Honeycomb theme */
+ HOLO_DARK,
+
+ /** Theme.HoloLight - a light version of the Honeycomb theme */
+ HOLO_LIGHT;
+ }
+}
diff --git a/assetstudio/src/com/android/assetstudiolib/GraphicGenerator.java b/assetstudio/src/com/android/assetstudiolib/GraphicGenerator.java
index 902b21d..dea6eeb 100644
--- a/assetstudio/src/com/android/assetstudiolib/GraphicGenerator.java
+++ b/assetstudio/src/com/android/assetstudiolib/GraphicGenerator.java
@@ -26,9 +26,13 @@ import java.net.URISyntaxException;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -38,15 +42,165 @@ import javax.imageio.ImageIO;
/**
* The base Generator class.
*/
-public class GraphicGenerator {
+public abstract class GraphicGenerator {
/**
* Options used for all generators.
*/
public static class Options {
+ /** Source image to use as a basis for the icon */
+ public BufferedImage sourceImage;
+ /** The density to generate the icon with */
+ public Density density = Density.XHIGH;
}
- public static float getScaleFactor(Density density) {
- return density.getDpiValue() / (float) Density.DEFAULT_DENSITY;
+ /** Shapes that can be used for icon backgrounds */
+ public static enum Shape {
+ /** Circular background */
+ CIRCLE("circle"),
+ /** Square background */
+ SQUARE("square");
+
+ /** Id, used in filenames to identify associated stencils */
+ public final String id;
+
+ Shape(String id) {
+ this.id = id;
+ }
+ }
+
+ /** Foreground effects styles */
+ public static enum Style {
+ /** No effects */
+ SIMPLE("fore1"),
+ /** "Fancy" effects */
+ FANCY("fore2"),
+ /** A glossy look */
+ GLOSSY("fore3");
+
+ /** Id, used in filenames to identify associated stencils */
+ public final String id;
+
+ Style(String id) {
+ this.id = id;
+ }
+ }
+
+ /**
+ * Generate a single icon using the given options
+ *
+ * @param context render context to use for looking up resources etc
+ * @param options options controlling the appearance of the icon
+ * @return a {@link BufferedImage} with the generated icon
+ */
+ public abstract BufferedImage generate(GraphicGeneratorContext context, Options options);
+
+ /**
+ * Computes the target filename (relative to the Android project folder)
+ * where an icon rendered with the given options should be stored. This is
+ * also used as the map keys in the result map used by
+ * {@link #generate(String, Map, GraphicGeneratorContext, Options, String)}.
+ *
+ * @param options the options object used by the generator for the current
+ * image
+ * @param name the base name to use when creating the path
+ * @return a path relative to the res/ folder where the image should be
+ * stored (will always use / as a path separator, not \ on Windows)
+ */
+ protected String getIconPath(Options options, String name) {
+ return getIconFolder(options) + '/' + getIconName(options, name);
+ }
+
+ /**
+ * Gets name of the file itself. It is sometimes modified by options, for
+ * example in unselected tabs we change foo.png to foo-unselected.png
+ */
+ protected String getIconName(Options options, String name) {
+ return name + ".png"; //$NON-NLS-1$
+ }
+
+ /**
+ * Gets name of the folder to contain the resource. It usually includes the
+ * density, but is also sometimes modified by options. For example, in some
+ * notification icons we add in -v9 or -v11.
+ */
+ protected String getIconFolder(Options options) {
+ return "res/drawable-" + options.density.getResourceValue(); //$NON-NLS-1$
+ }
+
+ /**
+ * Generates a full set of icons into the given map. The values in the map
+ * will be the generated images, and each value is keyed by the
+ * corresponding relative path of the image, which is determined by the
+ * {@link #getIconPath(Options, String)} method.
+ *
+ * @param category the current category to place images into (if null the
+ * density name will be used)
+ * @param categoryMap the map to put images into, should not be null. The
+ * map is a map from a category name, to a map from file path to
+ * image.
+ * @param context a generator context which for example can load resources
+ * @param options options to apply to this generator
+ * @param name the base name of the icons to generate
+ */
+ public void generate(String category, Map<String, Map<String, BufferedImage>> categoryMap,
+ GraphicGeneratorContext context, Options options, String name) {
+ 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();
+ }
+ });
+
+ for (Density density : densityValues) {
+ if (!density.isValidValueForDevice()) {
+ continue;
+ }
+ if (density == Density.TV) {
+ // Not yet supported -- missing stencil image
+ continue;
+ }
+ options.density = density;
+ BufferedImage image = generate(context, options);
+ if (image != null) {
+ String mapCategory = category;
+ if (mapCategory == null) {
+ mapCategory = options.density.getResourceValue();
+ }
+ Map<String, BufferedImage> imageMap = categoryMap.get(mapCategory);
+ if (imageMap == null) {
+ imageMap = new LinkedHashMap<String, BufferedImage>();
+ categoryMap.put(mapCategory, imageMap);
+ }
+ imageMap.put(getIconPath(options, name), image);
+ }
+ }
+ }
+
+ /**
+ * Returns the scale factor to apply for a given HDPI density to compute the
+ * absolute pixel count to use to draw an icon of the given target density
+ *
+ * @param density the density
+ * @return a factor to multiple hdpi distances with to compute the target density
+ */
+ public static float getHdpiScaleFactor(Density density) {
+ // We used to do this:
+ //return density.getDpiValue() / (float) Density.DEFAULT_DENSITY;
+ // However, the HTML5 version of the AssetStudio would end up with different
+ // sizes for the assets, because it uses this table:
+ // studio.util.getMultBaseHdpi = function(density) {
+ // switch (density) {
+ // case 'xhdpi': return 1.333333;
+ // case 'hdpi': return 1.0;
+ // case 'mdpi': return 0.666667;
+ // case 'ldpi': return 0.5;
+ // }
+ // return 1.0;
+ // };
+ // This corresponds to dividing the dpi value not by Density.MEDIUM but
+ // Density.HIGH:
+ return density.getDpiValue() / (float) Density.HIGH.getDpiValue();
}
/**
diff --git a/assetstudio/src/com/android/assetstudiolib/LauncherIconGenerator.java b/assetstudio/src/com/android/assetstudiolib/LauncherIconGenerator.java
index b6715a4..66cb6ae 100644
--- a/assetstudio/src/com/android/assetstudiolib/LauncherIconGenerator.java
+++ b/assetstudio/src/com/android/assetstudiolib/LauncherIconGenerator.java
@@ -16,93 +16,136 @@
package com.android.assetstudiolib;
-import com.android.resources.Density;
-
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
+import java.util.HashMap;
+import java.util.Map;
/**
* A {@link GraphicGenerator} that generates Android "launcher" icons.
*/
public class LauncherIconGenerator extends GraphicGenerator {
- private static final Rectangle BASE_IMAGE_RECT = new Rectangle(0, 0, 48, 48);
- private static final Rectangle BASE_TARGET_RECT = new Rectangle(4, 4, 40, 40);
-
- private Options mOptions;
- private BufferedImage mBackImage;
- private BufferedImage mMaskImage;
- private BufferedImage mForeImage;
-
- public LauncherIconGenerator(GraphicGeneratorContext context, Options options) {
- mOptions = options;
- mBackImage = context.loadImageResource("/images/launcher_stencil/"
- + options.shape.id + "/" + options.density.getResourceValue() + "/back.png");
- mForeImage = context.loadImageResource("/images/launcher_stencil/"
- + options.shape.id + "/" + options.density.getResourceValue() + "/"
- + options.style.id + ".png");
- mMaskImage = context.loadImageResource("/images/launcher_stencil/"
- + options.shape.id + "/" + options.density.getResourceValue() + "/mask.png");
- }
-
- public BufferedImage generate() {
- final float scaleFactor = GraphicGenerator.getScaleFactor(mOptions.density);
- Rectangle imageRect = Util.scaleRectangle(BASE_IMAGE_RECT, scaleFactor);
- Rectangle targetRect = Util.scaleRectangle(BASE_TARGET_RECT, scaleFactor);
+ private static final Rectangle IMAGE_SIZE_HDPI = new Rectangle(0, 0, 72, 72);
+ /* TODO: Adapt from html version:
+ 'square-web-targetRect': { x: 57, y: 57, w: 398, h: 398 },
+ 'circle-web-targetRect': { x: 42, y: 42, w: 428, h: 428 },
+ 'square-xhdpi-targetRect': { x: 11, y: 11, w: 74, h: 74 },
+ 'circle-xhdpi-targetRect': { x: 8, y: 8, w: 80, h: 80 },
+ 'square-hdpi-targetRect': { x: 8, y: 8, w: 56, h: 56 },
+ 'circle-hdpi-targetRect': { x: 6, y: 6, w: 60, h: 60 }, <====
+ 'square-mdpi-targetRect': { x: 5, y: 5, w: 38, h: 38 },
+ 'circle-mdpi-targetRect': { x: 4, y: 4, w: 40, h: 40 },
+ 'square-ldpi-targetRect': { x: 4, y: 4, w: 28, h: 28 },
+ 'circle-ldpi-targetRect': { x: 3, y: 3, w: 30, h: 30 }
+ */
+ private static final Rectangle TARGET_RECT_HDPI = new Rectangle(6, 6, 60, 60);
+
+ @Override
+ public BufferedImage generate(GraphicGeneratorContext context, Options options) {
+ LauncherOptions launcherOptions = (LauncherOptions) options;
+
+ String density;
+ if (launcherOptions.isWebGraphic) {
+ density = "web";
+ } else {
+ density = launcherOptions.density.getResourceValue();
+ }
+ String shape = launcherOptions.shape.id;
+ BufferedImage mBackImage = context.loadImageResource("/images/launcher_stencil/"
+ + shape + "/" + density + "/back.png");
+ BufferedImage mForeImage = context.loadImageResource("/images/launcher_stencil/"
+ + shape + "/" + density + "/" + launcherOptions.style.id + ".png");
+ BufferedImage mMaskImage = context.loadImageResource("/images/launcher_stencil/"
+ + shape + "/" + density + "/mask.png");
+
+ float scaleFactor = GraphicGenerator.getHdpiScaleFactor(launcherOptions.density);
+ if (launcherOptions.isWebGraphic) {
+ // Target size for the web graphic is 512
+ scaleFactor = 512 / (float) IMAGE_SIZE_HDPI.height;
+ }
+ Rectangle imageRect = Util.scaleRectangle(IMAGE_SIZE_HDPI, scaleFactor);
+ Rectangle targetRect = Util.scaleRectangle(TARGET_RECT_HDPI, scaleFactor);
BufferedImage outImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height);
Graphics2D g = (Graphics2D) outImage.getGraphics();
g.drawImage(mBackImage, 0, 0, null);
- {
- BufferedImage tempImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height);
- Graphics2D g2 = (Graphics2D) tempImage.getGraphics();
- g2.drawImage(mMaskImage, 0, 0, null);
- g2.setComposite(AlphaComposite.SrcAtop);
- g2.setPaint(new Color(mOptions.backgroundColor));
- g2.fillRect(0, 0, imageRect.width, imageRect.height);
-
- if (mOptions.crop) {
- Util.drawCenterCrop(g2, mOptions.sourceImage, targetRect);
- } else {
- Util.drawCenterInside(g2, mOptions.sourceImage, targetRect);
- }
-
- g.drawImage(tempImage, 0, 0, null);
+ BufferedImage tempImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height);
+ Graphics2D g2 = (Graphics2D) tempImage.getGraphics();
+ g2.drawImage(mMaskImage, 0, 0, null);
+ g2.setComposite(AlphaComposite.SrcAtop);
+ g2.setPaint(new Color(launcherOptions.backgroundColor));
+ g2.fillRect(0, 0, imageRect.width, imageRect.height);
+
+ if (launcherOptions.crop) {
+ Util.drawCenterCrop(g2, launcherOptions.sourceImage, targetRect);
+ } else {
+ Util.drawCenterInside(g2, launcherOptions.sourceImage, targetRect);
}
+ g.drawImage(tempImage, 0, 0, null);
g.drawImage(mForeImage, 0, 0, null);
+
+ g.dispose();
+ g2.dispose();
+
return outImage;
}
- public static class Options {
- public BufferedImage sourceImage;
- public int backgroundColor = 0;
- public boolean crop = true;
- public Shape shape = Shape.SQUARE;
- public Style style = Style.SIMPLE;
- public Density density = Density.XHIGH;
+ @Override
+ public void generate(String category, Map<String, Map<String, BufferedImage>> categoryMap,
+ GraphicGeneratorContext context, Options options, String name) {
+ LauncherOptions launcherOptions = (LauncherOptions) options;
+ boolean generateWebImage = launcherOptions.isWebGraphic;
+ launcherOptions.isWebGraphic = false;
+ super.generate(category, categoryMap, context, options, name);
+
+ if (generateWebImage) {
+ launcherOptions.isWebGraphic = true;
+ BufferedImage image = generate(context, options);
+ if (image != null) {
+ Map<String, BufferedImage> imageMap = new HashMap<String, BufferedImage>();
+ categoryMap.put("Web", imageMap);
+ imageMap.put(getIconPath(options, name), image);
+ }
+ }
+ }
- public static enum Shape {
- CIRCLE("circle"), SQUARE("square");
+ @Override
+ protected String getIconPath(Options options, String name) {
+ if (((LauncherOptions) options).isWebGraphic) {
+ return name + "-web.png"; // Store at the root of the project
+ }
- public String id;
+ return super.getIconPath(options, name);
+ }
- Shape(String id) {
- this.id = id;
- }
- }
+ /** Options specific to generating launcher icons */
+ public static class LauncherOptions extends GraphicGenerator.Options {
+ /** Background color, as an RRGGBB packed integer */
+ public int backgroundColor = 0;
- public static enum Style {
- SIMPLE("fore1"), FANCY("fore2"), GLOSSY("fore3");
+ /** Whether the image should be cropped or not */
+ public boolean crop = true;
- public String id;
+ /** The shape to use for the background */
+ public Shape shape = Shape.SQUARE;
- Style(String id) {
- this.id = id;
- }
- }
+ /** The effects to apply to the foreground */
+ public Style style = Style.SIMPLE;
+
+ /**
+ * Whether a web graphic should be generated (will ignore normal density
+ * setting). The {@link #generate(GraphicGeneratorContext, Options)}
+ * method will use this to decide whether to generate a normal density
+ * icon or a high res web image. The
+ * {@link GraphicGenerator#generate(String, Map, GraphicGeneratorContext, Options, String)}
+ * method will use this flag to determine whether it should include a
+ * web graphic in its iteration.
+ */
+ public boolean isWebGraphic;
}
}
diff --git a/assetstudio/src/com/android/assetstudiolib/MenuIconGenerator.java b/assetstudio/src/com/android/assetstudiolib/MenuIconGenerator.java
index 07b7a6b..8fdbddf 100644
--- a/assetstudio/src/com/android/assetstudiolib/MenuIconGenerator.java
+++ b/assetstudio/src/com/android/assetstudiolib/MenuIconGenerator.java
@@ -16,7 +16,9 @@
package com.android.assetstudiolib;
-import com.android.resources.Density;
+import com.android.assetstudiolib.Util.Effect;
+import com.android.assetstudiolib.Util.FillEffect;
+import com.android.assetstudiolib.Util.ShadowEffect;
import java.awt.Color;
import java.awt.GradientPaint;
@@ -28,65 +30,59 @@ import java.awt.image.BufferedImage;
* A {@link GraphicGenerator} that generates Android "menu" icons.
*/
public class MenuIconGenerator extends GraphicGenerator {
- private static final Rectangle BASE_IMAGE_RECT = new Rectangle(0, 0, 48, 48);
- private static final Rectangle BASE_TARGET_RECT = new Rectangle(8, 8, 32, 32);
-
- private Options mOptions;
-
- public MenuIconGenerator(GraphicGeneratorContext context, Options options) {
- mOptions = options;
+ /** Creates a menu icon generator */
+ public MenuIconGenerator() {
}
- public BufferedImage generate() {
- final float scaleFactor = GraphicGenerator.getScaleFactor(mOptions.density);
- Rectangle imageRect = Util.scaleRectangle(BASE_IMAGE_RECT, scaleFactor);
- Rectangle targetRect = Util.scaleRectangle(BASE_TARGET_RECT, scaleFactor);
+ @Override
+ public BufferedImage generate(GraphicGeneratorContext context, Options options) {
+ Rectangle imageSizeHdpi = new Rectangle(0, 0, 72, 72);
+ Rectangle targetRectHdpi = new Rectangle(12, 12, 48, 48);
+ float scaleFactor = GraphicGenerator.getHdpiScaleFactor(options.density);
+ Rectangle imageRect = Util.scaleRectangle(imageSizeHdpi, scaleFactor);
+ Rectangle targetRect = Util.scaleRectangle(targetRectHdpi, scaleFactor);
BufferedImage outImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height);
Graphics2D g = (Graphics2D) outImage.getGraphics();
- {
- BufferedImage tempImage = Util.newArgbBufferedImage(
- imageRect.width, imageRect.height);
- Graphics2D g2 = (Graphics2D) tempImage.getGraphics();
- Util.drawCenterInside(g2, mOptions.sourceImage, targetRect);
+ BufferedImage tempImage = Util.newArgbBufferedImage(
+ imageRect.width, imageRect.height);
+ Graphics2D g2 = (Graphics2D) tempImage.getGraphics();
+ Util.drawCenterInside(g2, options.sourceImage, targetRect);
- Util.drawEffects(g, tempImage, 0, 0, new Util.Effect[]{
- new Util.FillEffect(
- new GradientPaint(
- 0, 0,
- new Color(0xa3a3a3),
- 0, imageRect.height,
- new Color(0x787878))),
- new Util.ShadowEffect(
- 0,
- 3 * scaleFactor,
- 3 * scaleFactor,
- Color.black,
- 0.2,
- true),
- new Util.ShadowEffect(
- 0,
- 1,
- 0,
- Color.black,
- 0.35,
- true),
- new Util.ShadowEffect(
- 0,
- -1,
- 0,
- Color.white,
- 0.35,
- true),
- });
- }
+ Util.drawEffects(g, tempImage, 0, 0, new Effect[] {
+ new FillEffect(
+ new GradientPaint(
+ 0, 0,
+ new Color(0xa3a3a3),
+ 0, imageRect.height,
+ new Color(0x787878))),
+ new ShadowEffect(
+ 0,
+ 3 * scaleFactor,
+ 3 * scaleFactor,
+ Color.BLACK,
+ 0.2,
+ true),
+ new ShadowEffect(
+ 0,
+ 1,
+ 0,
+ Color.BLACK,
+ 0.35,
+ true),
+ new ShadowEffect(
+ 0,
+ -1,
+ 0,
+ Color.WHITE,
+ 0.35,
+ true),
+ });
- return outImage;
- }
+ g.dispose();
+ g2.dispose();
- public static class Options {
- public BufferedImage sourceImage;
- public Density density = Density.XHIGH;
+ return outImage;
}
}
diff --git a/assetstudio/src/com/android/assetstudiolib/NotificationIconGenerator.java b/assetstudio/src/com/android/assetstudiolib/NotificationIconGenerator.java
new file mode 100644
index 0000000..1237a89
--- /dev/null
+++ b/assetstudio/src/com/android/assetstudiolib/NotificationIconGenerator.java
@@ -0,0 +1,175 @@
+/*
+ * 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.assetstudiolib;
+
+import com.android.assetstudiolib.Util.Effect;
+import com.android.assetstudiolib.Util.FillEffect;
+import com.android.assetstudiolib.Util.ShadowEffect;
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.util.Map;
+
+/**
+ * Generate icons for the notifications bar
+ */
+public class NotificationIconGenerator extends GraphicGenerator {
+ /** Creates a new {@link NotificationIconGenerator} */
+ public NotificationIconGenerator() {
+ }
+
+ @Override
+ public BufferedImage generate(GraphicGeneratorContext context, Options options) {
+ Rectangle iconSizeHdpi;
+ Rectangle targetRectHdpi;
+ NotificationOptions notificationOptions = (NotificationOptions) options;
+ if (notificationOptions.version == Version.OLDER) {
+ iconSizeHdpi = new Rectangle(0, 0, 38, 38);
+ targetRectHdpi = new Rectangle(6, 6, 26, 26);
+ } else if (notificationOptions.version == Version.V11) {
+ iconSizeHdpi = new Rectangle(0, 0, 48, 48);
+ targetRectHdpi = new Rectangle(6, 6, 36, 36);
+ } else {
+ assert notificationOptions.version == Version.V9;
+ iconSizeHdpi = new Rectangle(0, 0, 24, 38);
+ targetRectHdpi = new Rectangle(0, 7, 24, 24);
+ }
+
+ final float scaleFactor = GraphicGenerator.getHdpiScaleFactor(options.density);
+ Rectangle imageRect = Util.scaleRectangle(iconSizeHdpi, scaleFactor);
+ Rectangle targetRect = Util.scaleRectangle(targetRectHdpi, scaleFactor);
+
+ BufferedImage outImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height);
+ Graphics2D g = (Graphics2D) outImage.getGraphics();
+
+ BufferedImage tempImage = Util.newArgbBufferedImage(
+ imageRect.width, imageRect.height);
+ Graphics2D g2 = (Graphics2D) tempImage.getGraphics();
+
+ if (notificationOptions.version == Version.OLDER) {
+ BufferedImage mBackImage = context.loadImageResource(
+ "/images/notification_stencil/"
+ + notificationOptions.shape.id + '/' +
+ notificationOptions.density.getResourceValue()
+ + ".png");
+ g.drawImage(mBackImage, 0, 0, null);
+ BufferedImage top = options.sourceImage;
+ BufferedImage filled = Util.filledImage(top, Color.WHITE);
+ Util.drawCenterInside(g, filled, targetRect);
+ } else if (notificationOptions.version == Version.V11) {
+ Util.drawCenterInside(g2, options.sourceImage, targetRect);
+ Util.drawEffects(g, tempImage, 0, 0, new Effect[] {
+ new FillEffect(
+ Color.WHITE),
+ });
+ } else {
+ assert notificationOptions.version == Version.V9;
+ Util.drawCenterInside(g2, options.sourceImage, targetRect);
+ Util.drawEffects(g, tempImage, 0, 0, new Effect[] {
+ new FillEffect(
+ new GradientPaint(
+ 0, 0,
+ new Color(0x919191),
+ 0, imageRect.height,
+ new Color(0x828282))),
+ new ShadowEffect(
+ 0,
+ 1,
+ 0,
+ Color.WHITE,
+ 0.10,
+ true),
+ });
+ }
+
+ g.dispose();
+ g2.dispose();
+
+ return outImage;
+ }
+
+ @Override
+ public void generate(String category, Map<String, Map<String, BufferedImage>> categoryMap,
+ GraphicGeneratorContext context, Options options, String name) {
+ for (Version version : Version.values()) {
+ ((NotificationOptions) options).version = version;
+ super.generate(version.getDisplayName(), categoryMap, context, options, name);
+ }
+ }
+
+ @Override
+ protected String getIconFolder(Options options) {
+ String folder = super.getIconFolder(options);
+ Version version = ((NotificationOptions) options).version;
+ if (version == Version.V11) {
+ return folder + "-v11"; //$NON-NLS-1$
+ } else if (version == Version.V9) {
+ return folder + "-v9"; //$NON-NLS-1$
+ } else {
+ return folder;
+ }
+ }
+
+ /**
+ * Options specific to generating notification icons
+ */
+ public static class NotificationOptions extends GraphicGenerator.Options {
+ /**
+ * The shape to use for graphics behind the icon (for {@link Version#OLDER} only)
+ */
+ public Shape shape = Shape.SQUARE;
+
+ /**
+ * The version of the icon to generate - different styles are used for different
+ * versions of Android
+ */
+ public Version version = Version.V9;
+ }
+
+ /**
+ * The version of the icon to generate - different styles are used for different
+ * versions of Android
+ */
+ public enum Version {
+ /** Icon style used for -v9 and -v10 */
+ V9("V9"),
+
+ /** Icon style used for -v11 (Honeycomb) and later */
+ V11("V11"),
+
+ /** Icon style used for versions older than v9 */
+ OLDER("Other");
+
+ private final String mDisplayName;
+
+ Version(String displayName) {
+ mDisplayName = displayName;
+ }
+
+ /**
+ * Returns the display name for this version, typically shown as a
+ * category
+ *
+ * @return the display name, never null
+ */
+ public String getDisplayName() {
+ return mDisplayName;
+ }
+ }
+}
diff --git a/assetstudio/src/com/android/assetstudiolib/TabIconGenerator.java b/assetstudio/src/com/android/assetstudiolib/TabIconGenerator.java
new file mode 100644
index 0000000..506aebd
--- /dev/null
+++ b/assetstudio/src/com/android/assetstudiolib/TabIconGenerator.java
@@ -0,0 +1,188 @@
+/*
+ * 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.assetstudiolib;
+
+import com.android.assetstudiolib.Util.Effect;
+import com.android.assetstudiolib.Util.FillEffect;
+import com.android.assetstudiolib.Util.ShadowEffect;
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.util.Map;
+
+
+/**
+ * Generate icons for tabs
+ */
+public class TabIconGenerator extends GraphicGenerator {
+ /** Creates a new {@link TabIconGenerator} */
+ public TabIconGenerator() {
+ }
+
+ @Override
+ public BufferedImage generate(GraphicGeneratorContext context, Options options) {
+ Rectangle iconSizeHdpi = new Rectangle(0, 0, 48, 48);
+ Rectangle targetRectHdpi = new Rectangle(3, 3, 42, 42);
+ final float scaleFactor = GraphicGenerator.getHdpiScaleFactor(options.density);
+ Rectangle imageRect = Util.scaleRectangle(iconSizeHdpi, scaleFactor);
+ Rectangle targetRect = Util.scaleRectangle(targetRectHdpi, scaleFactor);
+ BufferedImage outImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height);
+ Graphics2D g = (Graphics2D) outImage.getGraphics();
+
+ BufferedImage tempImage = Util.newArgbBufferedImage(
+ imageRect.width, imageRect.height);
+ Graphics2D g2 = (Graphics2D) tempImage.getGraphics();
+ Util.drawCenterInside(g2, options.sourceImage, targetRect);
+
+ TabOptions tabOptions = (TabOptions) options;
+ if (tabOptions.selected) {
+ if (tabOptions.oldStyle) {
+ Util.drawEffects(g, tempImage, 0, 0, new Effect[] {
+ new FillEffect(
+ new GradientPaint(
+ 0, 0,
+ new Color(0xa3a3a3),
+ 0, imageRect.height,
+ new Color(0x787878))),
+ new ShadowEffect(
+ 0,
+ 3 * scaleFactor,
+ 3 * scaleFactor,
+ Color.BLACK,
+ 0.2,
+ true),
+ new ShadowEffect(
+ 0,
+ 1,
+ 0,
+ Color.BLACK,
+ 0.35,
+ true),
+ new ShadowEffect(
+ 0,
+ -1,
+ 0,
+ Color.WHITE,
+ 0.35,
+ true),
+ });
+ } else {
+ Util.drawEffects(g, tempImage, 0, 0, new Effect[] {
+ new FillEffect(Color.WHITE),
+ new ShadowEffect(
+ 0,
+ 0,
+ 5 * scaleFactor,
+ Color.BLACK,
+ 0.25,
+ false),
+ });
+ }
+ } else {
+ // Unselected
+ if (tabOptions.oldStyle) {
+ Util.drawEffects(g, tempImage, 0, 0, new Effect[] {
+ new FillEffect(
+ new GradientPaint(
+ 0, 0.25f * imageRect.height,
+ new Color(0xf9f9f9),
+ 0, imageRect.height,
+ new Color(0xdfdfdf))),
+ new ShadowEffect(
+ 0,
+ 3 * scaleFactor,
+ 3 * scaleFactor,
+ Color.BLACK,
+ 0.1,
+ true),
+ new ShadowEffect(
+ 0,
+ 1,
+ 0,
+ Color.BLACK,
+ 0.35,
+ true),
+ new ShadowEffect(
+ 0,
+ -1,
+ 0,
+ Color.WHITE,
+ 0.35,
+ true),
+ });
+ } else {
+ Util.drawEffects(g, tempImage, 0, 0, new Effect[] {
+ new FillEffect(new Color(0x808080)),
+ });
+ }
+ }
+
+ g.dispose();
+ g2.dispose();
+
+ return outImage;
+ }
+
+ @Override
+ public void generate(String category, Map<String, Map<String, BufferedImage>> categoryMap,
+ GraphicGeneratorContext context, Options options, String name) {
+ TabOptions tabOptions = (TabOptions) options;
+ // Generate all permutations of tabOptions.selected and tabOptions.oldStyle
+ tabOptions.selected = true;
+ tabOptions.oldStyle = false;
+ super.generate("Selected (v5+)", categoryMap, context, options, name);
+ tabOptions.oldStyle = true;
+ super.generate("Selected", categoryMap, context, options, name);
+ tabOptions.selected = false;
+ tabOptions.oldStyle = false;
+ super.generate("Unselected (v5+)", categoryMap, context, options, name);
+ tabOptions.oldStyle = true;
+ super.generate("Unselected", categoryMap, context, options, name);
+ }
+
+ @Override
+ protected String getIconFolder(Options options) {
+ String folder = super.getIconFolder(options);
+
+ TabOptions tabOptions = (TabOptions) options;
+ if (tabOptions.oldStyle) {
+ return folder;
+ } else {
+ return folder + "-v5"; //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ protected String getIconName(Options options, String name) {
+ TabOptions tabOptions = (TabOptions) options;
+ if (tabOptions.selected) {
+ return name + "_selected.png"; //$NON-NLS-1$
+ } else {
+ return name + "_unselected.png"; //$NON-NLS-1$
+ }
+ }
+
+ /** Options specific to generating tab icons */
+ public static class TabOptions extends GraphicGenerator.Options {
+ /** Generate icon in the style used prior to v5 */
+ public boolean oldStyle;
+ /** Generate "selected" icon if true, and "unselected" icon if false */
+ public boolean selected = true;
+ }
+}
diff --git a/assetstudio/src/com/android/assetstudiolib/TextRenderUtil.java b/assetstudio/src/com/android/assetstudiolib/TextRenderUtil.java
index a103701..e08a234 100644
--- a/assetstudio/src/com/android/assetstudiolib/TextRenderUtil.java
+++ b/assetstudio/src/com/android/assetstudiolib/TextRenderUtil.java
@@ -16,14 +16,14 @@
package com.android.assetstudiolib;
+import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
+import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
-import java.awt.font.TextAttribute;
+import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
-import java.util.Hashtable;
-import java.util.Map;
/**
* A set of utility classes for rendering text to a {@link BufferedImage}, suitable for use as a
@@ -31,13 +31,18 @@ import java.util.Map;
*/
public class TextRenderUtil {
/**
- * Renders the given string with the provided {@link Options} to a {@link BufferedImage}.
+ * Renders the given string with the provided {@link Options} to a
+ * {@link BufferedImage}.
*
- * @param text The text to render.
+ * @param text The text to render.
+ * @param paddingPercentage If nonzero, a percentage of the width or height
+ * (whichever is smaller) to add as padding around the text
* @param options The optional parameters for rendering the text.
- * @return An image, suitable for use as an input to a {@link GraphicGenerator}.
+ * @return An image, suitable for use as an input to a
+ * {@link GraphicGenerator}.
*/
- public static BufferedImage renderTextImage(String text, Options options) {
+ public static BufferedImage renderTextImage(String text, int paddingPercentage,
+ Options options) {
if (options == null) {
options = new Options();
}
@@ -59,13 +64,32 @@ public class TextRenderUtil {
FontRenderContext frc = tempG.getFontRenderContext();
- Rectangle2D bounds = font.getStringBounds(text, frc);
+ TextLayout layout = new TextLayout(text, font, frc);
+ Rectangle2D bounds = layout.getBounds();
+
+ // The padding is a percentage relative to the overall minimum of the width or height
+ if (paddingPercentage != 0) {
+ double minDimension = Math.min(bounds.getWidth(), bounds.getHeight());
+ double delta = minDimension * paddingPercentage / 100;
+ bounds.setRect(bounds.getMinX() - delta, bounds.getMinY() - delta,
+ bounds.getWidth() + 2 * delta, bounds.getHeight() + 2 * delta);
+ }
BufferedImage image = Util.newArgbBufferedImage(
Math.max(1, (int) bounds.getWidth()), Math.max(1, (int) bounds.getHeight()));
Graphics2D g = (Graphics2D) image.getGraphics();
+ g.setColor(new Color(options.foregroundColor, true));
g.setFont(font);
- g.drawString(text, 0, (float) -bounds.getY());
+
+ g.setRenderingHint(
+ RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setRenderingHint(
+ RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+
+ g.drawString(text, (float) -bounds.getX(), (float) -bounds.getY());
+
+ g.dispose();
+ tempG.dispose();
return image;
}
@@ -79,6 +103,9 @@ public class TextRenderUtil {
// TODO: Instead, a graphic generator should use a different source image for each density.
private static final int DEFAULT_FONT_SIZE = 512;
+ /** Foreground color to render text with, as an AARRGGBB packed integer */
+ public int foregroundColor = 0xFFFFFFFF;
+
/**
* The optional {@link Font} to use. If null, a {@link Font} object will be generated using
* the other options.
diff --git a/assetstudio/src/com/android/assetstudiolib/Util.java b/assetstudio/src/com/android/assetstudiolib/Util.java
index 1a6b00e..927ca30 100644
--- a/assetstudio/src/com/android/assetstudiolib/Util.java
+++ b/assetstudio/src/com/android/assetstudiolib/Util.java
@@ -84,7 +84,7 @@ public class Util {
}
/**
- * Applies a gaussion blur of the given radius to the given {@link BufferedImage} using a kernel
+ * Applies a gaussian blur of the given radius to the given {@link BufferedImage} using a kernel
* convolution.
*
* @param source The source image.
diff --git a/assetstudio/src/images/notification_stencil/circle/hdpi.png b/assetstudio/src/images/notification_stencil/circle/hdpi.png
new file mode 100644
index 0000000..4d28710
--- /dev/null
+++ b/assetstudio/src/images/notification_stencil/circle/hdpi.png
Binary files differ
diff --git a/assetstudio/src/images/notification_stencil/circle/ldpi.png b/assetstudio/src/images/notification_stencil/circle/ldpi.png
new file mode 100644
index 0000000..5c9a9f7
--- /dev/null
+++ b/assetstudio/src/images/notification_stencil/circle/ldpi.png
Binary files differ
diff --git a/assetstudio/src/images/notification_stencil/circle/mdpi.png b/assetstudio/src/images/notification_stencil/circle/mdpi.png
new file mode 100644
index 0000000..1f064a2
--- /dev/null
+++ b/assetstudio/src/images/notification_stencil/circle/mdpi.png
Binary files differ
diff --git a/assetstudio/src/images/notification_stencil/circle/xhdpi.png b/assetstudio/src/images/notification_stencil/circle/xhdpi.png
new file mode 100644
index 0000000..f6a57c1
--- /dev/null
+++ b/assetstudio/src/images/notification_stencil/circle/xhdpi.png
Binary files differ
diff --git a/assetstudio/src/images/notification_stencil/square/hdpi.png b/assetstudio/src/images/notification_stencil/square/hdpi.png
new file mode 100644
index 0000000..f755f4f
--- /dev/null
+++ b/assetstudio/src/images/notification_stencil/square/hdpi.png
Binary files differ
diff --git a/assetstudio/src/images/notification_stencil/square/ldpi.png b/assetstudio/src/images/notification_stencil/square/ldpi.png
new file mode 100644
index 0000000..23846bd
--- /dev/null
+++ b/assetstudio/src/images/notification_stencil/square/ldpi.png
Binary files differ
diff --git a/assetstudio/src/images/notification_stencil/square/mdpi.png b/assetstudio/src/images/notification_stencil/square/mdpi.png
new file mode 100644
index 0000000..5f80247
--- /dev/null
+++ b/assetstudio/src/images/notification_stencil/square/mdpi.png
Binary files differ
diff --git a/assetstudio/src/images/notification_stencil/square/xhdpi.png b/assetstudio/src/images/notification_stencil/square/xhdpi.png
new file mode 100644
index 0000000..7c27d82
--- /dev/null
+++ b/assetstudio/src/images/notification_stencil/square/xhdpi.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/ActionBarIconGeneratorTest.java b/assetstudio/tests/src/com/android/assetstudiolib/ActionBarIconGeneratorTest.java
new file mode 100644
index 0000000..ed5ea04
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/ActionBarIconGeneratorTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.assetstudiolib;
+
+import com.android.assetstudiolib.ActionBarIconGenerator.ActionBarOptions;
+import com.android.assetstudiolib.ActionBarIconGenerator.Theme;
+
+import java.io.IOException;
+
+@SuppressWarnings("javadoc")
+public class ActionBarIconGeneratorTest extends GeneratorTest {
+ private void checkGraphic(String baseName, Theme theme) throws IOException {
+ ActionBarOptions options = new ActionBarOptions();
+ options.theme = theme;
+
+ ActionBarIconGenerator generator = new ActionBarIconGenerator();
+ checkGraphic(4, "actions", baseName, generator, options);
+ }
+
+ public void testDark() throws Exception {
+ checkGraphic("ic_action_dark", Theme.HOLO_DARK);
+ }
+
+ public void testLight() throws Exception {
+ checkGraphic("ic_action_light", Theme.HOLO_LIGHT);
+ }
+}
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/GeneratorTest.java b/assetstudio/tests/src/com/android/assetstudiolib/GeneratorTest.java
new file mode 100644
index 0000000..59812bf
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/GeneratorTest.java
@@ -0,0 +1,225 @@
+/*
+ * 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.assetstudiolib;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.imageio.ImageIO;
+
+import junit.framework.TestCase;
+
+/**
+ * Shared test infrastructure for code generator
+ */
+public abstract class GeneratorTest extends TestCase implements GraphicGeneratorContext {
+ private static final String TEST_DATA_REL_PATH =
+ "assetstudio/tests/src/com/android/assetstudiolib/testdata";
+
+ protected void checkGraphic(int expectedFileCount, String folderName, String baseName,
+ GraphicGenerator generator, GraphicGenerator.Options options)
+ throws IOException {
+ Map<String, Map<String, BufferedImage>> categoryMap =
+ new HashMap<String, Map<String, BufferedImage>>();
+ options.sourceImage = GraphicGenerator.getClipartImage("android.png");
+ generator.generate(null, categoryMap, this, options, baseName);
+
+ File targetDir = getTargetDir();
+
+ List<String> errors = new ArrayList<String>();
+ int fileCount = 0;
+ for (Map<String, BufferedImage> previews : categoryMap.values()) {
+ for (Map.Entry<String, BufferedImage> entry : previews.entrySet()) {
+ String relativePath = entry.getKey();
+ BufferedImage image = entry.getValue();
+
+ String path = "testdata" + File.separator + folderName + File.separator
+ + relativePath;
+ InputStream is = GeneratorTest.class.getResourceAsStream(path);
+ if (is == null) {
+ if (targetDir == null) {
+ fail("Did not find " + path
+ + ". Set ADT_SDK_SOURCE_PATH to have it created automatically");
+ }
+ File fileName = new File(targetDir, folderName + File.separator
+ + relativePath);
+ assertFalse(fileName.exists());
+ if (!fileName.getParentFile().exists()) {
+ boolean mkdir = fileName.getParentFile().mkdirs();
+ assertTrue(fileName.getParent(), mkdir);
+ }
+
+ ImageIO.write(image, "PNG", fileName);
+ errors.add("File did not exist, created " + fileName.getPath());
+ } else {
+ BufferedImage goldenImage = ImageIO.read(is);
+ assertImageSimilar(relativePath, goldenImage, image, 5.0f);
+ }
+ }
+
+ fileCount += previews.values().size();
+ }
+ if (errors.size() > 0) {
+ fail(errors.toString());
+ }
+
+ assertEquals("Wrong number of generated files", expectedFileCount, fileCount);
+ }
+
+ private void assertImageSimilar(String imageName, BufferedImage goldenImage,
+ BufferedImage image, float maxPercentDifferent) throws IOException {
+ assertTrue("Widths differ too much for " + imageName, Math.abs(goldenImage.getWidth()
+ - image.getWidth()) < 2);
+ assertTrue("Widths differ too much for " + imageName, Math.abs(goldenImage.getHeight()
+ - image.getHeight()) < 2);
+
+ assertEquals(BufferedImage.TYPE_INT_ARGB, image.getType());
+
+ if (goldenImage.getType() != BufferedImage.TYPE_INT_ARGB) {
+ BufferedImage temp = new BufferedImage(goldenImage.getWidth(), goldenImage.getHeight(),
+ BufferedImage.TYPE_INT_ARGB);
+ temp.getGraphics().drawImage(goldenImage, 0, 0, null);
+ goldenImage = temp;
+ }
+ assertEquals(BufferedImage.TYPE_INT_ARGB, goldenImage.getType());
+
+ int imageWidth = Math.min(goldenImage.getWidth(), image.getWidth());
+ int imageHeight = Math.min(goldenImage.getHeight(), image.getHeight());
+
+ // Blur the images to account for the scenarios where there are pixel
+ // differences
+ // in where a sharp edge occurs
+ // goldenImage = blur(goldenImage, 6);
+ // image = blur(image, 6);
+
+ int width = 3 * imageWidth;
+ int height = imageHeight;
+ BufferedImage deltaImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics g = deltaImage.getGraphics();
+
+ // Compute delta map
+ long delta = 0;
+ for (int y = 0; y < imageHeight; y++) {
+ for (int x = 0; x < imageWidth; x++) {
+ int goldenRgb = goldenImage.getRGB(x, y);
+ int rgb = image.getRGB(x, y);
+ if (goldenRgb == rgb) {
+ deltaImage.setRGB(imageWidth + x, y, 0x00808080);
+ continue;
+ }
+
+ // If the pixels have no opacity, don't delta colors at all
+ if (((goldenRgb & 0xFF000000) == 0) && (rgb & 0xFF000000) == 0) {
+ deltaImage.setRGB(imageWidth + x, y, 0x00808080);
+ continue;
+ }
+
+ int deltaR = ((rgb & 0xFF0000) >>> 16) - ((goldenRgb & 0xFF0000) >>> 16);
+ int newR = 128 + deltaR & 0xFF;
+ int deltaG = ((rgb & 0x00FF00) >>> 8) - ((goldenRgb & 0x00FF00) >>> 8);
+ int newG = 128 + deltaG & 0xFF;
+ int deltaB = (rgb & 0x0000FF) - (goldenRgb & 0x0000FF);
+ int newB = 128 + deltaB & 0xFF;
+
+ int avgAlpha = ((((goldenRgb & 0xFF000000) >>> 24)
+ + ((rgb & 0xFF000000) >>> 24)) / 2) << 24;
+
+ int newRGB = avgAlpha | newR << 16 | newG << 8 | newB;
+ deltaImage.setRGB(imageWidth + x, y, newRGB);
+
+ delta += Math.abs(deltaR);
+ delta += Math.abs(deltaG);
+ delta += Math.abs(deltaB);
+ }
+ }
+
+ // 3 different colors, 256 color levels
+ long total = imageHeight * imageWidth * 3L * 256L;
+ float percentDifference = (float) (delta * 100 / (double) total);
+
+ if (percentDifference > maxPercentDifferent) {
+ // Expected on the left
+ // Golden on the right
+ g.drawImage(goldenImage, 0, 0, null);
+ g.drawImage(image, 2 * imageWidth, 0, null);
+
+ // Labels
+ if (imageWidth > 80) {
+ g.setColor(Color.RED);
+ g.drawString("Expected", 10, 20);
+ g.drawString("Actual", 2 * imageWidth + 10, 20);
+ }
+
+ File output = new File(getTempDir(), "delta-"
+ + imageName.replace(File.separatorChar, '_'));
+ if (output.exists()) {
+ output.delete();
+ }
+ ImageIO.write(deltaImage, "PNG", output);
+ String message = String.format("Images differ (by %.1f%%) - see details in %s",
+ percentDifference, output);
+ System.out.println(message);
+ fail(message);
+ }
+
+ g.dispose();
+ }
+
+ protected File getTempDir() {
+ if (System.getProperty("os.name").equals("Mac OS X")) {
+ return new File("/tmp"); //$NON-NLS-1$
+ }
+
+ return new File(System.getProperty("java.io.tmpdir")); //$NON-NLS-1$
+ }
+
+ public BufferedImage loadImageResource(String path) {
+ try {
+ return GraphicGenerator.getStencilImage(path);
+ } catch (IOException e) {
+ fail(e.toString());
+ }
+
+ return null;
+ }
+
+ /** Get the location to write missing golden files to */
+ protected File getTargetDir() {
+ // Set $ADT_SDK_SOURCE_PATH to point to your git "sdk" directory
+ String sdk = System.getenv("ADT_SDK_SOURCE_PATH");
+ if (sdk != null) {
+ File sdkPath = new File(sdk);
+ if (sdkPath.exists()) {
+ File testData = new File(sdkPath, TEST_DATA_REL_PATH.replace('/',
+ File.separatorChar));
+ if (testData.exists()) {
+ return testData;
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/LauncherIconGeneratorTest.java b/assetstudio/tests/src/com/android/assetstudiolib/LauncherIconGeneratorTest.java
new file mode 100644
index 0000000..4d6680c
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/LauncherIconGeneratorTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.assetstudiolib;
+
+import com.android.assetstudiolib.LauncherIconGenerator.LauncherOptions;
+
+import java.io.IOException;
+
+@SuppressWarnings("javadoc")
+public class LauncherIconGeneratorTest extends GeneratorTest {
+ private void checkGraphic(String baseName,
+ GraphicGenerator.Shape shape, GraphicGenerator.Style style,
+ boolean crop, int background, boolean isWebGraphic) throws IOException {
+ LauncherOptions options = new LauncherOptions();
+ options.shape = shape;
+ options.crop = crop;
+ options.style = style;
+ options.backgroundColor = background;
+ options.isWebGraphic = isWebGraphic;
+
+ LauncherIconGenerator generator = new LauncherIconGenerator();
+ checkGraphic(4 + (isWebGraphic ? 1 : 0), "launcher", baseName, generator, options);
+ }
+
+ public void testLauncher_fancyCircle() throws Exception {
+ checkGraphic("red_fancy_circle", GraphicGenerator.Shape.CIRCLE,
+ GraphicGenerator.Style.FANCY, true, 0xFF0000, true);
+ }
+
+ public void testLauncher_glossySquare() throws Exception {
+ checkGraphic("blue_glossy_square", GraphicGenerator.Shape.SQUARE,
+ GraphicGenerator.Style.GLOSSY, true, 0x0040FF, true);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureLauncherAssetsPanel.java b/assetstudio/tests/src/com/android/assetstudiolib/MenuIconGeneratorTest.java
index 930e93c..700be4b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/assetstudio/ConfigureLauncherAssetsPanel.java
+++ b/assetstudio/tests/src/com/android/assetstudiolib/MenuIconGeneratorTest.java
@@ -13,25 +13,19 @@
* 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;
+package com.android.assetstudiolib;
-public class ConfigureLauncherAssetsPanel extends Composite {
-
- /**
- * Create the composite.
- * @param parent
- * @param style
- */
- public ConfigureLauncherAssetsPanel(Composite parent, int style) {
- super(parent, style);
+import java.io.IOException;
+@SuppressWarnings("javadoc")
+public class MenuIconGeneratorTest extends GeneratorTest {
+ private void checkGraphic(String baseName) throws IOException {
+ MenuIconGenerator generator = new MenuIconGenerator();
+ checkGraphic(4, "menus", baseName, generator, new GraphicGenerator.Options());
}
- @Override
- protected void checkSubclass() {
- // Disable the check that prevents subclassing of SWT components
+ public void testMenu() throws Exception {
+ checkGraphic("ic_menu_1");
}
-
}
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/NotificationIconGeneratorTest.java b/assetstudio/tests/src/com/android/assetstudiolib/NotificationIconGeneratorTest.java
new file mode 100644
index 0000000..7ac5634
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/NotificationIconGeneratorTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.assetstudiolib;
+
+import com.android.assetstudiolib.NotificationIconGenerator.NotificationOptions;
+
+import java.io.IOException;
+
+@SuppressWarnings("javadoc")
+public class NotificationIconGeneratorTest extends GeneratorTest {
+ private void checkGraphic(String baseName,
+ GraphicGenerator.Shape shape) throws IOException {
+ NotificationOptions options = new NotificationOptions();
+ options.shape = shape;
+
+ NotificationIconGenerator generator = new NotificationIconGenerator();
+ checkGraphic(12, "notification", baseName, generator, options);
+ }
+
+ public void testNotification1() throws Exception {
+ checkGraphic("ic_stat_circle", GraphicGenerator.Shape.CIRCLE);
+ }
+
+ public void testNotification2() throws Exception {
+ checkGraphic("ic_stat_square", GraphicGenerator.Shape.SQUARE);
+ }
+}
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/TabIconGeneratorTest.java b/assetstudio/tests/src/com/android/assetstudiolib/TabIconGeneratorTest.java
new file mode 100644
index 0000000..4fb4801
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/TabIconGeneratorTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.assetstudiolib;
+
+import java.io.IOException;
+
+@SuppressWarnings("javadoc")
+public class TabIconGeneratorTest extends GeneratorTest {
+ private void checkGraphic(String baseName) throws IOException {
+ TabIconGenerator generator = new TabIconGenerator();
+ checkGraphic(16, "tabs", baseName, generator, new TabIconGenerator.TabOptions());
+ }
+
+ public void testTabs1() throws Exception {
+ checkGraphic("ic_tab_1");
+ }
+}
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-hdpi/ic_action_dark.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-hdpi/ic_action_dark.png
new file mode 100644
index 0000000..ac9fcf9
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-hdpi/ic_action_dark.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-hdpi/ic_action_light.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-hdpi/ic_action_light.png
new file mode 100644
index 0000000..15da7b9
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-hdpi/ic_action_light.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-ldpi/ic_action_dark.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-ldpi/ic_action_dark.png
new file mode 100644
index 0000000..e9ea176
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-ldpi/ic_action_dark.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-ldpi/ic_action_light.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-ldpi/ic_action_light.png
new file mode 100644
index 0000000..1dca5d2
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-ldpi/ic_action_light.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-mdpi/ic_action_dark.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-mdpi/ic_action_dark.png
new file mode 100644
index 0000000..82ec17f
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-mdpi/ic_action_dark.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-mdpi/ic_action_light.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-mdpi/ic_action_light.png
new file mode 100644
index 0000000..a9ecda2
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-mdpi/ic_action_light.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-xhdpi/ic_action_dark.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-xhdpi/ic_action_dark.png
new file mode 100644
index 0000000..cd6b555
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-xhdpi/ic_action_dark.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-xhdpi/ic_action_light.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-xhdpi/ic_action_light.png
new file mode 100644
index 0000000..cdc2cfd
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/actions/res/drawable-xhdpi/ic_action_light.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/blue_glossy_square-web.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/blue_glossy_square-web.png
new file mode 100644
index 0000000..d8b8294
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/blue_glossy_square-web.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/red_fancy_circle-web.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/red_fancy_circle-web.png
new file mode 100644
index 0000000..e9bd6fe
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/red_fancy_circle-web.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-hdpi/blue_glossy_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-hdpi/blue_glossy_square.png
new file mode 100644
index 0000000..f549138
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-hdpi/blue_glossy_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-hdpi/red_fancy_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-hdpi/red_fancy_circle.png
new file mode 100644
index 0000000..b068fb5
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-hdpi/red_fancy_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-ldpi/blue_glossy_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-ldpi/blue_glossy_square.png
new file mode 100644
index 0000000..fcc7c1c
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-ldpi/blue_glossy_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-ldpi/red_fancy_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-ldpi/red_fancy_circle.png
new file mode 100644
index 0000000..b85b2b5
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-ldpi/red_fancy_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-mdpi/blue_glossy_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-mdpi/blue_glossy_square.png
new file mode 100644
index 0000000..29da2c3
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-mdpi/blue_glossy_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-mdpi/red_fancy_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-mdpi/red_fancy_circle.png
new file mode 100644
index 0000000..54ea5ed
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-mdpi/red_fancy_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-xhdpi/blue_glossy_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-xhdpi/blue_glossy_square.png
new file mode 100644
index 0000000..3377ddc
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-xhdpi/blue_glossy_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-xhdpi/red_fancy_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-xhdpi/red_fancy_circle.png
new file mode 100644
index 0000000..896da29
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/launcher/res/drawable-xhdpi/red_fancy_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-hdpi/ic_menu_1.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-hdpi/ic_menu_1.png
new file mode 100644
index 0000000..0d6d67f
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-hdpi/ic_menu_1.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-ldpi/ic_menu_1.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-ldpi/ic_menu_1.png
new file mode 100644
index 0000000..85655ed
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-ldpi/ic_menu_1.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-mdpi/ic_menu_1.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-mdpi/ic_menu_1.png
new file mode 100644
index 0000000..de68199
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-mdpi/ic_menu_1.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-xhdpi/ic_menu_1.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-xhdpi/ic_menu_1.png
new file mode 100644
index 0000000..dca9a75
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/menus/res/drawable-xhdpi/ic_menu_1.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v11/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v11/ic_stat_circle.png
new file mode 100644
index 0000000..daad503
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v11/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v11/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v11/ic_stat_square.png
new file mode 100644
index 0000000..daad503
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v11/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v9/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v9/ic_stat_circle.png
new file mode 100644
index 0000000..bdd8598
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v9/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v9/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v9/ic_stat_square.png
new file mode 100644
index 0000000..bdd8598
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi-v9/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi/ic_stat_circle.png
new file mode 100644
index 0000000..d2ea9f5
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi/ic_stat_square.png
new file mode 100644
index 0000000..a1c9285
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-hdpi/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v11/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v11/ic_stat_circle.png
new file mode 100644
index 0000000..228ab60
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v11/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v11/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v11/ic_stat_square.png
new file mode 100644
index 0000000..228ab60
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v11/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v9/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v9/ic_stat_circle.png
new file mode 100644
index 0000000..ea4b105
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v9/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v9/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v9/ic_stat_square.png
new file mode 100644
index 0000000..ea4b105
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi-v9/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi/ic_stat_circle.png
new file mode 100644
index 0000000..c315dff
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi/ic_stat_square.png
new file mode 100644
index 0000000..8592c1f
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-ldpi/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v11/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v11/ic_stat_circle.png
new file mode 100644
index 0000000..7749b11
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v11/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v11/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v11/ic_stat_square.png
new file mode 100644
index 0000000..7749b11
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v11/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v9/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v9/ic_stat_circle.png
new file mode 100644
index 0000000..1956c8e
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v9/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v9/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v9/ic_stat_square.png
new file mode 100644
index 0000000..1956c8e
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi-v9/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi/ic_stat_circle.png
new file mode 100644
index 0000000..c63fc8f
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi/ic_stat_square.png
new file mode 100644
index 0000000..40b27af
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-mdpi/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v11/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v11/ic_stat_circle.png
new file mode 100644
index 0000000..3dbfa96
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v11/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v11/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v11/ic_stat_square.png
new file mode 100644
index 0000000..3dbfa96
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v11/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v9/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v9/ic_stat_circle.png
new file mode 100644
index 0000000..8d52ab7
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v9/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v9/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v9/ic_stat_square.png
new file mode 100644
index 0000000..8d52ab7
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi-v9/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi/ic_stat_circle.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi/ic_stat_circle.png
new file mode 100644
index 0000000..d05fbff
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi/ic_stat_circle.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi/ic_stat_square.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi/ic_stat_square.png
new file mode 100644
index 0000000..c7159ec
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/notification/res/drawable-xhdpi/ic_stat_square.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi-v5/ic_tab_1_selected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi-v5/ic_tab_1_selected.png
new file mode 100644
index 0000000..e8e7e71
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi-v5/ic_tab_1_selected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi-v5/ic_tab_1_unselected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi-v5/ic_tab_1_unselected.png
new file mode 100644
index 0000000..8d1ea96
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi-v5/ic_tab_1_unselected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi/ic_tab_1_selected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi/ic_tab_1_selected.png
new file mode 100644
index 0000000..5a49be9
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi/ic_tab_1_selected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi/ic_tab_1_unselected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi/ic_tab_1_unselected.png
new file mode 100644
index 0000000..d957240
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-hdpi/ic_tab_1_unselected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi-v5/ic_tab_1_selected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi-v5/ic_tab_1_selected.png
new file mode 100644
index 0000000..0550dd2
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi-v5/ic_tab_1_selected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi-v5/ic_tab_1_unselected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi-v5/ic_tab_1_unselected.png
new file mode 100644
index 0000000..82f4412
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi-v5/ic_tab_1_unselected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi/ic_tab_1_selected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi/ic_tab_1_selected.png
new file mode 100644
index 0000000..81302e9
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi/ic_tab_1_selected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi/ic_tab_1_unselected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi/ic_tab_1_unselected.png
new file mode 100644
index 0000000..00568c7
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-ldpi/ic_tab_1_unselected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi-v5/ic_tab_1_selected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi-v5/ic_tab_1_selected.png
new file mode 100644
index 0000000..646490f
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi-v5/ic_tab_1_selected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi-v5/ic_tab_1_unselected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi-v5/ic_tab_1_unselected.png
new file mode 100644
index 0000000..c11de02
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi-v5/ic_tab_1_unselected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi/ic_tab_1_selected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi/ic_tab_1_selected.png
new file mode 100644
index 0000000..7c603b7
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi/ic_tab_1_selected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi/ic_tab_1_unselected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi/ic_tab_1_unselected.png
new file mode 100644
index 0000000..521bf60
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-mdpi/ic_tab_1_unselected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi-v5/ic_tab_1_selected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi-v5/ic_tab_1_selected.png
new file mode 100644
index 0000000..448454b
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi-v5/ic_tab_1_selected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi-v5/ic_tab_1_unselected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi-v5/ic_tab_1_unselected.png
new file mode 100644
index 0000000..52852ee
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi-v5/ic_tab_1_unselected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi/ic_tab_1_selected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi/ic_tab_1_selected.png
new file mode 100644
index 0000000..317fc5a
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi/ic_tab_1_selected.png
Binary files differ
diff --git a/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi/ic_tab_1_unselected.png b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi/ic_tab_1_unselected.png
new file mode 100644
index 0000000..7a0ffc6
--- /dev/null
+++ b/assetstudio/tests/src/com/android/assetstudiolib/testdata/tabs/res/drawable-xhdpi/ic_tab_1_unselected.png
Binary files differ
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/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"));