// Copyright 1996, Marimba Inc. All Rights Reserved.


// @(#)BackingStore.java, 1.11, 11/09/96





package marimba.gui;





import java.awt.*;





/**


 * A Backing store for AWT components.


 *


 * @author	Arthur van Hoff


 * @version 	1.11, 11/09/96


 */


public final class BackingStore {


    static Toolkit tk = Toolkit.getDefaultToolkit();





    Component owner;


    int width = 1;


    int height = 1;


    Image img;


    RectList rects = new RectList();





    /**


     * Clear an area.


     */


    void clearArea(int x, int y, int width, int height) {


	for (int i = rects.nrects ; i-- > 0 ;) {


	    Rect r = rects.rects[i];


	    if (r.intersects(x, y, width, height)) {


		rects.delete(i);


	    }


	}


    }





    /**


     * Add an area.


     */


    void addArea(Widget w, int x, int y, int width, int height) {


	clearArea(x, y, width, height);


	rects.add(new Rect(w, x, y, width, height));


    }





    /**


     * Check if an area is valid


     */


    boolean validArea(Widget w, int x, int y, int width, int height) {


	if ((x < 0) || (y < 0) || (x + width > this.width) || (y + height > this.height)) {


	    return false;


	}





	for (int i = rects.nrects ; i-- > 0 ;) {


	    Rect r = rects.rects[i];


	    if ((r.w == w) && (r.x == x) && (r.y == y) && (r.width == width) && (r.height == height)) {


		return true;


	    }


	}


	return false;


    }


    


    /**


     * Get the offscreen image. The component is the owner of


     * in which the offscreen buffer will be drawn. The bounding


     * rectangle indicates the area in which will be drawn. The


     * cliprect will be set to the indicated area.


     */


    public synchronized Graphics getGraphics(Component owner) {


	this.owner = owner;





	// Allocate the backing store


	Dimension d = owner.size();


	if ((img == null) || (width < d.width) || (height < d.height)) {


	    img = null;


	    width = Math.max(width, d.width);


	    height = Math.max(height, d.height);





	    try {


		//System.out.println("CREATE: " + width + "x" + height);


		img = owner.createImage(width, height);


	    } catch (OutOfMemoryError e) {


		return owner.getGraphics();


	    }


	}





	// Create the graphics context.


	return (img == null) ? owner.getGraphics() : img.getGraphics();


    }





    /**


     * Paint the backing store to the window. Note that the caller must


     * synchronize on the backingstore if multiple threads use the


     * same backing store to paint.


     */


    public synchronized void paint(Graphics g) {


	if (img != null) {


	    g.drawImage(img, 0, 0, null);


	}


	tk.sync();


    }





    /**


     * Debugging.


     */


    public String toString() {


	return getClass().getName() + "[" + width +"x" + height +


	    ((img != null) ? ",free]" : ",allocated]");


    }





    /**


     * Flush the backing store.


     */


    public synchronized void flush() {


	width = 1;


	height = 1;


	img = null;


	rects.clear();


    }


}


