package org.simantics.tests.modelled.ui; import java.util.List; import java.util.concurrent.Executors; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.eclipse.e4.ui.di.Focus; import org.eclipse.jface.layout.TreeColumnLayout; import org.eclipse.jface.viewers.CellLabelProvider; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.OwnerDrawLabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.TreeViewerColumn; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.custom.ViewForm; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Layout; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.ui.part.PageBook; import org.simantics.db.Resource; import org.simantics.scl.compiler.module.coverage.Coverage; public class STSTestRunnerView { public static final String ID = "org.simantics.tests.modelled.ui.stsTestRunnerView"; private Resource test; private SashForm sashForm; private PageBook viewerbook; private TreeViewer treeViewer; // private ITreeContentProvider treeContentProvider; private STSTestSuiteProvider provider; private StyledText output; private STSCounterPanel counterPanel; private STSProgressBar progressBar; private Composite counterComposite; @PostConstruct void createView(Composite parent) { GridLayout gridLayout= new GridLayout(); gridLayout.marginWidth= 0; gridLayout.marginHeight= 0; parent.setLayout(gridLayout); counterComposite= createProgressCountPanel(parent); counterComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); counterComposite.pack(); SashForm sashForm = createSashForm(parent); sashForm.setLayoutData(new GridData(GridData.FILL_BOTH)); } private SashForm createSashForm(Composite parent) { sashForm = new SashForm(parent, SWT.VERTICAL); ViewForm top = new ViewForm(sashForm, SWT.NONE); Composite empty = new Composite(top, SWT.NONE); empty.setLayout(new Layout() { @Override protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { return new Point(1, 1); // (0, 0) does not work with super-intelligent ViewForm } @Override protected void layout(Composite composite, boolean flushCache) { } }); top.setTopLeft(empty); // makes ViewForm draw the horizontal separator line ... // fTestViewer= new TestViewer(top, fClipboard, this); createTestViewers(top); top.setContent(viewerbook); treeViewer.setInput(test); ViewForm bottom = new ViewForm(sashForm, SWT.NONE); CTabFolder folder = new CTabFolder(bottom, SWT.BORDER); folder.setLayoutData(new GridData(GridData.FILL_BOTH)); CTabItem item1 = new CTabItem(folder, SWT.NONE); item1.setText("Execution"); // PageBook fViewerbook2= new PageBook(bottom, SWT.NULL); // Upper output = new StyledText(folder, SWT.MULTI | SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL); // output.setFont(textFont); { FormData formData = new FormData(); formData.top = new FormAttachment(0); // formData.bottom = new FormAttachment(sash); formData.left = new FormAttachment(0); formData.right = new FormAttachment(100); output.setLayoutData(formData); } item1.setControl(output); // fViewerbook2.showPage(output); bottom.setContent(folder); folder.setSelection(0); CTabItem item2 = new CTabItem(folder, SWT.NONE); item2.setText("Coverage"); Composite treeComposite = new Composite(folder, SWT.NONE); TreeViewer viewer = createCoverageViewer(treeComposite); item2.setControl(treeComposite); treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { ISelection selection = event.getSelection(); TreeSelection sel = (TreeSelection) selection; List testOutput = provider.getModel().getOutput(sel.getFirstElement()); viewer.setInput(sel.getFirstElement()); StringBuilder sb = new StringBuilder(); for (String o : testOutput) { sb.append(o); } output.setText(sb.toString()); } }); sashForm.setWeights(new int[] {50, 50}); return sashForm; } protected static final int COLUMN_ELEMENT = 0; protected static final int COLUMN_RATIO = 1; protected static final int COLUMN_COVERED = 2; protected static final int COLUMN_MISSED = 3; protected static final int COLUMN_TOTAL = 4; private TreeViewer createCoverageViewer(Composite parent) { // Composite treeViewerComposite = new Composite(parent, SWT.NONE); TreeColumnLayout layout = new TreeColumnLayout(); parent.setLayout(layout); Tree tree = new Tree(parent, SWT.MULTI | SWT.FULL_SELECTION); tree.setHeaderVisible(true); tree.setLinesVisible(true); STSCoverageProvider provider = new STSCoverageProvider(); TreeViewer viewer = new TreeViewer(tree); CoverageViewSorter sorter = new CoverageViewSorter(viewer); final TreeViewerColumn column0 = new TreeViewerColumn(viewer, SWT.LEFT); column0.setLabelProvider(new CellLabelProvider() { @Override public void update(ViewerCell cell) { cell.setText(provider.getText(cell.getElement())); cell.setImage(provider.getImage(cell.getElement())); } }); sorter.addColumn(column0, COLUMN_ELEMENT); final TreeViewerColumn column1 = new TreeViewerColumn(viewer, SWT.RIGHT); column1.setLabelProvider(new OwnerDrawLabelProvider() { @Override public void update(ViewerCell cell) { cell.setText(provider.getRatio(cell.getElement())); } @Override protected void erase(Event event, Object element) { } @Override protected void measure(Event event, Object element) { } @Override protected void paint(Event event, Object element) { final Coverage coverage = (Coverage) element; if (coverage != null) { RedGreenBar.draw(event, column1.getColumn().getWidth(), coverage); } } }); sorter.addColumn(column1, COLUMN_RATIO); final TreeViewerColumn column2 = new TreeViewerColumn(viewer, SWT.RIGHT); column2.setLabelProvider(new CellLabelProvider() { @Override public void update(ViewerCell cell) { cell.setText(provider.getCovered(cell.getElement())); } }); sorter.addColumn(column2, COLUMN_COVERED); final TreeViewerColumn column3 = new TreeViewerColumn(viewer, SWT.RIGHT); column3.setLabelProvider(new CellLabelProvider() { @Override public void update(ViewerCell cell) { cell.setText(provider.getMissed(cell.getElement())); } }); sorter.addColumn(column3, COLUMN_MISSED); final TreeViewerColumn column4 = new TreeViewerColumn(viewer, SWT.RIGHT); column4.setLabelProvider(new CellLabelProvider() { @Override public void update(ViewerCell cell) { cell.setText(provider.getTotal(cell.getElement())); } }); sorter.addColumn(column4, COLUMN_TOTAL); // viewer.addFilter(new ViewerFilter() { // public boolean select(Viewer viewer, Object parentElement, Object element) { // if (element == LOADING_ELEMENT) { // return true; // } else { // final ICoverageNode c = CoverageTools.getCoverageInfo(element); // if (c == null) { // return false; // } // final ICounter instructions = c.getInstructionCounter(); // if (instructions.getTotalCount() == 0) { // return false; // } // if (settings.getHideUnusedElements() && instructions.getCoveredCount() == 0) { // return false; // } // return true; // } // } // }); viewer.setComparator(sorter); layout.setColumnData(column0.getColumn(), new ColumnWeightData(0, 50, false)); layout.setColumnData(column1.getColumn(), new ColumnWeightData(0, 50, false)); layout.setColumnData(column2.getColumn(), new ColumnWeightData(0, 50, false)); layout.setColumnData(column3.getColumn(), new ColumnWeightData(0, 50, false)); layout.setColumnData(column4.getColumn(), new ColumnWeightData(0, 50, false)); String[] columns = new String[] {"Module", "Coverage", "Covered Instructions", "Missed Instructions", "Total Instructions"}; TreeColumn[] columns2 = viewer.getTree().getColumns(); for (int i = 0; i < columns2.length; i++) { columns2[i].setText(columns[i]); } restoreColumnWidth(viewer); viewer.setContentProvider(provider); return viewer; // viewer.addOpenListener(new IOpenListener() { // public void open(OpenEvent event) { // openAction.run((IStructuredSelection) event.getSelection()); // } // }); // MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ // menuMgr.setRemoveAllWhenShown(true); // tree.setMenu(menuMgr.createContextMenu(tree)); // getSite().registerContextMenu(menuMgr, viewer); // // CoverageTools.getSessionManager().addSessionListener(descriptionUpdater); // CoverageTools.addJavaCoverageListener(coverageListener); } private static final int[] DEFAULT_COLUMNWIDTH = new int[] { 200, 100, 120, 120, 120 }; public void restoreColumnWidth(TreeViewer viewer) { final TreeColumn[] columns = viewer.getTree().getColumns(); for (int i = 0; i < DEFAULT_COLUMNWIDTH.length; i++) { columns[i].setWidth(DEFAULT_COLUMNWIDTH[i]); } } protected Composite createProgressCountPanel(Composite parent) { Composite composite= new Composite(parent, SWT.NONE); GridLayout layout= new GridLayout(); composite.setLayout(layout); layout.numColumns = 1; counterPanel = new STSCounterPanel(composite); counterPanel.setLayoutData( new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); progressBar = new STSProgressBar(composite); progressBar.setLayoutData( new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); return composite; } private void createTestViewers(Composite parent) { viewerbook = new PageBook(parent, SWT.NULL); treeViewer = new TreeViewer(viewerbook, SWT.V_SCROLL | SWT.SINGLE); treeViewer.setUseHashlookup(true); STSTestSuiteModel model = new STSTestSuiteModel(); model.addListener(new STSExecutionListener() { @Override public void testExecuted() { treeViewer.getControl().getDisplay().syncExec(() -> { refreshCounters(); treeViewer.refresh(); }); } }); provider = new STSTestSuiteProvider(model); treeViewer.setContentProvider(provider); treeViewer.setLabelProvider(provider); viewerbook.showPage(treeViewer.getTree()); } @Focus void setFocus() { sashForm.setFocus(); } public void currentTest(Resource test) { treeViewer.setInput(test); refreshCounters(); } private void refreshCounters() { // TODO: Inefficient. Either // - keep a boolean fHasTestRun and update only on changes, or // - improve components to only redraw on changes (once!). int startedCount; int ignoredCount; int totalCount; int errorCount; int failureCount; int assumptionFailureCount; boolean hasErrorsOrFailures; boolean stopped; STSTestSuiteModel model = provider.getModel(); if (model != null) { startedCount= model.getStartedCount(); ignoredCount= model.getIgnoredCount(); totalCount= model.getTotalCount(); errorCount= model.getErrorCount(); failureCount= model.getFailureCount(); assumptionFailureCount = model.getAssumptionFailureCount(); hasErrorsOrFailures= errorCount + failureCount > 0; stopped= model.isStopped(); } else { startedCount= 0; ignoredCount= 0; totalCount= 0; errorCount= 0; failureCount= 0; assumptionFailureCount = 0; hasErrorsOrFailures= false; stopped= false; } counterPanel.setTotal(totalCount); counterPanel.setRunValue(startedCount, ignoredCount, assumptionFailureCount); counterPanel.setErrorValue(errorCount); counterPanel.setFailureValue(failureCount); int ticksDone; if (startedCount == 0) ticksDone= 0; else if (startedCount == totalCount && model.isStopped()) ticksDone= totalCount; else ticksDone= startedCount - 1; progressBar.reset(hasErrorsOrFailures, stopped, ticksDone, totalCount); } public void execute() { Executors.newSingleThreadExecutor().submit(new Runnable() { @Override public void run() { provider.getModel().execute(); } }); } @PreDestroy public void destroy() { provider.dispose(); } }