| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.user.cellview.client; |
| |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.dom.client.Document; |
| import com.google.gwt.dom.client.Element; |
| import com.google.gwt.dom.client.Style.Display; |
| import com.google.gwt.dom.client.Style.Overflow; |
| import com.google.gwt.dom.client.Style.TableLayout; |
| import com.google.gwt.dom.client.Style.Unit; |
| import com.google.gwt.dom.client.TableColElement; |
| import com.google.gwt.dom.client.TableElement; |
| import com.google.gwt.dom.client.TableSectionElement; |
| import com.google.gwt.event.dom.client.ScrollEvent; |
| import com.google.gwt.event.dom.client.ScrollHandler; |
| import com.google.gwt.resources.client.ClientBundle; |
| import com.google.gwt.resources.client.CssResource; |
| import com.google.gwt.resources.client.CssResource.ImportedWithPrefix; |
| import com.google.gwt.resources.client.ImageResource; |
| import com.google.gwt.resources.client.ImageResource.ImageOptions; |
| import com.google.gwt.user.cellview.client.LoadingStateChangeEvent.LoadingState; |
| import com.google.gwt.user.client.ui.CustomScrollPanel; |
| import com.google.gwt.user.client.ui.FlexTable; |
| import com.google.gwt.user.client.ui.HeaderPanel; |
| import com.google.gwt.user.client.ui.Image; |
| import com.google.gwt.user.client.ui.RequiresResize; |
| import com.google.gwt.user.client.ui.ScrollPanel; |
| import com.google.gwt.user.client.ui.SimplePanel; |
| import com.google.gwt.user.client.ui.Widget; |
| import com.google.gwt.view.client.ProvidesKey; |
| |
| /** |
| * A tabular view with a fixed header and footer section and a scrollable data |
| * section in the middle. This widget supports paging and columns. |
| * |
| * <p> |
| * <h3>Columns</h3> The {@link Column} class defines the |
| * {@link com.google.gwt.cell.client.Cell} used to render a column. Implement |
| * {@link Column#getValue(Object)} to retrieve the field value from the row |
| * object that will be rendered in the {@link com.google.gwt.cell.client.Cell}. |
| * </p> |
| * |
| * <p> |
| * <h3>Headers and Footers</h3> A {@link Header} can be placed at the top |
| * (header) or bottom (footer) of the {@link DataGrid}. You can specify a header |
| * as text using {@link #addColumn(Column, String)}, or you can create a custom |
| * {@link Header} that can change with the value of the cells, such as a column |
| * total. The {@link Header} will be rendered every time the row data changes or |
| * the table is redrawn. If you pass the same header instance (==) into adjacent |
| * columns, the header will span the columns. |
| * </p> |
| * |
| * <p> |
| * <h3>Examples</h3> |
| * <dl> |
| * <dt>Trivial example</dt> |
| * <dd>{@example com.google.gwt.examples.cellview.CellTableExample}</dd> |
| * <dt>FieldUpdater example</dt> |
| * <dd>{@example com.google.gwt.examples.cellview.CellTableFieldUpdaterExample}</dd> |
| * <dt>Key provider example</dt> |
| * <dd>{@example com.google.gwt.examples.view.KeyProviderExample}</dd> |
| * </dl> |
| * </p> |
| * |
| * @param <T> the data type of each row |
| */ |
| public class DataGrid<T> extends AbstractCellTable<T> implements RequiresResize { |
| |
| /** |
| * A ClientBundle that provides images for this widget. |
| */ |
| public interface Resources extends ClientBundle { |
| /** |
| * The loading indicator used while the table is waiting for data. |
| */ |
| @Source("cellTableLoading.gif") |
| @ImageOptions(flipRtl = true) |
| ImageResource dataGridLoading(); |
| |
| /** |
| * Icon used when a column is sorted in ascending order. |
| */ |
| @Source("sortAscending.png") |
| @ImageOptions(flipRtl = true) |
| ImageResource dataGridSortAscending(); |
| |
| /** |
| * Icon used when a column is sorted in descending order. |
| */ |
| @Source("sortDescending.png") |
| @ImageOptions(flipRtl = true) |
| ImageResource dataGridSortDescending(); |
| |
| /** |
| * The styles used in this widget. |
| */ |
| @Source(Style.DEFAULT_CSS) |
| Style dataGridStyle(); |
| } |
| |
| /** |
| * Styles used by this widget. |
| */ |
| @ImportedWithPrefix("gwt-CellTable") |
| public interface Style extends CssResource { |
| /** |
| * The path to the default CSS styles used by this resource. |
| */ |
| String DEFAULT_CSS = "com/google/gwt/user/cellview/client/DataGrid.css"; |
| |
| /** |
| * Applied to every cell. |
| */ |
| String dataGridCell(); |
| |
| /** |
| * Applied to even rows. |
| */ |
| String dataGridEvenRow(); |
| |
| /** |
| * Applied to cells in even rows. |
| */ |
| String dataGridEvenRowCell(); |
| |
| /** |
| * Applied to the first column. |
| */ |
| String dataGridFirstColumn(); |
| |
| /** |
| * Applied to the first column footers. |
| */ |
| String dataGridFirstColumnFooter(); |
| |
| /** |
| * Applied to the first column headers. |
| */ |
| String dataGridFirstColumnHeader(); |
| |
| /** |
| * Applied to footers cells. |
| */ |
| String dataGridFooter(); |
| |
| /** |
| * Applied to headers cells. |
| */ |
| String dataGridHeader(); |
| |
| /** |
| * Applied to the hovered row. |
| */ |
| String dataGridHoveredRow(); |
| |
| /** |
| * Applied to the cells in the hovered row. |
| */ |
| String dataGridHoveredRowCell(); |
| |
| /** |
| * Applied to the keyboard selected cell. |
| */ |
| String dataGridKeyboardSelectedCell(); |
| |
| /** |
| * Applied to the keyboard selected row. |
| */ |
| String dataGridKeyboardSelectedRow(); |
| |
| /** |
| * Applied to the cells in the keyboard selected row. |
| */ |
| String dataGridKeyboardSelectedRowCell(); |
| |
| /** |
| * Applied to the last column. |
| */ |
| String dataGridLastColumn(); |
| |
| /** |
| * Applied to the last column footers. |
| */ |
| String dataGridLastColumnFooter(); |
| |
| /** |
| * Applied to the last column headers. |
| */ |
| String dataGridLastColumnHeader(); |
| |
| /** |
| * Applied to odd rows. |
| */ |
| String dataGridOddRow(); |
| |
| /** |
| * Applied to cells in odd rows. |
| */ |
| String dataGridOddRowCell(); |
| |
| /** |
| * Applied to selected rows. |
| */ |
| String dataGridSelectedRow(); |
| |
| /** |
| * Applied to cells in selected rows. |
| */ |
| String dataGridSelectedRowCell(); |
| |
| /** |
| * Applied to header cells that are sortable. |
| */ |
| String dataGridSortableHeader(); |
| |
| /** |
| * Applied to header cells that are sorted in ascending order. |
| */ |
| String dataGridSortedHeaderAscending(); |
| |
| /** |
| * Applied to header cells that are sorted in descending order. |
| */ |
| String dataGridSortedHeaderDescending(); |
| |
| /** |
| * Applied to the table. |
| */ |
| String dataGridWidget(); |
| } |
| |
| /** |
| * A simple widget wrapper around a table element. |
| */ |
| static class TableWidget extends Widget { |
| private final TableColElement colgroup; |
| private TableSectionElement section; |
| private final TableElement tableElem; |
| |
| public TableWidget() { |
| // Setup the table. |
| tableElem = Document.get().createTableElement(); |
| tableElem.setCellSpacing(0); |
| tableElem.getStyle().setTableLayout(TableLayout.FIXED); |
| tableElem.getStyle().setWidth(100.0, Unit.PCT); |
| setElement(tableElem); |
| |
| // Add the colgroup. |
| colgroup = Document.get().createColGroupElement(); |
| tableElem.appendChild(colgroup); |
| } |
| |
| public void addColumnStyleName(int index, String styleName) { |
| ensureTableColElement(index).addClassName(styleName); |
| } |
| |
| /** |
| * Get the {@link TableColElement} at the specified index, creating it if |
| * necessary. |
| * |
| * @param index the column index |
| * @return the {@link TableColElement} |
| */ |
| public TableColElement ensureTableColElement(int index) { |
| // Ensure that we have enough columns. |
| for (int i = colgroup.getChildCount(); i <= index; i++) { |
| colgroup.appendChild(Document.get().createColElement()); |
| } |
| return colgroup.getChild(index).cast(); |
| } |
| |
| public void removeColumnStyleName(int index, String styleName) { |
| if (index >= colgroup.getChildCount()) { |
| return; |
| } |
| ensureTableColElement(index).removeClassName(styleName); |
| } |
| |
| /** |
| * Hide columns that aren't used in the table. |
| * |
| * @param start the first unused column index |
| */ |
| void hideUnusedColumns(int start) { |
| /* |
| * Set the width to zero for all col elements that appear after the last |
| * column. Clearing the width would cause it to take up the remaining |
| * width in a fixed layout table. |
| */ |
| int colCount = colgroup.getChildCount(); |
| for (int i = start; i < colCount; i++) { |
| setColumnWidth(i, "0px"); |
| } |
| } |
| |
| void setColumnWidth(int column, String width) { |
| if (width == null) { |
| ensureTableColElement(column).getStyle().clearWidth(); |
| } else { |
| ensureTableColElement(column).getStyle().setProperty("width", width); |
| } |
| } |
| } |
| |
| /** |
| * Adapter class to convert {@link Resources} to |
| * {@link AbstractCellTable.Resources}. |
| */ |
| private static class ResourcesAdapter implements AbstractCellTable.Resources { |
| |
| private final DataGrid.Resources resources; |
| private final StyleAdapter style; |
| |
| public ResourcesAdapter(DataGrid.Resources resources) { |
| this.resources = resources; |
| this.style = new StyleAdapter(resources.dataGridStyle()); |
| } |
| |
| @Override |
| public ImageResource sortAscending() { |
| return resources.dataGridSortAscending(); |
| } |
| |
| @Override |
| public ImageResource sortDescending() { |
| return resources.dataGridSortDescending(); |
| } |
| |
| @Override |
| public AbstractCellTable.Style style() { |
| return style; |
| } |
| } |
| |
| /** |
| * Adapter class to convert {@link Style} to {@link AbstractCellTable.Style}. |
| */ |
| private static class StyleAdapter implements AbstractCellTable.Style { |
| private final DataGrid.Style style; |
| |
| public StyleAdapter(DataGrid.Style style) { |
| this.style = style; |
| } |
| |
| @Override |
| public String cell() { |
| return style.dataGridCell(); |
| } |
| |
| @Override |
| public String evenRow() { |
| return style.dataGridEvenRow(); |
| } |
| |
| @Override |
| public String evenRowCell() { |
| return style.dataGridEvenRowCell(); |
| } |
| |
| @Override |
| public String firstColumn() { |
| return style.dataGridFirstColumn(); |
| } |
| |
| @Override |
| public String firstColumnFooter() { |
| return style.dataGridFirstColumnFooter(); |
| } |
| |
| @Override |
| public String firstColumnHeader() { |
| return style.dataGridFirstColumnHeader(); |
| } |
| |
| @Override |
| public String footer() { |
| return style.dataGridFooter(); |
| } |
| |
| @Override |
| public String header() { |
| return style.dataGridHeader(); |
| } |
| |
| @Override |
| public String hoveredRow() { |
| return style.dataGridHoveredRow(); |
| } |
| |
| @Override |
| public String hoveredRowCell() { |
| return style.dataGridHoveredRowCell(); |
| } |
| |
| @Override |
| public String keyboardSelectedCell() { |
| return style.dataGridKeyboardSelectedCell(); |
| } |
| |
| @Override |
| public String keyboardSelectedRow() { |
| return style.dataGridKeyboardSelectedRow(); |
| } |
| |
| @Override |
| public String keyboardSelectedRowCell() { |
| return style.dataGridKeyboardSelectedRowCell(); |
| } |
| |
| @Override |
| public String lastColumn() { |
| return style.dataGridLastColumn(); |
| } |
| |
| @Override |
| public String lastColumnFooter() { |
| return style.dataGridLastColumnFooter(); |
| } |
| |
| @Override |
| public String lastColumnHeader() { |
| return style.dataGridLastColumnHeader(); |
| } |
| |
| @Override |
| public String oddRow() { |
| return style.dataGridOddRow(); |
| } |
| |
| @Override |
| public String oddRowCell() { |
| return style.dataGridOddRowCell(); |
| } |
| |
| @Override |
| public String selectedRow() { |
| return style.dataGridSelectedRow(); |
| } |
| |
| @Override |
| public String selectedRowCell() { |
| return style.dataGridSelectedRowCell(); |
| } |
| |
| @Override |
| public String sortableHeader() { |
| return style.dataGridSortableHeader(); |
| } |
| |
| @Override |
| public String sortedHeaderAscending() { |
| return style.dataGridSortedHeaderAscending(); |
| } |
| |
| @Override |
| public String sortedHeaderDescending() { |
| return style.dataGridSortedHeaderDescending(); |
| } |
| |
| @Override |
| public String widget() { |
| return style.dataGridWidget(); |
| } |
| } |
| |
| private static final int DEFAULT_PAGESIZE = 50; |
| private static Resources DEFAULT_RESOURCES; |
| |
| /** |
| * Create the default loading indicator using the loading image in the |
| * specified {@link Resources}. |
| * |
| * @param resources the resources containing the loading image |
| * @return a widget loading indicator |
| */ |
| private static Widget createDefaultLoadingIndicator(Resources resources) { |
| ImageResource loadingImg = resources.dataGridLoading(); |
| if (loadingImg == null) { |
| return null; |
| } |
| Image image = new Image(loadingImg); |
| image.getElement().getStyle().setMarginTop(30.0, Unit.PX); |
| return image; |
| } |
| |
| private static Resources getDefaultResources() { |
| if (DEFAULT_RESOURCES == null) { |
| DEFAULT_RESOURCES = GWT.create(Resources.class); |
| } |
| return DEFAULT_RESOURCES; |
| } |
| |
| final TableWidget tableData; |
| final TableWidget tableFooter; |
| final TableWidget tableHeader; |
| private final FlexTable emptyTableWidgetContainer; |
| private final HeaderPanel headerPanel; |
| private final FlexTable loadingIndicatorContainer; |
| private final Style style; |
| private final Element tableDataContainer; |
| private final ScrollPanel tableDataScroller; |
| private final SimplePanel tableFooterContainer; |
| private final Element tableFooterScroller; |
| private final SimplePanel tableHeaderContainer; |
| private final Element tableHeaderScroller; |
| |
| /** |
| * Constructs a table with a default page size of 50. |
| */ |
| public DataGrid() { |
| this(DEFAULT_PAGESIZE); |
| } |
| |
| /** |
| * Constructs a table with the given page size. |
| * |
| * @param pageSize the page size |
| */ |
| public DataGrid(final int pageSize) { |
| this(pageSize, getDefaultResources()); |
| } |
| |
| /** |
| * Constructs a table with the given page size and the given |
| * {@link ProvidesKey key provider}. |
| * |
| * @param pageSize the page size |
| * @param keyProvider an instance of ProvidesKey<T>, or null if the record |
| * object should act as its own key |
| */ |
| public DataGrid(int pageSize, ProvidesKey<T> keyProvider) { |
| this(pageSize, getDefaultResources(), keyProvider); |
| } |
| |
| /** |
| * Constructs a table with the given page size with the specified |
| * {@link Resources}. |
| * |
| * @param pageSize the page size |
| * @param resources the resources to use for this widget |
| */ |
| public DataGrid(int pageSize, Resources resources) { |
| this(pageSize, resources, null); |
| } |
| |
| /** |
| * Constructs a table with the given page size, the specified |
| * {@link Resources}, and the given key provider. |
| * |
| * @param pageSize the page size |
| * @param resources the resources to use for this widget |
| * @param keyProvider an instance of ProvidesKey<T>, or null if the record |
| * object should act as its own key |
| */ |
| public DataGrid(int pageSize, Resources resources, ProvidesKey<T> keyProvider) { |
| this(pageSize, resources, keyProvider, createDefaultLoadingIndicator(resources)); |
| } |
| |
| /** |
| * Constructs a table with the given page size, the specified |
| * {@link Resources}, and the given key provider. |
| * |
| * @param pageSize the page size |
| * @param resources the resources to use for this widget |
| * @param keyProvider an instance of ProvidesKey<T>, or null if the record |
| * object should act as its own key |
| * @param loadingIndicator the widget to use as a loading indicator, or null |
| * to disable |
| */ |
| public DataGrid(int pageSize, Resources resources, ProvidesKey<T> keyProvider, |
| Widget loadingIndicator) { |
| super(new HeaderPanel(), pageSize, new ResourcesAdapter(resources), keyProvider); |
| headerPanel = (HeaderPanel) getWidget(); |
| |
| // Inject the stylesheet. |
| this.style = resources.dataGridStyle(); |
| this.style.ensureInjected(); |
| |
| // Create the header and footer widgets.. |
| tableHeader = new TableWidget(); |
| tableHeader.section = tableHeader.tableElem.createTHead(); |
| tableFooter = new TableWidget(); |
| tableFooter.section = tableFooter.tableElem.createTFoot(); |
| |
| /* |
| * Wrap the header and footer widgets in a div because we cannot set the |
| * min-width of a table element. We set the width/min-width of the div |
| * container instead. |
| */ |
| tableHeaderContainer = new SimplePanel(tableHeader); |
| tableFooterContainer = new SimplePanel(tableFooter); |
| |
| /* |
| * Get the element that wraps the container so we can adjust its scroll |
| * position. |
| */ |
| headerPanel.setHeaderWidget(tableHeaderContainer); |
| tableHeaderScroller = tableHeaderContainer.getElement().getParentElement(); |
| headerPanel.setFooterWidget(tableFooterContainer); |
| tableFooterScroller = tableFooterContainer.getElement().getParentElement(); |
| |
| /* |
| * Set overflow to hidden on the scrollable elements so we can change the |
| * scrollLeft position. |
| */ |
| tableHeaderScroller.getStyle().setOverflow(Overflow.HIDDEN); |
| tableFooterScroller.getStyle().setOverflow(Overflow.HIDDEN); |
| |
| // Create the body. |
| tableData = new TableWidget(); |
| if (tableData.tableElem.getTBodies().getLength() > 0) { |
| tableData.section = tableData.tableElem.getTBodies().getItem(0); |
| } else { |
| tableData.section = Document.get().createTBodyElement(); |
| tableData.tableElem.appendChild(tableData.section); |
| } |
| tableDataScroller = new CustomScrollPanel(tableData); |
| tableDataScroller.setHeight("100%"); |
| headerPanel.setContentWidget(tableDataScroller); |
| tableDataContainer = tableData.getElement().getParentElement(); |
| |
| /* |
| * CustomScrollPanel applies the inline block style to the container |
| * element, but we want the container to fill the available width. |
| */ |
| tableDataContainer.getStyle().setDisplay(Display.BLOCK); |
| |
| /* |
| * Create the containers for the empty table message and loading indicator. |
| * The containers are centered tables that contain one cell, which aligns |
| * the widget in the center of the panel. |
| */ |
| emptyTableWidgetContainer = new FlexTable(); |
| emptyTableWidgetContainer.getElement().setAttribute("align", "center"); |
| loadingIndicatorContainer = new FlexTable(); |
| loadingIndicatorContainer.getElement().setAttribute("align", "center"); |
| |
| // Set the loading indicator. |
| setLoadingIndicator(loadingIndicator); // Can be null. |
| |
| // Synchronize the scroll positions of the three tables. |
| tableDataScroller.addScrollHandler(new ScrollHandler() { |
| @Override |
| public void onScroll(ScrollEvent event) { |
| int scrollLeft = tableDataScroller.getHorizontalScrollPosition(); |
| tableHeaderScroller.setScrollLeft(scrollLeft); |
| tableFooterScroller.setScrollLeft(scrollLeft); |
| } |
| }); |
| } |
| |
| /** |
| * Constructs a table with a default page size of 50, and the given |
| * {@link ProvidesKey key provider}. |
| * |
| * @param keyProvider an instance of ProvidesKey<T>, or null if the record |
| * object should act as its own key |
| */ |
| public DataGrid(ProvidesKey<T> keyProvider) { |
| this(DEFAULT_PAGESIZE, keyProvider); |
| } |
| |
| @Override |
| public void addColumnStyleName(int index, String styleName) { |
| tableHeader.addColumnStyleName(index, styleName); |
| tableFooter.addColumnStyleName(index, styleName); |
| tableData.addColumnStyleName(index, styleName); |
| } |
| |
| /** |
| * Clear the width of the tables in this widget, which causes them to fill the |
| * available width. |
| * |
| * <p> |
| * The table width is not the same as the width of this widget. If the tables |
| * are narrower than this widget, there will be a gap between the table and |
| * the edge of the widget. If the tables are wider than this widget, a |
| * horizontal scrollbar will appear so the user can scroll horizontally. |
| * </p> |
| * |
| * @see #setMinimumTableWidth(double, Unit) |
| * @see #setTableWidth(double, Unit) |
| */ |
| public void clearTableWidth() { |
| tableHeaderContainer.getElement().getStyle().clearWidth(); |
| tableFooterContainer.getElement().getStyle().clearWidth(); |
| tableDataContainer.getStyle().clearWidth(); |
| } |
| |
| @Override |
| public void onResize() { |
| headerPanel.onResize(); |
| } |
| |
| @Override |
| public void removeColumnStyleName(int index, String styleName) { |
| tableHeader.removeColumnStyleName(index, styleName); |
| tableFooter.removeColumnStyleName(index, styleName); |
| tableData.removeColumnStyleName(index, styleName); |
| } |
| |
| @Override |
| public void setEmptyTableWidget(Widget widget) { |
| emptyTableWidgetContainer.setWidget(0, 0, widget); |
| super.setEmptyTableWidget(widget); |
| } |
| |
| @Override |
| public void setLoadingIndicator(Widget widget) { |
| loadingIndicatorContainer.setWidget(0, 0, widget); |
| super.setLoadingIndicator(widget); |
| } |
| |
| /** |
| * Set the minimum width of the tables in this widget. If the widget become |
| * narrower than the minimum width, a horizontal scrollbar will appear so the |
| * user can scroll horizontally. |
| * |
| * <p> |
| * Note that this method is not supported in IE6 and earlier versions of IE. |
| * </p> |
| * |
| * @param value the width |
| * @param unit the unit of the width |
| * @see #setTableWidth(double, Unit) |
| */ |
| public void setMinimumTableWidth(double value, Unit unit) { |
| /* |
| * The min-width style attribute doesn't apply to tables, so we set the |
| * min-width of the element that contains the table instead. The table width |
| * is fixed at 100%. |
| */ |
| tableHeaderContainer.getElement().getStyle().setProperty("minWidth", value, unit); |
| tableFooterContainer.getElement().getStyle().setProperty("minWidth", value, unit); |
| tableDataContainer.getStyle().setProperty("minWidth", value, unit); |
| } |
| |
| /** |
| * Set the width of the tables in this widget. By default, the width is not |
| * set and the tables take the available width. |
| * |
| * <p> |
| * The table width is not the same as the width of this widget. If the tables |
| * are narrower than this widget, there will be a gap between the table and |
| * the edge of the widget. If the tables are wider than this widget, a |
| * horizontal scrollbar will appear so the user can scroll horizontally. |
| * </p> |
| * |
| * <p> |
| * If your table has many columns and you want to ensure that the columns are |
| * not truncated, you probably want to use |
| * {@link #setMinimumTableWidth(double, Unit)} instead. That will ensure that |
| * the table is wide enough, but it will still allow the table to expand to |
| * 100% if the user has a wide screen. |
| * </p> |
| * |
| * <p> |
| * Note that setting the width in percentages will not work on older versions |
| * of IE because it does not account for scrollbars when calculating the |
| * width. |
| * </p> |
| * |
| * @param value the width |
| * @param unit the unit of the width |
| * @see #setMinimumTableWidth(double, Unit) |
| */ |
| public void setTableWidth(double value, Unit unit) { |
| /* |
| * The min-width style attribute doesn't apply to tables, so we set the |
| * min-width of the element that contains the table instead. For |
| * consistency, we set the width of the container as well. |
| */ |
| tableHeaderContainer.getElement().getStyle().setWidth(value, unit); |
| tableFooterContainer.getElement().getStyle().setWidth(value, unit); |
| tableDataContainer.getStyle().setWidth(value, unit); |
| } |
| |
| @Override |
| protected void doSetColumnWidth(int column, String width) { |
| if (width == null) { |
| tableData.ensureTableColElement(column).getStyle().clearWidth(); |
| tableHeader.ensureTableColElement(column).getStyle().clearWidth(); |
| tableFooter.ensureTableColElement(column).getStyle().clearWidth(); |
| } else { |
| tableData.ensureTableColElement(column).getStyle().setProperty("width", width); |
| tableHeader.ensureTableColElement(column).getStyle().setProperty("width", width); |
| tableFooter.ensureTableColElement(column).getStyle().setProperty("width", width); |
| } |
| } |
| |
| @Override |
| protected void doSetHeaderVisible(boolean isFooter, boolean isVisible) { |
| if (isFooter) { |
| headerPanel.setFooterWidget(isVisible ? tableFooterContainer : null); |
| } else { |
| headerPanel.setHeaderWidget(isVisible ? tableHeaderContainer : null); |
| } |
| } |
| |
| @Override |
| protected TableSectionElement getTableBodyElement() { |
| return tableData.section; |
| } |
| |
| @Override |
| protected TableSectionElement getTableFootElement() { |
| return tableFooter.section; |
| } |
| |
| @Override |
| protected TableSectionElement getTableHeadElement() { |
| return tableHeader.section; |
| } |
| |
| /** |
| * Called when the loading state changes. |
| * |
| * @param state the new loading state |
| */ |
| @Override |
| protected void onLoadingStateChanged(LoadingState state) { |
| Widget message = tableData; |
| if (state == LoadingState.LOADING) { |
| // Loading indicator. |
| message = loadingIndicatorContainer; |
| } else if (state == LoadingState.LOADED && getPresenter().isEmpty()) { |
| // Empty table. |
| message = emptyTableWidgetContainer; |
| } |
| |
| // Switch out the message to display. |
| tableDataScroller.setWidget(message); |
| |
| // Fire an event. |
| super.onLoadingStateChanged(state); |
| } |
| |
| @Override |
| protected void refreshColumnWidths() { |
| super.refreshColumnWidths(); |
| |
| // Hide unused col elements in the colgroup. |
| int columnCount = getColumnCount(); |
| tableHeader.hideUnusedColumns(columnCount); |
| tableData.hideUnusedColumns(columnCount); |
| tableFooter.hideUnusedColumns(columnCount); |
| } |
| } |