/******************************************************************************* * Copyright (c) 2015, 2016 itemis AG 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: * Alexander Nyßen (itemis AG) - initial API and implementation * *******************************************************************************/ package org.eclipse.gef.mvc.tests.fx; import static org.junit.Assert.assertEquals; import java.awt.Point; import java.util.Map; import org.eclipse.core.commands.operations.IOperationHistory; import org.eclipse.gef.common.adapt.AdapterKey; import org.eclipse.gef.mvc.fx.MvcFxModule; import org.eclipse.gef.mvc.fx.domain.HistoricizingDomain; import org.eclipse.gef.mvc.fx.domain.IDomain; import org.eclipse.gef.mvc.fx.gestures.ClickDragGesture; import org.eclipse.gef.mvc.fx.gestures.IGesture; import org.eclipse.gef.mvc.fx.parts.IContentPart; import org.eclipse.gef.mvc.fx.parts.IContentPartFactory; import org.eclipse.gef.mvc.fx.viewer.IViewer; import org.eclipse.gef.mvc.tests.fx.rules.FXNonApplicationThreadRule; import org.eclipse.gef.mvc.tests.fx.rules.FXNonApplicationThreadRule.RunnableWithResult; import org.junit.Rule; import org.junit.Test; import com.google.inject.Guice; import com.google.inject.Injector; import javafx.scene.Node; import javafx.scene.Scene; public class ClickDragGestureTests { private static class FXDomainDriver extends HistoricizingDomain { protected int openedExecutionTransactions = 0; protected int closedExecutionTransactions = 0; @Override public void closeExecutionTransaction(IGesture tool) { if (tool instanceof ClickDragGesture) { closedExecutionTransactions++; } super.closeExecutionTransaction(tool); } @Override public void openExecutionTransaction(IGesture tool) { super.openExecutionTransaction(tool); if (tool instanceof ClickDragGesture) { openedExecutionTransactions++; } } } /** * Ensure all tests are executed on the JavaFX application thread (and the * JavaFX toolkit is properly initialized). */ @Rule public FXNonApplicationThreadRule ctx = new FXNonApplicationThreadRule(); /** * It is important that a single execution transaction (see * {@link IDomain#openExecutionTransaction(org.eclipse.gef.mvc.fx.gestures.IGesture)} * ) is used for a complete click/drag interaction gesture, because * otherwise the transactional results of the gesture could not be undone in * a single step, as it would result in more than one operation within the * domain's {@link IOperationHistory}. * * @throws Throwable */ @Test public void singleExecutionTransactionUsedForInteraction() throws Throwable { // create injector (adjust module bindings for test) Injector injector = Guice.createInjector(new MvcFxModule() { protected void bindIContentPartFactory() { binder().bind(IContentPartFactory.class).toInstance(new IContentPartFactory() { @Override public IContentPart<? extends Node> createContentPart(Object content, Map<Object, Object> contextMap) { return null; } }); } @Override protected void bindIDomain() { // stub the domain to be able to keep track of opened execution // transactions binder().bind(IDomain.class).to(FXDomainDriver.class); } @Override protected void configure() { super.configure(); bindIContentPartFactory(); } }); // inject domain final FXDomainDriver domain = injector.getInstance(FXDomainDriver.class); final IViewer viewer = domain.getAdapter(AdapterKey.get(IViewer.class, IDomain.CONTENT_VIEWER_ROLE)); final Scene scene = ctx.createScene(viewer.getCanvas(), 100, 100); // activate domain, so tool gets activated and can register listeners ctx.runAndWait(new Runnable() { @Override public void run() { domain.activate(); assertEquals("No execution transaction should have been opened", 0, domain.openedExecutionTransactions); assertEquals("No execution transaction should have been closed", 0, domain.closedExecutionTransactions); } }); // move mouse to viewer center Point sceneCenter = ctx.runAndWait(new RunnableWithResult<Point>() { @Override public Point run() { // XXX: It seems to be important to compute the position from // within the JavaFX application thread. return new Point((int) (scene.getX() + scene.getWidth() / 2), (int) (scene.getY() + scene.getHeight() / 2)); } }); ctx.mouseMove(scene.getRoot(), sceneCenter.x, sceneCenter.y); // simulate click gesture ctx.mousePress(); ctx.runAndWait(new Runnable() { @Override public void run() { assertEquals("A single execution transaction should have been opened", 1, domain.openedExecutionTransactions); assertEquals("No execution transaction should have been closed", 0, domain.closedExecutionTransactions); } }); ctx.mouseRelease(); ctx.runAndWait(new Runnable() { @Override public void run() { assertEquals("A single execution transaction should have been opened", 1, domain.openedExecutionTransactions); assertEquals("A single execution transaction should have been closed", 1, domain.closedExecutionTransactions); } }); // re-initialize ctx.runAndWait(new Runnable() { @Override public void run() { domain.openedExecutionTransactions = 0; domain.closedExecutionTransactions = 0; assertEquals("No execution transaction should have been opened", 0, domain.openedExecutionTransactions); assertEquals("No execution transaction should have been closed", 0, domain.closedExecutionTransactions); } }); // simulate click/drag ctx.mousePress(); ctx.runAndWait(new Runnable() { @Override public void run() { assertEquals("A single execution transaction should have been opened", 1, domain.openedExecutionTransactions); assertEquals("No execution transaction should have been closed", 0, domain.closedExecutionTransactions); } }); ctx.mouseDrag(20, 20); ctx.runAndWait(new Runnable() { @Override public void run() { assertEquals("A single execution transaction should have been opened", 1, domain.openedExecutionTransactions); assertEquals("No execution transaction should have been closed", 0, domain.closedExecutionTransactions); } }); ctx.mouseRelease(); ctx.runAndWait(new Runnable() { @Override public void run() { assertEquals("A single execution transaction should have been opened", 1, domain.openedExecutionTransactions); assertEquals("A single execution transaction should have been closed", 1, domain.closedExecutionTransactions); } }); } }