diff --git a/platform/lang-impl/src/com/intellij/execution/RunManagerConfig.java b/platform/lang-impl/src/com/intellij/execution/RunManagerConfig.java index c9081bd4f632..1e81b5d07823 100644 --- a/platform/lang-impl/src/com/intellij/execution/RunManagerConfig.java +++ b/platform/lang-impl/src/com/intellij/execution/RunManagerConfig.java @@ -26,6 +26,7 @@ public class RunManagerConfig { private final StoringPropertyContainer myProperties; private final PropertiesComponent myPropertiesComponent; @NonNls private static final String RECENTS_LIMIT = "recentsLimit"; + @NonNls private static final String RESTART_REQUIRES_CONFIRMATION = "restartRequiresConfirmation"; public RunManagerConfig(PropertiesComponent propertiesComponent, RunManagerImpl manager) { @@ -45,4 +46,12 @@ public class RunManagerConfig { public void setRecentsLimit(int recentsLimit) { myPropertiesComponent.setValue(RECENTS_LIMIT, Integer.toString(recentsLimit)); } + + public boolean isRestartRequiresConfirmation() { + return myPropertiesComponent.getBoolean(RESTART_REQUIRES_CONFIRMATION, true); + } + + public void setRestartRequiresConfirmation (boolean restartRequiresConfirmation) { + myPropertiesComponent.setValue(RESTART_REQUIRES_CONFIRMATION, String.valueOf(restartRequiresConfirmation)); + } } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java index 48754f47d68e..725498e82ff1 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java @@ -46,6 +46,7 @@ import com.intellij.util.containers.HashMap; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import gnu.trove.THashSet; +import net.miginfocom.swing.MigLayout; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -91,7 +92,8 @@ class RunConfigurable extends BaseConfigurable { private final StorageAccessors myProperties = StorageAccessors.createGlobal("RunConfigurable"); private Configurable mySelectedConfigurable = null; private static final Logger LOG = Logger.getInstance("#com.intellij.execution.impl.RunConfigurable"); - private final JTextField myRecentsLimit = new JTextField("5"); + private final JTextField myRecentsLimit = new JTextField("5", 2); + private final JCheckBox myConfirmation = new JCheckBox(ExecutionBundle.message("rerun.confirmation.checkbox"), true); private Map myStoredComponents = new HashMap(); public RunConfigurable(final Project project) { @@ -449,21 +451,23 @@ class RunConfigurable extends BaseConfigurable { } private JPanel createRecentLimitPanel() { - final JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEADING)); + final JPanel bottomPanel = new JPanel(new MigLayout("ins 5, gap 5")); -// box.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); bottomPanel.add(new JLabel("Temporary configurations limit:")); - Dimension size = new Dimension(25, myRecentsLimit.getPreferredSize().height); - myRecentsLimit.setPreferredSize(size); - myRecentsLimit.setMaximumSize(size); - myRecentsLimit.setMinimumSize(size); - bottomPanel.add(myRecentsLimit); + bottomPanel.add(myRecentsLimit, "wrap, h pref!, w pref!"); + bottomPanel.add(myConfirmation, "spanx 2"); myRecentsLimit.getDocument().addDocumentListener(new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { setModified(true); } }); + myConfirmation.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + setModified(true); + } + }); return bottomPanel; } @@ -534,6 +538,7 @@ class RunConfigurable extends BaseConfigurable { final RunManagerEx manager = getRunManager(); final RunManagerConfig config = manager.getConfig(); myRecentsLimit.setText(Integer.toString(config.getRecentsLimit())); + myConfirmation.setSelected(config.isRestartRequiresConfirmation()); setModified(false); } @@ -562,6 +567,7 @@ class RunConfigurable extends BaseConfigurable { catch (NumberFormatException e) { // ignore } + manager.getConfig().setRestartRequiresConfirmation(myConfirmation.isSelected()); for (Configurable configurable : myStoredComponents.values()) { if (configurable.isModified()){ diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java b/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java index f34291e9113c..89f9f41b1fee 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java @@ -15,7 +15,9 @@ */ package com.intellij.execution.runners; +import com.intellij.CommonBundle; import com.intellij.execution.*; +import com.intellij.execution.impl.RunManagerImpl; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.ide.DataManager; @@ -23,8 +25,10 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.IconLoader; +import com.intellij.util.Alarm; import javax.swing.*; @@ -40,6 +44,7 @@ public class RestartAction extends AnAction implements DumbAware { private final Executor myExecutor; private final Icon myIcon; private final ExecutionEnvironment myEnvironment; + private final Alarm awaitingTerminationAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); public RestartAction(final Executor executor, final ProgramRunner runner, @@ -60,8 +65,60 @@ public class RestartAction extends AnAction implements DumbAware { public void actionPerformed(final AnActionEvent e) { final DataContext dataContext = e.getDataContext(); + final RunManagerConfig config = RunManagerImpl.getInstanceImpl(myEnvironment.getProject()).getConfig(); + if (myProcessHandler != null && !myProcessHandler.isProcessTerminated() && config.isRestartRequiresConfirmation()) { + DialogWrapper.DoNotAskOption option = new DialogWrapper.DoNotAskOption() { + @Override + public boolean isToBeShown() { + return config.isRestartRequiresConfirmation(); + } + + @Override + public void setToBeShown(boolean value, int exitCode) { + config.setRestartRequiresConfirmation(value); + } + + @Override + public boolean canBeHidden() { + return true; + } + + @Override + public boolean shouldSaveOptionsOnCancel() { + return false; + } + + @Override + public String getDoNotShowMessage() { + return CommonBundle.message("dialog.options.do.not.show"); + } + }; + if (Messages.OK != Messages.showOkCancelDialog(ExecutionBundle.message("rerun.confirmation.message", myEnvironment.getRunProfile().getName()), + ExecutionBundle.message("rerun.confirmation.title"), CommonBundle.message("button.ok"), + CommonBundle.message("button.cancel"), + Messages.getQuestionIcon(), option)) { + return; + } + } ActionManager.getInstance().getAction(IdeActions.ACTION_STOP_PROGRAM).actionPerformed(e); - doRestart(dataContext); + update(e); + if (myProcessHandler != null) { + Runnable runnable = new Runnable() { + @Override + public void run() { + if (myProcessHandler == null || myProcessHandler.isProcessTerminated()) { + doRestart(dataContext); + } + else { + awaitingTerminationAlarm.addRequest(this, 100); + } + } + }; + awaitingTerminationAlarm.addRequest(runnable, 100); + } + else { + doRestart(dataContext); + } } public void restart() { @@ -93,8 +150,9 @@ public class RestartAction extends AnAction implements DumbAware { myProcessHandler = null; // already terminated } presentation.setIcon(isRunning ? STOP_AND_START_ICON : myIcon); - - presentation.setEnabled(!ExecutorRegistry.getInstance().isStarting(myEnvironment.getProject(), myExecutor.getId(), myRunner.getRunnerId())); + boolean isTerminating = myProcessHandler != null && myProcessHandler.isProcessTerminating(); + boolean isStarting = ExecutorRegistry.getInstance().isStarting(myEnvironment.getProject(), myExecutor.getId(), myRunner.getRunnerId()); + presentation.setEnabled(!isStarting && !isTerminating); } public void registerShortcut(final JComponent component) { diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index afde9982522f..4321036ede15 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -159,6 +159,9 @@ terminating.process.progress.title=Terminating ''{0}'' waiting.for.vm.detach.progress.text=Waiting for process detach restart.error.message.title=Restart Error rerun.configuration.action.name=Rerun {0} +rerun.confirmation.message=Are you sure you want to stop ''{0}'' +rerun.confirmation.title=Stop Confirmation +rerun.confirmation.checkbox=Confirm rerun with process termination run.configuration.dump.threads.action.name=Dump Threads run.configuration.exit.action.name=Exit run.error.message.title=Run Error