From 93055338f8f5f0ccce8989338aecf6c5e2ec20d9 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 30 Sep 2015 21:23:28 +0300 Subject: [PATCH] 'Use alternative JRE' option reworked: checkbox removed, it now shows name of default JRE (IDEA-145791), icons and descriptions for JDK items added --- .../execution/applet/AppletConfigurable.form | 2 +- .../execution/applet/AppletConfigurable.java | 15 +- .../application/ApplicationConfigurable.form | 2 +- .../application/ApplicationConfigurable.java | 18 +- .../jar/JarApplicationConfigurable.form | 2 +- .../jar/JarApplicationConfigurable.java | 17 +- .../TestDiscoveryConfigurable.java | 19 +- .../execution/ui/AlternativeJREPanel.java | 2 + .../execution/ui/DefaultJreSelector.kt | 116 ++++++++ .../execution/ui/JreComboboxEditor.java | 64 ++++ .../intellij/execution/ui/JrePathEditor.java | 276 ++++++++++++++++++ .../com/intellij/openapi/util/extensions.kt | 38 +++ .../src/messages/ExecutionBundle.properties | 1 + .../src/run/PluginRunConfigurationEditor.java | 14 +- .../configuration/JUnitConfigurable.form | 2 +- .../configuration/JUnitConfigurable.java | 17 +- .../TestNGConfigurationEditor.form | 2 +- .../TestNGConfigurationEditor.java | 12 +- 18 files changed, 561 insertions(+), 58 deletions(-) create mode 100644 java/execution/impl/src/com/intellij/execution/ui/DefaultJreSelector.kt create mode 100644 java/execution/impl/src/com/intellij/execution/ui/JreComboboxEditor.java create mode 100644 java/execution/impl/src/com/intellij/execution/ui/JrePathEditor.java create mode 100644 platform/platform-impl/src/com/intellij/openapi/util/extensions.kt diff --git a/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurable.form b/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurable.form index decd17c17f37..bf72b5d62644 100644 --- a/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurable.form +++ b/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurable.form @@ -209,7 +209,7 @@ - + diff --git a/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurable.java b/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurable.java index 5e23915c7be3..741dec6024a2 100644 --- a/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurable.java +++ b/java/execution/impl/src/com/intellij/execution/applet/AppletConfigurable.java @@ -18,7 +18,8 @@ package com.intellij.execution.applet; import com.intellij.application.options.ModulesComboBox; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.impl.CheckableRunConfigurationEditor; -import com.intellij.execution.ui.AlternativeJREPanel; +import com.intellij.execution.ui.DefaultJreSelector; +import com.intellij.execution.ui.JrePathEditor; import com.intellij.execution.ui.ClassBrowser; import com.intellij.execution.ui.ConfigurationModuleSelector; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; @@ -64,7 +65,7 @@ public class AppletConfigurable extends SettingsEditor impl private JBLabel myClassNameLabel; private JBLabel myWidthLabel; private JLabel myHeightLabel; - private AlternativeJREPanel myAlternativeJREPanel; + private JrePathEditor myJrePathEditor; private final ButtonGroup myAppletRadioButtonGroup; private JComponent anchor; @@ -116,6 +117,7 @@ public class AppletConfigurable extends SettingsEditor impl myModuleSelector = new ConfigurationModuleSelector(project, getModuleComponent()); + myJrePathEditor.setDefaultJreSelector(DefaultJreSelector.fromModuleDependencies(getModuleComponent(), true)); myTablePlace.setLayout(new BorderLayout()); myParameters = new ListTableModel(PARAMETER_COLUMNS); myTable = new TableView(myParameters); @@ -241,7 +243,8 @@ public class AppletConfigurable extends SettingsEditor impl myParameters.setItems(cloneParameters(Arrays.asList(appletParameters))); } myModuleSelector.reset(configuration); - myAlternativeJREPanel.init(configuration.ALTERNATIVE_JRE_PATH, configuration.ALTERNATIVE_JRE_PATH_ENABLED); + myJrePathEditor + .setPathOrName(configuration.ALTERNATIVE_JRE_PATH, configuration.ALTERNATIVE_JRE_PATH_ENABLED); } private RawCommandLineEditor getVMParametersComponent() { @@ -275,8 +278,8 @@ public class AppletConfigurable extends SettingsEditor impl catch (NumberFormatException e) { } configuration.HTML_USED = myURL.isSelected(); - configuration.ALTERNATIVE_JRE_PATH = myAlternativeJREPanel.getPath(); - configuration.ALTERNATIVE_JRE_PATH_ENABLED = myAlternativeJREPanel.isPathEnabled(); + configuration.ALTERNATIVE_JRE_PATH = myJrePathEditor.getJrePathOrName(); + configuration.ALTERNATIVE_JRE_PATH_ENABLED = myJrePathEditor.isAlternativeJreSelected(); } private void createUIComponents() { @@ -294,7 +297,7 @@ public class AppletConfigurable extends SettingsEditor impl myModule.setAnchor(anchor); myPolicyFile.setAnchor(anchor); myVMParameters.setAnchor(anchor); - myAlternativeJREPanel.setAnchor(anchor); + myJrePathEditor.setAnchor(anchor); myHtmlFileLabel.setAnchor(anchor); } diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.form b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.form index 9803e48deb67..40fd90c71d4a 100644 --- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.form +++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.form @@ -40,7 +40,7 @@ - + diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java index 0f6b641976c5..3b2f95687b8c 100644 --- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java +++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java @@ -19,10 +19,7 @@ import com.intellij.application.options.ModulesComboBox; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.JavaExecutionUtil; import com.intellij.execution.configurations.ConfigurationUtil; -import com.intellij.execution.ui.AlternativeJREPanel; -import com.intellij.execution.ui.ClassBrowser; -import com.intellij.execution.ui.CommonJavaParametersPanel; -import com.intellij.execution.ui.ConfigurationModuleSelector; +import com.intellij.execution.ui.*; import com.intellij.execution.util.JreVersionDetector; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SettingsEditor; @@ -49,7 +46,7 @@ public class ApplicationConfigurable extends SettingsEditor - + diff --git a/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.java b/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.java index 03758cd031cb..d39ea40ece63 100644 --- a/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.java +++ b/java/execution/impl/src/com/intellij/execution/jar/JarApplicationConfigurable.java @@ -16,7 +16,8 @@ package com.intellij.execution.jar; import com.intellij.application.options.ModulesComboBox; -import com.intellij.execution.ui.AlternativeJREPanel; +import com.intellij.execution.ui.DefaultJreSelector; +import com.intellij.execution.ui.JrePathEditor; import com.intellij.execution.ui.CommonJavaParametersPanel; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.options.ConfigurationException; @@ -38,22 +39,23 @@ public class JarApplicationConfigurable extends SettingsEditor myModuleComponent; private JPanel myWholePanel; - private AlternativeJREPanel myAlternativeJREPanel; + private JrePathEditor myJrePathEditor; private final Project myProject; private JComponent myAnchor; public JarApplicationConfigurable(final Project project) { myProject = project; - myAnchor = UIUtil.mergeComponentsWithAnchor(myJarPathComponent, myCommonProgramParameters, myAlternativeJREPanel); + myAnchor = UIUtil.mergeComponentsWithAnchor(myJarPathComponent, myCommonProgramParameters, myJrePathEditor); ModulesComboBox modulesComboBox = myModuleComponent.getComponent(); modulesComboBox.allowEmptySelection(""); modulesComboBox.fillModules(project); + myJrePathEditor.setDefaultJreSelector(DefaultJreSelector.fromModuleDependencies(modulesComboBox, true)); } public void applyEditorTo(final JarApplicationConfiguration configuration) throws ConfigurationException { myCommonProgramParameters.applyTo(configuration); - configuration.setAlternativeJrePath(myAlternativeJREPanel.getPath()); - configuration.setAlternativeJrePathEnabled(myAlternativeJREPanel.isPathEnabled()); + configuration.setAlternativeJrePath(myJrePathEditor.getJrePathOrName()); + configuration.setAlternativeJrePathEnabled(myJrePathEditor.isAlternativeJreSelected()); configuration.setJarPath(FileUtil.toSystemIndependentName(myJarPathComponent.getComponent().getText())); configuration.setModule(myModuleComponent.getComponent().getSelectedModule()); } @@ -61,7 +63,8 @@ public class JarApplicationConfigurable extends SettingsEditor ext private JPanel myWholePanel = new JPanel(new BorderLayout()); private LabeledComponent myModule = new LabeledComponent(); private CommonJavaParametersPanel myCommonJavaParameters = new CommonJavaParametersPanel(); - private AlternativeJREPanel myAlternativeJREPanel = new AlternativeJREPanel(); + private JrePathEditor myJrePathEditor; private LabeledComponent myClass = new LabeledComponent(); private LabeledComponent myMethod = new LabeledComponent(); @@ -170,11 +167,12 @@ public class TestDiscoveryConfigurable ext myWholePanel.add(classpathPanel, BorderLayout.SOUTH); classpathPanel.add(myModule, BorderLayout.NORTH); - classpathPanel.add(myAlternativeJREPanel, BorderLayout.CENTER); + myJrePathEditor = new JrePathEditor(DefaultJreSelector.fromModuleDependencies(getModulesComponent(), false)); + classpathPanel.add(myJrePathEditor, BorderLayout.CENTER); UIUtil.setEnabled(myCommonJavaParameters.getProgramParametersComponent(), false, true); setAnchor(myModule.getLabel()); - myAlternativeJREPanel.setAnchor(myModule.getLabel()); + myJrePathEditor.setAnchor(myModule.getLabel()); myCommonJavaParameters.setAnchor(myModule.getLabel()); } @@ -186,8 +184,8 @@ public class TestDiscoveryConfigurable ext public void applyEditorTo(final TestDiscoveryConfiguration configuration) { applyHelpersTo(configuration); - configuration.setAlternativeJrePath(myAlternativeJREPanel.getPath()); - configuration.setAlternativeJrePathEnabled(myAlternativeJREPanel.isPathEnabled()); + configuration.setAlternativeJrePath(myJrePathEditor.getJrePathOrName()); + configuration.setAlternativeJrePathEnabled(myJrePathEditor.isAlternativeJreSelected()); configuration.setPosition(myPositionRb.isSelected() ? Pair.create(myClass.getComponent().getText().trim(), myMethod.getComponent().getText().trim()) : null); if (myChangesRb.isSelected()) { @@ -203,7 +201,8 @@ public class TestDiscoveryConfigurable ext public void resetEditorFrom(final TestDiscoveryConfiguration configuration) { myCommonJavaParameters.reset(configuration); getModuleSelector().reset(configuration); - myAlternativeJREPanel.init(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled()); + myJrePathEditor + .setPathOrName(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled()); final Pair position = configuration.getPosition(); if (position != null) { myPositionRb.setSelected(true); diff --git a/java/execution/impl/src/com/intellij/execution/ui/AlternativeJREPanel.java b/java/execution/impl/src/com/intellij/execution/ui/AlternativeJREPanel.java index f2e7f79ff5ee..5a6d49282394 100644 --- a/java/execution/impl/src/com/intellij/execution/ui/AlternativeJREPanel.java +++ b/java/execution/impl/src/com/intellij/execution/ui/AlternativeJREPanel.java @@ -42,6 +42,8 @@ import java.util.ArrayList; /** * User: anna * Date: Jun 21, 2005 + * + * @deprecated use {@link JrePathEditor} instead */ public class AlternativeJREPanel extends JPanel implements PanelWithAnchor { private final ComponentWithBrowseButton myPathField; diff --git a/java/execution/impl/src/com/intellij/execution/ui/DefaultJreSelector.kt b/java/execution/impl/src/com/intellij/execution/ui/DefaultJreSelector.kt new file mode 100644 index 000000000000..ddce492ca934 --- /dev/null +++ b/java/execution/impl/src/com/intellij/execution/ui/DefaultJreSelector.kt @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2015 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. + */ +/* + * Copyright 2000-2015 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.execution.ui + +import com.intellij.application.options.ModulesComboBox +import com.intellij.execution.configurations.JavaParameters +import com.intellij.execution.util.JavaParametersUtil +import com.intellij.openapi.editor.event.DocumentAdapter +import com.intellij.openapi.editor.event.DocumentEvent +import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.util.Pair +import com.intellij.openapi.util.component1 +import com.intellij.openapi.util.component2 +import com.intellij.ui.EditorTextFieldWithBrowseButton + +/** + * @author nik + */ + +abstract class DefaultJreSelector { + companion object { + @JvmStatic + fun projectSdk(project: Project): DefaultJreSelector = ProjectSdkSelector(project) + + @JvmStatic + fun fromModuleDependencies(moduleComboBox: ModulesComboBox, productionOnly: Boolean): DefaultJreSelector + = SdkFromModuleDependencies(moduleComboBox, {productionOnly}) + + @JvmStatic + fun fromSourceRootsDependencies(moduleComboBox: ModulesComboBox, classSelector: EditorTextFieldWithBrowseButton): DefaultJreSelector + = SdkFromSourceRootDependencies(moduleComboBox, classSelector) + } + + abstract fun getNameAndDescription(): Pair + open fun addChangeListener(listener: Runnable) { + } + + fun getDescriptionString(): String { + val (name, description) = getNameAndDescription() + return " (${name ?: ""} - $description)" + } + + + class ProjectSdkSelector(val project: Project): DefaultJreSelector() { + override fun getNameAndDescription() = Pair.create(ProjectRootManager.getInstance(project).projectSdkName, "project SDK") + } + + open class SdkFromModuleDependencies(val moduleComboBox: ModulesComboBox, val productionOnly: () -> Boolean): DefaultJreSelector() { + override fun getNameAndDescription(): Pair { + val module = moduleComboBox.selectedModule ?: return Pair.create(null, "module not specified") + + val productionOnly = productionOnly() + val jdkToRun = JavaParameters.getJdkToRunModule(module, productionOnly) + val moduleJdk = ModuleRootManager.getInstance(module).sdk + if (moduleJdk == null || jdkToRun == null) { + return Pair.create(null, "module not specified") + } + if (moduleJdk.homeDirectory == jdkToRun.homeDirectory) { + return Pair.create(moduleJdk.name, "SDK of '${module.name}' module") + } + return Pair.create(jdkToRun.name, "newest SDK from '${module.name}' module${if (productionOnly) "" else " test"} dependencies") + } + + override fun addChangeListener(listener: Runnable) { + moduleComboBox.addActionListener { listener.run() } + } + } + + class SdkFromSourceRootDependencies(moduleComboBox: ModulesComboBox, val classSelector: EditorTextFieldWithBrowseButton) + : SdkFromModuleDependencies(moduleComboBox, { isClassInProductionSources(moduleComboBox, classSelector) }) { + override fun addChangeListener(listener: Runnable) { + super.addChangeListener(listener) + classSelector.childComponent.addDocumentListener(object : DocumentAdapter() { + override fun documentChanged(e: DocumentEvent?) { + listener.run() + } + }) + } + } + +} + +private fun isClassInProductionSources(moduleSelector: ModulesComboBox, classSelector: EditorTextFieldWithBrowseButton): Boolean { + val module = moduleSelector.selectedModule ?: return false + return JavaParametersUtil.isClassInProductionSources(classSelector.text, module) ?: false +} diff --git a/java/execution/impl/src/com/intellij/execution/ui/JreComboboxEditor.java b/java/execution/impl/src/com/intellij/execution/ui/JreComboboxEditor.java new file mode 100644 index 000000000000..ee32962dfdf1 --- /dev/null +++ b/java/execution/impl/src/com/intellij/execution/ui/JreComboboxEditor.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2015 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.execution.ui; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.ui.SortedComboBoxModel; +import com.intellij.ui.components.JBTextField; +import com.intellij.util.ui.StatusText; + +import javax.swing.*; +import javax.swing.plaf.basic.BasicComboBoxEditor; + +/** + * @author nik + */ +class JreComboboxEditor extends BasicComboBoxEditor { + private final SortedComboBoxModel myComboBoxModel; + + public JreComboboxEditor(SortedComboBoxModel comboBoxModel) { + myComboBoxModel = comboBoxModel; + } + + @Override + public void setItem(Object anObject) { + editor.setText(anObject == null ? "" : ((JrePathEditor.JreComboBoxItem)anObject).getPresentableText()); + } + + @Override + public Object getItem() { + String text = editor.getText().trim(); + for (JrePathEditor.JreComboBoxItem item : myComboBoxModel.getItems()) { + if (item.getPresentableText().equals(text)) { + return item; + } + } + return new JrePathEditor.CustomJreItem(FileUtil.toSystemIndependentName(text)); + } + + @Override + protected JTextField createEditorComponent() { + return new JBTextField(); + } + + public StatusText getEmptyText() { + return getEditorComponent().getEmptyText(); + } + + public JBTextField getEditorComponent() { + return (JBTextField)super.getEditorComponent(); + } +} diff --git a/java/execution/impl/src/com/intellij/execution/ui/JrePathEditor.java b/java/execution/impl/src/com/intellij/execution/ui/JrePathEditor.java new file mode 100644 index 000000000000..7d24016a1ccd --- /dev/null +++ b/java/execution/impl/src/com/intellij/execution/ui/JrePathEditor.java @@ -0,0 +1,276 @@ +/* + * Copyright 2000-2015 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.execution.ui; + +import com.intellij.execution.ExecutionBundle; +import com.intellij.icons.AllIcons; +import com.intellij.ide.util.BrowseFilesListener; +import com.intellij.openapi.projectRoots.ProjectJdkTable; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ui.OrderEntryAppearanceService; +import com.intellij.openapi.ui.ComboBox; +import com.intellij.openapi.ui.TextComponentAccessor; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.*; +import com.intellij.ui.components.JBLabel; +import com.intellij.util.ui.StatusText; +import net.miginfocom.swing.MigLayout; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.io.File; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; + +/** + * @author nik + */ +public class JrePathEditor extends JPanel implements PanelWithAnchor { + private static final String DEFAULT_JRE_TEXT = "Default"; + private final ComboboxWithBrowseButton myPathField; + private final JBLabel myLabel; + private final JreComboboxEditor myComboboxEditor; + private final DefaultJreItem myDefaultJreItem; + private DefaultJreSelector myDefaultJreSelector; + private JComponent myAnchor; + private final SortedComboBoxModel myComboBoxModel; + private String myPreviousCustomJrePath; + + public JrePathEditor(DefaultJreSelector defaultJreSelector) { + this(); + setDefaultJreSelector(defaultJreSelector); + } + + /** + * This constructor can be used in UI forms. Don't forget to call {@link #setDefaultJreSelector(DefaultJreSelector)}! + */ + public JrePathEditor() { + myLabel = new JBLabel(ExecutionBundle.message("run.configuration.jre.label")); + + myComboBoxModel = new SortedComboBoxModel(new Comparator() { + @Override + public int compare(JreComboBoxItem o1, JreComboBoxItem o2) { + int result = Comparing.compare(o1.getOrder(), o2.getOrder()); + if (result != 0) { + return result; + } + return o1.getPresentableText().compareToIgnoreCase(o2.getPresentableText()); + } + }); + myDefaultJreItem = new DefaultJreItem(); + myComboBoxModel.add(myDefaultJreItem); + final Sdk[] allJDKs = ProjectJdkTable.getInstance().getAllJdks(); + for (Sdk sdk : allJDKs) { + myComboBoxModel.add(new SdkAsJreItem(sdk)); + } + + final Set jrePaths = new HashSet(); + for (JreProvider provider : JreProvider.EP_NAME.getExtensions()) { + String path = provider.getJrePath(); + if (!StringUtil.isEmpty(path)) { + jrePaths.add(path); + myComboBoxModel.add(new CustomJreItem(path)); + } + } + + for (Sdk jdk : allJDKs) { + String homePath = jdk.getHomePath(); + + if (!SystemInfo.isMac) { + final File jre = new File(jdk.getHomePath(), "jre"); + if (jre.isDirectory()) { + homePath = jre.getPath(); + } + } + if (jrePaths.add(homePath)) { + myComboBoxModel.add(new CustomJreItem(homePath)); + } + } + ComboBox comboBox = new ComboBox(myComboBoxModel); + comboBox.setEditable(true); + comboBox.setRenderer(new ColoredListCellRendererWrapper() { + @Override + protected void doCustomize(JList list, JreComboBoxItem value, int index, boolean selected, boolean hasFocus) { + value.render(this, selected); + } + }); + myComboboxEditor = new JreComboboxEditor(myComboBoxModel); + myComboboxEditor.getEditorComponent().setTextToTriggerEmptyTextStatus(DEFAULT_JRE_TEXT); + comboBox.setEditor(myComboboxEditor); + myPathField = new ComboboxWithBrowseButton(comboBox); + myPathField.addBrowseFolderListener(ExecutionBundle.message("run.configuration.select.alternate.jre.label"), + ExecutionBundle.message("run.configuration.select.jre.dir.label"), + null, BrowseFilesListener.SINGLE_DIRECTORY_DESCRIPTOR, + TextComponentAccessor.STRING_COMBOBOX_WHOLE_TEXT); + + setLayout(new MigLayout("ins 0, gap 10, fill, flowx")); + add(myLabel, "shrinkx"); + add(myPathField, "growx, pushx"); + + InsertPathAction.addTo(myComboboxEditor.getEditorComponent()); + + setAnchor(myLabel); + + updateUI(); + } + + @Nullable + public String getJrePathOrName() { + JreComboBoxItem jre = getSelectedJre(); + if (jre instanceof DefaultJreItem) { + return myPreviousCustomJrePath; + } + return jre.getPresentableText(); + } + + public boolean isAlternativeJreSelected() { + return !(getSelectedJre() instanceof DefaultJreItem); + } + + private JreComboBoxItem getSelectedJre() { + return (JreComboBoxItem)myPathField.getComboBox().getSelectedItem(); + } + + public void setDefaultJreSelector(DefaultJreSelector defaultJreSelector) { + myDefaultJreSelector = defaultJreSelector; + myDefaultJreSelector.addChangeListener(new Runnable() { + @Override + public void run() { + updateDefaultJrePresentation(); + } + }); + } + + public void setPathOrName(@Nullable String pathOrName, boolean useAlternativeJre) { + JreComboBoxItem toSelect = myDefaultJreItem; + if (!StringUtil.isEmpty(pathOrName)) { + myPreviousCustomJrePath = pathOrName; + JreComboBoxItem alternative = findOrAddCustomJre(pathOrName); + if (useAlternativeJre) { + toSelect = alternative; + } + } + myPathField.getChildComponent().setSelectedItem(toSelect); + updateDefaultJrePresentation(); + } + + private void updateDefaultJrePresentation() { + StatusText text = myComboboxEditor.getEmptyText(); + text.clear(); + text.appendText(DEFAULT_JRE_TEXT, SimpleTextAttributes.REGULAR_ATTRIBUTES); + text.appendText(myDefaultJreSelector.getDescriptionString(), SimpleTextAttributes.GRAY_ATTRIBUTES); + } + + private JreComboBoxItem findOrAddCustomJre(@NotNull String pathOrName) { + for (JreComboBoxItem item : myComboBoxModel.getItems()) { + if (item instanceof CustomJreItem && FileUtil.pathsEqual(pathOrName, ((CustomJreItem)item).myPath) + || item.getPresentableText().equals(pathOrName)) { + return item; + } + } + CustomJreItem item = new CustomJreItem(pathOrName); + myComboBoxModel.add(item); + return item; + } + + @Override + public JComponent getAnchor() { + return myAnchor; + } + + @Override + public void setAnchor(JComponent anchor) { + myAnchor = anchor; + myLabel.setAnchor(anchor); + } + + interface JreComboBoxItem { + void render(SimpleColoredComponent component, boolean selected); + String getPresentableText(); + int getOrder(); + } + + private static class SdkAsJreItem implements JreComboBoxItem { + private final Sdk mySdk; + + public SdkAsJreItem(Sdk sdk) { + mySdk = sdk; + } + + @Override + public void render(SimpleColoredComponent component, boolean selected) { + OrderEntryAppearanceService.getInstance().forJdk(mySdk, false, selected, true).customize(component); + } + + @Override + public String getPresentableText() { + return mySdk.getName(); + } + + @Override + public int getOrder() { + return 1; + } + } + + static class CustomJreItem implements JreComboBoxItem { + private final String myPath; + + public CustomJreItem(String path) { + myPath = path; + } + + @Override + public void render(SimpleColoredComponent component, boolean selected) { + component.append(getPresentableText()); + component.setIcon(AllIcons.Nodes.Folder); + } + + @Override + public String getPresentableText() { + return FileUtil.toSystemDependentName(myPath); + } + + @Override + public int getOrder() { + return 2; + } + } + + private class DefaultJreItem implements JreComboBoxItem { + @Override + public void render(SimpleColoredComponent component, boolean selected) { + component.append(DEFAULT_JRE_TEXT); + component.append(myDefaultJreSelector.getDescriptionString(), SimpleTextAttributes.GRAY_ATTRIBUTES); + } + + @Override + public String getPresentableText() { + return DEFAULT_JRE_TEXT; + } + + @Override + public int getOrder() { + return 0; + } + } +} + diff --git a/platform/platform-impl/src/com/intellij/openapi/util/extensions.kt b/platform/platform-impl/src/com/intellij/openapi/util/extensions.kt new file mode 100644 index 000000000000..34c17de215e8 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/util/extensions.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2015 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. + */ +/* + * Copyright 2000-2015 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.util + +/** + * Put here extension functions and variables for classes from util/util-rt modules + */ + +operator fun Pair.component1() = this.first +operator fun Pair.component2() = this.second diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index 5454e5bd38f0..3c9e8a0a4429 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -173,6 +173,7 @@ run.configuration.java.vm.parameters.label=&VM options: run.configuration.program.parameters=Program a&rguments: run.configuration.working.directory.label=&Working directory: run.configuration.use.alternate.jre.checkbox=Use alternative &JRE: +run.configuration.jre.label=&JRE: run.configuration.select.alternate.jre.label=Select Alternative JRE run.configuration.select.jre.dir.label=Select directory with JRE to run with run.configuration.arguments.help.panel.copy.action.name=Copy diff --git a/plugins/devkit/src/run/PluginRunConfigurationEditor.java b/plugins/devkit/src/run/PluginRunConfigurationEditor.java index 9749d3adca18..bb2701c37633 100644 --- a/plugins/devkit/src/run/PluginRunConfigurationEditor.java +++ b/plugins/devkit/src/run/PluginRunConfigurationEditor.java @@ -18,7 +18,8 @@ package org.jetbrains.idea.devkit.run; import com.intellij.application.options.ModulesComboBox; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.configurations.LogFileOptions; -import com.intellij.execution.ui.AlternativeJREPanel; +import com.intellij.execution.ui.DefaultJreSelector; +import com.intellij.execution.ui.JrePathEditor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.ConfigurationException; @@ -53,7 +54,7 @@ public class PluginRunConfigurationEditor extends SettingsEditor myVMParameters = new LabeledComponent(); private final LabeledComponent myProgramParameters = new LabeledComponent(); private JComponent anchor; - private final AlternativeJREPanel myAlternativeJREPanel = new AlternativeJREPanel(); + private final JrePathEditor myJrePathEditor; @NonNls private final JCheckBox myShowLogs = new JCheckBox(DevKitBundle.message("show.smth", "idea.log")); @@ -98,6 +99,7 @@ public class PluginRunConfigurationEditor extends SettingsEditor - + diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java index 0278535a81be..3bf98f3732c8 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java @@ -26,10 +26,7 @@ import com.intellij.execution.junit.JUnitUtil; import com.intellij.execution.junit.TestClassFilter; import com.intellij.execution.testframework.SourceScope; import com.intellij.execution.testframework.TestSearchScope; -import com.intellij.execution.ui.AlternativeJREPanel; -import com.intellij.execution.ui.ClassBrowser; -import com.intellij.execution.ui.CommonJavaParametersPanel; -import com.intellij.execution.ui.ConfigurationModuleSelector; +import com.intellij.execution.ui.*; import com.intellij.icons.AllIcons; import com.intellij.ide.util.ClassFilter; import com.intellij.ide.util.PackageChooserDialog; @@ -98,7 +95,7 @@ public class JUnitConfigurable extends SettingsEdi private JRadioButton mySingleModuleScope; private JRadioButton myModuleWDScope; private TextFieldWithBrowseButton myPatternTextField; - private AlternativeJREPanel myAlternativeJREPanel; + private JrePathEditor myJrePathEditor; private JComboBox myForkCb; private JBLabel myTestLabel; private JComboBox myTypeChooser; @@ -113,6 +110,7 @@ public class JUnitConfigurable extends SettingsEdi myProject = project; myModel = new JUnitConfigurationModel(project); myModuleSelector = new ConfigurationModuleSelector(project, getModulesComponent()); + myJrePathEditor.setDefaultJreSelector(DefaultJreSelector.fromModuleDependencies(getModulesComponent(), false)); myCommonJavaParameters.setModuleContext(myModuleSelector.getModule()); myCommonJavaParameters.setHasModuleMacro(); myModule.getComponent().addActionListener(new ActionListener() { @@ -247,7 +245,7 @@ public class JUnitConfigurable extends SettingsEdi UIUtil.setEnabled(myCommonJavaParameters.getProgramParametersComponent(), false, true); setAnchor(mySearchForTestsLabel); - myAlternativeJREPanel.setAnchor(myModule.getLabel()); + myJrePathEditor.setAnchor(myModule.getLabel()); myCommonJavaParameters.setAnchor(myModule.getLabel()); } @@ -273,8 +271,8 @@ public class JUnitConfigurable extends SettingsEdi else if (myModuleWDScope.isSelected()) { data.setScope(TestSearchScope.MODULE_WITH_DEPENDENCIES); } - configuration.setAlternativeJrePath(myAlternativeJREPanel.getPath()); - configuration.setAlternativeJrePathEnabled(myAlternativeJREPanel.isPathEnabled()); + configuration.setAlternativeJrePath(myJrePathEditor.getJrePathOrName()); + configuration.setAlternativeJrePathEnabled(myJrePathEditor.isAlternativeJreSelected()); myCommonJavaParameters.applyTo(configuration); configuration.setForkMode((String)myForkCb.getSelectedItem()); @@ -301,7 +299,8 @@ public class JUnitConfigurable extends SettingsEdi else { myWholeProjectScope.setSelected(true); } - myAlternativeJREPanel.init(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled()); + myJrePathEditor + .setPathOrName(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled()); myForkCb.setSelectedItem(configuration.getForkMode()); final int count = configuration.getRepeatCount(); myRepeatCountField.setText(String.valueOf(count)); diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.form b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.form index d6144e862d76..6dcebbbfb117 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.form +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.form @@ -158,7 +158,7 @@ - + diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java index eb91dac65e7e..856cb84027cc 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java @@ -28,7 +28,8 @@ import com.intellij.execution.JavaExecutionUtil; import com.intellij.execution.MethodBrowser; import com.intellij.execution.configuration.BrowseModuleValueActionListener; import com.intellij.execution.testframework.TestSearchScope; -import com.intellij.execution.ui.AlternativeJREPanel; +import com.intellij.execution.ui.DefaultJreSelector; +import com.intellij.execution.ui.JrePathEditor; import com.intellij.execution.ui.CommonJavaParametersPanel; import com.intellij.execution.ui.ConfigurationModuleSelector; import com.intellij.icons.AllIcons; @@ -80,7 +81,7 @@ public class TestNGConfigurationEditor extends Se private LabeledComponent classField; private LabeledComponent moduleClasspath; - private AlternativeJREPanel alternateJDK; + private JrePathEditor alternateJDK; private final ConfigurationModuleSelector moduleSelector; private JRadioButton suiteTest; private JRadioButton packageTest; @@ -136,6 +137,7 @@ public class TestNGConfigurationEditor extends Se model.setListener(this); createView(); moduleSelector = new ConfigurationModuleSelector(project, getModulesComponent()); + alternateJDK.setDefaultJreSelector(DefaultJreSelector.fromModuleDependencies(getModulesComponent(), false)); commonJavaParameters.setModuleContext(moduleSelector.getModule()); moduleClasspath.getComponent().addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -311,7 +313,7 @@ public class TestNGConfigurationEditor extends Se packagesInProject.setSelected(true); } evaluateModuleClassPath(); - alternateJDK.init(config.ALTERNATIVE_JRE_PATH, config.ALTERNATIVE_JRE_PATH_ENABLED); + alternateJDK.setPathOrName(config.ALTERNATIVE_JRE_PATH, config.ALTERNATIVE_JRE_PATH_ENABLED); propertiesList.clear(); propertiesList.addAll(data.TEST_PROPERTIES.entrySet()); propertiesTableModel.setParameterList(propertiesList); @@ -338,8 +340,8 @@ public class TestNGConfigurationEditor extends Se data.setScope(TestSearchScope.MODULE_WITH_DEPENDENCIES); } commonJavaParameters.applyTo(config); - config.ALTERNATIVE_JRE_PATH = alternateJDK.getPath(); - config.ALTERNATIVE_JRE_PATH_ENABLED = alternateJDK.isPathEnabled(); + config.ALTERNATIVE_JRE_PATH = alternateJDK.getJrePathOrName(); + config.ALTERNATIVE_JRE_PATH_ENABLED = alternateJDK.isAlternativeJreSelected(); data.TEST_PROPERTIES.clear(); for (Map.Entry entry : propertiesList) {