mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Build tool window: side-by-side view UX-496
This commit is contained in:
+4
@@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Object, ExecutionNode> 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<ExecutionConsole> 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<? extends Failure> failures = ((FailureResult)eventResult).getFailures();
|
||||
if (failures.isEmpty()) return false;
|
||||
for (Iterator<? extends Failure> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ExecutionConsole> implements BuildP
|
||||
private final AtomicBoolean isBuildStartEventProcessed = new AtomicBoolean();
|
||||
private final List<BuildEvent> 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<ExecutionConsole> 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<ExecutionConsole> 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<RunContentDescriptor> 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<ConsoleView> 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<ExecutionConsole> 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<ExecutionConsole> 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<ExecutionConsole> implements BuildP
|
||||
rerunActionGroup.add(stopAction);
|
||||
}
|
||||
actionGroup.add(rerunActionGroup);
|
||||
if (myViewManager.isBuildContentView()) {
|
||||
if (myViewManager.isBuildContentView() && !myViewSettingsProvider.isSideBySideView()) {
|
||||
actionGroup.addAll(getSwitchActions());
|
||||
actionGroup.addSeparator();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public class CompositeView<T extends ComponentContainer> 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<T extends ComponentContainer> 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<T extends ComponentContainer> 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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<RunContentDescriptor> 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<ConsoleView> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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<String, SMTestProxy> 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user