/*
  ==============================================================================

   This file is part of the JUCE library - "Jules' Utility Class Extensions"
   Copyright 2004-6 by Raw Material Software ltd.

  ------------------------------------------------------------------------------

   JUCE can be redistributed and/or modified under the terms of the
   GNU General Public License, as published by the Free Software Foundation;
   either version 2 of the License, or (at your option) any later version.

   JUCE is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with JUCE; if not, visit www.gnu.org/licenses or write to the
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
   Boston, MA 02111-1307 USA

  ------------------------------------------------------------------------------

   If you'd like to release a closed-source product which uses JUCE, commercial
   licenses are also available: visit www.rawmaterialsoftware.com/juce for
   more information.

  ==============================================================================
*/

#ifndef __JUCE_REPAINTMANAGER_JUCEHEADER__
#define __JUCE_REPAINTMANAGER_JUCEHEADER__

#include "juce_Component.h"
#include "../../events/juce_Timer.h"


//==============================================================================
/** Stores a cached image of a component, keeping track of regions that are invalidated.

    Also used on mac and linux as an asyncronous manager for regions that need redrawing.
    Not recommended for non-power users.

*/
class JUCE_API  RepaintManager  : public Timer
{
public:
    //==============================================================================
    /** Creates a RepaintManager.

        If the time specified elapses since the last time the cached image was used,
        then it'll be freed to reduce memory use.
    */
    RepaintManager (Component* const component,
                    const int timeBeforeReleasingImageMs);

    /** Destructor. */
    ~RepaintManager();


    //==============================================================================
    /** Tells the manager that this region of the component has changed and
        any cached images of it should be invalidated.
    */
    void invalidateCache (const int x, const int y, const int w, const int h);

    /** Tells the manager that this area needs to be redrawn, but it hasn't
        necessarily changed, so a cached version could be used when painting it.

        This will also trigger an asynchronous callback to repaintNow().
    */
    void repaint (int x, int y, int w, int h);

    /** Clears any regions that have been specified in repaint() but which haven't
        yet been painted.
    */
    void clearPendingRepaints();

    /** Redraws any areas of the cache necessary so that all the regions specified
        in calls to repaint() are correctly stored in the cached image.

        This may call the component's paint method.
    */
    void renderCacheAreasNeedingRepaint();

    /** This will call repaintNow() to do a synchronous repaint and put the results on the screen.

        Any areas that were pending a repaint will be passed to the repaintNow()
        method, and cleared afterwards.

        This is the method that will be called asychronously after a call to repaint(),
        but it can be called directly to flush any pending repaints.
    */
    void performPendingRepaints();

    /** Returns the cached image.

        This may return 0 if there's none currently available or if the size is
        zero.

        The origin co-ordinates returned are the position of this image's top-left
        corner, relative to the top-left of the component.
    */
    Image* getImage (int& originX, int& originY) const;

    /** Gets rid of any cached image currently held. */
    void releaseImage();


    //==============================================================================
    /** @internal */
    void timerCallback();

protected:
    /** Called to create a suitable image.

        Can be overridden to create special system-specific types of image.
    */
    virtual Image* createNewImage (int w, int h);

    /** A subclass should use this to update the cache and copy all the relevent bits of
        of it to the screen.

        The region specifies the bits that were indicated as needing a redraw. The subclass
        should call renderCacheAreasNeedingRepaint() to get the cached image up-to-date, then
        copy the image to the screen.
    */
    virtual void repaintNow (const RectangleList& areasToPaint);


private:
    //==============================================================================
    Component* component;
    Image* image;
    int originX, originY;
    int timeBeforeReleasingImage;
    uint32 lastTimeImageUsed;
    uint32 lastPaintTime;
    RectangleList validRegions, regionsNeedingRepaint;

    void ensureImageContains (int x, int y, int w, int h);
};


#endif   // __JUCE_REPAINTMANAGER_JUCEHEADER__
