如何使用GWT Celltable在多列上执行排序。我没有找到任何示例代码?见下图
我需要在多个列上执行服务器端排序。如何使用GWT Celltable实现此目的以及如何为多个列添加此箭头图标。任何线索?
答案 0 :(得分:1)
您可以使用自定义标题生成器。您可以使用下面的那个(它也支持排序顺序,但如果您不需要它,可以将其删除)
public class MultiSortHeaderOrFooterBuilder<T> extends AbstractHeaderOrFooterBuilder<T> {
private static class ColumnSortInfoHolder {
private ColumnSortInfo columnSortInfo;
private int sortIndex;
public ColumnSortInfoHolder(ColumnSortInfo columnSortInfo, int sortIndex) {
this.columnSortInfo = columnSortInfo;
this.sortIndex = sortIndex;
}
public int getSortIndex() {
return sortIndex;
}
public ColumnSortInfo getColumnSortInfo() {
return columnSortInfo;
}
}
private final int sortAscIconWidth;
private final int sortAscIconHalfHeight;
private final int sortDescIconWidth;
private final int sortDescIconHalfHeight;
private SafeHtml sortAscIconHtml;
private SafeHtml sortDescIconHtml;
private static final int ICON_PADDING = 6;
/**
* Create a new DefaultHeaderBuilder for the header of footer section.
*
* @param table
* the table being built
* @param isFooter
* true if building the footer, false if the header
*/
public MultiSortHeaderOrFooterBuilder(AbstractCellTable<T> table, boolean isFooter) {
super(table, isFooter);
ImageResource asc = table.getResources().sortAscending();
ImageResource desc = table.getResources().sortDescending();
if (asc != null) {
sortAscIconWidth = asc.getWidth() + ICON_PADDING;
sortAscIconHalfHeight = (int) Math.round(asc.getHeight() / 2.0);
} else {
sortAscIconWidth = 0;
sortAscIconHalfHeight = 0;
}
if (desc != null) {
sortDescIconWidth = desc.getWidth() + ICON_PADDING;
sortDescIconHalfHeight = (int) Math
.round(desc.getHeight() / 2.0);
} else {
sortDescIconWidth = 0;
sortDescIconHalfHeight = 0;
}
}
@Override
protected boolean buildHeaderOrFooterImpl() {
AbstractCellTable<T> table = getTable();
boolean isFooter = isBuildingFooter();
if (isFooter)
return false;
// Early exit if there aren't any columns to render.
int columnCount = table.getColumnCount();
if (columnCount == 0) {
// Nothing to render;
return false;
}
// Early exit if there aren't any headers in the columns to render.
boolean hasHeader = false;
for (int i = 0; i < columnCount; i++) {
if (table.getHeader(i) != null) {
hasHeader = true;
break;
}
}
if (hasHeader == false) {
return false;
}
HashMap<Column<?, ?>, ColumnSortInfoHolder> sortInfoByColumn = new HashMap<Column<?, ?>, ColumnSortInfoHolder>();
// Set sorting information for multisort
ColumnSortList sortList = table.getColumnSortList();
if (table.getColumnSortList().size() > 0) {
for (int colIdx = 0, sortPos = sortList.size(); colIdx < sortList.size(); colIdx++, sortPos--) {
ColumnSortInfo columnSortInfo = sortList.get(colIdx);
sortInfoByColumn.put(columnSortInfo.getColumn(), new ColumnSortInfoHolder(columnSortInfo, sortPos));
}
}
// Get information about the sorted column.
ColumnSortInfo sortedInfo = null;
boolean isSortAscending = false;
// Get the common style names.
Style style = table.getResources().style();
String className = isBuildingFooter() ? style.footer() : style.header();
String sortableStyle = " " + style.sortableHeader();
// Setup the first column.
Header<?> prevHeader = getHeader(0);
Column<T, ?> column = table.getColumn(0);
int prevColspan = 1;
boolean isSortable = false;
boolean isSorted = false;
StringBuilder classesBuilder = new StringBuilder(className);
classesBuilder.append(" ").append(isFooter ? style.firstColumnFooter() : style.firstColumnHeader());
if (!isFooter && column.isSortable()) {
isSortable = true;
sortedInfo = (sortInfoByColumn.get(column) != null) ? sortInfoByColumn.get(column).getColumnSortInfo() : null;
isSortAscending = (sortedInfo != null) ? sortedInfo.isAscending() : false;
isSorted = (sortedInfo != null);
}
// Loop through all column headers.
TableRowBuilder tr = startRow();
int curColumn;
for (curColumn = 1; curColumn < columnCount; curColumn++) {
Header<?> header = getHeader(curColumn);
if (header != prevHeader) {
// The header has changed, so append the previous one.
if (isSortable) {
classesBuilder.append(sortableStyle);
}
if (isSorted) {
classesBuilder.append(getSortStyle(style, isSortAscending));
}
appendExtraStyles(prevHeader, classesBuilder);
// Render the header.
TableCellBuilder th = tr.startTH().colSpan(prevColspan)
.className(classesBuilder.toString());
enableColumnHandlers(th, column);
if (prevHeader != null) {
// Build the header.
Context context = new Context(0, curColumn - prevColspan, prevHeader.getKey());
// Add div element with aria button role
if (isSortable) {
th.attribute("role", "button");
th.tabIndex(-1);
}
renderRichSortableHeader(th, context, prevHeader, isSorted, isSortAscending, sortInfoByColumn);
}
th.endTH();
// Reset the previous header.
prevHeader = header;
prevColspan = 1;
classesBuilder = new StringBuilder(className);
isSortable = false;
isSorted = false;
} else {
// Increment the colspan if the headers == each other.
prevColspan++;
}
column = table.getColumn(curColumn);
if (!isFooter && column.isSortable()) {
isSortable = true;
sortedInfo = (sortInfoByColumn.get(column) != null) ? sortInfoByColumn.get(column).getColumnSortInfo() : null;
isSortAscending = (sortedInfo != null) ? sortedInfo.isAscending() : false;
isSorted = (sortedInfo != null);
}
}
// Append the last header.
if (isSortable) {
classesBuilder.append(sortableStyle);
}
if (isSorted) {
classesBuilder.append(getSortStyle(style, isSortAscending));
}
classesBuilder.append(" ").append(
isFooter ? style.lastColumnFooter() : style.lastColumnHeader());
appendExtraStyles(prevHeader, classesBuilder);
// Render the last header.
TableCellBuilder th = tr.startTH().colSpan(prevColspan).className(classesBuilder.toString());
enableColumnHandlers(th, column);
if (prevHeader != null) {
Context context = new Context(0, curColumn - prevColspan, prevHeader.getKey());
renderRichSortableHeader(th, context, prevHeader, isSorted, isSortAscending, sortInfoByColumn);
}
th.endTH();
classesBuilder = new StringBuilder(style.header());
classesBuilder.append(" ").append(style.lastColumnHeader());
th = tr.startTH().className(classesBuilder.toString());
th.endTH();
// End the row.
tr.endTR();
return true;
}
/**
* Append the extra style names for the header.
*
* @param header
* the header that may contain extra styles, it can be null
* @param classesBuilder
* the string builder for the TD classes
*/
private <H> void appendExtraStyles(Header<H> header, StringBuilder classesBuilder) {
if (header == null) {
return;
}
String headerStyleNames = header.getHeaderStyleNames();
if (headerStyleNames != null) {
classesBuilder.append(" ").append(headerStyleNames);
}
}
private String getSortStyle(Style style, boolean isSortAscending) {
return isSortAscending ? style.sortedHeaderAscending() : style.sortedHeaderDescending();
}
/**
* Render a header, including a sort icon if the column is sortable and
* sorted.
*
* @param out
* the builder to render into
* @param header
* the header to render
* @param context
* the context of the header
* @param isSorted
* true if the column is sorted
* @param isSortAscending
* indicated the sort order, if sorted
*/
protected void renderRichSortableHeader(ElementBuilderBase<?> out,
Context context, Header<?> header, boolean isSorted,
boolean isSortAscending,
HashMap<Column<?, ?>, ColumnSortInfoHolder> sortIndexByColumn) {
AbstractCellTable<T> table = getTable();
ElementBuilderBase<?> headerContainer = out;
boolean posRight = LocaleInfo.getCurrentLocale().isRTL();
int iconWidth = 0;
int sortIndexWidth = 0;
if (isSorted) {
// Create an outer container to hold the icon and the header.
iconWidth = isSortAscending ? sortAscIconWidth : sortDescIconWidth;
int halfHeight = isSortAscending ? sortAscIconHalfHeight : sortDescIconHalfHeight;
DivBuilder outerDiv = out.startDiv();
StylesBuilder style = outerDiv.style().position(Position.RELATIVE).trustedProperty("zoom", "1");
style.endStyle();
// Add the icon.
DivBuilder imageHolder = outerDiv.startDiv();
style = outerDiv.style().position(Position.ABSOLUTE).top(50.0, Unit.PCT).lineHeight(0.0, Unit.PX).marginTop(-halfHeight, Unit.PX);
if (posRight) {
style.right(0, Unit.PX);
} else {
style.left(0, Unit.PX);
}
style.overflow(Overflow.VISIBLE).endStyle();
imageHolder.html(getSortIcon(isSortAscending));
imageHolder.endDiv();
if (table.getColumnSortList().size() > 0) {
DivBuilder sortIndexHolder = outerDiv.startDiv();
style = sortIndexHolder.style().position(Position.ABSOLUTE).top(0.0, Unit.PCT);
sortIndexWidth = iconWidth - 2;
if (posRight) {
style.right(sortIndexWidth, Unit.PX);
} else {
style.left(sortIndexWidth, Unit.PX);
}
Column<T, ?> column = table.getColumn(context.getColumn());
String sortIdx = String.valueOf(sortIndexByColumn.get(column).getSortIndex());
sortIndexHolder.html(SafeHtmlUtils.fromTrustedString(sortIdx));
sortIndexHolder.endDiv();
}
// Create the header wrapper.
headerContainer = outerDiv.startDiv();
}
StylesBuilder style = headerContainer.style().position(Position.RELATIVE);
if (posRight) {
style.paddingRight(iconWidth + sortIndexWidth + 7, Unit.PX);
} else {
style.paddingLeft(iconWidth + sortIndexWidth + 7, Unit.PX);
}
style.endStyle();
// Build the header.
renderHeader(headerContainer, context, header);
// Close the elements used for the sort icon.
if (isSorted) {
headerContainer.endDiv(); // headerContainer.
headerContainer.endDiv(); // outerDiv
}
}
private SafeHtml getSortIcon(boolean isAscending) {
AbstractCellTable<T> table = getTable();
if (isAscending) {
if (sortAscIconHtml == null) {
AbstractImagePrototype proto = AbstractImagePrototype.create(table.getResources().sortAscending());
sortAscIconHtml = SafeHtmlUtils.fromTrustedString(proto.getHTML());
}
return sortAscIconHtml;
} else {
if (sortDescIconHtml == null) {
AbstractImagePrototype proto = AbstractImagePrototype.create(table.getResources().sortDescending());
sortDescIconHtml = SafeHtmlUtils.fromTrustedString(proto.getHTML());
}
return sortDescIconHtml;
}
}
}
你这样设置
CellTable<Contact> table = new CellTable<Contact>();
table.setHeaderBuilder(new MultiSortHeaderOrFooterBuilder<TableComponent.Contact>(table, false));