Java tutorial
/** * Copyright (c) 2009-2010 MATSUFUJI Hideharu <matsufuji2008@gmail.com>, * 2010-2013 KUBO Atsuhiro <kubo@iteman.jp>, * All rights reserved. * * This file is part of MakeGood. * * 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.piece_framework.makegood.ui.views; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.contexts.IContextService; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.progress.UIJob; import com.piece_framework.makegood.core.TestResultsLayout; import com.piece_framework.makegood.core.result.Result; import com.piece_framework.makegood.core.result.TestCaseResult; import com.piece_framework.makegood.core.result.TestSuiteResult; import com.piece_framework.makegood.core.run.Failures; import com.piece_framework.makegood.launch.CommandLineBuilder; import com.piece_framework.makegood.launch.MakeGoodLaunch; import com.piece_framework.makegood.launch.TestLifecycle; import com.piece_framework.makegood.ui.Activator; import com.piece_framework.makegood.ui.MakeGoodContext; import com.piece_framework.makegood.ui.MakeGoodStatus; import com.piece_framework.makegood.ui.MakeGoodStatusChangeListener; import com.piece_framework.makegood.ui.Messages; import com.piece_framework.makegood.ui.TestResultsLayoutChangeListener; import com.piece_framework.makegood.ui.actions.ConfigureContinuousTestingAction; import com.piece_framework.makegood.ui.actions.MoveToNextFailureAction; import com.piece_framework.makegood.ui.actions.MoveToPreviousFailureAction; import com.piece_framework.makegood.ui.actions.RerunFailedTestsAction; import com.piece_framework.makegood.ui.actions.RerunTestAction; import com.piece_framework.makegood.ui.actions.RunAllTestsAction; import com.piece_framework.makegood.ui.actions.StopTestRunAction; import com.piece_framework.makegood.ui.actions.ToggleDebugTestAction; import com.piece_framework.makegood.ui.actions.ToggleShowOnlyFailuresAction; import com.piece_framework.makegood.ui.actions.ToggleStopOnFailureAction; import com.piece_framework.makegood.ui.widgets.ActiveText; import com.piece_framework.makegood.ui.widgets.ActiveTextListener; import com.piece_framework.makegood.ui.widgets.ExternalFileWithLineRange; import com.piece_framework.makegood.ui.widgets.FileWithLineRange; import com.piece_framework.makegood.ui.widgets.InternalFileWithLineRange; import com.piece_framework.makegood.ui.widgets.MakeGoodColor; import com.piece_framework.makegood.ui.widgets.ProgressBar; public class ResultView extends ViewPart implements TestResultsLayoutChangeListener { public static final String VIEW_ID = "com.piece_framework.makegood.ui.views.resultView"; //$NON-NLS-1$ /** * @since 2.5.0 */ public static boolean showOnlyFailures = false; private static final String CONTEXT_ID = "com.piece_framework.makegood.ui.contexts.resultView"; //$NON-NLS-1$ private ProgressBar progressBar; private CLabel testCountLabel; private CountLabel passCountLabel; private CountLabel failureCountLabel; private CountLabel errorCountLabel; private TreeViewer resultTreeViewer; private CLabel processTimeAverageLabel; private ElapsedTimer elapsedTimer; private IAction moveToPreviousFailureAction; private IAction moveToNextFailureAction; private IAction stopTestAction; /** * @since 2.1.0 */ private IAction rerunFailedTestsAction; private IAction rerunTestAction; private IAction runAllTestsAction; private FailureTrace failureTrace; private CLabel elapsedTimeLabel; private CLabel processTimeLabel; private boolean actionsInitialized = false; private ResultViewPartListener partListener = new ResultViewPartListener(); private EditorOpener editorOpener = new EditorOpener(); private ViewerFilter failureViewFilter = new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (!(element instanceof Result)) return false; Result result = (Result) element; return result.hasFailures() || result.hasErrors(); } }; /** * @since 1.3.0 */ private TestLifecycle testLifecycle; /** * @since 1.6.0 */ private StatusArea statusArea; /** * @since 1.8.0 */ private AdditionalInformation additionalInformation = new AdditionalInformation(); /** * @since 1.9.0 */ private CLabel endTimeLabel; /** * @since 2.5.0 */ private Composite testResultsComposite; @Override public void createPartControl(final Composite parent) { IContextService service = (IContextService) getSite().getService(IContextService.class); service.activateContext(CONTEXT_ID); parent.setLayout(adjustLayout(new GridLayout())); // Row1: The Status Area statusArea = createStatusArea(parent, SWT.NONE); statusArea.setLayoutData(createHorizontalFillGridData()); statusArea.setLayout(adjustLayout(new GridLayout())); // Row2: The Progress Bar and Watches Composite progressBarAndWatches = new Composite(parent, SWT.NONE); progressBarAndWatches.setLayoutData(createHorizontalFillGridData()); progressBarAndWatches.setLayout(adjustLayout(new GridLayout(5, true))); Composite progress = new Composite(progressBarAndWatches, SWT.NONE); GridData progressGridData = createHorizontalFillGridData(); progressGridData.horizontalSpan = 2; progress.setLayoutData(progressGridData); progress.setLayout(adjustLayout(new GridLayout())); Composite progressBarBorder = new Composite(progress, SWT.NONE); progressBarBorder.setLayoutData(createHorizontalFillGridData()); GridLayout progressBarBorderLayout = new GridLayout(); progressBarBorderLayout.marginWidth = 2; progressBarBorderLayout.marginHeight = 2; progressBarBorderLayout.horizontalSpacing = 2; progressBarBorderLayout.verticalSpacing = 2; progressBarBorder.setLayout(progressBarBorderLayout); progressBar = new ProgressBar(progressBarBorder); progressBar.setLayoutData(createHorizontalFillGridData()); progressBar.setLayout(adjustLayout(new GridLayout())); processTimeAverageLabel = new CLabel(progressBarAndWatches, SWT.LEFT); processTimeAverageLabel.setLayoutData(createHorizontalFillGridData()); processTimeLabel = new CLabel(progressBarAndWatches, SWT.LEFT); processTimeLabel.setLayoutData(createHorizontalFillGridData()); elapsedTimeLabel = new CLabel(progressBarAndWatches, SWT.LEFT); elapsedTimeLabel.setLayoutData(createHorizontalFillGridData()); // Row3: The Counters Composite counter = new Composite(parent, SWT.NONE); counter.setLayoutData(createHorizontalFillGridData()); counter.setLayout(adjustLayout(new GridLayout(5, true))); testCountLabel = new CLabel(counter, SWT.LEFT); testCountLabel.setLayoutData(createHorizontalFillGridData()); passCountLabel = new CountLabel(counter, SWT.LEFT, Messages.MakeGoodView_passesLabel, Activator.getImageDescriptor("icons/pass_gray.gif").createImage() //$NON-NLS-1$ ); failureCountLabel = new CountLabel(counter, SWT.LEFT, Messages.MakeGoodView_failuresLabel, Activator.getImageDescriptor("icons/failure_gray.gif").createImage() //$NON-NLS-1$ ); errorCountLabel = new CountLabel(counter, SWT.LEFT, Messages.MakeGoodView_errorsLabel, Activator.getImageDescriptor("icons/error_gray.gif").createImage() //$NON-NLS-1$ ); endTimeLabel = new CLabel(counter, SWT.LEFT); endTimeLabel.setLayoutData(createHorizontalFillGridData()); // Row4: The Test Results testResultsComposite = createTestResultsComposite(parent, SWT.NONE, MakeGoodContext.getInstance().getTestResultsLayout()); IViewSite site = getViewSite(); site.getPage().addPartListener(partListener); MakeGoodContext.getInstance().addStatusChangeListener(statusArea); MakeGoodContext.getInstance().addTestResultsLayoutChangeListener(this); clear(); testLifecycle = TestLifecycle.getInstance(); if (testLifecycle != null) { if (testLifecycle.getProgress().isStopped()) { markAsStopped(); } else if (testLifecycle.getProgress().hasFailures()) { markAsFailed(); } setTreeInput(testLifecycle.getProgress().getResult()); filterResults(); } elapsedTimer = new ElapsedTimer(200); } @Override public void setFocus() { resultTreeViewer.getTree().setFocus(); } private void clear() { progressBar.clear(); processTimeAverageLabel.setText(TimeFormatter.format(0) + "/" + //$NON-NLS-1$ Messages.MakeGoodView_averageTest); elapsedTimeLabel.setText(Messages.MakeGoodView_realTime + ": " + //$NON-NLS-1$ TimeFormatter.format(0)); processTimeLabel.setText(Messages.MakeGoodView_testTime + ": " + //$NON-NLS-1$ TimeFormatter.format(0)); endTimeLabel.setText(Messages.MakeGoodView_endTime + ":"); //$NON-NLS-1$ testCountLabel.setText(Messages.MakeGoodView_testsLabel + ": 0/0"); //$NON-NLS-1$ passCountLabel.clear(); failureCountLabel.clear(); errorCountLabel.clear(); resultTreeViewer.setInput(null); additionalInformation.clearMessage(); setContentDescription(additionalInformation.toString()); } private GridData createHorizontalFillGridData() { GridData horizontalFillGrid = new GridData(); horizontalFillGrid.horizontalAlignment = GridData.FILL; horizontalFillGrid.grabExcessHorizontalSpace = true; return horizontalFillGrid; } private GridData createBothFillGridData() { GridData bothFillGrid = new GridData(); bothFillGrid.horizontalAlignment = GridData.FILL; bothFillGrid.verticalAlignment = GridData.FILL; bothFillGrid.grabExcessHorizontalSpace = true; bothFillGrid.grabExcessVerticalSpace = true; return bothFillGrid; } private FailureTrace createFailureTrace(Composite parent, int style) { FailureTrace failureTrace = new FailureTrace(parent, style); failureTrace.setLayoutData(new GridData(GridData.FILL_BOTH)); failureTrace.setEditable(false); failureTrace.addListener(new EditorOpenActiveTextListener()); return failureTrace; } /** * @since 1.6.0 */ private StatusArea createStatusArea(Composite parent, int style) { StatusArea statusArea = new StatusArea(parent, style); statusArea.setBackground(parent.getBackground()); statusArea.addListener(new PreferencesOpenActiveTextListener()); return statusArea; } public void moveToNextFailure() { moveToPreviousOrNextFailure(Failures.FIND_NEXT); } public void moveToPreviousFailure() { moveToPreviousOrNextFailure(Failures.FIND_PREVIOUS); } @Override public void dispose() { IViewSite site = getViewSite(); if (site != null) { site.getPage().removePartListener(partListener); } MakeGoodContext.getInstance().removeTestResultsLayoutChangeListener(this); MakeGoodContext.getInstance().removeStatusChangeListener(statusArea); super.dispose(); } public void filterResults() { if (showOnlyFailures) { resultTreeViewer.addFilter(failureViewFilter); } else { resultTreeViewer.removeFilter(failureViewFilter); } } /** * @since 1.3.0 */ public boolean hasFailures() { if (testLifecycle == null) return false; return testLifecycle.getProgress().hasFailures(); } /** * @since 2.0.0 */ public void switchToUnselectedTestResultsTab() { if (testResultsComposite instanceof TabTestResultsComposite) { ((TabTestResultsComposite) testResultsComposite).switchToUnselectedTab(); } } void setTreeInput(TestSuiteResult result) { resultTreeViewer.setInput(result); } void updateOnEndTestCase() { if (testLifecycle.getProgress().hasFailures()) { markAsFailed(); } updateResult(); } void updateOnStartTestCase(TestCaseResult testCase) { updateTestCount(); resultTreeViewer.refresh(); } void startTest(TestLifecycle testLifecycle) { clear(); this.testLifecycle = testLifecycle; elapsedTimer.schedule(); } void endTest() { updateResult(); updateEndTime(); TreeItem topItem = resultTreeViewer.getTree().getTopItem(); if (topItem != null) { Result topResult = (Result) topItem.getData(); if (topResult != null) { resultTreeViewer.setSelection(new StructuredSelection(topResult)); } } } void markAsStopped() { progressBar.markAsStopped(); } void expandResultTreeToResult(Result result) { resultTreeViewer.expandToLevel(result, TreeViewer.ALL_LEVELS); } private void markAsFailed() { progressBar.markAsFailed(); if (moveToPreviousFailureAction != null) { moveToPreviousFailureAction.setEnabled(true); } if (moveToNextFailureAction != null) { moveToNextFailureAction.setEnabled(true); } } private void initializeActions(IViewSite site) { IToolBarManager manager = site.getActionBars().getToolBarManager(); ActionContributionItem showOnlyFailuresItem = (ActionContributionItem) manager .find(ToggleShowOnlyFailuresAction.ACTION_ID); if (showOnlyFailuresItem != null) { showOnlyFailuresItem.getAction().setChecked(showOnlyFailures); actionsInitialized = true; } ActionContributionItem previousFailureItem = (ActionContributionItem) manager .find(MoveToPreviousFailureAction.ACTION_ID); if (previousFailureItem != null) { moveToPreviousFailureAction = previousFailureItem.getAction(); moveToPreviousFailureAction.setEnabled(hasFailures()); } ActionContributionItem nextFailureItem = (ActionContributionItem) manager .find(MoveToNextFailureAction.ACTION_ID); if (nextFailureItem != null) { moveToNextFailureAction = nextFailureItem.getAction(); moveToNextFailureAction.setEnabled(hasFailures()); } ActionContributionItem stopOnFailureItem = (ActionContributionItem) manager .find(ToggleStopOnFailureAction.ACTION_ID); if (stopOnFailureItem != null) { stopOnFailureItem.getAction().setChecked(CommandLineBuilder.stopOnFailure); } ActionContributionItem debugTestItem = (ActionContributionItem) manager .find(ToggleDebugTestAction.ACTION_ID); if (debugTestItem != null) { debugTestItem.getAction().setChecked(MakeGoodContext.getInstance().isDebug()); } ActionContributionItem stopTestItem = (ActionContributionItem) manager.find(StopTestRunAction.ACTION_ID); if (stopTestItem != null) { stopTestAction = stopTestItem.getAction(); stopTestAction.setEnabled(MakeGoodLaunch.hasActiveLaunch()); } ActionContributionItem rerunTestItem = (ActionContributionItem) manager.find(RerunTestAction.ACTION_ID); if (rerunTestItem != null) { rerunTestAction = rerunTestItem.getAction(); rerunTestAction.setEnabled(MakeGoodContext.getInstance().getTestRunner().hasLastTest()); } ActionContributionItem rerunFailedTestsItem = (ActionContributionItem) manager .find(RerunFailedTestsAction.ACTION_ID); if (rerunFailedTestsItem != null) { rerunFailedTestsAction = rerunFailedTestsItem.getAction(); rerunFailedTestsAction.setEnabled(MakeGoodContext.getInstance().getTestRunner().hasLastTest()); } ActionContributionItem runAllTestsItem = (ActionContributionItem) manager.find(RunAllTestsAction.ACTION_ID); if (runAllTestsItem != null) { runAllTestsAction = runAllTestsItem.getAction(); runAllTestsAction.setEnabled(MakeGoodContext.getInstance().getActivePart().isAllTestsRunnable()); } ActionContributionItem configureContinuousTestingItem = (ActionContributionItem) manager .find(ConfigureContinuousTestingAction.ACTION_ID); if (configureContinuousTestingItem != null) { IAction configureContinuousTestingAction = configureContinuousTestingItem.getAction(); configureContinuousTestingAction .setImageDescriptor(MakeGoodContext.getInstance().getContinuousTesting().isEnabled() ? ConfigureContinuousTestingAction.IMAGE_DESCRIPTOR_ENABLED : ConfigureContinuousTestingAction.IMAGE_DESCRIPTOR_DISABLED); } } private GridLayout adjustLayout(GridLayout layout) { layout.marginWidth = 0; layout.marginHeight = 0; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; return layout; } private void moveToPreviousOrNextFailure(int direction) { Result selectedResult = (Result) ((IStructuredSelection) resultTreeViewer.getSelection()).getFirstElement(); if (selectedResult == null) { selectedResult = (Result) resultTreeViewer.getTree().getTopItem().getData(); } TestCaseResult previousOrNextResult = testLifecycle.getFailures().find(selectedResult, direction); if (previousOrNextResult == null) return; resultTreeViewer.setSelection(new StructuredSelection(previousOrNextResult), true); resultTreeViewer.expandToLevel(previousOrNextResult, TreeViewer.ALL_LEVELS); try { editorOpener.open(previousOrNextResult); } catch (PartInitException e) { Activator.getDefault().getLog() .log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, e.getMessage(), e)); } } private void updateResult() { progressBar.update(testLifecycle.getProgress().calculateRate()); processTimeAverageLabel .setText(TimeFormatter.format(testLifecycle.getProgress().calculateProcessTimeAverage()) + "/" + //$NON-NLS-1$ Messages.MakeGoodView_averageTest); processTimeAverageLabel.getParent().layout(); processTimeLabel.setText(Messages.MakeGoodView_testTime + ": " + //$NON-NLS-1$ TimeFormatter.format(testLifecycle.getProgress().getProcessTime())); passCountLabel.setCount(testLifecycle.getProgress().getPassCount()); failureCountLabel.setCount(testLifecycle.getProgress().getFailureCount()); errorCountLabel.setCount(testLifecycle.getProgress().getErrorCount()); resultTreeViewer.refresh(); } private void updateElapsedTime() { if (testLifecycle == null) return; elapsedTimeLabel.setText(Messages.MakeGoodView_realTime + ": " + //$NON-NLS-1$ TimeFormatter.format(testLifecycle.getProgress().getElapsedTime())); } private void updateTestCount() { if (testLifecycle == null) return; testCountLabel.setText(Messages.MakeGoodView_testsLabel + ": " + //$NON-NLS-1$ testLifecycle.getProgress().getCurrentTestCount() + "/" + //$NON-NLS-1$ testLifecycle.getProgress().getAllTestCount()); } private void update() { IViewSite site = super.getViewSite(); if (site == null) return; initializeActions(site); if (testLifecycle != null) { updateResult(); updateElapsedTime(); updateEndTime(); updateTestCount(); } } /** * @since 1.9.0 */ private void updateEndTime() { if (testLifecycle != null && testLifecycle.getProgress().isRunning() == false && testLifecycle.getEndTime() != null) { endTimeLabel.setText(Messages.MakeGoodView_endTime + ": " + //$NON-NLS-1$ new SimpleDateFormat("HH:mm:ss").format(testLifecycle.getEndTime()) //$NON-NLS-1$ ); } } /** * @since 2.5.0 */ private Composite createTestResultsComposite(Composite parent, int style, TestResultsLayout testResultsLayout) { if (TestResultsLayout.TAB.equals(testResultsLayout)) { return createTabTestResultsComposite(parent, style); } else if (TestResultsLayout.HORIZONTAL.equals(testResultsLayout)) { return createHorizontalTestResultsComposite(parent, style); } else { return createTabTestResultsComposite(parent, style); } } /** * @since 2.5.0 */ private Composite createTabTestResultsComposite(Composite parent, int style) { CTabFolder testResultsComposite = new TabTestResultsComposite(parent, style); testResultsComposite.setSimple(false); testResultsComposite.setLayoutData(createBothFillGridData()); testResultsComposite.setLayout(adjustLayout(new GridLayout())); return testResultsComposite; } /** * @since 2.5.0 */ private Composite createHorizontalTestResultsComposite(Composite parent, int style) { SashForm testResultsComposite = new HorizontalResultsComposite(parent, style); testResultsComposite.setLayoutData(createBothFillGridData()); testResultsComposite.setLayout(adjustLayout(new GridLayout(2, true))); return testResultsComposite; } /** * @since 2.5.0 */ private TreeViewer createTestResultsTreeViewer(Tree resultTree) { TreeViewer treeViewer = new TreeViewer(resultTree); treeViewer.setContentProvider(new ResultTreeContentProvider()); treeViewer.setLabelProvider(new ResultTreeLabelProvider()); treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { failureTrace.clearText(); if (!(event.getSelection() instanceof IStructuredSelection)) return; IStructuredSelection selection = (IStructuredSelection) event.getSelection(); Object element = selection.getFirstElement(); if (!(element instanceof TestCaseResult)) return; TestCaseResult testCase = (TestCaseResult) element; if (!testCase.isFixed()) return; if (!testCase.hasFailures() && !testCase.hasErrors()) return; failureTrace.setText(testCase.getFailureTrace()); } }); treeViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { Object element = ((IStructuredSelection) event.getSelection()).getFirstElement(); if (element == null) return; if (element instanceof Result) { try { editorOpener.open((Result) element); } catch (PartInitException e) { Activator.getDefault().getLog() .log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, e.getMessage(), e)); } } } }); return treeViewer; } /** * @since 2.5.0 */ @Override public void layoutChanged(TestResultsLayout testResultsLayout) { Composite parent = testResultsComposite.getParent(); if (!testResultsComposite.isDisposed()) { testResultsComposite.dispose(); } testResultsComposite = createTestResultsComposite(parent, SWT.NONE, testResultsLayout); testResultsComposite.getParent().layout(); testLifecycle = TestLifecycle.getInstance(); if (testLifecycle != null) { setTreeInput(testLifecycle.getProgress().getResult()); } } private class CountLabel { private CLabel label; private String text; public CountLabel(Composite parent, int style, String text, Image icon) { label = new CLabel(parent, style); label.setLayoutData(createHorizontalFillGridData()); label.setText(text); label.setImage(icon); this.text = text; } public void setCount(int count) { label.setText(text + ": " + count); //$NON-NLS-1$ } public void clear() { setCount(0); } } private class ElapsedTimer implements Runnable { private int delay; public ElapsedTimer(int delay) { this.delay = delay; } public void schedule() { elapsedTimeLabel.getDisplay().timerExec(delay, this); } @Override public void run() { if (!elapsedTimeLabel.isDisposed()) { updateElapsedTime(); schedule(); } } } private class FailureTrace extends ActiveText { public FailureTrace(Composite parent, int style) { super(parent, style); } @Override public void clearText() { super.clearText(); hideScrollBar(); } /** * @since 1.3.0 */ @Override public void setText(String text) { super.setText(text); showScrollBar(); } /** * @since 1.6.0 */ private void showScrollBar() { getVerticalBar().setVisible(true); getHorizontalBar().setVisible(true); } /** * @since 1.6.0 */ private void hideScrollBar() { getVerticalBar().setVisible(false); getHorizontalBar().setVisible(false); } /** * @since 1.6.0 */ @Override public void mouseDoubleClick(MouseEvent e) { } /** * @since 1.6.0 */ @Override public void mouseDown(MouseEvent e) { StyleRange style = findStyle(new Point(e.x, e.y)); if (style == null) return; if (!(style instanceof FileWithLineRange)) return; ((FileWithLineRange) style).openEditor(); } /** * @since 1.6.0 */ @Override public void mouseUp(MouseEvent e) { } /** * @since 1.6.0 */ @Override public void mouseMove(MouseEvent e) { StyleRange style = findStyle(new Point(e.x, e.y)); if (style == null) { setCursor(arrowCursor); return; } if (style instanceof FileWithLineRange) { setCursor(handCursor); return; } setCursor(arrowCursor); } } /** * @since 1.6.0 */ private class StatusArea extends ActiveText implements MakeGoodStatusChangeListener { private static final String UIJOB_NAME = "MakeGood Status Update"; //$NON-NLS-1$ private MakeGoodStatus status; public StatusArea(Composite parent, int style) { super(parent, style); } /** * @since 1.8.0 */ public void updateAdditionalInformation() { new UIJob(UIJOB_NAME) { @Override public IStatus runInUIThread(IProgressMonitor monitor) { if (isDisposed()) return Status.OK_STATUS; ; setContentDescription(additionalInformation.toString()); return Status.OK_STATUS; } }.schedule(); } public void isFailure(final String message) { new UIJob(UIJOB_NAME) { @Override public IStatus runInUIThread(IProgressMonitor monitor) { if (isDisposed()) return Status.OK_STATUS; ; if (actionsInitialized) { runAllTestsAction.setEnabled(false); rerunTestAction.setEnabled(false); rerunFailedTestsAction.setEnabled(false); } setForeground(new Color(statusArea.getDisplay(), MakeGoodColor.FAILED)); setText(message); return Status.OK_STATUS; } }.schedule(); } public void runningTest() { new UIJob(UIJOB_NAME) { @Override public IStatus runInUIThread(IProgressMonitor monitor) { if (isDisposed()) return Status.OK_STATUS; ; if (actionsInitialized) { runAllTestsAction.setEnabled(false); rerunTestAction.setEnabled(false); rerunFailedTestsAction.setEnabled(false); stopTestAction.setEnabled(true); moveToPreviousFailureAction.setEnabled(false); moveToNextFailureAction.setEnabled(false); } setForeground(statusArea.getParent().getForeground()); setText(Messages.MakeGoodView_Status_RunningTest); return Status.OK_STATUS; } }.schedule(); } public void waitingForTestRun() { new UIJob(UIJOB_NAME) { @Override public IStatus runInUIThread(IProgressMonitor monitor) { if (isDisposed()) return Status.OK_STATUS; ; if (actionsInitialized) { runAllTestsAction .setEnabled(MakeGoodContext.getInstance().getActivePart().isAllTestsRunnable()); rerunTestAction.setEnabled(MakeGoodContext.getInstance().getTestRunner().hasLastTest()); rerunFailedTestsAction .setEnabled(MakeGoodContext.getInstance().getTestRunner().hasLastTest()); stopTestAction.setEnabled(false); } setForeground(statusArea.getParent().getForeground()); setText(Messages.MakeGoodView_Status_WaitingForTestRun); return Status.OK_STATUS; } }.schedule(); } @Override public void statusChanged(MakeGoodStatus status) { this.status = status; if (this.status.getProject() != null) { additionalInformation.setProject(this.status.getProject()); } if (status == MakeGoodStatus.TestsNotFound) { additionalInformation.setMessage(Messages.MakeGoodView_Status_TestsNotFound); } else if (status == MakeGoodStatus.RelatedTestsNotFound) { additionalInformation.setMessage(Messages.MakeGoodView_Status_RelatedTestsNotFound); } else if (status == MakeGoodStatus.TypesNotFound) { additionalInformation.setMessage(Messages.MakeGoodView_Status_TypesNotFound); } else if (status == MakeGoodStatus.TestTargetNotFound) { additionalInformation.setMessage(Messages.MakeGoodView_Status_TestTargetNotFound); } updateAdditionalInformation(); switch (status) { case NoProjectSelected: isFailure(Messages.MakeGoodView_Status_NoProjectSelected); break; case ProjectNotFound: isFailure(Messages.MakeGoodView_Status_ProjectNotFound); break; case ProjectNotOpen: isFailure(Messages.MakeGoodView_Status_ProjectNotOpen); break; case NoTestableProjectSelected: isFailure(Messages.MakeGoodView_Status_NoTestableProjectSelected); break; case NoPHPExecutablesDefined: isFailure(Messages.MakeGoodView_Status_NoPHPExecutablesDefined); break; case SAPINotCLI: isFailure(Messages.MakeGoodView_Status_SAPINotCLI); break; case MakeGoodNotConfigured: isFailure(Messages.MakeGoodView_Status_MakeGoodNotConfigured); break; case TestingFrameworkNotAvailable: isFailure(status.getReason() + " " + Messages.MakeGoodView_Status_TestingFrameworkNotAvailable); //$NON-NLS-1$ break; case RunningTest: runningTest(); break; case WaitingForTestRun: waitingForTestRun(); break; default: break; } } @Override public void mouseDoubleClick(MouseEvent e) { } @Override public void mouseDown(MouseEvent e) { if (status == null) return; IProject project = status.getProject(); if (project == null) return; if (!project.exists()) return; StyleRange style = findStyle(new Point(e.x, e.y)); if (style == null) return; IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (window == null) return; IEclipsePreferences node = new ProjectScope(project) .getNode("org.eclipse.php.debug.core.Debug_Process_Preferences"); //$NON-NLS-1$ if (node == null) return; switch (status) { case NoPHPExecutablesDefined: case SAPINotCLI: if (!node.getBoolean("org.eclipse.php.debug.core.use-project-settings", false)) { //$NON-NLS-1$ PreferencesUtil.createPreferenceDialogOn(window.getShell(), "org.eclipse.php.debug.ui.preferences.PhpDebugPreferencePage", //$NON-NLS-1$ null, null).open(); } else { PreferencesUtil.createPropertyDialogOn(window.getShell(), project, "org.eclipse.php.debug.ui.property.PhpDebugPreferencePage", //$NON-NLS-1$ null, null).open(); } break; case MakeGoodNotConfigured: case TestingFrameworkNotAvailable: PreferencesUtil.createPropertyDialogOn(window.getShell(), project, "com.piece_framework.makegood.ui.propertyPages.makeGood", //$NON-NLS-1$ null, null).open(); break; default: break; } } @Override public void mouseUp(MouseEvent e) { } @Override public void mouseMove(MouseEvent e) { StyleRange style = findStyle(new Point(e.x, e.y)); if (style == null) { setCursor(arrowCursor); } else { setCursor(handCursor); } } } private class ResultViewPartListener implements IPartListener2 { @Override public void partActivated(IWorkbenchPartReference partRef) { if (!VIEW_ID.equals(partRef.getId())) { IWorkbenchPart activePart = partRef.getPage().getActivePart(); if (activePart != null) { MakeGoodContext.getInstance().getActivePart().update(activePart); } return; } update(); } @Override public void partBroughtToTop(IWorkbenchPartReference partRef) { } @Override public void partClosed(IWorkbenchPartReference partRef) { } @Override public void partDeactivated(IWorkbenchPartReference partRef) { } @Override public void partOpened(IWorkbenchPartReference partRef) { if (!VIEW_ID.equals(partRef.getId())) return; update(); } @Override public void partHidden(IWorkbenchPartReference partRef) { } @Override public void partVisible(IWorkbenchPartReference partRef) { if (!VIEW_ID.equals(partRef.getId())) return; update(); } @Override public void partInputChanged(IWorkbenchPartReference partRef) { } } private class ResultTreeContentProvider implements ITreeContentProvider { @Override public Object[] getChildren(Object parentElement) { List<Result> children = new ArrayList<Result>(((Result) parentElement).getChildren()); Collections.reverse(children); return children.toArray(new Result[children.size()]); } @Override public Object getParent(Object element) { return ((Result) element).getParent(); } @Override public boolean hasChildren(Object element) { if (!(element instanceof TestSuiteResult)) return false; return ((TestSuiteResult) element).hasChildren(); } @Override public Object[] getElements(Object inputElement) { return getChildren(inputElement); } @Override public void dispose() { } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } } private class ResultTreeLabelProvider extends LabelProvider { private Image passIcon; private Image errorIcon; private Image failureIcon; private Image inProgressIcon; public ResultTreeLabelProvider() { super(); passIcon = Activator.getImageDescriptor("icons/pass_white.gif").createImage(); //$NON-NLS-1$ errorIcon = Activator.getImageDescriptor("icons/error_white.gif").createImage(); //$NON-NLS-1$ failureIcon = Activator.getImageDescriptor("icons/failure_white.gif").createImage(); //$NON-NLS-1$ inProgressIcon = Activator.getImageDescriptor("icons/in_progress.gif").createImage(); //$NON-NLS-1$ } @Override public String getText(Object element) { Result result = (Result) element; return result.getName() + " (" + //$NON-NLS-1$ TimeFormatter.format(result.getTime()) + ")"; //$NON-NLS-1$ } @Override public Image getImage(Object element) { Result result = (Result) element; if (result.isFixed()) { if (result.hasFailures()) { return failureIcon; } else if (result.hasErrors()) { return errorIcon; } else { return passIcon; } } else { return inProgressIcon; } } } private static class TimeFormatter { private static String format(long nanoTime) { double timeForFormat = 0.0d; String unit = null; if (nanoTime >= 1000000000) { timeForFormat = nanoTime / 1000000000d; unit = "s"; //$NON-NLS-1$ } else if (nanoTime < 1000000000 && nanoTime >= 1000) { timeForFormat = nanoTime / 1000000d; unit = "ms"; //$NON-NLS-1$ } else if (nanoTime > 0) { return "< 0.001ms"; //$NON-NLS-1$ } else { return "0.000ms"; //$NON-NLS-1$ } return String.format("%.3f%s", timeForFormat, unit); //$NON-NLS-1$ } } private class EditorOpenActiveTextListener extends ActiveTextListener { public EditorOpenActiveTextListener() { super(Pattern.compile("^((?:/|[A-Z]:).+):(\\d+)$", Pattern.MULTILINE)); } @Override public void generateActiveText() { Matcher matcher = pattern.matcher(text.getText()); while (matcher.find()) { FileWithLineRange style; IFile file = ResourcesPlugin.getWorkspace().getRoot() .getFileForLocation(new Path(matcher.group(1))); if (file != null) { InternalFileWithLineRange iStyle = new InternalFileWithLineRange(); iStyle.file = file; iStyle.foreground = new Color(text.getDisplay(), MakeGoodColor.LINK_INTERNAL); style = (FileWithLineRange) iStyle; } else { ExternalFileWithLineRange eStyle = new ExternalFileWithLineRange(); eStyle.fileStore = EFS.getLocalFileSystem().getStore(new Path(matcher.group(1))); eStyle.foreground = new Color(text.getDisplay(), MakeGoodColor.LINK_EXTERNAL); style = (FileWithLineRange) eStyle; } style.start = matcher.start(); style.length = matcher.group().length(); style.line = Integer.valueOf(matcher.group(2)); this.text.addStyle(style); } } } /** * @since 1.6.0 */ private class PreferencesOpenActiveTextListener extends ActiveTextListener { public PreferencesOpenActiveTextListener() { super(Pattern.compile("(?:<a>)(.+?)(?:</a>)")); //$NON-NLS-1$ } @Override public void generateActiveText() { Matcher matcher = pattern.matcher(text.getText()); while (matcher.find()) { StyleRange style = new StyleRange(); style.underline = true; style.start = matcher.start(); style.length = matcher.group(1).length(); text.replaceText(matcher.replaceFirst(matcher.group(1))); text.addStyle(style); } } } /** * @since 1.8.0 */ private class AdditionalInformation { private IProject project; private String message; public void setProject(IProject project) { if (this.project != null && this.project != project) { clearMessage(); } this.project = project; } public void setMessage(String message) { this.message = message; } public void clearMessage() { setMessage(null); } @Override public String toString() { StringBuilder information = new StringBuilder(); if (project != null) { information.append("[" + project.getName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ } if (message != null && message.length() > 0) { information.append(" "); //$NON-NLS-1$ information.append(message); } return information.toString(); } } /** * @since 2.5.0 */ private class TabTestResultsComposite extends CTabFolder { private CTabItem testResultsTreeTabItem; private CTabItem failureTraceTabItem; public TabTestResultsComposite(Composite parent, int style) { super(parent, style); testResultsTreeTabItem = new CTabItem(this, SWT.NONE); testResultsTreeTabItem.setText(Messages.MakeGoodView_testResultsLabel); testResultsTreeTabItem.setImage(Activator.getImageDescriptor("icons/test_results.gif").createImage()); //$NON-NLS-1$ setSelection(testResultsTreeTabItem); Tree testResultsTree = new Tree(this, SWT.BORDER); testResultsTree.setLayoutData(createBothFillGridData()); testResultsTreeTabItem.setControl(testResultsTree); resultTreeViewer = createTestResultsTreeViewer(testResultsTree); failureTraceTabItem = new CTabItem(this, SWT.NONE); failureTraceTabItem.setText(Messages.MakeGoodView_failureTraceLabel); failureTraceTabItem.setImage(Activator.getImageDescriptor("icons/failure_trace.gif").createImage()); //$NON-NLS-1$ failureTrace = createFailureTrace(this, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); failureTraceTabItem.setControl(failureTrace); } public void switchToUnselectedTab() { if (getSelection() == testResultsTreeTabItem) { setSelection(failureTraceTabItem); } else if (getSelection() == failureTraceTabItem) { setSelection(testResultsTreeTabItem); } } } /** * @since 2.5.0 */ private class HorizontalResultsComposite extends SashForm { public HorizontalResultsComposite(Composite parent, int style) { super(parent, style); Composite testResultsTreeComposite = new Composite(this, SWT.NONE); testResultsTreeComposite.setLayoutData(createHorizontalFillGridData()); testResultsTreeComposite.setLayout(adjustLayout(new GridLayout(1, true))); Tree testResultsTree = new Tree(testResultsTreeComposite, SWT.BORDER); testResultsTree.setLayoutData(createBothFillGridData()); resultTreeViewer = createTestResultsTreeViewer(testResultsTree); testResultsTree.setLayoutData(createBothFillGridData()); Composite failureTraceComposite = new Composite(this, SWT.NONE); failureTraceComposite.setLayoutData(createHorizontalFillGridData()); failureTraceComposite.setLayout(adjustLayout(new GridLayout(1, true))); CLabel failureTraceLabel = new CLabel(failureTraceComposite, SWT.LEFT); failureTraceLabel.setText(Messages.MakeGoodView_failureTraceLabel); failureTraceLabel.setImage(Activator.getImageDescriptor("icons/failure_trace.gif").createImage()); //$NON-NLS-1$ failureTrace = createFailureTrace(failureTraceComposite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); } } }