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
;
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
) {
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;
120 public String
getId() {
121 return "project.structure";
125 public Runnable
enableSearch(final String option
) {
130 public String
getDisplayName() {
131 return ProjectBundle
.message("project.settings.display.name");
135 public Icon
getIcon() {
136 return IconLoader
.getIcon("/modules/modules.png");
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);
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;
179 private void initSidePanel() {
180 boolean isDefaultProject
= myProject
== ProjectManager
.getInstance().getDefaultProject();
182 mySidePanel
= new SidePanel(this, myHistory
);
183 mySidePanel
.addSeparator("Project Settings");
185 if (!isDefaultProject
) {
188 addProjectLibrariesConfig();
190 if (!isDefaultProject
) {
192 addArtifactsConfig();
194 mySidePanel
.addSeparator("Platform Settings");
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;
243 public void apply() throws ConfigurationException
{
244 for (Configurable each
: myName2Config
) {
245 if (each
.isModified()) {
251 myContext
.myUpdateDependenciesAlarm
.cancelAllRequests();
252 myContext
.myUpdateDependenciesAlarm
.addRequest(new Runnable(){
254 SwingUtilities
.invokeLater(new Runnable(){
256 if (myWasUiDisposed
) return;
265 public void reset() {
266 myWasUiDisposed
= false;
270 myProjectJdksModel
.reset(myProject
);
272 Configurable toSelect
= null;
273 for (Configurable each
: myName2Config
) {
274 if (myUiState
.lastEditedConfigurable
!= null && myUiState
.lastEditedConfigurable
.equals(each
.getDisplayName())) {
277 if (each
instanceof MasterDetailsComponent
) {
278 ((MasterDetailsComponent
)each
).setHistory(myHistory
);
285 if (toSelect
== null && myName2Config
.size() > 0) {
286 toSelect
= myName2Config
.iterator().next();
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() {
324 public void setHistory(final History 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();
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
;
424 UIUtil
.requestFocus(toFocus
);
428 final ActionCallback result
= new ActionCallback();
429 Place
.goFurther(toSelect
, place
, requestFocus
).notifyWhenDone(result
);
431 myDetails
.revalidate();
434 if (toSelect
!= null) {
435 mySidePanel
.select(createPlaceFor(toSelect
));
438 if (!myHistory
.isNavigatingNow() && mySelectedConfigurable
!= null) {
439 myHistory
.pushQueryPlace();
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() {
502 private class MyPanel
extends JPanel
implements DataProvider
{
504 super(new BorderLayout());
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
)) {
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
;
527 return myGlobalLibrariesConfig
;
531 public JComponent
getPreferredFocusedComponent() {