com.google.gwt.user.cellview.client.AbstractPager.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.user.cellview.client.AbstractPager.java

Source

/*
 * Copyright 2010 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.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.view.client.HasRows;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.RangeChangeEvent;
import com.google.gwt.view.client.RowCountChangeEvent;

/**
 * An abstract pager that exposes many methods useful for paging.
 */
public abstract class AbstractPager extends Composite {

    // Visible for testing.
    HandlerRegistration rangeChangeHandler;
    HandlerRegistration rowCountChangeHandler;

    private HasRows display;

    /**
     * If true, all operations should be limited to the data size.
     */
    private boolean isRangeLimited = true;

    /**
     * The last row count.
     */
    private int lastRowCount;

    /**
     * Get the {@link HasRows} being paged.
     *
     * @return the {@link HasRows}
     * @see #setDisplay(HasRows)
     */
    public HasRows getDisplay() {
        return display;
    }

    /**
     * Get the page size.
     *
     * @return the page size, or -1 if the display is not set
     * @see #setPageSize(int)
     */
    public int getPageSize() {
        return display == null ? -1 : display.getVisibleRange().getLength();
    }

    /**
     * Get the page start index.
     *
     * @return the page start index, or -1 if the display is not set
     * @see #setPageStart(int)
     */
    public int getPageStart() {
        return display == null ? -1 : display.getVisibleRange().getStart();
    }

    /**
     * Check if the page should be limited to the actual data size. Defaults to
     * true.
     *
     * @return true if the range is limited to the data size
     * @see #setRangeLimited(boolean)
     */
    public boolean isRangeLimited() {
        return isRangeLimited;
    }

    /**
     * Set whether or not the page range should be limited to the actual data
     * size. If true, all operations will adjust so that there is always data
     * visible on the page.
     *
     * @param isRangeLimited true to limit the range, false not to
     * @see #isRangeLimited()
     */
    public void setRangeLimited(boolean isRangeLimited) {
        this.isRangeLimited = isRangeLimited;
    }

    /**
     * Set the {@link HasRows} to be paged.
     *
     * @param display the {@link HasRows}
     * @see #getDisplay()
     */
    public void setDisplay(HasRows display) {
        // Remove the old handlers.
        if (rangeChangeHandler != null) {
            rangeChangeHandler.removeHandler();
            rangeChangeHandler = null;
        }
        if (rowCountChangeHandler != null) {
            rowCountChangeHandler.removeHandler();
            rowCountChangeHandler = null;
        }

        // Set the new display.
        this.display = display;
        if (display != null) {
            rangeChangeHandler = display.addRangeChangeHandler(new RangeChangeEvent.Handler() {
                @Override
                public void onRangeChange(RangeChangeEvent event) {
                    if (AbstractPager.this.display != null) {
                        onRangeOrRowCountChanged();
                    }
                }
            });
            rowCountChangeHandler = display.addRowCountChangeHandler(new RowCountChangeEvent.Handler() {
                @Override
                public void onRowCountChange(RowCountChangeEvent event) {
                    if (AbstractPager.this.display != null) {
                        handleRowCountChange(event.getNewRowCount(), event.isNewRowCountExact());
                    }
                }
            });

            // Initialize the pager.
            onRangeOrRowCountChanged();
        }
    }

    /**
     * Go to the first page.
     */
    protected void firstPage() {
        setPage(0);
    }

    /**
     * <p>
     * Get the current page index.
     * </p>
     * <p>
     * Since the page start index can be set to any value, its possible to be
     * between pages. In this case, the return value is the number of times
     * {@link #previousPage()} can be called.
     * </p>
     *
     * @return the page index, or -1 if the display is not set
     * @see #setPage(int)
     */
    protected int getPage() {
        if (display == null) {
            return -1;
        }
        Range range = display.getVisibleRange();
        int pageSize = range.getLength();
        return (range.getStart() + pageSize - 1) / pageSize;
    }

    /**
     * Get the number of pages based on the data size.
     *
     * @return the page count, or -1 if the display is not set
     */
    protected int getPageCount() {
        if (display == null) {
            return -1;
        }
        int pageSize = getPageSize();
        return (display.getRowCount() + pageSize - 1) / pageSize;
    }

    /**
     * Returns true if there is enough data such that a call to
     * {@link #nextPage()} will succeed in moving the starting point of the table
     * forward.
     *
     * @return true if there is a next page
     */
    protected boolean hasNextPage() {
        if (display == null) {
            return false;
        } else if (!display.isRowCountExact()) {
            return true;
        }
        Range range = display.getVisibleRange();
        return range.getStart() + range.getLength() < display.getRowCount();
    }

