/******************************************************************************* * Copyright (c) 2000, 2005 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.draw2d; import java.util.Map; import org.eclipse.swt.graphics.GC; import org.eclipse.draw2d.geometry.Rectangle; /** * Update managers handle the job of laying out and repainting figures. A desirable * implementation is to batches work to be done and collapses any redundant work. For * example, clients may be making multiple changes to figures, which require laying out * the same container or repainting the same region. * <P> * The update manager receives requests to validate certain figures, and repaint certain * areas of figures. An update manager could process every request synchronously, or it * could batch these requests and process them asynchronously. * <P> * The update process occurs in two phases. The first phase is laying out invalid figures. * This phase comes first because it usually introduces additional damage regions. In some * cases, while validating figures, new invalid figures may be appended to the update * manager. Of course, damage regions will be reported too as figures are layed out. * <P> * The second phase is to repaint all damaged areas. The update manager will typically * batch, clip, and union, all rectangles and perform a single paint of the overall * damaged area. * */ public abstract class UpdateManager { private UpdateListener listeners[] = new UpdateListener[0]; private boolean disposed; /** * Adds the dirty region defined by the coordinates on the IFigure <b>figure</b>. The * update manager should repaint the dirty region in a timely fashion. * * @param figure the dirty figure * @param x the x coordinate of the dirty region * @param y the y coordinate of the dirty region * @param w the width of the dirty region * @param h the height of the dirty region */ public abstract void addDirtyRegion(IFigure figure, int x, int y, int w, int h); /** * @see #addDirtyRegion(IFigure, int, int, int, int) */ public void addDirtyRegion(IFigure figure, Rectangle rect) { addDirtyRegion(figure, rect.x, rect.y, rect.width, rect.height); } /** * Causes an update to occur at some time, and the given runnable to be executed * following the update. * @since 3.1 * @param run the runnable */ public void runWithUpdate(Runnable run) { } /** * The receiver should call validate() on the IFigure <i>figure</i> in a timely fashion. * * @param figure the invalid figure */ public abstract void addInvalidFigure(IFigure figure); /** * Adds the given listener to the list of listeners to be notified of painting and * validation. * @param listener the listener to add */ public void addUpdateListener(UpdateListener listener) { if (listener == null) throw new IllegalArgumentException(); if (listeners == null) { listeners = new UpdateListener[1]; listeners[0] = listener; } else { int oldSize = listeners.length; UpdateListener newListeners[] = new UpdateListener[oldSize + 1]; System.arraycopy(listeners, 0, newListeners, 0, oldSize); newListeners[oldSize] = listener; listeners = newListeners; } } /** * Called when the EditPartViewer is being disposed. */ public void dispose() { disposed = true; } /** * Notifies listeners that painting is about to occur, passing them the damaged rectangle * and the map of dirty regions. * @param damage the damaged rectangle * @param dirtyRegions map of dirty regions to figures */ protected void firePainting(Rectangle damage, Map dirtyRegions) { UpdateListener localListeners[] = listeners; for (int i = 0; i < localListeners.length; i++) localListeners[i].notifyPainting(damage, dirtyRegions); } /** * Notifies listeners that validation is about to occur. */ protected void fireValidating() { UpdateListener localListeners[] = listeners; for (int i = 0; i < localListeners.length; i++) localListeners[i].notifyValidating(); } /** * @return whether this update manager has been disposed. */ protected boolean isDisposed() { return disposed; } /** * Forces an update to occur. Update managers will perform updates automatically, but may * do so asynchronously. Calling this method forces a synchronous update. */ public abstract void performUpdate(); void paint(GC gc) { performUpdate(new Rectangle(gc.getClipping())); } /** * Performs an update on the given exposed rectangle. * @param exposed the exposed rectangle */ public abstract void performUpdate(Rectangle exposed); /** * Removes one occurrence of the given UpdateListener by identity. * @param listener the listener to remove */ public void removeUpdateListener(UpdateListener listener) { if (listener == null) throw new IllegalArgumentException(); for (int index = 0; index < listeners.length; index++) if (listeners[index] == listener) { int newSize = listeners.length - 1; UpdateListener newListeners[] = null; if (newSize != 0) { newListeners = new UpdateListener[newSize]; System.arraycopy(listeners, 0, newListeners, 0, index); System.arraycopy(listeners, index + 1, newListeners, index, newSize - index); } else { newListeners = new UpdateListener[0]; } listeners = newListeners; return; } } /** * Sets the GraphicsSource for this update manager. * @param gs the new GraphicsSource */ public abstract void setGraphicsSource(GraphicsSource gs); /** * Sets the root figure. * @param figure the new root figure */ public abstract void setRoot(IFigure figure); /** * Performs a partial update if supported (validation only). Fires notification to * listeners that validation has been performed. By default this method calls {@link * #performUpdate()}. Subclasses should override this method to support validation * without repainting. * * @since 3.2 */ public void performValidation() { performUpdate(); } }