In CompositeCell, consumed events are determined as an union of all sub cells' consumed events. However, during event handling, an event may be fired to a sub-cell that doesn't actually consume this event. This is problematic if the cell doesn't check consumed events itself (which in most cases they don't).
Review at http://gwt-code-reviews.appspot.com/1632804
Review by: jlabanca@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10860 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/cell/client/CompositeCell.java b/user/src/com/google/gwt/cell/client/CompositeCell.java
index 8e83e0e..72e9e87 100644
--- a/user/src/com/google/gwt/cell/client/CompositeCell.java
+++ b/user/src/com/google/gwt/cell/client/CompositeCell.java
@@ -219,6 +219,13 @@
private <X> void onBrowserEventImpl(final Context context, Element parent,
final C object, NativeEvent event, final ValueUpdater<C> valueUpdater,
final HasCell<C, X> hasCell) {
+ Cell<X> cell = hasCell.getCell();
+ String eventType = event.getType();
+ Set<String> cellConsumedEvents = cell.getConsumedEvents();
+ if (cellConsumedEvents == null || !cellConsumedEvents.contains(eventType)) {
+ // If this sub-cell doesn't consume this event.
+ return;
+ }
ValueUpdater<X> tempUpdater = null;
final FieldUpdater<C, X> fieldUpdater = hasCell.getFieldUpdater();
if (fieldUpdater != null) {
@@ -232,7 +239,6 @@
}
};
}
- Cell<X> cell = hasCell.getCell();
cell.onBrowserEvent(context, parent, hasCell.getValue(object), event,
tempUpdater);
}
diff --git a/user/test/com/google/gwt/cell/client/CompositeCellTest.java b/user/test/com/google/gwt/cell/client/CompositeCellTest.java
index 2dd7d7f..c69b6df 100644
--- a/user/test/com/google/gwt/cell/client/CompositeCellTest.java
+++ b/user/test/com/google/gwt/cell/client/CompositeCellTest.java
@@ -39,19 +39,7 @@
// Add one cell that consumes events.
List<HasCell<String, ?>> cells = createHasCells(3);
final MockCell<String> mock = new MockCell<String>(true, null);
- cells.add(new HasCell<String, String>() {
- public Cell<String> getCell() {
- return mock;
- }
-
- public FieldUpdater<String, String> getFieldUpdater() {
- return null;
- }
-
- public String getValue(String object) {
- return object;
- }
- });
+ addCell(mock, cells);
CompositeCell<String> cell = new CompositeCell<String>(cells);
assertNull(cell.getConsumedEvents());
assertTrue(cell.dependsOnSelection());
@@ -64,19 +52,7 @@
// Add one cell that consumes events.
List<HasCell<String, ?>> cells = createHasCells(3);
final MockCell<String> mock = new MockCell<String>(false, null, "click");
- cells.add(new HasCell<String, String>() {
- public Cell<String> getCell() {
- return mock;
- }
-
- public FieldUpdater<String, String> getFieldUpdater() {
- return null;
- }
-
- public String getValue(String object) {
- return object;
- }
- });
+ addCell(mock, cells);
CompositeCell<String> cell = new CompositeCell<String>(cells);
assertEquals(1, cell.getConsumedEvents().size());
assertTrue(cell.getConsumedEvents().contains("click"));
@@ -100,19 +76,7 @@
return true;
}
};
- cells.add(new HasCell<String, String>() {
- public Cell<String> getCell() {
- return mock;
- }
-
- public FieldUpdater<String, String> getFieldUpdater() {
- return null;
- }
-
- public String getValue(String object) {
- return object;
- }
- });
+ addCell(mock, cells);
CompositeCell<String> cell = new CompositeCell<String>(cells);
Element parent = Document.get().createDivElement();
parent.setInnerHTML(getExpectedInnerHtml());
@@ -139,15 +103,16 @@
Document.get().getBody().appendChild(parent);
// Create the composite cell and updater.
- List<HasCell<String, ?>> cells = createHasCells(3);
+ List<HasCell<String, ?>> cells = createHasCells(2);
+ MockCell<String> innerCell = new MockCell<String>(false, "fromCell2", "click");
+ addCell(innerCell, cells);
final CompositeCell<String> cell = new CompositeCell<String>(cells);
- MockCell<String> innerCell = (MockCell<String>) cells.get(1).getCell();
// Add an event listener.
EventListener listener = new EventListener() {
public void onBrowserEvent(Event event) {
Context context = new Context(3, 4, "key");
- cell.onBrowserEvent(context, parent, "test", event, null);
+ cell.onBrowserEvent(context, parent, "test-x", event, null);
}
};
DOM.sinkEvents(parent, Event.ONCLICK);
@@ -156,14 +121,20 @@
// Fire the event on one of the inner cells.
NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false,
false, false, false);
- Element.as(parent.getChild(1)).dispatchEvent(event);
- innerCell.assertLastEventValue("test-1");
- innerCell.assertLastParentElement(Element.as(parent.getChild(1)));
+ Element.as(parent.getChild(2)).dispatchEvent(event);
+ innerCell.assertLastEventValue("test-x");
+ innerCell.assertLastParentElement(Element.as(parent.getChild(2)));
Context innerContext = innerCell.getLastContext();
assertEquals("key", innerContext.getKey());
assertEquals(3, innerContext.getIndex());
assertEquals(4, innerContext.getColumn());
+ // Fire the event to another cell that doesn't consume this event. Shouldn't respond
+ // to the event
+ MockCell<String> innerCell2 = (MockCell<String>) cells.get(1).getCell();
+ Element.as(parent.getChild(1)).dispatchEvent(event);
+ innerCell2.assertLastEventValue(null);
+
// Remove the element and event listener.
DOM.setEventListener(parent, null);
Document.get().getBody().removeChild(parent);
@@ -213,6 +184,25 @@
}
/**
+ * Add a cell to a {@link HasCell} list.
+ */
+ private void addCell(final Cell<String> cell, List<HasCell<String, ?>> cells) {
+ cells.add(new HasCell<String, String>() {
+ public Cell<String> getCell() {
+ return cell;
+ }
+
+ public FieldUpdater<String, String> getFieldUpdater() {
+ return null;
+ }
+
+ public String getValue(String object) {
+ return object;
+ }
+ });
+ }
+
+ /**
* Create an array of {@link HasCell}.
*
* @param count the number of cells to create