migrated to artifacts
[fedora-idea.git] / java / idea-ui / src / com / intellij / openapi / roots / ui / configuration / ProjectStructureConfigurable.java
blob069fb2bb004ed75361be05de63a6cf83df5f3cda
1 package com.intellij.openapi.roots.ui.configuration;
3 import com.intellij.facet.Facet;
4 import com.intellij.ide.util.PropertiesComponent;
5 import com.intellij.openapi.actionSystem.*;
6 import com.intellij.openapi.module.Module;
7 import com.intellij.openapi.module.ModuleManager;
8 import com.intellij.openapi.options.*;
9 import com.intellij.openapi.project.Project;
10 import com.intellij.openapi.project.ProjectBundle;
11 import com.intellij.openapi.project.ProjectManager;
12 import com.intellij.openapi.projectRoots.Sdk;
13 import com.intellij.openapi.roots.LibraryOrderEntry;
14 import com.intellij.openapi.roots.libraries.Library;
15 import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
16 import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactsStructureConfigurable;
17 import com.intellij.openapi.roots.ui.configuration.projectRoot.*;
18 import com.intellij.openapi.ui.DetailsComponent;
19 import com.intellij.openapi.ui.MasterDetailsComponent;
20 import com.intellij.openapi.ui.Splitter;
21 import com.intellij.openapi.util.ActionCallback;
22 import com.intellij.openapi.util.IconLoader;
23 import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
24 import com.intellij.packaging.artifacts.Artifact;
25 import com.intellij.ui.components.panels.Wrapper;
26 import com.intellij.ui.navigation.BackAction;
27 import com.intellij.ui.navigation.ForwardAction;
28 import com.intellij.ui.navigation.History;
29 import com.intellij.ui.navigation.Place;
30 import com.intellij.util.ui.UIUtil;
31 import org.jetbrains.annotations.Nls;
32 import org.jetbrains.annotations.NonNls;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
36 import javax.swing.*;
37 import java.awt.*;
38 import java.util.ArrayList;
39 import java.util.List;
41 public class ProjectStructureConfigurable extends BaseConfigurable implements SearchableConfigurable, Place.Navigator {
43 public static final DataKey<ProjectStructureConfigurable> KEY = DataKey.create("ProjectStructureConfiguration");
45 private final UIState myUiState = new UIState();
46 private Splitter mySplitter;
47 private JComponent myToolbarComponent;
48 @NonNls private static final String CATEGORY = "category";
49 private JComponent myToFocus;
50 private boolean myWasUiDisposed;
52 public static class UIState {
53 public float proportion;
54 public float sideProportion;
56 public String lastEditedConfigurable;
59 private final Project myProject;
60 private final ModuleManager myModuleManager;
61 private final FacetStructureConfigurable myFacetStructureConfigurable;
62 private final ArtifactsStructureConfigurable myArtifactsStructureConfigurable;
64 private History myHistory = new History(this);
65 private SidePanel mySidePanel;
67 private JPanel myComponent;
68 private final Wrapper myDetails = new Wrapper();
70 private Configurable mySelectedConfigurable;
72 private final ProjectJdksModel myProjectJdksModel = new ProjectJdksModel();
74 private ProjectConfigurable myProjectConfig;
75 private final ProjectLibrariesConfigurable myProjectLibrariesConfig;
76 private final GlobalLibrariesConfigurable myGlobalLibrariesConfig;
77 private ModuleStructureConfigurable myModulesConfig;
79 private boolean myWasIntialized;
81 private final List<Configurable> myName2Config = new ArrayList<Configurable>();
82 private final StructureConfigurableContext myContext;
83 private final ModulesConfigurator myModuleConfigurator;
84 private JdkListConfigurable myJdkListConfig;
86 private final JLabel myEmptySelection = new JLabel("<html><body><center>Select a setting to view or edit its details here</center></body></html>", JLabel.CENTER);
88 public ProjectStructureConfigurable(final Project project, final ModuleManager moduleManager, final ProjectLibrariesConfigurable projectLibrariesConfigurable,
89 final GlobalLibrariesConfigurable globalLibrariesConfigurable,
90 final ModuleStructureConfigurable moduleStructureConfigurable,
91 FacetStructureConfigurable facetStructureConfigurable,
92 ArtifactsStructureConfigurable artifactsStructureConfigurable) {
93 myProject = project;
94 myModuleManager = moduleManager;
95 myFacetStructureConfigurable = facetStructureConfigurable;
96 myArtifactsStructureConfigurable = artifactsStructureConfigurable;
98 myModuleConfigurator = new ModulesConfigurator(myProject, myProjectJdksModel);
99 myContext = new StructureConfigurableContext(myProject, myModuleManager, myModuleConfigurator);
100 myModuleConfigurator.setContext(myContext);
102 myProjectLibrariesConfig = projectLibrariesConfigurable;
103 myGlobalLibrariesConfig = globalLibrariesConfigurable;
104 myModulesConfig = moduleStructureConfigurable;
105 myProjectLibrariesConfig.init(myContext);
106 myGlobalLibrariesConfig.init(myContext);
107 myModulesConfig.init(myContext);
108 myFacetStructureConfigurable.init(myContext);
109 myArtifactsStructureConfigurable.init(myContext);
111 final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(myProject);
112 myUiState.lastEditedConfigurable = propertiesComponent.getValue("project.structure.last.edited");
113 final String proportion = propertiesComponent.getValue("project.structure.proportion");
114 myUiState.proportion = proportion != null ? Float.parseFloat(proportion) : 0;
115 final String sideProportion = propertiesComponent.getValue("project.structure.side.proportion");
116 myUiState.sideProportion = sideProportion != null ? Float.parseFloat(sideProportion) : 0;
119 @NonNls
120 public String getId() {
121 return "project.structure";
124 @Nullable
125 public Runnable enableSearch(final String option) {
126 return null;
129 @Nls
130 public String getDisplayName() {
131 return ProjectBundle.message("project.settings.display.name");
134 @Nullable
135 public Icon getIcon() {
136 return IconLoader.getIcon("/modules/modules.png");
139 @Nullable
140 @NonNls
141 public String getHelpTopic() {
142 return mySelectedConfigurable != null ? mySelectedConfigurable.getHelpTopic() : "";
145 public JComponent createComponent() {
146 myComponent = new MyPanel();
148 mySplitter = new Splitter(false, .15f);
149 mySplitter.setHonorComponentsMinimumSize(true);
151 initSidePanel();
153 final JPanel left = new JPanel(new BorderLayout()) {
154 public Dimension getMinimumSize() {
155 final Dimension original = super.getMinimumSize();
156 return new Dimension(Math.max(original.width, 100), original.height);
160 final DefaultActionGroup toolbarGroup = new DefaultActionGroup();
161 toolbarGroup.add(new BackAction(myComponent));
162 toolbarGroup.add(new ForwardAction(myComponent));
163 final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarGroup, true);
164 toolbar.setTargetComponent(myComponent);
165 myToolbarComponent = toolbar.getComponent();
166 left.add(myToolbarComponent, BorderLayout.NORTH);
167 left.add(mySidePanel, BorderLayout.CENTER);
169 mySplitter.setFirstComponent(left);
170 mySplitter.setSecondComponent(myDetails);
172 myComponent.add(mySplitter, BorderLayout.CENTER);
174 myWasIntialized = true;
176 return myComponent;
179 private void initSidePanel() {
180 boolean isDefaultProject = myProject == ProjectManager.getInstance().getDefaultProject();
182 mySidePanel = new SidePanel(this, myHistory);
183 mySidePanel.addSeparator("Project Settings");
184 addProjectConfig();
185 if (!isDefaultProject) {
186 addModulesConfig();
188 addProjectLibrariesConfig();
190 if (!isDefaultProject) {
191 addFacetsConfig();
192 addArtifactsConfig();
194 mySidePanel.addSeparator("Platform Settings");
195 addJdkListConfig();
196 addGlobalLibrariesConfig();
199 private void addArtifactsConfig() {
200 addConfigurable(myArtifactsStructureConfigurable);
203 public ArtifactsStructureConfigurable getArtifactsStructureConfigurable() {
204 return myArtifactsStructureConfigurable;
207 private void addFacetsConfig() {
208 addConfigurable(myFacetStructureConfigurable);
211 private void addJdkListConfig() {
212 myJdkListConfig = JdkListConfigurable.getInstance(myProject);
213 myJdkListConfig.init(myContext);
214 addConfigurable(myJdkListConfig);
217 private void addProjectConfig() {
218 myProjectConfig = new ProjectConfigurable(myProject, myModuleConfigurator, myProjectJdksModel);
219 addConfigurable(myProjectConfig);
222 private void addProjectLibrariesConfig() {
223 addConfigurable(myProjectLibrariesConfig);
226 private void addGlobalLibrariesConfig() {
227 addConfigurable(myGlobalLibrariesConfig);
230 private void addModulesConfig() {
231 myModulesConfig = ModuleStructureConfigurable.getInstance(myProject);
232 addConfigurable(myModulesConfig);
235 public boolean isModified() {
236 for (Configurable each : myName2Config) {
237 if (each.isModified()) return true;
240 return false;
243 public void apply() throws ConfigurationException {
244 for (Configurable each : myName2Config) {
245 if (each.isModified()) {
246 each.apply();
250 //cleanup
251 myContext.myUpdateDependenciesAlarm.cancelAllRequests();
252 myContext.myUpdateDependenciesAlarm.addRequest(new Runnable(){
253 public void run() {
254 SwingUtilities.invokeLater(new Runnable(){
255 public void run() {
256 if (myWasUiDisposed) return;
257 reset();
261 }, 0);
265 public void reset() {
266 myWasUiDisposed = false;
268 myContext.reset();
270 myProjectJdksModel.reset(myProject);
272 Configurable toSelect = null;
273 for (Configurable each : myName2Config) {
274 if (myUiState.lastEditedConfigurable != null && myUiState.lastEditedConfigurable.equals(each.getDisplayName())) {
275 toSelect = each;
277 if (each instanceof MasterDetailsComponent) {
278 ((MasterDetailsComponent)each).setHistory(myHistory);
280 each.reset();
283 myHistory.clear();
285 if (toSelect == null && myName2Config.size() > 0) {
286 toSelect = myName2Config.iterator().next();
289 removeSelected();
291 navigateTo(toSelect != null ? createPlaceFor(toSelect) : null, false);
293 if (myUiState.proportion > 0) {
294 mySplitter.setProportion(myUiState.proportion);
298 public void disposeUIResources() {
299 if (!myWasIntialized) return;
300 final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(myProject);
301 propertiesComponent.setValue("project.structure.last.edited", myUiState.lastEditedConfigurable);
302 propertiesComponent.setValue("project.structure.proportion", String.valueOf(myUiState.proportion));
303 propertiesComponent.setValue("project.structure.side.proportion", String.valueOf(myUiState.sideProportion));
305 myWasUiDisposed = true;
307 myUiState.proportion = mySplitter.getProportion();
308 saveSideProportion();
310 for (Configurable each : myName2Config) {
311 each.disposeUIResources();
314 myName2Config.clear();
316 myModuleConfigurator.getFacetsConfigurator().clearMaps();
317 myWasIntialized = false;
320 public History getHistory() {
321 return myHistory;
324 public void setHistory(final History history) {
325 myHistory = history;
328 public void queryPlace(@NotNull final Place place) {
329 place.putPath(CATEGORY, mySelectedConfigurable);
330 Place.queryFurther(mySelectedConfigurable, place);
333 public ActionCallback select(@Nullable final String moduleToSelect, String tab, final boolean requestFocus) {
334 Place place = new Place().putPath(CATEGORY, myModulesConfig);
335 if (moduleToSelect != null) {
336 final Module module = ModuleManager.getInstance(myProject).findModuleByName(moduleToSelect);
337 assert module != null;
338 place = place.putPath(ModuleStructureConfigurable.TREE_OBJECT, module);
340 return navigateTo(place, requestFocus);
343 public ActionCallback select(@Nullable final Facet facetToSelect, final boolean requestFocus) {
344 Place place = new Place().putPath(CATEGORY, myModulesConfig);
345 if (facetToSelect != null) {
346 place = place.putPath(ModuleStructureConfigurable.TREE_OBJECT, facetToSelect);
348 return navigateTo(place, requestFocus);
351 public ActionCallback select(@NotNull Sdk sdk, final boolean requestFocus) {
352 Place place = new Place().putPath(CATEGORY, myJdkListConfig);
353 place.putPath(BaseStructureConfigurable.TREE_NAME, sdk.getName());
354 return navigateTo(place, requestFocus);
357 public ActionCallback selectProjectOrGlobalLibrary(@NotNull Library library, boolean requestFocus) {
358 Place place = new Place().putPath(CATEGORY, getConfigurableFor(library));
359 place.putPath(BaseStructureConfigurable.TREE_NAME, library.getName());
360 return navigateTo(place, requestFocus);
363 public ActionCallback select(@Nullable Artifact artifact, boolean requestFocus) {
364 Place place = new Place().putPath(CATEGORY, myArtifactsStructureConfigurable);
365 if (artifact != null) {
366 place.putPath(BaseStructureConfigurable.TREE_NAME, artifact.getName());
368 return navigateTo(place, requestFocus);
371 public ActionCallback select(@NotNull LibraryOrderEntry libraryOrderEntry, final boolean requestFocus) {
372 final Library lib = libraryOrderEntry.getLibrary();
373 if (lib != null && lib.getTable() == null) {
374 Place place = new Place().putPath(CATEGORY, myModulesConfig);
375 place.putPath(BaseStructureConfigurable.TREE_OBJECT, libraryOrderEntry.getOwnerModule());
376 return navigateTo(place, requestFocus);
378 Place place = new Place().putPath(CATEGORY, getConfigurableFor(lib));
379 place.putPath(BaseStructureConfigurable.TREE_NAME, libraryOrderEntry.getLibraryName());
380 return navigateTo(place, requestFocus);
383 public ActionCallback navigateTo(@Nullable final Place place, final boolean requestFocus) {
384 final Configurable toSelect = (Configurable)place.getPath(CATEGORY);
386 JComponent detailsContent = myDetails.getTargetComponent();
388 if (mySelectedConfigurable != toSelect) {
389 saveSideProportion();
390 removeSelected();
392 if (toSelect != null) {
393 detailsContent = toSelect.createComponent();
394 myDetails.setContent(detailsContent);
397 mySelectedConfigurable = toSelect;
398 if (mySelectedConfigurable != null) {
399 myUiState.lastEditedConfigurable = mySelectedConfigurable.getDisplayName();
402 if (toSelect instanceof MasterDetailsComponent) {
403 final MasterDetailsComponent masterDetails = (MasterDetailsComponent)toSelect;
404 if (myUiState.sideProportion > 0) {
405 masterDetails.getSplitter().setProportion(myUiState.sideProportion);
407 masterDetails.setHistory(myHistory);
410 if (toSelect instanceof DetailsComponent.Facade) {
411 ((DetailsComponent.Facade)toSelect).getDetailsComponent().setBannerMinHeight(myToolbarComponent.getPreferredSize().height);
417 if (detailsContent != null) {
418 JComponent toFocus = IdeFocusTraversalPolicy.getPreferredFocusedComponent(detailsContent);
419 if (toFocus == null) {
420 toFocus = detailsContent;
422 if (requestFocus) {
423 myToFocus = toFocus;
424 UIUtil.requestFocus(toFocus);
428 final ActionCallback result = new ActionCallback();
429 Place.goFurther(toSelect, place, requestFocus).notifyWhenDone(result);
431 myDetails.revalidate();
432 myDetails.repaint();
434 if (toSelect != null) {
435 mySidePanel.select(createPlaceFor(toSelect));
438 if (!myHistory.isNavigatingNow() && mySelectedConfigurable != null) {
439 myHistory.pushQueryPlace();
442 return result;
445 private void saveSideProportion() {
446 if (mySelectedConfigurable instanceof MasterDetailsComponent) {
447 myUiState.sideProportion = ((MasterDetailsComponent)mySelectedConfigurable).getSplitter().getProportion();
451 private void removeSelected() {
452 myDetails.removeAll();
453 mySelectedConfigurable = null;
454 myUiState.lastEditedConfigurable = null;
456 myDetails.add(myEmptySelection, BorderLayout.CENTER);
459 public static ProjectStructureConfigurable getInstance(final Project project) {
460 return ShowSettingsUtil.getInstance().findProjectConfigurable(project, ProjectStructureConfigurable.class);
463 public ProjectJdksModel getProjectJdksModel() {
464 return myProjectJdksModel;
467 public JdkListConfigurable getJdkConfig() {
468 return myJdkListConfig;
471 public ProjectLibrariesConfigurable getProjectLibrariesConfig() {
472 return myProjectLibrariesConfig;
475 public GlobalLibrariesConfigurable getGlobalLibrariesConfig() {
476 return myGlobalLibrariesConfig;
479 public ModuleStructureConfigurable getModulesConfig() {
480 return myModulesConfig;
483 public ProjectConfigurable getProjectConfig() {
484 return myProjectConfig;
487 private void addConfigurable(Configurable configurable) {
488 myName2Config.add(configurable);
490 mySidePanel.addPlace(createPlaceFor(configurable), new Presentation(configurable.getDisplayName()));
493 private static Place createPlaceFor(final Configurable configurable) {
494 return new Place().putPath(CATEGORY, configurable);
498 public StructureConfigurableContext getContext() {
499 return myContext;
502 private class MyPanel extends JPanel implements DataProvider {
503 public MyPanel() {
504 super(new BorderLayout());
507 @Nullable
508 public Object getData(@NonNls final String dataId) {
509 if (KEY.getName().equals(dataId)) {
510 return ProjectStructureConfigurable.this;
511 } else if (History.KEY.getName().equals(dataId)) {
512 return getHistory();
513 } else {
514 return null;
518 public Dimension getPreferredSize() {
519 return new Dimension(1024, 768);
523 public BaseLibrariesConfigurable getConfigurableFor(final Library library) {
524 if (LibraryTablesRegistrar.PROJECT_LEVEL.equals(library.getTable().getTableLevel())) {
525 return myProjectLibrariesConfig;
526 } else {
527 return myGlobalLibrariesConfig;
531 public JComponent getPreferredFocusedComponent() {
532 return myToFocus;