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 7997f0111908..e8a84c708f59 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 @@ -350,6 +350,9 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i if (progressListener != null) { long eventTime = System.currentTimeMillis(); AnAction rerunTaskAction = new MyTaskRerunAction(progressListener, myEnv, myContentDescriptor); + BuildViewSettingsProvider viewSettingsProvider = + consoleView instanceof BuildViewSettingsProvider ? + new BuildViewSettingsProviderAdapter((BuildViewSettingsProvider)consoleView) : null; progressListener.onEvent( new StartBuildEventImpl(new DefaultBuildDescriptor(id, executionName, workingDir, eventTime), "running...") .withProcessHandler(processHandler, view -> { @@ -360,6 +363,7 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i .withRestartAction(rerunTaskAction) .withRestartActions(restartActions) .withExecutionEnvironment(myEnv) + .withBuildViewSettingsProvider(viewSettingsProvider) ); } } diff --git a/platform/lang-impl/src/com/intellij/build/BuildTreeConsoleView.java b/platform/lang-impl/src/com/intellij/build/BuildTreeConsoleView.java index 01b0c10f74c6..c5ab983f19b9 100644 --- a/platform/lang-impl/src/com/intellij/build/BuildTreeConsoleView.java +++ b/platform/lang-impl/src/com/intellij/build/BuildTreeConsoleView.java @@ -8,7 +8,9 @@ import com.intellij.execution.filters.TextConsoleBuilderFactory; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.ConsoleView; import com.intellij.execution.ui.ConsoleViewContentType; +import com.intellij.execution.ui.ExecutionConsole; import com.intellij.icons.AllIcons; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -66,6 +68,8 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; +import static com.intellij.build.BuildView.CONSOLE_VIEW_NAME; + /** * @author Vladislav.Soroka */ @@ -73,11 +77,14 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon private static final Logger LOG = Logger.getInstance(BuildTreeConsoleView.class); @NonNls private static final String TREE = "tree"; + @NonNls private static final String SPLITTER_PROPERTY = "SMTestRunner.Splitter.Proportion"; private final JPanel myPanel = new JPanel(); private final Map nodesMap = ContainerUtil.newConcurrentMap(); private final Project myProject; - private final DetailsHandler myDetailsHandler; + private final ConsoleViewHandler myConsoleViewHandler; + @NotNull + private final BuildViewSettingsProvider myViewSettingsProvider; private final TableColumn myTimeColumn; private final String myWorkingDir; private final AtomicBoolean myDisposed = new AtomicBoolean(); @@ -86,7 +93,10 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon private final ExecutionNode myRootNode; private volatile int myTimeColumnWidth; - public BuildTreeConsoleView(Project project, BuildDescriptor buildDescriptor) { + public BuildTreeConsoleView(Project project, + BuildDescriptor buildDescriptor, + @Nullable ExecutionConsole executionConsole, + @NotNull BuildViewSettingsProvider buildViewSettingsProvider) { myProject = project; myWorkingDir = FileUtil.toSystemIndependentName(buildDescriptor.getWorkingDir()); final ColumnInfo[] COLUMNS = { @@ -107,6 +117,7 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon } } }; + myViewSettingsProvider = buildViewSettingsProvider; myRootNode = new ExecutionNode(myProject, null); myRootNode.setAutoExpandNode(true); @@ -182,7 +193,7 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon myTimeColumn = treeTable.getColumnModel().getColumn(1); myTimeColumn.setResizable(false); - updateTimeColumnWidth("Running for " + StringUtil.formatDuration(11111L), true); + updateTimeColumnWidth(StringUtil.formatDurationApproximate(11111L), true); TreeUtil.installActions(myTree); @@ -192,29 +203,38 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon myPanel.setLayout(new BorderLayout()); ThreeComponentsSplitter myThreeComponentsSplitter = new ThreeComponentsSplitter() { + @Override + public void setFirstSize(int size) { + super.setFirstSize(size); + float proportion = size / (float)getWidth(); + PropertiesComponent.getInstance().setValue(SPLITTER_PROPERTY, proportion, 0.3f); + } + @Override public void doLayout() { super.doLayout(); - JComponent detailsComponent = myDetailsHandler.getComponent(); + JComponent detailsComponent = myConsoleViewHandler.getComponent(); if (detailsComponent != null && detailsComponent.isVisible()) { - int firstSize = getFirstSize(); - int lastSize = getLastSize(); - if (firstSize == 0 && lastSize == 0) { - int width = Math.round(getWidth() / 2f); - if (width > 0) { - setFirstSize(width); - } - } + updateSplitter(this); } } }; Disposer.register(this, myThreeComponentsSplitter); myThreeComponentsSplitter.setFirstComponent(myContentPanel); - myDetailsHandler = new DetailsHandler(myProject, myTree, myThreeComponentsSplitter); - myThreeComponentsSplitter.setLastComponent(myDetailsHandler.getComponent()); + myConsoleViewHandler = + new ConsoleViewHandler(myProject, myTree, myThreeComponentsSplitter, executionConsole, buildViewSettingsProvider); + myThreeComponentsSplitter.setLastComponent(myConsoleViewHandler.getComponent()); myPanel.add(myThreeComponentsSplitter, BorderLayout.CENTER); } + @Override + public void clear() { + getRootElement().removeChildren(); + nodesMap.clear(); + myConsoleViewHandler.clear(); + myTreeModel.invalidate(); + } + private ExecutionNode getRootElement() { return myRootNode; } @@ -223,96 +243,6 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon public void print(@NotNull String text, @NotNull ConsoleViewContentType contentType) { } - @Override - public void clear() { - getRootElement().removeChildren(); - nodesMap.clear(); - myDetailsHandler.clear(); - myTreeModel.invalidate(); - } - - @Override - public void scrollTo(int offset) { - } - - @Override - public void attachToProcess(ProcessHandler processHandler) { - } - - @Override - public boolean isOutputPaused() { - return false; - } - - @Override - public void setOutputPaused(boolean value) { - } - - @Override - public boolean hasDeferredOutput() { - return false; - } - - @Override - public void performWhenNoDeferredOutput(@NotNull Runnable runnable) { - } - - @Override - public void setHelpId(@NotNull String helpId) { - } - - @Override - public void addMessageFilter(@NotNull Filter filter) { - } - - @Override - public void printHyperlink(@NotNull String hyperlinkText, @Nullable HyperlinkInfo info) { - } - - @Override - public int getContentSize() { - return 0; - } - - @Override - public boolean canPause() { - return false; - } - - @NotNull - @Override - public AnAction[] createConsoleActions() { - return AnAction.EMPTY_ARRAY; - } - - @Override - public void allowHeavyFilters() { - } - - @Override - public JComponent getComponent() { - return myPanel; - } - - @Override - public JComponent getPreferredFocusableComponent() { - return myTree; - } - - @Override - public void dispose() { - myDisposed.set(true); - } - - public boolean isDisposed() { - return myDisposed.get(); - } - - @Override - public void onEvent(@NotNull BuildEvent event) { - myTreeModel.getInvoker().runOrInvokeLater(() -> onEventInternal(event)); - } - public void onEventInternal(@NotNull BuildEvent event) { ExecutionNode parentNode = event.getParentId() == null ? null : nodesMap.get(event.getParentId()); ExecutionNode currentNode = nodesMap.get(event.getId()); @@ -396,9 +326,12 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon aHint = aHint == null ? "at " + time : aHint + " at " + time; currentNode.setHint(aHint); updateTimeColumnWidth(myTimeColumnWidth); - if (myDetailsHandler.myExecutionNode == null) { + if (myViewSettingsProvider.isSideBySideView()) { + currentNode.setResult(null); + } + if (myConsoleViewHandler.myExecutionNode == null) { ExecutionNode element = getRootElement(); - ApplicationManager.getApplication().invokeLater(() -> myDetailsHandler.setNode(element)); + ApplicationManager.getApplication().invokeLater(() -> myConsoleViewHandler.setNode(element)); } if (((FinishBuildEvent)event).getResult() instanceof FailureResult) { @@ -421,6 +354,101 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon scheduleUpdate(currentNode); } + @Override + public void scrollTo(int offset) { + } + + @Override + public void attachToProcess(ProcessHandler processHandler) { + } + + @Override + public boolean isOutputPaused() { + return false; + } + + @Override + public void setOutputPaused(boolean value) { + } + + @Override + public boolean hasDeferredOutput() { + return false; + } + + @Override + public void performWhenNoDeferredOutput(@NotNull Runnable runnable) { + } + + @Override + public void setHelpId(@NotNull String helpId) { + } + + @Override + public void addMessageFilter(@NotNull Filter filter) { + } + + @Override + public void printHyperlink(@NotNull String hyperlinkText, @Nullable HyperlinkInfo info) { + } + + @Override + public int getContentSize() { + return 0; + } + + @Override + public boolean canPause() { + return false; + } + + @NotNull + @Override + public AnAction[] createConsoleActions() { + return AnAction.EMPTY_ARRAY; + } + + @Override + public void allowHeavyFilters() { + } + + @Override + public JComponent getComponent() { + return myPanel; + } + + @Override + public JComponent getPreferredFocusableComponent() { + return myTree; + } + + @Override + public void dispose() { + myDisposed.set(true); + } + + public boolean isDisposed() { + return myDisposed.get(); + } + + @Override + public void onEvent(@NotNull BuildEvent event) { + myTreeModel.getInvoker().runOrInvokeLater(() -> onEventInternal(event)); + } + + private static void updateSplitter(@NotNull ThreeComponentsSplitter myThreeComponentsSplitter) { + int firstSize = myThreeComponentsSplitter.getFirstSize(); + //int lastSize = myThreeComponentsSplitter.getLastSize(); + int splitterWidth = myThreeComponentsSplitter.getWidth(); + if (firstSize == 0/* && lastSize == 0*/) { + float proportion = PropertiesComponent.getInstance().getFloat(SPLITTER_PROPERTY, 0.3f); + int width = Math.round(splitterWidth * proportion); + if (width > 0) { + myThreeComponentsSplitter.setFirstSize(width); + } + } + } + protected void expand(TreeTableTree tree) { TreeUtil.expand(tree, path -> { @@ -601,30 +629,45 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon return node; } - private static class DetailsHandler { - private final ThreeComponentsSplitter mySplitter; - private final ConsoleView myConsole; + private static class ConsoleViewHandler { + private static final String TASK_OUTPUT_VIEW_NAME = "taskOutputView"; private final JPanel myPanel; + private final CompositeView myView; + @NotNull + private final BuildViewSettingsProvider myViewSettingsProvider; @Nullable private ExecutionNode myExecutionNode; - DetailsHandler(Project project, - TreeTableTree tree, - ThreeComponentsSplitter threeComponentsSplitter) { - myConsole = TextConsoleBuilderFactory.getInstance().createBuilder(project).getConsole(); - mySplitter = threeComponentsSplitter; + ConsoleViewHandler(Project project, + TreeTableTree tree, + ThreeComponentsSplitter threeComponentsSplitter, + @Nullable ExecutionConsole executionConsole, + @NotNull BuildViewSettingsProvider buildViewSettingsProvider) { myPanel = new JPanel(new BorderLayout()); - JComponent consoleComponent = myConsole.getComponent(); - AnAction[] consoleActions = myConsole.createConsoleActions(); + ConsoleView myNodeConsole = TextConsoleBuilderFactory.getInstance().createBuilder(project).getConsole(); + myViewSettingsProvider = buildViewSettingsProvider; + myView = new CompositeView<>(null); + if (executionConsole != null && buildViewSettingsProvider.isSideBySideView()) { + myView.addView(executionConsole, CONSOLE_VIEW_NAME, true); + } + myView.addView(myNodeConsole, TASK_OUTPUT_VIEW_NAME, false); + if (buildViewSettingsProvider.isSideBySideView()) { + myView.enableView(CONSOLE_VIEW_NAME, false); + myPanel.setVisible(true); + } + else { + myPanel.setVisible(false); + } + JComponent consoleComponent = myNodeConsole.getComponent(); + AnAction[] consoleActions = myNodeConsole.createConsoleActions(); consoleComponent.setFocusable(true); final Color editorBackground = EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground(); consoleComponent.setBorder(new CompoundBorder(IdeBorderFactory.createBorder(SideBorder.RIGHT), new SideBorder(editorBackground, SideBorder.LEFT))); - myPanel.add(consoleComponent, BorderLayout.CENTER); + myPanel.add(myView.getComponent(), BorderLayout.CENTER); final ActionToolbar toolbar = ActionManager.getInstance() .createActionToolbar("BuildResults", new DefaultActionGroup(consoleActions), false); myPanel.add(toolbar.getComponent(), BorderLayout.EAST); - myPanel.setVisible(false); tree.addTreeSelectionListener(e -> { TreePath path = e.getPath(); if (path == null || !e.isAddedPath()) { @@ -634,15 +677,21 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon setNode(selectionPath != null ? (DefaultMutableTreeNode)selectionPath.getLastPathComponent() : null); }); - Disposer.register(threeComponentsSplitter, myConsole); + Disposer.register(threeComponentsSplitter, myView); + Disposer.register(threeComponentsSplitter, myNodeConsole); + } + + private ConsoleView getTaskOutputView() { + return (ConsoleView)myView.getView(TASK_OUTPUT_VIEW_NAME); } public boolean setNode(@NotNull ExecutionNode node) { EventResult eventResult = node.getResult(); boolean hasChanged = false; + ConsoleView taskOutputView = getTaskOutputView(); if (eventResult instanceof FailureResult) { - myConsole.clear(); + taskOutputView.clear(); List failures = ((FailureResult)eventResult).getFailures(); if (failures.isEmpty()) return false; for (Iterator iterator = failures.iterator(); iterator.hasNext(); ) { @@ -655,7 +704,7 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon printDetails(failure, text); hasChanged = true; if (iterator.hasNext()) { - myConsole.print("\n\n", ConsoleViewContentType.NORMAL_OUTPUT); + taskOutputView.print("\n\n", ConsoleViewContentType.NORMAL_OUTPUT); } } } @@ -667,27 +716,22 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon if (details.isEmpty()) { return false; } - myConsole.clear(); + taskOutputView.clear(); printDetails(null, details); hasChanged = true; } if (!hasChanged) return false; - myConsole.scrollTo(0); - int firstSize = mySplitter.getFirstSize(); - int lastSize = mySplitter.getLastSize(); + taskOutputView.scrollTo(0); - if (firstSize == 0 && lastSize == 0) { - int width = Math.round(mySplitter.getWidth() / 2f); - mySplitter.setFirstSize(width); - } + myView.enableView(TASK_OUTPUT_VIEW_NAME, !myViewSettingsProvider.isSideBySideView()); myPanel.setVisible(true); return true; } private boolean printDetails(Failure failure, @Nullable String details) { - return BuildConsoleUtils.printDetails(myConsole, failure, details); + return BuildConsoleUtils.printDetails(getTaskOutputView(), failure, details); } public void setNode(@Nullable DefaultMutableTreeNode node) { @@ -700,7 +744,13 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon } myExecutionNode = null; - myPanel.setVisible(false); + if (myView.getView(CONSOLE_VIEW_NAME) != null) { + myView.enableView(CONSOLE_VIEW_NAME); + myPanel.setVisible(true); + } + else { + myPanel.setVisible(false); + } } public JComponent getComponent() { @@ -709,7 +759,7 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon public void clear() { myPanel.setVisible(false); - myConsole.clear(); + getTaskOutputView().clear(); } } } diff --git a/platform/lang-impl/src/com/intellij/build/BuildView.java b/platform/lang-impl/src/com/intellij/build/BuildView.java index 457a674fbad4..ec0de4f8e201 100644 --- a/platform/lang-impl/src/com/intellij/build/BuildView.java +++ b/platform/lang-impl/src/com/intellij/build/BuildView.java @@ -18,6 +18,7 @@ package com.intellij.build; import com.intellij.build.events.BuildEvent; import com.intellij.build.events.OutputBuildEvent; import com.intellij.build.events.StartBuildEvent; +import com.intellij.build.events.impl.StartBuildEventImpl; import com.intellij.build.process.BuildProcessHandler; import com.intellij.execution.actions.StopAction; import com.intellij.execution.actions.StopProcessAction; @@ -61,6 +62,8 @@ public class BuildView extends CompositeView implements BuildP private final AtomicBoolean isBuildStartEventProcessed = new AtomicBoolean(); private final List myAfterStartEvents = ContainerUtil.createConcurrentList(); private final ViewManager myViewManager; + @Nullable private ExecutionConsole myExecutionConsole; + private BuildViewSettingsProvider myViewSettingsProvider; public BuildView(Project project, BuildDescriptor buildDescriptor, String selectionStateKey, ViewManager viewManager) { this(project, null, buildDescriptor, selectionStateKey, viewManager); @@ -75,9 +78,7 @@ public class BuildView extends CompositeView implements BuildP myProject = project; myBuildDescriptor = buildDescriptor; myViewManager = viewManager; - if (executionConsole != null) { - addView(executionConsole, CONSOLE_VIEW_NAME, viewManager.isConsoleEnabledByDefault()); - } + myExecutionConsole = executionConsole; } @Override @@ -120,38 +121,53 @@ public class BuildView extends CompositeView implements BuildP private void onStartBuild(StartBuildEvent startBuildEvent) { myStartBuildEventRef.set(startBuildEvent); - String eventViewName = BuildTreeConsoleView.class.getName(); - BuildTreeConsoleView eventView = getView(eventViewName, BuildTreeConsoleView.class); - if (eventView == null) { - eventView = new BuildTreeConsoleView(myProject, myBuildDescriptor); - addView(eventView, eventViewName, !myViewManager.isConsoleEnabledByDefault()); + if (startBuildEvent instanceof StartBuildEventImpl) { + myViewSettingsProvider = ((StartBuildEventImpl)startBuildEvent).getBuildViewSettingsProvider(); } - - ExecutionConsole executionConsoleView = getConsoleView(); - if (executionConsoleView == null) { + if (myViewSettingsProvider == null) { + myViewSettingsProvider = () -> false; + } + if (myExecutionConsole == null) { Supplier descriptorSupplier = startBuildEvent.getContentDescriptorSupplier(); RunContentDescriptor runContentDescriptor = descriptorSupplier != null ? descriptorSupplier.get() : null; - executionConsoleView = runContentDescriptor != null && + myExecutionConsole = runContentDescriptor != null && runContentDescriptor.getExecutionConsole() != null && runContentDescriptor.getExecutionConsole() != this ? - runContentDescriptor.getExecutionConsole() : new BuildTextConsoleView(myProject); - addView(executionConsoleView, CONSOLE_VIEW_NAME, myViewManager.isConsoleEnabledByDefault()); + runContentDescriptor.getExecutionConsole() : new BuildTextConsoleView(myProject); if (runContentDescriptor != null && Disposer.findRegisteredObject(runContentDescriptor, this) == null) { Disposer.register(this, runContentDescriptor); } } + if (myExecutionConsole != null) { + myExecutionConsole.getComponent(); //create editor to be able to add console editor actions + if (myViewSettingsProvider.isExecutionViewHidden() || !myViewSettingsProvider.isSideBySideView()) { + addView(myExecutionConsole, CONSOLE_VIEW_NAME, myViewManager.isConsoleEnabledByDefault()); + } + } + + BuildTreeConsoleView eventView = null; + if (!myViewSettingsProvider.isExecutionViewHidden()) { + String eventViewName = BuildTreeConsoleView.class.getName(); + eventView = getView(eventViewName, BuildTreeConsoleView.class); + if (eventView == null) { + eventView = new BuildTreeConsoleView(myProject, myBuildDescriptor, + myExecutionConsole, + myViewSettingsProvider); + addView(eventView, eventViewName, myViewSettingsProvider.isSideBySideView() || !myViewManager.isConsoleEnabledByDefault()); + } + } BuildProcessHandler processHandler = startBuildEvent.getProcessHandler(); - if (executionConsoleView instanceof ConsoleView) { + if (myExecutionConsole instanceof ConsoleView) { for (Filter filter : startBuildEvent.getExecutionFilters()) { - ((ConsoleView)executionConsoleView).addMessageFilter(filter); + ((ConsoleView)myExecutionConsole).addMessageFilter(filter); } if (processHandler != null) { - ((ConsoleView)executionConsoleView).attachToProcess(processHandler); + ((ConsoleView)myExecutionConsole).attachToProcess(processHandler); Consumer attachedConsoleConsumer = startBuildEvent.getAttachedConsoleConsumer(); if (attachedConsoleConsumer != null) { - attachedConsoleConsumer.consume((ConsoleView)executionConsoleView); + attachedConsoleConsumer.consume((ConsoleView)myExecutionConsole); } if (!processHandler.isStartNotified()) { processHandler.startNotify(); @@ -162,11 +178,13 @@ public class BuildView extends CompositeView implements BuildP processHandler.startNotify(); } - eventView.onEvent(startBuildEvent); + if (eventView != null) { + eventView.onEvent(startBuildEvent); + } } private ExecutionConsole getConsoleView() { - return getView(CONSOLE_VIEW_NAME, ExecutionConsole.class); + return myExecutionConsole; } @Override @@ -273,12 +291,13 @@ public class BuildView extends CompositeView implements BuildP public void update(@NotNull AnActionEvent e) { super.update(e); String eventViewName = BuildTreeConsoleView.class.getName(); - e.getPresentation().setVisible(!BuildView.this.isViewEnabled(eventViewName)); + e.getPresentation().setVisible(!myViewSettingsProvider.isSideBySideView() && !BuildView.this.isViewEnabled(eventViewName)); } }; ExecutionConsole consoleView = getConsoleView(); if (consoleView instanceof ConsoleView) { + consoleView.getComponent(); //create editor to be able to add console editor actions final AnAction[] consoleActions = ((ConsoleView)consoleView).createConsoleActions(); for (AnAction anAction : consoleActions) { if (anAction instanceof StopAction) { @@ -303,7 +322,7 @@ public class BuildView extends CompositeView implements BuildP rerunActionGroup.add(stopAction); } actionGroup.add(rerunActionGroup); - if (myViewManager.isBuildContentView()) { + if (myViewManager.isBuildContentView() && !myViewSettingsProvider.isSideBySideView()) { actionGroup.addAll(getSwitchActions()); actionGroup.addSeparator(); } diff --git a/platform/lang-impl/src/com/intellij/build/BuildViewSettingsProvider.java b/platform/lang-impl/src/com/intellij/build/BuildViewSettingsProvider.java new file mode 100644 index 000000000000..8a6fb129b529 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/build/BuildViewSettingsProvider.java @@ -0,0 +1,14 @@ +// Copyright 2000-2019 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.build; + +import com.intellij.openapi.util.registry.Registry; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Experimental +public interface BuildViewSettingsProvider { + boolean isExecutionViewHidden(); + + default boolean isSideBySideView() { + return Registry.is("build.view.side-by-side", false); + } +} diff --git a/platform/lang-impl/src/com/intellij/build/BuildViewSettingsProviderAdapter.java b/platform/lang-impl/src/com/intellij/build/BuildViewSettingsProviderAdapter.java new file mode 100644 index 000000000000..675561c8d130 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/build/BuildViewSettingsProviderAdapter.java @@ -0,0 +1,15 @@ +// Copyright 2000-2019 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.build; + +public class BuildViewSettingsProviderAdapter implements BuildViewSettingsProvider { + private boolean myExecutionViewHidden; + + public BuildViewSettingsProviderAdapter(BuildViewSettingsProvider buildViewSettingsProvider) { + myExecutionViewHidden = buildViewSettingsProvider.isExecutionViewHidden(); + } + + @Override + public boolean isExecutionViewHidden() { + return myExecutionViewHidden; + } +} diff --git a/platform/lang-impl/src/com/intellij/build/CompositeView.java b/platform/lang-impl/src/com/intellij/build/CompositeView.java index e86589a001aa..51e86adc34e8 100644 --- a/platform/lang-impl/src/com/intellij/build/CompositeView.java +++ b/platform/lang-impl/src/com/intellij/build/CompositeView.java @@ -55,7 +55,7 @@ public class CompositeView extends JPanel implemen mySwitchViewAction = new SwitchViewAction(); } - public void addView(T view, String viewName, boolean enable) { + public void addView(@NotNull T view, @NotNull String viewName, boolean enable) { T oldView = getView(viewName); if (oldView != null) { remove(oldView.getComponent()); @@ -73,17 +73,23 @@ public class CompositeView extends JPanel implemen } public void enableView(@NotNull String viewName) { + enableView(viewName, true); + } + + public void enableView(@NotNull String viewName, boolean requestFocus) { if (!StringUtil.equals(viewName, myEnabledViewRef.get())) { myEnabledViewRef.set(viewName); CardLayout cl = (CardLayout)(getLayout()); cl.show(this, viewName); } - IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> { - ComponentContainer view = getView(viewName); - if (view != null) { - IdeFocusManager.getGlobalInstance().requestFocus(view.getPreferredFocusableComponent(), true); - } - }); + if (requestFocus) { + IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> { + ComponentContainer view = getView(viewName); + if (view != null) { + IdeFocusManager.getGlobalInstance().requestFocus(view.getPreferredFocusableComponent(), true); + } + }); + } } public boolean isViewEnabled(String viewName) { @@ -162,9 +168,11 @@ public class CompositeView extends JPanel implemen public void update(@NotNull AnActionEvent e) { final Presentation presentation = e.getPresentation(); if (myViewMap.size() <= 1) { + presentation.setVisible(false); presentation.setEnabled(false); } else { + presentation.setVisible(true); presentation.setEnabled(true); presentation.putClientProperty(SELECTED_PROPERTY, isSelected(e)); } diff --git a/platform/lang-impl/src/com/intellij/build/ExecutionNode.java b/platform/lang-impl/src/com/intellij/build/ExecutionNode.java index 00cd5188f5d1..54be3f4f91f7 100644 --- a/platform/lang-impl/src/com/intellij/build/ExecutionNode.java +++ b/platform/lang-impl/src/com/intellij/build/ExecutionNode.java @@ -173,12 +173,12 @@ public class ExecutionNode extends CachingSimpleNode { if (startTime == endTime) return null; if (isRunning()) { final long duration = startTime == 0 ? 0 : System.currentTimeMillis() - startTime; - String durationText = StringUtil.formatDuration(duration); + String durationText = StringUtil.formatDurationApproximate(duration); int index = durationText.indexOf("s "); if (index != -1) { durationText = durationText.substring(0, index + 1); } - return "Running for " + durationText; + return durationText; } else { return isSkipped(myResult) ? null : StringUtil.formatDuration(endTime - startTime); diff --git a/platform/lang-impl/src/com/intellij/build/events/impl/StartBuildEventImpl.java b/platform/lang-impl/src/com/intellij/build/events/impl/StartBuildEventImpl.java index c82b4d5ad729..13f14aead523 100644 --- a/platform/lang-impl/src/com/intellij/build/events/impl/StartBuildEventImpl.java +++ b/platform/lang-impl/src/com/intellij/build/events/impl/StartBuildEventImpl.java @@ -16,6 +16,7 @@ package com.intellij.build.events.impl; import com.intellij.build.BuildDescriptor; +import com.intellij.build.BuildViewSettingsProvider; import com.intellij.build.events.StartBuildEvent; import com.intellij.build.process.BuildProcessHandler; import com.intellij.execution.filters.Filter; @@ -25,6 +26,7 @@ import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.util.Consumer; import com.intellij.util.SmartList; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -50,6 +52,8 @@ public class StartBuildEventImpl extends StartEventImpl implements StartBuildEve private ExecutionEnvironment myExecutionEnvironment; @Nullable private Supplier myContentDescriptorSupplier; + @Nullable + private BuildViewSettingsProvider myBuildViewSettingsProvider; public StartBuildEventImpl(@NotNull BuildDescriptor descriptor, @NotNull String message) { super(descriptor.getId(), null, descriptor.getStartTime(), message); @@ -104,6 +108,12 @@ public class StartBuildEventImpl extends StartEventImpl implements StartBuildEve return myAttachedConsoleConsumer; } + @Nullable + @ApiStatus.Experimental + public BuildViewSettingsProvider getBuildViewSettingsProvider() { + return myBuildViewSettingsProvider; + } + public StartBuildEventImpl withProcessHandler(@Nullable BuildProcessHandler processHandler, @Nullable Consumer attachedConsoleConsumer) { myProcessHandler = processHandler; @@ -140,4 +150,10 @@ public class StartBuildEventImpl extends StartEventImpl implements StartBuildEve myFilters.addAll(Arrays.asList(filters)); return this; } + + @ApiStatus.Experimental + public StartBuildEventImpl withBuildViewSettingsProvider(@Nullable BuildViewSettingsProvider viewSettingsProvider) { + myBuildViewSettingsProvider = viewSettingsProvider; + return this; + } } diff --git a/platform/lang-impl/testSources/com/intellij/build/BuildTreeConsoleViewTest.kt b/platform/lang-impl/testSources/com/intellij/build/BuildTreeConsoleViewTest.kt index 9e05cf471f6a..e28cd3122286 100644 --- a/platform/lang-impl/testSources/com/intellij/build/BuildTreeConsoleViewTest.kt +++ b/platform/lang-impl/testSources/com/intellij/build/BuildTreeConsoleViewTest.kt @@ -33,8 +33,10 @@ class BuildTreeConsoleViewTest: LightPlatformTestCase() { "test descriptor", "fake path", 1L) - - treeConsoleView = BuildTreeConsoleView(getProject(), buildDescriptor) + treeConsoleView = BuildTreeConsoleView(getProject(), buildDescriptor, null, object : BuildViewSettingsProvider { + override fun isExecutionViewHidden(): Boolean = false + override fun isSideBySideView(): Boolean = true + }) } @Test diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 966341fd4a5c..b7a3e9d0a0bd 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -1876,4 +1876,7 @@ ide.service.view=true ide.service.view.description=Enable Services tool window ide.service.view.restartRequired=true +build.view.side-by-side=false +build.view.side-by-side.description=Enable Build tool window tree and console side-by-side view + # TODO please use EP com.intellij.registryKey for plugin/product specific keys \ No newline at end of file diff --git a/plugins/gradle/java/src/execution/test/runner/GradleTestsExecutionConsole.java b/plugins/gradle/java/src/execution/test/runner/GradleTestsExecutionConsole.java index 0a9ac2636065..22f9d7bab58a 100644 --- a/plugins/gradle/java/src/execution/test/runner/GradleTestsExecutionConsole.java +++ b/plugins/gradle/java/src/execution/test/runner/GradleTestsExecutionConsole.java @@ -15,10 +15,12 @@ */ package org.jetbrains.plugins.gradle.execution.test.runner; +import com.intellij.build.BuildViewSettingsProvider; import com.intellij.execution.testframework.TestConsoleProperties; import com.intellij.execution.testframework.sm.runner.SMTestLocator; import com.intellij.execution.testframework.sm.runner.SMTestProxy; import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView; +import com.intellij.openapi.util.registry.Registry; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nullable; @@ -27,7 +29,7 @@ import java.util.Map; /** * @author Vladislav.Soroka */ -public class GradleTestsExecutionConsole extends SMTRunnerConsoleView { +public class GradleTestsExecutionConsole extends SMTRunnerConsoleView implements BuildViewSettingsProvider { private final Map testsMap = ContainerUtil.newHashMap(); private final StringBuilder myBuffer = new StringBuilder(); @@ -52,4 +54,9 @@ public class GradleTestsExecutionConsole extends SMTRunnerConsoleView { public SMTestLocator getUrlProvider() { return GradleConsoleProperties.GRADLE_TEST_LOCATOR; } + + @Override + public boolean isExecutionViewHidden() { + return Registry.is("build.view.side-by-side", false); + } }