blob: a1090bbea78bd03edf6c43cfffea6a6160748ce9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2014 Xored Software Inc 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:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.verifications.text.impl;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.reconciler.AbstractReconciler;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.rcptt.core.VerificationProcessor;
import org.eclipse.rcptt.core.scenario.Verification;
import org.eclipse.rcptt.ecl.runtime.IProcess;
import org.eclipse.rcptt.tesla.core.ui.StyleRangeEntry;
import org.eclipse.rcptt.tesla.core.ui.TextPosition;
import org.eclipse.rcptt.tesla.ecl.impl.TeslaBridge;
import org.eclipse.rcptt.tesla.internal.ui.player.PlayerTextUtils;
import org.eclipse.rcptt.tesla.internal.ui.player.SWTUIElement;
import org.eclipse.rcptt.tesla.internal.ui.player.TeslaSWTAccess;
import org.eclipse.rcptt.tesla.recording.aspects.jface.text.JFaceTextEventManager;
import org.eclipse.rcptt.verifications.runtime.ErrorList;
import org.eclipse.rcptt.verifications.text.TextFactory;
import org.eclipse.rcptt.verifications.text.TextVerification;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Widget;
public class TextVerificationProcessor extends VerificationProcessor {
@Override
public void finish(Verification verification, Object data, IProcess process) throws CoreException {
final TextVerification textVerification = (TextVerification)
verification;
final SWTUIElement swtuiElement =
TeslaBridge.resolveSWTUIElement(textVerification.getSelector(), process);
final Widget widget = swtuiElement.widget;
final ErrorList errors = new ErrorList();
widget.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
String expectedText = textVerification.getText();
if (expectedText == null)
expectedText = "";
if (widget instanceof StyledText)
unfold((StyledText) widget);
String actualText = PlayerTextUtils.getTextForVerification(swtuiElement);
if (actualText == null)
actualText = "";
if (!actualText.equals(expectedText)) {
errors.add("Expected text is \"%s\", but it was \"%s\".",
expectedText, actualText);
}
EList<StyleRangeEntry> expectedStyleEntries = textVerification.getStyles();
if (expectedStyleEntries.size() > 0 && !textVerification.isIgnoreStyling()) {
if (!(widget instanceof StyledText))
errors.add("Expected StyledText widget, got %s.",
widget.getClass().getName());
else {
StyledText styledText = (StyledText) widget;
List<StyleRangeEntry> actualStyleEntries = PlayerTextUtils.captureStyleRanges(styledText);
PlayerTextUtils.squashRanges(actualStyleEntries);
boolean failed = false;
for (int i = 0; i < Math.min(expectedStyleEntries.size(), actualStyleEntries.size()); ++i) {
StyleRangeEntry expected = expectedStyleEntries.get(i);
StyleRangeEntry actual = actualStyleEntries.get(i);
if (!EcoreUtil.equals(expected, actual)) {
errors.add(
"Difference in text styling found at %s.",
posToString(earliestPos(expected.getStartPos(), actual.getStartPos())));
failed = true;
break;
}
}
if (!failed && expectedStyleEntries.size() != actualStyleEntries.size()) {
if (actualStyleEntries.size() > expectedStyleEntries.size())
// actual text contains more style ranges
errors.add("Difference in text styling found at %s.",
posToString(actualStyleEntries.get(expectedStyleEntries.size()).getStartPos()));
else
// expected text contains more style ranges
errors.add(
"Difference in text styling found at %s.",
posToString(actualStyleEntries.get(actualStyleEntries.size() - 1).getStartPos()));
}
}
}
}
});
errors.throwIfAny(String.format("Widget text verification '%s' failed:", verification.getName()),
this.getClass().getPackage().getName(), verification.getId());
}
@Override
public Verification create(EObject param, IProcess process) throws CoreException {
final TextVerification p = (TextVerification) param;
final SWTUIElement swtuiElement =
TeslaBridge.resolveSWTUIElement(p.getSelector(), process);
final Widget widget = swtuiElement.widget;
final TextVerification result = TextFactory.eINSTANCE.createTextVerification();
widget.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
result.setSelector(p.getSelector());
result.setText(PlayerTextUtils.getTextForVerification(swtuiElement));
if (widget instanceof StyledText) {
StyledText styledText = (StyledText) widget;
if (unfold(styledText))
result.setText(PlayerTextUtils.getTextForVerification(swtuiElement));
List<StyleRangeEntry> captured = PlayerTextUtils.captureStyleRanges(styledText);
PlayerTextUtils.squashRanges(captured);
result.getStyles().addAll(captured);
result.setIgnoreStyling(result.getStyles().size() > 0 ? p.isIgnoreStyling() : true);
} else
result.setIgnoreStyling(true);
}
});
return result;
}
private static boolean unfold(StyledText styledText) {
TextViewer viewer = JFaceTextEventManager.getViewer(styledText);
if (viewer != null && viewer instanceof SourceViewer) {
viewer.doOperation(ProjectionViewer.EXPAND_ALL);
AbstractReconciler reconciler =
TeslaSWTAccess.getField(AbstractReconciler.class,
viewer, "fReconciler");
if (reconciler != null) {
TeslaSWTAccess.call(reconciler, "forceReconciling");
Object thread = TeslaSWTAccess.getField(Object.class,
reconciler, "fThread");
if (thread != null)
TeslaSWTAccess.call(thread, "suspendCallerWhileDirty");
}
return true;
}
return false;
}
private static TextPosition earliestPos(TextPosition a, TextPosition b) {
if (a.getLine() < b.getLine())
return a;
else if (a.getLine() > b.getLine())
return b;
else if (a.getColumn() < b.getColumn())
return a;
else
return b;
}
private static String posToString(TextPosition p) {
return String.format("line %s column %s", p.getLine(), p.getColumn());
}
}