| /* |
| * 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); |
| } |
| } |
| } |