/******************************************************************************* * Copyright (c) 2014, 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 static org.junit.Assert.assertNull; import java.util.Collections; import java.util.List; import java.util.Map; import org.eclipse.gef.common.reflect.ReflectionUtils; import org.eclipse.gef.fx.listeners.VisualChangeListener; import org.eclipse.gef.mvc.fx.parts.AbstractContentPart; import org.eclipse.gef.mvc.fx.parts.AbstractHandlePart; import org.eclipse.gef.mvc.fx.parts.IVisualPart; import org.eclipse.gef.mvc.fx.parts.LayeredRootPart; import org.eclipse.gef.mvc.tests.fx.rules.FXNonApplicationThreadRule; import org.junit.Rule; import org.junit.Test; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; import javafx.scene.Group; import javafx.scene.Node; /** * Tests for {@link AbstractHandlePart}. * * @author anyssen * */ public class AbstractHandlePartTests { /** * Ensure the JavaFX toolkit is properly initialized. */ @Rule public FXNonApplicationThreadRule ctx = new FXNonApplicationThreadRule(); // TODO: use injection private LayeredRootPart rp = new LayeredRootPart() { @Override protected void doAddChildVisual(IVisualPart<? extends Node> child, int index) { getVisual().getChildren().add(index, child.getVisual()); } @Override protected Group doCreateVisual() { return new Group(); } @Override public void doRefreshVisual(Group visual) { // nothing to do }; @Override protected void doRemoveChildVisual(IVisualPart<? extends Node> child, int index) { getVisual().getChildren().remove(index); }; }; private AbstractContentPart<Node> cp = new AbstractContentPart<Node>() { @Override protected Node doCreateVisual() { return new Group(); } @Override protected SetMultimap<? extends Object, String> doGetContentAnchorages() { return HashMultimap.create(); } @Override protected List<? extends Object> doGetContentChildren() { return Collections.emptyList(); } @Override protected void doRefreshVisual(Node visual) { // nothing to do } }; private AbstractHandlePart<Node> hp = new AbstractHandlePart<Node>() { @Override protected Node doCreateVisual() { return new Group(); } @Override protected void doRefreshVisual(Node visual) { // nothing to do } }; protected Map<IVisualPart<? extends Node>, Integer> getAnchorageLinkCount(AbstractHandlePart<Node> hp) { return ReflectionUtils.getPrivateFieldValue(hp, "anchorageLinkCount"); } protected Map<IVisualPart<? extends Node>, VisualChangeListener> getVisualChangeListeners( AbstractHandlePart<Node> hp) { return ReflectionUtils.getPrivateFieldValue(hp, "visualChangeListeners"); } /** * Tests that an {@link AbstractHandlePart} only registers a single * {@link VisualChangeListener} per anchorage (even if there are several * anchorage links with different roles), and that this listener is not * removed before all links are removed again. */ @Test public void testProperRegistrationOfVisualChangeListeners() { // ensure the visual of both parts have a common ancestor (the // root part // visual) rp.addChild(cp); rp.addChild(hp); assertNull(getAnchorageLinkCount(hp).get(cp)); assertEquals(0, getVisualChangeListeners(hp).size()); // check we have a single visual change listener after anchoring // the handle part hp.attachToAnchorage(cp, "r1"); assertEquals(1, getAnchorageLinkCount(hp).get(cp).intValue()); assertEquals(1, getVisualChangeListeners(hp).size()); // check we still have only a single change listener after // anchoring the // same handle part with a different role hp.attachToAnchorage(cp, "r2"); assertEquals(2, getAnchorageLinkCount(hp).get(cp).intValue()); assertEquals(1, getVisualChangeListeners(hp).size()); // check we still have a visual change listener, even if one // anchorage // is removed hp.detachFromAnchorage(cp, "r2"); assertEquals(1, getAnchorageLinkCount(hp).get(cp).intValue()); assertEquals(1, getVisualChangeListeners(hp).size()); // ensure no visual change listener is registered any more hp.detachFromAnchorage(cp, "r1"); assertNull(getAnchorageLinkCount(hp).get(cp)); assertEquals(0, getVisualChangeListeners(hp).size()); // re-attach and assure the map is intialized again hp.attachToAnchorage(cp, "r1"); assertEquals(1, getAnchorageLinkCount(hp).get(cp).intValue()); assertEquals(1, getVisualChangeListeners(hp).size()); } }