package jetbrains.mps.baseLanguage.unitTest.execution.tool; /*Generated by MPS */ import javax.swing.JPanel; import com.intellij.openapi.Disposable; import jetbrains.mps.baseLanguage.unitTest.execution.client.TestRunState; import jetbrains.mps.project.MPSProject; import java.util.List; import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import com.intellij.openapi.project.Project; import com.intellij.execution.ui.ConsoleView; import jetbrains.mps.ide.project.ProjectHelper; import javax.swing.JComponent; import java.awt.Dimension; import com.intellij.openapi.ui.Splitter; import java.awt.BorderLayout; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.actionSystem.ActionPlaces; import javax.swing.JScrollPane; import com.intellij.ui.ScrollPaneFactory; import javax.swing.JTable; import com.intellij.ui.table.JBTable; import java.awt.GridLayout; import com.intellij.ui.components.JBScrollPane; import com.intellij.execution.process.ProcessListener; import java.awt.GridBagLayout; import java.awt.GridBagConstraints; import com.intellij.ide.util.PropertiesComponent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; import com.intellij.openapi.actionSystem.DataProvider; import java.awt.LayoutManager; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.NonNls; import jetbrains.mps.workbench.MPSDataKeys; import jetbrains.mps.ide.ui.tree.MPSTreeNode; import jetbrains.mps.baseLanguage.unitTest.execution.client.ITestNodeWrapper; public class UnitTestViewComponent extends JPanel implements Disposable { private static final String SPLITTER_SIZE_PROPERTY = UnitTestOptions.PREFIX + ".UnitTestViewComponent" + ".splitter"; private final TestRunState myTestState; private final TestOutputComponent myOutputComponent; private final TestTree myTreeComponent; private final ProgressLine myProgressLineComponent; private final TestToolbarPanel myActionToolComponent; private final MPSProject myProject; private final FailedTestOccurrenceNavigator myTestNavigator; private final List<_FunctionTypes._void_P0_E0> myListeners = ListSequence.fromList(new ArrayList<_FunctionTypes._void_P0_E0>()); public UnitTestViewComponent(Project project, ConsoleView console, TestRunState testRunState, _FunctionTypes._void_P0_E0 closeListener) { myProject = ProjectHelper.fromIdeaProject(project); myTestState = testRunState; StatisticsTableModel statisticsModel = new StatisticsTableModel(myTestState); myTreeComponent = new TestTree(myTestState, myProject, this); myTestNavigator = new FailedTestOccurrenceNavigator(myTreeComponent); myActionToolComponent = new TestToolbarPanel(myTreeComponent, myTestNavigator); JComponent leftPanel = createTreeComponent(myActionToolComponent, myTreeComponent); myProgressLineComponent = new ProgressLine(myTestState); myProgressLineComponent.setMinimumSize(new Dimension(0, myProgressLineComponent.getMinimumSize().height)); myOutputComponent = new TestOutputComponent(console, myTestState); myTreeComponent.addTreeSelectionListener(new TestTreeSelectionListener(myTreeComponent, statisticsModel, myOutputComponent)); myTreeComponent.addMouseListener(new TestTreeRootMouseListener(myTreeComponent, statisticsModel, myOutputComponent)); JPanel rightPanel = createOutputComponent(console, myProgressLineComponent, myOutputComponent.getComponent(), statisticsModel); Splitter splitter = new Splitter(false); initSplitterProportion(splitter, 0.2f, "tree"); splitter.setFirstComponent(leftPanel); splitter.setSecondComponent(rightPanel); setLayout(new BorderLayout()); add(splitter, BorderLayout.CENTER); myTestState.addView(myTreeComponent); myTestState.addView(myProgressLineComponent); myTestState.addView(myOutputComponent); addCloseListener(closeListener); } public JComponent createActionsToolbar(ConsoleView console) { DefaultActionGroup group = new DefaultActionGroup(console.createConsoleActions()); ActionManager manager = ActionManager.getInstance(); ActionToolbar toolbar = manager.createActionToolbar(ActionPlaces.UNKNOWN, group, false); toolbar.setLayoutPolicy(ActionToolbar.WRAP_LAYOUT_POLICY); return toolbar.getComponent(); } private JComponent createTreeComponent(JComponent toolbar, JComponent tree) { UnitTestViewComponent.MyTreePanel treePanel = new UnitTestViewComponent.MyTreePanel(new BorderLayout()); JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(tree); treePanel.add(scrollPane, BorderLayout.CENTER); treePanel.add(toolbar, BorderLayout.NORTH); return treePanel; } private JComponent createStatisticsComponent(StatisticsTableModel testStatisticsModel) { JTable statisticsTable = new JBTable(testStatisticsModel); statisticsTable.setDefaultRenderer(TestStatisticsRow.class, new StatisticsRowRenderer()); JPanel tablePanel = new JPanel(new GridLayout(1, 1)); tablePanel.add(new JBScrollPane(statisticsTable)); return tablePanel; } public ProcessListener getProcessListener() { return myProgressLineComponent.getProcessListener(); } @Override public void dispose() { myOutputComponent.dispose(); myTreeComponent.dispose(); invokeCloseListeners(); } public void addCloseListener(_FunctionTypes._void_P0_E0 listener) { ListSequence.fromList(myListeners).addElement(listener); } public void invokeCloseListeners() { for (_FunctionTypes._void_P0_E0 listener : ListSequence.fromList(myListeners)) { listener.invoke(); } } private JPanel createOutputComponent(ConsoleView console, JComponent progressLine, JComponent testOutput, StatisticsTableModel statisticsModel) { JPanel rightPanel = new JPanel(new GridBagLayout()); JComponent stackTraceActions = createActionsToolbar(console); stackTraceActions.setMaximumSize(new Dimension(rightPanel.getWidth(), stackTraceActions.getMaximumSize().height)); Splitter outputStatisticSplitter = new Splitter(false); initSplitterProportion(outputStatisticSplitter, 0.5f, "statistic"); outputStatisticSplitter.setFirstComponent(testOutput); JComponent statistics = createStatisticsComponent(statisticsModel); outputStatisticSplitter.setSecondComponent(statistics); GridBagConstraints c = new GridBagConstraints(); rightPanel.setBorder(null); c.fill = GridBagConstraints.VERTICAL; c.anchor = GridBagConstraints.LINE_START; c.gridx = 0; c.gridy = 1; c.weighty = 1; c.weightx = 0; rightPanel.add(stackTraceActions, c); c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 1; c.gridy = 0; c.weighty = 0; c.weightx = 1; rightPanel.add(progressLine, c); c.fill = GridBagConstraints.BOTH; c.gridx = 1; c.gridy = 1; c.weighty = 1; c.weightx = 1; rightPanel.add(outputStatisticSplitter, c); return rightPanel; } public void initSplitterProportion(final Splitter splitter, float defaultProportion, final String id) { final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(); String value = propertiesComponent.getValue(UnitTestViewComponent.SPLITTER_SIZE_PROPERTY + "." + id); float proportion = defaultProportion; if ((value != null && value.length() > 0)) { try { proportion = Float.parseFloat(value); } catch (NumberFormatException ignore) { } } splitter.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { if (event.getPropertyName().equals(Splitter.PROP_PROPORTION)) { propertiesComponent.setValue(UnitTestViewComponent.SPLITTER_SIZE_PROPERTY + "." + id, String.valueOf(splitter.getProportion())); } } }); splitter.setProportion(proportion); } /*package*/ class MyTreePanel extends JPanel implements DataProvider { public MyTreePanel(LayoutManager manager) { super(manager); } @Nullable @Override public Object getData(@NonNls String dataId) { if (MPSDataKeys.MPS_PROJECT.is(dataId)) { return myProject; } if (MPSDataKeys.NODE.is(dataId)) { MPSTreeNode currentNode = myTreeComponent.getCurrentNode(); if (currentNode == null) { return null; } ITestNodeWrapper testWrapper = (ITestNodeWrapper) currentNode.getUserObject(); // XXX it's unclear whether we shall assume model read lock here, or obtain it ourselves // I didn't get the lock here as it's stupid to ask for SNode not inside a lock already. return testWrapper.getNodePointer().resolve(myProject.getRepository()); } return null; } } }