refactoring to remove duplicated code from project structure configurables in RubyMine and Web IDE; project structure configurable in PyCharm

This commit is contained in:
Dmitry Jemerov
2010-01-13 22:32:05 +03:00
parent 9c22c65583
commit 1ef6f65bc8
9 changed files with 224 additions and 103 deletions
@@ -41,7 +41,7 @@ import java.util.Map;
public class JavaContentEntriesEditor extends CommonContentEntriesEditor {
public JavaContentEntriesEditor(String moduleName, ModuleConfigurationState state) {
super(moduleName, state);
super(moduleName, state, true, true);
}
protected ContentEntryEditor createContentEntryEditor(final String contentEntryUrl) {
@@ -54,7 +54,7 @@ public class JavaContentEntriesEditor extends CommonContentEntriesEditor {
}
protected ContentEntryTreeEditor createContentEntryTreeEditor(Project project) {
return new JavaContentEntryTreeEditor(project);
return new ContentEntryTreeEditor(project, true, true);
}
@Override
@@ -26,7 +26,7 @@ public abstract class JavaContentEntryEditor extends ContentEntryEditor {
private final CompilerModuleExtension myCompilerExtension;
public JavaContentEntryEditor(final String contentEntryUrl) {
super(contentEntryUrl);
super(contentEntryUrl, true, true);
myCompilerExtension = getModel().getModuleExtension(CompilerModuleExtension.class);
}
@@ -1,41 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.roots.ui.configuration;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.actions.ToggleExcludedStateAction;
import com.intellij.openapi.roots.ui.configuration.actions.ToggleSourcesStateAction;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import javax.swing.*;
import java.awt.event.KeyEvent;
public class JavaContentEntryTreeEditor extends ContentEntryTreeEditor {
public JavaContentEntryTreeEditor(Project project) {
super(project);
}
@Override
protected void createEditingActions() {
ToggleSourcesStateAction markSourcesAction = new ToggleSourcesStateAction(myTree, this, false);
markSourcesAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.ALT_MASK)), myTree);
setupExcludedAction();
setupTestsAction();
myEditingActionsGroup.add(markSourcesAction);
}
}
@@ -17,26 +17,21 @@ package com.intellij.openapi.roots.ui.configuration;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ContentFolder;
import com.intellij.openapi.roots.ExcludeFolder;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.roots.IconActionComponent;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public abstract class JavaContentRootPanel extends ContentRootPanel {
private static final Color SOURCES_COLOR = new Color(0x0A50A1);
private static final Icon ADD_PREFIX_ICON = IconLoader.getIcon("/modules/setPackagePrefix.png");
private static final Icon ADD_PREFIX_ROLLOVER_ICON = IconLoader.getIcon("/modules/setPackagePrefixRollover.png");
public JavaContentRootPanel(ActionCallback callback) {
super(callback);
super(callback, true, true);
}
@Nullable
@@ -66,46 +61,4 @@ public abstract class JavaContentRootPanel extends ContentRootPanel {
panel.add(Box.createHorizontalStrut(3), BorderLayout.EAST);
return panel;
}
protected void addFolderGroupComponents() {
final List<ContentFolder> sources = new ArrayList<ContentFolder>();
final List<ContentFolder> testSources = new ArrayList<ContentFolder>();
final List<ContentFolder> excluded = new ArrayList<ContentFolder>();
final SourceFolder[] sourceFolders = getContentEntry().getSourceFolders();
for (SourceFolder folder : sourceFolders) {
if (folder.isSynthetic()) {
continue;
}
final VirtualFile folderFile = folder.getFile();
if (folderFile != null && (isExcluded(folderFile) || isUnderExcludedDirectory(folderFile))) {
continue;
}
if (folder.isTestSource()) {
testSources.add(folder);
}
else {
sources.add(folder);
}
}
final ExcludeFolder[] excludeFolders = getContentEntry().getExcludeFolders();
for (final ExcludeFolder excludeFolder : excludeFolders) {
if (!excludeFolder.isSynthetic()) {
excluded.add(excludeFolder);
}
}
if (sources.size() > 0) {
final JComponent sourcesComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.sources.group"), sources.toArray(new ContentFolder[sources.size()]), SOURCES_COLOR);
this.add(sourcesComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0));
}
if (testSources.size() > 0) {
final JComponent testSourcesComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.test.sources.group"), testSources.toArray(new ContentFolder[testSources.size()]), TESTS_COLOR);
this.add(testSourcesComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0));
}
if (excluded.size() > 0) {
final JComponent excludedComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.excluded.group"), excluded.toArray(new ContentFolder[excluded.size()]), EXCLUDED_COLOR);
this.add(excludedComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0));
}
}
}
@@ -28,8 +28,8 @@ import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
import com.intellij.openapi.roots.ui.componentsList.layout.VerticalStackLayout;
import com.intellij.openapi.roots.ui.configuration.actions.IconWithTextAction;
@@ -59,7 +59,7 @@ import java.util.Map;
* Date: Oct 4, 2003
* Time: 6:54:57 PM
*/
public abstract class CommonContentEntriesEditor extends ModuleElementsEditor {
public class CommonContentEntriesEditor extends ModuleElementsEditor {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.ContentEntriesEditor");
public static final String NAME = ProjectBundle.message("module.paths.title");
public static final Icon ICON = IconLoader.getIcon("/modules/sources.png");
@@ -76,11 +76,15 @@ public abstract class CommonContentEntriesEditor extends ModuleElementsEditor {
private final String myModuleName;
private final ModulesProvider myModulesProvider;
private final ModuleConfigurationState myState;
private final boolean myCanMarkSources;
private final boolean myCanMarkTestSources;
public CommonContentEntriesEditor(String moduleName, ModuleConfigurationState state) {
public CommonContentEntriesEditor(String moduleName, ModuleConfigurationState state, boolean canMarkSources, boolean canMarkTestSources) {
super(state);
myState = state;
myModuleName = moduleName;
myCanMarkSources = canMarkSources;
myCanMarkTestSources = canMarkTestSources;
myModulesProvider = state.getModulesProvider();
final VirtualFileManagerAdapter fileManagerListener = new VirtualFileManagerAdapter() {
public void afterRefreshFinish(boolean asynchronous) {
@@ -183,7 +187,9 @@ public abstract class CommonContentEntriesEditor extends ModuleElementsEditor {
return null;
}
protected abstract ContentEntryTreeEditor createContentEntryTreeEditor(Project project);
protected ContentEntryTreeEditor createContentEntryTreeEditor(Project project) {
return new ContentEntryTreeEditor(project, myCanMarkSources, myCanMarkTestSources);
}
protected void addAdditionalSettingsToPanel(final JPanel mainPanel) {
}
@@ -212,7 +218,14 @@ public abstract class CommonContentEntriesEditor extends ModuleElementsEditor {
myEditorsPanel.add(component);
}
protected abstract ContentEntryEditor createContentEntryEditor(String contentEntryUrl);
protected ContentEntryEditor createContentEntryEditor(String contentEntryUrl) {
return new ContentEntryEditor(contentEntryUrl, myCanMarkSources, myCanMarkTestSources) {
@Override
protected ModifiableRootModel getModel() {
return CommonContentEntriesEditor.this.getModel();
}
};
}
void selectContentEntry(final String contentEntryUrl) {
if (mySelectedEntryUrl != null && mySelectedEntryUrl.equals(contentEntryUrl)) {
@@ -44,6 +44,8 @@ public abstract class ContentEntryEditor implements ContentRootPanel.ActionCallb
private JPanel myMainPanel;
protected EventDispatcher<ContentEntryEditorListener> myEventDispatcher;
private String myContentEntryUrl;
protected final boolean myCanMarkSources;
protected final boolean myCanMarkTestSources;
public interface ContentEntryEditorListener extends EventListener{
void editingStarted(ContentEntryEditor editor);
@@ -56,8 +58,10 @@ public abstract class ContentEntryEditor implements ContentRootPanel.ActionCallb
void packagePrefixSet(ContentEntryEditor editor, SourceFolder folder);
}
public ContentEntryEditor(final String contentEntryUrl) {
public ContentEntryEditor(final String contentEntryUrl, boolean canMarkSources, boolean canMarkTestSources) {
myContentEntryUrl = contentEntryUrl;
myCanMarkSources = canMarkSources;
myCanMarkTestSources = canMarkTestSources;
}
public String getContentEntryUrl() {
@@ -171,7 +175,14 @@ public abstract class ContentEntryEditor implements ContentRootPanel.ActionCallb
myMainPanel.revalidate();
}
protected abstract ContentRootPanel createContentRootPane();
protected ContentRootPanel createContentRootPane() {
return new ContentRootPanel(this, myCanMarkSources, myCanMarkTestSources) {
@Override
protected ContentEntry getContentEntry() {
return ContentEntryEditor.this.getContentEntry();
}
};
}
@Nullable
public SourceFolder addSourceFolder(VirtualFile file, boolean isTestSource) {
@@ -61,8 +61,10 @@ import java.util.Comparator;
* Date: Oct 9, 2003
* Time: 1:19:47 PM
*/
public abstract class ContentEntryTreeEditor {
public class ContentEntryTreeEditor {
private final Project myProject;
private final boolean myCanMarkSources;
private final boolean myCanMarkTestSources;
protected Tree myTree;
private FileSystemTreeImpl myFileSystemTree;
private final JPanel myTreePanel;
@@ -72,8 +74,10 @@ public abstract class ContentEntryTreeEditor {
private final MyContentEntryEditorListener myContentEntryEditorListener = new MyContentEntryEditorListener();
private final FileChooserDescriptor myDescriptor;
public ContentEntryTreeEditor(Project project) {
public ContentEntryTreeEditor(Project project, boolean canMarkSources, boolean canMarkTestSources) {
myProject = project;
myCanMarkSources = canMarkSources;
myCanMarkTestSources = canMarkTestSources;
myTree = new Tree();
myTree.setRootVisible(true);
myTree.setShowsRootHandles(true);
@@ -94,6 +98,17 @@ public abstract class ContentEntryTreeEditor {
}
protected void createEditingActions() {
if (myCanMarkSources) {
ToggleSourcesStateAction markSourcesAction = new ToggleSourcesStateAction(myTree, this, false);
markSourcesAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.ALT_MASK)), myTree);
myEditingActionsGroup.add(markSourcesAction);
}
if (myCanMarkTestSources) {
setupTestsAction();
}
setupExcludedAction();
}
protected TreeCellRenderer getContentEntryCellRenderer() {
@@ -41,7 +41,9 @@ import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@@ -49,6 +51,7 @@ import java.util.Map;
* Date: Jan 19, 2004
*/
public abstract class ContentRootPanel extends JPanel {
protected static final Color SOURCES_COLOR = new Color(0x0A50A1);
protected static final Color TESTS_COLOR = new Color(0x008C2E);
protected static final Color EXCLUDED_COLOR = new Color(0x992E00);
private static final Color SELECTED_HEADER_COLOR = new Color(0xDEF2FF);
@@ -66,6 +69,8 @@ public abstract class ContentRootPanel extends JPanel {
private JComponent myHeader;
private JComponent myBottom;
private final Map<JComponent, Color> myComponentToForegroundMap = new HashMap<JComponent, Color>();
private final boolean myCanMarkSources;
private final boolean myCanMarkTestSources;
public interface ActionCallback {
void deleteContentEntry();
@@ -74,9 +79,11 @@ public abstract class ContentRootPanel extends JPanel {
void setPackagePrefix(SourceFolder folder, String prefix);
}
public ContentRootPanel(ActionCallback callback) {
public ContentRootPanel(ActionCallback callback, boolean canMarkSources, boolean canMarkTestSources) {
super(new GridBagLayout());
myCallback = callback;
myCanMarkSources = canMarkSources;
myCanMarkTestSources = canMarkTestSources;
}
@Nullable
@@ -95,7 +102,48 @@ public abstract class ContentRootPanel extends JPanel {
setSelected(false);
}
protected abstract void addFolderGroupComponents();
protected void addFolderGroupComponents() {
final List<ContentFolder> sources = new ArrayList<ContentFolder>();
final List<ContentFolder> testSources = new ArrayList<ContentFolder>();
final List<ContentFolder> excluded = new ArrayList<ContentFolder>();
final SourceFolder[] sourceFolders = getContentEntry().getSourceFolders();
for (SourceFolder folder : sourceFolders) {
if (folder.isSynthetic()) {
continue;
}
final VirtualFile folderFile = folder.getFile();
if (folderFile != null && (isExcluded(folderFile) || isUnderExcludedDirectory(folderFile))) {
continue;
}
if (folder.isTestSource()) {
testSources.add(folder);
}
else {
sources.add(folder);
}
}
final ExcludeFolder[] excludeFolders = getContentEntry().getExcludeFolders();
for (final ExcludeFolder excludeFolder : excludeFolders) {
if (!excludeFolder.isSynthetic()) {
excluded.add(excludeFolder);
}
}
if (sources.size() > 0 && myCanMarkSources) {
final JComponent sourcesComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.sources.group"), sources.toArray(new ContentFolder[sources.size()]),
SOURCES_COLOR);
this.add(sourcesComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0));
}
if (testSources.size() > 0 && myCanMarkTestSources) {
final JComponent testSourcesComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.test.sources.group"), testSources.toArray(new ContentFolder[testSources.size()]), TESTS_COLOR);
this.add(testSourcesComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0));
}
if (excluded.size() > 0) {
final JComponent excludedComponent = createFolderGroupComponent(ProjectBundle.message("module.paths.excluded.group"), excluded.toArray(new ContentFolder[excluded.size()]), EXCLUDED_COLOR);
this.add(excludedComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0));
}
}
private JComponent createHeader() {
final JPanel panel = new JPanel(new GridBagLayout());
@@ -0,0 +1,122 @@
package com.intellij.openapi.roots.ui.configuration;
import com.intellij.facet.impl.DefaultFacetsProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.impl.ModuleConfigurationStateImpl;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import javax.swing.*;
import java.awt.*;
import java.util.List;
/**
* @author yole
*/
public class PlatformContentEntriesConfigurable implements Configurable {
private final Module myModule;
private final boolean myCanMarkSources;
private final boolean myCanMarkTestSources;
private final JPanel myTopPanel = new JPanel(new BorderLayout());
private ModifiableRootModel myModifiableModel;
private CommonContentEntriesEditor myEditor;
public PlatformContentEntriesConfigurable(final Module module, boolean canMarkSources, boolean canMarkTestSources) {
myModule = module;
myCanMarkSources = canMarkSources;
myCanMarkTestSources = canMarkTestSources;
}
public String getDisplayName() {
return "Project Structure";
}
public Icon getIcon() {
return null;
}
public String getHelpTopic() {
return null;
}
public JComponent createComponent() {
createEditor();
return myTopPanel;
}
private void createEditor() {
myModifiableModel = ApplicationManager.getApplication().runReadAction(new Computable<ModifiableRootModel>() {
public ModifiableRootModel compute() {
return ModuleRootManager.getInstance(myModule).getModifiableModel();
}
});
final ModuleConfigurationStateImpl moduleConfigurationState =
new ModuleConfigurationStateImpl(myModule.getProject(), new DefaultModulesProvider(myModule.getProject())) {
@Override
public ModifiableRootModel getRootModel() {
return myModifiableModel;
}
@Override
public FacetsProvider getFacetsProvider() {
return DefaultFacetsProvider.INSTANCE;
}
};
myEditor = new CommonContentEntriesEditor(myModule.getName(), moduleConfigurationState, myCanMarkSources, myCanMarkTestSources) {
@Override
protected List<ContentEntry> addContentEntries(VirtualFile[] files) {
List<ContentEntry> entries = super.addContentEntries(files);
addContentEntryPanels(entries.toArray(new ContentEntry[entries.size()]));
return entries;
}
};
JComponent component = ApplicationManager.getApplication().runReadAction(new Computable<JComponent>() {
public JComponent compute() {
return myEditor.createComponent();
}
});
myTopPanel.add(component, BorderLayout.CENTER);
}
public boolean isModified() {
return myEditor.isModified();
}
public void apply() throws ConfigurationException {
myEditor.apply();
if (myModifiableModel.isChanged()) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
myModifiableModel.commit();
}
});
myEditor.disposeUIResources();
myTopPanel.remove(myEditor.getComponent());
createEditor();
}
}
public void reset() {
myEditor.reset();
// TODO?
}
public void disposeUIResources() {
if (myEditor != null) {
myEditor.disposeUIResources();
myTopPanel.remove(myEditor.getComponent());
myEditor = null;
}
if (myModifiableModel != null) {
myModifiableModel.dispose();
myModifiableModel = null;
}
}
}