diff --git a/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.kt b/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.kt index 61cdc58c6552..f3fb42a7bfdc 100644 --- a/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.kt +++ b/java/java-tests/testSrc/com/intellij/execution/impl/RunConfigurableTest.kt @@ -1,7 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.execution.impl -import com.intellij.execution.actions.ChooseRunConfigurationPopup +import com.intellij.execution.actions.ChooseRunConfigurationManager import com.intellij.execution.actions.ExecutorProvider import com.intellij.execution.application.ApplicationConfigurationType import com.intellij.execution.impl.RunConfigurableNodeKind.* @@ -245,7 +245,7 @@ internal class RunConfigurableTest { val executorProvider = ExecutorProvider { throw UnsupportedOperationException() } val dataContext = DataManager.getInstance().getDataContext(configurable.tree) - assertThat(ChooseRunConfigurationPopup.createSettingsList(runManager, executorProvider, false, false, dataContext).joinToString("\n") { + assertThat(ChooseRunConfigurationManager.createSettingsList(runManager, executorProvider, false, false, dataContext).joinToString("\n") { val value = it.value if (value is String) { "[$value]" @@ -262,7 +262,7 @@ internal class RunConfigurableTest { [5] JUnit: All in titled5 (level: TEMPORARY) """.trimIndent()) - assertThat(ChooseRunConfigurationPopup.createSettingsList(runManager, executorProvider, false, true, dataContext).joinToString("\n") { + assertThat(ChooseRunConfigurationManager.createSettingsList(runManager, executorProvider, false, true, dataContext).joinToString("\n") { val value = it.value if (value is String) { "[$value]" diff --git a/platform/execution-impl/api-dump-unreviewed.txt b/platform/execution-impl/api-dump-unreviewed.txt index 4d7129a252d6..3c475e6c316a 100644 --- a/platform/execution-impl/api-dump-unreviewed.txt +++ b/platform/execution-impl/api-dump-unreviewed.txt @@ -262,32 +262,6 @@ a:com.intellij.execution.actions.BaseRunConfigurationAction - s:suggestRunActionName(com.intellij.execution.configurations.RunConfiguration):java.lang.String - update(com.intellij.openapi.actionSystem.AnActionEvent):V - pa:updatePresentation(com.intellij.openapi.actionSystem.Presentation,java.lang.String,com.intellij.execution.actions.ConfigurationContext):V -f:com.intellij.execution.actions.ChooseRunConfigurationPopup -- com.intellij.execution.actions.ExecutorProvider -- (com.intellij.openapi.project.Project,java.lang.String,com.intellij.execution.Executor,com.intellij.execution.Executor):V -- s:createFlatSettingsList(com.intellij.openapi.project.Project):java.util.List -- s:createSettingsList(com.intellij.execution.impl.RunManagerImpl,com.intellij.execution.actions.ExecutorProvider,Z,Z,com.intellij.openapi.actionSystem.DataContext):java.util.List -- s:createSettingsList(com.intellij.openapi.project.Project,com.intellij.execution.actions.ExecutorProvider,com.intellij.openapi.actionSystem.DataContext,Z):java.util.List -- s:createSettingsList(com.intellij.openapi.project.Project,com.intellij.execution.actions.ExecutorProvider,Z):java.util.List -- s:deleteConfiguration(com.intellij.openapi.project.Project,com.intellij.execution.RunnerAndConfigurationSettings,com.intellij.openapi.ui.popup.JBPopup):V -- getExecutor():com.intellij.execution.Executor -a:com.intellij.execution.actions.ChooseRunConfigurationPopup$ItemWrapper -- com.intellij.ui.popup.NumericMnemonicItem -- p:(java.lang.Object):V -- p:(java.lang.Object,Z):V -- available(com.intellij.execution.Executor):Z -- canBeDeleted():Z -- equals(java.lang.Object):Z -- getNextStep(com.intellij.openapi.project.Project,com.intellij.execution.actions.ChooseRunConfigurationPopup):com.intellij.openapi.ui.popup.PopupStep -- getType():com.intellij.execution.configurations.ConfigurationType -- getValue():java.lang.Object -- hasActions():Z -- hashCode():I -- isDynamic():Z -- a:perform(com.intellij.openapi.project.Project,com.intellij.execution.Executor,com.intellij.openapi.actionSystem.DataContext):V -- setDynamic(Z):V -- s:wrap(com.intellij.openapi.project.Project,com.intellij.execution.RunnerAndConfigurationSettings):com.intellij.execution.actions.ChooseRunConfigurationPopup$ItemWrapper -- s:wrap(com.intellij.openapi.project.Project,com.intellij.execution.RunnerAndConfigurationSettings,Z):com.intellij.execution.actions.ChooseRunConfigurationPopup$ItemWrapper c:com.intellij.execution.actions.ChooseRunConfigurationPopupAction - com.intellij.openapi.actionSystem.AnAction - com.intellij.openapi.project.DumbAware diff --git a/platform/execution-impl/api-dump.txt b/platform/execution-impl/api-dump.txt index 16d98d81face..d15337fdcaf0 100644 --- a/platform/execution-impl/api-dump.txt +++ b/platform/execution-impl/api-dump.txt @@ -27,6 +27,12 @@ com.intellij.execution.InputRedirectAware$InputRedirectOptions - a:setRedirectInputPath(java.lang.String):V com.intellij.execution.RunConfigurationConverter - a:convertRunConfigurationOnDemand(org.jdom.Element):Z +f:com.intellij.execution.actions.ChooseRunConfigurationManager +- ():V +- s:createFlatSettingsList(com.intellij.openapi.project.Project):java.util.List +- s:createSettingsList(com.intellij.execution.impl.RunManagerImpl,com.intellij.execution.actions.ExecutorProvider,Z,Z,com.intellij.openapi.actionSystem.DataContext):java.util.List +- s:createSettingsList(com.intellij.openapi.project.Project,com.intellij.execution.actions.ExecutorProvider,com.intellij.openapi.actionSystem.DataContext,Z):java.util.List +- s:deleteConfiguration(com.intellij.openapi.project.Project,com.intellij.execution.RunnerAndConfigurationSettings,com.intellij.openapi.ui.popup.JBPopup):V com.intellij.execution.actions.ExecutorProvider - a:getExecutor():com.intellij.execution.Executor c:com.intellij.execution.actions.StopAction diff --git a/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationManager.java b/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationManager.java new file mode 100644 index 000000000000..6e01ed1264f0 --- /dev/null +++ b/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationManager.java @@ -0,0 +1,739 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.execution.actions; + +import com.intellij.CommonBundle; +import com.intellij.execution.*; +import com.intellij.execution.configurations.ConfigurationType; +import com.intellij.execution.executors.ExecutorGroup; +import com.intellij.execution.impl.EditConfigurationsDialog; +import com.intellij.execution.impl.RunManagerImpl; +import com.intellij.execution.impl.RunManagerImplKt; +import com.intellij.execution.impl.RunnerAndConfigurationSettingsImpl; +import com.intellij.execution.runners.ExecutionUtil; +import com.intellij.execution.runners.ProgramRunner; +import com.intellij.icons.AllIcons; +import com.intellij.ide.DataManager; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.idea.ActionsBundle; +import com.intellij.openapi.actionSystem.ActionPlaces; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DoNotAskOption; +import com.intellij.openapi.ui.MessageDialogBuilder; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.ListSeparator; +import com.intellij.openapi.ui.popup.PopupStep; +import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.NlsContexts; +import com.intellij.openapi.util.NlsSafe; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; + +import javax.swing.*; +import java.util.*; + +import static java.util.Objects.requireNonNull; + +public final class ChooseRunConfigurationManager { + + public static @NotNull List> createSettingsList(@NotNull Project project, + @NotNull ExecutorProvider executorProvider, + @NotNull DataContext dataContext, + boolean isCreateEditAction) { + RunManager runManager = RunManager.getInstanceIfCreated(project); + if (runManager == null) { + return Collections.emptyList(); + } + //noinspection TestOnlyProblems + return createSettingsList((RunManagerImpl)runManager, executorProvider, isCreateEditAction, + Registry.is("run.popup.move.folders.to.top", false), dataContext); + } + + public static List> createFlatSettingsList(@NotNull Project project) { + return RunManagerImplKt.createFlatSettingsList(project); + } + + @TestOnly + public static @NotNull List> createSettingsList(@NotNull RunManagerImpl runManager, + @NotNull ExecutorProvider executorProvider, + boolean isCreateEditAction, + boolean isMoveFoldersToTop, + @NotNull DataContext dataContext) { + List> result = new ArrayList<>(); + + if (isCreateEditAction) { + result.add(createEditAction()); + } + + Project project = runManager.getProject(); + final RunnerAndConfigurationSettings selectedConfiguration = runManager.getSelectedConfiguration(); + if (selectedConfiguration != null) { + addActionsForSelected(selectedConfiguration, project, result); + } + + Map> wrappedExisting = new LinkedHashMap<>(); + List folderWrappers = new SmartList<>(); + for (Map> folderToConfigurations : runManager.getConfigurationsGroupedByTypeAndFolder( + false).values()) { + if (isMoveFoldersToTop) { + for (Map.Entry> entry : folderToConfigurations.entrySet()) { + final String folderName = entry.getKey(); + List configurations = entry.getValue(); + if (folderName != null) { + folderWrappers.add(createFolderItem(project, executorProvider, selectedConfiguration, folderName, configurations)); + } + else { + for (RunnerAndConfigurationSettings configuration : configurations) { + wrapAndAdd(project, configuration, selectedConfiguration, wrappedExisting); + } + } + } + } + else { + // add only folders + for (Map.Entry> entry : folderToConfigurations.entrySet()) { + final String folderName = entry.getKey(); + if (folderName != null) { + result.add(createFolderItem(project, executorProvider, selectedConfiguration, folderName, entry.getValue())); + } + } + + // add configurations + List configurations = folderToConfigurations.get(null); + if (!ContainerUtil.isEmpty(configurations)) { + for (RunnerAndConfigurationSettings configuration : configurations) { + result.add(wrapAndAdd(project, configuration, selectedConfiguration, wrappedExisting)); + } + } + } + } + + if (isMoveFoldersToTop) { + result.addAll(folderWrappers); + } + if (!DumbService.isDumb(project)) { + populateWithDynamicRunners(result, wrappedExisting, project, RunManagerEx.getInstanceEx(project), selectedConfiguration, dataContext); + } + if (isMoveFoldersToTop) { + result.addAll(wrappedExisting.values()); + } + return result; + } + + public static void deleteConfiguration(@NotNull Project project, + @NotNull RunnerAndConfigurationSettings configurationSettings, + @Nullable JBPopup popupToCancel) { + RunManagerConfig runManagerConfig = RunManagerImpl.getInstanceImpl(project).getConfig(); + boolean confirmed; + if (runManagerConfig.isDeletionFromPopupRequiresConfirmation()) { + if (popupToCancel != null) { + popupToCancel.cancel(); + } + + confirmed = MessageDialogBuilder.yesNo(CommonBundle.message("title.confirmation"), + ExecutionBundle.message("are.you.sure.you.want.to.delete.0", configurationSettings.getName())) + .doNotAsk(new DoNotAskOption.Adapter() { + @Override + public void rememberChoice(boolean isSelected, int exitCode) { + runManagerConfig.setDeletionFromPopupRequiresConfirmation(!isSelected); + } + + @Override + public @NotNull String getDoNotShowMessage() { + return ExecutionBundle.message("don.t.ask.again"); + } + + @Override + public boolean shouldSaveOptionsOnCancel() { + return true; + } + }) + .ask(project); + } + else { + confirmed = true; + } + if (confirmed) { + RunManager.getInstance(project).removeConfiguration(configurationSettings); + } + } + + private static @NotNull ChooseRunConfigurationPopup.ItemWrapper wrapAndAdd(@NotNull Project project, + @NotNull RunnerAndConfigurationSettings configuration, + @Nullable RunnerAndConfigurationSettings selectedConfiguration, + @NotNull Map> wrappedExisting) { + ChooseRunConfigurationPopup.ItemWrapper wrapped = ChooseRunConfigurationPopup.ItemWrapper.wrap(project, configuration); + if (configuration == selectedConfiguration) { + wrapped.setMnemonic(1); + } + wrappedExisting.put(configuration, wrapped); + return wrapped; + } + + private static @NotNull FolderWrapper createFolderItem(@NotNull Project project, + @NotNull ExecutorProvider executorProvider, + @Nullable RunnerAndConfigurationSettings selectedConfiguration, + @NotNull String folderName, + @NotNull List configurations) { + boolean isSelected = selectedConfiguration != null && configurations.contains(selectedConfiguration); + String value = folderName; + if (isSelected) { + value += " (mnemonic is to \"" + selectedConfiguration.getName() + "\")"; + } + FolderWrapper + result = new FolderWrapper(project, executorProvider, value, configurations); + if (isSelected) { + result.setMnemonic(1); + } + return result; + } + + private static void addActionsForSelected(@NotNull RunnerAndConfigurationSettings selectedConfiguration, + @NotNull Project project, + @NotNull List> result) { + boolean isFirst = true; + final ExecutionTarget activeTarget = ExecutionTargetManager.getActiveTarget(project); + for (ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selectedConfiguration.getConfiguration())) { + ChooseRunConfigurationPopup.ItemWrapper + itemWrapper = new ChooseRunConfigurationPopup.ItemWrapper<>(eachTarget, isFirst) { + @Override + public Icon getIcon() { + return requireNonNull(getValue()).getIcon(); + } + + @Override + public String getText() { + return requireNonNull(getValue()).getDisplayName(); + } + + @Override + public void perform(final @NotNull Project project, final @NotNull Executor executor, @NotNull DataContext context) { + ExecutionTargetManager.setActiveTarget(project, requireNonNull(getValue())); + ExecutionUtil.doRunConfiguration(selectedConfiguration, executor, null, null, context); + } + + @Override + public boolean available(Executor executor) { + return true; + } + }; + itemWrapper.setChecked(eachTarget.equals(activeTarget)); + result.add(itemWrapper); + isFirst = false; + } + } + + private static @NotNull ChooseRunConfigurationPopup.ItemWrapper createEditAction() { + ChooseRunConfigurationPopup.ItemWrapper result = new ChooseRunConfigurationPopup.ItemWrapper<>(null) { + @Override + public Icon getIcon() { + return AllIcons.Actions.EditSource; + } + + @Override + public String getText() { + return UIUtil.removeMnemonic(ActionsBundle.message("action.editRunConfigurations.text")); + } + + @Override + public void perform(final @NotNull Project project, final @NotNull Executor executor, @NotNull DataContext context) { + if (new EditConfigurationsDialog(project) { + @Override + protected void init() { + setOKButtonText(executor.getActionName()); + myExecutor = executor; + super.init(); + } + }.showAndGet()) { + ApplicationManager.getApplication().invokeLater(() -> { + RunnerAndConfigurationSettings configuration = RunManager.getInstance(project).getSelectedConfiguration(); + if (configuration != null) { + ExecutionUtil.doRunConfiguration(configuration, executor, null, null, context); + } + }, project.getDisposed()); + } + } + + @Override + public boolean available(Executor executor) { + return true; + } + }; + result.setMnemonic(0); + return result; + } + + private static void populateWithDynamicRunners(List> result, + Map> existing, + Project project, + RunManager manager, + RunnerAndConfigurationSettings selectedConfiguration, + @NotNull DataContext dataContext) { + final ConfigurationContext context = ConfigurationContext.getFromContext(dataContext, ActionPlaces.UNKNOWN); + + List producers = PreferredProducerFind.getConfigurationsFromContext(context.getLocation(), + context, false, true); + if (producers == null) return; + + producers = ContainerUtil.sorted(producers, ConfigurationFromContext.NAME_COMPARATOR); + + final RunnerAndConfigurationSettings[] preferred = {null}; + + int i = 2; // selectedConfiguration == null ? 1 : 2; + for (final ConfigurationFromContext fromContext : producers) { + final RunnerAndConfigurationSettings configuration = fromContext.getConfigurationSettings(); + if (existing.containsKey(configuration)) { + ChooseRunConfigurationPopup.ItemWrapper wrapper = existing.get(configuration); + if (wrapper.getMnemonic() != 1) { + wrapper.setMnemonic(i); + i++; + } + } + else { + if (selectedConfiguration != null && configuration.equals(selectedConfiguration)) continue; + + if (preferred[0] == null) { + preferred[0] = configuration; + } + + ChooseRunConfigurationPopup.ItemWrapper wrapper = new ChooseRunConfigurationPopup.ItemWrapper(configuration) { + @Override + public Icon getIcon() { + return RunManagerEx.getInstanceEx(project).getConfigurationIcon(configuration); + } + + @Override + public String getText() { + return Executor.shortenNameIfNeeded(configuration.getName()) + configuration.getConfiguration().getPresentableType(); + } + + @Override + public boolean available(Executor executor) { + return ProgramRunner.getRunner(executor.getId(), configuration.getConfiguration()) != null; + } + + @Override + public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) { + manager.setTemporaryConfiguration(configuration); + RunManager.getInstance(project).setSelectedConfiguration(configuration); + ExecutionUtil.doRunConfiguration(configuration, executor, null, null, context); + } + + @Override + public PopupStep getNextStep(@NotNull Project project, final @NotNull ChooseRunConfigurationPopup action) { + return new ConfigurationActionsStep(project, action, configuration, isDynamic()); + } + + @Override + public boolean hasActions() { + return true; + } + }; + + wrapper.setDynamic(true); + wrapper.setMnemonic(i); + result.add(wrapper); + i++; + } + } + } + + static final class FolderWrapper extends ChooseRunConfigurationPopup.ItemWrapper { + private final Project myProject; + private final ExecutorProvider myExecutorProvider; + final List myConfigurations; + + private FolderWrapper(Project project, + ExecutorProvider executorProvider, + @Nullable String value, + List configurations) { + super(value); + myProject = project; + myExecutorProvider = executorProvider; + myConfigurations = configurations; + } + + @Override + public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) { + RunManager runManager = RunManager.getInstance(project); + RunnerAndConfigurationSettings selectedConfiguration = runManager.getSelectedConfiguration(); + if (myConfigurations.contains(selectedConfiguration)) { + runManager.setSelectedConfiguration(selectedConfiguration); + ExecutionUtil.runConfiguration(requireNonNull(selectedConfiguration), myExecutorProvider.getExecutor()); + } + } + + @Override + public @NotNull Icon getIcon() { + return AllIcons.Nodes.Folder; + } + + @Override + public String getText() { + return getValue(); + } + + @Override + public @Nullable ConfigurationType getType() { + return Registry.is("run.popup.move.folders.to.top") || myConfigurations.isEmpty() + ? null + : myConfigurations.get(0).getType(); + } + + @Override + public boolean hasActions() { + return true; + } + + @Override + public PopupStep getNextStep(Project project, ChooseRunConfigurationPopup action) { + List steps = new ArrayList<>(); + for (RunnerAndConfigurationSettings settings : myConfigurations) { + steps.add(new ConfigurationActionsStep(project, action, settings, false)); + } + return new FolderStep(myProject, myExecutorProvider, null, steps, action); + } + } + + static final class FolderStep extends BaseListPopupStep { + private final Project myProject; + private final ChooseRunConfigurationPopup myPopup; + private final ExecutorProvider myExecutorProvider; + + private FolderStep(Project project, + ExecutorProvider executorProvider, + @NlsSafe String folderName, + List children, + ChooseRunConfigurationPopup popup) { + super(folderName, children, new ArrayList<>()); + myProject = project; + myExecutorProvider = executorProvider; + myPopup = popup; + } + + @Override + public PopupStep onChosen(ConfigurationActionsStep selectedValue, boolean finalChoice) { + if (finalChoice) { + if (myPopup.myEditConfiguration) { + final RunnerAndConfigurationSettings settings = selectedValue.getSettings(); + return doFinalStep(() -> myPopup.editConfiguration(myProject, settings)); + } + + return doFinalStep(() -> { + RunnerAndConfigurationSettings settings = selectedValue.getSettings(); + RunManager.getInstance(myProject).setSelectedConfiguration(settings); + ExecutionUtil.runConfiguration(settings, myExecutorProvider.getExecutor()); + }); + } + else { + return selectedValue; + } + } + + @Override + public Icon getIconFor(ConfigurationActionsStep aValue) { + return aValue.getIcon(); + } + + @Override + public @NotNull String getTextFor(ConfigurationActionsStep value) { + return value.getName(); + } + + @Override + public boolean hasSubstep(ConfigurationActionsStep selectedValue) { + return !selectedValue.getValues().isEmpty(); + } + } + + static final class ConfigurationListPopupStep extends BaseListPopupStep> { + private final Project myProject; + private final ChooseRunConfigurationPopup myAction; + private int myDefaultConfiguration = -1; + + ConfigurationListPopupStep(final @NotNull ChooseRunConfigurationPopup action, + final @NotNull Project project, + final @NotNull @Nls String title, + @NotNull List> list) { + super(title, list); + myProject = project; + myAction = action; + + if (-1 == getDefaultOptionIndex()) { + myDefaultConfiguration = getDynamicIndex(); + } + + boolean hasMnemonics = ContainerUtil.exists(getValues(), wrapper -> wrapper.getMnemonic() != -1); + if (hasMnemonics) getValues().forEach(wrapper -> wrapper.setMnemonicsEnabled(true)); + } + + private int getDynamicIndex() { + int i = 0; + for (ChooseRunConfigurationPopup.ItemWrapper wrapper : getValues()) { + if (wrapper.isDynamic()) { + return i; + } + i++; + } + + return -1; + } + + @Override + public boolean isAutoSelectionEnabled() { + return false; + } + + @Override + public ListSeparator getSeparatorAbove(ChooseRunConfigurationPopup.ItemWrapper value) { + if (value.addSeparatorAbove()) return new ListSeparator(); + + List> configurations = getValues(); + final int index = configurations.indexOf(value); + if (index > 0 && index <= configurations.size() - 1) { + ChooseRunConfigurationPopup.ItemWrapper aboveConfiguration = configurations.get(index - 1); + + if (aboveConfiguration != null && aboveConfiguration.isDynamic() != value.isDynamic()) { + return new ListSeparator(); + } + + final ConfigurationType currentType = value.getType(); + final ConfigurationType aboveType = aboveConfiguration == null ? null : aboveConfiguration.getType(); + if (aboveType != currentType && currentType != null) { + return new ListSeparator(); // new ListSeparator(currentType.getDisplayName()); + } + } + + return null; + } + + @Override + public boolean isSpeedSearchEnabled() { + return true; + } + + @Override + public int getDefaultOptionIndex() { + final RunnerAndConfigurationSettings currentConfiguration = RunManager.getInstance(myProject).getSelectedConfiguration(); + if (currentConfiguration == null && myDefaultConfiguration != -1) { + return myDefaultConfiguration; + } + + return currentConfiguration instanceof RunnerAndConfigurationSettingsImpl ? getValues() + .indexOf(ChooseRunConfigurationPopup.ItemWrapper.wrap(myProject, currentConfiguration)) : -1; + } + + @Override + public PopupStep onChosen(ChooseRunConfigurationPopup.ItemWrapper wrapper, boolean finalChoice) { + if (myAction.myEditConfiguration) { + final Object o = wrapper.getValue(); + if (o instanceof RunnerAndConfigurationSettingsImpl) { + return doFinalStep(() -> myAction.editConfiguration(myProject, (RunnerAndConfigurationSettings)o)); + } + } + + if (finalChoice && wrapper.available(myAction.getExecutor())) { + return doFinalStep(() -> { + if (myAction.getExecutor() == myAction.myAlternativeExecutor) { + PropertiesComponent.getInstance().setValue(myAction.myAddKey, Boolean.toString(true)); + } + + wrapper.perform(myProject, myAction.getExecutor(), DataManager.getInstance().getDataContext()); + }); + } + else { + return wrapper.getNextStep(myProject, myAction); + } + } + + @Override + public boolean isFinal(ChooseRunConfigurationPopup.ItemWrapper wrapper) { + return myAction.myEditConfiguration + || wrapper.available(myAction.getExecutor()) + || wrapper.getNextStep(myProject, myAction) == FINAL_CHOICE; + } + + @Override + public boolean hasSubstep(ChooseRunConfigurationPopup.ItemWrapper selectedValue) { + return selectedValue.hasActions(); + } + + @Override + public @NotNull String getTextFor(ChooseRunConfigurationPopup.ItemWrapper value) { + //noinspection DialogTitleCapitalization + return value.getText(); + } + + @Override + public Icon getIconFor(ChooseRunConfigurationPopup.ItemWrapper value) { + return value.getIcon(); + } + } + + static final class ConfigurationActionsStep extends BaseListPopupStep { + + private final @NotNull RunnerAndConfigurationSettings mySettings; + private final @NotNull Project myProject; + + ConfigurationActionsStep(final @NotNull Project project, + ChooseRunConfigurationPopup action, + final @NotNull RunnerAndConfigurationSettings settings, final boolean dynamic) { + super(null, buildActions(project, action, settings, dynamic)); + myProject = project; + mySettings = settings; + } + + public @NotNull RunnerAndConfigurationSettings getSettings() { + return mySettings; + } + + public @NlsContexts.ListItem String getName() { + return Executor.shortenNameIfNeeded(mySettings.getName()); + } + + public Icon getIcon() { + return RunManagerEx.getInstanceEx(myProject).getConfigurationIcon(mySettings); + } + + @Override + public ListSeparator getSeparatorAbove(ActionWrapper value) { + return value.addSeparatorAbove() ? new ListSeparator() : null; + } + + private static ActionWrapper[] buildActions(final @NotNull Project project, + final ChooseRunConfigurationPopup action, + final @NotNull RunnerAndConfigurationSettings settings, + final boolean dynamic) { + final List result = new ArrayList<>(); + + final ExecutionTarget active = ExecutionTargetManager.getActiveTarget(project); + for (final ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, settings.getConfiguration())) { + result.add(new ActionWrapper(eachTarget.getDisplayName(), eachTarget.getIcon()) { + { + setChecked(eachTarget.equals(active)); + } + + @Override + public void perform() { + final RunManager manager = RunManager.getInstance(project); + if (dynamic) { + manager.setTemporaryConfiguration(settings); + } + manager.setSelectedConfiguration(settings); + + ExecutionTargetManager.setActiveTarget(project, eachTarget); + ExecutionUtil.runConfiguration(settings, action.getExecutor()); + } + }); + } + + boolean isFirst = true; + final List allExecutors = new ArrayList<>(); + for (Executor executor : Executor.EXECUTOR_EXTENSION_NAME.getExtensionList()) { + if (executor instanceof ExecutorGroup) { + allExecutors.addAll(((ExecutorGroup)executor).childExecutors()); + } + else { + allExecutors.add(executor); + } + } + for (final Executor executor : allExecutors) { + if (ExecutorRegistryImpl.RunnerHelper.canRun(project, executor, settings.getConfiguration())) { + result.add(new ActionWrapper(executor.getActionName(), executor.getIcon(), isFirst) { + @Override + public void perform() { + final RunManager manager = RunManager.getInstance(project); + if (dynamic) { + manager.setTemporaryConfiguration(settings); + } + if (!manager.isRiderRunWidgetActive()) manager.setSelectedConfiguration(settings); + ExecutorRegistryImpl.RunnerHelper.run(project, settings.getConfiguration(), settings, DataContext.EMPTY_CONTEXT, executor); + } + }); + isFirst = false; + } + } + + result.add(new ActionWrapper(ExecutionBundle.message("choose.run.popup.edit"), AllIcons.Actions.EditSource, true) { + @Override + public void perform() { + if (dynamic) { + RunManager.getInstance(project).setTemporaryConfiguration(settings); + } + action.editConfiguration(project, settings); + } + }); + + if (settings.isTemporary() || dynamic) { + result.add(new ActionWrapper(ExecutionBundle.message("choose.run.popup.save"), AllIcons.Actions.MenuSaveall) { + @Override + public void perform() { + final RunManager manager = RunManager.getInstance(project); + if (dynamic) { + manager.setTemporaryConfiguration(settings); + } + manager.makeStable(settings); + } + }); + } + result.add(new ActionWrapper(ExecutionBundle.message("choose.run.popup.delete"), AllIcons.Actions.Cancel) { + @Override + public void perform() { + deleteConfiguration(project, settings, action.myPopup); + } + }); + + return result.toArray(new ActionWrapper[0]); + } + + @Override + public PopupStep onChosen(ActionWrapper selectedValue, boolean finalChoice) { + return doFinalStep(() -> selectedValue.perform()); + } + + @Override + public Icon getIconFor(ActionWrapper aValue) { + return aValue.getIcon(); + } + + @Override + public @NotNull String getTextFor(ActionWrapper value) { + return value.getText(); + } + } + + abstract static class ActionWrapper extends ChooseRunConfigurationPopup.Wrapper { + private final @Nls String myName; + private final Icon myIcon; + + ActionWrapper(@Nls String name, Icon icon) { + this(name, icon, false); + } + + ActionWrapper(@Nls String name, Icon icon, boolean addSeparatorAbove) { + super(addSeparatorAbove); + myName = name; + myIcon = icon; + } + + public abstract void perform(); + + @Override + public String getText() { + return myName; + } + + @Override + public Icon getIcon() { + return myIcon; + } + } +} diff --git a/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java b/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java index c37c4402b2d9..50a526961803 100644 --- a/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java +++ b/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java @@ -1,67 +1,58 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.execution.actions; -import com.intellij.CommonBundle; import com.intellij.execution.*; +import com.intellij.execution.actions.ChooseRunConfigurationManager.ConfigurationListPopupStep; +import com.intellij.execution.actions.ChooseRunConfigurationManager.FolderWrapper; import com.intellij.execution.configurations.ConfigurationType; -import com.intellij.execution.executors.ExecutorGroup; -import com.intellij.execution.impl.*; -import com.intellij.execution.runners.ExecutionUtil; -import com.intellij.execution.runners.ProgramRunner; -import com.intellij.icons.AllIcons; +import com.intellij.execution.impl.RunDialog; +import com.intellij.execution.impl.RunManagerImpl; import com.intellij.ide.DataManager; import com.intellij.ide.util.PropertiesComponent; -import com.intellij.idea.ActionsBundle; -import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DoNotAskOption; -import com.intellij.openapi.ui.MessageDialogBuilder; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.ListPopupStep; -import com.intellij.openapi.ui.popup.ListSeparator; import com.intellij.openapi.ui.popup.PopupStep; -import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.util.NlsActions; -import com.intellij.openapi.util.NlsContexts; -import com.intellij.openapi.util.NlsSafe; -import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.popup.NumericMnemonicItem; import com.intellij.ui.popup.WizardPopup; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.ui.popup.list.PopupListElementRenderer; import com.intellij.ui.speedSearch.SpeedSearch; -import com.intellij.util.SmartList; import com.intellij.util.concurrency.annotations.RequiresBackgroundThread; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; -import com.intellij.util.ui.UIUtil; -import org.jetbrains.annotations.*; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; -import java.util.*; import java.util.List; +import java.util.Objects; import static java.util.Objects.requireNonNull; +/** + * Use {@link ChooseRunConfigurationManager} instead. + */ +@ApiStatus.Internal public final class ChooseRunConfigurationPopup implements ExecutorProvider { private final Project myProject; - private final @NotNull String myAddKey; + final @NotNull String myAddKey; private final @NotNull Executor myDefaultExecutor; - private final @Nullable Executor myAlternativeExecutor; + final @Nullable Executor myAlternativeExecutor; private Executor myCurrentExecutor; - private boolean myEditConfiguration; - private RunListPopup myPopup; + boolean myEditConfiguration; + RunListPopup myPopup; public ChooseRunConfigurationPopup(@NotNull Project project, @NotNull String addKey, @@ -75,7 +66,7 @@ public final class ChooseRunConfigurationPopup implements ExecutorProvider { @RequiresBackgroundThread @NotNull ListPopupStep buildStep(@NotNull DataContext dataContext) { - List> settingsList = createSettingsList(myProject, this, dataContext, true); + List> settingsList = ChooseRunConfigurationManager.createSettingsList(myProject, this, dataContext, true); return new ConfigurationListPopupStep(this, myProject, myDefaultExecutor.getActionName(), settingsList); } @@ -195,7 +186,7 @@ public final class ChooseRunConfigurationPopup implements ExecutorProvider { } } - private void editConfiguration(@NotNull Project project, @NotNull RunnerAndConfigurationSettings configuration) { + void editConfiguration(@NotNull Project project, @NotNull RunnerAndConfigurationSettings configuration) { final Executor executor = getExecutor(); PropertiesComponent.getInstance().setValue("run.configuration.edit.ad", Boolean.toString(true)); if (RunDialog.editConfiguration(project, configuration, ExecutionBundle.message("dialog.title.edit.configuration.settings"), executor)) { @@ -204,42 +195,14 @@ public final class ChooseRunConfigurationPopup implements ExecutorProvider { } } + /** + * @deprecated Use {@link ChooseRunConfigurationManager#deleteConfiguration(Project, RunnerAndConfigurationSettings, JBPopup)} + */ + @Deprecated public static void deleteConfiguration(@NotNull Project project, @NotNull RunnerAndConfigurationSettings configurationSettings, @Nullable JBPopup popupToCancel) { - RunManagerConfig runManagerConfig = RunManagerImpl.getInstanceImpl(project).getConfig(); - boolean confirmed; - if (runManagerConfig.isDeletionFromPopupRequiresConfirmation()) { - if (popupToCancel != null) { - popupToCancel.cancel(); - } - - confirmed = MessageDialogBuilder.yesNo(CommonBundle.message("title.confirmation"), - ExecutionBundle.message("are.you.sure.you.want.to.delete.0", configurationSettings.getName())) - .doNotAsk(new DoNotAskOption.Adapter() { - @Override - public void rememberChoice(boolean isSelected, int exitCode) { - runManagerConfig.setDeletionFromPopupRequiresConfirmation(!isSelected); - } - - @Override - public @NotNull String getDoNotShowMessage() { - return ExecutionBundle.message("don.t.ask.again"); - } - - @Override - public boolean shouldSaveOptionsOnCancel() { - return true; - } - }) - .ask(project); - } - else { - confirmed = true; - } - if (confirmed) { - RunManager.getInstance(project).removeConfiguration(configurationSettings); - } + ChooseRunConfigurationManager.deleteConfiguration(project, configurationSettings, popupToCancel); } @Override @@ -251,6 +214,17 @@ public final class ChooseRunConfigurationPopup implements ExecutorProvider { return new MyAbstractAction(listPopup, number, executor); } + /** + * @deprecated Use {@link ChooseRunConfigurationManager#createSettingsList(RunManagerImpl, ExecutorProvider, boolean, boolean, DataContext)} + */ + @Deprecated + public static @NotNull List> createSettingsList(@NotNull Project project, + @NotNull ExecutorProvider executorProvider, + @NotNull DataContext dataContext, + boolean isCreateEditAction) { + return ChooseRunConfigurationManager.createSettingsList(project, executorProvider, dataContext, isCreateEditAction); + } + @ApiStatus.Internal public abstract static class Wrapper implements NumericMnemonicItem { private int myMnemonic = -1; @@ -288,6 +262,7 @@ public final class ChooseRunConfigurationPopup implements ExecutorProvider { myMnemonic = mnemonic; } + @SuppressWarnings("SameParameterValue") protected void setMnemonicsEnabled(boolean mnemonicsEnabled) { myMnemonicsEnabled = mnemonicsEnabled; } @@ -415,7 +390,7 @@ public final class ChooseRunConfigurationPopup implements ExecutorProvider { @Override public PopupStep getNextStep(final @NotNull Project project, final @NotNull ChooseRunConfigurationPopup action) { - return new ConfigurationActionsStep(project, action, requireNonNull(getValue()), isDynamic()); + return new ChooseRunConfigurationManager.ConfigurationActionsStep(project, action, requireNonNull(getValue()), isDynamic()); } }; } @@ -426,289 +401,6 @@ public final class ChooseRunConfigurationPopup implements ExecutorProvider { } } - private static final class ConfigurationListPopupStep extends BaseListPopupStep> { - private final Project myProject; - private final ChooseRunConfigurationPopup myAction; - private int myDefaultConfiguration = -1; - - private ConfigurationListPopupStep(final @NotNull ChooseRunConfigurationPopup action, - final @NotNull Project project, - final @NotNull @Nls String title, - @NotNull List> list) { - super(title, list); - myProject = project; - myAction = action; - - if (-1 == getDefaultOptionIndex()) { - myDefaultConfiguration = getDynamicIndex(); - } - - boolean hasMnemonics = ContainerUtil.exists(getValues(), wrapper -> wrapper.getMnemonic() != -1); - if (hasMnemonics) getValues().forEach(wrapper -> wrapper.setMnemonicsEnabled(true)); - } - - private int getDynamicIndex() { - int i = 0; - for (ItemWrapper wrapper : getValues()) { - if (wrapper.isDynamic()) { - return i; - } - i++; - } - - return -1; - } - - @Override - public boolean isAutoSelectionEnabled() { - return false; - } - - @Override - public ListSeparator getSeparatorAbove(ItemWrapper value) { - if (value.addSeparatorAbove()) return new ListSeparator(); - - List> configurations = getValues(); - final int index = configurations.indexOf(value); - if (index > 0 && index <= configurations.size() - 1) { - ItemWrapper aboveConfiguration = configurations.get(index - 1); - - if (aboveConfiguration != null && aboveConfiguration.isDynamic() != value.isDynamic()) { - return new ListSeparator(); - } - - final ConfigurationType currentType = value.getType(); - final ConfigurationType aboveType = aboveConfiguration == null ? null : aboveConfiguration.getType(); - if (aboveType != currentType && currentType != null) { - return new ListSeparator(); // new ListSeparator(currentType.getDisplayName()); - } - } - - return null; - } - - @Override - public boolean isSpeedSearchEnabled() { - return true; - } - - @Override - public int getDefaultOptionIndex() { - final RunnerAndConfigurationSettings currentConfiguration = RunManager.getInstance(myProject).getSelectedConfiguration(); - if (currentConfiguration == null && myDefaultConfiguration != -1) { - return myDefaultConfiguration; - } - - return currentConfiguration instanceof RunnerAndConfigurationSettingsImpl ? getValues() - .indexOf(ItemWrapper.wrap(myProject, currentConfiguration)) : -1; - } - - @Override - public PopupStep onChosen(final ItemWrapper wrapper, boolean finalChoice) { - if (myAction.myEditConfiguration) { - final Object o = wrapper.getValue(); - if (o instanceof RunnerAndConfigurationSettingsImpl) { - return doFinalStep(() -> myAction.editConfiguration(myProject, (RunnerAndConfigurationSettings)o)); - } - } - - if (finalChoice && wrapper.available(myAction.getExecutor())) { - return doFinalStep(() -> { - if (myAction.getExecutor() == myAction.myAlternativeExecutor) { - PropertiesComponent.getInstance().setValue(myAction.myAddKey, Boolean.toString(true)); - } - - wrapper.perform(myProject, myAction.getExecutor(), DataManager.getInstance().getDataContext()); - }); - } - else { - return wrapper.getNextStep(myProject, myAction); - } - } - - @Override - public boolean isFinal(ItemWrapper wrapper) { - return myAction.myEditConfiguration - || wrapper.available(myAction.getExecutor()) - || wrapper.getNextStep(myProject, myAction) == FINAL_CHOICE; - } - - @Override - public boolean hasSubstep(ItemWrapper selectedValue) { - return selectedValue.hasActions(); - } - - @Override - public @NotNull String getTextFor(ItemWrapper value) { - //noinspection DialogTitleCapitalization - return value.getText(); - } - - @Override - public Icon getIconFor(ItemWrapper value) { - return value.getIcon(); - } - } - - private static final class ConfigurationActionsStep extends BaseListPopupStep { - - private final @NotNull RunnerAndConfigurationSettings mySettings; - private final @NotNull Project myProject; - - private ConfigurationActionsStep(final @NotNull Project project, - ChooseRunConfigurationPopup action, - final @NotNull RunnerAndConfigurationSettings settings, final boolean dynamic) { - super(null, buildActions(project, action, settings, dynamic)); - myProject = project; - mySettings = settings; - } - - public @NotNull RunnerAndConfigurationSettings getSettings() { - return mySettings; - } - - public @NlsContexts.ListItem String getName() { - return Executor.shortenNameIfNeeded(mySettings.getName()); - } - - public Icon getIcon() { - return RunManagerEx.getInstanceEx(myProject).getConfigurationIcon(mySettings); - } - - @Override - public ListSeparator getSeparatorAbove(ActionWrapper value) { - return value.addSeparatorAbove() ? new ListSeparator() : null; - } - - private static ActionWrapper[] buildActions(final @NotNull Project project, - final ChooseRunConfigurationPopup action, - final @NotNull RunnerAndConfigurationSettings settings, - final boolean dynamic) { - final List result = new ArrayList<>(); - - final ExecutionTarget active = ExecutionTargetManager.getActiveTarget(project); - for (final ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, settings.getConfiguration())) { - result.add(new ActionWrapper(eachTarget.getDisplayName(), eachTarget.getIcon()) { - { - setChecked(eachTarget.equals(active)); - } - - @Override - public void perform() { - final RunManager manager = RunManager.getInstance(project); - if (dynamic) { - manager.setTemporaryConfiguration(settings); - } - manager.setSelectedConfiguration(settings); - - ExecutionTargetManager.setActiveTarget(project, eachTarget); - ExecutionUtil.runConfiguration(settings, action.getExecutor()); - } - }); - } - - boolean isFirst = true; - final List allExecutors = new ArrayList<>(); - for (Executor executor: Executor.EXECUTOR_EXTENSION_NAME.getExtensionList()) { - if (executor instanceof ExecutorGroup) { - allExecutors.addAll(((ExecutorGroup)executor).childExecutors()); - } - else { - allExecutors.add(executor); - } - } - for (final Executor executor : allExecutors) { - if (ExecutorRegistryImpl.RunnerHelper.canRun(project, executor, settings.getConfiguration())) { - result.add(new ActionWrapper(executor.getActionName(), executor.getIcon(), isFirst) { - @Override - public void perform() { - final RunManager manager = RunManager.getInstance(project); - if (dynamic) { - manager.setTemporaryConfiguration(settings); - } - if (!manager.isRiderRunWidgetActive()) manager.setSelectedConfiguration(settings); - ExecutorRegistryImpl.RunnerHelper.run(project, settings.getConfiguration(), settings, DataContext.EMPTY_CONTEXT, executor); - } - }); - isFirst = false; - } - } - - result.add(new ActionWrapper(ExecutionBundle.message("choose.run.popup.edit"), AllIcons.Actions.EditSource, true) { - @Override - public void perform() { - if (dynamic) { - RunManager.getInstance(project).setTemporaryConfiguration(settings); - } - action.editConfiguration(project, settings); - } - }); - - if (settings.isTemporary() || dynamic) { - result.add(new ActionWrapper(ExecutionBundle.message("choose.run.popup.save"), AllIcons.Actions.MenuSaveall) { - @Override - public void perform() { - final RunManager manager = RunManager.getInstance(project); - if (dynamic) { - manager.setTemporaryConfiguration(settings); - } - manager.makeStable(settings); - } - }); - } - result.add(new ActionWrapper(ExecutionBundle.message("choose.run.popup.delete"), AllIcons.Actions.Cancel) { - @Override - public void perform() { - deleteConfiguration(project, settings, action.myPopup); - } - }); - - return result.toArray(new ActionWrapper[0]); - } - - @Override - public PopupStep onChosen(final ActionWrapper selectedValue, boolean finalChoice) { - return doFinalStep(() -> selectedValue.perform()); - } - - @Override - public Icon getIconFor(ActionWrapper aValue) { - return aValue.getIcon(); - } - - @Override - public @NotNull String getTextFor(ActionWrapper value) { - return value.getText(); - } - } - - private abstract static class ActionWrapper extends Wrapper { - private final @Nls String myName; - private final Icon myIcon; - - private ActionWrapper(@Nls String name, Icon icon) { - this(name, icon, false); - } - - private ActionWrapper(@Nls String name, Icon icon, boolean addSeparatorAbove) { - super(addSeparatorAbove); - myName = name; - myIcon = icon; - } - - public abstract void perform(); - - @Override - public String getText() { - return myName; - } - - @Override - public Icon getIcon() { - return myIcon; - } - } - private static final class MyAbstractAction extends AbstractAction implements DumbAware { private final ListPopupImpl myListPopup; private final int myNumber; @@ -808,7 +500,7 @@ public final class ChooseRunConfigurationPopup implements ExecutorProvider { final Object o = getListModel().get(index); if (o instanceof ItemWrapper && ((ItemWrapper)o).canBeDeleted()) { RunnerAndConfigurationSettings runConfig = (RunnerAndConfigurationSettings)((ItemWrapper)o).getValue(); - deleteConfiguration(myProject, requireNonNull(runConfig), ChooseRunConfigurationPopup.this.myPopup); + ChooseRunConfigurationManager.deleteConfiguration(myProject, requireNonNull(runConfig), ChooseRunConfigurationPopup.this.myPopup); getListModel().deleteItem(o); List values = getListStep().getValues(); @@ -828,376 +520,4 @@ public final class ChooseRunConfigurationPopup implements ExecutorProvider { return true; } } - - private static final class FolderWrapper extends ItemWrapper { - private final Project myProject; - private final ExecutorProvider myExecutorProvider; - private final List myConfigurations; - - private FolderWrapper(Project project, ExecutorProvider executorProvider, @Nullable String value, List configurations) { - super(value); - myProject = project; - myExecutorProvider = executorProvider; - myConfigurations = configurations; - } - - @Override - public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) { - RunManager runManager = RunManager.getInstance(project); - RunnerAndConfigurationSettings selectedConfiguration = runManager.getSelectedConfiguration(); - if (myConfigurations.contains(selectedConfiguration)) { - runManager.setSelectedConfiguration(selectedConfiguration); - ExecutionUtil.runConfiguration(requireNonNull(selectedConfiguration), myExecutorProvider.getExecutor()); - } - } - - @Override - public @NotNull Icon getIcon() { - return AllIcons.Nodes.Folder; - } - - @Override - public String getText() { - return getValue(); - } - - @Override - public @Nullable ConfigurationType getType() { - return Registry.is("run.popup.move.folders.to.top") || myConfigurations.isEmpty() - ? null - : myConfigurations.get(0).getType(); - } - - @Override - public boolean hasActions() { - return true; - } - - @Override - public PopupStep getNextStep(Project project, ChooseRunConfigurationPopup action) { - List steps = new ArrayList<>(); - for (RunnerAndConfigurationSettings settings : myConfigurations) { - steps.add(new ConfigurationActionsStep(project, action, settings, false)); - } - return new FolderStep(myProject, myExecutorProvider, null, steps, action); - } - } - - private static final class FolderStep extends BaseListPopupStep { - private final Project myProject; - private final ChooseRunConfigurationPopup myPopup; - private final ExecutorProvider myExecutorProvider; - - private FolderStep(Project project, ExecutorProvider executorProvider, @NlsSafe String folderName, List children, - ChooseRunConfigurationPopup popup) { - super(folderName, children, new ArrayList<>()); - myProject = project; - myExecutorProvider = executorProvider; - myPopup = popup; - } - - @Override - public PopupStep onChosen(final ConfigurationActionsStep selectedValue, boolean finalChoice) { - if (finalChoice) { - if (myPopup.myEditConfiguration) { - final RunnerAndConfigurationSettings settings = selectedValue.getSettings(); - return doFinalStep(() -> myPopup.editConfiguration(myProject, settings)); - } - - return doFinalStep(() -> { - RunnerAndConfigurationSettings settings = selectedValue.getSettings(); - RunManager.getInstance(myProject).setSelectedConfiguration(settings); - ExecutionUtil.runConfiguration(settings, myExecutorProvider.getExecutor()); - }); - } else { - return selectedValue; - } - } - - @Override - public Icon getIconFor(ConfigurationActionsStep aValue) { - return aValue.getIcon(); - } - - @Override - public @NotNull String getTextFor(ConfigurationActionsStep value) { - return value.getName(); - } - - @Override - public boolean hasSubstep(ConfigurationActionsStep selectedValue) { - return !selectedValue.getValues().isEmpty(); - } - } - - /** - * @deprecated Use {@link #createSettingsList(Project, ExecutorProvider, DataContext, boolean)} - */ - @Deprecated(forRemoval = true) - public static @NotNull List> createSettingsList(@NotNull Project project, - @NotNull ExecutorProvider executorProvider, - boolean isCreateEditAction) { - return createSettingsList(project, executorProvider, DataManager.getInstance().getDataContext(), isCreateEditAction); - } - - public static @NotNull List> createSettingsList(@NotNull Project project, - @NotNull ExecutorProvider executorProvider, - @NotNull DataContext dataContext, - boolean isCreateEditAction) { - RunManager runManager = RunManager.getInstanceIfCreated(project); - if (runManager == null) { - return Collections.emptyList(); - } - //noinspection TestOnlyProblems - return createSettingsList((RunManagerImpl)runManager, executorProvider, isCreateEditAction, - Registry.is("run.popup.move.folders.to.top", false), dataContext); - } - - public static List> createFlatSettingsList(@NotNull Project project) { - return RunManagerImplKt.createFlatSettingsList(project); - } - - @TestOnly - public static @NotNull List> createSettingsList(@NotNull RunManagerImpl runManager, - @NotNull ExecutorProvider executorProvider, - boolean isCreateEditAction, - boolean isMoveFoldersToTop, - @NotNull DataContext dataContext) { - List> result = new ArrayList<>(); - - if (isCreateEditAction) { - result.add(createEditAction()); - } - - Project project = runManager.getProject(); - final RunnerAndConfigurationSettings selectedConfiguration = runManager.getSelectedConfiguration(); - if (selectedConfiguration != null) { - addActionsForSelected(selectedConfiguration, project, result); - } - - Map> wrappedExisting = new LinkedHashMap<>(); - List folderWrappers = new SmartList<>(); - for (Map> folderToConfigurations : runManager.getConfigurationsGroupedByTypeAndFolder(false).values()) { - if (isMoveFoldersToTop) { - for (Map.Entry> entry : folderToConfigurations.entrySet()) { - final String folderName = entry.getKey(); - List configurations = entry.getValue(); - if (folderName != null) { - folderWrappers.add(createFolderItem(project, executorProvider, selectedConfiguration, folderName, configurations)); - } - else { - for (RunnerAndConfigurationSettings configuration : configurations) { - wrapAndAdd(project, configuration, selectedConfiguration, wrappedExisting); - } - } - } - } - else { - // add only folders - for (Map.Entry> entry : folderToConfigurations.entrySet()) { - final String folderName = entry.getKey(); - if (folderName != null) { - result.add(createFolderItem(project, executorProvider, selectedConfiguration, folderName, entry.getValue())); - } - } - - // add configurations - List configurations = folderToConfigurations.get(null); - if (!ContainerUtil.isEmpty(configurations)) { - for (RunnerAndConfigurationSettings configuration : configurations) { - result.add(wrapAndAdd(project, configuration, selectedConfiguration, wrappedExisting)); - } - } - } - } - - if (isMoveFoldersToTop) { - result.addAll(folderWrappers); - } - if (!DumbService.isDumb(project)) { - populateWithDynamicRunners(result, wrappedExisting, project, RunManagerEx.getInstanceEx(project), selectedConfiguration, dataContext); - } - if (isMoveFoldersToTop) { - result.addAll(wrappedExisting.values()); - } - return result; - } - - private static @NotNull ItemWrapper wrapAndAdd(@NotNull Project project, - @NotNull RunnerAndConfigurationSettings configuration, - @Nullable RunnerAndConfigurationSettings selectedConfiguration, - @NotNull Map> wrappedExisting) { - ItemWrapper wrapped = ItemWrapper.wrap(project, configuration); - if (configuration == selectedConfiguration) { - wrapped.setMnemonic(1); - } - wrappedExisting.put(configuration, wrapped); - return wrapped; - } - - private static @NotNull FolderWrapper createFolderItem(@NotNull Project project, - @NotNull ExecutorProvider executorProvider, - @Nullable RunnerAndConfigurationSettings selectedConfiguration, - @NotNull String folderName, - @NotNull List configurations) { - boolean isSelected = selectedConfiguration != null && configurations.contains(selectedConfiguration); - String value = folderName; - if (isSelected) { - value += " (mnemonic is to \"" + selectedConfiguration.getName() + "\")"; - } - FolderWrapper result = new FolderWrapper(project, executorProvider, value, configurations); - if (isSelected) { - result.setMnemonic(1); - } - return result; - } - - private static void addActionsForSelected(@NotNull RunnerAndConfigurationSettings selectedConfiguration, - @NotNull Project project, - @NotNull List> result) { - boolean isFirst = true; - final ExecutionTarget activeTarget = ExecutionTargetManager.getActiveTarget(project); - for (ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selectedConfiguration.getConfiguration())) { - ItemWrapper itemWrapper = new ItemWrapper<>(eachTarget, isFirst) { - @Override - public Icon getIcon() { - return requireNonNull(getValue()).getIcon(); - } - - @Override - public String getText() { - return requireNonNull(getValue()).getDisplayName(); - } - - @Override - public void perform(final @NotNull Project project, final @NotNull Executor executor, @NotNull DataContext context) { - ExecutionTargetManager.setActiveTarget(project, requireNonNull(getValue())); - ExecutionUtil.doRunConfiguration(selectedConfiguration, executor, null, null, context); - } - - @Override - public boolean available(Executor executor) { - return true; - } - }; - itemWrapper.setChecked(eachTarget.equals(activeTarget)); - result.add(itemWrapper); - isFirst = false; - } - } - - private static @NotNull ItemWrapper createEditAction() { - ItemWrapper result = new ItemWrapper<>(null) { - @Override - public Icon getIcon() { - return AllIcons.Actions.EditSource; - } - - @Override - public String getText() { - return UIUtil.removeMnemonic(ActionsBundle.message("action.editRunConfigurations.text")); - } - - @Override - public void perform(final @NotNull Project project, final @NotNull Executor executor, @NotNull DataContext context) { - if (new EditConfigurationsDialog(project) { - @Override - protected void init() { - setOKButtonText(executor.getActionName()); - myExecutor = executor; - super.init(); - } - }.showAndGet()) { - ApplicationManager.getApplication().invokeLater(() -> { - RunnerAndConfigurationSettings configuration = RunManager.getInstance(project).getSelectedConfiguration(); - if (configuration != null) { - ExecutionUtil.doRunConfiguration(configuration, executor, null, null, context); - } - }, project.getDisposed()); - } - } - - @Override - public boolean available(Executor executor) { - return true; - } - }; - result.setMnemonic(0); - return result; - } - - private static void populateWithDynamicRunners(List> result, - Map> existing, - Project project, - RunManager manager, - RunnerAndConfigurationSettings selectedConfiguration, - @NotNull DataContext dataContext) { - final ConfigurationContext context = ConfigurationContext.getFromContext(dataContext, ActionPlaces.UNKNOWN); - - List producers = PreferredProducerFind.getConfigurationsFromContext(context.getLocation(), - context, false, true); - if (producers == null) return; - - producers = ContainerUtil.sorted(producers, ConfigurationFromContext.NAME_COMPARATOR); - - final RunnerAndConfigurationSettings[] preferred = {null}; - - int i = 2; // selectedConfiguration == null ? 1 : 2; - for (final ConfigurationFromContext fromContext : producers) { - final RunnerAndConfigurationSettings configuration = fromContext.getConfigurationSettings(); - if (existing.containsKey(configuration)) { - ItemWrapper wrapper = existing.get(configuration); - if (wrapper.getMnemonic() != 1) { - wrapper.setMnemonic(i); - i++; - } - } - else { - if (selectedConfiguration != null && configuration.equals(selectedConfiguration)) continue; - - if (preferred[0] == null) { - preferred[0] = configuration; - } - - ItemWrapper wrapper = new ItemWrapper(configuration) { - @Override - public Icon getIcon() { - return RunManagerEx.getInstanceEx(project).getConfigurationIcon(configuration); - } - - @Override - public String getText() { - return Executor.shortenNameIfNeeded(configuration.getName()) + configuration.getConfiguration().getPresentableType(); - } - - @Override - public boolean available(Executor executor) { - return ProgramRunner.getRunner(executor.getId(), configuration.getConfiguration()) != null; - } - - @Override - public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) { - manager.setTemporaryConfiguration(configuration); - RunManager.getInstance(project).setSelectedConfiguration(configuration); - ExecutionUtil.doRunConfiguration(configuration, executor, null, null, context); - } - - @Override - public PopupStep getNextStep(final @NotNull Project project, final @NotNull ChooseRunConfigurationPopup action) { - return new ConfigurationActionsStep(project, action, configuration, isDynamic()); - } - - @Override - public boolean hasActions() { - return true; - } - }; - - wrapper.setDynamic(true); - wrapper.setMnemonic(i); - result.add(wrapper); - i++; - } - } - } } diff --git a/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopupAction.kt b/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopupAction.kt index 13c040d36358..eb4912e50f1a 100644 --- a/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopupAction.kt +++ b/platform/execution-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopupAction.kt @@ -28,7 +28,7 @@ open class ChooseRunConfigurationPopupAction : AnAction(), DumbAware { popup.show(step) } - override fun getActionUpdateThread() = ActionUpdateThread.BGT + override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT override fun update(e: AnActionEvent) { e.presentation.isEnabledAndVisible = e.getData(CommonDataKeys.PROJECT)?.isDisposed == false && defaultExecutor != null diff --git a/platform/execution-impl/src/com/intellij/execution/startup/ProjectStartupConfigurable.java b/platform/execution-impl/src/com/intellij/execution/startup/ProjectStartupConfigurable.java index ed0670edf30c..a15fbd95e3ed 100644 --- a/platform/execution-impl/src/com/intellij/execution/startup/ProjectStartupConfigurable.java +++ b/platform/execution-impl/src/com/intellij/execution/startup/ProjectStartupConfigurable.java @@ -5,6 +5,7 @@ import com.intellij.execution.ExecutionBundle; import com.intellij.execution.Executor; import com.intellij.execution.RunManager; import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.actions.ChooseRunConfigurationManager; import com.intellij.execution.actions.ChooseRunConfigurationPopup; import com.intellij.execution.actions.ExecutorProvider; import com.intellij.execution.configurations.ConfigurationFactory; @@ -260,7 +261,7 @@ final class ProjectStartupConfigurable implements SearchableConfigurable, Config final Executor executor = DefaultRunExecutor.getRunExecutorInstance(); final List> wrappers = new ArrayList<>(); wrappers.add(createNewWrapper(button)); - var allSettings = ChooseRunConfigurationPopup.createSettingsList(myProject, new ExecutorProvider() { + var allSettings = ChooseRunConfigurationManager.createSettingsList(myProject, new ExecutorProvider() { @Override public Executor getExecutor() { return executor; diff --git a/platform/lang-impl/api-dump-unreviewed.txt b/platform/lang-impl/api-dump-unreviewed.txt index 186b72e0cb6f..06d19cdbfb7e 100644 --- a/platform/lang-impl/api-dump-unreviewed.txt +++ b/platform/lang-impl/api-dump-unreviewed.txt @@ -8413,21 +8413,6 @@ f:com.intellij.ide.actions.searcheverywhere.RecentFilesSEContributor$Factory - com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributorFactory - ():V - createContributor(com.intellij.openapi.actionSystem.AnActionEvent):com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributor -f:com.intellij.ide.actions.searcheverywhere.RunConfigurationsSEContributor -- com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributor -- (com.intellij.openapi.project.Project,java.awt.Component,java.util.function.Supplier):V -- fetchElements(java.lang.String,com.intellij.openapi.progress.ProgressIndicator,com.intellij.util.Processor):V -- getElementsRenderer():javax.swing.ListCellRenderer -- getGroupName():java.lang.String -- getSearchProviderId():java.lang.String -- getSortWeight():I -- getSupportedCommands():java.util.List -- processSelectedItem(com.intellij.execution.actions.ChooseRunConfigurationPopup$ItemWrapper,I,java.lang.String):Z -- showInFindResults():Z -f:com.intellij.ide.actions.searcheverywhere.RunConfigurationsSEContributor$Factory -- com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributorFactory -- ():V -- createContributor(com.intellij.openapi.actionSystem.AnActionEvent):com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributor f:com.intellij.ide.actions.searcheverywhere.SEResultsEqualityProvider$Companion - f:composite(java.util.Collection):com.intellij.ide.actions.searcheverywhere.SEResultsEqualityProvider - f:getEP_NAME():com.intellij.openapi.extensions.ExtensionPointName diff --git a/platform/lang-impl/src/com/intellij/ide/actions/runAnything/RunAnythingRunConfigurationProvider.java b/platform/lang-impl/src/com/intellij/ide/actions/runAnything/RunAnythingRunConfigurationProvider.java index 7101b9e1a5ac..d1aafdce88cd 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/runAnything/RunAnythingRunConfigurationProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/runAnything/RunAnythingRunConfigurationProvider.java @@ -1,7 +1,7 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.actions.runAnything; -import com.intellij.execution.actions.ChooseRunConfigurationPopup; +import com.intellij.execution.actions.ChooseRunConfigurationManager; import com.intellij.execution.actions.ChooseRunConfigurationPopup.ItemWrapper; import com.intellij.ide.IdeBundle; import com.intellij.openapi.actionSystem.DataContext; @@ -40,9 +40,9 @@ public final class RunAnythingRunConfigurationProvider extends com.intellij.ide. private static Collection sort(@NotNull Project project, @NotNull String pattern) { MinusculeMatcher matcher = NameUtil.buildMatcher("*" + pattern).build(); - List> list = ChooseRunConfigurationPopup.createFlatSettingsList(project); + List> list = ChooseRunConfigurationManager.createFlatSettingsList(project); TreeMap map = new TreeMap<>(Comparator.reverseOrder()); - for (ItemWrapper wrapper : list) { + for (ItemWrapper wrapper : list) { String name = wrapper.getText(); FList fragments = matcher.matchingFragments(name); if (fragments != null) { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/RunConfigurationsSEContributor.java b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/RunConfigurationsSEContributor.java index 41e5697189e2..206e75f59f6d 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/RunConfigurationsSEContributor.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/searcheverywhere/RunConfigurationsSEContributor.java @@ -4,6 +4,7 @@ package com.intellij.ide.actions.searcheverywhere; import com.intellij.execution.Executor; import com.intellij.execution.ExecutorRegistry; import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.actions.ChooseRunConfigurationManager; import com.intellij.execution.actions.ChooseRunConfigurationPopup; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.execution.executors.DefaultRunExecutor; @@ -27,6 +28,7 @@ import com.intellij.util.Processor; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.intellij.lang.annotations.MagicConstant; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,6 +41,7 @@ import java.util.List; import java.util.Optional; import java.util.function.Supplier; +@ApiStatus.Internal public final class RunConfigurationsSEContributor implements SearchEverywhereContributor { private final SearchEverywhereCommandInfo RUN_COMMAND = @@ -113,7 +116,7 @@ public final class RunConfigurationsSEContributor implements SearchEverywhereCon pattern = filterString(pattern); MinusculeMatcher matcher = NameUtil.buildMatcher(pattern).build(); - for (ChooseRunConfigurationPopup.ItemWrapper wrapper : ChooseRunConfigurationPopup.createFlatSettingsList(myProject)) { + for (ChooseRunConfigurationPopup.ItemWrapper wrapper : ChooseRunConfigurationManager.createFlatSettingsList(myProject)) { if (matcher.matches(wrapper.getText()) && !consumer.process(wrapper)) { return; } diff --git a/platform/platform-api/resources/messages/IdeBundle.properties b/platform/platform-api/resources/messages/IdeBundle.properties index 4f6415fd43d0..61216e3d24f1 100644 --- a/platform/platform-api/resources/messages/IdeBundle.properties +++ b/platform/platform-api/resources/messages/IdeBundle.properties @@ -1131,7 +1131,7 @@ run.anything.recent.project.command.placeholder=open run.anything.actions.undefined=Undefined run.anything.notification.warning.content=Command ''{0}'' failed to execute. run.anything.notification.warning.title=Failed Command Execution -run.anything.run.configurations.group.title=Run configurations +run.anything.run.configurations.group.title=Run Configurations run.anything.help.list.empty.secondary.text=Select command run.anything.main.list.empty.primary.text=Run command or configuration run.anything.main.list.empty.secondary.text=Type "?" to see all commands