update copyright
[fedora-idea.git] / java / idea-ui / src / com / intellij / ide / util / newProjectWizard / AddSupportForFrameworksPanel.java
blob0fa533079c8ecf3447798bfa5c4cbafa02a8920f
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.ide.util.newProjectWizard;
19 import com.intellij.facet.impl.ui.libraries.LibraryCompositionOptionsPanel;
20 import com.intellij.facet.impl.ui.libraries.LibraryCompositionSettings;
21 import com.intellij.facet.impl.ui.libraries.LibraryDownloadingMirrorsMap;
22 import com.intellij.facet.ui.FacetBasedFrameworkSupportProvider;
23 import com.intellij.facet.ui.libraries.LibraryDownloadInfo;
24 import com.intellij.facet.ui.libraries.LibraryInfo;
25 import com.intellij.facet.ui.libraries.RemoteRepositoryInfo;
26 import com.intellij.ide.util.frameworkSupport.FrameworkSupportConfigurable;
27 import com.intellij.ide.util.frameworkSupport.FrameworkSupportConfigurableListener;
28 import com.intellij.ide.util.frameworkSupport.FrameworkSupportProvider;
29 import com.intellij.ide.util.newProjectWizard.impl.FrameworkSupportModelImpl;
30 import com.intellij.ide.util.projectWizard.ModuleBuilder;
31 import com.intellij.openapi.diagnostic.Logger;
32 import com.intellij.openapi.module.Module;
33 import com.intellij.openapi.roots.ModifiableRootModel;
34 import com.intellij.openapi.roots.libraries.Library;
35 import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
36 import com.intellij.openapi.ui.Splitter;
37 import com.intellij.openapi.ui.VerticalFlowLayout;
38 import com.intellij.openapi.util.Comparing;
39 import com.intellij.openapi.util.Computable;
40 import com.intellij.openapi.util.MultiValuesMap;
41 import com.intellij.openapi.util.Pair;
42 import com.intellij.ui.CheckedTreeNode;
43 import com.intellij.ui.IdeBorderFactory;
44 import com.intellij.ui.ScrollPaneFactory;
45 import com.intellij.ui.SeparatorFactory;
46 import com.intellij.util.graph.CachingSemiGraph;
47 import com.intellij.util.graph.DFSTBuilder;
48 import com.intellij.util.graph.GraphGenerator;
49 import org.jetbrains.annotations.NonNls;
50 import org.jetbrains.annotations.NotNull;
51 import org.jetbrains.annotations.Nullable;
53 import javax.swing.*;
54 import javax.swing.event.TreeSelectionEvent;
55 import javax.swing.event.TreeSelectionListener;
56 import java.awt.*;
57 import java.util.*;
58 import java.util.List;
60 /**
61 * @author nik
63 public class AddSupportForFrameworksPanel {
64 private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.newProjectWizard.AddSupportForFrameworksStep");
65 @NonNls private static final String UNCHECKED_CARD = "unchecked";
66 @NonNls private static final String EMPTY_CARD = "empty";
67 private JPanel myMainPanel;
68 private JPanel myFrameworksPanel;
69 private List<List<FrameworkSupportNode>> myGroups;
70 private final LibrariesContainer myLibrariesContainer;
71 private final Computable<String> myBaseDirForLibrariesGetter;
72 private final List<FrameworkSupportProvider> myProviders;
73 private final LibraryDownloadingMirrorsMap myMirrorsMap;
74 private final FrameworkSupportModelImpl myModel;
75 private JPanel myOptionsPanel;
76 private FrameworksTree myFrameworksTree;
77 private Set<String> myInitializedOptionsPanelIds = new HashSet<String>();
78 private FrameworkSupportNode myLastSelectedNode;
79 private JLabel myTickCheckboxLabel;
81 public AddSupportForFrameworksPanel(final List<FrameworkSupportProvider> providers, final @NotNull LibrariesContainer librariesContainer,
82 @Nullable ModuleBuilder builder, Computable<String> baseDirForLibrariesGetter) {
83 myLibrariesContainer = librariesContainer;
84 myBaseDirForLibrariesGetter = baseDirForLibrariesGetter;
85 myProviders = providers;
86 myModel = new FrameworkSupportModelImpl(myLibrariesContainer.getProject(), builder);
87 createNodes();
88 myMirrorsMap = createMirrorsMap();
90 final Splitter splitter = new Splitter(false, 0.35f, 0.1f, 0.7f);
91 myFrameworksTree = new FrameworksTree(myGroups) {
92 @Override
93 protected void onNodeStateChanged(CheckedTreeNode node) {
94 if (!(node instanceof FrameworkSupportNode)) return;
96 final FrameworkSupportNode frameworkSupportNode = (FrameworkSupportNode)node;
97 frameworkSupportNode.setConfigurableComponentEnabled(node.isChecked());
98 updateOptionsPanel();
99 myModel.onFrameworkSelectionChanged(frameworkSupportNode);
102 myFrameworksTree.addTreeSelectionListener(new TreeSelectionListener() {
103 public void valueChanged(TreeSelectionEvent e) {
104 onSelectionChanged();
107 splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myFrameworksTree));
108 myOptionsPanel = new JPanel(new CardLayout());
109 myOptionsPanel.add(EMPTY_CARD, new JPanel());
110 final JPanel uncheckedLabelPanel = new JPanel(new BorderLayout());
111 myTickCheckboxLabel = new JLabel("Tick checkbox");
112 uncheckedLabelPanel.add(BorderLayout.NORTH, myTickCheckboxLabel);
113 myOptionsPanel.add(UNCHECKED_CARD, uncheckedLabelPanel);
114 splitter.setSecondComponent(myOptionsPanel);
115 myFrameworksPanel.add(splitter, BorderLayout.CENTER);
118 private void onSelectionChanged() {
119 if (!myFrameworksTree.isProcessingMouseEventOnCheckbox()) {
120 updateOptionsPanel();
123 final FrameworkSupportNode selectedNode = getSelectedNode();
124 if (!Comparing.equal(selectedNode, myLastSelectedNode)) {
125 applyLibraryOptionsForSelected();
127 myLastSelectedNode = selectedNode;
128 if (selectedNode != null) {
129 final LibraryCompositionOptionsPanel newOptionsPanel = selectedNode.getLibraryCompositionOptionsPanel(myLibrariesContainer, myMirrorsMap);
130 if (newOptionsPanel != null) {
131 newOptionsPanel.updateRepositoriesMirrors(myMirrorsMap);
137 private void applyLibraryOptionsForSelected() {
138 if (myLastSelectedNode != null) {
139 final LibraryCompositionOptionsPanel optionsPanel = myLastSelectedNode.getLibraryCompositionOptionsPanel(myLibrariesContainer, myMirrorsMap);
140 if (optionsPanel != null) {
141 optionsPanel.saveSelectedRepositoriesMirrors(myMirrorsMap);
142 optionsPanel.apply();
147 private void updateOptionsPanel() {
148 final FrameworkSupportNode node = getSelectedNode();
149 if (node != null) {
150 if (node.isChecked()) {
151 initializeOptionsPanel(node);
152 showCard(node.getProvider().getId());
154 else {
155 myTickCheckboxLabel.setText("Select check box to add '" + node.getTitle() + "' support");
156 showCard(UNCHECKED_CARD);
159 else {
160 showCard(EMPTY_CARD);
164 @Nullable
165 private FrameworkSupportNode getSelectedNode() {
166 final FrameworkSupportNode[] nodes = myFrameworksTree.getSelectedNodes(FrameworkSupportNode.class, null);
167 return nodes.length == 1 ? nodes[0] : null;
170 private void initializeOptionsPanel(final FrameworkSupportNode node) {
171 final String id = node.getProvider().getId();
172 if (!myInitializedOptionsPanelIds.contains(id)) {
173 final JPanel optionsPanel = new JPanel(new VerticalFlowLayout());
174 JComponent separator = SeparatorFactory.createSeparator(node.getTitle() + " Settings", null);
175 separator.setBorder(IdeBorderFactory.createEmptyBorder(0, 0, 5, 5));
177 optionsPanel.add(separator);
178 final FrameworkSupportConfigurable configurable = node.getConfigurable();
179 optionsPanel.add(configurable.getComponent());
180 final JPanel librariesOptionsPanelWrapper = new JPanel(new BorderLayout());
181 optionsPanel.add(librariesOptionsPanelWrapper);
182 configurable.addListener(new FrameworkSupportConfigurableListener() {
183 public void frameworkVersionChanged() {
184 librariesOptionsPanelWrapper.removeAll();
185 addLibrariesOptionsPanel(node, librariesOptionsPanelWrapper);
186 librariesOptionsPanelWrapper.revalidate();
189 addLibrariesOptionsPanel(node, librariesOptionsPanelWrapper);
190 myOptionsPanel.add(id, optionsPanel);
191 myInitializedOptionsPanelIds.add(id);
195 private void addLibrariesOptionsPanel(FrameworkSupportNode node, JPanel librariesOptionsPanelWrapper) {
196 final LibraryCompositionOptionsPanel libraryOptionsPanel = node.getLibraryCompositionOptionsPanel(myLibrariesContainer, myMirrorsMap);
197 if (libraryOptionsPanel != null) {
198 librariesOptionsPanelWrapper.add(BorderLayout.CENTER, libraryOptionsPanel.getMainPanel());
202 private void showCard(String cardName) {
203 ((CardLayout)myOptionsPanel.getLayout()).show(myOptionsPanel, cardName);
206 private LibraryDownloadingMirrorsMap createMirrorsMap() {
207 List<RemoteRepositoryInfo> repositoryInfos = getRemoteRepositories();
208 return new LibraryDownloadingMirrorsMap(repositoryInfos.toArray(new RemoteRepositoryInfo[repositoryInfos.size()]));
211 private List<RemoteRepositoryInfo> getRemoteRepositories() {
212 List<RemoteRepositoryInfo> repositoryInfos = new ArrayList<RemoteRepositoryInfo>();
213 List<FrameworkSupportNode> frameworkNodes = getFrameworkNodes(false);
214 for (FrameworkSupportNode node : frameworkNodes) {
215 LibraryInfo[] libraries = node.getLibraries();
216 for (LibraryInfo library : libraries) {
217 LibraryDownloadInfo downloadInfo = library.getDownloadingInfo();
218 if (downloadInfo != null) {
219 RemoteRepositoryInfo repository = downloadInfo.getRemoteRepository();
220 if (repository != null) {
221 repositoryInfos.add(repository);
226 return repositoryInfos;
229 private List<LibraryCompositionSettings> getLibrariesCompositionSettingsList() {
230 List<LibraryCompositionSettings> list = new ArrayList<LibraryCompositionSettings>();
231 List<FrameworkSupportNode> selected = getFrameworkNodes(true);
232 for (FrameworkSupportNode node : selected) {
233 final LibraryCompositionSettings settings = node.getLibraryCompositionSettings();
234 if (settings != null) {
235 list.add(settings);
238 return list;
241 public boolean downloadLibraries() {
242 applyLibraryOptionsForSelected();
243 List<LibraryCompositionSettings> list = getLibrariesCompositionSettingsList();
244 for (LibraryCompositionSettings compositionSettings : list) {
245 if (!compositionSettings.downloadFiles(myMirrorsMap, myLibrariesContainer, myMainPanel)) return false;
247 return true;
250 private void createNodes() {
251 Map<String, FrameworkSupportNode> nodes = new HashMap<String, FrameworkSupportNode>();
252 MultiValuesMap<String, FrameworkSupportNode> groups = new MultiValuesMap<String, FrameworkSupportNode>(true);
253 for (FrameworkSupportProvider frameworkSupport : myProviders) {
254 createNode(frameworkSupport, nodes, groups);
257 myGroups = new ArrayList<List<FrameworkSupportNode>>();
258 for (String groupId : groups.keySet()) {
259 final Collection<FrameworkSupportNode> collection = groups.get(groupId);
260 if (collection != null) {
261 final List<FrameworkSupportNode> group = new ArrayList<FrameworkSupportNode>();
262 for (FrameworkSupportNode node : collection) {
263 if (node.getParentNode() == null) {
264 group.add(node);
267 FrameworkSupportNode.sortByTitle(group);
268 myGroups.add(group);
273 @Nullable
274 private FrameworkSupportNode createNode(final FrameworkSupportProvider provider, final Map<String, FrameworkSupportNode> nodes,
275 final MultiValuesMap<String, FrameworkSupportNode> groups) {
276 FrameworkSupportNode node = nodes.get(provider.getId());
277 if (node == null) {
278 String underlyingFrameworkId = provider.getUnderlyingFrameworkId();
279 FrameworkSupportNode parentNode = null;
280 if (underlyingFrameworkId != null) {
281 FrameworkSupportProvider parentProvider = findProvider(underlyingFrameworkId);
282 if (parentProvider == null) {
283 LOG.info("Cannot find id = " + underlyingFrameworkId);
284 return null;
286 parentNode = createNode(parentProvider, nodes, groups);
288 node = new FrameworkSupportNode(provider, parentNode, myModel, myBaseDirForLibrariesGetter);
289 nodes.put(provider.getId(), node);
290 groups.put(provider.getGroupId(), node);
292 return node;
295 @Nullable
296 private FrameworkSupportProvider findProvider(@NotNull String id) {
297 for (FrameworkSupportProvider provider : myProviders) {
298 if (id.equals(provider.getId())) {
299 return provider;
302 LOG.info("Cannot find framework support provider '" + id + "'");
303 return null;
306 public JComponent getMainPanel() {
307 return myMainPanel;
310 private List<FrameworkSupportNode> getFrameworkNodes(final boolean selectedOnly) {
311 ArrayList<FrameworkSupportNode> list = new ArrayList<FrameworkSupportNode>();
312 if (myGroups != null) {
313 for (List<FrameworkSupportNode> group : myGroups) {
314 addChildFrameworks(group, list, selectedOnly);
317 return list;
320 private static void addChildFrameworks(final List<FrameworkSupportNode> list, final List<FrameworkSupportNode> result,
321 final boolean selectedOnly) {
322 for (FrameworkSupportNode node : list) {
323 if (!selectedOnly || node.isChecked()) {
324 result.add(node);
325 addChildFrameworks(node.getChildren(), result, selectedOnly);
330 public void addSupport(final @NotNull Module module, final @NotNull ModifiableRootModel rootModel) {
331 List<Library> addedLibraries = new ArrayList<Library>();
332 List<FrameworkSupportNode> selectedFrameworks = getFrameworkNodes(true);
333 sortFrameworks(selectedFrameworks);
335 for (FrameworkSupportNode node : selectedFrameworks) {
336 FrameworkSupportConfigurable configurable = node.getConfigurable();
337 final LibraryCompositionSettings settings = node.getLibraryCompositionSettings();
338 Library library = settings != null ? settings.addLibraries(rootModel, addedLibraries) : null;
339 configurable.addSupport(module, rootModel, library);
341 for (FrameworkSupportNode node : selectedFrameworks) {
342 FrameworkSupportProvider provider = node.getProvider();
343 if (provider instanceof FacetBasedFrameworkSupportProvider && !addedLibraries.isEmpty()) {
344 ((FacetBasedFrameworkSupportProvider)provider).processAddedLibraries(module, addedLibraries);
349 private void sortFrameworks(final List<FrameworkSupportNode> nodes) {
350 DFSTBuilder<FrameworkSupportProvider> builder = new DFSTBuilder<FrameworkSupportProvider>(GraphGenerator.create(CachingSemiGraph.create(new ProvidersGraph(myProviders))));
351 if (!builder.isAcyclic()) {
352 Pair<FrameworkSupportProvider,FrameworkSupportProvider> pair = builder.getCircularDependency();
353 LOG.error("Circular dependency between providers '" + pair.getFirst().getId() + "' and '" + pair.getSecond().getId() + "' was found.");
356 final Comparator<FrameworkSupportProvider> comparator = builder.comparator();
357 Collections.sort(nodes, new Comparator<FrameworkSupportNode>() {
358 public int compare(final FrameworkSupportNode o1, final FrameworkSupportNode o2) {
359 return comparator.compare(o1.getProvider(), o2.getProvider());
364 private class ProvidersGraph implements GraphGenerator.SemiGraph<FrameworkSupportProvider> {
365 private final List<FrameworkSupportProvider> myFrameworkSupportProviders;
367 public ProvidersGraph(final List<FrameworkSupportProvider> frameworkSupportProviders) {
368 myFrameworkSupportProviders = new ArrayList<FrameworkSupportProvider>(frameworkSupportProviders);
371 public Collection<FrameworkSupportProvider> getNodes() {
372 return myFrameworkSupportProviders;
375 public Iterator<FrameworkSupportProvider> getIn(final FrameworkSupportProvider provider) {
376 String[] ids = provider.getPrecedingFrameworkProviderIds();
377 List<FrameworkSupportProvider> dependencies = new ArrayList<FrameworkSupportProvider>();
378 String underlyingId = provider.getUnderlyingFrameworkId();
379 if (underlyingId != null) {
380 FrameworkSupportProvider underlyingProvider = findProvider(underlyingId);
381 if (underlyingProvider != null) {
382 dependencies.add(underlyingProvider);
385 for (String id : ids) {
386 FrameworkSupportProvider dependency = findProvider(id);
387 if (dependency != null) {
388 dependencies.add(dependency);
391 return dependencies.iterator();