101b81047ef3dcb79d546ca4001353ebb35ebdb2
[idea/community.git] / java / idea-ui / src / com / intellij / openapi / roots / ui / configuration / ClasspathEditor.java
1 /*
2  * Copyright 2004-2005 Alexey Efimov
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.openapi.roots.ui.configuration;
17
18 import com.intellij.ProjectTopics;
19 import com.intellij.ide.JavaUiBundle;
20 import com.intellij.openapi.Disposable;
21 import com.intellij.openapi.compiler.JavaCompilerBundle;
22 import com.intellij.openapi.options.ConfigurationException;
23 import com.intellij.openapi.projectRoots.Sdk;
24 import com.intellij.openapi.roots.ModifiableRootModel;
25 import com.intellij.openapi.roots.ModuleRootEvent;
26 import com.intellij.openapi.roots.ModuleRootListener;
27 import com.intellij.openapi.roots.OrderEntry;
28 import com.intellij.openapi.roots.impl.storage.ClassPathStorageUtil;
29 import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
30 import com.intellij.openapi.roots.impl.storage.ClasspathStorageProvider;
31 import com.intellij.openapi.roots.ui.configuration.classpath.ClasspathPanelImpl;
32 import com.intellij.openapi.ui.ComboBox;
33 import com.intellij.openapi.util.Disposer;
34 import com.intellij.ui.SimpleListCellRenderer;
35 import com.intellij.util.ArrayUtilRt;
36 import com.intellij.util.ui.JBUI;
37 import org.jetbrains.annotations.NotNull;
38 import org.jetbrains.annotations.Nullable;
39
40 import javax.swing.*;
41 import java.awt.*;
42 import java.util.LinkedHashMap;
43 import java.util.Map;
44
45 public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootListener {
46   /**
47    * @deprecated Use {@link #getName()} instead
48    */
49   @Deprecated
50   public static final String NAME = "Dependencies";
51
52   private ClasspathPanelImpl myPanel;
53   private ClasspathFormatPanel myClasspathFormatPanel;
54
55   public ClasspathEditor(final ModuleConfigurationState state) {
56     super(state);
57
58     final Disposable disposable = Disposer.newDisposable();
59     state.getProject().getMessageBus().connect(disposable).subscribe(ProjectTopics.PROJECT_ROOTS, this);
60     registerDisposable(disposable);
61   }
62
63   @Override
64   public boolean isModified() {
65     return super.isModified() || (myClasspathFormatPanel != null && myClasspathFormatPanel.isModified());
66   }
67
68   @Override
69   public String getHelpTopic() {
70     return "projectStructure.modules.dependencies";
71   }
72
73   @Override
74   public String getDisplayName() {
75     return getName();
76   }
77
78   @Override
79   public void saveData() {
80     myPanel.stopEditing();
81   }
82
83   @Override
84   public void apply() throws ConfigurationException {
85     if (myClasspathFormatPanel != null) {
86       myClasspathFormatPanel.apply();
87     }
88   }
89
90   @Override
91   public void canApply() throws ConfigurationException {
92     super.canApply();
93     if (myClasspathFormatPanel != null) {
94       myClasspathFormatPanel.canApply();
95     }
96   }
97
98   @Override
99   public JComponent createComponentImpl() {
100     myPanel = new ClasspathPanelImpl(getState());
101     final JPanel panel = new JPanel(new BorderLayout());
102     panel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
103     panel.add(myPanel, BorderLayout.CENTER);
104
105     final ModuleJdkConfigurable jdkConfigurable =
106       new ModuleJdkConfigurable(this, ProjectStructureConfigurable.getInstance(myProject).getProjectJdksModel()) {
107         @Override
108         protected ModifiableRootModel getRootModel() {
109           return getModifiableModel();
110         }
111       };
112     panel.add(jdkConfigurable.createComponent(), BorderLayout.NORTH);
113     jdkConfigurable.reset();
114     registerDisposable(jdkConfigurable);
115
116     ClasspathStorageProvider[] providers = ClasspathStorageProvider.EXTENSION_POINT_NAME.getExtensions();
117     if (providers.length > 0) {
118       myClasspathFormatPanel = new ClasspathFormatPanel(providers, getState());
119       panel.add(myClasspathFormatPanel, BorderLayout.SOUTH);
120     }
121
122     return panel;
123   }
124
125   private ModifiableRootModel getModifiableModel() {
126     return getState().getRootModel();
127   }
128
129   public void selectOrderEntry(@NotNull final OrderEntry entry) {
130     myPanel.selectOrderEntry(entry);
131   }
132
133   @Override
134   public void moduleStateChanged() {
135     if (myPanel != null) {
136       myPanel.initFromModel();
137     }
138   }
139
140   @Override
141   public void rootsChanged(@NotNull ModuleRootEvent event) {
142     if (myPanel != null) {
143       myPanel.rootsChanged();
144     }
145   }
146
147   public void setSdk(@Nullable final Sdk newJDK) {
148     final ModifiableRootModel model = getModel();
149     if (newJDK != null) {
150       model.setSdk(newJDK);
151     }
152     else {
153       model.inheritSdk();
154     }
155
156     if (myPanel != null) {
157       myPanel.forceInitFromModel();
158     }
159   }
160
161   private static final class ClasspathFormatPanel extends JPanel {
162     private final @NotNull ModuleConfigurationState myState;
163     private final JComboBox<String> comboBoxClasspathFormat;
164
165     private ClasspathFormatPanel(ClasspathStorageProvider[] providers, @NotNull ModuleConfigurationState state) {
166       super(new GridBagLayout());
167       myState = state;
168
169       JLabel comboBoxClasspathFormatLabel = new JLabel(JavaUiBundle.message("project.roots.classpath.format.label"));
170       add(comboBoxClasspathFormatLabel,
171           new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, JBUI.insets(10, 6, 6, 0), 0, 0));
172
173       Map<String, String> formatIdToDescription = new LinkedHashMap<>();
174       formatIdToDescription.put(ClassPathStorageUtil.DEFAULT_STORAGE, JavaUiBundle.message("project.roots.classpath.format.default.descr"));
175       for (ClasspathStorageProvider provider : providers) {
176         formatIdToDescription.put(provider.getID(), provider.getDescription());
177       }
178       comboBoxClasspathFormat = new ComboBox<>(ArrayUtilRt.toStringArray(formatIdToDescription.keySet()));
179       comboBoxClasspathFormat.setRenderer(SimpleListCellRenderer.create("", formatIdToDescription::get));
180       comboBoxClasspathFormat.setSelectedItem(getModuleClasspathFormat());
181       comboBoxClasspathFormatLabel.setLabelFor(comboBoxClasspathFormat);
182       add(comboBoxClasspathFormat,
183           new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, JBUI.insets(6, 6, 6, 0), 0, 0));
184     }
185
186     private String getSelectedClasspathFormat() {
187       return (String)comboBoxClasspathFormat.getSelectedItem();
188     }
189
190     private String getModuleClasspathFormat() {
191       return ClassPathStorageUtil.getStorageType(myState.getRootModel().getModule());
192     }
193
194     private boolean isModified() {
195       return !getSelectedClasspathFormat().equals(getModuleClasspathFormat());
196     }
197
198     public void canApply() throws ConfigurationException {
199       ClasspathStorageProvider provider = ClasspathStorage.getProvider(getSelectedClasspathFormat());
200       if (provider != null) {
201         provider.assertCompatible(myState.getRootModel());
202       }
203     }
204
205     private void apply() throws ConfigurationException {
206       canApply();
207       ClasspathStorage.setStorageType(myState.getRootModel(), getSelectedClasspathFormat());
208     }
209   }
210
211   public static String getName() {
212     return JavaCompilerBundle.message("modules.classpath.title");
213   }
214 }