Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

pgwidgetdnd.cpp

Go to the documentation of this file.
00001 /*
00002     ParaGUI - crossplatform widgetset
00003     Copyright (C) 2000,2001,2002  Alexander Pipelka
00004  
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009  
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014  
00015     You should have received a copy of the GNU Library General Public
00016     License along with this library; if not, write to the Free
00017     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  
00019     Alexander Pipelka
00020     pipelka@teleweb.at
00021  
00022     Last Update:      $Author: mbickel $
00023     Update Date:      $Date: 2008-04-20 16:44:34 $
00024     Source File:      $Source: /home/cvspsrv/cvsroot/games/asc/source/libs/paragui/src/widgets/pgwidgetdnd.cpp,v $
00025     CVS/RCS Revision: $Revision: 1.3 $
00026     Status:           $State: Exp $
00027 */
00028 
00029 #include "pgwidgetdnd.h"
00030 #include "pgapplication.h"
00031 #include "pgdraw.h"
00032 #include "pgeventsupplier.h"
00033 
00034 PG_WidgetDnD* PG_WidgetDnD::dnd_objectlist = NULL;
00035 
00036 PG_WidgetDnD::PG_WidgetDnD(PG_Widget* parent, int dndID, const PG_Rect& r) :
00037                 PG_Widget(parent, r, false),
00038                 CanDrag(true),
00039                 CanDrop(true),
00040                 Draging(false),
00041                 dragimage(NULL),
00042 dragimagecache(NULL) {
00043         SetID(dndID);
00044 
00045         // put myself into the dnd chain
00046         dnd_next = dnd_objectlist;
00047         dnd_objectlist = this;
00048 }
00049 
00050 PG_WidgetDnD::PG_WidgetDnD(PG_Widget* parent, int dndID, const PG_Rect& r, bool bCreateSurface) :
00051                 PG_Widget(parent, r, bCreateSurface),
00052                 CanDrag(true),
00053                 CanDrop(true),
00054                 Draging(false),
00055                 dragimage(NULL),
00056 dragimagecache(NULL) {
00057         SetID(dndID);
00058 
00059         // put myself into the dnd chain
00060         dnd_next = dnd_objectlist;
00061         dnd_objectlist = this;
00062 }
00063 
00064 PG_WidgetDnD::~PG_WidgetDnD() {
00065         RemoveObjectDnD(this);
00066 }
00067 
00069 bool PG_WidgetDnD::GetDrag() {
00070         return CanDrag;
00071 }
00072 
00074 bool PG_WidgetDnD::GetDrop() {
00075         return CanDrop;
00076 }
00077 
00079 void PG_WidgetDnD::RemoveObjectDnD(PG_WidgetDnD* obj) {
00080         PG_WidgetDnD* obj_before = NULL;
00081         PG_WidgetDnD* list = dnd_objectlist;
00082 
00083         // search the object
00084         while((list != NULL) && (list != obj)) {
00085                 obj_before = list;
00086                 list = list->dnd_next;
00087         }
00088 
00089         // check if object was found
00090         if(list == NULL)
00091                 return;
00092 
00093         // remove the object from the chain
00094 
00095         if(obj_before == NULL)
00096                 dnd_objectlist = this->dnd_next;
00097         else {
00098                 obj_before->dnd_next = obj->dnd_next;
00099         }
00100         obj->dnd_next = NULL;
00101 }
00102 
00104 PG_WidgetDnD* PG_WidgetDnD::FindDropTarget(PG_Point pt) {
00105         PG_WidgetDnD* list = dnd_objectlist;
00106 
00107         // Process all DnD widgets
00108         while(list != NULL) {
00109                 if(list->IsInside(pt) && list->IsVisible()) {                                   // drop point inside widget -> possible detection (kind regards seti)
00110                         break;
00111                 }
00112                 list = list->dnd_next;
00113         }
00114 
00115         if(list == NULL) {                                                      // no drop target found
00116                 return NULL;
00117         }
00118 
00119         if(!list->GetDrop()) {                                  // check if target is able to catch drops
00120                 return NULL;
00121         }
00122 
00123         if(list->AcceptDrop(this, GetID())) {           // ask if we may drop
00124                 return list;
00125         }
00126 
00127         return NULL;            // no one wants us to drop on them
00128 }
00129 
00131 bool PG_WidgetDnD::AcceptDrop(PG_WidgetDnD* source, int dndID) {
00132         return CanDrop;
00133 }
00134 
00136 void PG_WidgetDnD::SetDrag(bool drag) {
00137         CanDrag = drag;
00138 }
00139 
00141 void PG_WidgetDnD::SetDrop(bool drop) {
00142         CanDrop = drop;
00143 }
00144 
00146 bool PG_WidgetDnD::eventDragStart() {
00147         return true;
00148 }
00149 
00151 bool PG_WidgetDnD::eventMouseButtonDown(const SDL_MouseButtonEvent* button) {
00152         int x,y;
00153 
00154         PG_Application::GetEventSupplier()->GetMouseState(x, y);
00155         CheckCursorPos(x, y);
00156 
00157         if((button->button == 1) && CanDrag) {
00158                 SetCapture();
00159 
00160                 dragPointOld.x = x;
00161                 dragPointOld.y = y;
00162 
00163                 dragPointStart.x = x;
00164                 dragPointStart.y = y;
00165 
00166                 Draging = true;
00167                 eventDragStart();
00168                 dragimage = eventQueryDragImage();
00169 
00170                 if(dragimage != NULL) {
00171                         dragimagecache = PG_Draw::CreateRGBSurface(dragimage->w, dragimage->h);
00172                 }
00173 
00174                 cacheDragArea(dragPointOld);
00175 
00176                 return true;
00177         }
00178 
00179         return false;
00180 }
00181 
00183 bool PG_WidgetDnD::eventMouseMotion(const SDL_MouseMotionEvent* motion) {
00184         PG_WidgetDnD* target = NULL;
00185         SDL_Surface* dropimage = NULL;
00186 
00187         int x,y;
00188         PG_Point pt;
00189 
00190         PG_Application::GetEventSupplier()->GetMouseState(x, y);
00191         CheckCursorPos(x, y);
00192         pt.x = x;
00193         pt.y = y;
00194 
00195         // Process message if we are in drag-mode
00196         if(Draging) {
00197 
00198                 if(dragimage == NULL) {
00199                         return true;
00200                 }
00201 
00202                 target = FindDropTarget(pt);
00203 
00204                 if(target != NULL) {
00205                         dropimage = target->eventQueryDropImage(dragimage);
00206 
00207                         if(dropimage != NULL) {
00208                                 dragimage = dropimage;
00209                         }
00210                 } else {
00211                         dragimage = eventQueryDragImage();
00212                 }
00213 
00214                 dragPointCurrent.x = x;
00215                 dragPointCurrent.y = y;
00216 
00217                 // restore area on old drag position
00218                 restoreDragArea(dragPointOld);
00219 
00220                 // copy new area into cache
00221                 cacheDragArea(dragPointCurrent);
00222 
00223                 // paint and update new drag area
00224                 drawDragArea(dragPointCurrent, dragimage);
00225                 updateDragArea(dragPointCurrent, dragimage);
00226 
00227                 //  update old dragposition (screen)
00228                 updateDragArea(dragPointOld, dragimagecache);
00229 
00230                 // old = current
00231                 dragPointOld.x = x;
00232                 dragPointOld.y = y;
00233 
00234                 return true;
00235         }
00236 
00237         return  PG_Widget::eventMouseMotion(motion);
00238 }
00239 
00241 bool PG_WidgetDnD::eventMouseButtonUp(const SDL_MouseButtonEvent* button) {
00242         PG_WidgetDnD* target = NULL;
00243         int x,y;
00244         PG_Point pt;
00245 
00246         PG_Application::GetEventSupplier()->GetMouseState(x, y);
00247         CheckCursorPos(x, y);
00248 
00249         pt.x = x;
00250         pt.y = y;
00251 
00252         if((button->button == 1) && Draging) {
00253                 target = FindDropTarget(pt);
00254 
00255                 if(dragimagecache != NULL) {
00256 
00257                         // restore area on old drag position
00258                         restoreDragArea(dragPointOld);
00259 
00260                         //  update old dragposition (screen)
00261 
00262                         drawDragArea(dragPointOld, dragimagecache);
00263                         updateDragArea(dragPointOld, dragimagecache);
00264                 }
00265 
00266                 if(target != NULL) {
00267                         target->eventDragDrop(this, GetID());
00268                 } else {
00269                         slideDragImage(pt, dragPointStart, 20, dragimage);
00270                         eventDragCancel();
00271                 }
00272 
00273                 if(dragimagecache != NULL) {
00274                         // free surface
00275                         PG_Application::UnloadSurface(dragimagecache);
00276 
00277                         dragimage = NULL;
00278                         dragimagecache = NULL;
00279                 }
00280 
00281                 ReleaseCapture();
00282                 Draging = false;
00283 
00284                 return true;
00285         }
00286 
00287         return false;
00288 }
00289 
00291 bool PG_WidgetDnD::eventDragDrop(PG_WidgetDnD* source, int dndID) {
00292         return true;
00293 }
00294 
00296 bool PG_WidgetDnD::eventDragCancel() {
00297         return true;
00298 }
00299 
00301 SDL_Surface* PG_WidgetDnD::eventQueryDragImage() {
00302         return NULL;
00303 }
00304 
00306 void PG_WidgetDnD::cacheDragArea(PG_Point p) {
00307         SDL_Rect srcrect;
00308         SDL_Rect dstrect;
00309 
00310         if(!dragimagecache || !dragimage)
00311                 return;
00312 
00313    PG_Application::ScreenLocker locker(true);
00314 
00315         srcrect.x = p.x;
00316         srcrect.y = p.y;
00317         srcrect.w = dragimagecache->w;
00318         srcrect.h = dragimagecache->h;
00319 
00320         dstrect.x = 0;
00321         dstrect.y = 0;
00322         dstrect.w = dragimagecache->w;
00323         dstrect.h = dragimagecache->h;
00324 
00325         PG_Draw::BlitSurface(PG_Application::GetScreen(), srcrect, dragimagecache, dstrect);
00326 }
00327 
00329 void PG_WidgetDnD::restoreDragArea(PG_Point p) {
00330         SDL_Rect srcrect;
00331         SDL_Rect dstrect;
00332 
00333         if((dragimagecache == NULL) || (dragimage == NULL))
00334                 return;
00335 
00336    PG_Application::ScreenLocker locker(true);
00337 
00338         srcrect.x = 0;
00339         srcrect.y = 0;
00340         srcrect.w = dragimagecache->w;
00341         srcrect.h = dragimagecache->h;
00342 
00343         dstrect.x = p.x;
00344         dstrect.y = p.y;
00345         dstrect.w = dragimagecache->w;
00346         dstrect.h = dragimagecache->h;
00347 
00348         PG_Draw::BlitSurface(dragimagecache, srcrect, PG_Application::GetScreen(), dstrect);
00349 }
00351 void PG_WidgetDnD::CheckCursorPos(int& x, int& y) {
00352 
00353         if(dragimage == NULL)
00354                 return;
00355 
00356         x -= dragimage->w / 2;
00357         y -= dragimage->h / 2;
00358 
00359         if(x<0)
00360                 x=0;
00361         if(y<0)
00362                 y=0;
00363 
00364         if(x + dragimage->w > PG_Application::GetScreen()->w)
00365                 x = PG_Application::GetScreen()->w - dragimage->w;
00366 
00367         if(y + dragimage->h > PG_Application::GetScreen()->h)
00368                 y = PG_Application::GetScreen()->h - dragimage->h;
00369 }
00370 
00372 SDL_Surface* PG_WidgetDnD::eventQueryDropImage(SDL_Surface* dragimage) {
00373         return NULL;
00374 }
00376 void PG_WidgetDnD::drawDragArea(PG_Point pt, SDL_Surface* image) {
00377         SDL_Rect srcrect;
00378         SDL_Rect dstrect;
00379 
00380         srcrect.x = 0;
00381         srcrect.y = 0;
00382         srcrect.w = image->w;
00383         srcrect.h = image->h;
00384 
00385         dstrect.x = pt.x;
00386         dstrect.y = pt.y;
00387         dstrect.w = image->w;
00388         dstrect.h = image->h;
00389 
00390    PG_Application::ScreenLocker locker(true);
00391         PG_Draw::BlitSurface(image, srcrect, PG_Application::GetScreen(), dstrect);
00392 
00393 }
00395 void PG_WidgetDnD::updateDragArea(PG_Point pt, SDL_Surface* image) {
00396         SDL_Rect dstrect;
00397 
00398         dstrect.x = pt.x;
00399         dstrect.y = pt.y;
00400         dstrect.w = image->w;
00401         dstrect.h = image->h;
00402 
00403         PG_Application::UpdateRects(PG_Application::GetScreen(), 1, &dstrect);
00404 }
00405 
00407 void PG_WidgetDnD::slideDragImage(PG_Point start, PG_Point end, int steps, SDL_Surface* image) {
00408         double dx, dy;
00409         PG_Point current,old;
00410 
00411         dx = end.x - start.x;
00412         dy = end.y - start.y;
00413 
00414         dx /= steps;
00415         dy /= steps;
00416 
00417         for(int i=0; i<steps; i++) {
00418                 current.x = (int)((double)start.x + (double)i*dx);
00419                 current.y = (int)((double)start.y + (double)i*dy);
00420 
00421                 if(i>0) {
00422                         drawDragArea(old, dragimagecache);
00423                 }
00424 
00425                 cacheDragArea(current);
00426                 drawDragArea(current, dragimage);
00427                 updateDragArea(current, dragimage);
00428 
00429                 if(i>0) {
00430                         updateDragArea(old, dragimagecache);
00431                 }
00432 
00433                 old = current;
00434 
00435                 SDL_Delay(10);
00436         }
00437 
00438         drawDragArea(old, dragimagecache);
00439         updateDragArea(old, dragimagecache);
00440 }

Generated on Tue Jun 24 01:27:50 2008 for Advanced Strategic Command by  doxygen 1.4.2