PFen.cpp

Aller à la documentation de ce fichier.
00001 #include "PFen.h"
00002 
00003 using namespace std;
00004 
00005 //retourne true si un problème à eu lieu, false sinon.
00006 bool PFen::Draw(void)
00007 {
00008     // calcul des coordonées absolues de la fenêtre
00009     SDL_Rect coordAbs=coord;
00010     calcCoord(&coordAbs);
00011 
00012     if(ClearWindow())
00013     {
00014         logErr(__FILE__,__LINE__,"Echec de ClearWindow\n");
00015         return true;
00016     }
00017     if(PrepareWindow())//cette fonction devra vérifier si il est nécessaire de refaire tous les calculs
00018     {
00019         logErr(__FILE__,__LINE__,"Echec de PrepareWindow\n");
00020         return true;
00021     }
00022     if(SDL_BlitSurface(screen,&coordAbs,shadow,NULL))//sauvegarde de l'écran
00023     {
00024         logErr(__FILE__,__LINE__,SDL_GetError());
00025         return true;
00026     }
00027     if(SDL_BlitSurface(window,NULL,screen,&coordAbs))//affichage
00028     {
00029         logErr(__FILE__,__LINE__,SDL_GetError());
00030         return true;
00031     }
00032 
00033     PFen *ptrMere=mere;//bloc pour insérer une tabulation pour chaque mere dans stderr, pour indenter les erreurs
00034     while(ptrMere)
00035     {fputc('\t',stderr);ptrMere=ptrMere->mere;}
00036     fprintf(stderr,"%x coord:(%d,%d)/(%d,%d)\toldCoord:(%d,%d)/(%d,%d)\n",(int)this,coord.x,coord.y,coord.w,coord.h,oldCoord.x,oldCoord.y,oldCoord.w,oldCoord.h);
00037     oldCoord=coord;
00038     for_each(filles.begin(),filles.end(), mem_fun(&PFen::Draw));
00039 
00040     drawed=true;
00041     return false;
00042 }
00043 
00044 //Redimensionne la fenêtre
00045 //Si relative vaut:
00046 //0: données brutes
00047 //1: données relatives (agrandit ou rétrécit donc)
00048 //true si échec
00049 bool PFen::Resize(short width, short height, unsigned char relative)
00050 {
00051     needInit=true;
00052     if(!relative)
00053     {
00054         if(height<0 || width<0)
00055         {
00056             logErr(__FILE__,__LINE__,"height(=%d) ou width(=%d) sont nuls\n",height,width);
00057             return true;
00058         }
00059         coord.h=height;
00060         coord.w=width;
00061     }
00062     else
00063     {
00064         coord.h+=height;
00065         coord.w+=width;
00066     }
00067     return false;
00068 }
00069 
00070 //Redimensionne la fenêtre avec un pourcentage.
00071 //si target vaut 0: le pourcentage s'applique à la mère
00072 //si target vaut 1: le pourcentage s'applique à elle-même
00073 //true si échec
00074 bool PFen::Resize(float width, float height, bool target)
00075 {
00076 
00077     if(!target)
00078     {
00079         if(!mere)
00080         {
00081             logErr(__FILE__,__LINE__,"mere est nul");
00082             return true;
00083         }
00084         return Resize(mere->window->w*width,mere->window->h*height,0);
00085     }
00086     return Resize(window->w*width,window->h*height,1);
00087 }
00088 
00089 //Déplace la fenêtre.
00090 //Si relative vaut 1 et que la fenêtre est une fille, les valeurs sont relatives à la fenêtre mère.
00091 //Si relative vaut 2, les valeurs sont relatives à elle-même.
00092 //true si échec
00093 bool PFen::Move(short x, short y, unsigned char relative)
00094 {
00095     if(relative==1)//relatif à la mère
00096     {
00097         if(!mere)
00098         {
00099             logErr(__FILE__,__LINE__,"mere est nul");
00100             return true;
00101         }
00102         coord.x=x;
00103         coord.y=y;
00104     }
00105     else if(relative==2)//relatif à elle même
00106     {
00107         coord.x+=x;
00108         coord.y+=y;
00109     }
00110     else//absolu
00111     {
00112         //soustraire tour à tour les coordonées de chaque mère pour avoir les coordonnées relatives finales.
00113         PFen *ptrMere=mere;
00114         if(ptrMere)
00115         {
00116             coord.x=0;
00117             coord.y=0;
00118             while(ptrMere)
00119             {
00120                 coord.x+=ptrMere->coord.x;
00121                 coord.y+=ptrMere->coord.y;
00122                 ptrMere=ptrMere->mere;
00123             }//c contient les coordonnées du point 0,0 de la fenetre
00124             coord.x-=x;
00125             coord.y-=y;
00126         }
00127         else
00128         {
00129             coord.x=x;
00130             coord.y=y;
00131         }
00132     }
00133     return false;
00134 }
00135 
00136 //Déplace la fenêtre dans la fenêtre mère. Positions en % de la mère.
00137 //true si échec.
00138 bool PFen::Move(float x, float y)
00139 {
00140 
00141     if(!mere)
00142     {
00143         logErr(__FILE__,__LINE__,"mere est nul");
00144         return true;
00145     }
00146     return Move((short)(mere->coord.w*x),(short)(mere->coord.h*y),1);
00147 }
00148 
00149 //Retourne true si un problème à eu lieu.
00150 bool PFen::ClearWindow(void)
00151 {
00152 
00153     if(drawed)
00154     {
00155         // calcul des coordonées absolues de la fenêtre
00156         SDL_Rect coordAbs=oldCoord;
00157         PFen *ptrMere=this;
00158         while(ptrMere->mere)
00159         {
00160             ptrMere=ptrMere->mere;
00161             coordAbs.x+=ptrMere->oldCoord.x;
00162             coordAbs.y+=ptrMere->oldCoord.y;
00163         }
00164 
00165         for_each(filles.rbegin(),filles.rend(),mem_fun(&PFen::ClearWindow));
00166         if(SDL_BlitSurface(shadow,NULL,screen,&coordAbs))
00167         {
00168             logErr(__FILE__,__LINE__,SDL_GetError());
00169             return true;
00170         }
00171         drawed=false;
00172     }
00173     return false;
00174 }
00175 
00176 //retourne true si problème
00177 bool PFen::PrepareWindow(void)
00178 {
00179 
00180     //NOTE regarder du côté de SDL_gfx pour gérer les zoom et agrandissements
00181     //NOTE pour éviter les problèmes: avoir des textures pour les traits de 1px de longueur OU calculer la dimension de la fenêtre précisément. Sinon, risque d'avoir un empiètement sur les coins.
00182     if(!needInit)
00183         return false;
00184     if(!border || !body)
00185     {
00186         logErr(__FILE__,__LINE__,"border(=%x) ou body(=%x) n'ont pas été initialisés",(unsigned int)border,(unsigned int)body);
00187         return true; //si border n'à pas été initialisée, retourner une erreur
00188     }
00189     SDL_Rect destRect= {0,0,0,0};
00190     Uint32 flags=(screen->flags)&(SDL_SWSURFACE|SDL_HWSURFACE|SDL_SRCCOLORKEY|SDL_SRCALPHA);
00191     int bpp=screen->format->BitsPerPixel;
00192 
00193     SDL_FreeSurface(shadow);
00194     SDL_FreeSurface(window);
00195     shadow=SDL_CreateRGBSurface(flags,coord.w, coord.h, bpp, 0, 0, 0, 0);
00196     if(!shadow)
00197     {
00198         logErr(__FILE__,__LINE__,SDL_GetError());
00199         return true;
00200     }
00201 
00202     window=SDL_CreateRGBSurface(flags,coord.w, coord.h, bpp, Rmask, Gmask, Bmask, Amask);
00203     if(!window)
00204     {
00205         logErr(__FILE__,__LINE__,SDL_GetError());
00206         return true;
00207     }
00208 
00209     destRect.x=border->width[HAUTDROITE];
00210     destRect.y=border->height[HAUTGAUCHE];
00211     if(SDL_BlitSurface(body,NULL,window, &destRect))
00212     {
00213         logErr(__FILE__,__LINE__,SDL_GetError());
00214         return true;
00215     }
00216 
00217     destRect.x=0;
00218     destRect.y=0;
00219     destRect.w=coord.w;
00220     destRect.h=coord.h;
00221     border->Draw(window,&destRect);
00222 
00223     needInit=false;
00224     return false;
00225 }
00226 
00227 PFen::PFen(void)
00228     :Rmask(0)
00229     ,Gmask(0)
00230     ,Bmask(0)
00231     ,Amask(0)
00232     ,filles()
00233     ,coord()
00234     ,mere(0)
00235     ,shadow(0)
00236     ,window(0)
00237     ,body(0)
00238     ,border(0)
00239     ,refEvent()
00240     ,screen(0)
00241     ,oldCoord()
00242     ,drawed(false)
00243     ,needInit(true)
00244 {
00245     if(SDL_InitSubSystem(SDL_INIT_VIDEO))
00246         logErr(__FILE__,__LINE__,SDL_GetError()); //TODO (#9) Il faudrait aussi utiliser une exception pour empêcher la création d'une fenêtre si le sous-système vidéo à foiré
00247     if(!(screen=SDL_GetVideoSurface()))
00248         logErr(__FILE__,__LINE__,SDL_GetError());
00249     coord.h=0;
00250     coord.w=0;
00251     coord.x=0;
00252     coord.y=0;
00253 }
00254 
00255 PFen::PFen(PFen *Mere)
00256     :Rmask(0)
00257     ,Gmask(0)
00258     ,Bmask(0)
00259     ,Amask(0)
00260     ,filles()
00261     ,coord()
00262     ,mere(Mere)
00263     ,shadow(0)
00264     ,window(0)
00265     ,body(0)
00266     ,border(0)
00267     ,refEvent()
00268     ,screen(mere->screen)
00269     ,oldCoord()
00270     ,drawed(false)
00271     ,needInit(true)
00272 {
00273 }
00274 
00275 void PFen::SetMasks(unsigned long rmask, unsigned long gmask, unsigned long bmask, unsigned long amask)
00276 {
00277     needInit=true;
00278     Rmask=rmask;
00279     Gmask=gmask;
00280     Bmask=bmask;
00281     Amask=amask;
00282 }
00283 
00284 list<PFen*>::iterator PFen::CreateSubWindow(void)
00285 {
00286     filles.push_front(new PFen(this));
00287     return filles.begin();
00288 }
00289 
00290 //si tout est ok, renvoie false.
00291 bool PFen::InitTextures(BorderTexture *bordTex,char* filebody)
00292 {
00293     needInit=true;
00294     border=bordTex;
00295     SDL_FreeSurface(body);
00296     if(!filebody)
00297     {
00298         logErr(__FILE__,__LINE__,"filebody vaut NULL\n");
00299         return false;
00300     }
00301     if(!border)
00302     {
00303         logErr(__FILE__,__LINE__,"bordTex vaut NULL\n");
00304         return false;
00305     }
00306     if(!(body=SDL_LoadBMP(filebody)))
00307     {
00308         logErr(__FILE__,__LINE__,SDL_GetError());
00309         return true;
00310     }
00311 
00312     if(border->isInit())
00313         return false;
00314     return true;
00315 }
00316 
00317 bool PFen::SetAlpha(unsigned char alpha,bool srcAlpha,bool rleAccel)
00318 {
00319     Amask=alpha;
00320     if(SDL_SetAlpha(window,(srcAlpha*SDL_SRCALPHA)|(rleAccel*SDL_RLEACCEL),alpha))
00321     {
00322         logErr(__FILE__,__LINE__,SDL_GetError());
00323         return true;
00324     }
00325     return false;
00326 }
00327 
00328 void PFen::calcCoord(SDL_Rect *c)
00329 {
00330     // calcul des coordonées absolues de la fenêtre
00331     PFen *ptrMere=this;
00332     while(ptrMere->mere)
00333     {
00334         ptrMere=ptrMere->mere;
00335         c->x+=ptrMere->coord.x;
00336         c->y+=ptrMere->coord.y;
00337     }
00338 }
00339 
00340 PFen::~PFen(void)
00341 {
00342     if(mere)
00343         mere->filles.remove(this);
00344 
00345     while (!filles.empty())
00346         delete filles.front();
00347     SDL_FreeSurface(shadow);
00348     SDL_FreeSurface(window);
00349     SDL_FreeSurface(body);
00350 }
00351 
00352 PFen::PFen(PFen &source, PFen *Mere)
00353     :Rmask(source.Rmask)
00354     ,Gmask(source.Gmask)
00355     ,Bmask(source.Bmask)
00356     ,Amask(source.Amask)
00357     ,filles()
00358     ,coord(source.coord)
00359     ,mere(source.mere)
00360     ,shadow(0)
00361     ,window(0)
00362     ,body(source.body)
00363     ,border(source.border)
00364     ,refEvent()
00365     ,screen(source.screen)
00366     ,oldCoord()
00367     ,drawed(false)
00368     ,needInit(true) // window et shadow DOIVENT être réinitialisées (ou alors, il faut que je les duplique, ce qui pourrait économiser de la ressource de calcul)
00369 {
00370     list<PFen*>::iterator it;
00371     coord.h=source.coord.h;
00372     coord.w=source.coord.w;
00373     coord.x=source.coord.x;
00374     coord.y=source.coord.y;
00375 
00376     if(Mere)
00377         mere=Mere;
00378 
00379     if(mere)
00380         (mere->filles).push_back(this);
00381 
00382     if(body)
00383         body->refcount++;
00384     for(it=source.filles.begin();it!=source.filles.end();it++)
00385         filles.push_back(new PFen(**it,this));
00386 }
00387 
00388 PFen &PFen::operator=(PFen &source)
00389 {
00390     Rmask=source.Rmask;
00391     Gmask=source.Gmask;
00392     Bmask=source.Bmask;
00393     Amask=source.Amask;
00394     coord.h=source.coord.h;
00395     coord.w=source.coord.w;
00396     coord.x=source.coord.x;
00397     coord.y=source.coord.y;
00398     mere=source.mere;
00399     shadow=0;
00400     window=0;
00401     body=source.body;
00402     border=source.border;
00403     screen=source.screen;
00404     drawed=false;
00405     needInit=true; // window et shadow DOIVENT être réinitialisées (ou alors, il faut que je les duplique, ce qui pourrait économiser de la ressource de calcul)
00406 
00407     list<PFen*>::iterator it;
00408 
00409     if(mere)
00410         (mere->filles).push_back(this);
00411 
00412     if(body)
00413         body->refcount++;
00414 
00415     //trouver le moyen de remplacer par un for_each également
00416     for(it=source.filles.begin();it!=source.filles.end();it++)
00417         filles.push_back(new PFen(**it,this));
00418     return *this;
00419     // TODO (Bérenger#9#): Méthode à tester. Devrait fonctionner, vu le peu de différences avec le constructeur de copie, mais prudence est mère de sûreté.
00420 }
00421 // TODO : vérifier que dans le cas ou 2 fenetres non affiliées dont l'ordre d'affichage ne suit aucun ordre prédéfini ne causent pas d'altération des graphismes lorsqu'elles se chevauchent
00422 
00423 /* TODO ajouter la gestion des timers:
00424 Questions:
00425 _ la gestion de timer pourrait-elle être intéressante?
00426     _si oui, s'inspirer de la classe d'empilage d'event de référence:
00427 
00428 */
00429 
00430 bool PFen::testEvent(const SDL_Event *evnt)
00431 {
00432     event=(SDL_Event*)evnt;
00433     pTestEvent();
00434     return evFired;
00435 }
00436 
00437 bool PFen::pTestEvent(void)
00438 {
00439 //TODO définir une exception
00440 /*
00441     try
00442     {
00443         for_each(refEvent.begin(),refEvent.end(),testEvent); //ne marche pas car testEvent prend un argument
00444         for_each(filles.begin(),filles.end(),mem_fun(pTestEvent));
00445     }
00446     catch(MonException)
00447     {
00448         evFired=true;
00449         throw;
00450     }
00451     evFired=false;
00452 */
00453     return false;
00454 }

Généré le Sun Nov 15 16:53:06 2009 pour PFen par  doxygen 1.6.1