CompositeCellの値を取得/設定する方法について、GoogleCode、GWT ShowCase、GWT Developer Notes、およびGoogleグループを調べました。CellTable内での使用方法を説明する決定的な例はありません。
いくつかのコードを見つめましょう...最初に抽象クラス...
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);
}
}
そして具体的な実装...
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;
}
}
エネルギーオファー(EnergyOfferDTO)があります。MW / Priceポイントのリスト(OfferPriceMWPairDTO)があります。1日の何時間にもわたって最大10個の曲線を表示できるグリッドをレンダリングしたいと思います(曲線はその日のMW /価格ポイントのコレクションです)。これらの各曲線列に、1組の入力フィールド(1つは価格用、もう1つはmw値用)を含める必要があります。それぞれの列とセルを作成し、CompositeCellにまとめます。それはどれほど難しいでしょうか?
ボイラープレートのセットアップ、スタイル、および動作をカプセル化できるように、CellTable(つまり、ToggleableGrid)を拡張することにしました。表示モードを設定することもできます。このモードは、TextCellまたはTextInputCellなどのAbstractInputCellの具象派生物をレンダリングするために、列が作成されるときに参照されます(isInEditModeを参照)。また、ReferenceDataを使用してオプションの値を設定できるように、SelectionCellの拡張機能(つまり、ReferenceDataBackedSelectionCell)を作成しました。単一の入力列が機能します!テキストとして、または入力フィールドまたは選択リストとして表示できます。私に頭痛の種を引き起こしているのはCompositeCellです。
このコードは入力フィールドのペアを正しくレンダリングしますが、値はすべて空白(null)であり、空白のテキストまたは空白の入力フィールドのペアのいずれかです。
addPriceMwColumnメソッドをざっと見てください。多分あなたは私が見ない何かを見ることができますか?