Home | History | Annotate | Download | only in assetstudio
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ide.eclipse.adt.internal.assetstudio;
     18 
     19 import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectWizard.DEFAULT_LAUNCHER_ICON;
     20 import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
     21 
     22 import com.android.annotations.NonNull;
     23 import com.android.annotations.Nullable;
     24 import com.android.assetstudiolib.ActionBarIconGenerator;
     25 import com.android.assetstudiolib.GraphicGenerator;
     26 import com.android.assetstudiolib.GraphicGenerator.Shape;
     27 import com.android.assetstudiolib.LauncherIconGenerator;
     28 import com.android.assetstudiolib.MenuIconGenerator;
     29 import com.android.assetstudiolib.NotificationIconGenerator;
     30 import com.android.assetstudiolib.TabIconGenerator;
     31 import com.android.assetstudiolib.TextRenderUtil;
     32 import com.android.assetstudiolib.Util;
     33 import com.android.ide.eclipse.adt.AdtPlugin;
     34 import com.android.ide.eclipse.adt.AdtUtils;
     35 import com.android.ide.eclipse.adt.internal.assetstudio.CreateAssetSetWizardState.SourceType;
     36 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageControl;
     37 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils;
     38 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SwtUtils;
     39 import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
     40 import com.android.utils.Pair;
     41 
     42 import org.eclipse.core.resources.IFile;
     43 import org.eclipse.core.resources.IProject;
     44 import org.eclipse.core.resources.IResource;
     45 import org.eclipse.core.resources.IWorkspaceRoot;
     46 import org.eclipse.core.resources.ResourcesPlugin;
     47 import org.eclipse.core.runtime.CoreException;
     48 import org.eclipse.core.runtime.IPath;
     49 import org.eclipse.core.runtime.IStatus;
     50 import org.eclipse.core.runtime.NullProgressMonitor;
     51 import org.eclipse.core.runtime.Path;
     52 import org.eclipse.jface.dialogs.IMessageProvider;
     53 import org.eclipse.jface.dialogs.MessageDialog;
     54 import org.eclipse.jface.wizard.WizardPage;
     55 import org.eclipse.swt.SWT;
     56 import org.eclipse.swt.custom.ScrolledComposite;
     57 import org.eclipse.swt.custom.StackLayout;
     58 import org.eclipse.swt.events.ModifyEvent;
     59 import org.eclipse.swt.events.ModifyListener;
     60 import org.eclipse.swt.events.MouseAdapter;
     61 import org.eclipse.swt.events.MouseEvent;
     62 import org.eclipse.swt.events.SelectionEvent;
     63 import org.eclipse.swt.events.SelectionListener;
     64 import org.eclipse.swt.graphics.Color;
     65 import org.eclipse.swt.graphics.Font;
     66 import org.eclipse.swt.graphics.FontData;
     67 import org.eclipse.swt.graphics.Image;
     68 import org.eclipse.swt.graphics.RGB;
     69 import org.eclipse.swt.layout.GridData;
     70 import org.eclipse.swt.layout.GridLayout;
     71 import org.eclipse.swt.layout.RowData;
     72 import org.eclipse.swt.layout.RowLayout;
     73 import org.eclipse.swt.widgets.Button;
     74 import org.eclipse.swt.widgets.ColorDialog;
     75 import org.eclipse.swt.widgets.Composite;
     76 import org.eclipse.swt.widgets.Control;
     77 import org.eclipse.swt.widgets.Display;
     78 import org.eclipse.swt.widgets.FileDialog;
     79 import org.eclipse.swt.widgets.FontDialog;
     80 import org.eclipse.swt.widgets.Label;
     81 import org.eclipse.swt.widgets.Slider;
     82 import org.eclipse.swt.widgets.Text;
     83 
     84 import java.awt.Paint;
     85 import java.awt.image.BufferedImage;
     86 import java.io.ByteArrayInputStream;
     87 import java.io.ByteArrayOutputStream;
     88 import java.io.File;
     89 import java.io.IOException;
     90 import java.io.InputStream;
     91 import java.util.Collections;
     92 import java.util.Iterator;
     93 import java.util.LinkedHashMap;
     94 import java.util.Map;
     95 import java.util.Map.Entry;
     96 
     97 import javax.imageio.ImageIO;
     98 
     99 /**
    100  * This is normally page 2 of a Create New Asset Set wizard, unless we can offer actions
    101  * to create a specific asset type, in which case we skip page 1. On this page the user
    102  * gets to configure the parameters of the asset, and see a preview.
    103  */
    104 public class ConfigureAssetSetPage extends WizardPage implements SelectionListener,
    105         ModifyListener {
    106     private final CreateAssetSetWizardState mValues;
    107 
    108     private static final int PREVIEW_AREA_WIDTH = 144;
    109 
    110     private boolean mShown;
    111 
    112     private Composite mConfigurationArea;
    113     private Button mImageRadio;
    114     private Button mClipartRadio;
    115     private Button mTextRadio;
    116     private Button mPickImageButton;
    117     private Button mTrimCheckBox;
    118     private Slider mPaddingSlider;
    119     private Label mPercentLabel;
    120     private Button mCropRadio;
    121     private Button mCenterRadio;
    122     private Button mNoShapeRadio;
    123     private Button mSquareRadio;
    124     private Button mCircleButton;
    125     private Button mBgButton;
    126     private Button mFgButton;
    127     private Composite mPreviewArea;
    128     private Button mFontButton;
    129     private Composite mForegroundArea;
    130     private Composite mImageForm;
    131     private Composite mClipartForm;
    132     private Composite mTextForm;
    133     private Text mImagePathText;
    134 
    135     private boolean mTimerPending;
    136     private RGB mBgColor;
    137     private RGB mFgColor;
    138     private Text mText;
    139 
    140     /** Most recently set image path: preserved across wizard sessions */
    141     private static String sImagePath;
    142     private Button mChooseClipart;
    143     private Composite mClipartPreviewPanel;
    144     private Label mThemeLabel;
    145     private Composite mThemeComposite;
    146     private Button mHoloLightRadio;
    147     private Button mHoloDarkRadio;
    148     private Label mScalingLabel;
    149     private Composite mScalingComposite;
    150     private Label mShapeLabel;
    151     private Composite mShapeComposite;
    152     private Label mBgColorLabel;
    153     private Label mFgColorLabel;
    154 
    155     private boolean mIgnore;
    156     private SourceType mShowingType;
    157 
    158     /**
    159      * Create the wizard.
    160      *
    161      * @param values the wizard state
    162      */
    163     public ConfigureAssetSetPage(CreateAssetSetWizardState values) {
    164         super("configureAssetPage");
    165         mValues = values;
    166 
    167         setTitle("Configure Icon Set");
    168         setDescription("Configure the attributes of the icon set");
    169     }
    170 
    171     /**
    172      * Create contents of the wizard.
    173      *
    174      * @param parent the parent widget
    175      */
    176     @Override
    177     @SuppressWarnings("unused") // Don't warn about unassigned "new Label(.)": has side-effect
    178     public void createControl(Composite parent) {
    179         Composite container = new Composite(parent, SWT.NULL);
    180 
    181         setControl(container);
    182         GridLayout glContainer = new GridLayout(2, false);
    183         glContainer.marginWidth = 0;
    184         glContainer.horizontalSpacing = 0;
    185         glContainer.marginHeight = 0;
    186         glContainer.verticalSpacing = 0;
    187         container.setLayout(glContainer);
    188 
    189         ScrolledComposite configurationScrollArea = new ScrolledComposite(container, SWT.V_SCROLL);
    190         configurationScrollArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 2));
    191         configurationScrollArea.setExpandHorizontal(true);
    192         configurationScrollArea.setExpandVertical(true);
    193 
    194         mConfigurationArea = new Composite(configurationScrollArea, SWT.NONE);
    195         GridLayout glConfigurationArea = new GridLayout(3, false);
    196         glConfigurationArea.horizontalSpacing = 0;
    197         glConfigurationArea.marginRight = 15;
    198         glConfigurationArea.marginWidth = 0;
    199         glConfigurationArea.marginHeight = 0;
    200         mConfigurationArea.setLayout(glConfigurationArea);
    201 
    202         Label foregroundLabel = new Label(mConfigurationArea, SWT.NONE);
    203         foregroundLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    204         foregroundLabel.setText("Foreground:");
    205 
    206         Composite foregroundComposite = new Composite(mConfigurationArea, SWT.NONE);
    207         foregroundComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
    208         GridLayout glForegroundComposite = new GridLayout(5, false);
    209         glForegroundComposite.horizontalSpacing = 0;
    210         foregroundComposite.setLayout(glForegroundComposite);
    211 
    212         mImageRadio = new Button(foregroundComposite, SWT.FLAT | SWT.TOGGLE);
    213         mImageRadio.setSelection(false);
    214         mImageRadio.addSelectionListener(this);
    215         mImageRadio.setText("Image");
    216 
    217         mClipartRadio = new Button(foregroundComposite, SWT.FLAT | SWT.TOGGLE);
    218         mClipartRadio.setText("Clipart");
    219         mClipartRadio.addSelectionListener(this);
    220 
    221         mTextRadio = new Button(foregroundComposite, SWT.FLAT | SWT.TOGGLE);
    222         mTextRadio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
    223         mTextRadio.setText("Text");
    224         mTextRadio.addSelectionListener(this);
    225         new Label(mConfigurationArea, SWT.NONE);
    226 
    227         mForegroundArea = new Composite(mConfigurationArea, SWT.NONE);
    228         mForegroundArea.setLayout(new StackLayout());
    229         mForegroundArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
    230 
    231         mImageForm = new Composite(mForegroundArea, SWT.NONE);
    232         mImageForm.setLayout(new GridLayout(3, false));
    233 
    234         Label fileLabel = new Label(mImageForm, SWT.NONE);
    235         fileLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    236         fileLabel.setText("Image File:");
    237 
    238         mImagePathText = new Text(mImageForm, SWT.BORDER);
    239         GridData pathLayoutData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
    240         pathLayoutData.widthHint = 200;
    241         mImagePathText.setLayoutData(pathLayoutData);
    242         mImagePathText.addSelectionListener(this);
    243         mImagePathText.addModifyListener(this);
    244 
    245         mPickImageButton = new Button(mImageForm, SWT.FLAT);
    246         mPickImageButton.setText("Browse...");
    247         mPickImageButton.addSelectionListener(this);
    248 
    249         mClipartForm = new Composite(mForegroundArea, SWT.NONE);
    250         mClipartForm.setLayout(new GridLayout(2, false));
    251 
    252         mChooseClipart = new Button(mClipartForm, SWT.FLAT);
    253         mChooseClipart.setText("Choose...");
    254         mChooseClipart.addSelectionListener(this);
    255 
    256         mClipartPreviewPanel = new Composite(mClipartForm, SWT.NONE);
    257         RowLayout rlClipartPreviewPanel = new RowLayout(SWT.HORIZONTAL);
    258         rlClipartPreviewPanel.marginBottom = 0;
    259         rlClipartPreviewPanel.marginTop = 0;
    260         rlClipartPreviewPanel.center = true;
    261         mClipartPreviewPanel.setLayout(rlClipartPreviewPanel);
    262         mClipartPreviewPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
    263 
    264         mTextForm = new Composite(mForegroundArea, SWT.NONE);
    265         mTextForm.setLayout(new GridLayout(2, false));
    266 
    267         Label textLabel = new Label(mTextForm, SWT.NONE);
    268         textLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    269         textLabel.setText("Text:");
    270 
    271         mText = new Text(mTextForm, SWT.BORDER);
    272         mText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
    273         mText.addModifyListener(this);
    274 
    275         Label fontLabel = new Label(mTextForm, SWT.NONE);
    276         fontLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    277         fontLabel.setText("Font:");
    278 
    279         mFontButton = new Button(mTextForm, SWT.FLAT);
    280         mFontButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
    281         mFontButton.addSelectionListener(this);
    282         mFontButton.setText("Choose Font...");
    283         new Label(mConfigurationArea, SWT.NONE);
    284 
    285         mTrimCheckBox = new Button(mConfigurationArea, SWT.CHECK);
    286         mTrimCheckBox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
    287         mTrimCheckBox.setSelection(false);
    288         mTrimCheckBox.setText("Trim Surrounding Blank Space");
    289         mTrimCheckBox.addSelectionListener(this);
    290         new Label(mConfigurationArea, SWT.NONE);
    291 
    292         Label paddingLabel = new Label(mConfigurationArea, SWT.NONE);
    293         paddingLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
    294         paddingLabel.setText("Additional Padding:");
    295         new Label(mConfigurationArea, SWT.NONE);
    296 
    297         mPaddingSlider = new Slider(mConfigurationArea, SWT.NONE);
    298         mPaddingSlider.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
    299         // This doesn't work right -- not sure why. For now just use a plain slider
    300         // and subtract 10 from it to get the real range.
    301         //mPaddingSlider.setValues(0, -10, 50, 0, 1, 10);
    302         //mPaddingSlider.setSelection(10 + 15);
    303         mPaddingSlider.addSelectionListener(this);
    304 
    305         mPercentLabel = new Label(mConfigurationArea, SWT.NONE);
    306         mPercentLabel.setText("  15%"); // Enough available space for -10%
    307         mScalingLabel = new Label(mConfigurationArea, SWT.NONE);
    308         mScalingLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    309         mScalingLabel.setText("Foreground Scaling:");
    310 
    311         mScalingComposite = new Composite(mConfigurationArea, SWT.NONE);
    312         mScalingComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
    313         GridLayout gl_mScalingComposite = new GridLayout(5, false);
    314         gl_mScalingComposite.horizontalSpacing = 0;
    315         mScalingComposite.setLayout(gl_mScalingComposite);
    316 
    317         mCropRadio = new Button(mScalingComposite, SWT.FLAT | SWT.TOGGLE);
    318         mCropRadio.setSelection(true);
    319         mCropRadio.setText("Crop");
    320         mCropRadio.addSelectionListener(this);
    321 
    322         mCenterRadio = new Button(mScalingComposite, SWT.FLAT | SWT.TOGGLE);
    323         mCenterRadio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
    324         mCenterRadio.setText("Center");
    325         mCenterRadio.addSelectionListener(this);
    326 
    327         mShapeLabel = new Label(mConfigurationArea, SWT.NONE);
    328         mShapeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    329         mShapeLabel.setText("Shape");
    330 
    331         mShapeComposite = new Composite(mConfigurationArea, SWT.NONE);
    332         mShapeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
    333         GridLayout gl_mShapeComposite = new GridLayout(6, false);
    334         gl_mShapeComposite.horizontalSpacing = 0;
    335         mShapeComposite.setLayout(gl_mShapeComposite);
    336 
    337         mNoShapeRadio = new Button(mShapeComposite, SWT.FLAT | SWT.TOGGLE);
    338         mNoShapeRadio.setText("None");
    339         mNoShapeRadio.addSelectionListener(this);
    340 
    341         mSquareRadio = new Button(mShapeComposite, SWT.FLAT | SWT.TOGGLE);
    342         mSquareRadio.setSelection(true);
    343         mSquareRadio.setText("Square");
    344         mSquareRadio.addSelectionListener(this);
    345 
    346         mCircleButton = new Button(mShapeComposite, SWT.FLAT | SWT.TOGGLE);
    347         mCircleButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
    348         mCircleButton.setText("Circle");
    349         mCircleButton.addSelectionListener(this);
    350 
    351         mThemeLabel = new Label(mConfigurationArea, SWT.NONE);
    352         mThemeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    353         mThemeLabel.setText("Theme");
    354 
    355         mThemeComposite = new Composite(mConfigurationArea, SWT.NONE);
    356         mThemeComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
    357         GridLayout gl_mThemeComposite = new GridLayout(2, false);
    358         gl_mThemeComposite.horizontalSpacing = 0;
    359         mThemeComposite.setLayout(gl_mThemeComposite);
    360 
    361         mHoloLightRadio = new Button(mThemeComposite, SWT.FLAT | SWT.TOGGLE);
    362         mHoloLightRadio.setText("Holo Light");
    363         mHoloLightRadio.setSelection(true);
    364         mHoloLightRadio.addSelectionListener(this);
    365 
    366         mHoloDarkRadio = new Button(mThemeComposite, SWT.FLAT | SWT.TOGGLE);
    367         mHoloDarkRadio.setText("Holo Dark");
    368         mHoloDarkRadio.addSelectionListener(this);
    369 
    370         mBgColorLabel = new Label(mConfigurationArea, SWT.NONE);
    371         mBgColorLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    372         mBgColorLabel.setText("Background Color:");
    373 
    374         mBgButton = new Button(mConfigurationArea, SWT.FLAT);
    375         mBgButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
    376         mBgButton.addSelectionListener(this);
    377         mBgButton.setAlignment(SWT.CENTER);
    378 
    379         mFgColorLabel = new Label(mConfigurationArea, SWT.NONE);
    380         mFgColorLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
    381         mFgColorLabel.setText("Foreground Color:");
    382 
    383         mFgButton = new Button(mConfigurationArea, SWT.FLAT);
    384         mFgButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
    385         mFgButton.setAlignment(SWT.CENTER);
    386         mFgButton.addSelectionListener(this);
    387 
    388         configurationScrollArea.setContent(mConfigurationArea);
    389         configurationScrollArea.setMinSize(mConfigurationArea.computeSize(SWT.DEFAULT,
    390                 SWT.DEFAULT));
    391 
    392         Label previewLabel = new Label(container, SWT.NONE);
    393         previewLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
    394         previewLabel.setText("Preview:");
    395 
    396         mPreviewArea = new Composite(container, SWT.BORDER);
    397 
    398         RowLayout rlPreviewAreaPreviewArea = new RowLayout(SWT.HORIZONTAL);
    399         rlPreviewAreaPreviewArea.wrap = true;
    400         rlPreviewAreaPreviewArea.pack = true;
    401         rlPreviewAreaPreviewArea.center = true;
    402         rlPreviewAreaPreviewArea.spacing = 0;
    403         rlPreviewAreaPreviewArea.marginBottom = 0;
    404         rlPreviewAreaPreviewArea.marginTop = 0;
    405         rlPreviewAreaPreviewArea.marginRight = 0;
    406         rlPreviewAreaPreviewArea.marginLeft = 0;
    407         mPreviewArea.setLayout(rlPreviewAreaPreviewArea);
    408         GridData gdMPreviewArea = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
    409         gdMPreviewArea.widthHint = PREVIEW_AREA_WIDTH;
    410         mPreviewArea.setLayoutData(gdMPreviewArea);
    411 
    412         // Initial color
    413         Display display = parent.getDisplay();
    414         updateColor(display, mValues.background, true /*background*/);
    415         updateColor(display, mValues.foreground, false /*background*/);
    416 
    417         setSourceType(mValues.sourceType);
    418 
    419         new Label(mConfigurationArea, SWT.NONE);
    420         new Label(mConfigurationArea, SWT.NONE);
    421         new Label(mConfigurationArea, SWT.NONE);
    422 
    423         validatePage();
    424     }
    425 
    426     void configureAssetType(AssetType type) {
    427         if (mValues.sourceType != mShowingType) {
    428             mShowingType = mValues.sourceType;
    429             showGroup(type.needsForegroundScaling(), mScalingLabel, mScalingComposite);
    430             showGroup(type.needsShape(), mShapeLabel, mShapeComposite);
    431             showGroup(type.needsTheme(), mThemeLabel, mThemeComposite);
    432             showGroup(type.needsColors(), mBgColorLabel, mBgButton);
    433             showGroup(type.needsColors() && mValues.sourceType != SourceType.IMAGE,
    434                     mFgColorLabel, mFgButton);
    435 
    436             Composite parent = mScalingLabel.getParent();
    437             parent.pack();
    438             parent.layout();
    439         }
    440     }
    441 
    442     private static void showGroup(boolean show, Control control1, Control control2) {
    443         showControl(show, control1);
    444         showControl(show, control2);
    445     }
    446 
    447     private static void showControl(boolean show, Control control) {
    448         Object data = control.getLayoutData();
    449         if (data instanceof GridData) {
    450             GridData gridData = (GridData) data;
    451             gridData.exclude = !show;
    452         }
    453         control.setVisible(show);
    454     }
    455 
    456     @Override
    457     public void setVisible(boolean visible) {
    458         super.setVisible(visible);
    459 
    460         // We update the image selection here rather than in {@link #createControl} because
    461         // that method is called when the wizard is created, and we want to wait until the
    462         // user has chosen a project before attempting to look up the right default image to use
    463         if (visible) {
    464             mShown = true;
    465 
    466             // Clear out old previews - important if the user goes back to page one, changes
    467             // asset type and steps into page 2 - at that point we arrive here and we might
    468             // display the old previews for a brief period until the preview delay timer expires.
    469             for (Control c : mPreviewArea.getChildren()) {
    470                 c.dispose();
    471             }
    472             mPreviewArea.layout(true);
    473 
    474             // Update asset type configuration: will show/hide parameter controls depending
    475             // on which asset type is chosen
    476             AssetType type = mValues.type;
    477             assert type != null;
    478             configureAssetType(type);
    479 
    480             // Initial image - use the most recently used image, or the default launcher
    481             // icon created in our default projects, if there
    482             if (mValues.imagePath != null) {
    483                 sImagePath = mValues.imagePath.getPath();
    484             }
    485             if (sImagePath == null) {
    486                 IProject project = mValues.project;
    487                 if (project != null) {
    488                     IResource icon = project.findMember("res/drawable-hdpi/icon.png"); //$NON-NLS-1$
    489                     if (icon != null) {
    490                         IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot();
    491                         IPath workspacePath = workspace.getLocation();
    492                         sImagePath = workspacePath.append(icon.getFullPath()).toOSString();
    493                     }
    494                 }
    495             }
    496             if (sImagePath != null) {
    497                 mValues.imagePath = new File(sImagePath);
    498                 mImagePathText.setText(sImagePath);
    499             }
    500 
    501             try {
    502                 mIgnore = true;
    503 
    504                 mTrimCheckBox.setSelection(mValues.trim);
    505 
    506                 // This doesn't work right -- not sure why. For now just use a plain slider
    507                 // and subtract 10 from it to get the real range.
    508                 //mPaddingSlider.setValues(0, -10, 50, 0, 1, 10);
    509                 //mPaddingSlider.setSelection(10 + 15);
    510                 mPaddingSlider.setSelection(mValues.padding + 10);
    511                 mPercentLabel.setText(Integer.toString(mValues.padding) + '%');
    512 
    513                 if (mValues.imagePath != null) {
    514                     mImagePathText.setText(mValues.imagePath.getPath());
    515                 }
    516 
    517                 if (mValues.text != null) {
    518                     mText.setText(mValues.text);
    519                 }
    520 
    521                 setSourceType(mValues.sourceType);
    522 
    523                 // Shape=NONE does not apply for notification icons; it's needed for API < 9
    524                 if (mValues.shape == Shape.NONE && mValues.type == AssetType.NOTIFICATION) {
    525                     mValues.shape = Shape.SQUARE;
    526                 }
    527 
    528                 setShape(mValues.shape);
    529                 mNoShapeRadio.setEnabled(mValues.type != AssetType.NOTIFICATION);
    530 
    531                 if (mValues.sourceType == SourceType.CLIPART
    532                         && mValues.clipartName != null) {
    533                     updateClipartPreview();
    534                 }
    535 
    536                 // Initial color
    537                 Display display = mPreviewArea.getDisplay();
    538                 //updateColor(display, new RGB(0xa4, 0xc6, 0x39), true /*background*/);
    539                 updateColor(display, mValues.background, true /*background*/);
    540                 updateColor(display, mValues.foreground, false /*background*/);
    541 
    542                 updateTrimOptions();
    543             } finally {
    544                 mIgnore = false;
    545             }
    546 
    547             validatePage();
    548 
    549             requestUpdatePreview(true /*quickly*/);
    550 
    551             if (mTextRadio.getSelection()) {
    552                 mText.setFocus();
    553             }
    554         }
    555     }
    556 
    557     private void setSourceType(CreateAssetSetWizardState.SourceType sourceType) {
    558         if (sourceType == CreateAssetSetWizardState.SourceType.IMAGE) {
    559             chooseForegroundTab(mImageRadio, mImageForm);
    560         } else if (sourceType == CreateAssetSetWizardState.SourceType.CLIPART) {
    561             chooseForegroundTab(mClipartRadio, mClipartForm);
    562             mChooseClipart.setFocus();
    563         } else if (sourceType == CreateAssetSetWizardState.SourceType.TEXT) {
    564             updateFontLabel();
    565             chooseForegroundTab(mTextRadio, mTextForm);
    566             mText.setFocus();
    567         }
    568     }
    569 
    570     private void updateTrimOptions() {
    571         // Trimming and padding is not available for clipart images; padding etc is
    572         // predefined to work well with action bar icons
    573         if (mValues.sourceType == SourceType.CLIPART
    574                 && mValues.type == AssetType.ACTIONBAR) {
    575             mTrimCheckBox.setEnabled(false);
    576             mPaddingSlider.setEnabled(false);
    577             mValues.trim = false;
    578         } else if (!mTrimCheckBox.isEnabled()) {
    579             mTrimCheckBox.setEnabled(true);
    580             mPaddingSlider.setEnabled(true);
    581         }
    582     }
    583 
    584     private boolean validatePage() {
    585         String error = null;
    586         //String warning = null;
    587 
    588         if (mImageRadio.getSelection()) {
    589             String path = mValues.imagePath != null ? mValues.imagePath.getPath() : null;
    590             if (path == null || path.length() == 0) {
    591                 error = "Select an image";
    592             } else if (path.equals(DEFAULT_LAUNCHER_ICON)) {
    593                 // Silent
    594             } else if (!(new File(path).exists())) {
    595                 error = String.format("%1$s does not exist", path);
    596             } else {
    597                 // Preserve across wizard sessions
    598                 sImagePath = path;
    599             }
    600         } else if (mTextRadio.getSelection()) {
    601             if (mValues.text.length() == 0) {
    602                 error = "Enter text";
    603             }
    604         } else {
    605             assert mClipartRadio.getSelection();
    606             if (mValues.clipartName == null) {
    607                 error = "Select clip art";
    608             }
    609         }
    610 
    611         setPageComplete(error == null);
    612         if (error != null) {
    613             setMessage(error, IMessageProvider.ERROR);
    614         //} else if (warning != null) {
    615         //    setMessage(warning, IMessageProvider.WARNING);
    616         } else {
    617             setErrorMessage(null);
    618             setMessage(null);
    619         }
    620 
    621         return error == null;
    622     }
    623 
    624     @Override
    625     public boolean isPageComplete() {
    626         // Force user to reach second page before hitting Finish
    627         return mShown;
    628     }
    629 
    630     // ---- Implements ModifyListener ----
    631 
    632     @Override
    633     public void modifyText(ModifyEvent e) {
    634         if (mIgnore) {
    635             return;
    636         }
    637 
    638         if (e.getSource() == mImagePathText) {
    639             mValues.imagePath = new File(mImagePathText.getText().trim());
    640             requestUpdatePreview(false);
    641         } else if (e.getSource() == mText) {
    642             mValues.text = mText.getText().trim();
    643             requestUpdatePreview(false);
    644         }
    645 
    646         validatePage();
    647     }
    648 
    649     // ---- Implements SelectionListener ----
    650 
    651     @Override
    652     public void widgetDefaultSelected(SelectionEvent e) {
    653         // Nothing to do
    654     }
    655 
    656     @Override
    657     public void widgetSelected(SelectionEvent e) {
    658         if (mIgnore) {
    659             return;
    660         }
    661 
    662         Object source = e.getSource();
    663         boolean updateQuickly = true;
    664 
    665         // Tabs
    666         if (source == mImageRadio) {
    667             mValues.sourceType = CreateAssetSetWizardState.SourceType.IMAGE;
    668             chooseForegroundTab((Button) source, mImageForm);
    669             configureAssetType(mValues.type);
    670             updateTrimOptions();
    671         } else if (source == mClipartRadio) {
    672             mValues.sourceType = CreateAssetSetWizardState.SourceType.CLIPART;
    673             chooseForegroundTab((Button) source, mClipartForm);
    674             configureAssetType(mValues.type);
    675             updateTrimOptions();
    676         } else if (source == mTextRadio) {
    677             mValues.sourceType = CreateAssetSetWizardState.SourceType.TEXT;
    678             updateFontLabel();
    679             chooseForegroundTab((Button) source, mTextForm);
    680             configureAssetType(mValues.type);
    681             mText.setFocus();
    682             updateTrimOptions();
    683         }
    684 
    685         // Choose image file
    686         if (source == mPickImageButton) {
    687             FileDialog dialog = new FileDialog(mPickImageButton.getShell(), SWT.OPEN);
    688 
    689             String curLocation = mImagePathText.getText().trim();
    690             if (!curLocation.isEmpty()) {
    691                 dialog.setFilterPath(curLocation);
    692             }
    693 
    694             String file = dialog.open();
    695             if (file != null) {
    696                 mValues.imagePath = new File(file);
    697                 mImagePathText.setText(file);
    698             }
    699         }
    700 
    701         // Enforce Radio Groups
    702         if (source == mCropRadio) {
    703             mCropRadio.setSelection(true); // Ensure that you can't toggle it off
    704             mCenterRadio.setSelection(false);
    705             mValues.crop = true;
    706         } else if (source == mCenterRadio) {
    707             mCenterRadio.setSelection(true);
    708             mCropRadio.setSelection(false);
    709             mValues.crop = false;
    710         }
    711         if (source == mSquareRadio) {
    712             mValues.shape = GraphicGenerator.Shape.SQUARE;
    713             setShape(mValues.shape);
    714         } else if (source == mCircleButton) {
    715             mValues.shape = GraphicGenerator.Shape.CIRCLE;
    716             setShape(mValues.shape);
    717         } else if (source == mNoShapeRadio) {
    718             mValues.shape = GraphicGenerator.Shape.NONE;
    719             setShape(mValues.shape);
    720         }
    721 
    722         if (source == mTrimCheckBox) {
    723             mValues.trim = mTrimCheckBox.getSelection();
    724         }
    725 
    726         if (source == mHoloDarkRadio) {
    727             mHoloDarkRadio.setSelection(true);
    728             mHoloLightRadio.setSelection(false);
    729             mValues.holoDark = true;
    730         } else if (source == mHoloLightRadio) {
    731             mHoloLightRadio.setSelection(true);
    732             mHoloDarkRadio.setSelection(false);
    733             mValues.holoDark = false;
    734         }
    735 
    736         if (source == mChooseClipart) {
    737             MessageDialog dialog = new MessageDialog(mChooseClipart.getShell(),
    738                     "Choose Clip Art",
    739                     null, "Choose Clip Art Image:", MessageDialog.NONE,
    740                     new String[] { "Close" }, 0) {
    741                 @Override
    742                 protected Control createCustomArea(Composite parent) {
    743                     // Outer form which just establishes a width for the inner form which
    744                     // wraps in a RowLayout
    745                     Composite outer = new Composite(parent, SWT.NONE);
    746                     GridLayout gridLayout = new GridLayout();
    747                     outer.setLayout(gridLayout);
    748 
    749                     Composite chooserForm = new Composite(outer, SWT.NONE);
    750                     GridData gd = new GridData();
    751                     gd.grabExcessVerticalSpace = true;
    752                     gd.widthHint = 450;
    753                     chooserForm.setLayoutData(gd);
    754                     RowLayout clipartFormLayout = new RowLayout(SWT.HORIZONTAL);
    755                     clipartFormLayout.center = true;
    756                     clipartFormLayout.wrap = true;
    757                     chooserForm.setLayout(clipartFormLayout);
    758 
    759                     MouseAdapter clickListener = new MouseAdapter() {
    760                         @Override
    761                         public void mouseDown(MouseEvent event) {
    762                             // Clicked on some of the sample art
    763                             if (event.widget instanceof ImageControl) {
    764                                 ImageControl image = (ImageControl) event.widget;
    765                                 mValues.clipartName = (String) image.getData();
    766                                 close();
    767 
    768                                 updateClipartPreview();
    769                                 updatePreview();
    770                             }
    771                         }
    772                     };
    773                     Display display = chooserForm.getDisplay();
    774                     Color hoverColor = display.getSystemColor(SWT.COLOR_RED);
    775                     Iterator<String> clipartImages = GraphicGenerator.getClipartNames();
    776                     while (clipartImages.hasNext()) {
    777                         String name = clipartImages.next();
    778                         try {
    779                             BufferedImage icon = GraphicGenerator.getClipartIcon(name);
    780                             if (icon != null) {
    781                                 Image swtImage = SwtUtils.convertToSwt(display, icon, true, -1);
    782                                 ImageControl img = new ImageControl(chooserForm,
    783                                         SWT.NONE, swtImage);
    784                                 img.setData(name);
    785                                 img.setHoverColor(hoverColor);
    786                                 img.addMouseListener(clickListener);
    787                             }
    788                         } catch (IOException e1) {
    789                             AdtPlugin.log(e1, null);
    790                         }
    791                     }
    792                     outer.pack();
    793                     outer.layout();
    794                     return outer;
    795                 }
    796             };
    797             dialog.open();
    798         }
    799 
    800         if (source == mBgButton) {
    801             ColorDialog dlg = new ColorDialog(mBgButton.getShell());
    802             dlg.setRGB(mBgColor);
    803             dlg.setText("Choose a new Background Color");
    804             RGB rgb = dlg.open();
    805             if (rgb != null) {
    806                 // Dispose the old color, create the
    807                 // new one, and set into the label
    808                 mValues.background = rgb;
    809                 updateColor(mBgButton.getDisplay(), rgb, true /*background*/);
    810             }
    811         } else if (source == mFgButton) {
    812             ColorDialog dlg = new ColorDialog(mFgButton.getShell());
    813             dlg.setRGB(mFgColor);
    814             dlg.setText("Choose a new Foreground Color");
    815             RGB rgb = dlg.open();
    816             if (rgb != null) {
    817                 // Dispose the old color, create the
    818                 // new one, and set into the label
    819                 mValues.foreground = rgb;
    820                 updateColor(mFgButton.getDisplay(), rgb, false /*background*/);
    821             }
    822         }
    823 
    824         if (source == mFontButton) {
    825             FontDialog dialog = new FontDialog(mFontButton.getShell());
    826             FontData[] fontList;
    827             if (mFontButton.getData() == null) {
    828                 fontList = mFontButton.getDisplay().getFontList(
    829                         mValues.getTextFont().getFontName(), true /*scalable*/);
    830             } else {
    831                 fontList = mFontButton.getFont().getFontData();
    832             }
    833             dialog.setFontList(fontList);
    834             FontData data = dialog.open();
    835             if (data != null) {
    836                 Font font = new Font(mFontButton.getDisplay(), dialog.getFontList());
    837                 mFontButton.setFont(font);
    838                 mFontButton.setData(font);
    839 
    840                 // Always use a large font for the rendering, even though user is typically
    841                 // picking small font sizes in the font chooser
    842                 //int dpi = mFontButton.getDisplay().getDPI().y;
    843                 //int height = (int) Math.round(fontData.getHeight() * dpi / 72.0);
    844                 int fontHeight = new TextRenderUtil.Options().fontSize;
    845                 FontData fontData = font.getFontData()[0];
    846                 int awtStyle = java.awt.Font.PLAIN;
    847                 int swtStyle = fontData.getStyle();
    848                 if ((swtStyle & SWT.ITALIC) != 0) {
    849                     awtStyle |= java.awt.Font.ITALIC;
    850                 }
    851                 if ((swtStyle & SWT.BOLD) != 0) {
    852                     awtStyle = java.awt.Font.BOLD;
    853                 }
    854                 mValues.setTextFont(new java.awt.Font(fontData.getName(), awtStyle, fontHeight));
    855 
    856                 updateFontLabel();
    857                 mFontButton.getParent().pack();
    858             }
    859         }
    860 
    861         if (source == mPaddingSlider) {
    862             mValues.padding = getPadding();
    863             mPercentLabel.setText(Integer.toString(getPadding()) + '%');
    864 
    865             // When dragging the slider, only do periodic updates
    866             updateQuickly = false;
    867         }
    868 
    869         requestUpdatePreview(updateQuickly);
    870     }
    871 
    872     @SuppressWarnings("unused") // SWT constructors have side effects and are not unused
    873     private void updateClipartPreview() {
    874         for (Control c : mClipartPreviewPanel.getChildren()) {
    875             c.dispose();
    876         }
    877         if (mClipartPreviewPanel.getChildren().length == 0) {
    878             try {
    879                 BufferedImage icon = GraphicGenerator.getClipartIcon(
    880                         mValues.clipartName);
    881                 if (icon != null) {
    882                     Display display = mClipartForm.getDisplay();
    883                     Image swtImage = SwtUtils.convertToSwt(display, icon,
    884                             true, -1);
    885                     new ImageControl(mClipartPreviewPanel,
    886                             SWT.NONE, swtImage);
    887                 }
    888             } catch (IOException e1) {
    889                 AdtPlugin.log(e1, null);
    890             }
    891             mClipartPreviewPanel.pack();
    892             mClipartPreviewPanel.layout();
    893         }
    894     }
    895 
    896     private void setShape(GraphicGenerator.Shape shape) {
    897         if (shape == GraphicGenerator.Shape.SQUARE) {
    898             mSquareRadio.setSelection(true);
    899             mCircleButton.setSelection(false);
    900             mNoShapeRadio.setSelection(false);
    901         } else if (shape == GraphicGenerator.Shape.CIRCLE) {
    902             mCircleButton.setSelection(true);
    903             mSquareRadio.setSelection(false);
    904             mNoShapeRadio.setSelection(false);
    905         } else if (shape == GraphicGenerator.Shape.NONE) {
    906             mNoShapeRadio.setSelection(true);
    907             mCircleButton.setSelection(false);
    908             mSquareRadio.setSelection(false);
    909         } else {
    910             assert false : shape;
    911         }
    912     }
    913 
    914     private void updateFontLabel() {
    915         mFontButton.setText(mValues.getTextFont().getFontName());
    916     }
    917 
    918     private int getPadding() {
    919         // Shifted - see comment for mPaddingSlider construction for an explanation
    920         return mPaddingSlider.getSelection() - 10;
    921     }
    922 
    923     private void chooseForegroundTab(Button newButton, Composite newArea) {
    924         if (newButton.getSelection()) {
    925             mImageRadio.setSelection(false);
    926             mClipartRadio.setSelection(false);
    927             mTextRadio.setSelection(false);
    928             newButton.setSelection(true);
    929             StackLayout stackLayout = (StackLayout) mForegroundArea.getLayout();
    930             stackLayout.topControl = newArea;
    931             mForegroundArea.layout();
    932         } else {
    933             // Treat it as a radio button: you can't click to turn it off, you have to
    934             // click on one of the other buttons
    935             newButton.setSelection(true);
    936         }
    937     }
    938 
    939     /**
    940      * Delay updates of the preview, to ensure that the SWT UI acts immediately (to handle
    941      * radio group selections etc).
    942      *
    943      * @param quickly if true, update the previews soon, otherwise schedule one a bit later
    944      */
    945     private void requestUpdatePreview(boolean quickly) {
    946         if (mTimerPending) {
    947             return;
    948         }
    949         mTimerPending = true;
    950 
    951         final Runnable timer = new Runnable() {
    952             @Override
    953             public void run() {
    954                 mTimerPending = false;
    955                 updatePreview();
    956             }
    957         };
    958 
    959         mPreviewArea.getDisplay().timerExec(quickly ? 10 : 250, timer);
    960     }
    961 
    962     private void updatePreview() {
    963         Display display = mPreviewArea.getDisplay();
    964 
    965         for (Control c : mPreviewArea.getChildren()) {
    966             c.dispose();
    967         }
    968 
    969         if (!validatePage()) {
    970             return;
    971         }
    972 
    973         Map<String, Map<String, BufferedImage>> map = generateImages(mValues,
    974                 true /*previewOnly*/, this);
    975         for (Entry<String, Map<String, BufferedImage>> categoryEntry : map.entrySet()) {
    976             String category = categoryEntry.getKey();
    977             if (category.length() > 0) {
    978                 Label nameLabel = new Label(mPreviewArea, SWT.NONE);
    979                 nameLabel.setText(String.format("%1$s:", category));
    980                 RowData rowData = new RowData();
    981                 nameLabel.setLayoutData(rowData);
    982                 // Ensure these get their own rows
    983                 rowData.width = PREVIEW_AREA_WIDTH;
    984             }
    985 
    986             Map<String, BufferedImage> images = categoryEntry.getValue();
    987             for (Entry<String, BufferedImage> entry :  images.entrySet()) {
    988                 BufferedImage image = entry.getValue();
    989                 Image swtImage = SwtUtils.convertToSwt(display, image, true, -1);
    990                 if (swtImage != null) {
    991                     @SuppressWarnings("unused") // Has side effect
    992                     ImageControl imageControl = new ImageControl(mPreviewArea, SWT.NONE, swtImage);
    993                 }
    994             }
    995         }
    996 
    997         mPreviewArea.layout(true);
    998     }
    999 
   1000     /**
   1001      * Generate images using the given wizard state
   1002      *
   1003      * @param mValues the state to use
   1004      * @param previewOnly whether we are only generating previews
   1005      * @param page if non null, a wizard page to write error messages to
   1006      * @return a map of image objects
   1007      */
   1008     public static Map<String, Map<String, BufferedImage>> generateImages(
   1009             @NonNull CreateAssetSetWizardState mValues,
   1010             boolean previewOnly,
   1011             @Nullable WizardPage page) {
   1012         // Map of ids to images: Preserve insertion order (the densities)
   1013         Map<String, Map<String, BufferedImage>> categoryMap =
   1014                 new LinkedHashMap<String, Map<String, BufferedImage>>();
   1015 
   1016         AssetType type = mValues.type;
   1017         boolean trim = mValues.trim;
   1018 
   1019         BufferedImage sourceImage = null;
   1020         switch (mValues.sourceType) {
   1021             case IMAGE: {
   1022                 // Load the image
   1023                 // TODO: Only do this when the source image type is image
   1024                 String path = mValues.imagePath != null ? mValues.imagePath.getPath() : "";
   1025                 if (path.length() == 0) {
   1026                     if (page != null) {
   1027                         page.setErrorMessage("Enter a filename");
   1028                     }
   1029                     return Collections.emptyMap();
   1030                 }
   1031                 if (!path.equals(DEFAULT_LAUNCHER_ICON)) {
   1032                     File file = new File(path);
   1033                     if (!file.isFile()) {
   1034                         if (page != null) {
   1035                             page.setErrorMessage(String.format("%1$s does not exist", file.getPath()));
   1036                         }
   1037                         return Collections.emptyMap();
   1038                     }
   1039                 }
   1040 
   1041                 if (page != null) {
   1042                     page.setErrorMessage(null);
   1043                 }
   1044                 try {
   1045                     sourceImage = mValues.getCachedImage(path, false);
   1046                     if (sourceImage != null) {
   1047                         if (trim) {
   1048                             sourceImage = ImageUtils.cropBlank(sourceImage, null, TYPE_INT_ARGB);
   1049                         }
   1050                         if (mValues.padding != 0) {
   1051                             sourceImage = Util.paddedImage(sourceImage, mValues.padding);
   1052                         }
   1053                     }
   1054                 } catch (IOException ioe) {
   1055                     if (page != null) {
   1056                         page.setErrorMessage(ioe.getLocalizedMessage());
   1057                     }
   1058                 }
   1059                 break;
   1060             }
   1061             case CLIPART: {
   1062                 try {
   1063                     sourceImage = GraphicGenerator.getClipartImage(mValues.clipartName);
   1064 
   1065                     boolean isActionBar = mValues.type == AssetType.ACTIONBAR;
   1066                     if (trim && !isActionBar) {
   1067                         sourceImage = ImageUtils.cropBlank(sourceImage, null, TYPE_INT_ARGB);
   1068                     }
   1069 
   1070                     if (type.needsColors()) {
   1071                         RGB fg = mValues.foreground;
   1072                         int color = 0xFF000000 | (fg.red << 16) | (fg.green << 8) | fg.blue;
   1073                         Paint paint = new java.awt.Color(color);
   1074                         sourceImage = Util.filledImage(sourceImage, paint);
   1075                     }
   1076 
   1077                     int padding = mValues.padding;
   1078                     if (padding != 0 && !isActionBar) {
   1079                         sourceImage = Util.paddedImage(sourceImage, padding);
   1080                     }
   1081                 } catch (IOException e) {
   1082                     AdtPlugin.log(e, null);
   1083                     return categoryMap;
   1084                 }
   1085                 break;
   1086             }
   1087             case TEXT: {
   1088                 String text = mValues.text;
   1089                 TextRenderUtil.Options options = new TextRenderUtil.Options();
   1090                 options.font = mValues.getTextFont();
   1091                 int color;
   1092                 if (type.needsColors()) {
   1093                     RGB fg = mValues.foreground;
   1094                     color = 0xFF000000 | (fg.red << 16) | (fg.green << 8) | fg.blue;
   1095                 } else {
   1096                     color = 0xFFFFFFFF;
   1097                 }
   1098                 options.foregroundColor = color;
   1099                 sourceImage = TextRenderUtil.renderTextImage(text, mValues.padding, options);
   1100 
   1101                 if (trim) {
   1102                     sourceImage = ImageUtils.cropBlank(sourceImage, null, TYPE_INT_ARGB);
   1103                 }
   1104 
   1105                 int padding = mValues.padding;
   1106                 if (padding != 0) {
   1107                     sourceImage = Util.paddedImage(sourceImage, padding);
   1108                 }
   1109                 break;
   1110             }
   1111         }
   1112 
   1113         GraphicGenerator generator = null;
   1114         GraphicGenerator.Options options = null;
   1115         switch (type) {
   1116             case LAUNCHER: {
   1117                 generator = new LauncherIconGenerator();
   1118                 LauncherIconGenerator.LauncherOptions launcherOptions =
   1119                         new LauncherIconGenerator.LauncherOptions();
   1120                 launcherOptions.shape = mValues.shape;
   1121                 launcherOptions.crop = mValues.crop;
   1122                 launcherOptions.style = GraphicGenerator.Style.SIMPLE;
   1123 
   1124                 RGB bg = mValues.background;
   1125                 int color = (bg.red << 16) | (bg.green << 8) | bg.blue;
   1126                 launcherOptions.backgroundColor = color;
   1127                 // Flag which tells the generator iterator to include a web graphic
   1128                 launcherOptions.isWebGraphic = !previewOnly;
   1129                 options = launcherOptions;
   1130 
   1131                 break;
   1132             }
   1133             case MENU:
   1134                 generator = new MenuIconGenerator();
   1135                 options = new GraphicGenerator.Options();
   1136                 break;
   1137             case ACTIONBAR: {
   1138                 generator = new ActionBarIconGenerator();
   1139                 ActionBarIconGenerator.ActionBarOptions actionBarOptions =
   1140                         new ActionBarIconGenerator.ActionBarOptions();
   1141                 actionBarOptions.theme = mValues.holoDark
   1142                         ? ActionBarIconGenerator.Theme.HOLO_DARK
   1143                                 : ActionBarIconGenerator.Theme.HOLO_LIGHT;
   1144                 actionBarOptions.sourceIsClipart = (mValues.sourceType == SourceType.CLIPART);
   1145 
   1146                 options = actionBarOptions;
   1147                 break;
   1148             }
   1149             case NOTIFICATION: {
   1150                 generator = new NotificationIconGenerator();
   1151                 options = new NotificationIconGenerator.NotificationOptions();
   1152                 break;
   1153             }
   1154             case TAB:
   1155                 generator = new TabIconGenerator();
   1156                 options = new TabIconGenerator.TabOptions();
   1157                 break;
   1158             default:
   1159                 AdtPlugin.log(IStatus.ERROR, "Unsupported asset type: %1$s", type);
   1160                 return categoryMap;
   1161         }
   1162 
   1163         options.sourceImage = sourceImage;
   1164 
   1165         IProject project = mValues.project;
   1166         if (mValues.minSdk != -1) {
   1167             options.minSdk = mValues.minSdk;
   1168         } else {
   1169             Pair<Integer, Integer> v = ManifestInfo.computeSdkVersions(project);
   1170             options.minSdk = v.getFirst();
   1171         }
   1172 
   1173         String baseName = mValues.outputName;
   1174         generator.generate(null, categoryMap, mValues, options, baseName);
   1175 
   1176         return categoryMap;
   1177     }
   1178 
   1179     /**
   1180      * Generate custom icons into the project based on the asset studio wizard
   1181      * state
   1182      *
   1183      * @param newProject the project to write into
   1184      * @param values the wizard state to read configuration settings from
   1185      * @param previewOnly whether we are only generating a preview. For example,
   1186      *            the launcher icons won't generate a huge 512x512 web graphic
   1187      *            in preview mode
   1188      * @param page a wizard page to write error messages to, or null
   1189      */
   1190     public static void generateIcons(final IProject newProject,
   1191             @NonNull CreateAssetSetWizardState values,
   1192             boolean previewOnly,
   1193             @Nullable WizardPage page) {
   1194         // Generate the custom icons
   1195         Map<String, Map<String, BufferedImage>> categories = generateImages(values,
   1196                 false /*previewOnly*/, page);
   1197         for (Map<String, BufferedImage> previews : categories.values()) {
   1198             for (Map.Entry<String, BufferedImage> entry : previews.entrySet()) {
   1199                 String relativePath = entry.getKey();
   1200                 IPath dest = new Path(relativePath);
   1201                 IFile file = newProject.getFile(dest);
   1202 
   1203                 // In case template already created icons (should remove that)
   1204                 // remove them first
   1205                 if (file.exists()) {
   1206                     try {
   1207                         file.delete(true, new NullProgressMonitor());
   1208                     } catch (CoreException e) {
   1209                         AdtPlugin.log(e, null);
   1210                     }
   1211                 }
   1212                 AdtUtils.createWsParentDirectory(file.getParent());
   1213                 BufferedImage image = entry.getValue();
   1214 
   1215                 ByteArrayOutputStream stream = new ByteArrayOutputStream();
   1216                 try {
   1217                     ImageIO.write(image, "PNG", stream); //$NON-NLS-1$
   1218                     byte[] bytes = stream.toByteArray();
   1219                     InputStream is = new ByteArrayInputStream(bytes);
   1220                     file.create(is, true /*force*/, null /*progress*/);
   1221                 } catch (IOException e) {
   1222                     AdtPlugin.log(e, null);
   1223                 } catch (CoreException e) {
   1224                     AdtPlugin.log(e, null);
   1225                 }
   1226 
   1227                 try {
   1228                     file.getParent().refreshLocal(1, new NullProgressMonitor());
   1229                 } catch (CoreException e) {
   1230                     AdtPlugin.log(e, null);
   1231                 }
   1232             }
   1233         }
   1234     }
   1235 
   1236     private void updateColor(Display display, RGB color, boolean isBackground) {
   1237         // Button.setBackgroundColor does not work (at least not on OSX) so
   1238         // we instead have to use Button.setImage with an image of the given
   1239         // color
   1240         BufferedImage coloredImage = ImageUtils.createColoredImage(60, 20, color);
   1241         Image image = SwtUtils.convertToSwt(display, coloredImage, false, -1);
   1242 
   1243         if (isBackground) {
   1244             mBgColor = color;
   1245             mBgButton.setImage(image);
   1246         } else {
   1247             mFgColor = color;
   1248             mFgButton.setImage(image);
   1249         }
   1250     }
   1251 }
   1252