| /* |
| * 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 com.android.ide.eclipse.adt.AdtConstants; |
| import com.android.ide.eclipse.adt.AdtPlugin; |
| import com.android.ide.eclipse.adt.AdtUtils; |
| import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; |
| import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; |
| import com.android.utils.Pair; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.ui.JavaUI; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.viewers.ISelectionProvider; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.TreePath; |
| import org.eclipse.jface.viewers.TreeSelection; |
| import org.eclipse.jface.wizard.Wizard; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.INewWizard; |
| import org.eclipse.ui.IViewPart; |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPartSite; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.part.FileEditorInput; |
| |
| import java.awt.image.BufferedImage; |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.imageio.ImageIO; |
| |
| /** |
| * Wizard for creating a new icon set |
| */ |
| public class CreateAssetSetWizard extends Wizard implements INewWizard { |
| private ChooseAssetTypePage mChooseAssetPage; |
| private ConfigureAssetSetPage mConfigureAssetPage; |
| private IProject mInitialProject; |
| private List<IResource> mCreatedFiles; |
| private CreateAssetSetWizardState mValues = new CreateAssetSetWizardState(); |
| |
| /** Creates a new asset set wizard */ |
| public CreateAssetSetWizard() { |
| setWindowTitle("Create Asset Set"); |
| } |
| |
| @Override |
| public void addPages() { |
| mValues.project = mInitialProject; |
| |
| mChooseAssetPage = new ChooseAssetTypePage(mValues); |
| mConfigureAssetPage = new ConfigureAssetSetPage(mValues); |
| |
| addPage(mChooseAssetPage); |
| addPage(mConfigureAssetPage); |
| } |
| |
| @Override |
| public boolean performFinish() { |
| Map<String, Map<String, BufferedImage>> categories = |
| ConfigureAssetSetPage.generateImages(mValues, false, null); |
| |
| IProject project = mValues.project; |
| |
| // Write out the images into the project |
| boolean yesToAll = false; |
| mCreatedFiles = new ArrayList<IResource>(); |
| |
| for (Map<String, BufferedImage> previews : categories.values()) { |
| for (Map.Entry<String, BufferedImage> entry : previews.entrySet()) { |
| String relativePath = entry.getKey(); |
| IPath dest = new Path(relativePath); |
| IFile file = project.getFile(dest); |
| if (file.exists()) { |
| // Warn that the file already exists and ask the user what to do |
| if (!yesToAll) { |
| MessageDialog dialog = new MessageDialog(null, "File Already Exists", null, |
| String.format( |
| "%1$s already exists.\nWould you like to replace it?", |
| file.getProjectRelativePath().toOSString()), |
| MessageDialog.QUESTION, new String[] { |
| // Yes will be moved to the end because it's the default |
| "Yes", "No", "Cancel", "Yes to All" |
| }, 0); |
| int result = dialog.open(); |
| switch (result) { |
| case 0: |
| // Yes |
| break; |
| case 3: |
| // Yes to all |
| yesToAll = true; |
| break; |
| case 1: |
| // No |
| continue; |
| case SWT.DEFAULT: |
| case 2: |
| // Cancel |
| return false; |
| } |
| } |
| |
| try { |
| file.delete(true, new NullProgressMonitor()); |
| } catch (CoreException e) { |
| AdtPlugin.log(e, null); |
| } |
| } |
| |
| 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*/); |
| mCreatedFiles.add(file); |
| } catch (IOException e) { |
| AdtPlugin.log(e, null); |
| } catch (CoreException e) { |
| AdtPlugin.log(e, null); |
| } |
| |
| try { |
| file.getParent().refreshLocal(1, new NullProgressMonitor()); |
| } catch (CoreException e) { |
| AdtPlugin.log(e, null); |
| } |
| } |
| } |
| |
| // Finally select the files themselves |
| selectFiles(project, mCreatedFiles); |
| |
| return true; |
| } |
| |
| private void selectFiles(IProject project, List<? extends IResource> createdFiles) { |
| // Attempt to select the newly created files in the Package Explorer |
| IWorkbench workbench = AdtPlugin.getDefault().getWorkbench(); |
| IWorkbenchPage page = workbench.getActiveWorkbenchWindow().getActivePage(); |
| IViewPart viewPart = page.findView(JavaUI.ID_PACKAGES); |
| if (viewPart != null) { |
| IWorkbenchPartSite site = viewPart.getSite(); |
| IJavaProject javaProject = null; |
| try { |
| javaProject = BaseProjectHelper.getJavaProject(project); |
| } catch (CoreException e) { |
| AdtPlugin.log(e, null); |
| } |
| final ISelectionProvider provider = site.getSelectionProvider(); |
| if (provider != null) { |
| List<TreePath> pathList = new ArrayList<TreePath>(); |
| for (IResource file : createdFiles) { |
| // Create a TreePath for the given file, |
| // which should be the JavaProject, followed by the folders down to |
| // the final file. |
| List<Object> segments = new ArrayList<Object>(); |
| segments.add(file); |
| IContainer folder = file.getParent(); |
| if (folder != null && !(folder instanceof IProject)) { |
| segments.add(folder); |
| // res folder |
| folder = folder.getParent(); |
| if (folder != null && !(folder instanceof IProject)) { |
| segments.add(folder); |
| } |
| } |
| // project |
| segments.add(javaProject); |
| |
| Collections.reverse(segments); |
| TreePath path = new TreePath(segments.toArray()); |
| pathList.add(path); |
| |
| // IDEA: Maybe normalize the files backwards (IFile objects aren't unique) |
| // by maybe using the package explorer icons instead |
| } |
| |
| TreePath[] paths = pathList.toArray(new TreePath[pathList.size()]); |
| final TreeSelection selection = new TreeSelection(paths); |
| |
| provider.setSelection(selection); |
| |
| // Workaround: The above doesn't always work; it will frequently select |
| // some siblings of the real files. I've tried a number of workarounds: |
| // normalizing the IFile objects by looking up the canonical ones via |
| // their relative paths from the project; deferring execution with |
| // Display.asyncRun; first calling select on the parents, etc. |
| // However, it turns out a simple workaround works best: Calling this |
| // method TWICE. The first call seems to expand all the necessary parents, |
| // and the second call ensures that the correct children are selected! |
| provider.setSelection(selection); |
| |
| viewPart.setFocus(); |
| } |
| } |
| } |
| |
| /** Sets the initial project to be used by the wizard */ |
| void setProject(IProject project) { |
| mInitialProject = project; |
| mValues.project = project; |
| } |
| |
| @Override |
| public void init(IWorkbench workbench, IStructuredSelection selection) { |
| setHelpAvailable(false); |
| |
| mInitialProject = guessProject(selection); |
| mValues.project = mInitialProject; |
| } |
| |
| private IProject guessProject(IStructuredSelection selection) { |
| if (selection == null) { |
| return null; |
| } |
| |
| for (Object element : selection.toList()) { |
| if (element instanceof IAdaptable) { |
| IResource res = (IResource) ((IAdaptable) element).getAdapter(IResource.class); |
| IProject project = res != null ? res.getProject() : null; |
| |
| // Is this an Android project? |
| try { |
| if (project == null || !project.hasNature(AdtConstants.NATURE_DEFAULT)) { |
| continue; |
| } |
| } catch (CoreException e) { |
| // checking the nature failed, ignore this resource |
| continue; |
| } |
| |
| return project; |
| } else if (element instanceof Pair<?, ?>) { |
| // Pair of Project/String |
| @SuppressWarnings("unchecked") |
| Pair<IProject, String> pair = (Pair<IProject, String>) element; |
| return pair.getFirst(); |
| } |
| } |
| |
| // Try to figure out the project from the active editor |
| IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| if (window != null) { |
| IWorkbenchPage page = window.getActivePage(); |
| if (page != null) { |
| IEditorPart activeEditor = page.getActiveEditor(); |
| if (activeEditor instanceof AndroidXmlEditor) { |
| Object input = ((AndroidXmlEditor) activeEditor).getEditorInput(); |
| if (input instanceof FileEditorInput) { |
| FileEditorInput fileInput = (FileEditorInput) input; |
| return fileInput.getFile().getProject(); |
| } |
| } |
| } |
| } |
| |
| IJavaProject[] projects = AdtUtils.getOpenAndroidProjects(); |
| if (projects != null && projects.length == 1) { |
| return projects[0].getProject(); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the list of files created by the wizard. This method will return |
| * null if {@link #performFinish()} has not yet been called. |
| * |
| * @return a list of files created by the wizard, or null |
| */ |
| List<IResource> getCreatedFiles() { |
| return mCreatedFiles; |
| } |
| } |