package org.eclipse.nebula.widgets.grid; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.EventObject; import java.util.Iterator; import org.eclipse.nebula.widgets.grid.Grid.GridVisibleRange; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; /** * This support class adds the possibility to get informed when the visual range * in the grid is modified. E.g. to implement clever resource management * <p> * <b>This support is provisional and may change</b> * </p> */ public class GridVisibleRangeSupport { private Collection rangeChangeListener; private Grid grid; private GridVisibleRange oldRange = new GridVisibleRange(); private Listener paintListener = new Listener() { public void handleEvent(Event event) { calculateChange(); } }; /** * Listener notified when the visible range changes */ public interface VisibleRangeChangedListener { /** * Method called when range is changed * * @param event * the event holding informations about the change */ public void rangeChanged(RangeChangedEvent event); } /** * Event informing about the change */ public static class RangeChangedEvent extends EventObject { /** * */ private static final long serialVersionUID = 1L; /** * Rows new in the visible range */ public GridItem[] addedRows; /** * Rows removed from the range */ public GridItem[] removedRows; /** * Columns added to the range */ public GridColumn[] addedColumns; /** * Columns removed from the range */ public GridColumn[] removedColumns; /** * The current visible range */ public GridVisibleRange visibleRange; RangeChangedEvent(Grid grid, GridVisibleRange visibleRange) { super(grid); this.visibleRange = visibleRange; } } private GridVisibleRangeSupport(Grid grid) { this.grid = grid; this.grid.setSizeOnEveryItemImageChange(true); // FIXME Maybe better to listen to resize, ... ? grid.addListener(SWT.Paint, paintListener); } /** * Add a listener who is informed when the range is changed * * @param listener * the listener to add */ public void addRangeChangeListener(VisibleRangeChangedListener listener) { if (rangeChangeListener == null) { rangeChangeListener = new ArrayList(); } rangeChangeListener.add(listener); } /** * Remove the listener from the ones informed when the range is changed * * @param listener */ public void removeRangeChangeListener(VisibleRangeChangedListener listener) { if (rangeChangeListener != null) { rangeChangeListener.remove(listener); if (rangeChangeListener.size() == 0) { rangeChangeListener = null; } } } private void calculateChange() { // FIXME Add back if (rangeChangeListener != null) { GridVisibleRange range = grid.getVisibleRange(); ArrayList lOrigItems = new ArrayList(); lOrigItems.addAll(Arrays.asList(oldRange.getItems())); ArrayList lNewItems = new ArrayList(); lNewItems.addAll(Arrays.asList(range.getItems())); Iterator it = lNewItems.iterator(); while (it.hasNext()) { if (lOrigItems.remove(it.next())) { it.remove(); } } ArrayList lOrigColumns = new ArrayList(); lOrigColumns.addAll(Arrays.asList(oldRange.getColumns())); ArrayList lNewColumns = new ArrayList(); lNewColumns.addAll(Arrays.asList(range.getColumns())); it = lNewColumns.iterator(); while (it.hasNext()) { if (lOrigColumns.remove(it.next())) { it.remove(); } } if (lOrigItems.size() != 0 || lNewItems.size() != 0 || lOrigColumns.size() != 0 || lNewColumns.size() != 0) { RangeChangedEvent evt = new RangeChangedEvent(grid, range); evt.addedRows = new GridItem[lNewItems.size()]; lNewItems.toArray(evt.addedRows); evt.removedRows = new GridItem[lOrigItems.size()]; lOrigItems.toArray(evt.removedRows); evt.addedColumns = new GridColumn[lNewColumns.size()]; lNewColumns.toArray(evt.addedColumns); evt.removedColumns = new GridColumn[lOrigColumns.size()]; lNewColumns.toArray(evt.removedColumns); it = rangeChangeListener.iterator(); while (it.hasNext()) { ((VisibleRangeChangedListener) it.next()).rangeChanged(evt); } } oldRange = range; } } /** * Create a range support for the given grid instance * * @param grid * the grid instance the range support is created for * @return the created range support */ public static GridVisibleRangeSupport createFor(Grid grid) { return new GridVisibleRangeSupport(grid); } }