be7e3b84a59e4dc36ce3aa6e167e7bd5c14fe1a3
[idea/community.git] / platform / lang-impl / src / com / intellij / application / options / ModuleAwareProjectConfigurable.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
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.application.options;
17
18 import com.intellij.openapi.module.Module;
19 import com.intellij.openapi.options.Configurable;
20 import com.intellij.openapi.options.ConfigurationException;
21 import com.intellij.openapi.options.SearchableConfigurable;
22 import com.intellij.openapi.options.UnnamedConfigurable;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.ui.Splitter;
25 import com.intellij.openapi.util.Condition;
26 import com.intellij.platform.ModuleAttachProcessor;
27 import com.intellij.ui.CollectionListModel;
28 import com.intellij.ui.ListSpeedSearch;
29 import com.intellij.ui.components.JBList;
30 import com.intellij.ui.components.JBScrollPane;
31 import com.intellij.util.Function;
32 import com.intellij.util.containers.ContainerUtil;
33 import org.jetbrains.annotations.Nls;
34 import org.jetbrains.annotations.NotNull;
35 import org.jetbrains.annotations.Nullable;
36
37 import javax.swing.*;
38 import javax.swing.event.ListSelectionEvent;
39 import javax.swing.event.ListSelectionListener;
40 import java.awt.*;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Map;
44
45 /**
46  * @author yole
47  */
48 public abstract class ModuleAwareProjectConfigurable<T extends UnnamedConfigurable> implements SearchableConfigurable,
49                                                                                                Configurable.NoScroll {
50   @NotNull
51   private final Project myProject;
52   private final String myDisplayName;
53   private final String myHelpTopic;
54   private final Map<Module, T> myModuleConfigurables = new HashMap<>();
55
56   public ModuleAwareProjectConfigurable(@NotNull Project project, String displayName, String helpTopic) {
57     myProject = project;
58     myDisplayName = displayName;
59     myHelpTopic = helpTopic;
60   }
61
62   @Nls
63   @Override
64   public String getDisplayName() {
65     return myDisplayName;
66   }
67
68   @Override
69   public String getHelpTopic() {
70     return myHelpTopic;
71   }
72
73   protected boolean isSuitableForModule(@NotNull Module module) {
74     return true;
75   }
76
77   @Override
78   public JComponent createComponent() {
79     if (myProject.isDefault()) {
80       T configurable = createDefaultProjectConfigurable();
81       if (configurable != null) {
82         myModuleConfigurables.put(null, configurable);
83         return configurable.createComponent();
84       }
85     }
86     final List<Module> modules = ContainerUtil.filter(ModuleAttachProcessor.getSortedModules(myProject),
87                                                       module -> isSuitableForModule(module));
88     if (modules.size() == 1) {
89       Module module = modules.get(0);
90       final T configurable = createModuleConfigurable(module);
91       myModuleConfigurables.put(module, configurable);
92       return configurable.createComponent();
93     }
94     final Splitter splitter = new Splitter(false, 0.25f);
95     final JBList moduleList = new JBList(new CollectionListModel<>(modules));
96     new ListSpeedSearch(moduleList, new Function<Object, String>() {
97       @Override
98       public String fun(Object o) {
99         if (o instanceof Module) {
100           return ((Module)o).getName();
101         }
102         return null;
103       }
104     });
105     moduleList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
106     moduleList.setCellRenderer(new ModuleListCellRenderer());
107     splitter.setFirstComponent(new JBScrollPane(moduleList));
108     final CardLayout layout = new CardLayout();
109     final JPanel cardPanel = new JPanel(layout);
110     splitter.setSecondComponent(cardPanel);
111     for (Module module : modules) {
112       final T configurable = createModuleConfigurable(module);
113       myModuleConfigurables.put(module, configurable);
114       final JComponent component = configurable.createComponent();
115       cardPanel.add(component, module.getName());
116     }
117     moduleList.addListSelectionListener(new ListSelectionListener() {
118       @Override
119       public void valueChanged(ListSelectionEvent e) {
120         final Module value = (Module)moduleList.getSelectedValue();
121         layout.show(cardPanel, value.getName());
122       }
123     });
124     if (modules.size() > 0) {
125       moduleList.setSelectedIndex(0);
126       layout.show(cardPanel, modules.get(0).getName());
127     }
128     return splitter;
129   }
130
131   @Nullable
132   protected T createDefaultProjectConfigurable() {
133     return null;
134   }
135
136   @NotNull
137   protected abstract T createModuleConfigurable(Module module);
138
139   @Override
140   public boolean isModified() {
141     for (T configurable : myModuleConfigurables.values()) {
142       if (configurable.isModified()) return true;
143     }
144     return false;
145   }
146
147   @Override
148   public void apply() throws ConfigurationException {
149     for (T configurable : myModuleConfigurables.values()) {
150       configurable.apply();
151     }
152   }
153
154   @Override
155   public void reset() {
156     for (T configurable : myModuleConfigurables.values()) {
157       configurable.reset();
158     }
159   }
160
161   @Override
162   public void disposeUIResources() {
163     for (T configurable : myModuleConfigurables.values()) {
164       configurable.disposeUIResources();
165     }
166     myModuleConfigurables.clear();
167   }
168
169   @NotNull
170   @Override
171   public String getId() {
172     return getClass().getName();
173   }
174
175   @NotNull
176   protected final Project getProject() {
177     return myProject;
178   }
179 }