/* * Copyright 2014 Red Hat, Inc. and/or its affiliates. * * 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 org.dashbuilder.renderer.client.table; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import com.google.gwt.cell.client.TextCell; import com.google.gwt.cell.client.ValueUpdater; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.ColumnSortEvent; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.AsyncDataProvider; import com.google.gwt.view.client.HasData; import org.dashbuilder.dataset.ColumnType; import org.dashbuilder.dataset.sort.SortOrder; import org.dashbuilder.displayer.client.AbstractDisplayerView; import org.dashbuilder.renderer.client.resources.i18n.TableConstants; import org.gwtbootstrap3.client.ui.Label; import org.uberfire.client.callbacks.Callback; import org.uberfire.ext.widgets.common.client.tables.PagedTable; import static com.google.gwt.dom.client.BrowserEvents.*; public class TableDisplayerView extends AbstractDisplayerView<TableDisplayer> implements TableDisplayer.View { protected HTML titleHtml = new HTML(); protected HorizontalPanel filterPanel; protected TableProvider tableProvider = new TableProvider(); protected VerticalPanel rootPanel = new VerticalPanel(); protected PagedTable<Integer> table; @Override public void init(TableDisplayer presenter) { super.setPresenter(presenter); super.setVisualization(rootPanel); rootPanel.add(titleHtml); } @Override public void showTitle(String title) { titleHtml.setText(title); } @Override public String getGroupsTitle() { return TableConstants.INSTANCE.tableDisplayer_groupsTitle(); } @Override public String getColumnsTitle() { return TableConstants.INSTANCE.tableDisplayer_columnsTitle(); } @Override public void createTable(int pageSize) { table = new PagedTable<Integer>(pageSize); table.pageSizesSelector.setVisible(false); table.setEmptyTableCaption(TableConstants.INSTANCE.tableDisplayer_noDataAvailable()); tableProvider.addDataDisplay(table); rootPanel.add(table); } @Override public void redrawTable() { table.redraw(); } @Override public void setWidth(int width) { table.setWidth(width + "px"); } @Override public void setSortEnabled(boolean enabled) { table.addColumnSortHandler(new ColumnSortEvent.AsyncHandler(table) { public void onColumnSort(ColumnSortEvent event) { String column = ((DataColumnCell) event.getColumn().getCell()).columnId; SortOrder order = event.isSortAscending() ? SortOrder.ASCENDING : SortOrder.DESCENDING; getPresenter().sortBy(column, order); } }); } @Override public void setTotalRows(int rows) { table.setRowCount(rows, true); } @Override public void setPagerEnabled(boolean enabled) { table.pager.setVisible(enabled); int rows = table.getRowCount() > table.getPageSize() ? table.getPageSize() : table.getRowCount(); table.setHeight(calculateHeight(rows) + "px"); } @Override public void addColumn(ColumnType columnType, String columnId, String columnName, int index, boolean selectEnabled, boolean sortEnabled) { Column<Integer,?> column = createColumn(columnType, columnId, selectEnabled, index); if (column != null) { column.setSortable(sortEnabled); table.addColumn(column, columnName); } } @Override public void clearFilterStatus() { if (filterPanel != null) { table.getLeftToolbar().remove(filterPanel); filterPanel = null; } } @Override public void addFilterValue(String value) { if (filterPanel == null) { filterPanel = new HorizontalPanel(); filterPanel.getElement().setAttribute("cellpadding", "2"); table.getLeftToolbar().add(filterPanel); } filterPanel.add(new Label(value)); } @Override public void addFilterReset() { Anchor anchor = new Anchor(TableConstants.INSTANCE.tableDisplayer_reset()); filterPanel.add(anchor); anchor.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { getPresenter().filterReset(); } }); } @Override public void gotoFirstPage() { tableProvider.gotoFirstPage(); } @Override public int getLastOffset() { return tableProvider.lastOffset; } // Table internals public int calculateHeight(int rows) { int rowHeight = 39 - rows; int offset = 20 - rows; rowHeight = rowHeight < 30 ? 30 : rowHeight; offset = offset < 0 ? 0 : offset; return offset + (rowHeight * (rows == 0 ? 1 : rows)); } protected Column<Integer,?> createColumn(ColumnType type, String columnId, final boolean selectable, final int columnNumber) { switch (type) { case LABEL: return new Column<Integer,String>( new DataColumnCell(columnId, selectable)) { public String getValue(Integer row) { return getPresenter().formatValue(row, columnNumber); } }; case NUMBER: case DATE: case TEXT: return new Column<Integer,String>( new DataColumnCell(columnId, selectable)) { public String getValue(Integer row) { return getPresenter().formatValue(row, columnNumber); } }; } return null; } protected class DataColumnCell extends TextCell { private String columnId; private boolean selectable = false; DataColumnCell(String columnId, boolean selectable) { this.columnId = columnId; this.selectable = selectable; } @Override public Set<String> getConsumedEvents() { Set<String> consumedEvents = new HashSet<String>(); if (selectable) { consumedEvents.add(CLICK); } return consumedEvents; } @Override public void onBrowserEvent(Context context, Element parent, String value, NativeEvent event, ValueUpdater<String> valueUpdater) { if (selectable) { int rowIndexInPage = context.getIndex() - table.getPageStart(); getPresenter().selectCell(columnId, rowIndexInPage); } } } /** * The table data provider */ protected class TableProvider extends AsyncDataProvider<Integer> { protected int lastOffset = 0; protected List<Integer> getCurrentPageRows(HasData<Integer> display) { final int start = ((PagedTable) display).getPageStart(); int pageSize = ((PagedTable) display).getPageSize(); int end = start + pageSize; if (end > table.getRowCount()) { end = table.getRowCount(); } final List<Integer> rows = new ArrayList<Integer>(end-start); for (int i = 0; i < end-start; i++) { rows.add(i); } return rows; } /** * Both filter & sort invoke this method from redraw() */ public void gotoFirstPage() { // Avoid fetching the data set again lastOffset = 0; // This calls internally to onRangeChanged() when the page changes table.pager.setPage(0); int start = table.getPageStart(); final List<Integer> rows = getCurrentPageRows(table); updateRowData(start, rows); } /** * Invoked from createWidget just after the data set has been fetched. */ public void addDataDisplay(HasData<Integer> display) { // Avoid fetching the data set again lastOffset = 0; // This calls internally to onRangeChanged() super.addDataDisplay(display); } /** * This is invoked internally by the PagedTable on navigation actions. */ protected void onRangeChanged(final HasData<Integer> display) { int start = ((PagedTable) display).getPageStart(); final List<Integer> rows = getCurrentPageRows(display); if (lastOffset == start) { updateRowData(lastOffset, rows); } else { lastOffset = start; getPresenter().lookupCurrentPage(new Callback<Integer>() { public void callback(Integer rowsFetched) { updateRowData(lastOffset, rows); table.setHeight(calculateHeight(rowsFetched) + "px"); } }); } } } }