Por que não existem exemplos decentes de CompositeCell em uso em uma CellTabl
Examinei o GoogleCode, o GWT ShowCase, as Notas do desenvolvedor do GWT e os Grupos do Google para saber como obter / definir valores de um CompositeCell. Não há um exemplo definitivo que explique como usá-lo em uma CellTabl
Vamos olhar para algum código ... primeiro uma classe abstrata ...
public abstract class ToggleableGrid<T> extends CellTable<T> {
private static final String DEFAULT_TABLE_WIDTH = "100%";
private static final DisplayMode DEFAULT_MODE = DisplayMode.VIEW;
protected void setDefaults() {
setWidth(DEFAULT_TABLE_WIDTH);
// Set the message to display when the table is empty.
setEmptyTableWidget(new Label(UiMessages.INSTANCE.no_results()));
// Add a selection model so we can select cells
final SelectionModel<T> selectionModel = new MultiSelectionModel<T>();
setSelectionModel(selectionModel, DefaultSelectionEventManager.<T> createDefaultManager());
}
public void setInput(List<T> content) {
setInput(content, DEFAULT_MODE);
}
public void setInput(List<T> content, DisplayMode mode) {
setDefaults();
resetTableColumns();
final ListDataProvider<T> dataProvider = new ListDataProvider<T>(content);
final ListHandler<T> sortHandler = new ListHandler<T>(dataProvider.getList());
addColumnSortHandler(sortHandler);
initializeStructure(constructMetadata(), sortHandler, mode);
dataProvider.addDataDisplay(this);
}
// see http://stackoverflow.com/questions/3772480/remove-all-columns-from-a-celltable
// concrete classes are forced to maintain a handle on all columns added
private void resetTableColumns() {
for (final Column<T, ?> column: allColumns()) {
removeColumn(column);
}
allColumns().clear();
}
public boolean isInEditMode(DisplayMode currentDisplayMode) {
boolean result = false;
if (currentDisplayMode == DisplayMode.EDIT) {
result = true;
}
return result;
}
protected abstract Set<Column<T, ?>> allColumns();
protected abstract TableMetadata constructMetadata();
protected abstract void initializeStructure(TableMetadata metadata, ListHandler<T> sortHandler, DisplayMode mode);
protected void setColumnHorizontalAlignment(Column<T, ?> column, HorizontalAlignmentConstant alignment) {
column.setHorizontalAlignment(alignment);
}
@Override
public void addColumn(Column<T, ?> column, String columnHeaderName) {
final StringBuffer sb = new StringBuffer();
sb.append("<div align=\"right\">").append(columnHeaderName).append("</div>");
final SafeHtml header = new OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml(sb.toString());
addColumn(column, header);
allColumns().add(column);
}
}
E então uma implementação concreta ...
public class EnergyOfferGrid extends ToggleableGrid<EnergyOfferDTO> {
private static final int MAX_NUMBER_OF_MW_PRICE_POINTS = 10;
private Set<Column<EnergyOfferDTO, ?>> columns = new HashSet<Column<EnergyOfferDTO, ?>>();
@Override
protected Set<Column<EnergyOfferDTO, ?>> allColumns() {
return columns;
}
@Override
protected TableMetadata constructMetadata() {
final TableMetadata metadata = new TableMetadata();
// TODO Consider a predefined set of ReferenceData to be held in a common package
// Use Slope
metadata.addColumnMetadata(UiMessages.INSTANCE.use_slope(), new String[] {UiMessages.INSTANCE.yes(), UiMessages.INSTANCE.no()}, new String[] {"true", "false"});
return metadata;
}
@Override
protected void initializeStructure(TableMetadata metadata, ListHandler<EnergyOfferDTO> sortHandler, DisplayMode currentDisplayMode) {
addHourColumn(sortHandler);
addUseSlopeColumn(metadata, sortHandler, currentDisplayMode);
for (int i = 1; i <= MAX_NUMBER_OF_MW_PRICE_POINTS; i++) {
addPriceMwColumn(i, currentDisplayMode);
}
}
protected void addHourColumn(ListHandler<EnergyOfferDTO> sortHandler) {
final Column<EnergyOfferDTO, String> hourColumn = new Column<EnergyOfferDTO, String>(new TextCell()) {
@Override
public String getValue(EnergyOfferDTO energyOffer) {
String result = "";
final String isoDateTime = energyOffer.getDateTime();
if (isoDateTime != null && !isoDateTime.isEmpty()) {
final Date dateTime = TimeUtil.isoToDate(isoDateTime);
if (dateTime != null) {
result = TimeUtil.dateToHour(dateTime);
}
}
return result;
}
};
hourColumn.setSortable(true);
sortHandler.setComparator(hourColumn, new Comparator<EnergyOfferDTO>() {
@Override
public int compare(EnergyOfferDTO eo1, EnergyOfferDTO eo2) {
return eo1.getDateTime().compareTo(eo2.getDateTime());
}
});
addColumn(hourColumn, UiMessages.INSTANCE.hour());
setColumnWidth(hourColumn, 10, Unit.PCT);
setColumnHorizontalAlignment(hourColumn, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected void addUseSlopeColumn(TableMetadata metadata, ListHandler<EnergyOfferDTO> sortHandler, DisplayMode currentDisplayMode) {
final ReferenceData refData = metadata.allColumnMetadata().get(UiMessages.INSTANCE.use_slope());
Column<EnergyOfferDTO, String> useSlopeColumn;
Cell<String> cell;
if (isInEditMode(currentDisplayMode)) {
cell = new ReferenceDataBackedSelectionCell(refData);
} else {
cell = new TextCell();
}
useSlopeColumn = new Column<EnergyOfferDTO, String>(cell) {
@Override
public String getValue(EnergyOfferDTO energyOffer) {
return refData.getDisplayValueForSubmitValue(Boolean.toString(energyOffer.isSlope()));
}
};
useSlopeColumn.setSortable(true);
sortHandler.setComparator(useSlopeColumn, new Comparator<EnergyOfferDTO>() {
@Override
public int compare(EnergyOfferDTO eo1, EnergyOfferDTO eo2) {
return eo1.getDateTime().compareTo(eo2.getDateTime());
}
});
addColumn(useSlopeColumn, UiMessages.INSTANCE.use_slope());
setColumnWidth(useSlopeColumn, 10, Unit.PCT);
setColumnHorizontalAlignment(useSlopeColumn, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected void addPriceMwColumn(final int colIndex, DisplayMode currentDisplayMode) {
// Construct a composite cell for energy offers that includes a pair of text inputs
final List<HasCell<EnergyOfferDTO, ?>> hasCells = new ArrayList<
HasCell<EnergyOfferDTO, ?>>();
// this DTO is passed along so that price and mw values for new entries are kept together
final OfferPriceMwPairDTO newOfferPriceMwPairDTO = new OfferPriceMwPairDTO();
// Price
final HasCell<EnergyOfferDTO, String> priceCell = generatePriceCell(colIndex, newOfferPriceMwPairDTO, currentDisplayMode);
hasCells.add(priceCell);
// MW
final HasCell<EnergyOfferDTO, String> mwCell = generateMwCell(colIndex, newOfferPriceMwPairDTO, currentDisplayMode);
hasCells.add(mwCell);
// Composite
final CompositeCell<EnergyOfferDTO> priceMwCell = generateCompositeCell(hasCells);
final Column<EnergyOfferDTO, EnergyOfferDTO> priceMwColumn = new Column<EnergyOfferDTO, EnergyOfferDTO>(priceMwCell) {
@Override
public EnergyOfferDTO getValue(EnergyOfferDTO energyOffer) {
// we do this to satisfy the anonymous type's contract,
// but know that this column's composite cell delegates to its individual cell impls to get a value
return null;
}
};
addColumn(priceMwColumn, String.valueOf(colIndex));
setColumnWidth(priceMwColumn, 8, Unit.PCT);
setColumnHorizontalAlignment(priceMwColumn, HasHorizontalAlignment.ALIGN_RIGHT);
}
protected HasCell<EnergyOfferDTO, String> generatePriceCell(final int colIndex, final OfferPriceMwPairDTO newOfferPriceMwPair, DisplayMode currentDisplayMode) {
HasCell<EnergyOfferDTO, String> priceCell;
if (isInEditMode(currentDisplayMode)) {
priceCell = new HasCell<EnergyOfferDTO, String>() {
private TextInputCell cell = new TextInputCell();
@Override
public Cell<String> getCell() {
return cell;
}
@Override
public FieldUpdater<EnergyOfferDTO, String> getFieldUpdater() {
return new FieldUpdater<EnergyOfferDTO, String>() {
@Override
public void update(int index, EnergyOfferDTO energyOffer, String value) {
if (value != null && !value.isEmpty()) {
// number format exceptions should be caught and handled by event bus's handle method
final double valueAsDouble = NumberFormat.getDecimalFormat().parse(value);
final BigDecimal price = BigDecimal.valueOf(valueAsDouble);
final List<OfferPriceMwPairDTO> offerPriceCurve = energyOffer.getOfferPriceCurve();
final OfferPriceMwPairDTO offerPriceMwPairDTO = offerPriceCurve.get(colIndex);
if (offerPriceMwPairDTO == null) { // we have a new price value
newOfferPriceMwPair.setPrice(price);
offerPriceCurve.add(newOfferPriceMwPair);
} else {
offerPriceMwPairDTO.setPrice(price);
}
}
}
};
}
@Override
public String getValue(EnergyOfferDTO energyOffer) {
String result = "";
if (energyOffer != null) {
final List<OfferPriceMwPairDTO> offerPriceCurve = energyOffer.getOfferPriceCurve();
final OfferPriceMwPairDTO offerPriceMwPairDTO = offerPriceCurve.get(colIndex);
if (offerPriceMwPairDTO != null) {
final BigDecimal price = offerPriceMwPairDTO.getPrice();
result = String.valueOf(price.doubleValue());
}
}
return result;
}
};
} else {
priceCell = new Column<EnergyOfferDTO, String>(new TextCell()) {
@Override
public String getValue(EnergyOfferDTO energyOffer) {
String result = "";
if (energyOffer != null) {
final List<OfferPriceMwPairDTO> offerPriceCurve = energyOffer.getOfferPriceCurve();
final OfferPriceMwPairDTO offerPriceMwPairDTO = offerPriceCurve.get(colIndex);
if (offerPriceMwPairDTO != null) {
final BigDecimal price = offerPriceMwPairDTO.getPrice();
result = String.valueOf(price.doubleValue());
}
}
return result;
}
};
}
return priceCell;
}
protected HasCell<EnergyOfferDTO, String> generateMwCell(final int colIndex, final OfferPriceMwPairDTO newOfferPriceMwPair, DisplayMode currentDisplayMode) {
HasCell<EnergyOfferDTO, String> mwCell;
if (isInEditMode(currentDisplayMode)) {
mwCell = new HasCell<EnergyOfferDTO, String>() {
private TextInputCell cell = new TextInputCell();
@Override
public Cell<String> getCell() {
return cell;
}
@Override
public FieldUpdater<EnergyOfferDTO, String> getFieldUpdater() {
return new FieldUpdater<EnergyOfferDTO, String>() {
@Override
public void update(int index, EnergyOfferDTO energyOffer, String value) {
if (value != null && !value.isEmpty()) {
// number format exceptions should be caught and handled by event bus's handle method
final double valueAsDouble = NumberFormat.getDecimalFormat().parse(value);
final BigDecimal mw = BigDecimal.valueOf(valueAsDouble);
final List<OfferPriceMwPairDTO> offerPriceCurve = energyOffer.getOfferPriceCurve();
final OfferPriceMwPairDTO offerPriceMwPairDTO = offerPriceCurve.get(colIndex);
if (offerPriceMwPairDTO == null) { // we have a new mw value
newOfferPriceMwPair.setMw(mw);
offerPriceCurve.add(newOfferPriceMwPair);
} else {
offerPriceMwPairDTO.setMw(mw);
}
}
}
};
}
@Override
public String getValue(EnergyOfferDTO energyOffer) {
String result = "";
if (energyOffer != null) {
final List<OfferPriceMwPairDTO> offerPriceCurve = energyOffer.getOfferPriceCurve();
final OfferPriceMwPairDTO offerPriceMwPairDTO = offerPriceCurve.get(colIndex);
if (offerPriceMwPairDTO != null) {
final BigDecimal mw = offerPriceMwPairDTO.getMw();
result = String.valueOf(mw.doubleValue());
}
}
return result;
}
};
} else {
mwCell = new Column<EnergyOfferDTO, String>(new TextCell()) {
@Override
public String getValue(EnergyOfferDTO energyOffer) {
String result = "";
if (energyOffer != null) {
final List<OfferPriceMwPairDTO> offerPriceCurve = energyOffer.getOfferPriceCurve();
final OfferPriceMwPairDTO offerPriceMwPairDTO = offerPriceCurve.get(colIndex);
if (offerPriceMwPairDTO != null) {
final BigDecimal mw = offerPriceMwPairDTO.getMw();
result = String.valueOf(mw.doubleValue());
}
}
return result;
}
};
}
return mwCell;
}
protected CompositeCell<EnergyOfferDTO> generateCompositeCell(final List<HasCell<EnergyOfferDTO, ?>> hasCells) {
final CompositeCell<EnergyOfferDTO> compositeCell = new CompositeCell<EnergyOfferDTO>(hasCells) {
@Override
public void render(Context context, EnergyOfferDTO value, SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<table><tbody><tr>");
for (final HasCell<EnergyOfferDTO, ?> hasCell : hasCells) {
render(context, value, sb, hasCell);
}
sb.appendHtmlConstant("</tr></tbody></table>");
}
@Override
protected Element getContainerElement(Element parent) {
// Return the first TR element in the table.
return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
}
@Override
protected <X> void render(Context context, EnergyOfferDTO value,
SafeHtmlBuilder sb, HasCell<EnergyOfferDTO, X> hasCell) {
final Cell<X> cell = hasCell.getCell();
sb.appendHtmlConstant("<td>");
cell.render(context, hasCell.getValue(value), sb);
sb.appendHtmlConstant("</td>");
}
};
return compositeCell;
}
}
Tenho uma oferta de energia (EnergyOfferDTO). Possui uma lista de pontos MW / preço (OfferPriceMWPairDTO). Eu quero renderizar uma grade em que por horas do dia eu possa ver até 10 curvas (as curvas são a coleção de pontos MW / Preço do dia). Quero que cada uma dessas colunas da curva contenha um par de campos de entrada (um para preço e outro para valor mw). Eu imagino, ei, crie colunas e células para cada uma delas e as junte em um CompositeCell. Quão difícil isso poderia ser
Decidi estender o CellTable (ou seja, ToggleableGrid) para poder encapsular a configuração, o estilo e o comportamento da placa da caldeira; também para definir um modo de exibição. O modo é consultado à medida que as colunas estão sendo construídas (consulte isInEditMode) para renderizar um TextCell ou um derivado concreto de AbstractInputCell, como TextInputCell. Também criei uma extensão para SelectionCell (ou seja, ReferenceDataBackedSelectionCell) para poder definir o valor de uma opção usando o ReferenceData. Colunas de entrada única funcionam! Eu posso exibi-los como texto ou como campo de entrada ou selecionar lista. É o CompositeCell que está me causando dores de cabeça.
Enquanto esse código renderizará os pares de campos de entrada corretamente, os valores estarão em branco (nulo), em branco ou em branc
Por favor, dê uma olhada no método addPriceMwColumn. Talvez você possa ver algo que eu não vejo