blob: 6b10012535def0ff1c5194b45292d95824eedf31 [file] [log] [blame]
/*
* 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;
}
}