| /* |
| * 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 static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectWizard.DEFAULT_LAUNCHER_ICON; |
| import static java.awt.image.BufferedImage.TYPE_INT_ARGB; |
| |
| import com.android.annotations.NonNull; |
| import com.android.annotations.Nullable; |
| import com.android.assetstudiolib.ActionBarIconGenerator; |
| import com.android.assetstudiolib.GraphicGenerator; |
| import com.android.assetstudiolib.GraphicGenerator.Shape; |
| import com.android.assetstudiolib.LauncherIconGenerator; |
| import com.android.assetstudiolib.MenuIconGenerator; |
| import com.android.assetstudiolib.NotificationIconGenerator; |
| import com.android.assetstudiolib.TabIconGenerator; |
| import com.android.assetstudiolib.TextRenderUtil; |
| import com.android.assetstudiolib.Util; |
| import com.android.ide.eclipse.adt.AdtPlugin; |
| import com.android.ide.eclipse.adt.AdtUtils; |
| import com.android.ide.eclipse.adt.internal.assetstudio.CreateAssetSetWizardState.SourceType; |
| 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.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; |
| import com.android.utils.Pair; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jface.dialogs.IMessageProvider; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.wizard.WizardPage; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.ScrolledComposite; |
| import org.eclipse.swt.custom.StackLayout; |
| import org.eclipse.swt.events.ModifyEvent; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.events.MouseAdapter; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.FontData; |
| 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; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.FileDialog; |
| import org.eclipse.swt.widgets.FontDialog; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Slider; |
| import org.eclipse.swt.widgets.Text; |
| |
| import java.awt.Paint; |
| import java.awt.image.BufferedImage; |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| import javax.imageio.ImageIO; |
| |
| /** |
| * This is normally page 2 of a Create New Asset Set wizard, unless we can offer actions |
| * to create a specific asset type, in which case we skip page 1. On this page the user |
| * gets to configure the parameters of the asset, and see a preview. |
| */ |
| public class ConfigureAssetSetPage extends WizardPage implements SelectionListener, |
| ModifyListener { |
| private final CreateAssetSetWizardState mValues; |
| |
| private static final int PREVIEW_AREA_WIDTH = 144; |
| |
| private boolean mShown; |
| |
| private Composite mConfigurationArea; |
| private Button mImageRadio; |
| private Button mClipartRadio; |
| private Button mTextRadio; |
| private Button mPickImageButton; |
| private Button mTrimCheckBox; |
| private Slider mPaddingSlider; |
| private Label mPercentLabel; |
| private Button mCropRadio; |
| private Button mCenterRadio; |
| private Button mNoShapeRadio; |
| private Button mSquareRadio; |
| private Button mCircleButton; |
| private Button mBgButton; |
| private Button mFgButton; |
| private Composite mPreviewArea; |
| private Button mFontButton; |
| private Composite mForegroundArea; |
| private Composite mImageForm; |
| private Composite mClipartForm; |
| private Composite mTextForm; |
| private Text mImagePathText; |
| |
| private boolean mTimerPending; |
| private RGB mBgColor; |
| private RGB mFgColor; |
| private Text mText; |
| |
| /** Most recently set image path: preserved across wizard sessions */ |
| 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 boolean mIgnore; |
| private SourceType mShowingType; |
| |
| /** |
| * Create the wizard. |
| * |
| * @param values the wizard state |
| */ |
| public ConfigureAssetSetPage(CreateAssetSetWizardState values) { |
| super("configureAssetPage"); |
| mValues = values; |
| |
| setTitle("Configure Icon Set"); |
| setDescription("Configure the attributes of the icon set"); |
| } |
| |
| /** |
| * Create contents of the wizard. |
| * |
| * @param parent the parent widget |
| */ |
| @Override |
| @SuppressWarnings("unused") // Don't warn about unassigned "new Label(.)": has side-effect |
| public void createControl(Composite parent) { |
| Composite container = new Composite(parent, SWT.NULL); |
| |
| setControl(container); |
| GridLayout glContainer = new GridLayout(2, false); |
| glContainer.marginWidth = 0; |
| glContainer.horizontalSpacing = 0; |
| glContainer.marginHeight = 0; |
| glContainer.verticalSpacing = 0; |
| container.setLayout(glContainer); |
| |
| ScrolledComposite configurationScrollArea = new ScrolledComposite(container, SWT.V_SCROLL); |
| configurationScrollArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 2)); |
| configurationScrollArea.setExpandHorizontal(true); |
| configurationScrollArea.setExpandVertical(true); |
| |
| mConfigurationArea = new Composite(configurationScrollArea, SWT.NONE); |
| GridLayout glConfigurationArea = new GridLayout(3, false); |
| glConfigurationArea.horizontalSpacing = 0; |
| glConfigurationArea.marginRight = 15; |
| glConfigurationArea.marginWidth = 0; |
| glConfigurationArea.marginHeight = 0; |
| mConfigurationArea.setLayout(glConfigurationArea); |
| |
| 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(mConfigurationArea, SWT.NONE); |
| foregroundComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1)); |
| GridLayout glForegroundComposite = new GridLayout(5, false); |
| glForegroundComposite.horizontalSpacing = 0; |
| foregroundComposite.setLayout(glForegroundComposite); |
| |
| mImageRadio = new Button(foregroundComposite, SWT.FLAT | SWT.TOGGLE); |
| mImageRadio.setSelection(false); |
| mImageRadio.addSelectionListener(this); |
| mImageRadio.setText("Image"); |
| |
| mClipartRadio = new Button(foregroundComposite, SWT.FLAT | SWT.TOGGLE); |
| mClipartRadio.setText("Clipart"); |
| mClipartRadio.addSelectionListener(this); |
| |
| mTextRadio = new Button(foregroundComposite, SWT.FLAT | SWT.TOGGLE); |
| mTextRadio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1)); |
| mTextRadio.setText("Text"); |
| mTextRadio.addSelectionListener(this); |
| new Label(mConfigurationArea, SWT.NONE); |
| |
| mForegroundArea = new Composite(mConfigurationArea, SWT.NONE); |
| mForegroundArea.setLayout(new StackLayout()); |
| mForegroundArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); |
| |
| mImageForm = new Composite(mForegroundArea, SWT.NONE); |
| mImageForm.setLayout(new GridLayout(3, false)); |
| |
| Label fileLabel = new Label(mImageForm, SWT.NONE); |
| fileLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); |
| fileLabel.setText("Image File:"); |
| |
| mImagePathText = new Text(mImageForm, SWT.BORDER); |
| GridData pathLayoutData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); |
| pathLayoutData.widthHint = 200; |
| mImagePathText.setLayoutData(pathLayoutData); |
| mImagePathText.addSelectionListener(this); |
| mImagePathText.addModifyListener(this); |
| |
| mPickImageButton = new Button(mImageForm, SWT.FLAT); |
| mPickImageButton.setText("Browse..."); |
| mPickImageButton.addSelectionListener(this); |
| |
| mClipartForm = new Composite(mForegroundArea, SWT.NONE); |
| mClipartForm.setLayout(new GridLayout(2, false)); |
| |
| mChooseClipart = new Button(mClipartForm, SWT.FLAT); |
| mChooseClipart.setText("Choose..."); |
| mChooseClipart.addSelectionListener(this); |
| |
| mClipartPreviewPanel = new Composite(mClipartForm, SWT.NONE); |
| RowLayout rlClipartPreviewPanel = new RowLayout(SWT.HORIZONTAL); |
| rlClipartPreviewPanel.marginBottom = 0; |
| rlClipartPreviewPanel.marginTop = 0; |
| rlClipartPreviewPanel.center = true; |
| mClipartPreviewPanel.setLayout(rlClipartPreviewPanel); |
| mClipartPreviewPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); |
| |
| mTextForm = new Composite(mForegroundArea, SWT.NONE); |
| mTextForm.setLayout(new GridLayout(2, false)); |
| |
| Label textLabel = new Label(mTextForm, SWT.NONE); |
| textLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); |
| textLabel.setText("Text:"); |
| |
| mText = new Text(mTextForm, SWT.BORDER); |
| mText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); |
| mText.addModifyListener(this); |
| |
| Label fontLabel = new Label(mTextForm, SWT.NONE); |
| fontLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); |
| fontLabel.setText("Font:"); |
| |
| mFontButton = new Button(mTextForm, SWT.FLAT); |
| mFontButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); |
| mFontButton.addSelectionListener(this); |
| mFontButton.setText("Choose Font..."); |
| new Label(mConfigurationArea, SWT.NONE); |
| |
| mTrimCheckBox = new Button(mConfigurationArea, SWT.CHECK); |
| mTrimCheckBox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1)); |
| mTrimCheckBox.setSelection(false); |
| mTrimCheckBox.setText("Trim Surrounding Blank Space"); |
| mTrimCheckBox.addSelectionListener(this); |
| new Label(mConfigurationArea, 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(mConfigurationArea, SWT.NONE); |
| |
| mPaddingSlider = new Slider(mConfigurationArea, SWT.NONE); |
| mPaddingSlider.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); |
| // This doesn't work right -- not sure why. For now just use a plain slider |
| // and subtract 10 from it to get the real range. |
| //mPaddingSlider.setValues(0, -10, 50, 0, 1, 10); |
| //mPaddingSlider.setSelection(10 + 15); |
| mPaddingSlider.addSelectionListener(this); |
| |
| mPercentLabel = new Label(mConfigurationArea, SWT.NONE); |
| mPercentLabel.setText(" 15%"); // Enough available space for -10% |
| mScalingLabel = new Label(mConfigurationArea, SWT.NONE); |
| mScalingLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); |
| mScalingLabel.setText("Foreground Scaling:"); |
| |
| 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(mScalingComposite, SWT.FLAT | SWT.TOGGLE); |
| mCropRadio.setSelection(true); |
| mCropRadio.setText("Crop"); |
| mCropRadio.addSelectionListener(this); |
| |
| 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); |
| |
| mShapeLabel = new Label(mConfigurationArea, SWT.NONE); |
| mShapeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); |
| mShapeLabel.setText("Shape"); |
| |
| mShapeComposite = new Composite(mConfigurationArea, SWT.NONE); |
| mShapeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1)); |
| GridLayout gl_mShapeComposite = new GridLayout(6, false); |
| gl_mShapeComposite.horizontalSpacing = 0; |
| mShapeComposite.setLayout(gl_mShapeComposite); |
| |
| mNoShapeRadio = new Button(mShapeComposite, SWT.FLAT | SWT.TOGGLE); |
| mNoShapeRadio.setText("None"); |
| mNoShapeRadio.addSelectionListener(this); |
| |
| mSquareRadio = new Button(mShapeComposite, SWT.FLAT | SWT.TOGGLE); |
| mSquareRadio.setSelection(true); |
| mSquareRadio.setText("Square"); |
| mSquareRadio.addSelectionListener(this); |
| |
| 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); |
| |
| 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); |
| |
| 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); |
| |
| 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(mConfigurationArea, SWT.FLAT); |
| mFgButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1)); |
| mFgButton.setAlignment(SWT.CENTER); |
| mFgButton.addSelectionListener(this); |
| |
| configurationScrollArea.setContent(mConfigurationArea); |
| configurationScrollArea.setMinSize(mConfigurationArea.computeSize(SWT.DEFAULT, |
| SWT.DEFAULT)); |
| |
| Label previewLabel = new Label(container, SWT.NONE); |
| previewLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1)); |
| previewLabel.setText("Preview:"); |
| |
| mPreviewArea = new Composite(container, SWT.BORDER); |
| |
| RowLayout rlPreviewAreaPreviewArea = new RowLayout(SWT.HORIZONTAL); |
| rlPreviewAreaPreviewArea.wrap = true; |
| rlPreviewAreaPreviewArea.pack = true; |
| rlPreviewAreaPreviewArea.center = true; |
| rlPreviewAreaPreviewArea.spacing = 0; |
| rlPreviewAreaPreviewArea.marginBottom = 0; |
| rlPreviewAreaPreviewArea.marginTop = 0; |
| rlPreviewAreaPreviewArea.marginRight = 0; |
| rlPreviewAreaPreviewArea.marginLeft = 0; |
| mPreviewArea.setLayout(rlPreviewAreaPreviewArea); |
| GridData gdMPreviewArea = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1); |
| gdMPreviewArea.widthHint = PREVIEW_AREA_WIDTH; |
| mPreviewArea.setLayoutData(gdMPreviewArea); |
| |
| // Initial color |
| Display display = parent.getDisplay(); |
| updateColor(display, mValues.background, true /*background*/); |
| updateColor(display, mValues.foreground, false /*background*/); |
| |
| setSourceType(mValues.sourceType); |
| |
| new Label(mConfigurationArea, SWT.NONE); |
| new Label(mConfigurationArea, SWT.NONE); |
| new Label(mConfigurationArea, SWT.NONE); |
| |
| validatePage(); |
| } |
| |
| void configureAssetType(AssetType type) { |
| if (mValues.sourceType != mShowingType) { |
| mShowingType = mValues.sourceType; |
| showGroup(type.needsForegroundScaling(), mScalingLabel, mScalingComposite); |
| showGroup(type.needsShape(), mShapeLabel, mShapeComposite); |
| showGroup(type.needsTheme(), mThemeLabel, mThemeComposite); |
| showGroup(type.needsColors(), mBgColorLabel, mBgButton); |
| showGroup(type.needsColors() && mValues.sourceType != SourceType.IMAGE, |
| mFgColorLabel, mFgButton); |
| |
| 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); |
| |
| // We update the image selection here rather than in {@link #createControl} because |
| // 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) { |
| mShown = true; |
| |
| // 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 |
| AssetType type = mValues.type; |
| 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 (mValues.imagePath != null) { |
| sImagePath = mValues.imagePath.getPath(); |
| } |
| if (sImagePath == null) { |
| IProject project = mValues.project; |
| if (project != null) { |
| IResource icon = project.findMember("res/drawable-hdpi/icon.png"); //$NON-NLS-1$ |
| if (icon != null) { |
| IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot(); |
| IPath workspacePath = workspace.getLocation(); |
| sImagePath = workspacePath.append(icon.getFullPath()).toOSString(); |
| } |
| } |
| } |
| if (sImagePath != null) { |
| mValues.imagePath = new File(sImagePath); |
| mImagePathText.setText(sImagePath); |
| } |
| |
| try { |
| mIgnore = true; |
| |
| mTrimCheckBox.setSelection(mValues.trim); |
| |
| // This doesn't work right -- not sure why. For now just use a plain slider |
| // and subtract 10 from it to get the real range. |
| //mPaddingSlider.setValues(0, -10, 50, 0, 1, 10); |
| //mPaddingSlider.setSelection(10 + 15); |
| mPaddingSlider.setSelection(mValues.padding + 10); |
| mPercentLabel.setText(Integer.toString(mValues.padding) + '%'); |
| |
| if (mValues.imagePath != null) { |
| mImagePathText.setText(mValues.imagePath.getPath()); |
| } |
| |
| if (mValues.text != null) { |
| mText.setText(mValues.text); |
| } |
| |
| setSourceType(mValues.sourceType); |
| |
| // Shape=NONE does not apply for notification icons; it's needed for API < 9 |
| if (mValues.shape == Shape.NONE && mValues.type == AssetType.NOTIFICATION) { |
| mValues.shape = Shape.SQUARE; |
| } |
| |
| setShape(mValues.shape); |
| mNoShapeRadio.setEnabled(mValues.type != AssetType.NOTIFICATION); |
| |
| if (mValues.sourceType == SourceType.CLIPART |
| && mValues.clipartName != null) { |
| updateClipartPreview(); |
| } |
| |
| // Initial color |
| Display display = mPreviewArea.getDisplay(); |
| //updateColor(display, new RGB(0xa4, 0xc6, 0x39), true /*background*/); |
| updateColor(display, mValues.background, true /*background*/); |
| updateColor(display, mValues.foreground, false /*background*/); |
| |
| updateTrimOptions(); |
| } finally { |
| mIgnore = false; |
| } |
| |
| validatePage(); |
| |
| requestUpdatePreview(true /*quickly*/); |
| |
| if (mTextRadio.getSelection()) { |
| mText.setFocus(); |
| } |
| } |
| } |
| |
| private void setSourceType(CreateAssetSetWizardState.SourceType sourceType) { |
| if (sourceType == CreateAssetSetWizardState.SourceType.IMAGE) { |
| chooseForegroundTab(mImageRadio, mImageForm); |
| } else if (sourceType == CreateAssetSetWizardState.SourceType.CLIPART) { |
| chooseForegroundTab(mClipartRadio, mClipartForm); |
| mChooseClipart.setFocus(); |
| } else if (sourceType == CreateAssetSetWizardState.SourceType.TEXT) { |
| updateFontLabel(); |
| chooseForegroundTab(mTextRadio, mTextForm); |
| mText.setFocus(); |
| } |
| } |
| |
| private void updateTrimOptions() { |
| // Trimming and padding is not available for clipart images; padding etc is |
| // predefined to work well with action bar icons |
| if (mValues.sourceType == SourceType.CLIPART |
| && mValues.type == AssetType.ACTIONBAR) { |
| mTrimCheckBox.setEnabled(false); |
| mPaddingSlider.setEnabled(false); |
| mValues.trim = false; |
| } else if (!mTrimCheckBox.isEnabled()) { |
| mTrimCheckBox.setEnabled(true); |
| mPaddingSlider.setEnabled(true); |
| } |
| } |
| |
| private boolean validatePage() { |
| String error = null; |
| //String warning = null; |
| |
| if (mImageRadio.getSelection()) { |
| String path = mValues.imagePath != null ? mValues.imagePath.getPath() : null; |
| if (path == null || path.length() == 0) { |
| error = "Select an image"; |
| } else if (path.equals(DEFAULT_LAUNCHER_ICON)) { |
| // Silent |
| } else if (!(new File(path).exists())) { |
| error = String.format("%1$s does not exist", path); |
| } else { |
| // Preserve across wizard sessions |
| sImagePath = path; |
| } |
| } else if (mTextRadio.getSelection()) { |
| if (mValues.text.length() == 0) { |
| error = "Enter text"; |
| } |
| } else { |
| assert mClipartRadio.getSelection(); |
| if (mValues.clipartName == null) { |
| error = "Select clip art"; |
| } |
| } |
| |
| setPageComplete(error == null); |
| if (error != null) { |
| setMessage(error, IMessageProvider.ERROR); |
| //} else if (warning != null) { |
| // setMessage(warning, IMessageProvider.WARNING); |
| } else { |
| setErrorMessage(null); |
| setMessage(null); |
| } |
| |
| return error == null; |
| } |
| |
| @Override |
| public boolean isPageComplete() { |
| // Force user to reach second page before hitting Finish |
| return mShown; |
| } |
| |
| // ---- Implements ModifyListener ---- |
| |
| @Override |
| public void modifyText(ModifyEvent e) { |
| if (mIgnore) { |
| return; |
| } |
| |
| if (e.getSource() == mImagePathText) { |
| mValues.imagePath = new File(mImagePathText.getText().trim()); |
| requestUpdatePreview(false); |
| } else if (e.getSource() == mText) { |
| mValues.text = mText.getText().trim(); |
| requestUpdatePreview(false); |
| } |
| |
| validatePage(); |
| } |
| |
| // ---- Implements SelectionListener ---- |
| |
| @Override |
| public void widgetDefaultSelected(SelectionEvent e) { |
| // Nothing to do |
| } |
| |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (mIgnore) { |
| return; |
| } |
| |
| Object source = e.getSource(); |
| boolean updateQuickly = true; |
| |
| // Tabs |
| if (source == mImageRadio) { |
| mValues.sourceType = CreateAssetSetWizardState.SourceType.IMAGE; |
| chooseForegroundTab((Button) source, mImageForm); |
| configureAssetType(mValues.type); |
| updateTrimOptions(); |
| } else if (source == mClipartRadio) { |
| mValues.sourceType = CreateAssetSetWizardState.SourceType.CLIPART; |
| chooseForegroundTab((Button) source, mClipartForm); |
| configureAssetType(mValues.type); |
| updateTrimOptions(); |
| } else if (source == mTextRadio) { |
| mValues.sourceType = CreateAssetSetWizardState.SourceType.TEXT; |
| updateFontLabel(); |
| chooseForegroundTab((Button) source, mTextForm); |
| configureAssetType(mValues.type); |
| mText.setFocus(); |
| updateTrimOptions(); |
| } |
| |
| // Choose image file |
| if (source == mPickImageButton) { |
| FileDialog dialog = new FileDialog(mPickImageButton.getShell(), SWT.OPEN); |
| |
| String curLocation = mImagePathText.getText().trim(); |
| if (!curLocation.isEmpty()) { |
| dialog.setFilterPath(curLocation); |
| } |
| |
| String file = dialog.open(); |
| if (file != null) { |
| mValues.imagePath = new File(file); |
| mImagePathText.setText(file); |
| } |
| } |
| |
| // Enforce Radio Groups |
| if (source == mCropRadio) { |
| mCropRadio.setSelection(true); // Ensure that you can't toggle it off |
| mCenterRadio.setSelection(false); |
| mValues.crop = true; |
| } else if (source == mCenterRadio) { |
| mCenterRadio.setSelection(true); |
| mCropRadio.setSelection(false); |
| mValues.crop = false; |
| } |
| if (source == mSquareRadio) { |
| mValues.shape = GraphicGenerator.Shape.SQUARE; |
| setShape(mValues.shape); |
| } else if (source == mCircleButton) { |
| mValues.shape = GraphicGenerator.Shape.CIRCLE; |
| setShape(mValues.shape); |
| } else if (source == mNoShapeRadio) { |
| mValues.shape = GraphicGenerator.Shape.NONE; |
| setShape(mValues.shape); |
| } |
| |
| if (source == mTrimCheckBox) { |
| mValues.trim = mTrimCheckBox.getSelection(); |
| } |
| |
| if (source == mHoloDarkRadio) { |
| mHoloDarkRadio.setSelection(true); |
| mHoloLightRadio.setSelection(false); |
| mValues.holoDark = true; |
| } else if (source == mHoloLightRadio) { |
| mHoloLightRadio.setSelection(true); |
| mHoloDarkRadio.setSelection(false); |
| mValues.holoDark = false; |
| } |
| |
| if (source == mChooseClipart) { |
| MessageDialog dialog = new MessageDialog(mChooseClipart.getShell(), |
| "Choose Clip Art", |
| null, "Choose Clip Art Image:", MessageDialog.NONE, |
| new String[] { "Close" }, 0) { |
| @Override |
| protected Control createCustomArea(Composite parent) { |
| // Outer form which just establishes a width for the inner form which |
| // wraps in a RowLayout |
| Composite outer = new Composite(parent, SWT.NONE); |
| GridLayout gridLayout = new GridLayout(); |
| outer.setLayout(gridLayout); |
| |
| Composite chooserForm = new Composite(outer, SWT.NONE); |
| GridData gd = new GridData(); |
| gd.grabExcessVerticalSpace = true; |
| gd.widthHint = 450; |
| chooserForm.setLayoutData(gd); |
| RowLayout clipartFormLayout = new RowLayout(SWT.HORIZONTAL); |
| clipartFormLayout.center = true; |
| clipartFormLayout.wrap = true; |
| chooserForm.setLayout(clipartFormLayout); |
| |
| MouseAdapter clickListener = new MouseAdapter() { |
| @Override |
| public void mouseDown(MouseEvent event) { |
| // Clicked on some of the sample art |
| if (event.widget instanceof ImageControl) { |
| ImageControl image = (ImageControl) event.widget; |
| mValues.clipartName = (String) image.getData(); |
| close(); |
| |
| updateClipartPreview(); |
| updatePreview(); |
| } |
| } |
| }; |
| Display display = chooserForm.getDisplay(); |
| Color hoverColor = display.getSystemColor(SWT.COLOR_RED); |
| Iterator<String> clipartImages = GraphicGenerator.getClipartNames(); |
| while (clipartImages.hasNext()) { |
| String name = clipartImages.next(); |
| try { |
| BufferedImage icon = GraphicGenerator.getClipartIcon(name); |
| if (icon != null) { |
| Image swtImage = SwtUtils.convertToSwt(display, icon, true, -1); |
| ImageControl img = new ImageControl(chooserForm, |
| SWT.NONE, swtImage); |
| img.setData(name); |
| img.setHoverColor(hoverColor); |
| img.addMouseListener(clickListener); |
| } |
| } catch (IOException e1) { |
| AdtPlugin.log(e1, null); |
| } |
| } |
| outer.pack(); |
| outer.layout(); |
| return outer; |
| } |
| }; |
| dialog.open(); |
| } |
| |
| if (source == mBgButton) { |
| ColorDialog dlg = new ColorDialog(mBgButton.getShell()); |
| dlg.setRGB(mBgColor); |
| dlg.setText("Choose a new Background Color"); |
| RGB rgb = dlg.open(); |
| if (rgb != null) { |
| // Dispose the old color, create the |
| // new one, and set into the label |
| mValues.background = rgb; |
| updateColor(mBgButton.getDisplay(), rgb, true /*background*/); |
| } |
| } else if (source == mFgButton) { |
| ColorDialog dlg = new ColorDialog(mFgButton.getShell()); |
| dlg.setRGB(mFgColor); |
| dlg.setText("Choose a new Foreground Color"); |
| RGB rgb = dlg.open(); |
| if (rgb != null) { |
| // Dispose the old color, create the |
| // new one, and set into the label |
| mValues.foreground = rgb; |
| updateColor(mFgButton.getDisplay(), rgb, false /*background*/); |
| } |
| } |
| |
| if (source == mFontButton) { |
| FontDialog dialog = new FontDialog(mFontButton.getShell()); |
| FontData[] fontList; |
| if (mFontButton.getData() == null) { |
| fontList = mFontButton.getDisplay().getFontList( |
| mValues.getTextFont().getFontName(), 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); |
| mFontButton.setData(font); |
| |
| // 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; |
| FontData fontData = font.getFontData()[0]; |
| int awtStyle = java.awt.Font.PLAIN; |
| int swtStyle = fontData.getStyle(); |
| if ((swtStyle & SWT.ITALIC) != 0) { |
| awtStyle |= java.awt.Font.ITALIC; |
| } |
| if ((swtStyle & SWT.BOLD) != 0) { |
| awtStyle = java.awt.Font.BOLD; |
| } |
| mValues.setTextFont(new java.awt.Font(fontData.getName(), awtStyle, fontHeight)); |
| |
| updateFontLabel(); |
| mFontButton.getParent().pack(); |
| } |
| } |
| |
| if (source == mPaddingSlider) { |
| mValues.padding = getPadding(); |
| mPercentLabel.setText(Integer.toString(getPadding()) + '%'); |
| |
| // When dragging the slider, only do periodic updates |
| updateQuickly = false; |
| } |
| |
| requestUpdatePreview(updateQuickly); |
| } |
| |
| @SuppressWarnings("unused") // SWT constructors have side effects and are not unused |
| private void updateClipartPreview() { |
| for (Control c : mClipartPreviewPanel.getChildren()) { |
| c.dispose(); |
| } |
| if (mClipartPreviewPanel.getChildren().length == 0) { |
| try { |
| BufferedImage icon = GraphicGenerator.getClipartIcon( |
| mValues.clipartName); |
| if (icon != null) { |
| Display display = mClipartForm.getDisplay(); |
| Image swtImage = SwtUtils.convertToSwt(display, icon, |
| true, -1); |
| new ImageControl(mClipartPreviewPanel, |
| SWT.NONE, swtImage); |
| } |
| } catch (IOException e1) { |
| AdtPlugin.log(e1, null); |
| } |
| mClipartPreviewPanel.pack(); |
| mClipartPreviewPanel.layout(); |
| } |
| } |
| |
| private void setShape(GraphicGenerator.Shape shape) { |
| if (shape == GraphicGenerator.Shape.SQUARE) { |
| mSquareRadio.setSelection(true); |
| mCircleButton.setSelection(false); |
| mNoShapeRadio.setSelection(false); |
| } else if (shape == GraphicGenerator.Shape.CIRCLE) { |
| mCircleButton.setSelection(true); |
| mSquareRadio.setSelection(false); |
| mNoShapeRadio.setSelection(false); |
| } else if (shape == GraphicGenerator.Shape.NONE) { |
| mNoShapeRadio.setSelection(true); |
| mCircleButton.setSelection(false); |
| mSquareRadio.setSelection(false); |
| } else { |
| assert false : shape; |
| } |
| } |
| |
| private void updateFontLabel() { |
| mFontButton.setText(mValues.getTextFont().getFontName()); |
| } |
| |
| private int getPadding() { |
| // Shifted - see comment for mPaddingSlider construction for an explanation |
| return mPaddingSlider.getSelection() - 10; |
| } |
| |
| private void chooseForegroundTab(Button newButton, Composite newArea) { |
| if (newButton.getSelection()) { |
| mImageRadio.setSelection(false); |
| mClipartRadio.setSelection(false); |
| mTextRadio.setSelection(false); |
| newButton.setSelection(true); |
| 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); |
| } |
| } |
| |
| /** |
| * Delay updates of the preview, to ensure that the SWT UI acts immediately (to handle |
| * radio group selections etc). |
| * |
| * @param quickly if true, update the previews soon, otherwise schedule one a bit later |
| */ |
| private void requestUpdatePreview(boolean quickly) { |
| if (mTimerPending) { |
| return; |
| } |
| mTimerPending = true; |
| |
| final Runnable timer = new Runnable() { |
| @Override |
| public void run() { |
| mTimerPending = false; |
| updatePreview(); |
| } |
| }; |
| |
| mPreviewArea.getDisplay().timerExec(quickly ? 10 : 250, timer); |
| } |
| |
| private void updatePreview() { |
| Display display = mPreviewArea.getDisplay(); |
| |
| for (Control c : mPreviewArea.getChildren()) { |
| c.dispose(); |
| } |
| |
| if (!validatePage()) { |
| return; |
| } |
| |
| Map<String, Map<String, BufferedImage>> map = generateImages(mValues, |
| true /*previewOnly*/, this); |
| 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); |
| } |
| |
| /** |
| * Generate images using the given wizard state |
| * |
| * @param mValues the state to use |
| * @param previewOnly whether we are only generating previews |
| * @param page if non null, a wizard page to write error messages to |
| * @return a map of image objects |
| */ |
| public static Map<String, Map<String, BufferedImage>> generateImages( |
| @NonNull CreateAssetSetWizardState mValues, |
| boolean previewOnly, |
| @Nullable WizardPage page) { |
| // Map of ids to images: Preserve insertion order (the densities) |
| Map<String, Map<String, BufferedImage>> categoryMap = |
| new LinkedHashMap<String, Map<String, BufferedImage>>(); |
| |
| AssetType type = mValues.type; |
| boolean trim = mValues.trim; |
| |
| BufferedImage sourceImage = null; |
| switch (mValues.sourceType) { |
| case IMAGE: { |
| // Load the image |
| // TODO: Only do this when the source image type is image |
| String path = mValues.imagePath != null ? mValues.imagePath.getPath() : ""; |
| if (path.length() == 0) { |
| if (page != null) { |
| page.setErrorMessage("Enter a filename"); |
| } |
| return Collections.emptyMap(); |
| } |
| if (!path.equals(DEFAULT_LAUNCHER_ICON)) { |
| File file = new File(path); |
| if (!file.isFile()) { |
| if (page != null) { |
| page.setErrorMessage(String.format("%1$s does not exist", file.getPath())); |
| } |
| return Collections.emptyMap(); |
| } |
| } |
| |
| if (page != null) { |
| page.setErrorMessage(null); |
| } |
| try { |
| sourceImage = mValues.getCachedImage(path, false); |
| if (sourceImage != null) { |
| if (trim) { |
| sourceImage = ImageUtils.cropBlank(sourceImage, null, TYPE_INT_ARGB); |
| } |
| if (mValues.padding != 0) { |
| sourceImage = Util.paddedImage(sourceImage, mValues.padding); |
| } |
| } |
| } catch (IOException ioe) { |
| if (page != null) { |
| page.setErrorMessage(ioe.getLocalizedMessage()); |
| } |
| } |
| break; |
| } |
| case CLIPART: { |
| try { |
| sourceImage = GraphicGenerator.getClipartImage(mValues.clipartName); |
| |
| boolean isActionBar = mValues.type == AssetType.ACTIONBAR; |
| if (trim && !isActionBar) { |
| sourceImage = ImageUtils.cropBlank(sourceImage, null, TYPE_INT_ARGB); |
| } |
| |
| if (type.needsColors()) { |
| RGB fg = mValues.foreground; |
| int color = 0xFF000000 | (fg.red << 16) | (fg.green << 8) | fg.blue; |
| Paint paint = new java.awt.Color(color); |
| sourceImage = Util.filledImage(sourceImage, paint); |
| } |
| |
| int padding = mValues.padding; |
| if (padding != 0 && !isActionBar) { |
| sourceImage = Util.paddedImage(sourceImage, padding); |
| } |
| } catch (IOException e) { |
| AdtPlugin.log(e, null); |
| return categoryMap; |
| } |
| break; |
| } |
| case TEXT: { |
| String text = mValues.text; |
| TextRenderUtil.Options options = new TextRenderUtil.Options(); |
| options.font = mValues.getTextFont(); |
| int color; |
| if (type.needsColors()) { |
| RGB fg = mValues.foreground; |
| color = 0xFF000000 | (fg.red << 16) | (fg.green << 8) | fg.blue; |
| } else { |
| color = 0xFFFFFFFF; |
| } |
| options.foregroundColor = color; |
| sourceImage = TextRenderUtil.renderTextImage(text, mValues.padding, options); |
| |
| if (trim) { |
| sourceImage = ImageUtils.cropBlank(sourceImage, null, TYPE_INT_ARGB); |
| } |
| |
| int padding = mValues.padding; |
| if (padding != 0) { |
| sourceImage = Util.paddedImage(sourceImage, padding); |
| } |
| break; |
| } |
| } |
| |
| GraphicGenerator generator = null; |
| GraphicGenerator.Options options = null; |
| switch (type) { |
| case LAUNCHER: { |
| generator = new LauncherIconGenerator(); |
| LauncherIconGenerator.LauncherOptions launcherOptions = |
| new LauncherIconGenerator.LauncherOptions(); |
| launcherOptions.shape = mValues.shape; |
| launcherOptions.crop = mValues.crop; |
| launcherOptions.style = GraphicGenerator.Style.SIMPLE; |
| |
| RGB bg = mValues.background; |
| int color = (bg.red << 16) | (bg.green << 8) | bg.blue; |
| launcherOptions.backgroundColor = color; |
| // Flag which tells the generator iterator to include a web graphic |
| launcherOptions.isWebGraphic = !previewOnly; |
| options = launcherOptions; |
| |
| break; |
| } |
| case MENU: |
| generator = new MenuIconGenerator(); |
| options = new GraphicGenerator.Options(); |
| break; |
| case ACTIONBAR: { |
| generator = new ActionBarIconGenerator(); |
| ActionBarIconGenerator.ActionBarOptions actionBarOptions = |
| new ActionBarIconGenerator.ActionBarOptions(); |
| actionBarOptions.theme = mValues.holoDark |
| ? ActionBarIconGenerator.Theme.HOLO_DARK |
| : ActionBarIconGenerator.Theme.HOLO_LIGHT; |
| actionBarOptions.sourceIsClipart = (mValues.sourceType == SourceType.CLIPART); |
| |
| options = actionBarOptions; |
| break; |
| } |
| case NOTIFICATION: { |
| generator = new NotificationIconGenerator(); |
| options = new NotificationIconGenerator.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; |
| } |
| |
| options.sourceImage = sourceImage; |
| |
| IProject project = mValues.project; |
| if (mValues.minSdk != -1) { |
| options.minSdk = mValues.minSdk; |
| } else { |
| Pair<Integer, Integer> v = ManifestInfo.computeSdkVersions(project); |
| options.minSdk = v.getFirst(); |
| } |
| |
| String baseName = mValues.outputName; |
| generator.generate(null, categoryMap, mValues, options, baseName); |
| |
| return categoryMap; |
| } |
| |
| /** |
| * Generate custom icons into the project based on the asset studio wizard |
| * state |
| * |
| * @param newProject the project to write into |
| * @param values the wizard state to read configuration settings from |
| * @param previewOnly whether we are only generating a preview. For example, |
| * the launcher icons won't generate a huge 512x512 web graphic |
| * in preview mode |
| * @param page a wizard page to write error messages to, or null |
| */ |
| public static void generateIcons(final IProject newProject, |
| @NonNull CreateAssetSetWizardState values, |
| boolean previewOnly, |
| @Nullable WizardPage page) { |
| // Generate the custom icons |
| Map<String, Map<String, BufferedImage>> categories = generateImages(values, |
| false /*previewOnly*/, page); |
| 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 = newProject.getFile(dest); |
| |
| // In case template already created icons (should remove that) |
| // remove them first |
| if (file.exists()) { |
| try { |
| file.delete(true, new NullProgressMonitor()); |
| } catch (CoreException e) { |
| AdtPlugin.log(e, null); |
| } |
| } |
| AdtUtils.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*/); |
| } 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); |
| } |
| } |
| } |
| } |
| |
| private void updateColor(Display display, RGB color, boolean isBackground) { |
| // Button.setBackgroundColor does not work (at least not on OSX) so |
| // we instead have to use Button.setImage with an image of the given |
| // color |
| BufferedImage coloredImage = ImageUtils.createColoredImage(60, 20, color); |
| Image image = SwtUtils.convertToSwt(display, coloredImage, false, -1); |
| |
| if (isBackground) { |
| mBgColor = color; |
| mBgButton.setImage(image); |
| } else { |
| mFgColor = color; |
| mFgButton.setImage(image); |
| } |
| } |
| } |