Почему в CellTable нет достойных примеров использования CompositeCell?
Я поинтересовался, как получить / установить значения CompositeCell, GoogleCode, GWT ShowCase, GWT Developer Notes и Google Groups. Не существует одного определенного примера, который объясняет, как использовать его в 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://stackru.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/ ценовых баллов (OfferPriceMWPairDTO). Я хочу визуализировать сетку, в которой для часов дня я могу видеть до 10 кривых (кривые, представляющие собой коллекцию MW/ ценовых точек за день). Я хочу, чтобы каждый из этих столбцов кривой содержал пару полей ввода (одно для цены и одно для значения mw). Я полагаю, эй, создать столбцы и ячейки для каждого, а затем объединить их в CompositeCell. Как трудно это может быть?
Я решил расширить CellTable (то есть, ToggleableGrid), чтобы я мог инкапсулировать настройку, стиль и поведение рабочей панели; а также установить режим отображения. С режимом обращаются, когда строятся столбцы (см. IsInEditMode) для визуализации либо TextCell, либо конкретной производной от AbstractInputCell, например TextInputCell. Я также создал расширение для SelectionCell (т. Е. ReferenceDataBackedSelectionCell), чтобы можно было установить значение параметра с помощью ReferenceData. Единственные входные столбцы работают! Я могу отобразить их как текст или как поле ввода или выбрать список. Именно CompositeCell вызывает у меня головную боль.
Хотя этот код будет правильно отображать пары полей ввода, все значения будут пустыми (пустыми), либо пустым текстом, либо пустыми парами полей ввода.
Пожалуйста, ознакомьтесь с методом addPriceMwColumn. Может быть, вы можете увидеть то, что я не вижу?
1 ответ
Может ли это быть так же просто, как возвращение EnergyOfferDTO
в вашей колонке вместо null
? (вы можете использовать IdentityColumn
)
Вы говорите в комментарии в своем коде, что составная ячейка делегирует свои ячейки, но столбец обязан сначала дать значение составной ячейке, а затем составная ячейка будет вызывать каждую HasCell
извлечь значение внутренней ячейки из значения, переданного в составную ячейку.
Как примечание, ваша составная ячейка render
метод не должен зацикливаться на hasCells
список, он должен просто позвонить super.render(context, value, sb)
(конечно, все еще украшать его appendHtmlConstant
звонки), которая сделает работу.