    /**
     * Returns true if there is enough data to display a given number of
     * additional pages.
     *
     * @param pages the number of pages to query
     * @return true if there are {@code pages} next pages
     */
    protected boolean hasNextPages(int pages) {
        if (display == null) {
            return false;
        }
        Range range = display.getVisibleRange();
        return range.getStart() + pages * range.getLength() < display.getRowCount();
    }

    /**
     * Returns true if there is enough data such that the specified page is within
     * range.
     *
     * @param index the page index
     * @return true if the specified page is in range
     */
    protected boolean hasPage(int index) {
        return display == null ? false : getPageSize() * index < display.getRowCount();
    }

    /**
     * Returns true if there is enough data such that a call to
     * {@link #previousPage()} will succeed in moving the starting point of the
     * table backward.
     *
     * @return true if there is a previous page
     */
    protected boolean hasPreviousPage() {
        return display == null ? false : getPageStart() > 0 && display.getRowCount() > 0;
    }

    /**
     * Returns true if there is enough data to display a given number of previous
     * pages.
     *
     * @param pages the number of previous pages to query
     * @return true if there are {@code pages} previous pages
     */
    protected boolean hasPreviousPages(int pages) {
        if (display == null) {
            return false;
        }
        Range range = display.getVisibleRange();
        return (pages - 1) * range.getLength() < range.getStart();
    }

    /**
     * Go to the last page.
     */
    protected void lastPage() {
        setPage(getPageCount() - 1);
    }

    /**
     * Set the page start to the last index that will still show a full page.
     */
    protected void lastPageStart() {
        if (display != null) {
            setPageStart(display.getRowCount() - getPageSize());
        }
    }

    /**
     * Advance the starting row by 'pageSize' rows.
     */
    protected void nextPage() {
        if (display != null) {
            Range range = display.getVisibleRange();
            setPageStart(range.getStart() + range.getLength());
        }
    }

    /**
     * Called when the range or row count changes. Implement this method to update
     * the pager.
     */
    protected abstract void onRangeOrRowCountChanged();

    /**
     * Move the starting row back by 'pageSize' rows.
     */
    protected void previousPage() {
        if (display != null) {
            Range range = display.getVisibleRange();
            setPageStart(range.getStart() - range.getLength());
        }
    }

    /**
     * Go to a specific page.
     *
     * @param index the page index
     * @see #getPage()
     */
    protected void setPage(int index) {
        if (display != null && (!isRangeLimited || !display.isRowCountExact() || hasPage(index))) {
            // We don't use the local version of setPageStart because it would
            // constrain the index, but the user probably wants to use absolute page
            // indexes.
            int pageSize = getPageSize();
            display.setVisibleRange(pageSize * index, pageSize);
        }
    }

    /**
     * Set the page size of the display.
     *
     * @param pageSize the new page size
     * @see #getPageSize()
     */
    protected void setPageSize(int pageSize) {
        if (display != null) {
            Range range = display.getVisibleRange();
            int pageStart = range.getStart();
            if (isRangeLimited && display.isRowCountExact()) {
                pageStart = Math.min(pageStart, display.getRowCount() - pageSize);
            }
            pageStart = Math.max(0, pageStart);
            display.setVisibleRange(pageStart, pageSize);
        }
    }

    /**
     * Set the page start index.
     *
     * @param index the index
     * @see #getPageStart()
     */
    protected void setPageStart(int index) {
        if (display != null) {
            Range range = display.getVisibleRange();
            int pageSize = range.getLength();
            if (isRangeLimited && display.isRowCountExact()) {
                index = Math.min(index, display.getRowCount() - pageSize);
            }
            index = Math.max(0, index);
            if (index != range.getStart()) {
                display.setVisibleRange(index, pageSize);
            }
        }
    }

    /**
     * Called when the row count changes. Only called if display is non-null.
     *
     * @param rowCount the new row count
     * @param isExact true if the row count is exact
     */
    private void handleRowCountChange(int rowCount, boolean isExact) {
        int oldRowCount = lastRowCount;
        lastRowCount = display.getRowCount();

        // If the row count has changed, limit the range.
        if (isRangeLimited && oldRowCount != lastRowCount) {
            setPageStart(getPageStart());
        }

        // Call user methods.
        onRangeOrRowCountChanged();
    }
}