| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * 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 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.testing.ui; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.InputStream; |
| import java.nio.charset.StandardCharsets; |
| |
| import org.eclipse.compare.CompareConfiguration; |
| import org.eclipse.compare.CompareViewerPane; |
| import org.eclipse.compare.IEncodedStreamContentAccessor; |
| import org.eclipse.compare.ITypedElement; |
| import org.eclipse.compare.contentmergeviewer.TextMergeViewer; |
| import org.eclipse.compare.structuremergeviewer.DiffNode; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.dltk.internal.testing.model.TestElement; |
| import org.eclipse.dltk.testing.DLTKTestingMessages; |
| import org.eclipse.dltk.testing.DLTKTestingPlugin; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.dialogs.TrayDialog; |
| import org.eclipse.jface.text.DocumentEvent; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.ITypedRegion; |
| import org.eclipse.jface.text.Region; |
| import org.eclipse.jface.text.TextAttribute; |
| import org.eclipse.jface.text.TextPresentation; |
| import org.eclipse.jface.text.TextViewer; |
| import org.eclipse.jface.text.presentation.IPresentationDamager; |
| import org.eclipse.jface.text.presentation.IPresentationReconciler; |
| import org.eclipse.jface.text.presentation.IPresentationRepairer; |
| import org.eclipse.jface.text.presentation.PresentationReconciler; |
| import org.eclipse.jface.text.source.ISourceViewer; |
| import org.eclipse.jface.text.source.SourceViewer; |
| import org.eclipse.jface.text.source.SourceViewerConfiguration; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.StyleRange; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.PlatformUI; |
| |
| public class CompareResultDialog extends TrayDialog { |
| private static final String PREFIX_SUFFIX_PROPERTY = "org.eclipse.jdt.internal.junit.ui.CompareResultDialog.prefixSuffix"; //$NON-NLS-1$ |
| |
| private static class CompareResultMergeViewer extends TextMergeViewer { |
| private CompareResultMergeViewer(Composite parent, int style, |
| CompareConfiguration configuration) { |
| super(parent, style, configuration); |
| } |
| |
| @Override |
| protected void createControls(Composite composite) { |
| super.createControls(composite); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, |
| IDLTKTestingHelpContextIds.RESULT_COMPARE_DIALOG); |
| } |
| |
| // protected void createToolItems(ToolBarManager tbm) { |
| // ResourceBundle bundle= CompareUI.getResourceBundle(); |
| // tbm.add(new IgnoreWhiteSpaceAction(bundle, |
| // getCompareConfiguration())); |
| // super.createToolItems(tbm); |
| // } |
| |
| @Override |
| protected void configureTextViewer(TextViewer textViewer) { |
| if (textViewer instanceof SourceViewer) { |
| int[] prefixSuffixOffsets = (int[]) getCompareConfiguration() |
| .getProperty(PREFIX_SUFFIX_PROPERTY); |
| ((SourceViewer) textViewer) |
| .configure(new CompareResultViewerConfiguration( |
| prefixSuffixOffsets)); |
| } |
| } |
| } |
| |
| private static class CompareResultViewerConfiguration |
| extends SourceViewerConfiguration { |
| private static class SimpleDamagerRepairer |
| implements IPresentationDamager, IPresentationRepairer { |
| private IDocument fDocument; |
| private final int[] fPrefixSuffixOffsets2; |
| |
| public SimpleDamagerRepairer(int[] prefixSuffixOffsets) { |
| fPrefixSuffixOffsets2 = prefixSuffixOffsets; |
| } |
| |
| @Override |
| public void setDocument(IDocument document) { |
| fDocument = document; |
| } |
| |
| @Override |
| public IRegion getDamageRegion(ITypedRegion partition, |
| DocumentEvent event, boolean changed) { |
| return new Region(0, fDocument.getLength()); |
| } |
| |
| @Override |
| public void createPresentation(TextPresentation presentation, |
| ITypedRegion damage) { |
| int prefix = fPrefixSuffixOffsets2[0]; |
| int suffix = fPrefixSuffixOffsets2[1]; |
| TextAttribute attr = new TextAttribute( |
| Display.getDefault().getSystemColor(SWT.COLOR_RED), |
| null, SWT.BOLD); |
| presentation.addStyleRange(new StyleRange(prefix, |
| fDocument.getLength() - suffix - prefix, |
| attr.getForeground(), attr.getBackground(), |
| attr.getStyle())); |
| } |
| } |
| |
| private final int[] fPrefixSuffixOffsets; |
| |
| public CompareResultViewerConfiguration(int[] prefixSuffixOffsets) { |
| fPrefixSuffixOffsets = prefixSuffixOffsets; |
| } |
| |
| @Override |
| public IPresentationReconciler getPresentationReconciler( |
| ISourceViewer sourceViewer) { |
| PresentationReconciler reconciler = new PresentationReconciler(); |
| SimpleDamagerRepairer dr = new SimpleDamagerRepairer( |
| fPrefixSuffixOffsets); |
| reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); |
| reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); |
| return reconciler; |
| } |
| } |
| |
| private static class CompareElement |
| implements ITypedElement, IEncodedStreamContentAccessor { |
| private String fContent; |
| |
| public CompareElement(String content) { |
| fContent = content; |
| } |
| |
| @Override |
| public String getName() { |
| return "<no name>"; //$NON-NLS-1$ |
| } |
| |
| @Override |
| public Image getImage() { |
| return null; |
| } |
| |
| @Override |
| public String getType() { |
| return "txt"; //$NON-NLS-1$ |
| } |
| |
| @Override |
| public InputStream getContents() { |
| return new ByteArrayInputStream( |
| fContent.getBytes(StandardCharsets.UTF_8)); |
| } |
| |
| @Override |
| public String getCharset() throws CoreException { |
| return "UTF-8"; //$NON-NLS-1$ |
| } |
| } |
| |
| private TextMergeViewer fViewer; |
| private String fExpected; |
| private String fActual; |
| private String fTestName; |
| |
| /** |
| * Lengths of common prefix and suffix. Note: this array is passed to the |
| * DamagerRepairer and the lengths are updated on content change. |
| */ |
| private final int[] fPrefixSuffix = new int[2]; |
| |
| public CompareResultDialog(Shell parentShell, TestElement element) { |
| super(parentShell); |
| setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX); |
| setFailedTest(element); |
| } |
| |
| private void setFailedTest(TestElement failedTest) { |
| fTestName = failedTest.getTestName(); |
| fExpected = failedTest.getExpected(); |
| fActual = failedTest.getActual(); |
| computePrefixSuffix(); |
| } |
| |
| @Override |
| protected IDialogSettings getDialogBoundsSettings() { |
| return DLTKTestingPlugin.getDefault() |
| .getDialogSettingsSection(getClass().getName()); |
| } |
| |
| private void computePrefixSuffix() { |
| int end = Math.min(fExpected.length(), fActual.length()); |
| int i = 0; |
| for (; i < end; i++) |
| if (fExpected.charAt(i) != fActual.charAt(i)) |
| break; |
| fPrefixSuffix[0] = i; |
| |
| int j = fExpected.length() - 1; |
| int k = fActual.length() - 1; |
| int l = 0; |
| for (; k >= i && j >= i; k--, j--) { |
| if (fExpected.charAt(j) != fActual.charAt(k)) |
| break; |
| l++; |
| } |
| fPrefixSuffix[1] = l; |
| } |
| |
| @Override |
| protected void configureShell(Shell newShell) { |
| super.configureShell(newShell); |
| newShell.setText(DLTKTestingMessages.CompareResultDialog_title); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, |
| IDLTKTestingHelpContextIds.RESULT_COMPARE_DIALOG); |
| } |
| |
| @Override |
| protected void createButtonsForButtonBar(Composite parent) { |
| createButton(parent, IDialogConstants.OK_ID, |
| DLTKTestingMessages.CompareResultDialog_labelOK, true); |
| } |
| |
| @Override |
| protected Control createDialogArea(Composite parent) { |
| Composite composite = (Composite) super.createDialogArea(parent); |
| GridLayout layout = new GridLayout(); |
| layout.numColumns = 1; |
| composite.setLayout(layout); |
| |
| CompareViewerPane pane = new CompareViewerPane(composite, |
| SWT.BORDER | SWT.FLAT); |
| pane.setText(fTestName); |
| GridData data = new GridData( |
| GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL); |
| data.widthHint = convertWidthInCharsToPixels(120); |
| data.heightHint = convertHeightInCharsToPixels(13); |
| pane.setLayoutData(data); |
| |
| Control previewer = createPreviewer(pane); |
| pane.setContent(previewer); |
| GridData gd = new GridData(GridData.FILL_BOTH); |
| previewer.setLayoutData(gd); |
| applyDialogFont(parent); |
| return composite; |
| } |
| |
| private Control createPreviewer(Composite parent) { |
| final CompareConfiguration compareConfiguration = new CompareConfiguration(); |
| compareConfiguration.setLeftLabel( |
| DLTKTestingMessages.CompareResultDialog_expectedLabel); |
| compareConfiguration.setLeftEditable(false); |
| compareConfiguration.setRightLabel( |
| DLTKTestingMessages.CompareResultDialog_actualLabel); |
| compareConfiguration.setRightEditable(false); |
| compareConfiguration.setProperty(CompareConfiguration.IGNORE_WHITESPACE, |
| Boolean.FALSE); |
| compareConfiguration.setProperty(PREFIX_SUFFIX_PROPERTY, fPrefixSuffix); |
| |
| fViewer = new CompareResultMergeViewer(parent, SWT.NONE, |
| compareConfiguration); |
| setCompareViewerInput(); |
| |
| Control control = fViewer.getControl(); |
| control.addDisposeListener(e -> compareConfiguration.dispose()); |
| return control; |
| } |
| |
| private void setCompareViewerInput() { |
| if (!fViewer.getControl().isDisposed()) |
| fViewer.setInput(new DiffNode(new CompareElement(fExpected), |
| new CompareElement(fActual))); |
| } |
| |
| public void setInput(TestElement failedTest) { |
| setFailedTest(failedTest); |
| setCompareViewerInput(); |
| } |
| } |