/******************************************************************************* * 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 java.util.concurrent.CountDownLatch; 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.IGesture; import org.eclipse.gef.mvc.fx.gestures.TypeGesture; 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.application.Platform; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.SnapshotResult; import javafx.scene.input.KeyCode; import javafx.util.Callback; public class TypeGestureTests { private static class FXDomainDriver extends HistoricizingDomain { protected int openedExecutionTransactions = 0; protected int closedExecutionTransactions = 0; @Override public void closeExecutionTransaction(IGesture tool) { if (tool instanceof TypeGesture) { closedExecutionTransactions++; } super.closeExecutionTransaction(tool); } @Override public void openExecutionTransaction(IGesture tool) { super.openExecutionTransaction(tool); if (tool instanceof TypeGesture) { openedExecutionTransactions++; } }; } /** * Ensure that 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 press/drag interaction gesture, because * otherwise the transactional results of the gesture could not be undone. * * @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() { 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); } }); // repaint ctx.getPanel().repaint(); ctx.waitForIdle(); final CountDownLatch latch = new CountDownLatch(1); Platform.runLater(new Runnable() { @Override public void run() { scene.getRoot().snapshot(new Callback<SnapshotResult, Void>() { @Override public Void call(SnapshotResult param) { latch.countDown(); return null; } }, null, null); } }); latch.await(); ctx.getPanel().repaint(); ctx.waitForIdle(); // 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); // click into the viewer to gain keyboard focus ctx.mousePress(); ctx.mouseRelease(); // simulate press/release gesture ctx.keyPress(scene.getRoot(), KeyCode.K); 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.keyRelease(); 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); } }); } }