blob: 5deea9c75f742952e2546fe93b7dca7afd78eb05 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* 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.intellij.openapi.roots.ui.configuration.artifacts;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.impl.libraries.LibraryTableImplUtil;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditorListener;
import com.intellij.openapi.roots.ui.configuration.projectRoot.*;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.ui.MasterDetailsState;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.packaging.artifacts.*;
import com.intellij.packaging.impl.artifacts.ArtifactUtil;
import com.intellij.packaging.impl.artifacts.InvalidArtifact;
import com.intellij.packaging.impl.artifacts.PackagingElementPath;
import com.intellij.packaging.impl.artifacts.PackagingElementProcessor;
import com.intellij.packaging.impl.elements.LibraryElementType;
import com.intellij.packaging.impl.elements.LibraryPackagingElement;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author nik
*/
public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
private ArtifactsStructureConfigurableContextImpl myPackagingEditorContext;
private final ArtifactEditorSettings myDefaultSettings = new ArtifactEditorSettings();
public ArtifactsStructureConfigurable(@NotNull Project project) {
super(project, new ArtifactStructureConfigurableState());
}
@Override
protected String getComponentStateKey() {
return "ArtifactsStructureConfigurable.UI";
}
public void init(StructureConfigurableContext context, ModuleStructureConfigurable moduleStructureConfigurable,
ProjectLibrariesConfigurable projectLibrariesConfig, GlobalLibrariesConfigurable globalLibrariesConfig) {
super.init(context);
myPackagingEditorContext = new ArtifactsStructureConfigurableContextImpl(myContext, myProject, myDefaultSettings, new ArtifactAdapter() {
@Override
public void artifactAdded(@NotNull Artifact artifact) {
final MyNode node = addArtifactNode(artifact);
selectNodeInTree(node);
myContext.getDaemonAnalyzer().queueUpdate(myPackagingEditorContext.getOrCreateArtifactElement(artifact));
}
});
context.getModulesConfigurator().addAllModuleChangeListener(new ModuleEditor.ChangeListener() {
@Override
public void moduleStateChanged(ModifiableRootModel moduleRootModel) {
for (ProjectStructureElement element : getProjectStructureElements()) {
myContext.getDaemonAnalyzer().queueUpdate(element);
}
}
});
final ItemsChangeListener listener = new ItemsChangeListener() {
@Override
public void itemChanged(@Nullable Object deletedItem) {
if (deletedItem instanceof Library || deletedItem instanceof Module) {
onElementDeleted();
}
}
@Override
public void itemsExternallyChanged() {
}
};
moduleStructureConfigurable.addItemsChangeListener(listener);
projectLibrariesConfig.addItemsChangeListener(listener);
globalLibrariesConfig.addItemsChangeListener(listener);
context.addLibraryEditorListener(new LibraryEditorListener() {
@Override
public void libraryRenamed(@NotNull Library library, String oldName, String newName) {
final Artifact[] artifacts = myPackagingEditorContext.getArtifactModel().getArtifacts();
for (Artifact artifact : artifacts) {
updateLibraryElements(artifact, library, oldName, newName);
}
}
});
}
private void updateLibraryElements(final Artifact artifact, final Library library, final String oldName, final String newName) {
if (ArtifactUtil.processPackagingElements(myPackagingEditorContext.getRootElement(artifact), LibraryElementType.LIBRARY_ELEMENT_TYPE,
new PackagingElementProcessor<LibraryPackagingElement>() {
@Override
public boolean process(@NotNull LibraryPackagingElement element,
@NotNull PackagingElementPath path) {
return !isResolvedToLibrary(element, library, oldName);
}
}, myPackagingEditorContext, false, artifact.getArtifactType())) {
return;
}
myPackagingEditorContext.editLayout(artifact, new Runnable() {
@Override
public void run() {
final ModifiableArtifact modifiableArtifact = myPackagingEditorContext.getOrCreateModifiableArtifactModel().getOrCreateModifiableArtifact(artifact);
ArtifactUtil.processPackagingElements(modifiableArtifact, LibraryElementType.LIBRARY_ELEMENT_TYPE, new PackagingElementProcessor<LibraryPackagingElement>() {
@Override
public boolean process(@NotNull LibraryPackagingElement element, @NotNull PackagingElementPath path) {
if (isResolvedToLibrary(element, library, oldName)) {
element.setLibraryName(newName);
}
return true;
}
}, myPackagingEditorContext, false);
}
});
final ArtifactEditorImpl artifactEditor = myPackagingEditorContext.getArtifactEditor(artifact);
if (artifactEditor != null) {
artifactEditor.rebuildTries();
}
}
private static boolean isResolvedToLibrary(LibraryPackagingElement element, Library library, String name) {
if (!element.getLibraryName().equals(name)) {
return false;
}
final LibraryTable table = library.getTable();
if (table != null) {
return table.getTableLevel().equals(element.getLevel());
}
return element.getLevel().equals(LibraryTableImplUtil.MODULE_LEVEL);
}
private void onElementDeleted() {
for (ArtifactEditorImpl editor : myPackagingEditorContext.getArtifactEditors()) {
editor.getSourceItemsTree().rebuildTree();
editor.queueValidation();
}
}
@Override
protected MasterDetailsState getState() {
((ArtifactStructureConfigurableState)myState).setDefaultArtifactSettings(myDefaultSettings.getState());
return super.getState();
}
@Override
public void loadState(MasterDetailsState object) {
super.loadState(object);
myDefaultSettings.loadState(((ArtifactStructureConfigurableState)myState).getDefaultArtifactSettings());
}
@Override
@Nls
public String getDisplayName() {
return ProjectBundle.message("display.name.artifacts");
}
@Override
protected void loadTree() {
myTree.setRootVisible(false);
myTree.setShowsRootHandles(false);
for (Artifact artifact : myPackagingEditorContext.getArtifactModel().getAllArtifactsIncludingInvalid()) {
addArtifactNode(artifact);
}
}
@NotNull
@Override
protected Collection<? extends ProjectStructureElement> getProjectStructureElements() {
final List<ProjectStructureElement> elements = new ArrayList<ProjectStructureElement>();
for (Artifact artifact : myPackagingEditorContext.getArtifactModel().getAllArtifactsIncludingInvalid()) {
elements.add(myPackagingEditorContext.getOrCreateArtifactElement(artifact));
}
return elements;
}
private MyNode addArtifactNode(final Artifact artifact) {
final NamedConfigurable<Artifact> configurable;
if (artifact instanceof InvalidArtifact) {
configurable = new InvalidArtifactConfigurable((InvalidArtifact)artifact, myPackagingEditorContext, TREE_UPDATER);
}
else {
configurable = new ArtifactConfigurable(artifact, myPackagingEditorContext, TREE_UPDATER);
}
final MyNode node = new MyNode(configurable);
addNode(node, myRoot);
return node;
}
@Override
public void reset() {
loadComponentState();
myPackagingEditorContext.resetModifiableModel();
super.reset();
}
@Override
public boolean isModified() {
final ModifiableArtifactModel modifiableModel = myPackagingEditorContext.getActualModifiableModel();
if (modifiableModel != null && modifiableModel.isModified()) {
return true;
}
return myPackagingEditorContext.getManifestFilesInfo().isManifestFilesModified() || super.isModified();
}
public ArtifactsStructureConfigurableContext getArtifactsStructureContext() {
return myPackagingEditorContext;
}
public ModifiableArtifactModel getModifiableArtifactModel() {
return myPackagingEditorContext.getOrCreateModifiableArtifactModel();
}
@Override
protected AbstractAddGroup createAddAction() {
return new AbstractAddGroup(ProjectBundle.message("add.new.header.text")) {
@NotNull
@Override
public AnAction[] getChildren(@Nullable AnActionEvent e) {
final ArtifactType[] types = ArtifactType.getAllTypes();
final AnAction[] actions = new AnAction[types.length];
for (int i = 0; i < types.length; i++) {
actions[i] = createAddArtifactAction(types[i]);
}
return actions;
}
};
}
private AnAction createAddArtifactAction(@NotNull final ArtifactType type) {
final List<? extends ArtifactTemplate> templates = type.getNewArtifactTemplates(myPackagingEditorContext);
final ArtifactTemplate emptyTemplate = new ArtifactTemplate() {
@Override
public String getPresentableName() {
return "Empty";
}
@Override
public NewArtifactConfiguration createArtifact() {
final String name = "unnamed";
return new NewArtifactConfiguration(type.createRootElement(name), name, type);
}
};
if (templates.isEmpty()) {
return new AddArtifactAction(type, emptyTemplate, type.getPresentableName(), type.getIcon());
}
final DefaultActionGroup group = new DefaultActionGroup(type.getPresentableName(), true);
group.getTemplatePresentation().setIcon(type.getIcon());
group.add(new AddArtifactAction(type, emptyTemplate, emptyTemplate.getPresentableName(), null));
group.addSeparator();
for (ArtifactTemplate template : templates) {
group.add(new AddArtifactAction(type, template, template.getPresentableName(), null));
}
return group;
}
private void addArtifact(@NotNull ArtifactType type, @NotNull ArtifactTemplate artifactTemplate) {
Artifact artifact = ArtifactUtil.addArtifact(myPackagingEditorContext.getOrCreateModifiableArtifactModel(), type, artifactTemplate);
selectNodeInTree(findNodeByObject(myRoot, artifact));
}
@Override
public void apply() throws ConfigurationException {
myPackagingEditorContext.saveEditorSettings();
super.apply();
myPackagingEditorContext.getManifestFilesInfo().saveManifestFiles();
final ModifiableArtifactModel modifiableModel = myPackagingEditorContext.getActualModifiableModel();
if (modifiableModel != null) {
new WriteAction() {
@Override
protected void run(final Result result) {
modifiableModel.commit();
}
}.execute();
myPackagingEditorContext.resetModifiableModel();
}
reset(); // TODO: fix to not reset on apply!
}
@Override
public void disposeUIResources() {
myPackagingEditorContext.saveEditorSettings();
super.disposeUIResources();
myPackagingEditorContext.disposeUIResources();
}
@Override
public String getHelpTopic() {
final String topic = super.getHelpTopic();
return topic != null ? topic : "reference.settingsdialog.project.structure.artifacts";
}
@Override
protected void removeArtifact(Artifact artifact) {
myPackagingEditorContext.getOrCreateModifiableArtifactModel().removeArtifact(artifact);
myContext.getDaemonAnalyzer().removeElement(myPackagingEditorContext.getOrCreateArtifactElement(artifact));
}
@Override
protected void processRemovedItems() {
}
@Override
protected boolean wasObjectStored(Object editableObject) {
return false;
}
@Override
@NotNull
public String getId() {
return "project.artifacts";
}
@Override
public Runnable enableSearch(String option) {
return null;
}
@Override
public void dispose() {
}
private class AddArtifactAction extends DumbAwareAction {
private final ArtifactType myType;
private final ArtifactTemplate myArtifactTemplate;
public AddArtifactAction(@NotNull ArtifactType type, @NotNull ArtifactTemplate artifactTemplate, final @NotNull String actionText,
final Icon icon) {
super(actionText, null, icon);
myType = type;
myArtifactTemplate = artifactTemplate;
}
@Override
public void actionPerformed(AnActionEvent e) {
addArtifact(myType, myArtifactTemplate);
}
}
}