// Copyright 2017 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).
package com.twitter.intellij.pants.ui;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.errorTreeView.NewErrorTreeRenderer;
import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel;
import com.intellij.ide.errorTreeView.impl.ErrorTreeViewConfiguration;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.ui.AutoScrollToSourceHandler;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SideBorder;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.EditSourceOnDoubleClickHandler;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import com.twitter.intellij.pants.PantsBundle;
import com.twitter.intellij.pants.execution.PantsMakeBeforeRun;
import org.jetbrains.annotations.NotNull;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.BorderLayout;
/**
* A JPanel consisting control buttons on the left and a ConsoleView on the right displaying Pants output.
* <p>
* Template came from {@link NewErrorTreeViewPanel} but heavily trimmed.
*/
public class PantsConsoleViewPanel extends JPanel {
protected static final Logger LOG = Logger.getInstance("#com.intellij.ide.errorTreeView.NewErrorTreeViewPanel");
private final ErrorTreeViewConfiguration myConfiguration;
protected Project myProject;
private Tree myTree;
private final AutoScrollToSourceHandler myAutoScrollToSourceHandler;
public PantsConsoleViewPanel(Project project) {
myProject = project;
myConfiguration = ErrorTreeViewConfiguration.getInstance(project);
setLayout(new BorderLayout());
myAutoScrollToSourceHandler = new AutoScrollToSourceHandler() {
@Override
protected boolean isAutoScrollMode() {
return myConfiguration.isAutoscrollToSource();
}
@Override
protected void setAutoScrollMode(boolean state) {
myConfiguration.setAutoscrollToSource(state);
}
};
JPanel myMessagePanel = new JPanel(new BorderLayout());
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
final DefaultTreeModel treeModel = new DefaultTreeModel(root);
myTree = createTree(treeModel);
myTree.getEmptyText().setText(IdeBundle.message("errortree.noMessages"));
myAutoScrollToSourceHandler.install(myTree);
TreeUtil.installActions(myTree);
UIUtil.setLineStyleAngled(myTree);
myTree.setRootVisible(false);
myTree.setShowsRootHandles(true);
myTree.setLargeModel(true);
JScrollPane scrollPane = NewErrorTreeRenderer.install(myTree);
scrollPane.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT));
myMessagePanel.add(PantsConsoleManager.getOrMakeNewConsole(myProject).getComponent(), BorderLayout.CENTER);
add(createToolbarPanel(), BorderLayout.WEST);
add(myMessagePanel, BorderLayout.CENTER);
EditSourceOnDoubleClickHandler.install(myTree);
}
@NotNull
protected Tree createTree(@NotNull final DefaultTreeModel treeModel) {
return new Tree(treeModel) {
@Override
public void setRowHeight(int i) {
super.setRowHeight(0);
// this is needed in order to make UI calculate the height for each particular row
}
};
}
private class StopAction extends DumbAwareAction {
public StopAction() {
super(IdeBundle.message("action.stop"), null, AllIcons.Actions.Suspend);
}
@Override
public void actionPerformed(AnActionEvent e) {
PantsMakeBeforeRun.terminatePantsProcess(e.getProject());
PantsConsoleManager.getOrMakeNewConsole(e.getProject()).print(PantsBundle.message("pants.command.terminated"), ConsoleViewContentType.ERROR_OUTPUT);
}
@Override
public void update(AnActionEvent event) {
// Make the action only clickable when there is an active Pants process.
Presentation presentation = event.getPresentation();
Project project = event.getProject();
if (project == null) {
return;
}
presentation.setEnabled(PantsMakeBeforeRun.hasActivePantsProcess(project));
}
}
private JPanel createToolbarPanel() {
AnAction closeMessageViewAction = new StopAction();
DefaultActionGroup leftUpdateableActionGroup = new DefaultActionGroup();
leftUpdateableActionGroup.add(closeMessageViewAction);
JPanel toolbarPanel = new JPanel(new BorderLayout());
ActionManager actionManager = ActionManager.getInstance();
ActionToolbar leftToolbar = actionManager.createActionToolbar(ActionPlaces.COMPILER_MESSAGES_TOOLBAR, leftUpdateableActionGroup, false);
toolbarPanel.add(leftToolbar.getComponent(), BorderLayout.WEST);
return toolbarPanel;
}
}