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