| /* |
| * 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.ide.util.newProjectWizard; |
| |
| import com.intellij.facet.impl.ui.libraries.LibraryCompositionSettings; |
| import com.intellij.facet.impl.ui.libraries.LibraryOptionsPanel; |
| import com.intellij.facet.ui.FacetBasedFrameworkSupportProvider; |
| import com.intellij.framework.FrameworkGroup; |
| import com.intellij.framework.FrameworkVersion; |
| import com.intellij.framework.addSupport.FrameworkSupportInModuleConfigurable; |
| import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider; |
| import com.intellij.framework.addSupport.FrameworkVersionListener; |
| import com.intellij.ide.util.frameworkSupport.FrameworkSupportConfigurable; |
| import com.intellij.ide.util.frameworkSupport.FrameworkSupportProvider; |
| import com.intellij.ide.util.frameworkSupport.FrameworkSupportUtil; |
| import com.intellij.ide.util.newProjectWizard.impl.FrameworkSupportCommunicator; |
| import com.intellij.ide.util.newProjectWizard.impl.FrameworkSupportModelBase; |
| import com.intellij.openapi.Disposable; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.roots.IdeaModifiableModelsProvider; |
| import com.intellij.openapi.roots.ModifiableRootModel; |
| import com.intellij.openapi.roots.libraries.Library; |
| import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer; |
| import com.intellij.openapi.ui.Splitter; |
| import com.intellij.openapi.util.Comparing; |
| import com.intellij.ui.CheckedTreeNode; |
| import com.intellij.ui.IdeBorderFactory; |
| import com.intellij.ui.ScrollPaneFactory; |
| import com.intellij.util.Function; |
| import com.intellij.util.containers.ContainerUtil; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.event.TreeSelectionEvent; |
| import javax.swing.event.TreeSelectionListener; |
| import javax.swing.tree.DefaultTreeModel; |
| import java.awt.*; |
| import java.util.*; |
| import java.util.List; |
| |
| /** |
| * @author nik |
| */ |
| public class AddSupportForFrameworksPanel implements Disposable { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.newProjectWizard.AddSupportForFrameworksStep"); |
| @NonNls private static final String EMPTY_CARD = "empty"; |
| private JPanel myMainPanel; |
| private JPanel myFrameworksPanel; |
| private JLabel myLabel; |
| |
| private List<FrameworkSupportInModuleProvider> myProviders; |
| private List<FrameworkSupportNodeBase> myRoots; |
| |
| private final LibrariesContainer myLibrariesContainer; |
| private final FrameworkSupportModelBase myModel; |
| private final JPanel myOptionsPanel; |
| private final FrameworksTree myFrameworksTree; |
| private final Map<FrameworkSupportNode, FrameworkSupportOptionsComponent> myInitializedOptionsComponents = new HashMap<FrameworkSupportNode, FrameworkSupportOptionsComponent>(); |
| private final Map<FrameworkGroup<?>, JPanel> myInitializedGroupPanels = new HashMap<FrameworkGroup<?>, JPanel>(); |
| private FrameworkSupportNodeBase myLastSelectedNode; |
| |
| private Collection<FrameworkSupportNodeBase> myAssociatedFrameworks; |
| @Nullable |
| private final JPanel myAssociatedFrameworksPanel; |
| |
| public AddSupportForFrameworksPanel(final List<FrameworkSupportInModuleProvider> providers, |
| final FrameworkSupportModelBase model, boolean vertical, @Nullable JPanel associatedFrameworksPanel) { |
| myModel = model; |
| myAssociatedFrameworksPanel = associatedFrameworksPanel; |
| myLibrariesContainer = model.getLibrariesContainer(); |
| |
| myLabel.setVisible(!vertical); |
| Splitter splitter = vertical ? new Splitter(true, 0.6f, 0.2f, 0.8f) : new Splitter(false, 0.3f, 0.3f, 0.7f); |
| splitter.setHonorComponentsMinimumSize(false); |
| myFrameworksTree = new FrameworksTree(model) { |
| @Override |
| protected void onNodeStateChanged(CheckedTreeNode node) { |
| if (!(node instanceof FrameworkSupportNode)) return; |
| |
| final FrameworkSupportNode frameworkSupportNode = (FrameworkSupportNode)node; |
| if (frameworkSupportNode == getSelectedNode()) { |
| updateOptionsPanel(); |
| } |
| final FrameworkSupportInModuleConfigurable configurable = frameworkSupportNode.getConfigurable(); |
| configurable.onFrameworkSelectionChanged(node.isChecked()); |
| myModel.onFrameworkSelectionChanged(frameworkSupportNode); |
| onFrameworkStateChanged(); |
| } |
| }; |
| model.addFrameworkVersionListener(new FrameworkVersionListener() { |
| @Override |
| public void versionChanged(FrameworkVersion version) { |
| ((DefaultTreeModel)myFrameworksTree.getModel()).nodeChanged(getSelectedNode()); |
| } |
| }, this); |
| |
| myFrameworksTree.addTreeSelectionListener(new TreeSelectionListener() { |
| public void valueChanged(TreeSelectionEvent e) { |
| onSelectionChanged(); |
| } |
| }); |
| |
| JPanel treePanel = new JPanel(new BorderLayout()); |
| treePanel.add(ScrollPaneFactory.createScrollPane(myFrameworksTree), BorderLayout.CENTER); |
| treePanel.setMinimumSize(new Dimension(200, 300)); |
| |
| splitter.setFirstComponent(treePanel); |
| myOptionsPanel = new JPanel(new CardLayout()); |
| JPanel emptyCard = new JPanel(); |
| emptyCard.setPreferredSize(new Dimension(400, 100)); |
| myOptionsPanel.add(EMPTY_CARD, emptyCard); |
| |
| splitter.setSecondComponent(myOptionsPanel); |
| myFrameworksPanel.add(splitter, BorderLayout.CENTER); |
| |
| setProviders(providers); |
| } |
| |
| public void setProviders(List<FrameworkSupportInModuleProvider> providers) { |
| setProviders(providers, Collections.<String>emptySet(), Collections.<String>emptySet()); |
| } |
| |
| public void setProviders(List<FrameworkSupportInModuleProvider> providers, Set<String> associated, Set<String> preselected) { |
| myProviders = providers; |
| |
| myAssociatedFrameworks = createNodes(myProviders, associated, preselected); |
| for (FrameworkSupportNodeBase node : myRoots) { |
| if (preselected.contains(node.getId())) { |
| node.setChecked(true); |
| } |
| } |
| setAssociatedFrameworks(); |
| |
| myFrameworksTree.setRoots(myRoots); |
| myFrameworksTree.setSelectionRow(0); |
| } |
| |
| public void setAssociatedFrameworks() { |
| |
| if (myAssociatedFrameworksPanel == null) return; |
| for (FrameworkSupportNodeBase nodeBase : myAssociatedFrameworks) { |
| if (nodeBase instanceof FrameworkSupportNode) { |
| ((FrameworkSupportNode)nodeBase).getConfigurable().onFrameworkSelectionChanged(true); |
| FrameworkSupportOptionsComponent component = initializeOptionsPanel((FrameworkSupportNode)nodeBase, false); |
| addAssociatedFrameworkComponent(component.getMainPanel(), myAssociatedFrameworksPanel); |
| } |
| else { |
| JPanel panel = initializeGroupPanel((FrameworkGroup<?>)nodeBase.getUserObject(), false); |
| addAssociatedFrameworkComponent(panel, myAssociatedFrameworksPanel); |
| } |
| } |
| } |
| |
| private static void addAssociatedFrameworkComponent(JPanel component, JPanel panel) { |
| panel.add(component, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0, GridBagConstraints.NORTHWEST, |
| GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); |
| } |
| |
| protected void onFrameworkStateChanged() {} |
| |
| private void onSelectionChanged() { |
| if (!myFrameworksTree.isProcessingMouseEventOnCheckbox()) { |
| updateOptionsPanel(); |
| } |
| |
| final FrameworkSupportNodeBase selectedNode = getSelectedNode(); |
| if (!Comparing.equal(selectedNode, myLastSelectedNode)) { |
| applyLibraryOptionsForSelected(); |
| |
| myLastSelectedNode = selectedNode; |
| } |
| } |
| |
| @Override |
| public void dispose() { |
| } |
| |
| private void applyLibraryOptionsForSelected() { |
| if (myLastSelectedNode instanceof FrameworkSupportNode) { |
| final FrameworkSupportOptionsComponent optionsComponent = myInitializedOptionsComponents.get((FrameworkSupportNode)myLastSelectedNode); |
| if (optionsComponent != null) { |
| final LibraryOptionsPanel optionsPanel = optionsComponent.getLibraryOptionsPanel(); |
| if (optionsPanel != null) { |
| optionsPanel.apply(); |
| } |
| } |
| } |
| } |
| |
| private void updateOptionsPanel() { |
| final FrameworkSupportNodeBase node = getSelectedNode(); |
| if (node instanceof FrameworkSupportNode) { |
| FrameworkSupportNode frameworkSupportNode = (FrameworkSupportNode)node; |
| initializeOptionsPanel(frameworkSupportNode, true); |
| showCard(frameworkSupportNode.getId()); |
| UIUtil.setEnabled(myOptionsPanel, frameworkSupportNode.isChecked(), true); |
| frameworkSupportNode.getConfigurable().onFrameworkSelectionChanged(node.isChecked()); |
| } |
| else if (node instanceof FrameworkGroupNode) { |
| FrameworkGroup<?> group = ((FrameworkGroupNode)node).getUserObject(); |
| initializeGroupPanel(group, true); |
| showCard(group.getId()); |
| UIUtil.setEnabled(myOptionsPanel, true, true); |
| } |
| else { |
| showCard(EMPTY_CARD); |
| } |
| } |
| |
| private JPanel initializeGroupPanel(FrameworkGroup<?> group, boolean addToOptions) { |
| JPanel panel = myInitializedGroupPanels.get(group); |
| if (panel == null) { |
| FrameworkVersionComponent component = new FrameworkVersionComponent(myModel, group.getId(), group.getGroupVersions(), group.getPresentableName() + " version:"); |
| panel = component.getMainPanel(); |
| myInitializedGroupPanels.put(group, panel); |
| if (addToOptions) { |
| myOptionsPanel.add(group.getId(), wrapInScrollPane(panel)); |
| } |
| } |
| return panel; |
| } |
| |
| @Nullable |
| public FrameworkSupportNodeBase getSelectedNode() { |
| final FrameworkSupportNodeBase[] nodes = myFrameworksTree.getSelectedNodes(FrameworkSupportNodeBase.class, null); |
| return nodes.length == 1 ? nodes[0] : null; |
| } |
| |
| private FrameworkSupportOptionsComponent initializeOptionsPanel(final FrameworkSupportNode node, boolean addToOptions) { |
| FrameworkSupportOptionsComponent component = myInitializedOptionsComponents.get(node); |
| if (component == null) { |
| final FrameworkSupportNodeBase parentNode = node.getParentNode(); |
| if (parentNode instanceof FrameworkSupportNode) { |
| initializeOptionsPanel((FrameworkSupportNode)parentNode, addToOptions); |
| } |
| else if (parentNode instanceof FrameworkGroupNode) { |
| initializeGroupPanel(((FrameworkGroupNode)parentNode).getUserObject(), addToOptions); |
| } |
| |
| component = new FrameworkSupportOptionsComponent(myModel, myLibrariesContainer, this, |
| node.getUserObject(), node.getConfigurable()); |
| if (addToOptions) { |
| myOptionsPanel.add(node.getId(), wrapInScrollPane(component.getMainPanel())); |
| } |
| myInitializedOptionsComponents.put(node, component); |
| } |
| return component; |
| } |
| |
| private static JScrollPane wrapInScrollPane(JPanel panel) { |
| JPanel wrapper = new JPanel(new BorderLayout()); |
| wrapper.add(panel); |
| wrapper.setBorder(IdeBorderFactory.createEmptyBorder(5)); |
| return ScrollPaneFactory.createScrollPane(wrapper, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, |
| ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); |
| } |
| |
| private void showCard(String cardName) { |
| ((CardLayout)myOptionsPanel.getLayout()).show(myOptionsPanel, cardName); |
| } |
| |
| private List<LibraryCompositionSettings> getLibrariesCompositionSettingsList() { |
| List<LibraryCompositionSettings> list = new ArrayList<LibraryCompositionSettings>(); |
| List<FrameworkSupportNode> selected = getSelectedNodes(); |
| for (FrameworkSupportNode node : selected) { |
| ContainerUtil.addIfNotNull(list, getLibraryCompositionSettings(node)); |
| } |
| return list; |
| } |
| |
| @Nullable |
| private LibraryCompositionSettings getLibraryCompositionSettings(FrameworkSupportNode node) { |
| final FrameworkSupportOptionsComponent optionsComponent = myInitializedOptionsComponents.get(node); |
| return optionsComponent != null ? optionsComponent.getLibraryCompositionSettings() : null; |
| } |
| |
| public boolean downloadLibraries() { |
| applyLibraryOptionsForSelected(); |
| List<LibraryCompositionSettings> list = getLibrariesCompositionSettingsList(); |
| for (LibraryCompositionSettings compositionSettings : list) { |
| if (!compositionSettings.downloadFiles(myMainPanel)) return false; |
| } |
| return true; |
| } |
| |
| private Collection<FrameworkSupportNodeBase> createNodes(List<FrameworkSupportInModuleProvider> providers, |
| Set<String> associated, |
| final Set<String> preselected) { |
| Map<String, FrameworkSupportNode> nodes = new HashMap<String, FrameworkSupportNode>(); |
| Map<FrameworkGroup<?>, FrameworkGroupNode> groups = new HashMap<FrameworkGroup<?>, FrameworkGroupNode>(); |
| List<FrameworkSupportNodeBase> roots = new ArrayList<FrameworkSupportNodeBase>(); |
| Map<String, FrameworkSupportNodeBase> associatedNodes = new LinkedHashMap<String, FrameworkSupportNodeBase>(); |
| for (FrameworkSupportInModuleProvider provider : providers) { |
| createNode(provider, nodes, groups, roots, providers, associated, associatedNodes); |
| } |
| |
| FrameworkSupportNodeBase.sortByName(roots, new Comparator<FrameworkSupportNodeBase>() { |
| @Override |
| public int compare(FrameworkSupportNodeBase o1, FrameworkSupportNodeBase o2) { |
| return Comparing.compare(preselected.contains(o2.getId()), preselected.contains(o1.getId())); |
| } |
| }); |
| myRoots = roots; |
| return associatedNodes.values(); |
| } |
| |
| @Nullable |
| private FrameworkSupportNode createNode(final FrameworkSupportInModuleProvider provider, |
| final Map<String, FrameworkSupportNode> nodes, |
| final Map<FrameworkGroup<?>, FrameworkGroupNode> groupNodes, |
| List<FrameworkSupportNodeBase> roots, |
| List<FrameworkSupportInModuleProvider> providers, |
| Set<String> associated, |
| Map<String, FrameworkSupportNodeBase> associatedNodes) { |
| String id = provider.getFrameworkType().getId(); |
| FrameworkSupportNode node = nodes.get(id); |
| if (node != null || associatedNodes.containsKey(id)) { |
| return node; |
| } |
| String underlyingTypeId = provider.getFrameworkType().getUnderlyingFrameworkTypeId(); |
| FrameworkSupportNodeBase parentNode = null; |
| final FrameworkGroup<?> group = provider.getFrameworkType().getParentGroup(); |
| if (underlyingTypeId != null) { |
| FrameworkSupportInModuleProvider parentProvider = FrameworkSupportUtil.findProvider(underlyingTypeId, providers); |
| if (parentProvider == null) { |
| LOG.info("Cannot find id = " + underlyingTypeId); |
| return null; |
| } |
| parentNode = createNode(parentProvider, nodes, groupNodes, roots, providers, associated, associatedNodes); |
| } |
| else if (group != null) { |
| parentNode = groupNodes.get(group); |
| if (parentNode == null) { |
| FrameworkGroupNode groupNode = new FrameworkGroupNode(group, null); |
| if (associated.contains(groupNode.getId())) { |
| associatedNodes.put(groupNode.getId(), groupNode); |
| } |
| else { |
| groupNodes.put(group, groupNode); |
| parentNode = groupNode; |
| roots.add(groupNode); |
| } |
| } |
| } |
| node = new FrameworkSupportNode(provider, parentNode, myModel, this); |
| if (associated.contains(id)) { |
| associatedNodes.put(id, node); |
| } |
| else { |
| nodes.put(id, node); |
| if (parentNode == null) { |
| roots.add(node); |
| } |
| } |
| return node; |
| } |
| |
| public JComponent getMainPanel() { |
| return myMainPanel; |
| } |
| |
| public FrameworksTree getFrameworksTree() { |
| return myFrameworksTree; |
| } |
| |
| public boolean hasSelectedFrameworks() { |
| return !getSelectedNodes().isEmpty(); |
| } |
| |
| public List<FrameworkSupportNode> getSelectedNodes() { |
| List<FrameworkSupportNode> list = new ArrayList<FrameworkSupportNode>(); |
| if (myRoots != null) { |
| addChildFrameworks(myRoots, list); |
| } |
| list.addAll(ContainerUtil.mapNotNull(myAssociatedFrameworks, new Function.InstanceOf<FrameworkSupportNodeBase, FrameworkSupportNode>(FrameworkSupportNode.class))); |
| return list; |
| } |
| |
| private static void addChildFrameworks(final List<FrameworkSupportNodeBase> list, final List<FrameworkSupportNode> result) { |
| for (FrameworkSupportNodeBase node : list) { |
| if (node.isChecked() || node instanceof FrameworkGroupNode) { |
| if (node instanceof FrameworkSupportNode) { |
| result.add((FrameworkSupportNode)node); |
| } |
| //noinspection unchecked |
| addChildFrameworks(node.getChildren(), result); |
| } |
| } |
| } |
| |
| public void addSupport(final @NotNull Module module, final @NotNull ModifiableRootModel rootModel) { |
| List<Library> addedLibraries = new ArrayList<Library>(); |
| List<FrameworkSupportNode> selectedFrameworks = getSelectedNodes(); |
| sortFrameworks(selectedFrameworks); |
| List<FrameworkSupportConfigurable> selectedConfigurables = new ArrayList<FrameworkSupportConfigurable>(); |
| final IdeaModifiableModelsProvider modifiableModelsProvider = new IdeaModifiableModelsProvider(); |
| for (FrameworkSupportNode node : selectedFrameworks) { |
| FrameworkSupportInModuleConfigurable configurable = node.getConfigurable(); |
| if (configurable instanceof OldFrameworkSupportProviderWrapper.FrameworkSupportConfigurableWrapper) { |
| selectedConfigurables.add(((OldFrameworkSupportProviderWrapper.FrameworkSupportConfigurableWrapper)configurable).getConfigurable()); |
| } |
| final LibraryCompositionSettings settings = getLibraryCompositionSettings(node); |
| Library library = settings != null ? settings.addLibraries(rootModel, addedLibraries, myLibrariesContainer) : null; |
| if (configurable instanceof OldFrameworkSupportProviderWrapper.FrameworkSupportConfigurableWrapper) { |
| ((OldFrameworkSupportProviderWrapper.FrameworkSupportConfigurableWrapper)configurable).getConfigurable().addSupport(module, rootModel, |
| library); |
| } |
| else { |
| configurable.addSupport(module, rootModel, modifiableModelsProvider); |
| } |
| } |
| for (FrameworkSupportNode node : selectedFrameworks) { |
| FrameworkSupportInModuleProvider provider = node.getUserObject(); |
| if (provider instanceof OldFrameworkSupportProviderWrapper) { |
| final FrameworkSupportProvider oldProvider = ((OldFrameworkSupportProviderWrapper)provider).getProvider(); |
| if (oldProvider instanceof FacetBasedFrameworkSupportProvider && !addedLibraries.isEmpty()) { |
| ((FacetBasedFrameworkSupportProvider)oldProvider).processAddedLibraries(module, addedLibraries); |
| } |
| } |
| } |
| for (FrameworkSupportCommunicator communicator : FrameworkSupportCommunicator.EP_NAME.getExtensions()) { |
| communicator.onFrameworkSupportAdded(module, rootModel, selectedConfigurables, myModel); |
| } |
| } |
| |
| private void sortFrameworks(final List<FrameworkSupportNode> nodes) { |
| final Comparator<FrameworkSupportInModuleProvider> comparator = FrameworkSupportUtil.getFrameworkSupportProvidersComparator(myProviders); |
| Collections.sort(nodes, new Comparator<FrameworkSupportNode>() { |
| public int compare(final FrameworkSupportNode o1, final FrameworkSupportNode o2) { |
| return comparator.compare(o1.getUserObject(), o2.getUserObject()); |
| } |
| }); |
| } |
| } |