org.glom.web.client.ui.details.RelatedListTable.java Source code

Java tutorial

Introduction

Here is the source code for org.glom.web.client.ui.details.RelatedListTable.java

Source

/*
 * Copyright (C) 2011 Openismus GmbH
 *
 * This file is part of GWT-Glom.
 *
 * GWT-Glom is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * GWT-Glom is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with GWT-Glom.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.glom.web.client.ui.details;

import java.util.ArrayList;

import org.glom.web.client.OnlineGlomServiceAsync;
import org.glom.web.client.ui.OnlineGlomConstants;
import org.glom.web.client.ui.cell.NavigationButtonCell;
import org.glom.web.client.ui.list.ListTable;
import org.glom.web.shared.DataItem;
import org.glom.web.shared.TypedDataItem;
import org.glom.web.shared.libglom.layout.LayoutItemPortal;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortList;
import com.google.gwt.user.cellview.client.ColumnSortList.ColumnSortInfo;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.RowCountChangeEvent;

/**
 *
 */
public class RelatedListTable extends ListTable {

    // OnlineGlomConstants.java is generated in the target/ directory,
    // from OnlineGlomConstants.properties
    // by the gwt-maven-plugin's i18n (mvn:i18n) goal.
    private final OnlineGlomConstants constants = GWT.create(OnlineGlomConstants.class);

    // These represent the minimum and maximum number of rows in the cell table not the number of rows with data.
    private static final int MAX_TABLE_ROWS = 5;
    private static final int MIN_TABLE_ROWS = MAX_TABLE_ROWS;

    private final TypedDataItem foreignKeyValue;
    private LayoutItemPortal portal = null;
    private int numNonEmptyRows = 0;

    private final static int expectedHeight = initializeExepectedHeight();

    public RelatedListTable(final String documentID, final String tableName,
            final LayoutItemPortal layoutItemPortal, final TypedDataItem foreignKeyValue,
            final NavigationButtonCell navigationButtonCell) {

        super(documentID);
        super.tableName = tableName;

        // These variables need to be set before the createCellTable() method is called so that the data provider can
        // use them.
        this.foreignKeyValue = foreignKeyValue;
        this.portal = layoutItemPortal;

        createCellTable(layoutItemPortal, tableName, MAX_TABLE_ROWS, constants.open(), navigationButtonCell);

        // The FixedLayout property tells the browser that we want to manually specify the column widths and don't want
        // the table to overflow it's container. Browsers will make columns with equal widths since we're currently not
        // manally specifying the column widths.
        cellTable.setWidth("100%", true);

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.glom.web.client.ui.list.ListTable#getDataProvider()
     */
    @Override
    protected AsyncDataProvider<DataItem[]> getDataProvider() {
        final AsyncDataProvider<DataItem[]> dataProvider = new AsyncDataProvider<DataItem[]>() {

            @Override
            @SuppressWarnings("unchecked")
            protected void onRangeChanged(final HasData<DataItem[]> display) {
                // setup the callback object
                final Range range = display.getVisibleRange();
                final int start = range.getStart();
                final AsyncCallback<ArrayList<DataItem[]>> callback = new AsyncCallback<ArrayList<DataItem[]>>() {
                    @Override
                    public void onFailure(final Throwable caught) {
                        // TODO: create a way to notify users of asynchronous callback failures
                        GWT.log("AsyncCallback Failed: OnlineGlomService.getRelatedListData(): "
                                + caught.getMessage());
                    }

                    @Override
                    public void onSuccess(final ArrayList<DataItem[]> result) {
                        // keep track of the number of non-empty rows (rows with data)
                        numNonEmptyRows = 0;
                        if (result != null) {
                            numNonEmptyRows = result.size();
                        }

                        // Add empty rows if required.
                        final int numEmptyRows = MIN_TABLE_ROWS - numNonEmptyRows;
                        for (int i = 0; i < numEmptyRows; i++) {
                            // A row that has one null item will be rendered as an empty row.
                            result.add(new DataItem[1]);
                        }
                        updateRowData(start, result);

                        // Note: numNonEmptyRows is not used by the RowCountChangeEvent handler but we need to fire the
                        // event to get ListTable.ListTablePage.createText() to run and update the pager text using
                        // getNumNonEmptyRows().
                        RowCountChangeEvent.fire(display, numNonEmptyRows, true);
                    }
                };

                // get data from the server
                final ColumnSortList colSortList = cellTable.getColumnSortList();
                int sortColumn = -1; // -1 means no sort.
                boolean ascending = false;
                if (colSortList.size() > 0) {
                    // ColumnSortEvent has been requested by the user
                    final ColumnSortInfo info = colSortList.get(0);
                    sortColumn = cellTable.getColumnIndex((Column<DataItem[], ?>) info.getColumn());
                    ascending = info.isAscending();
                }

                OnlineGlomServiceAsync.Util.getInstance().getRelatedListData(documentID, tableName, portal,
                        foreignKeyValue, start, range.getLength(), sortColumn, ascending, callback);
            }
        };

        return dataProvider;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.glom.web.client.ui.list.ListTable#getMinNumVisibleRows()
     */
    @Override
    public int getMinNumVisibleRows() {
        return MIN_TABLE_ROWS;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.glom.web.client.ui.list.ListTable#getNumNonEmptyRows()
     */
    @Override
    public int getNumNonEmptyRows() {
        return numNonEmptyRows;
    }

    /**
     * Gets the expected height of a RelatedListTable.
     * 
     * @return the expect height of a RelatedListTable in pixels
     */
    public static int getExpectedHeight() {
        return expectedHeight;
    }

    // called while class is being initialized
    private static int initializeExepectedHeight() {
        // TODO Use a real RelatedListTable instead of building one manually. It's probably better to do this when
        // RelatedListTables are created in Portal instead of DetailsActivity.

        // This table simulates a related list with one row containing a Text cell and a Button cell.
        final SafeHtmlBuilder tableBuilder = new SafeHtmlBuilder();
        tableBuilder.append(SafeHtmlUtils.fromSafeConstant(
                "<table class=\"data-list\"><thead><tr><th>TH</th><th>BH</th></tr></thead><tbody>"));
        for (int i = 0; i < MAX_TABLE_ROWS; i++) {
            tableBuilder.append(SafeHtmlUtils
                    .fromSafeConstant("<tr><td>T</td><td><button type=\"button\">B</button></td></tr>"));
        }
        tableBuilder.append(SafeHtmlUtils.fromSafeConstant("</tbody></head>"));
        final HTML table = new HTML(tableBuilder.toSafeHtml());

        // The pager
        final SimplePager pager = new SimplePager();
        pager.addStyleName("pager");

        // Pack the table and pager as they are found in the details view.
        final FlowPanel group = new FlowPanel();
        group.setStyleName("group");
        final FlowPanel subgroup = new FlowPanel();
        subgroup.setStyleName("portal");
        subgroup.add(table);
        subgroup.add(pager);
        group.add(subgroup);

        // Calculate the height similar to Utils.getWidgetHeight().
        final Document doc = Document.get();
        com.google.gwt.dom.client.Element div = doc.createDivElement();
        div.getStyle().setVisibility(Visibility.HIDDEN);
        div.appendChild(group.getElement().<com.google.gwt.dom.client.Element>cast());
        doc.getBody().appendChild(div);
        final int relatedListTableHeight = group.getElement().getFirstChildElement().getOffsetHeight();

        // remove the div from the from the document
        doc.getBody().removeChild(div);
        div = null;

        return relatedListTableHeight;
    }
}