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