1 /********************************************************************************
2 *                                                                               *
3 *             B a c k  B u f f e r e d  C a n v a s  W i d g e t                *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 2002 by Davy Durham.  With coding tips from Jeroen van der Zijp *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or                 *
9 * modify it under the terms of the GNU Lesser General Public                    *
10 * License as published by the Free Software Foundation; either                  *
11 * version 2.1 of the License, or (at your option) any later version.            *
12 *                                                                               *
13 * This library is distributed in the hope that it will be useful,               *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU             *
16 * Lesser General Public License for more details.                               *
17 *                                                                               *
18 * You should have received a copy of the GNU Lesser General Public              *
19 * License along with this library; if not, write to the Free Software           *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.    *
21 *********************************************************************************
22 * $Id: FXBackBufferedCanvas.h 1652 2003-10-07 18:39:33Z ddurham $                       *
23 ********************************************************************************/
24 #ifndef FXBACKBUFFEREDCANVAS_H
25 #define FXBACKBUFFEREDCANVAS_H
26 
27 
28 // NOTE: Jeroen (author of FOX) said that he would at some point put this widget into FOX
29 // so for now, I'm adding it to the missing directory in case someone doesn't have a version
30 // of FOX with this widget.  Eventually I should be able to remove it.  The original source
31 // had a separate .h and .cpp file.. I combined it for a quick and dirty way not to need a
32 // lib
33 
34 //#include "FXCanvas.h" // uncomment when putting into lib
35 
36 // namespace FX {
37 
38 
39 // Back Buffered Canvas, an area drawn by another object, except a little more expensive but to reduce flicker
40 class FXAPI FXBackBufferedCanvas : public FXCanvas
41 {
FXDECLARE(FXBackBufferedCanvas)42 	FXDECLARE(FXBackBufferedCanvas)
43 public:
44 	// Construct new back buffered drawing canvas widget
45 	FXBackBufferedCanvas(FXComposite* p,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=FRAME_NORMAL,FXint x=0,FXint y=0,FXint w=0,FXint h=0) :
46 		FXCanvas(p,tgt,sel,opts,x,y,w,h),
47 		backBuffer(new FXImage(getApp(),NULL,0,w,h)),
48 		inOnPaintEvent(false),
49 		currentDC(NULL)
50 	{
51 	}
52 
~FXBackBufferedCanvas()53 	virtual ~FXBackBufferedCanvas()
54 	{
55 		delete backBuffer;
56 	}
57 
58 	/*
59 	 * - This can be used to set the options of the back buffer to include
60 	 * IMAGE_OWNED so that the drawing code can call getBackBufferData()
61 	 * and render/modify the back buffer.
62 	 * - When IMAGE_OWNED is included in the options, then backBuffer->render()
63 	 * will be called just before the backbuffer is blitted to the screen.
64 	 */
setBackBufferOptions(FXint options)65 	void setBackBufferOptions(FXint options)
66 	{
67 		delete backBuffer;
68 		if(options&IMAGE_OWNED) options|=IMAGE_KEEP;
69 		backBuffer=new FXImage(getApp(),NULL,options,getWidth(),getHeight());
70 	}
71 	// NOTE: ??? if IMAGE_OWNED is in the flags, then there is really no need to allocate an FXDCWindow and return it via the ptr parameter in the onPaint even or via the return value of beginPaint()
72 
getBackBufferData()73 	void *getBackBufferData()
74 	{
75 		return backBuffer->getData();
76 	}
77 
create()78 	void create()
79 	{
80 		FXCanvas::create();
81 		backBuffer->create();
82 	}
83 
onPaint(FXObject * sender,FXSelector sel,void * ptr)84 	long onPaint(FXObject *sender,FXSelector sel,void *ptr)
85 	{
86 		// ??? I hope no one triggers this event again while we're handling this event (could check the inOnPaintEvent flag and ignore it if necesary)
87 
88 		endPaint(); // just in case someone forgot to call endPaint after calling beginPaint or an except wasn't handled or something
89 
90 		if(((FXEvent *)ptr)->synthetic && target)
91 		{ // triggered by a call to update()
92 			inOnPaintEvent=true; // used to avoid problems if the user calls beginPaint and endPaint within the onPaint handler
93 			FXDCWindow dc(backBuffer);
94 			currentDC=&dc;
95 
96 			target->handle(this,FXSEL(SEL_PAINT,message),currentDC);
97 
98 			inOnPaintEvent=false;
99 			currentDC=NULL;
100 		}
101 
102 		// now blit the back buffer to the screen
103 		FXDCWindow screenDC(this);
104 		FXEvent *ev=(FXEvent *)ptr;
105 		backBuffer->render();
106 		screenDC.drawArea(backBuffer,ev->rect.x,ev->rect.y,ev->rect.w,ev->rect.h,ev->rect.x,ev->rect.y);
107 
108 		return 1;
109 	}
110 
111 	// Resized .. so resize the back buffer and repaint it
onConfigure(FXObject * sender,FXSelector sel,void * ptr)112 	long onConfigure(FXObject *sender,FXSelector sel,void *ptr)
113 	{
114 		backBuffer->resize(getWidth(),getHeight());
115 		update();
116 		if(target)
117 			target->handle(this,FXSEL(SEL_CONFIGURE,message),ptr);
118 		return 1;
119 	}
120 
121 	// Normally, the user should wait for the SEL_PAINT event to draw the the canvas, in which case
122 	// the ptr parameter would contain the DC to draw to.
123 	//
124 	// However, these two methods need to be used if the user is not waiting for the SEL_PAINT event
125 	// to draw to the canvas since the user should actually be drawing to the back buffer and not the
126 	// actual canvas on screen.  (I suppose much more work could be done to make the use of back buffering
127 	// completly transparent and make it have the same interface as FXCanvas)
beginPaint()128 	FXDC *beginPaint()
129 	{
130 		if(inOnPaintEvent)
131 			return currentDC;
132 		else
133 			return currentDC=new FXDCWindow(backBuffer);
134 	}
135 
endPaint()136 	void endPaint()
137 	{
138 		if(!inOnPaintEvent && currentDC!=NULL)
139 		{
140 			delete currentDC;
141 			currentDC=NULL;
142 
143 			// I suppose we should just blit the whole thing when they're done painting
144 			FXDCWindow screenDC(this);
145 			backBuffer->render();
146 			screenDC.drawArea(backBuffer,0,0,getWidth(),getHeight(),0,0);
147 			// tell the event loop that no painting is necessary now for this window???
148 			// 	is there a way to do this Jeroen?
149 		}
150 	}
151 
152 protected:
FXBackBufferedCanvas()153 	FXBackBufferedCanvas() {}
154 private:
155 	FXImage *backBuffer;
156 	bool inOnPaintEvent;
157 	FXDC *currentDC;
158 };
159 
160 // Map
161 FXDEFMAP(FXBackBufferedCanvas) FXBackBufferedCanvasMap[]=
162 {
163 	FXMAPFUNC(SEL_PAINT,0,FXBackBufferedCanvas::onPaint),
164 	FXMAPFUNC(SEL_CONFIGURE,0,FXBackBufferedCanvas::onConfigure),
165 };
166 
167 
168 // Object implementation
169 FXIMPLEMENT(FXBackBufferedCanvas,FXWindow,FXBackBufferedCanvasMap,ARRAYNUMBER(FXBackBufferedCanvasMap))
170 
171 // }
172 
173 #endif
174