view dwtx/draw2d/UpdateManager.d @ 98:95307ad235d9

Added Draw2d code, still work in progress
author Frank Benoit <benoit@tionex.de>
date Sun, 03 Aug 2008 00:52:14 +0200
parents
children
line wrap: on
line source

/*******************************************************************************
 * 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
 * Port to the D programming language:
 *     Frank Benoit <benoit@tionex.de>
 *******************************************************************************/
module dwtx.draw2d.UpdateManager;

import dwt.dwthelper.utils;
import dwt.dwthelper.Runnable;
import dwtx.dwtxhelper.Collection;

import dwt.graphics.GC;
import dwtx.draw2d.geometry.Rectangle;
import dwtx.draw2d.IFigure;
import dwtx.draw2d.UpdateListener;
import dwtx.draw2d.GraphicsSource;

/**
 * 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[];
private bool 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 is null)
        throw new IllegalArgumentException("");
    if (listeners is null) {
        listeners = new UpdateListener[1];
        listeners[0] = listener;
    } else {
        int oldSize = listeners.length;
        UpdateListener newListeners[] = new UpdateListener[oldSize + 1];
        SimpleType!(UpdateListener).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 bool 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 is null)
        throw new IllegalArgumentException("");
    for (int index = 0; index < listeners.length; index++)
        if (listeners[index] is listener) {
            int newSize = listeners.length - 1;
            UpdateListener newListeners[] = null;
            if (newSize !is 0) {
                newListeners = new UpdateListener[newSize];
                SimpleType!(UpdateListener).arraycopy(listeners, 0, newListeners, 0, index);
                SimpleType!(UpdateListener).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();
}

}