blob: 269e6bc9ec189867a478acf910c1dbba359360ef [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 RCP Vision (http://www.rcp-vision.com) 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:
* Lorenzo Bettini - Initial contribution and API
*******************************************************************************/
package org.eclipse.emf.parsley.tests
import com.google.inject.MembersInjector
import javax.inject.Inject
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.EStructuralFeature
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain
import org.eclipse.emf.parsley.junit4.AbstractEmfParsleyShellBasedTest
import org.eclipse.emf.parsley.listeners.AsyncCommandStackListenerHelper
import org.eclipse.emf.parsley.resource.ResourceLoader
import org.eclipse.emf.parsley.tests.models.testmodels.ClassForControls
import org.eclipse.emf.parsley.tests.models.testmodels.ClassWithName
import org.eclipse.emf.parsley.tests.util.EmfParsleyFixturesAndUtilitiesTestRule
import org.eclipse.emf.parsley.tests.util.TestableCommandStackListenerClient
import org.eclipse.emf.parsley.viewers.ColumnLabelProviderFactory
import org.eclipse.emf.parsley.viewers.TableViewerEditingSupport
import org.eclipse.jface.viewers.ArrayContentProvider
import org.eclipse.jface.viewers.CellEditor
import org.eclipse.jface.viewers.ColumnViewer
import org.eclipse.jface.viewers.TableViewer
import org.eclipse.jface.viewers.TableViewerColumn
import org.eclipse.jface.viewers.ViewerCell
import org.eclipse.swt.SWT
import org.eclipse.swt.widgets.Composite
import org.eclipse.swt.widgets.Widget
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import static org.junit.Assert.*
/**
* This checks that the model is updated only when it makes sense to update it,
* i.e., if the value in the cell editor is effectively changed and it's different
* from the original value in the cell editor.
*
* @author Lorenzo Bettini
*/
class TableViewerEditingSupportTest extends AbstractEmfParsleyShellBasedTest {
@Rule public extension EmfParsleyFixturesAndUtilitiesTestRule fixtures = new EmfParsleyFixturesAndUtilitiesTestRule()
@Inject var MembersInjector<TableViewerEditingSupport> membersInjector
@Inject var ColumnLabelProviderFactory columnLabelProviderFactory
@Inject var AdapterFactoryEditingDomain editingDomain
@Inject var ResourceLoader resourceLoader
@Inject var AsyncCommandStackListenerHelper helper
var TestableCommandStackListenerClient client
var TestableTableViewer tableViewer
val static TEST_URI = "http://dummy/My.testmodels"
var ClassForControls modelInstance
var ClassWithName referredInstance1
var ClassWithName referredInstance2
/**
* Make some protected methods public so that we can call them
*/
static class TestableTableViewerEditingSupport extends TableViewerEditingSupport {
new(ColumnViewer viewer, EStructuralFeature eStructuralFeature) {
super(viewer, eStructuralFeature)
}
override initializeCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
super.initializeCellEditorValue(cellEditor, cell)
}
override canEdit(Object element) {
super.canEdit(element)
}
override getValue(Object element) {
super.getValue(element)
}
override setValue(Object element, Object value) {
super.setValue(element, value)
}
override getCellEditor(Object element) {
super.getCellEditor(element)
}
}
/**
* Make some protected methods public so that we can call them
*/
static class TestableTableViewer extends TableViewer {
new(Composite parent) {
super(parent)
}
override getViewerRowFromItem(Widget item) {
super.getViewerRowFromItem(item)
}
}
@Before
def void setupEditingSupport() {
getOrCreateInjector.injectMembers(this)
tableViewer = new TestableTableViewer(shell)
client = new TestableCommandStackListenerClient
helper.addCommandStackListener(editingDomain, shell, client)
modelInstance = classForControlsInstance
referredInstance1 = createClassWithName("1")
referredInstance2 = createClassWithName("2")
}
@Test def void testBooleanNewValue() {
assertUpdatesAfterSimulation(testPackage.classForControls_BooleanFeature, true, true)
}
@Test def void testBooleanNewValueEqualsToOriginal() {
assertUpdatesAfterSimulation(testPackage.classForControls_BooleanFeature, false, false)
}
@Test def void testStringFeatureNewValue() {
assertUpdatesAfterSimulation(testPackage.classForControls_StringFeature, "a", true)
}
@Test def void testStringFeatureNewValueEqualsToOriginalDefault() {
// if a string feature was null in the model the original value in the cell editor
// is an empty string
assertUpdatesAfterSimulation(testPackage.classForControls_StringFeature, "", false)
}
@Test def void testIntegerFeatureNewValueEqualsToOriginalDefault() {
// an int feature is set to 0 by default
assertUpdatesAfterSimulation(testPackage.classForControls_IntFeature, "0", false)
}
@Test def void testIntegerFeatureNewValue() {
assertUpdatesAfterSimulation(testPackage.classForControls_IntFeature, "1", true)
}
@Test def void testReferenceFeatureNewValueEqualsToOriginalDefault() {
// a reference feature is set to null by default
assertUpdatesAfterSimulation(testPackage.classForControls_ReferenceToClassWithName, "", false)
}
@Test def void testReferenceFeatureNewValue() {
// a reference feature is set to null by default
assertUpdatesAfterSimulation(testPackage.classForControls_ReferenceToClassWithName, referredInstance1, true)
}
def private assertUpdatesAfterSimulation(EStructuralFeature feature, Object newValue, boolean expectModelChanged) {
val editingSupport = createEditingSupport(feature)
val items = tableViewer.table.items
// the table viewer has only one row
val tableItem = items.head
val row = tableViewer.getViewerRowFromItem(tableItem)
// and only one column, the one for the specified feature
val cell = row.getCell(0)
val cellEditor = editingSupport.getCellEditor(modelInstance)
// this is the inital value in the cell editor
editingSupport.initializeCellEditorValue(cellEditor, cell)
// simulates editing
cellEditor.value = newValue
// should the model be updated with the cell editor new value?
editingSupport.setValue(modelInstance, cellEditor.value)
// since we use a command stack listener, notified asynchronously, we must
// make sure that all async events are dispatched
flushPendingEvents
assertEquals("events: " + client.commandsAffectingResources, expectModelChanged,
!client.commandsAffectingResources.empty)
assertTrue(editingSupport.canEdit(modelInstance))
}
def private createEditingSupport(EStructuralFeature feature) {
editingDomain.getResourceFromLoader => [
contents += modelInstance
contents += referredInstance1
contents += referredInstance2
]
val tableViewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
tableViewerColumn.setLabelProvider(columnLabelProviderFactory.createColumnLabelProvider(feature));
new TestableTableViewerEditingSupport(tableViewer, feature) => [
membersInjector.injectMembers(it)
tableViewerColumn.editingSupport = it
tableViewer.contentProvider = new ArrayContentProvider
tableViewer.input = newArrayList(classForControlsInstance)
]
}
private def getResourceFromLoader(AdapterFactoryEditingDomain e1) {
val resourceSet = e1.resourceSet
resourceSet.setupResouceFactory
val response = resourceLoader.getResource(
e1,
URI.createURI(TEST_URI)
)
response.resource
}
}