diff --git a/java/compiler/impl/src/com/intellij/build/AbstractViewManager.java b/java/compiler/impl/src/com/intellij/build/AbstractViewManager.java index f779382847a0..f58baaa51722 100644 --- a/java/compiler/impl/src/com/intellij/build/AbstractViewManager.java +++ b/java/compiler/impl/src/com/intellij/build/AbstractViewManager.java @@ -16,17 +16,19 @@ package com.intellij.build; import com.intellij.build.events.*; +import com.intellij.execution.actions.StopAction; import com.intellij.execution.actions.StopProcessAction; -import com.intellij.execution.console.DuplexConsoleView; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ExecutionEnvironment; -import com.intellij.execution.ui.ConsoleView; -import com.intellij.execution.ui.ConsoleViewContentType; -import com.intellij.execution.ui.ExecutionConsole; +import com.intellij.execution.runners.FakeRerunAction; +import com.intellij.execution.ui.*; +import com.intellij.execution.ui.actions.CloseAction; +import com.intellij.execution.ui.layout.impl.RunnerLayoutUiImpl; import com.intellij.icons.AllIcons; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComponentContainer; import com.intellij.openapi.ui.ThreeComponentsSplitter; import com.intellij.openapi.util.Disposer; import com.intellij.ui.SimpleColoredComponent; @@ -35,17 +37,21 @@ import com.intellij.ui.components.JBList; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.content.Content; import com.intellij.ui.content.impl.ContentImpl; -import com.intellij.util.*; +import com.intellij.ui.content.tabs.PinToolwindowTabAction; +import com.intellij.util.Alarm; +import com.intellij.util.Consumer; +import com.intellij.util.ObjectUtils; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.EdtInvocationManager; import com.intellij.util.ui.EmptyIcon; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.border.EmptyBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; @@ -55,6 +61,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; /** * @author Vladislav.Soroka @@ -69,7 +76,7 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp @Nullable private final JBList myBuildsList; private final Map myBuildsMap; - private final Map> myViewMap; + private final Map myViewMap; private volatile Content myContent; private volatile DefaultActionGroup myToolbarActions; @@ -131,8 +138,7 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp } } if (shouldBeCleared) { - for (DuplexConsoleView view : myViewMap.values()) { - view.clear(); + for (BuildView view : myViewMap.values()) { Disposer.dispose(view); } listModel.clear(); @@ -166,40 +172,80 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp } ProcessHandler processHandler = ((StartBuildEvent)event).getProcessHandler(); - DuplexConsoleView view = myViewMap.computeIfAbsent(buildInfo, info -> { - ExecutionConsole executionConsole = ((StartBuildEvent)event).getExecutionConsole(); - if (executionConsole == null) { - executionConsole = new BuildTextConsoleView(myProject); + BuildView view = myViewMap.computeIfAbsent(buildInfo, info -> { + ExecutionConsole executionConsole = null; + ComponentContainer componentContainer = null; + Supplier contentDescriptorSupplier = ((StartBuildEvent)event).getContentDescriptorSupplier(); + if (contentDescriptorSupplier != null) { + RunContentDescriptor contentDescriptor = contentDescriptorSupplier.get(); + if (contentDescriptor != null) { + executionConsole = contentDescriptor.getExecutionConsole(); + List leftToolbarActions = ContainerUtil.newArrayList(); + RunnerLayoutUi layoutUi = contentDescriptor.getRunnerLayoutUi(); + if (layoutUi instanceof RunnerLayoutUiImpl) { + RunnerLayoutUiImpl layoutUiImpl = (RunnerLayoutUiImpl)layoutUi; + layoutUiImpl.setLeftToolbarVisible(false); + layoutUiImpl.setContentToolbarBefore(false); + leftToolbarActions.addAll(layoutUiImpl.getActions()); + } + JComponent component = contentDescriptor.getComponent(); + AnAction[] leftToolbarActionsArray = leftToolbarActions.toArray(new AnAction[leftToolbarActions.size()]); + componentContainer = new BuildConsoleView() { + @Override + public void onEvent(BuildEvent event) { + } + + @Override + public AnAction[] createConsoleActions() { + return leftToolbarActionsArray; + } + + @Override + public JComponent getComponent() { + return component; + } + + @Override + public JComponent getPreferredFocusableComponent() { + return component; + } + + @Override + public void dispose() { + } + }; + } } - final DuplexConsoleView duplexConsoleView = - new BuildDuplexConsoleView(executionConsole, ((StartBuildEvent)event)); - duplexConsoleView.setDisableSwitchConsoleActionOnProcessEnd(false); - duplexConsoleView.getSwitchConsoleActionPresentation().setIcon(AllIcons.Actions.ChangeView); - duplexConsoleView.getSwitchConsoleActionPresentation().setText("Toggle view"); - duplexConsoleView.enableConsole(!isConsoleEnabledByDefault()); + if (componentContainer == null) { + componentContainer = executionConsole = new BuildTextConsoleView(myProject); + } + final BuildView buildView = new BuildView(myProject, componentContainer, ((StartBuildEvent)event)); + buildView.enableView(!isConsoleEnabledByDefault()); if (processHandler != null) { + if (executionConsole instanceof ConsoleView) { + ((ConsoleView)executionConsole).attachToProcess(processHandler); + Consumer attachedConsoleConsumer = ((StartBuildEvent)event).getAttachedConsoleConsumer(); + if (attachedConsoleConsumer != null) { + attachedConsoleConsumer.consume((ConsoleView)executionConsole); + } + } if (!processHandler.isStartNotified()) { processHandler.startNotify(); } - ((ConsoleView)executionConsole).attachToProcess(processHandler); - Consumer attachedConsoleConsumer = ((StartBuildEvent)event).getAttachedConsoleConsumer(); - if (attachedConsoleConsumer != null) { - attachedConsoleConsumer.consume((ConsoleView)executionConsole); - } } - Disposer.register(myThreeComponentsSplitter, duplexConsoleView); + Disposer.register(myThreeComponentsSplitter, buildView); if (isTabbedView()) { final JComponent consoleComponent = new JPanel(new BorderLayout()); - consoleComponent.add(duplexConsoleView, BorderLayout.CENTER); + consoleComponent.add(buildView, BorderLayout.CENTER); DefaultActionGroup toolbarActions = new DefaultActionGroup(); consoleComponent.add(ActionManager.getInstance().createActionToolbar( "", toolbarActions, false).getComponent(), BorderLayout.WEST); - toolbarActions.addAll(duplexConsoleView.createConsoleActions()); + toolbarActions.addAll(buildView.createConsoleActions()); myBuildContentManager.addTabbedContent( consoleComponent, getViewName(), buildInfo.title + ", " + DateFormatUtil.formatDateTime(System.currentTimeMillis()) + " ", - true, AllIcons.CodeStyle.Gear, duplexConsoleView); + true, AllIcons.CodeStyle.Gear, buildView); } - return duplexConsoleView; + return buildView; }); if (!isTabbedView() && myThreeComponentsSplitter.getLastComponent() == null) { @@ -212,15 +258,15 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp myBuildsList.getModel().getSize() > 1 && myThreeComponentsSplitter.getFirstComponent() == null) { JBScrollPane scrollPane = new JBScrollPane(); - scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0)); + scrollPane.setBorder(JBUI.Borders.empty()); scrollPane.setViewportView(myBuildsList); myThreeComponentsSplitter.setFirstComponent(scrollPane); myBuildsList.setVisible(true); myBuildsList.setSelectedIndex(0); myThreeComponentsSplitter.repaint(); - for (DuplexConsoleView consoleView : myViewMap.values()) { - BuildConsoleView buildConsoleView = consoleView.getPrimaryConsoleView(); + for (BuildView consoleView : myViewMap.values()) { + BuildConsoleView buildConsoleView = consoleView.getPrimaryView(); if (buildConsoleView instanceof BuildTreeConsoleView) { ((BuildTreeConsoleView)buildConsoleView).hideRootNode(); } @@ -230,7 +276,7 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp myThreeComponentsSplitter.setFirstComponent(null); } myProgressWatcher.addBuild(buildInfo); - view.getPrimaryConsoleView().print("\r", ConsoleViewContentType.SYSTEM_OUTPUT); + //view.getPrimaryView().print("\r", ConsoleViewContentType.SYSTEM_OUTPUT); } else { if (event instanceof FinishBuildEvent) { @@ -247,18 +293,18 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp runnables.add(() -> { final BuildInfo buildInfo = myBuildsMap.get(event.getId()); - DuplexConsoleView view = myViewMap.get(buildInfo); + BuildView view = myViewMap.get(buildInfo); if (event instanceof OutputBuildEvent) { - ConsoleView consoleView = view.getSecondaryConsoleView(); + ComponentContainer consoleView = view.getSecondaryView(); if (consoleView instanceof BuildConsoleView) { ((BuildConsoleView)consoleView).onEvent(event); } - else { - consoleView.print(event.getMessage(), ConsoleViewContentType.NORMAL_OUTPUT); + else if ((consoleView instanceof ConsoleView)) { + ((ConsoleView)consoleView).print(event.getMessage(), ConsoleViewContentType.NORMAL_OUTPUT); } } else { - view.getPrimaryConsoleView().onEvent(event); + view.getPrimaryView().onEvent(event); } }); @@ -275,7 +321,7 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp BuildInfo selectedBuild = myBuildsList.getSelectedValue(); if (selectedBuild == null) return; - DuplexConsoleView view = myViewMap.get(selectedBuild); + BuildView view = myViewMap.get(selectedBuild); JComponent lastComponent = myThreeComponentsSplitter.getLastComponent(); if (view != null && lastComponent != view.getComponent()) { myThreeComponentsSplitter.setLastComponent(view.getComponent()); @@ -392,49 +438,61 @@ public abstract class AbstractViewManager implements BuildProgressListener, Disp } } - private class BuildDuplexConsoleView extends DuplexConsoleView implements DataProvider { - private final ExecutionConsole myExecutionConsole; + private static class BuildView extends CompositeView implements DataProvider { + private final ComponentContainer myComponentContainer; private final StartBuildEvent myEvent; - public BuildDuplexConsoleView(ExecutionConsole executionConsole, StartBuildEvent event) { - super(new BuildTreeConsoleView(AbstractViewManager.this.myProject), (ConsoleView)executionConsole); - myExecutionConsole = executionConsole; + public BuildView(Project project, ComponentContainer componentContainer, StartBuildEvent event) { + super(new BuildTreeConsoleView(project), componentContainer); + myComponentContainer = componentContainer; myEvent = event; } @NotNull @Override public AnAction[] createConsoleActions() { - final DefaultActionGroup textActionGroup = new DefaultActionGroup() { + final DefaultActionGroup rerunActionGroup = new DefaultActionGroup(); + AnAction stopAction = null; + if (myEvent.getProcessHandler() != null) { + stopAction = new StopProcessAction("Stop", "Stop", myEvent.getProcessHandler()); + } + final DefaultActionGroup consoleActionGroup = new DefaultActionGroup() { @Override public void update(AnActionEvent e) { super.update(e); - e.getPresentation().setVisible(!BuildDuplexConsoleView.this.isPrimaryConsoleEnabled()); + e.getPresentation().setVisible(!BuildView.this.isPrimaryConsoleEnabled()); } }; - final AnAction[] consoleActions = ((ConsoleView)myExecutionConsole).createConsoleActions(); - for (AnAction anAction : consoleActions) { - textActionGroup.add(anAction); + if (myComponentContainer instanceof BuildConsoleView) { + final AnAction[] consoleActions = ((BuildConsoleView)myComponentContainer).createConsoleActions(); + for (AnAction anAction : consoleActions) { + if (anAction instanceof StopAction) { + if (stopAction == null) { + stopAction = anAction; + } + } + else if (!(anAction instanceof FakeRerunAction || + anAction instanceof PinToolwindowTabAction || + anAction instanceof CloseAction)) { + consoleActionGroup.add(anAction); + } + } } - - final List anActions = ContainerUtil.newArrayList(); final DefaultActionGroup actionGroup = new DefaultActionGroup(); - AnAction[] restartActions = myEvent.getRestartActions(); - for (AnAction anAction : restartActions) { - actionGroup.add(anAction); + for (AnAction anAction : myEvent.getRestartActions()) { + rerunActionGroup.add(anAction); } - if (myEvent.getProcessHandler() != null) { - actionGroup.add(new StopProcessAction("Stop", "Stop", myEvent.getProcessHandler())); + if (stopAction != null) { + rerunActionGroup.add(stopAction); } + actionGroup.add(rerunActionGroup); actionGroup.addSeparator(); AnAction[] actions = super.createConsoleActions(); actionGroup.addAll(actions); if (actions.length > 0) { actionGroup.addSeparator(); } - anActions.add(actionGroup); - anActions.add(textActionGroup); - return ArrayUtil.toObjectArray(anActions, AnAction.class); + return new AnAction[]{actionGroup, consoleActionGroup}; } @Nullable diff --git a/java/compiler/impl/src/com/intellij/build/BuildConsoleView.java b/java/compiler/impl/src/com/intellij/build/BuildConsoleView.java index 83ebb78702fd..0c5e04c2caf1 100644 --- a/java/compiler/impl/src/com/intellij/build/BuildConsoleView.java +++ b/java/compiler/impl/src/com/intellij/build/BuildConsoleView.java @@ -15,13 +15,14 @@ */ package com.intellij.build; -import com.intellij.execution.ui.ConsoleView; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.ui.ComponentContainer; import org.jetbrains.annotations.ApiStatus; /** * @author Vladislav.Soroka */ @ApiStatus.Experimental -public interface BuildConsoleView extends ConsoleView, BuildProgressListener { - String getViewId(); +public interface BuildConsoleView extends ComponentContainer, BuildProgressListener { + AnAction[] createConsoleActions(); } diff --git a/java/compiler/impl/src/com/intellij/build/BuildTextConsoleView.java b/java/compiler/impl/src/com/intellij/build/BuildTextConsoleView.java index a7b307bf2a7f..1e7cbf3c2774 100644 --- a/java/compiler/impl/src/com/intellij/build/BuildTextConsoleView.java +++ b/java/compiler/impl/src/com/intellij/build/BuildTextConsoleView.java @@ -38,11 +38,6 @@ public class BuildTextConsoleView extends ConsoleViewImpl implements BuildConsol super(project, viewer); } - @Override - public String getViewId() { - return "console"; - } - @Override public void onEvent(BuildEvent event) { myAnsiEscapeDecoder.escapeText(event.getMessage(), ProcessOutputTypes.STDOUT, this); diff --git a/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java b/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java index a5ec29588191..e139406a4fcc 100644 --- a/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java +++ b/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java @@ -266,11 +266,6 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon public void dispose() { } - @Override - public String getViewId() { - return "TREE"; - } - @Override public void onEvent(BuildEvent event) { ExecutionNode parentNode = event.getParentId() == null ? null : nodesMap.get(event.getParentId()); diff --git a/java/compiler/impl/src/com/intellij/build/CompositeView.java b/java/compiler/impl/src/com/intellij/build/CompositeView.java new file mode 100644 index 000000000000..4b2b7a94a345 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/build/CompositeView.java @@ -0,0 +1,153 @@ +/* + * Copyright 2000-2017 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.build; + +import com.intellij.execution.console.ConsoleHistoryController; +import com.intellij.execution.console.LanguageConsoleView; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.actionSystem.ToggleAction; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.ui.ComponentContainer; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.util.Arrays; +import java.util.List; + +/** + * @author Vladislav.Soroka + */ +public class CompositeView extends JPanel + implements ComponentContainer, DataProvider { + private final static String PRIMARY_PANEL = "PRIMARY_PANEL"; + private final static String SECONDARY_PANEL = "SECONDARY_PANEL"; + + @NotNull + private final S myPrimaryView; + @NotNull + private final T mySecondaryView; + private boolean myPrimary; + @NotNull + private final SwitchViewAction mySwitchViewAction; + + public CompositeView(@NotNull S primaryView, @NotNull T secondaryView) { + super(new CardLayout()); + myPrimaryView = primaryView; + mySecondaryView = secondaryView; + + add(myPrimaryView.getComponent(), PRIMARY_PANEL); + add(mySecondaryView.getComponent(), SECONDARY_PANEL); + + mySwitchViewAction = new SwitchViewAction(); + + myPrimary = true; + enableView(true); + + Disposer.register(this, myPrimaryView); + Disposer.register(this, mySecondaryView); + } + + public void enableView(boolean primary) { + if (primary == myPrimary) return; + + CardLayout cl = (CardLayout)(getLayout()); + cl.show(this, primary ? PRIMARY_PANEL : SECONDARY_PANEL); + IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> { + IdeFocusManager.getGlobalInstance().requestFocus(getView(primary).getComponent(), true); + }); + myPrimary = primary; + } + + public boolean isPrimaryConsoleEnabled() { + return myPrimary; + } + + @NotNull + public S getPrimaryView() { + return myPrimaryView; + } + + @NotNull + public T getSecondaryView() { + return mySecondaryView; + } + + public ComponentContainer getView(boolean primary) { + return primary ? getPrimaryView() : getSecondaryView(); + } + + @NotNull + public AnAction[] createConsoleActions() { + List actions = ContainerUtil.newArrayList(); + actions.add(mySwitchViewAction); + LanguageConsoleView langConsole = + ContainerUtil.findInstance(Arrays.asList(myPrimaryView, mySecondaryView), LanguageConsoleView.class); + ConsoleHistoryController controller = langConsole != null ? ConsoleHistoryController.getController(langConsole) : null; + if (controller != null) actions.add(controller.getBrowseHistory()); + + return ArrayUtil.toObjectArray(actions, AnAction.class); + } + + @Override + public JComponent getComponent() { + return this; + } + + @Override + public JComponent getPreferredFocusableComponent() { + return this; + } + + @Override + public void dispose() { + } + + @Nullable + @Override + public Object getData(@NonNls String dataId) { + final ComponentContainer consoleView = getView(isPrimaryConsoleEnabled()); + return consoleView instanceof DataProvider ? ((DataProvider)consoleView).getData(dataId) : null; + } + + private class SwitchViewAction extends ToggleAction implements DumbAware { + public SwitchViewAction() { + super("Toggle view", null, + AllIcons.Actions.ChangeView); + } + + @Override + public boolean isSelected(final AnActionEvent event) { + return !isPrimaryConsoleEnabled(); + } + + @Override + public void setSelected(final AnActionEvent event, final boolean flag) { + enableView(!flag); + ApplicationManager.getApplication().invokeLater(() -> update(event)); + } + } +} diff --git a/java/compiler/impl/src/com/intellij/build/events/StartBuildEvent.java b/java/compiler/impl/src/com/intellij/build/events/StartBuildEvent.java index 883f2339dee0..90bd9b5e494c 100644 --- a/java/compiler/impl/src/com/intellij/build/events/StartBuildEvent.java +++ b/java/compiler/impl/src/com/intellij/build/events/StartBuildEvent.java @@ -18,13 +18,15 @@ package com.intellij.build.events; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.ui.ConsoleView; -import com.intellij.execution.ui.ExecutionConsole; +import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.util.Consumer; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.function.Supplier; + /** * @author Vladislav.Soroka */ @@ -42,7 +44,7 @@ public interface StartBuildEvent extends StartEvent { AnAction[] getRestartActions(); @Nullable - ExecutionConsole getExecutionConsole(); + Supplier getContentDescriptorSupplier(); @Nullable Consumer getAttachedConsoleConsumer(); diff --git a/java/compiler/impl/src/com/intellij/build/events/impl/StartBuildEventImpl.java b/java/compiler/impl/src/com/intellij/build/events/impl/StartBuildEventImpl.java index c05ad6f2d2dd..b0eaa1343a76 100644 --- a/java/compiler/impl/src/com/intellij/build/events/impl/StartBuildEventImpl.java +++ b/java/compiler/impl/src/com/intellij/build/events/impl/StartBuildEventImpl.java @@ -19,7 +19,7 @@ import com.intellij.build.events.StartBuildEvent; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.ui.ConsoleView; -import com.intellij.execution.ui.ExecutionConsole; +import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.util.Consumer; import com.intellij.util.SmartList; @@ -28,6 +28,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.List; +import java.util.function.Supplier; /** * @author Vladislav.Soroka @@ -41,9 +42,9 @@ public class StartBuildEventImpl extends StartEventImpl implements StartBuildEve @NotNull private List myRestartActions = new SmartList<>(); @Nullable - private ExecutionConsole myExecutionConsole; - @Nullable private ExecutionEnvironment myExecutionEnvironment; + @Nullable + private Supplier myContentDescriptorSupplier; public StartBuildEventImpl(@NotNull Object eventId, @NotNull String buildTitle, @@ -78,8 +79,8 @@ public class StartBuildEventImpl extends StartEventImpl implements StartBuildEve @Nullable @Override - public ExecutionConsole getExecutionConsole() { - return myExecutionConsole; + public Supplier getContentDescriptorSupplier() { + return myContentDescriptorSupplier; } @Nullable @@ -105,13 +106,13 @@ public class StartBuildEventImpl extends StartEventImpl implements StartBuildEve return this; } - public StartBuildEventImpl withConsoleView(ExecutionConsole executionConsole) { - myExecutionConsole = executionConsole; - return this; - } - public StartBuildEventImpl withExecutionEnvironment(ExecutionEnvironment env) { myExecutionEnvironment = env; return this; } + + public StartBuildEventImpl withContentDescriptorSupplier(Supplier contentDescriptorSupplier) { + myContentDescriptorSupplier = contentDescriptorSupplier; + return this; + } } diff --git a/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties b/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties index 2a4ad4f42e03..ec5633a5a947 100644 --- a/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties +++ b/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties @@ -91,10 +91,10 @@ run.configuration.settings.label.project={0} project: run.configuration.settings.label.tasks=Tasks: run.configuration.settings.label.vmoptions=VM options: run.configuration.settings.label.arguments=Arguments: -run.text.starting.multiple.task={0}: Executing tasks ''{1}''...\n -run.text.starting.single.task={0}: Executing task ''{1}''...\n -run.text.ended.multiple.task={0}: Tasks execution finished ''{1}''.\n -run.text.ended.single.task={0}: Task execution finished ''{1}''.\n +run.text.starting.multiple.task={0}: Executing tasks ''{1}''... +run.text.starting.single.task={0}: Executing task ''{1}''... +run.text.ended.multiple.task={0}: Tasks execution finished ''{1}''. +run.text.ended.single.task={0}: Task execution finished ''{1}''. run.error.undefined.task=No task to execute is specified run.invalid.jvm.agent.configuration=Invalid JVM agent configuration used ''{0}'' diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java index e292c46f4939..6e63085272f5 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemRunConfiguration.java @@ -16,6 +16,7 @@ package com.intellij.openapi.externalSystem.service.execution; import com.intellij.build.BuildProgressListener; +import com.intellij.build.BuildViewManager; import com.intellij.build.TasksViewManager; import com.intellij.build.events.BuildEvent; import com.intellij.build.events.impl.FailureResultImpl; @@ -28,11 +29,14 @@ import com.intellij.execution.configurations.*; import com.intellij.execution.console.DuplexConsoleView; import com.intellij.execution.executors.DefaultDebugExecutor; import com.intellij.execution.impl.ConsoleViewImpl; +import com.intellij.execution.impl.ExecutionManagerImpl; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.execution.runners.FakeRerunAction; import com.intellij.execution.runners.ProgramRunner; import com.intellij.execution.ui.ExecutionConsole; +import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -76,6 +80,7 @@ import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -157,7 +162,7 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i @Nullable @Override - public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException { + public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) { MyRunnableState runnableState = new MyRunnableState(mySettings, getProject(), DefaultDebugExecutor.EXECUTOR_ID.equals(executor.getId()), this, env); copyUserDataTo(runnableState); @@ -188,6 +193,7 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i @NotNull private final Project myProject; @NotNull private final ExternalSystemRunConfiguration myConfiguration; @NotNull private final ExecutionEnvironment myEnv; + @Nullable private RunContentDescriptor myContentDescriptor; private final int myDebugPort; @@ -288,36 +294,16 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i public void onStart(@NotNull ExternalSystemTaskId id, String workingDir) { if (progressListener != null) { long eventTime = System.currentTimeMillis(); - AnAction rerunTaskAction = new AnAction() { - @Override - public void update(@NotNull AnActionEvent e) { - super.update(e); - Presentation p = e.getPresentation(); - p.setEnabled(processHandler.isProcessTerminated()); - } - - @Override - public void actionPerformed(AnActionEvent e) { - try { - MyRunnableState.this.execute(executor, runner); - } - catch (ExecutionException ex) { - LOG.warn(ex); - } - } - }; - rerunTaskAction.getTemplatePresentation().setText("Rerun"); - rerunTaskAction.getTemplatePresentation().setDescription("Rerun"); - rerunTaskAction.getTemplatePresentation().setIcon(AllIcons.Actions.Restart); + AnAction rerunTaskAction = new MyTaskRerunAction(progressListener, myEnv, myContentDescriptor); progressListener.onEvent( new StartBuildEventImpl(id, executionName, eventTime, "running...") .withProcessHandler(processHandler, view -> { - processHandler.notifyTextAvailable(greeting, ProcessOutputTypes.SYSTEM); + processHandler.notifyTextAvailable(greeting + "\n\n", ProcessOutputTypes.SYSTEM); foldGreetingOrFarewell(consoleView, greeting, true); }) + .withContentDescriptorSupplier(() -> myContentDescriptor) .withRestartAction(rerunTaskAction) .withRestartActions(restartActions) - .withConsoleView(consoleView) .withExecutionEnvironment(myEnv)); } } @@ -371,14 +357,18 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i farewell = ExternalSystemBundle.message("run.text.ended.single.task", endDateTime, mySettings.toString()); } - processHandler.notifyTextAvailable(farewell, ProcessOutputTypes.SYSTEM); + processHandler.notifyTextAvailable(farewell + "\n", ProcessOutputTypes.SYSTEM); foldGreetingOrFarewell(consoleView, farewell, false); processHandler.notifyProcessTerminated(0); } }; task.execute(ArrayUtil.prepend(taskListener, ExternalSystemTaskNotificationListener.EP_NAME.getExtensions())); }); - return new DefaultExecutionResult(null, processHandler); + return new DefaultExecutionResult(consoleView, processHandler); + } + + public void setContentDescriptor(@Nullable RunContentDescriptor contentDescriptor) { + myContentDescriptor = contentDescriptor; } } @@ -439,4 +429,49 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i }); } } + + private static class MyTaskRerunAction extends FakeRerunAction { + private final BuildProgressListener myProgressListener; + private final RunContentDescriptor myContentDescriptor; + private final ExecutionEnvironment myEnvironment; + + public MyTaskRerunAction(BuildProgressListener progressListener, + ExecutionEnvironment environment, + RunContentDescriptor contentDescriptor) { + myProgressListener = progressListener; + myContentDescriptor = contentDescriptor; + myEnvironment = environment; + } + + @Override + public void update(@NotNull AnActionEvent event) { + Presentation presentation = event.getPresentation(); + ExecutionEnvironment environment = getEnvironment(event); + if (environment != null) { + presentation.setText(ExecutionBundle.message("rerun.configuration.action.name", + StringUtil.escapeMnemonics(environment.getRunProfile().getName()))); + Icon icon = ExecutionManagerImpl.isProcessRunning(getDescriptor(event)) + ? AllIcons.Actions.Restart + : myProgressListener instanceof BuildViewManager + ? AllIcons.Actions.Compile + : environment.getExecutor().getIcon(); + presentation.setIcon(icon); + presentation.setEnabled(isEnabled(event)); + return; + } + + presentation.setEnabled(false); + } + + @Nullable + @Override + protected RunContentDescriptor getDescriptor(AnActionEvent event) { + return myContentDescriptor != null ? myContentDescriptor : super.getDescriptor(event); + } + + @Override + protected ExecutionEnvironment getEnvironment(@NotNull AnActionEvent event) { + return myEnvironment; + } + } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java index 86d1b6138f0d..40eccd79abc5 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java @@ -53,7 +53,22 @@ public class ExternalSystemTaskDebugRunner extends GenericDebuggerRunner { int port = ((ExternalSystemRunConfiguration.MyRunnableState)state).getDebugPort(); if (port > 0) { RemoteConnection connection = new RemoteConnection(true, "127.0.0.1", String.valueOf(port), true); - return attachVirtualMachine(state, environment, connection, true); + RunContentDescriptor runContentDescriptor = attachVirtualMachine(state, environment, connection, true); + if (runContentDescriptor == null) return null; + + ((ExternalSystemRunConfiguration.MyRunnableState)state).setContentDescriptor(runContentDescriptor); + RunContentDescriptor descriptor = + new RunContentDescriptor(runContentDescriptor.getExecutionConsole(), runContentDescriptor.getProcessHandler(), + runContentDescriptor.getComponent(), runContentDescriptor.getDisplayName(), + runContentDescriptor.getIcon(), runContentDescriptor.getActivationCallback(), + runContentDescriptor.getRestartActions()) { + @Override + public boolean isHiddenContent() { + return true; + } + }; + descriptor.setRunnerLayoutUi(runContentDescriptor.getRunnerLayoutUi()); + return descriptor; } else { LOG.warn("Can't attach debugger to external system task execution. Reason: target debug port is unknown"); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.kt index 3c1baa6ff372..d6cc52b03287 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.kt +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.kt @@ -22,6 +22,7 @@ import com.intellij.execution.configurations.RunnerSettings import com.intellij.execution.executors.DefaultRunExecutor import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.execution.runners.GenericProgramRunner +import com.intellij.execution.runners.RunContentBuilder import com.intellij.execution.ui.RunContentDescriptor import com.intellij.openapi.externalSystem.util.ExternalSystemConstants import javax.swing.JComponent @@ -41,12 +42,22 @@ class ExternalSystemTaskRunner : GenericProgramRunner() { @Throws(ExecutionException::class) override fun doExecute(state: RunProfileState, environment: ExecutionEnvironment): RunContentDescriptor? { - val executionResult = state.execute(environment.executor, this) ?: return null + if (state !is ExternalSystemRunConfiguration.MyRunnableState) return null - return object : RunContentDescriptor(executionResult.executionConsole, executionResult.processHandler, - EMPTY_COMPONENT, environment.runProfile.name, null) { - override fun isHiddenContent() = true + val executionResult = state.execute(environment.executor, this) ?: return null + val runContentDescriptor = RunContentBuilder(executionResult, environment).showRunContent(environment.contentToReuse) ?: return null + + state.setContentDescriptor(runContentDescriptor) + val descriptor = object : RunContentDescriptor(runContentDescriptor.executionConsole, runContentDescriptor.processHandler, + runContentDescriptor.component, runContentDescriptor.displayName, + runContentDescriptor.icon, runContentDescriptor.activationCallback, + runContentDescriptor.restartActions) { + override fun isHiddenContent(): Boolean { + return true + } } + descriptor.runnerLayoutUi = runContentDescriptor.runnerLayoutUi + return descriptor } companion object { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java index d80eac9c1d51..e5d012becb1a 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java @@ -567,8 +567,7 @@ public class ExternalSystemUtil { } public void cancellImport() { - ApplicationManager.getApplication().executeOnPooledThread( - (Runnable)() -> myTask.cancel(ExternalSystemTaskNotificationListener.EP_NAME.getExtensions())); + myTask.cancel(ExternalSystemTaskNotificationListener.EP_NAME.getExtensions()); } };