package com.intellij.lang.javascript.flex.projectStructure;
import com.intellij.lang.javascript.flex.FlexBundle;
import com.intellij.lang.javascript.flex.FlexModuleType;
import com.intellij.lang.javascript.flex.library.FlexLibraryType;
import com.intellij.lang.javascript.flex.projectStructure.model.Dependencies;
import com.intellij.lang.javascript.flex.projectStructure.model.DependencyEntry;
import com.intellij.lang.javascript.flex.projectStructure.model.ModifiableFlexBuildConfiguration;
import com.intellij.lang.javascript.flex.projectStructure.model.ModuleLibraryEntry;
import com.intellij.lang.javascript.flex.projectStructure.options.FlexProjectRootsUtil;
import com.intellij.lang.javascript.flex.projectStructure.ui.CompositeConfigurable;
import com.intellij.lang.javascript.flex.projectStructure.ui.DependenciesConfigurable;
import com.intellij.lang.javascript.flex.projectStructure.ui.FlexBCConfigurable;
import com.intellij.lang.javascript.flex.projectStructure.ui.FlexProjectStructureUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureExtension;
import com.intellij.openapi.roots.ui.configuration.projectRoot.RemoveConfigurableHandler;
import com.intellij.openapi.ui.MasterDetailsComponent;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.ui.navigation.Place;
import icons.FlexIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.TreeNode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class FlexBuildConfigurationsExtension extends ModuleStructureExtension {
final FlexBCConfigurator myConfigurator;
public FlexBuildConfigurationsExtension() {
myConfigurator = new FlexBCConfigurator();
}
public static FlexBuildConfigurationsExtension getInstance() {
return ModuleStructureExtension.EP_NAME.findExtension(FlexBuildConfigurationsExtension.class);
}
public FlexBCConfigurator getConfigurator() {
return myConfigurator;
}
public void reset(Project project) {
myConfigurator.reset(project);
}
public boolean addModuleNodeChildren(final Module module,
final MasterDetailsComponent.MyNode moduleNode,
final Runnable treeNodeNameUpdater) {
if (!(ModuleType.get(module) instanceof FlexModuleType)) {
return false;
}
final List<CompositeConfigurable> configurables = myConfigurator.getOrCreateConfigurables(module, treeNodeNameUpdater);
for (final CompositeConfigurable configurable : configurables) {
if (MasterDetailsComponent.findNodeByObject(moduleNode, configurable.getEditableObject()) == null) {
moduleNode.add(new BuildConfigurationNode(configurable));
}
}
return configurables.size() > 0;
}
public void moduleRemoved(final Module module) {
myConfigurator.moduleRemoved(module);
}
public boolean isModified() {
return myConfigurator.isModified();
}
public void apply() throws ConfigurationException {
myConfigurator.apply();
}
@Override
public void afterModelCommit() {
myConfigurator.afterModelCommit();
}
public void disposeUIResources() {
myConfigurator.dispose();
}
@Override
public List<RemoveConfigurableHandler<?>> getRemoveHandlers() {
return Collections.singletonList(new RemoveConfigurableHandler<ModifiableFlexBuildConfiguration>(CompositeConfigurable.class) {
@Override
public boolean canBeRemoved(@NotNull Collection<ModifiableFlexBuildConfiguration> configurations) {
return myConfigurator.canBeRemoved(configurations.toArray(new ModifiableFlexBuildConfiguration[configurations.size()]));
}
@Override
public boolean remove(@NotNull Collection<ModifiableFlexBuildConfiguration> configurations) {
for (ModifiableFlexBuildConfiguration configuration : configurations) {
myConfigurator.removeConfiguration(configuration);
}
return true;
}
});
}
public boolean canBeCopied(final NamedConfigurable configurable) {
return configurable instanceof CompositeConfigurable;
}
public void copy(final NamedConfigurable configurable, final Runnable treeNodeNameUpdater) {
myConfigurator.copy(((CompositeConfigurable)configurable), treeNodeNameUpdater);
}
public Collection<AnAction> createAddActions(final NullableComputable<MasterDetailsComponent.MyNode> selectedNodeRetriever,
final Runnable treeNodeNameUpdater,
final Project project,
final MasterDetailsComponent.MyNode root) {
final Collection<AnAction> actions = new ArrayList<>(2);
actions.add(new DumbAwareAction(FlexBundle.message("create.bc.action.text"), FlexBundle.message("create.bc.action.description"),
FlexIcons.Flash_run_config) {
public void update(final AnActionEvent e) {
e.getPresentation().setVisible(getFlexModuleForNode(selectedNodeRetriever.compute()) != null);
}
public void actionPerformed(final AnActionEvent e) {
final Module module = getFlexModuleForNode(selectedNodeRetriever.compute());
myConfigurator.addConfiguration(module, treeNodeNameUpdater);
}
});
return actions;
}
@Nullable
private static Module getFlexModuleForNode(@Nullable MasterDetailsComponent.MyNode node) {
while (node != null) {
final NamedConfigurable configurable = node.getConfigurable();
final Object editableObject = configurable == null ? null : configurable.getEditableObject();
if (editableObject instanceof Module && ModuleType.get((Module)editableObject) instanceof FlexModuleType) {
return (Module)editableObject;
}
final TreeNode parent = node.getParent();
node = parent instanceof MasterDetailsComponent.MyNode ? (MasterDetailsComponent.MyNode)parent : null;
}
return null;
}
@Nullable
public ActionCallback selectOrderEntry(@NotNull final Module module, @Nullable final OrderEntry entry) {
if (ModuleType.get(module) != FlexModuleType.getInstance()) {
return null;
}
if (entry instanceof LibraryOrderEntry) {
final Library library = ((LibraryOrderEntry)entry).getLibrary();
if (library != null && library.getTable() == null && ((LibraryEx)library).getKind() == FlexLibraryType.FLEX_LIBRARY) {
final String libraryId = FlexProjectRootsUtil.getLibraryId(library);
final List<CompositeConfigurable> configurables = myConfigurator.getBCConfigurables(module);
// several build configurations may depend on the same library, here we select the first one we find
for (CompositeConfigurable configurable : configurables) {
final FlexBCConfigurable bcConfigurable = FlexBCConfigurable.unwrap(configurable);
final Dependencies dependencies = bcConfigurable.getDependenciesConfigurable().getEditableObject();
for (DependencyEntry e : dependencies.getEntries()) {
if (!(e instanceof ModuleLibraryEntry) || !((ModuleLibraryEntry)e).getLibraryId().equals(libraryId)) {
continue;
}
final Place p = FlexProjectStructureUtil.createPlace(bcConfigurable, DependenciesConfigurable.TAB_NAME);
final DependenciesConfigurable.Location.TableEntry tableEntry =
DependenciesConfigurable.Location.TableEntry.forModuleLibrary(libraryId);
p.putPath(FlexBCConfigurable.LOCATION_ON_TAB, tableEntry);
return ProjectStructureConfigurable.getInstance(module.getProject()).navigateTo(p, true);
}
}
}
}
return ProjectStructureConfigurable.getInstance(module.getProject()).select(module.getName(), null, true);
}
}