package edu.ualberta.med.biobank.widgets.infotables; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Table; import edu.ualberta.med.biobank.gui.common.BgcLogger; /** * Used to display tabular information for a class in the object model or * combined information from several classes in the object model. * <p> * The information in the table is loaded in a background thread. By loading * object model data in a background thread, the main UI thread is not blocked * when displaying the cells of the table. * <p> * This widget supports the following listeners: double click listener, edit * listener, and delete listener. The double click listener is invoked when the * user double clicks on a row in the table. The edit and delete listeners are * invoked via the table's context menu. When one of these listeners is * registered, the widget adds an "Edit" and / or "Delete" item to the context * menu. The corresponding listener is then invoked when the user selects either * one of the two menu choices. The event passed to the listener contains the * current selection for the table. * <p> * This widget also allows for a row of information to be copied to the * clipboard. The "Copy" command is made available in the context menu. When * this command is selected by the user the rows that are currently selected are * copied to the clipboard. * <p> * If neither the edit or delete listeners are registered, then the table is * configured to be in multi select mode and the selection of multiple lines is * available to the user. * <p> * NOTE: * <p> * Care should be taken in the label provider so that blocking calls are not * made to the object model. All calls to the object model should be done in * abstract method getCollectionModelObject(). * * @param <T> The model object wrapper the table is based on. * */ public abstract class InfoTableWidget<T> extends InfoTableBgrLoader<T> { /* * see http://lekkimworld.com/2008/03/27/setting_table_row_height_in_swt * .html for how to set row height. */ private static BgcLogger logger = BgcLogger.getLogger(InfoTableWidget.class .getName()); protected List<BiobankCollectionModel> model; @SuppressWarnings("unused") public InfoTableWidget(Composite parent, List<T> collection, String[] headings, int rowsPerPage, Class<?> wrapperClass) { super(parent, collection, headings, null, rowsPerPage); } public InfoTableWidget(Composite parent, List<T> list, String[] headings, Class<?> wrapperClass) { this(parent, list, headings, 5, wrapperClass); } @Override protected void init(List<T> list) { reloadData = true; model = new ArrayList<BiobankCollectionModel>(); initModel(list); } @Override protected void setPaginationParams(List<T> collection) { paginationRequired = paginationWidget .setTableMaxRows(collection.size()); if (paginationRequired) { getTableViewer().refresh(); } } /** * Derived classes should override this method if info table support editing * of items in the table. * * @return true if editing is allowed. */ @Override protected boolean isEditMode() { return false; } protected BiobankCollectionModel getSelectionInternal() { Assert.isTrue(!tableViewer.getTable().isDisposed(), "widget is disposed"); //$NON-NLS-1$ IStructuredSelection stSelection = (IStructuredSelection) tableViewer .getSelection(); return (BiobankCollectionModel) stSelection.getFirstElement(); } protected void initModel(List<?> collection) { if ((collection == null) || (model.size() == collection.size())) return; BiobankTableSorter comparator = getComparator(); if (comparator != null) Collections.sort(collection, comparator); model.clear(); for (int i = 0, n = collection.size(); i < n; ++i) { model.add(new BiobankCollectionModel(i)); } } protected abstract BiobankTableSorter getComparator(); protected abstract String getCollectionModelObjectToString(Object o); @Override public boolean setFocus() { tableViewer.getControl().setFocus(); return true; } /** * Should be used by info tables that allow editing of data. Use this method * instead of setCollection(). * * @param list */ public void reloadCollection(final List<T> list, T selection) { reloadData = true; setList(list, selection); } public void reloadCollection(final List<T> list) { reloadCollection(list, null); } @Override protected void tableLoader(final List<T> collection, final T selection) { final TableViewer viewer = getTableViewer(); final Table table = viewer.getTable(); Display display = viewer.getTable().getDisplay(); initModel(collection); if (paginationRequired) { int rowsPerPage = paginationWidget.getRowsPerPage(); start = paginationWidget.getCurrentPage() * rowsPerPage; end = Math.min(start + rowsPerPage, model.size()); } else { start = 0; end = model.size(); } final List<BiobankCollectionModel> modelSubList = model.subList(start, end); display.syncExec(new Runnable() { @Override public void run() { if (!table.isDisposed()) { tableViewer.setInput(modelSubList); } } }); try { BiobankCollectionModel selItem = null; for (int i = start; i < end; ++i) { if (table.isDisposed()) return; final BiobankCollectionModel item = model.get(i); Assert.isNotNull(item != null); if (reloadData || (item.o == null)) { item.o = getCollectionModelObject(collection .get(item.index)); } display.syncExec(new Runnable() { @Override public void run() { if (!table.isDisposed()) { viewer.refresh(item, false); } } }); if ((selection != null) && selection.equals(item.o)) { selItem = item; } } reloadData = false; final BiobankCollectionModel selectedItem = selItem; display.syncExec(new Runnable() { @Override public void run() { if (!table.isDisposed()) { if (paginationRequired) { enablePaginationWidget(true); } if (selectedItem != null) { tableViewer.setSelection(new StructuredSelection( selectedItem)); } } } }); } catch (Exception e) { logger.error("setCollection error", e); //$NON-NLS-1$ } } public Object getCollectionModelObject(Object item) throws Exception { return item; } }