import java.util.Set;
import java.util.logging.Logger;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
public Object getValue(final JsonObject obj) {
final JsonObject rowData = obj.getObject(GridState.JSONKEY_DATA);
- assert rowData.hasKey(id) : "Could not find data for column with id "
- + id;
+ if (rowData.hasKey(id)) {
+ final JsonValue columnValue = rowData.get(id);
- final JsonValue columnValue = rowData.get(id);
+ return rendererConnector.decode(columnValue);
+ }
- return rendererConnector.decode(columnValue);
+ return null;
}
/*
@Override
public void bind(final int rowIndex) {
- /*
- * Because most shared state handling is deferred, we must
- * defer this too to ensure the editorConnector references
- * in shared state are up to date before opening the editor.
- * Yes, this is a hack on top of a hack.
- */
- Scheduler.get().scheduleDeferred(new ScheduledCommand() {
- @Override
- public void execute() {
- serverInitiated = true;
- GridConnector.this.getWidget().editRow(rowIndex);
- }
- });
+ serverInitiated = true;
+ GridConnector.this.getWidget().editRow(rowIndex);
}
@Override
@Override
public void confirmBind() {
- /*
- * See comment in bind()
- */
- Scheduler.get().scheduleDeferred(new ScheduledCommand() {
- @Override
- public void execute() {
- endRequest();
- }
- });
+ endRequest();
+
}
@Override
updateSelectionFromState();
}
- /*
- * The operations in here have been made deferred.
- *
- * The row data needed to react to column changes comes in the RPC
- * calls. Since state is always updated before RPCs are called, we need
- * to be sure that RPC is called before Grid reacts to state changes.
- *
- * Note that there are still some methods annotated with @OnStateChange
- * that aren't deferred. That's okay, though.
- */
-
- Scheduler.get().scheduleDeferred(new ScheduledCommand() {
- @Override
- public void execute() {
- // Column updates
- if (stateChangeEvent.hasPropertyChanged("columns")) {
-
- // Remove old columns
- purgeRemovedColumns();
-
- // Add new columns
- for (GridColumnState state : getState().columns) {
- if (!columnIdToColumn.containsKey(state.id)) {
- addColumnFromStateChangeEvent(state);
- }
- updateColumnFromState(columnIdToColumn.get(state.id),
- state);
- }
- }
+ // Column updates
+ if (stateChangeEvent.hasPropertyChanged("columns")) {
- if (stateChangeEvent.hasPropertyChanged("columnOrder")) {
- if (orderNeedsUpdate(getState().columnOrder)) {
- updateColumnOrderFromState(getState().columnOrder);
- }
- }
+ // Remove old columns
+ purgeRemovedColumns();
- if (stateChangeEvent.hasPropertyChanged("header")) {
- updateHeaderFromState(getState().header);
+ // Add new columns
+ for (GridColumnState state : getState().columns) {
+ if (!columnIdToColumn.containsKey(state.id)) {
+ addColumnFromStateChangeEvent(state);
}
+ updateColumnFromState(columnIdToColumn.get(state.id), state);
+ }
+ }
- if (stateChangeEvent.hasPropertyChanged("footer")) {
- updateFooterFromState(getState().footer);
- }
+ if (stateChangeEvent.hasPropertyChanged("columnOrder")) {
+ if (orderNeedsUpdate(getState().columnOrder)) {
+ updateColumnOrderFromState(getState().columnOrder);
+ }
+ }
- if (stateChangeEvent.hasPropertyChanged("editorEnabled")) {
- getWidget().setEditorEnabled(getState().editorEnabled);
- }
+ if (stateChangeEvent.hasPropertyChanged("header")) {
+ updateHeaderFromState(getState().header);
+ }
- if (stateChangeEvent.hasPropertyChanged("frozenColumnCount")) {
- getWidget().setFrozenColumnCount(
- getState().frozenColumnCount);
- }
+ if (stateChangeEvent.hasPropertyChanged("footer")) {
+ updateFooterFromState(getState().footer);
+ }
- }
- });
+ if (stateChangeEvent.hasPropertyChanged("editorEnabled")) {
+ getWidget().setEditorEnabled(getState().editorEnabled);
+ }
+ if (stateChangeEvent.hasPropertyChanged("frozenColumnCount")) {
+ getWidget().setFrozenColumnCount(getState().frozenColumnCount);
+ }
}
private void updateColumnOrderFromState(List<String> stateColumnOrder) {
itemId);
valueChangeListeners.put(itemId, listener);
- for (final Object propertyId : item.getItemPropertyIds()) {
- final Property<?> property = item
- .getItemProperty(propertyId);
+ for (final Column column : getGrid().getColumns()) {
+ final Property<?> property = item.getItemProperty(column
+ .getPropertyId());
if (property instanceof ValueChangeNotifier) {
((ValueChangeNotifier) property)
.addValueChangeListener(listener);
.remove(itemId);
if (listener != null) {
- for (final Object propertyId : item.getItemPropertyIds()) {
+ for (final Column column : getGrid().getColumns()) {
final Property<?> property = item
- .getItemProperty(propertyId);
+ .getItemProperty(column.getPropertyId());
if (property instanceof ValueChangeNotifier) {
((ValueChangeNotifier) property)
.removeValueChangeListener(listener);
}
/**
- * Manages removed properties in active rows.
+ * Manages removed columns in active rows.
+ * <p>
+ * This method does <em>not</em> send data again to the client.
*
- * @param removedPropertyIds
- * the property ids that have been removed from the container
+ * @param removedColumns
+ * the columns that have been removed from the grid
*/
- public void propertiesRemoved(
- @SuppressWarnings("unused") Collection<Object> removedPropertyIds) {
- /*
- * no-op, for now.
- *
- * The Container should be responsible for cleaning out any
- * ValueChangeListeners from removed Properties. Components will
- * benefit from this, however.
- */
+ public void columnsRemoved(Collection<Column> removedColumns) {
+ if (removedColumns.isEmpty()) {
+ return;
+ }
+
+ for (int i = activeRange.getStart(); i < activeRange.getEnd(); i++) {
+ final Object itemId = container.getIdByIndex(i);
+ final Item item = container.getItem(itemId);
+ final GridValueChangeListener listener = valueChangeListeners
+ .get(itemId);
+ assert (listener != null) : "a listener should've been pre-made by addValueChangeListeners";
+
+ for (final Column column : removedColumns) {
+ final Property<?> property = item.getItemProperty(column
+ .getPropertyId());
+ if (property instanceof ValueChangeNotifier) {
+ ((ValueChangeNotifier) property)
+ .removeValueChangeListener(listener);
+ }
+ }
+ }
}
/**
- * Manages added properties in active rows.
+ * Manages added columns in active rows.
+ * <p>
+ * This method sends the data for the changed rows to client side.
*
- * @param addedPropertyIds
- * the property ids that have been added to the container
+ * @param addedColumns
+ * the columns that have been added to the grid
*/
- public void propertiesAdded(Collection<Object> addedPropertyIds) {
- if (addedPropertyIds.isEmpty()) {
+ public void columnsAdded(Collection<Column> addedColumns) {
+ if (addedColumns.isEmpty()) {
return;
}
.get(itemId);
assert (listener != null) : "a listener should've been pre-made by addValueChangeListeners";
- for (final Object propertyId : addedPropertyIds) {
- final Property<?> property = item
- .getItemProperty(propertyId);
+ for (final Column column : addedColumns) {
+ final Property<?> property = item.getItemProperty(column
+ .getPropertyId());
if (property instanceof ValueChangeNotifier) {
((ValueChangeNotifier) property)
.addValueChangeListener(listener);
}
/**
- * Informs this data provider that some of the properties have been removed
- * from the container.
- * <p>
- * Please note that we could add our own
- * {@link com.vaadin.data.Container.PropertySetChangeListener
- * PropertySetChangeListener} to the container, but then we'd need to
- * implement the same bookeeping for finding what's added and removed that
- * Grid already does in its own listener.
+ * Informs this data provider that given columns have been removed from
+ * grid.
*
* @param removedColumns
- * a list of property ids for the removed columns
+ * a list of removed columns
*/
- public void propertiesRemoved(List<Object> removedColumns) {
- activeRowHandler.propertiesRemoved(removedColumns);
+ public void columnsRemoved(List<Column> removedColumns) {
+ activeRowHandler.columnsRemoved(removedColumns);
}
/**
- * Informs this data provider that some of the properties have been added to
- * the container.
- * <p>
- * Please note that we could add our own
- * {@link com.vaadin.data.Container.PropertySetChangeListener
- * PropertySetChangeListener} to the container, but then we'd need to
- * implement the same bookeeping for finding what's added and removed that
- * Grid already does in its own listener.
+ * Informs this data provider that given columns have been added to grid.
*
- * @param addedPropertyIds
- * a list of property ids for the added columns
+ * @param addedColumns
+ * a list of added columns
*/
- public void propertiesAdded(HashSet<Object> addedPropertyIds) {
- activeRowHandler.propertiesAdded(addedPropertyIds);
+ public void columnsAdded(List<Column> addedColumns) {
+ activeRowHandler.columnsAdded(addedColumns);
}
public DataProviderKeyMapper getKeyMapper() {
Collection<?> properties = new HashSet<Object>(event.getContainer()
.getContainerPropertyIds());
- // Cleanup columns that are no longer in grid
- List<Object> removedColumns = new LinkedList<Object>();
- for (Object columnId : columns.keySet()) {
- if (!properties.contains(columnId)) {
- removedColumns.add(columnId);
+ // Find columns that need to be removed.
+ List<Column> removedColumns = new LinkedList<Column>();
+ for (Object propertyId : columns.keySet()) {
+ if (!properties.contains(propertyId)) {
+ removedColumns.add(getColumn(propertyId));
}
}
- for (Object columnId : removedColumns) {
- removeColumn(columnId);
- columnKeys.remove(columnId);
+
+ // Actually remove columns.
+ for (Column column : removedColumns) {
+ Object propertyId = column.getPropertyId();
+ internalRemoveColumn(propertyId);
+ columnKeys.remove(propertyId);
}
- datasourceExtension.propertiesRemoved(removedColumns);
+ datasourceExtension.columnsRemoved(removedColumns);
// Add new columns
- HashSet<Object> addedPropertyIds = new HashSet<Object>();
+ List<Column> addedColumns = new LinkedList<Column>();
for (Object propertyId : properties) {
if (!columns.containsKey(propertyId)) {
- appendColumn(propertyId);
- addedPropertyIds.add(propertyId);
+ addedColumns.add(appendColumn(propertyId));
}
}
- datasourceExtension.propertiesAdded(addedPropertyIds);
+ datasourceExtension.columnsAdded(addedColumns);
if (getFrozenColumnCount() > columns.size()) {
setFrozenColumnCount(columns.size());
} else {
addColumnProperty(propertyId, String.class, "");
}
- return getColumn(propertyId);
+
+ // Inform the data provider of this new column.
+ Column column = getColumn(propertyId);
+ List<Column> addedColumns = new ArrayList<Column>();
+ addedColumns.add(column);
+ datasourceExtension.columnsAdded(addedColumns);
+
+ return column;
}
/**
* Removes all columns from this Grid.
*/
public void removeAllColumns() {
+ List<Column> removed = new ArrayList<Column>(columns.values());
Set<Object> properties = new HashSet<Object>(columns.keySet());
for (Object propertyId : properties) {
removeColumn(propertyId);
}
+ datasourceExtension.columnsRemoved(removed);
}
/**
* The property id of column to be removed
*/
public void removeColumn(Object propertyId) {
+ List<Column> removed = new ArrayList<Column>();
+ removed.add(getColumn(propertyId));
+ internalRemoveColumn(propertyId);
+ datasourceExtension.columnsRemoved(removed);
+ }
+
+ private void internalRemoveColumn(Object propertyId) {
setEditorField(propertyId, null);
header.removeColumn(propertyId);
footer.removeColumn(propertyId);