blob: deac54c4026583092b7f22e320535ea1ee7ecc97 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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.tools.idea.npw;
import com.android.builder.model.SourceProvider;
import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import com.android.tools.idea.templates.Parameter;
import com.android.tools.idea.templates.TemplateMetadata;
import com.android.tools.idea.ui.ImageComponent;
import com.android.tools.idea.wizard.template.TemplateWizardState;
import com.android.tools.idea.wizard.template.TemplateWizardStep;
import com.google.common.collect.Iterators;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.IdeaSourceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.android.tools.idea.npw.AssetStudioAssetGenerator.*;
/**
* This is the common asset set step for both PNG files and SVG files.
*/
abstract public class CommonAssetSetStep extends TemplateWizardStep implements Disposable {
private static final Logger LOG = Logger.getInstance(CommonAssetSetStep.class);
protected SourceProvider mySourceProvider = null;
protected AssetStudioAssetGenerator myAssetGenerator;
protected AssetType mySelectedAssetType;
protected boolean myInitialized;
protected final MergingUpdateQueue myUpdateQueue;
protected final Map<String, Map<String, BufferedImage>> myImageMap = new ConcurrentHashMap<String, Map<String, BufferedImage>>();
@SuppressWarnings("UseJBColor") // Colors are used for the graphics generator, not the plugin UI
public CommonAssetSetStep(TemplateWizardState state,
@Nullable Project project,
@Nullable Module module,
@Nullable Icon sidePanelIcon,
UpdateListener updateListener,
@Nullable VirtualFile invocationTarget) {
super(state, project, module, sidePanelIcon, updateListener);
myAssetGenerator = new AssetStudioAssetGenerator(state);
if (invocationTarget != null && module != null) {
AndroidFacet facet = AndroidFacet.getInstance(myModule);
if (facet != null) {
mySourceProvider = Iterators.getNext(IdeaSourceProvider.getSourceProvidersForFile(facet, invocationTarget, null).iterator(), null);
}
}
myUpdateQueue = new MergingUpdateQueue("asset.studio", 200, true, null, this, null, false);
}
@Override
public boolean validate() {
if (!super.validate()) {
return false;
}
String assetName = myTemplateState.getString(ATTR_ASSET_NAME);
if (drawableExists(assetName)) {
setErrorHtml(String.format("A drawable resource named %s already exists and will be overwritten.", assetName));
}
requestPreviewUpdate();
return isValid();
}
/**
* (Re)schedule the background task which updates the preview images.
*/
private void requestPreviewUpdate() {
myUpdateQueue.cancelAllUpdates();
myUpdateQueue.queue(new Update("update") {
@Override
public void run() {
try {
myAssetGenerator.generateImages(myImageMap, true, true);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
updatePreviewImages();
}
});
}
catch (final ImageGeneratorException e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
setErrorHtml(e.getMessage());
}
});
}
}
});
}
abstract protected void updatePreviewImages();
protected static void setIconOrClear(@NotNull ImageComponent component, @Nullable BufferedImage image) {
if (image == null) {
component.setIcon(null);
} else {
component.setIcon(new ImageIcon(image));
}
}
@Override
public void updateStep() {
super.updateStep();
if (!myInitialized) {
myInitialized = true;
initialize();
}
}
abstract protected void initialize();
@NotNull
abstract protected String computeResourceName();
/**
* Must be run inside a write action. Creates the asset files on disk.
*/
public void createAssets(@Nullable Module module) {
File targetResDir = (File)myTemplateState.get(ChooseOutputResDirStep.ATTR_OUTPUT_FOLDER);
if (targetResDir == null) {
if (myTemplateState.hasAttr(TemplateMetadata.ATTR_RES_DIR)) {
assert module != null;
File moduleDir = new File(module.getModuleFilePath()).getParentFile();
targetResDir = new File(moduleDir, myTemplateState.getString(TemplateMetadata.ATTR_RES_DIR));
} else {
return;
}
}
generateAssetFiles(targetResDir);
VirtualFile resDir = LocalFileSystem.getInstance().findFileByIoFile(targetResDir);
if (resDir != null) {
// Refresh the res directory so that the new files show up in the IDE.
resDir.refresh(true, true);
} else {
// If we can't find the res directory, refresh the project.
if (myProject != null) {
myProject.getBaseDir().refresh(true, true);
}
}
}
abstract protected void generateAssetFiles(File targetResDir);
protected boolean drawableExists(String resourceName) {
if (mySourceProvider != null) {
return Parameter.existsResourceFile(mySourceProvider, myModule, ResourceFolderType.DRAWABLE, ResourceType.DRAWABLE, resourceName);
}
return Parameter.existsResourceFile(myModule, ResourceType.DRAWABLE, resourceName);
}
@Override
public void dispose() {
myUpdateQueue.cancelAllUpdates();
}
}