/*******************************************************************************
* Copyright (C) 2011 Angelo Zerr <angelo.zerr@gmail.com>, Pascal Leclercq <pascal.leclercq@gmail.com>
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Angelo ZERR - initial API and implementation
* Pascal Leclercq - initial API and implementation
*******************************************************************************/
package org.eclipse.nebula.widgets.pagination;
import java.io.Serializable;
import java.util.Locale;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.swt.SWT;
/**
*
* The pagination controller is used to store information about pagination :
*
* <ul>
* <li>the current page index: index of the selected page.</li>
* <li>the page size: number items to display per page.</li>
* <li>the total elements: the total elements of the paginated list.</li>
* <li>the current sort information: the property name and direction of the
* sort.</li>
* </ul>
*
* <p>
* The controller fire events as soon as pagination information change
* (ex:selected page change). Those information can be observed by adding
* {@link IPageChangedListener} to the controller.
* </p>
*
*/
public class PageableController implements Serializable {
private static final long serialVersionUID = 8456710060857724013L;
public static final int DEFAULT_PAGE_INDEX = -1;
public static final int DEFAULT_PAGE_SIZE = 10;
// the current page index: index of the selected page
private int currentPage;
// the page size: number items to display per page
private int pageSize;
// the total elements: the total elements of the paginated list
private long totalElements;
// the current sort information: the property name and direction of the
// sort.
private String sortPropertyName;
private int sortDirection;
// The current locale used for the resources
private Locale locale = Locale.getDefault();
private ListenerList pageChangedListeners = new ListenerList();
/**
* Constructor with default page size.
*
*/
public PageableController() {
this(DEFAULT_PAGE_SIZE);
}
/**
* Constructor with page size.
*
* @param pageSize
* size of the page (number items displayed per page).
*/
public PageableController(int pageSize) {
this.currentPage = DEFAULT_PAGE_INDEX;
this.pageSize = pageSize;
this.totalElements = 0;
this.sortPropertyName = null;
this.sortDirection = SWT.NONE;
}
/**
* Adds the listener to the collection of listeners who will be notified
* when the page controller changed ( the current page page size, total
* elements or sort change.
*
* @param listener
* the listener which should be notified when the controller
* change.
* @param listener
*
* @see IPageChangedListener
* @see #removePageChangedListener(IPageChangedListener)
*
*/
public void addPageChangedListener(IPageChangedListener listener) {
if (listener == null) {
throw new NullPointerException(
"Cannot add a null page changed listener"); //$NON-NLS-1$
}
pageChangedListeners.add(listener);
}
/**
* Removes the listener from the collection of listeners who will be
* notified when page controller changed ( the current page page size, total
* elements or sort change.
*
* @param listener
* the listener which should no longer be notified
*
* @see IPageChangedListener
* @see #addPageChangedListener(IPageChangedListener)
*/
public void removePageChangedListener(IPageChangedListener listener) {
if (listener != null) {
pageChangedListeners.remove(listener);
}
}
/**
* Returns true if there is a previous page and false otherwise.
*
* @return true if there is a previous page and false otherwise.
*/
public boolean hasPreviousPage() {
return getCurrentPage() > 0;
}
/**
* Returns whether the current page is the first one.
*
* @return
*/
public boolean isFirstPage() {
return !hasPreviousPage();
}
/**
* Returns true if there is a next page and false otherwise.
*
* @return true if there is a next page and false otherwise.
*/
public boolean hasNextPage() {
return ((getCurrentPage() + 1) * getPageSize()) < totalElements;
}
/**
* Returns the current page index.
*
* @return
*/
public int getCurrentPage() {
return currentPage;
}
/**
* Set the current page index and fire events if the given page index is
* different from the current page index.
*
* @param currentPage
* new current page index.
*/
public void setCurrentPage(int currentPage) {
if (this.currentPage != currentPage) {
int oldPageNumber = this.currentPage;
this.currentPage = currentPage;
notifyListenersForPageIndexChanged(oldPageNumber, currentPage);
}
}
/**
* Returns the page size: number items to display per page.
*
* @return
*/
public int getPageSize() {
return pageSize;
}
/**
* Set the page size and fire events if the given page size is different
* from the current page size.
*
* @param pageSize
* page size: number items to display per page.
*/
public void setPageSize(int pageSize) {
if (this.pageSize != pageSize) {
int oldPageSize = this.pageSize;
this.pageSize = pageSize;
notifyListenersForPageSizeChanged(oldPageSize, pageSize);
}
}
/**
* Returns the total pages.
*
* @return
*/
public int getTotalPages() {
return getPageSize() == 0 ? 0 : (int) Math.ceil((double) totalElements
/ (double) getPageSize());
}
/**
* Returns whether the current page is the last one.
*
* @return
*/
public boolean isLastPage() {
return !hasNextPage();
}
public void setTotalElements(long totalElements) {
if (this.totalElements != totalElements) {
long oldTotalElements = this.totalElements;
this.totalElements = totalElements;
notifyListenersForTotalElementsChanged(oldTotalElements,
totalElements);
}
}
/**
* Returns the total elements.
*
* @return
*/
public long getTotalElements() {
return totalElements;
}
/**
* Returns the current page offset.
*
* @return
*/
public int getPageOffset() {
return getCurrentPage() * getPageSize();
}
/**
* Set the sort and fire events if the given sort is different from the
* current sort.
*
* @param propertyName
* the sort property name.
* @param sortDirection
* the sort direction {@link SWT.UP}, {@link SWT.DOWN}.
*/
public void setSort(String propertyName, int sortDirection) {
if (this.sortPropertyName != propertyName
|| this.sortDirection != sortDirection) {
String oldPopertyName = this.sortPropertyName;
this.sortPropertyName = propertyName;
int oldSortDirection = this.sortDirection;
this.sortDirection = sortDirection;
notifyListenersForSortChanged(oldPopertyName, propertyName,
oldSortDirection, sortDirection);
}
}
/**
* Returns the property name used to sort.
*
* @return the sort property name.
*/
public String getSortPropertyName() {
return sortPropertyName;
}
/**
* Returns the sort direction {@link SWT.UP}, {@link SWT.DOWN}.
*
* @return
*/
public int getSortDirection() {
return sortDirection;
}
/**
* Reset the current page index and force the fire events of page index
* changed.
*/
public void reset() {
int oldCurrentPage = currentPage;
this.currentPage = 0;
notifyListenersForPageIndexChanged(oldCurrentPage, currentPage);
// this.propertyName = null;
// this.sortDirection = SWT.NONE;
}
/**
* Set the local for the resources.
*
* @param locale
*/
public void setLocale(Locale locale) {
Locale oldLocale = this.locale;
this.locale = locale;
if (!oldLocale.equals(locale)) {
notifyListenersForLocaleChanged(oldLocale, locale);
}
}
private void notifyListenersForPageIndexChanged(int oldPageNumber,
int newPageNumber) {
final Object[] listeners = pageChangedListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
final IPageChangedListener listener = (IPageChangedListener) listeners[i];
listener.pageIndexChanged(oldPageNumber, newPageNumber, this);
}
}
private void notifyListenersForTotalElementsChanged(long oldTotalElements,
long newTotalElements) {
final Object[] listeners = pageChangedListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
final IPageChangedListener listener = (IPageChangedListener) listeners[i];
listener.totalElementsChanged(oldTotalElements, newTotalElements,
this);
}
}
private void notifyListenersForSortChanged(String oldPopertyName,
String propertyName, int oldSortDirection, int sortDirection) {
final Object[] listeners = pageChangedListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
final IPageChangedListener listener = (IPageChangedListener) listeners[i];
listener.sortChanged(oldPopertyName, propertyName,
oldSortDirection, sortDirection, this);
}
}
private void notifyListenersForPageSizeChanged(int oldPageSize,
int newPageSize) {
final Object[] listeners = pageChangedListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
final IPageChangedListener listener = (IPageChangedListener) listeners[i];
listener.pageSizeChanged(oldPageSize, newPageSize, this);
}
}
private void notifyListenersForLocaleChanged(Locale oldLocale,
Locale newLocale) {
final Object[] listeners = pageChangedListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
final IPageChangedListener listener = (IPageChangedListener) listeners[i];
listener.localeChanged(oldLocale, newLocale, this);
}
}
}