/*******************************************************************************
* 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 implementation
*
*******************************************************************************/
package org.eclipse.gef.mvc.tests.fx;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.gef.mvc.fx.models.SelectionModel;
import org.eclipse.gef.mvc.fx.parts.AbstractContentPart;
import org.eclipse.gef.mvc.fx.parts.IContentPart;
import org.junit.Assert;
import org.junit.Test;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Node;
/**
* Tests proper behavior of the {@link SelectionModel}.
*
* @author anyssen
*
*/
public class SelectionModelTests {
private class ContentPartStub extends AbstractContentPart<Node> {
@Override
protected Node doCreateVisual() {
return null;
}
@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) {
}
}
private class ListChangeExpector<E> implements ListChangeListener<E> {
private ObservableList<? extends E> source;
private LinkedList<List<E>> removedValuesQueue = new LinkedList<>();
private LinkedList<List<E>> addedValuesQueue = new LinkedList<>();
public ListChangeExpector(ObservableList<? extends E> source) {
this.source = source;
}
public void addExpectation(List<E> removedValues, List<E> addedValues) {
// We check that the reference to the observable value is correct,
// thus do not copy the passed in values.
removedValuesQueue.addFirst(removedValues);
addedValuesQueue.addFirst(addedValues);
}
public void check() {
if (removedValuesQueue.size() > 0) {
fail("Did not receive " + removedValuesQueue.size() + " expected changes.");
}
}
@Override
public void onChanged(javafx.collections.ListChangeListener.Change<? extends E> c) {
if (removedValuesQueue.size() <= 0) {
fail("Received unexpected change.");
}
while (c.next()) {
assertEquals(source, c.getList());
assertEquals(removedValuesQueue.pollLast(), c.getRemoved());
assertEquals(addedValuesQueue.pollLast(), c.getAddedSubList());
}
}
}
@Test
public void testAppend() {
SelectionModel selectionModel = new SelectionModel();
IContentPart<Node> c1 = new ContentPartStub();
IContentPart<Node> c2 = new ContentPartStub();
IContentPart<Node> c3 = new ContentPartStub();
selectionModel.appendToSelection(c3);
Assert.assertEquals(Arrays.asList(c3), selectionModel.getSelectionUnmodifiable());
selectionModel.appendToSelection(c2);
Assert.assertEquals(Arrays.asList(c3, c2), selectionModel.getSelectionUnmodifiable());
selectionModel.appendToSelection(c1);
Assert.assertEquals(Arrays.asList(c3, c2, c1), selectionModel.getSelectionUnmodifiable());
selectionModel.appendToSelection(c3);
Assert.assertEquals(Arrays.asList(c2, c1, c3), selectionModel.getSelectionUnmodifiable());
selectionModel.appendToSelection(c2);
Assert.assertEquals(Arrays.asList(c1, c3, c2), selectionModel.getSelectionUnmodifiable());
selectionModel.appendToSelection(Arrays.asList(c1, c2));
Assert.assertEquals(Arrays.asList(c3, c1, c2), selectionModel.getSelectionUnmodifiable());
try {
selectionModel.appendToSelection(Arrays.asList(c1, c2, c1));
Assert.fail();
} catch (IllegalArgumentException e) {
// expect that an IllegalArgumentException is thrown if a selection
// list contains duplicates
}
}
@Test
public void testChangeEvents() {
SelectionModel selectionModel = new SelectionModel();
IContentPart<Node> c1 = new ContentPartStub();
IContentPart<Node> c2 = new ContentPartStub();
IContentPart<Node> c3 = new ContentPartStub();
ListChangeExpector<IContentPart<? extends Node>> listener = new ListChangeExpector<>(
selectionModel.getSelectionUnmodifiable());
selectionModel.getSelectionUnmodifiable().addListener(listener);
// no change on empty selection
selectionModel.clearSelection();
listener.check();
// ensure multi select raises a single event only
listener.addExpectation(Collections.<IContentPart<? extends Node>>emptyList(), Arrays.asList(c1, c2, c3));
selectionModel.setSelection(Arrays.asList(c1, c2, c3));
listener.check();
// no event if selection did not change
selectionModel.setSelection(Arrays.asList(c1, c2, c3));
listener.check();
listener.addExpectation(Arrays.asList(c1, c2, c3), Collections.<IContentPart<? extends Node>>emptyList());
selectionModel.clearSelection();
listener.check();
// ensure multi append raises a single event only
listener.addExpectation(Collections.<IContentPart<? extends Node>>emptyList(), Arrays.asList(c1, c2, c3));
selectionModel.appendToSelection(Arrays.asList(c1, c2, c3));
listener.check();
// no notification if append is without effect
selectionModel.appendToSelection(Arrays.asList(c1, c2, c3));
listener.check();
listener.addExpectation(Arrays.asList(c1, c2, c3), Collections.<IContentPart<? extends Node>>emptyList());
selectionModel.clearSelection();
listener.check();
// ensure multi prepend raises a single event only
listener.addExpectation(Collections.<IContentPart<? extends Node>>emptyList(), Arrays.asList(c1, c2, c3));
selectionModel.prependToSelection(Arrays.asList(c1, c2, c3));
listener.check();
// no change if prepend is without effect
selectionModel.prependToSelection(Arrays.asList(c1, c2, c3));
listener.check();
listener.addExpectation(Collections.<IContentPart<? extends Node>>singletonList(c2),
Collections.<IContentPart<? extends Node>>emptyList());
selectionModel.removeFromSelection(c2);
listener.check();
// no change if remove is without effect
selectionModel.removeFromSelection(c2);
listener.check();
// ensure listener is properly de-registered
selectionModel.getSelectionUnmodifiable().removeListener(listener);
selectionModel.removeFromSelection(c3);
listener.check();
}
@Test
public void testDeselect() {
SelectionModel selectionModel = new SelectionModel();
IContentPart<Node> c1 = new ContentPartStub();
IContentPart<Node> c2 = new ContentPartStub();
IContentPart<Node> c3 = new ContentPartStub();
selectionModel.setSelection(Arrays.asList(c1, c2, c3));
Assert.assertEquals(Arrays.asList(c1, c2, c3), selectionModel.getSelectionUnmodifiable());
selectionModel.removeFromSelection(c2);
Assert.assertEquals(Arrays.asList(c1, c3), selectionModel.getSelectionUnmodifiable());
selectionModel.removeFromSelection(c3);
Assert.assertEquals(Arrays.asList(c1), selectionModel.getSelectionUnmodifiable());
// deselect c3 again; the selection of c1 should be preserved
selectionModel.removeFromSelection(c3);
Assert.assertEquals(Arrays.asList(c1), selectionModel.getSelectionUnmodifiable());
selectionModel.removeFromSelection(c1);
Assert.assertEquals(Collections.emptyList(), selectionModel.getSelectionUnmodifiable());
}
@Test
public void testDeselectAll() {
SelectionModel selectionModel = new SelectionModel();
IContentPart<Node> c1 = new ContentPartStub();
IContentPart<Node> c2 = new ContentPartStub();
IContentPart<Node> c3 = new ContentPartStub();
selectionModel.setSelection(Arrays.asList(c1, c2, c3));
selectionModel.clearSelection();
Assert.assertEquals(Collections.emptyList(), selectionModel.getSelectionUnmodifiable());
}
@Test
public void testPrepend() {
SelectionModel selectionModel = new SelectionModel();
IContentPart<Node> c1 = new ContentPartStub();
IContentPart<Node> c2 = new ContentPartStub();
IContentPart<Node> c3 = new ContentPartStub();
selectionModel.prependToSelection(c3);
Assert.assertEquals(Arrays.asList(c3), selectionModel.getSelectionUnmodifiable());
selectionModel.prependToSelection(c2);
Assert.assertEquals(Arrays.asList(c2, c3), selectionModel.getSelectionUnmodifiable());
selectionModel.prependToSelection(c1);
Assert.assertEquals(Arrays.asList(c1, c2, c3), selectionModel.getSelectionUnmodifiable());
selectionModel.prependToSelection(c3);
Assert.assertEquals(Arrays.asList(c3, c1, c2), selectionModel.getSelectionUnmodifiable());
selectionModel.prependToSelection(c2);
Assert.assertEquals(Arrays.asList(c2, c3, c1), selectionModel.getSelectionUnmodifiable());
selectionModel.prependToSelection(Arrays.asList(c1, c2));
Assert.assertEquals(Arrays.asList(c1, c2, c3), selectionModel.getSelectionUnmodifiable());
try {
selectionModel.prependToSelection(Arrays.asList(c1, c2, c1));
Assert.fail();
} catch (IllegalArgumentException e) {
// expect that an IllegalArgumentException is thrown if a selection
// list contains duplicates
}
}
@Test
public void testSelect() {
SelectionModel selectionModel = new SelectionModel();
IContentPart<Node> c1 = new ContentPartStub();
IContentPart<Node> c2 = new ContentPartStub();
IContentPart<Node> c3 = new ContentPartStub();
selectionModel.setSelection(Arrays.asList(c1, c2));
Assert.assertEquals(Arrays.asList(c1, c2), selectionModel.getSelectionUnmodifiable());
Assert.assertTrue(selectionModel.isSelected(c1));
Assert.assertTrue(selectionModel.isSelected(c2));
selectionModel.setSelection(c3);
Assert.assertEquals(Arrays.asList(c3), selectionModel.getSelectionUnmodifiable());
Assert.assertTrue(selectionModel.isSelected(c3));
try {
selectionModel.setSelection(Arrays.asList(c1, c2, c1));
Assert.fail();
} catch (IllegalArgumentException e) {
// expect that an IllegalArgumentException is thrown if a selection
// list contains duplicates
}
}
}