Java tutorial
/******************************************************************************* * * Copyright (c) 2016 ecFeed AS. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * *******************************************************************************/ package com.ecfeed.ui.dialogs; import java.text.DecimalFormat; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import com.ecfeed.core.adapter.IImplementationStatusResolver; import com.ecfeed.core.model.MethodNode; import com.ecfeed.core.model.TestCaseNode; import com.ecfeed.ui.common.EclipseImplementationStatusResolver; import com.ecfeed.ui.common.Messages; import com.ecfeed.ui.common.TestCasesViewerContentProvider; import com.ecfeed.ui.common.TestCasesViewerLabelProvider; import com.ecfeed.ui.common.TreeCheckStateListener; import com.ecfeed.ui.common.utils.IFileInfoProvider; public class CalculateCoverageDialog extends TitleAreaDialog { private Canvas[] fCanvasSet; private CoverageCalculator fCalculator; private MethodNode fMethod; IFileInfoProvider fFileInfoProvider; //Initial state of the tree viewer private final Object[] fInitChecked; private final Object[] fInitGrayed; private CheckboxTreeViewer fTestCasesViewer; private CoverageTreeViewerListener fCheckStateListener; private IImplementationStatusResolver fStatusResolver; private class CoverageTreeViewerListener extends TreeCheckStateListener { // saved tree state Object fTreeState[]; public CoverageTreeViewerListener(CheckboxTreeViewer treeViewer) { super(treeViewer); fTreeState = new Object[0]; } @Override public void checkStateChanged(CheckStateChangedEvent event) { super.checkStateChanged(event); Object element = event.getElement(); boolean checked = event.getChecked(); Set<TestCaseNode> checkedTestCases; if (fTestCasesViewer.getCheckedElements().length == 0) { checkedTestCases = null; } else { checkedTestCases = getCheckedTestCases(element, checked); } applyCheckedTestCases(checkedTestCases, checked); } public void applyCheckedTestCases(Collection<TestCaseNode> checkedTestCases, boolean checked) { fCalculator.setCurrentChangedCases(checkedTestCases, checked); if (fCalculator.calculateCoverage()) { fTreeState = getViewer().getCheckedElements(); drawBarGraph(); } else { revertLastTreeChange(); } } private Set<TestCaseNode> getCheckedTestCases(Object element, boolean checked) { Set<TestCaseNode> testCases = new HashSet<>(); if (checked) { // TestSuite if (element instanceof String) { String testSuiteName = (String) element; testCases.addAll(fMethod.getTestCases(testSuiteName)); } // TestCaseNode else { testCases.add((TestCaseNode) element); } } // if action is deselection else { // TestSuite if (element instanceof String) { String testSuiteName = (String) element; // if test suite was grayed add all test cases of that suite // that were checked for (Object tcase : fTreeState) { if (testSuiteName.equals(getContentProvider().getParent(tcase))) { testCases.add((TestCaseNode) tcase); } } // if parent has no children shown in the tree, but they all // are implicitly selected if (testCases.isEmpty()) { testCases.addAll(fMethod.getTestCases(testSuiteName)); } } // TestCaseNode else { testCases.add((TestCaseNode) element); } } return testCases; } private void revertLastTreeChange() { getViewer().setCheckedElements(fTreeState); } } public CalculateCoverageDialog(Shell parentShell, MethodNode method, Object[] checked, Object[] grayed, IFileInfoProvider fileInfoProvider) { super(parentShell); setHelpAvailable(false); setShellStyle(SWT.BORDER | SWT.RESIZE | SWT.TITLE | SWT.APPLICATION_MODAL); fFileInfoProvider = fileInfoProvider; fMethod = method; fCalculator = new CoverageCalculator(fMethod.getMethodParameters()); fStatusResolver = new EclipseImplementationStatusResolver(fileInfoProvider); fInitChecked = checked; fInitGrayed = grayed; } @Override public Point getInitialSize() { return new Point(600, 800); } @Override protected void createButtonsForButtonBar(Composite parent) { Button okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, false); okButton.setEnabled(true); } @Override protected Control createDialogArea(Composite parent) { setTitle(Messages.DIALOG_CALCULATE_COVERAGE_TITLE); setMessage(Messages.DIALOG_CALCULATE_COVERAGE_MESSAGE); Composite area = (Composite) super.createDialogArea(parent); Composite mainContainer = new Composite(area, SWT.NONE); mainContainer.setLayout(new GridLayout(1, false)); mainContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); createTestCaseComposite(mainContainer); createCoverageGraphComposite(mainContainer); setInitialSelection(fTestCasesViewer, fInitChecked, fInitGrayed); //Draw bar graph. Possible change for a timer with slight delay if tests prove current solution insufficient in some cases. Display.getDefault().asyncExec(new Runnable() { @Override public void run() { drawBarGraph(); } }); return area; } private void setInitialSelection(CheckboxTreeViewer viewer, Object[] checked, Object[] grayed) { viewer.setCheckedElements(checked); viewer.setGrayedElements(grayed); Set<TestCaseNode> testCases = new HashSet<>(); for (Object element : checked) { //if the element is non grayed test suite name if (element instanceof String && Arrays.asList(grayed).contains(element) == false) { testCases.addAll(fMethod.getTestCases((String) element)); } else if (element instanceof TestCaseNode) { testCases.add((TestCaseNode) element); } } fCheckStateListener.applyCheckedTestCases(testCases, true); } private void createTestCaseComposite(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new GridLayout(1, false)); GridData griddata = new GridData(SWT.FILL, SWT.FILL, true, true); griddata.minimumHeight = 250; composite.setLayoutData(griddata); Label selectTestCasesLabel = new Label(composite, SWT.WRAP); selectTestCasesLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); selectTestCasesLabel.setText(Messages.DIALOG_CALCULATE_COVERAGE_MESSAGE); createTestCaseViewer(composite); } private void createTestCaseViewer(Composite parent) { Tree tree = new Tree(parent, SWT.CHECK | SWT.BORDER); tree.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true, 1, 1)); fTestCasesViewer = new CheckboxTreeViewer(tree); fTestCasesViewer.setContentProvider(new TestCasesViewerContentProvider(fMethod)); fTestCasesViewer .setLabelProvider(new TestCasesViewerLabelProvider(fStatusResolver, fMethod, fFileInfoProvider)); fTestCasesViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); fTestCasesViewer.setInput(fMethod); fCheckStateListener = new CoverageTreeViewerListener(fTestCasesViewer); fTestCasesViewer.addCheckStateListener(fCheckStateListener); } private void createCoverageGraphComposite(Composite parent) { ScrolledComposite scrolled = new ScrolledComposite(parent, SWT.BORDER | SWT.FILL | SWT.V_SCROLL); GridData scrolledgriddata = new GridData(SWT.FILL, SWT.FILL, true, true); scrolledgriddata.minimumWidth = 100; scrolledgriddata.minimumHeight = 150; scrolled.setLayout(new GridLayout(1, false)); scrolled.setLayoutData(scrolledgriddata); scrolled.setExpandHorizontal(true); scrolled.setExpandVertical(true); Composite composite = new Composite(scrolled, SWT.BORDER | SWT.FILL); composite.setLayout(new GridLayout(1, false)); GridData griddata = new GridData(SWT.FILL, SWT.FILL, true, true); griddata.minimumHeight = 100; composite.setLayoutData(griddata); createCoverageGraphViewer(composite); scrolled.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); scrolled.setContent(composite); final ScrollBar vBar = scrolled.getVerticalBar(); SelectionListener listener = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { drawBarGraph(); } }; vBar.addSelectionListener(listener); } private void createCoverageGraphViewer(Composite parent) { fCanvasSet = new Canvas[getN()]; for (int n = 0; n < getN(); n++) { fCanvasSet[n] = new Canvas(parent, SWT.FILL); fCanvasSet[n].setSize(getInitialSize().x, 40); GridData griddata = new GridData(SWT.FILL, SWT.FILL, true, false); griddata.minimumHeight = 40; fCanvasSet[n].setLayoutData(griddata); } parent.getParent().addListener(SWT.Resize, new Listener() { @Override public void handleEvent(Event e) { drawBarGraph(); } }); } private void drawBarGraph() { double[] coverage = fCalculator.getCoverage(); if (getN() == coverage.length) { for (int n = 0; n < getN(); n++) { Display display = Display.getCurrent(); Canvas fCanvas = fCanvasSet[n]; fCanvas.setSize(fCanvas.getParent().getSize().x, 40); GC gc = new GC(fCanvas); gc.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); gc.fillRectangle(0, 0, fCanvas.getSize().x, fCanvas.getSize().y); int spacing = 5; int width = fCanvas.getSize().x - spacing * 8; int height = fCanvas.getSize().y; // Clear the canvas Color outworldTeal = new Color(display, 16, 224, 224); gc.setBackground(outworldTeal); Color lightBlue = new Color(display, 96, 128, 255); double widthunit = (double) width / 100; int fontsize = height / 4; Font font = new Font(display, display.getSystemFont().getFontData()[0].getName(), fontsize, 1); gc.setFont(font); int linewidth = 2; int topborder; int topbarborder; int bottomborder = 0; int fontspacing = (fontsize * 8) / 5; topborder = 0; topbarborder = topborder + fontspacing; bottomborder = height - spacing; gc.setForeground(lightBlue); gc.fillGradientRectangle(0, topbarborder, (int) (coverage[n] * widthunit), bottomborder - topbarborder, false); gc.setLineWidth(linewidth); gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK)); gc.drawLine(linewidth, bottomborder, width - linewidth, bottomborder); gc.drawLine(linewidth / 2, topbarborder, linewidth / 2, bottomborder); gc.drawLine((width) - linewidth / 2, topbarborder, (width) - linewidth / 2, bottomborder); DecimalFormat df = new DecimalFormat("#.00"); String nlabel = "N= " + (n + 1); String percentvalue = df.format(coverage[n]) + "%"; gc.drawString(nlabel, 10, topborder, true); gc.drawString(percentvalue, (width / 2) - fontspacing, (topbarborder), true); font.dispose(); outworldTeal.dispose(); gc.dispose(); } } } private int getN() { return fMethod.getParameters().size(); } }