/******************************************************************************* * 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.awt.print.Pageable; import java.util.List; import org.eclipse.jface.viewers.AbstractListViewer; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.nebula.widgets.pagination.collections.PageResult; import org.eclipse.nebula.widgets.pagination.collections.PageResultContentProvider; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.TreeItem; /** * This class help you to configure a {@link PageableController} to manage * paginated list data in a {@link Viewer}. This helper manages the 2 following * strategies for pagination : * * <ul> * <li> * load the paginated list and <strong>replace data</strong> from the viewer * with the new list. See * {@link PageLoaderStrategyHelper#loadPageAndReplaceItems(PageableController, Viewer, IPageLoader)} * </li> * <li> * load the paginated list and <strong>add to the data</strong> of the viewer * the new list. See * {@link PageLoaderStrategyHelper#loadPageAndAddItems(PageableController, TableViewer, IPageLoader)} * </li> * </ul> * */ public class PageLoaderStrategyHelper { // ---------------- Replace strategy /** * This method loads the paginated list by using the given page loader * {@link IPageLoader} and information about pagination from the given * controller {@link PageableController}. After loading paginated list * returned in a pagination structure {@link PageResult}, this method : * * <ul> * <li>update the total elements of the given controller * {@link PageableController}</li> * <li>refresh the given {@link Viewer} by replacing data with the new * paginated list.</li> * </ul> * * @param controller * the controller to use to load paginated list and update the * total elements. * @param viewer * the viewer to refresh with new paginated list. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. */ public static void loadPageAndReplaceItems( final PageableController controller, final Viewer viewer, final IPageLoader<?> pageLoader, final IPageContentProvider pageContentProvider, final IPageLoaderHandler<PageableController> handler) { Object page = loadPageAndUpdateTotalElements(controller, pageLoader, pageContentProvider, handler); if (page != null) { List<?> content = pageContentProvider.getPaginatedList(page); if (content != null) { // Refresh the viewer with the paginated list. viewer.setInput(content); } } } /** * Create {@link IPageChangedListener} with pagination "replace" strategy. * See * {@link PageLoaderStrategyHelper#loadPageAndReplaceItems(PageableController, Viewer, IPageLoader)} * for more information. * * @param controller * the controller to use to load paginated list and update the * total elements. * @param viewer * the viewer to refresh with new paginated list. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. * @return */ public static IPageChangedListener createLoadPageAndReplaceItemsListener( final PageableController controller, final StructuredViewer viewer, final IPageLoader<?> pageLoader, final IPageContentProvider pageContentProvider, final IPageLoaderHandler<PageableController> handler) { return new PageChangedAdapter() { @Override public void pageIndexChanged(int oldPageIndex, int newPageIndex, PageableController controller) { PageLoaderStrategyHelper.loadPageAndReplaceItems(controller, viewer, pageLoader, pageContentProvider, handler); } @Override public void pageSizeChanged(int oldPageSize, int newPageSize, PageableController paginationController) { controller.reset(); } @Override public void sortChanged(String oldPopertyName, String propertyName, int oldSortDirection, int sortDirection, PageableController controller) { controller.reset(); } }; } // ---------------- Add strategy // ---------------- For table /** * This method loads the paginated list by using the given page loader * {@link IPageLoader} and information about pagination from the given * controller {@link PageableController}. After loading paginated list * returned in a pagination structure {@link PageResult}, this method : * * <ul> * <li>update the total elements of the given controller * {@link PageableController}</li> * <li>refresh the given {@link Viewer} by replacing data with the new * paginated list.</li> * </ul> * * @param controller * the controller to use to load paginated list and update the * total elements. * @param viewer * the viewer to refresh with new paginated list. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. */ public static void loadPageAndAddItems(final PageableController controller, final TableViewer viewer, final IPageLoader<?> pageLoader, final IPageContentProvider pageContentProvider, final IPageLoaderHandler<PageableController> handler) { Object page = loadPageAndUpdateTotalElements(controller, pageLoader, pageContentProvider, handler); if (page != null) { List<?> content = pageContentProvider.getPaginatedList(page); if (content != null && !content.isEmpty()) { viewer.add(content.toArray()); int count = viewer.getTable().getItemCount(); if (count > 0) { TableItem item = viewer.getTable().getItem(count - 1); item.setData(LazyItemsSelectionListener.LAST_ITEM_LOADED, true); } } } } /** * Create {@link IPageChangedListener} with pagination "add" strategy. See * {@link PageLoaderStrategyHelper#loadPageAndAddItems(PageableController, TableViewer, IPageLoader)} * for more information. * * @param controller * the controller to use to load paginated list and update the * total elements. * @param viewer * the viewer to refresh with new paginated list. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. * * @return */ public static IPageChangedListener createLoadPageAndAddItemsListener( final PageableController controller, final TableViewer viewer, final IPageLoader<?> pageLoader, final IPageLoaderHandler<PageableController> handler) { return createLoadPageAndAddItemsListener(controller, viewer, pageLoader, PageResultContentProvider.getInstance(), handler); } /** * Create {@link IPageChangedListener} with pagination "add" strategy. See * {@link PageLoaderStrategyHelper#loadPageAndAddItems(PageableController, TableViewer, IPageLoader)} * for more information. * * @param controller * the controller to use to load paginated list and update the * total elements. * @param viewer * the viewer to refresh with new paginated list. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. * * @return */ public static IPageChangedListener createLoadPageAndAddItemsListener( final PageableController controller, final TableViewer viewer, final IPageLoader<?> pageLoader, final IPageContentProvider pageContentProvider, final IPageLoaderHandler<PageableController> handler) { return new PageChangedAdapter() { @Override public void pageIndexChanged(int oldPageIndex, int newPageIndex, PageableController controller) { PageLoaderStrategyHelper.loadPageAndAddItems(controller, viewer, pageLoader, pageContentProvider, handler); } @Override public void pageSizeChanged(int oldPageSize, int newPageSize, PageableController paginationController) { controller.reset(); } @Override public void sortChanged(String oldPopertyName, String propertyName, int oldSortDirection, int sortDirection, PageableController controller) { controller.reset(); } }; } // ---------------- For tree /** * This method loads the paginated list by using the given page loader * {@link IPageLoader} and information about pagination from the given * controller {@link PageableController}. After loading paginated list * returned in a pagination structure {@link PageResult}, this method : * * <ul> * <li>update the total elements of the given controller * {@link PageableController}</li> * <li>refresh the given {@link Viewer} by replacing data with the new * paginated list.</li> * </ul> * * @param controller * the controller to use to load paginated list and update the * total elements. * @param viewer * the viewer to refresh with new paginated list. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. */ public static void loadPageAndAddItems(final PageableController controller, final Object parentElementOrTreePath, final TreeViewer viewer, final IPageLoader<?> pageLoader, final IPageContentProvider pageContentProvider, final IPageLoaderHandler<PageableController> handler) { Object page = loadPageAndUpdateTotalElements(controller, pageLoader, pageContentProvider, handler); if (page != null) { List<?> content = pageContentProvider.getPaginatedList(page); if (content != null && !content.isEmpty()) { viewer.add(parentElementOrTreePath, content.toArray()); int count = viewer.getTree().getItemCount(); if (count > 0) { TreeItem item = viewer.getTree().getItem(count - 1); item.setData(LazyItemsSelectionListener.LAST_ITEM_LOADED, true); } } } } /** * Create {@link IPageChangedListener} with pagination "add" strategy. See * {@link PageLoaderStrategyHelper#loadPageAndAddItems(PageableController, TableViewer, IPageLoader)} * for more information. * * @param controller * the controller to use to load paginated list and update the * total elements. * @param viewer * the viewer to refresh with new paginated list. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. * * @return */ public static IPageChangedListener createLoadPageAndAddItemsListener( final PageableController controller, final Object parentElementOrTreePath, final TreeViewer viewer, final IPageLoader<?> pageLoader, final IPageContentProvider pageContentProvider, final IPageLoaderHandler<PageableController> handler) { return new PageChangedAdapter() { @Override public void pageIndexChanged(int oldPageIndex, int newPageIndex, PageableController controller) { PageLoaderStrategyHelper.loadPageAndAddItems(controller, parentElementOrTreePath, viewer, pageLoader, pageContentProvider, handler); } @Override public void pageSizeChanged(int oldPageSize, int newPageSize, PageableController paginationController) { controller.reset(); } @Override public void sortChanged(String oldPopertyName, String propertyName, int oldSortDirection, int sortDirection, PageableController controller) { controller.reset(); } }; } // ---------------- For list view /** * This method loads the paginated list by using the given page loader * {@link IPageLoader} and information about pagination from the given * controller {@link PageableController}. After loading paginated list * returned in a pagination structure {@link PageResult}, this method : * * <ul> * <li>update the total elements of the given controller * {@link PageableController}</li> * <li>refresh the given {@link Viewer} by replacing data with the new * paginated list.</li> * </ul> * * @param controller * the controller to use to load paginated list and update the * total elements. * @param viewer * the viewer to refresh with new paginated list. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. */ public static void loadPageAndAddItems(final PageableController controller, final AbstractListViewer viewer, final IPageLoader<?> pageLoader, final IPageContentProvider pageContentProvider, final IPageLoaderHandler<PageableController> handler) { Object page = loadPageAndUpdateTotalElements(controller, pageLoader, pageContentProvider, handler); List<?> content = pageContentProvider.getPaginatedList(page); if (content != null && !content.isEmpty()) { viewer.add(content.toArray()); } } /** * Create {@link IPageChangedListener} with pagination "add" strategy. See * {@link PageLoaderStrategyHelper#loadPageAndAddItems(PageableController, TableViewer, IPageLoader)} * for more information. * * @param controller * the controller to use to load paginated list and update the * total elements. * @param viewer * the viewer to refresh with new paginated list. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. * @return */ public static IPageChangedListener createLoadPageAndAddItemsListener( final PageableController controller, final AbstractListViewer viewer, final IPageLoader<?> pageLoader, final IPageContentProvider pageContentProvider, final IPageLoaderHandler<PageableController> handler) { return new PageChangedAdapter() { @Override public void pageIndexChanged(int oldPageIndex, int newPageIndex, PageableController controller) { PageLoaderStrategyHelper.loadPageAndAddItems(controller, viewer, pageLoader, pageContentProvider, handler); } @Override public void pageSizeChanged(int oldPageSize, int newPageSize, PageableController paginationController) { controller.reset(); } @Override public void sortChanged(String oldPopertyName, String propertyName, int oldSortDirection, int sortDirection, PageableController controller) { controller.reset(); } }; } // ---------------- Utilities methods /** * Load the paginated list and update the total element of the given * controller. * * @param controller * the controller to use to load paginated list and update the * total elements. * @param pageLoader * the page loader used to load paginated list. * @pageContentProvider the page content provider to retrieves total * elements+paginated list from the page result * structure returned by the pageLoader. * @param handler * the page loader handler to observe before/after page loading * process. If null no observation is done. * * @return the pagination {@link PageResult}. */ public static Object loadPageAndUpdateTotalElements( final PageableController controller, final IPageLoader<?> pageLoader, final IPageContentProvider pageContentProvider, final IPageLoaderHandler<PageableController> handler) { // Load the paginated list. Object page = null; if (handler == null) { page = loadPage(pageLoader, controller); } else { handler.onBeforePageLoad(controller); try { page = loadPage(pageLoader, controller); handler.onAfterPageLoad(controller, null); } catch (Throwable e) { boolean stop = handler.onAfterPageLoad(controller, e); if (stop) { return null; } if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new RuntimeException(e); } } // Update the total elements of the controller. controller.setTotalElements(pageContentProvider.getTotalElements(page)); return page; } /** * Load the paginated list. * * @param pageLoader * the page loader used to load paginated list. * @param pageable * the pagination {@link Pageable}. * @return the pagination {@link PageResult}. */ public static Object loadPage(IPageLoader<?> pageLoader, PageableController controller) { if (pageLoader == null) { throw new NullPointerException("PageLoader cannot be null!"); } return pageLoader.loadPage(controller); } }