Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cardrgnmouse.cpp

Go to the documentation of this file.
00001 //
00002 //    CardLib - CardRegion mouse-related stuff
00003 //
00004 //    Freeware
00005 //    Copyright J Brown 2001
00006 //
00007 #include <windows.h>
00008 #include <math.h>
00009 #include <stdio.h>
00010 
00011 #include "cardlib.h"
00012 #include "cardwindow.h"
00013 #include "cardregion.h"
00014 
00015 #if 1
00016 #define TRACE(s)
00017 #else
00018 #define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s)
00019 #endif
00020 
00021 double __CARDZOOMSPEED = 32;
00022 
00023 int ClipCard(HDC hdc, int x, int y, int width, int height);
00024 void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);
00025 
00026 #ifdef _DEBUG
00027 
00028 static pDebugClickProc DebugStackClickProc = 0;
00029 
00030 void CardLib_SetStackClickProc(pDebugClickProc proc)
00031 {
00032     DebugStackClickProc = proc;
00033 }
00034 
00035 #endif
00036 
00037 CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h)
00038 {
00039     int maxoverlap    =  0;
00040     int maxoverlapidx = -1;
00041 
00042     //find the stack which is most covered by the dropped
00043     //cards. Only include those which allow drops.
00044     //
00045     for(int i = 0; i < nNumCardRegions; i++)
00046     {
00047         int percent = Regions[i]->GetOverlapRatio(x, y, w, h);
00048 
00049         //if this stack has the biggest coverage yet
00050         if(percent > maxoverlap && Regions[i]->IsVisible())
00051         {
00052             maxoverlap = percent;
00053             maxoverlapidx = i;
00054         }
00055     }
00056 
00057     //if we found a stack to drop onto
00058     if(maxoverlapidx != -1)
00059     {
00060         return Regions[maxoverlapidx];
00061     }
00062     else
00063     {
00064         return 0;
00065     }
00066 }
00067 
00068 bool CardRegion::IsPointInStack(int x, int y)
00069 {
00070     int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos;
00071     int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos;
00072 
00073     if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible)
00074         return true;
00075     else
00076         return false;
00077 }
00078 
00079 int CardRegion::GetNumDragCards(int x, int y)
00080 {
00081     int cardindex = 0;        //index from stack start
00082     int maxidx;
00083 
00084     //make x,y relative to the stack's upper left corner
00085     x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0);
00086     y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0);
00087 
00088     //if stack is empty, cannot drag any cards from it
00089     if(cardstack.NumCards() <= 0)
00090         return 0;
00091 
00092     //see which card in the stack has been clicked on
00093     //top-bottom ordering
00094     if(yoffset > 0)
00095     {
00096         if(y < height - __cardheight)
00097             cardindex = y / yoffset;
00098         else
00099             cardindex = cardstack.NumCards() - 1;
00100     }
00101     else if(yoffset < 0)
00102     {
00103         if(y < __cardheight)
00104             cardindex = cardstack.NumCards() - 1;
00105         else
00106             cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2;
00107     }
00108     else    //yoffset == 0
00109     {
00110         cardindex = cardstack.NumCards() - 1;
00111     }
00112 
00113     maxidx = cardindex;
00114 
00115     //if left-right
00116     if(xoffset > 0)
00117     {
00118         if(x < width - __cardwidth)
00119             cardindex = x / xoffset;
00120         else
00121             cardindex = cardstack.NumCards() - 1;
00122     }
00123     else if(xoffset < 0)
00124     {
00125         if(x < __cardwidth)
00126             cardindex = cardstack.NumCards() - 1;
00127         else
00128             cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2;
00129     }
00130     else
00131     {
00132         cardindex = cardstack.NumCards() - 1;
00133     }
00134 
00135     if(cardindex > maxidx) cardindex = maxidx;
00136 
00137     if(cardindex > cardstack.NumCards())
00138         cardindex = 1;
00139 
00140     //if are trying to drag too many cards at once
00141     return cardstack.NumCards() - cardindex;
00142 }
00143 
00144 bool CardRegion::CanDragCards(int iNumCards)
00145 {
00146     if(iNumCards <= 0) return false;
00147     if(nThreedCount > 1 && iNumCards > 1) return false;
00148 
00149     if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
00150     {
00151 //        TRACE("Failed to gain access to card stack\n");
00152         return false;
00153     }
00154 
00155     ReleaseMutex(mxlock);
00156 
00157     switch(uDragRule)
00158     {
00159     case CS_DRAG_ALL:
00160         return true;
00161 
00162     case CS_DRAG_TOP:
00163 
00164         if(iNumCards == 1)
00165             return true;
00166         else
00167             return false;
00168 
00169     case CS_DRAG_NONE:
00170         return false;
00171 
00172     case CS_DRAG_CALLBACK:
00173 
00174         if(CanDragCallback)
00175         {
00176             return CanDragCallback(*this, iNumCards);
00177         }
00178         else
00179         {
00180             return false;
00181         }
00182 
00183     default:
00184         return false;
00185     }
00186 }
00187 
00188 bool CardRegion::CanDropCards(CardStack &cards)
00189 {
00190     if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
00191     {
00192         return false;
00193     }
00194 
00195     ReleaseMutex(mxlock);
00196 
00197     switch(uDropRule)
00198     {
00199     case CS_DROP_ALL:
00200         return true;
00201 
00202     case CS_DROP_NONE:
00203         return false;
00204 
00205     case CS_DROP_CALLBACK:
00206 
00207         if(CanDropCallback)
00208         {
00209             return CanDropCallback(*this, cards);
00210         }
00211         else
00212         {
00213             return false;
00214         }
00215 
00216     default:
00217         return false;
00218     }
00219 }
00220 
00221 bool CardRegion::OnLButtonDblClk(int x, int y)
00222 {
00223     iNumDragCards = GetNumDragCards(x, y);
00224 
00225     if(DblClickCallback)
00226         DblClickCallback(*this, iNumDragCards);
00227 
00228     return true;
00229 }
00230 
00231 bool CardRegion::OnLButtonDown(int x, int y)
00232 {
00233     iNumDragCards = GetNumDragCards(x, y);
00234 
00235 #ifdef _DEBUG
00236     if(DebugStackClickProc)
00237     {
00238         if(!DebugStackClickProc(*this))
00239             return false;
00240     }
00241 #endif
00242 
00243     if(ClickCallback)
00244         ClickCallback(*this, iNumDragCards);
00245 
00246     if(CanDragCards(iNumDragCards) != false)
00247     {
00248 
00249         //offset of the mouse cursor relative to the top-left corner
00250         //of the cards that are being dragged
00251         mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards);
00252         mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards);
00253 
00254         if(xoffset < 0)
00255             mousexoffset += -xoffset * (iNumDragCards - 1);
00256 
00257         if(yoffset < 0)
00258             mouseyoffset += -yoffset * (iNumDragCards - 1);
00259 
00260         //remove the cards from the source stack
00261         dragstack = cardstack.Pop(iNumDragCards);
00262 
00263         //prepare the back buffer, and the drag image
00264         PrepareDragBitmaps(iNumDragCards);
00265 
00266         oldx = x - mousexoffset;
00267         oldy = y - mouseyoffset;
00268 
00269         Update();            //Update this stack's card count + size
00270 
00271         SetCapture((HWND)parentWnd);
00272 
00273         //set AFTER settings the dragstack...
00274         fMouseDragging = true;
00275 
00276         return true;
00277     }
00278 
00279     return false;
00280 }
00281 
00282 void CardRegion::ClickRelease(int x, int y)
00283 {
00284     iNumDragCards = GetNumDragCards(x, y);
00285 
00286     if (ClickReleaseCallback)
00287         ClickReleaseCallback(*this, iNumDragCards); 
00288 }
00289 
00290 bool CardRegion::OnLButtonUp(int x, int y)
00291 {
00292     CardRegion *pDestStack = 0;
00293     HDC hdc;
00294     int dropstackid = CS_DROPZONE_NODROP;
00295 
00296     RECT dragrect;
00297     DropZone *dropzone;
00298 
00299     fMouseDragging = false;
00300 
00301     //first of all, see if any drop zones have been registered
00302     SetRect(&dragrect, x-mousexoffset, y-mouseyoffset, x-mousexoffset+nDragCardWidth, y-mouseyoffset+nDragCardHeight);
00303 
00304     dropzone = parentWnd.GetDropZoneFromRect(&dragrect);
00305 
00306     if(dropzone)
00307     {
00308         dropstackid = dropzone->DropCards(dragstack);
00309 
00310         if(dropstackid != CS_DROPZONE_NODROP)
00311             pDestStack = parentWnd.CardRegionFromId(dropstackid);
00312         else
00313             pDestStack = 0;
00314     }
00315     else
00316     {
00317         pDestStack = parentWnd.GetBestStack(x - mousexoffset, y - mouseyoffset, nDragCardWidth, nDragCardHeight);
00318     }
00319 
00320     // If have found a stack to drop onto
00321     //
00322     TRACE ( "can I drop card?\n" );
00323     if(pDestStack && pDestStack->CanDropCards(dragstack))
00324     {
00325         TRACE ( "yes, dropping card\n" );
00326         hdc = GetDC((HWND)parentWnd);
00327         //            UseNicePalette(hdc);
00328         ZoomCard(hdc, x - mousexoffset, y  - mouseyoffset, pDestStack);
00329         ReleaseDC((HWND)parentWnd, hdc);
00330 
00331         //
00332         //add the cards to the destination stack
00333         //
00334         CardStack temp = pDestStack->GetCardStack();
00335         temp.Push(dragstack);
00336 
00337         pDestStack->SetCardStack(temp);
00338 //        pDestStack->Update();        //Update this stack's card count + size
00339 //        pDestStack->UpdateFaceDir(temp);
00340 
00341         //    Call the remove callback on THIS stack, if one is specified
00342         //
00343         if(RemoveCallback)
00344             RemoveCallback(*this, iNumDragCards);
00345 
00346         //    Call the add callback, if one is specified
00347         //
00348         if(pDestStack->AddCallback)
00349             pDestStack->AddCallback(*pDestStack, pDestStack->cardstack);//index, deststack->numcards);
00350 
00351         RedrawIfNotDim(pDestStack, true);
00352         TRACE ( "done dropping card\n" );
00353     }
00354 
00355     //
00356     //    Otherwise, let the cards snap back onto this stack
00357     //
00358     else
00359     {
00360         TRACE ( "no, putting card back\n" );
00361         hdc = GetDC((HWND)parentWnd);
00362         TRACE ( "calling ZoomCard()\n" );
00363         ZoomCard(hdc, x - mousexoffset, y - mouseyoffset, this);
00364         TRACE ( "cardstack += dragstack\n" );
00365         cardstack += dragstack;
00366         TRACE ( "calling ReleaseDC()\n" );
00367         ReleaseDC((HWND)parentWnd, hdc);
00368 
00369         TRACE ( "calling Update()\n" );
00370         Update();        //Update this stack's card count + size
00371         TRACE ( "done putting card back\n" );
00372     }
00373 
00374     ReleaseDragBitmaps();
00375     ReleaseCapture();
00376 
00377     TRACE ( "OnLButtonUp() done\n" );
00378     return true;
00379 }
00380 
00381 bool CardRegion::OnMouseMove(int x, int y)
00382 {
00383     HDC hdc;
00384 
00385     hdc = GetDC((HWND)parentWnd);
00386 
00387     x -= mousexoffset;
00388     y -= mouseyoffset;
00389 
00390     MoveDragCardTo(hdc, x, y);
00391 
00392     //BitBlt(hdc, nDragCardWidth+10, 0, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);
00393     //BitBlt(hdc, 0, 0, nDragCardWidth, nDragCardHeight, hdcDragCard, 0, 0, SRCCOPY);
00394 
00395     ReleaseDC((HWND)parentWnd, hdc);
00396 
00397     oldx = x;
00398     oldy = y;
00399 
00400     return true;
00401 }
00402 
00403 //
00404 //    There is a bug in BitBlt when the source x,y
00405 //    become < 0. So this wrapper function simply adjusts
00406 //    the coords so that we never try to blt in from this range
00407 //
00408 BOOL ClippedBitBlt(HDC hdcDest, int x, int y, int width, int height, HDC hdcSrc, int srcx, int srcy, DWORD dwROP)
00409 {
00410     if(srcx < 0)
00411     {
00412         x = 0 - srcx;
00413         width = width + srcx;
00414         srcx = 0;
00415     }
00416 
00417     if(srcy < 0)
00418     {
00419         y = 0 - srcy;
00420         height = height + srcy;
00421         srcy = 0;
00422     }
00423 
00424     return BitBlt(hdcDest, x, y, width, height, hdcSrc, srcx, srcy, dwROP);
00425 }
00426 
00427 void CardRegion::MoveDragCardTo(HDC hdc, int x, int y)
00428 {
00429     RECT inter, rect1, rect2;
00430 
00431     //mask off the new position of the drag-card, so
00432     //that it will not be painted over
00433     ClipCard(hdc, x, y, nDragCardWidth, nDragCardHeight);
00434 
00435     //restore the area covered by the card at its previous position
00436     BitBlt(hdc, oldx, oldy, nDragCardWidth, nDragCardHeight, hdcBackGnd, 0, 0, SRCCOPY);
00437 
00438     //remove clipping so we can draw the card at its new place
00439     SelectClipRgn(hdc, NULL);
00440 
00441     //if the card's old and new positions overlap, then we
00442     //need some funky code to update the "saved background" image,
00443     SetRect(&rect1, oldx, oldy, oldx+nDragCardWidth, oldy+nDragCardHeight);
00444     SetRect(&rect2,    x,    y,    x+nDragCardWidth,    y+nDragCardHeight);
00445 
00446     if(IntersectRect(&inter, &rect1, &rect2))
00447     {
00448         int interwidth = inter.right-inter.left;
00449         int interheight = inter.bottom-inter.top;
00450         int destx, desty, srcx, srcy;
00451 
00452         if(rect2.left > rect1.left)
00453         {
00454             destx = 0; srcx = nDragCardWidth - interwidth;
00455         }
00456         else
00457         {
00458             destx = nDragCardWidth  - interwidth; srcx = 0;
00459         }
00460 
00461         if(rect2.top  > rect1.top)
00462         {
00463             desty = 0; srcy = nDragCardHeight - interheight;
00464         }
00465         else
00466         {
00467             desty = nDragCardHeight - interheight; srcy = 0;
00468         }
00469 
00470         //shift the bit we didn't use for the restore (due to the clipping)
00471         //into the opposite corner
00472         BitBlt(hdcBackGnd, destx,desty, interwidth, interheight, hdcBackGnd, srcx, srcy, SRCCOPY);
00473 
00474         ExcludeClipRect(hdcBackGnd, destx, desty, destx+interwidth, desty+interheight);
00475 
00476         //this bit requires us to clip the BitBlt (from screen to background)
00477         //as BitBlt is a bit buggy it seems
00478         ClippedBitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);
00479         SelectClipRgn(hdcBackGnd, NULL);
00480     }
00481     else
00482     {
00483         BitBlt(hdcBackGnd, 0,0, nDragCardWidth, nDragCardHeight, hdc, x, y, SRCCOPY);
00484     }
00485 
00486     //finally draw the card to the screen
00487     DrawCard(hdc, x, y, hdcDragCard, nDragCardWidth, nDragCardHeight);
00488 }
00489 
00490 
00491 //extern "C" int _fltused(void) { return 0; }
00492 //extern "C" int _ftol(void) { return 0; }
00493 
00494 //
00495 //    Better do this in fixed-point, to stop
00496 //    VC from linking in floatingpoint-long conversions
00497 //
00498 //#define FIXED_PREC_MOVE
00499 #ifdef  FIXED_PREC_MOVE
00500 #define PRECISION 12
00501 void ZoomCard(HDC hdc, int xpos, int ypos, CARDSTACK *dest)
00502 {
00503     long dx, dy, x , y;
00504 
00505 
00506     int apparentcards;
00507     x = xpos << PRECISION; y = ypos << PRECISION;
00508 
00509     oldx = (int)xpos;
00510     oldy = (int)ypos;
00511 
00512     apparentcards=dest->numcards/dest->threedcount;
00513 
00514     int idestx = dest->xpos + dest->xoffset * (apparentcards);// - iNumDragCards);
00515     int idesty = dest->ypos + dest->yoffset * (apparentcards);// - iNumDragCards);
00516 
00517     //normalise the motion vector
00518     dx = (idestx<<PRECISION) - x;
00519     dy = (idesty<<PRECISION) - y;
00520     long recip = (1 << PRECISION) / 1;//sqrt(dx*dx + dy*dy);
00521 
00522     dx *= recip * 16;//CARDZOOMSPEED;
00523     dy *= recip * 16;//CARDZOOMSPEED;
00524 
00525     //if(dx < 0) dxinc = 1.001; else
00526 
00527     for(;;)
00528     {
00529         int ix, iy;
00530         x += dx;
00531         y += dy;
00532 
00533         ix = (int)x>>PRECISION;
00534         iy = (int)y>>PRECISION;
00535         if(dx < 0 && ix < idestx) ix = idestx;
00536         else if(dx > 0 && ix > idestx) ix = idestx;
00537 
00538         if(dy < 0 && iy < idesty) iy = idesty;
00539         else if(dy > 0 && iy > idesty) iy = idesty;
00540 
00541         MoveDragCardTo(hdc, ix, iy);
00542 
00543         if(ix == idestx && iy == idesty)
00544             break;
00545 
00546         oldx = (int)x >> PRECISION;
00547         oldy = (int)y >> PRECISION;
00548 
00549         //dx *= 1.2;
00550         //dy *= 1.2;
00551 
00552         Sleep(10);
00553     }
00554 }
00555 #else
00556 void CardRegion::ZoomCard(HDC hdc, int xpos, int ypos, CardRegion *pDestStack)
00557 {
00558     TRACE ( "ENTER ZoomCard()\n" );
00559     double dx, dy, x ,y;
00560     int apparentcards;
00561     x = (double)xpos; y = (double)ypos;
00562 
00563     oldx = (int)x;
00564     oldy = (int)y;
00565 
00566     apparentcards = pDestStack->cardstack.NumCards() / pDestStack->nThreedCount;
00567 
00568     int idestx = pDestStack->xpos + pDestStack->xoffset * (apparentcards);
00569     int idesty = pDestStack->ypos + pDestStack->yoffset * (apparentcards);
00570 
00571     if(pDestStack->yoffset < 0)
00572         idesty += pDestStack->yoffset * (iNumDragCards-1);
00573 
00574     if(pDestStack->xoffset < 0)
00575         idestx += pDestStack->xoffset * (iNumDragCards-1);
00576 
00577     //normalise the motion vector
00578     dx = idestx - x;
00579     dy = idesty - y;
00580     if ( fabs(dx) + fabs(dy) < 0.001f )
00581     {
00582         MoveDragCardTo(hdc, idestx, idesty);
00583         return;
00584     }
00585     double recip = 1.0 / sqrt(dx*dx + dy*dy);
00586     dx *= recip * __CARDZOOMSPEED; dy *= recip * __CARDZOOMSPEED;
00587 
00588     //if(dx < 0) dxinc = 1.001; else
00589 
00590     for(;;)
00591     {
00592         bool attarget = true;
00593         int ix, iy;
00594         x += dx;
00595         y += dy;
00596 
00597         ix = (int)x;
00598         iy = (int)y;
00599 
00600         if(dx < 0.0 && ix < idestx) ix = idestx;
00601         else if(dx > 0.0 && ix > idestx) ix = idestx;
00602         else attarget = false;
00603 
00604         if(dy < 0.0 && iy < idesty) iy = idesty;
00605         else if(dy > 0.0 && iy > idesty) iy = idesty;
00606         else attarget = false;
00607 
00608         //if the target stack wants the drag cards drawn differently
00609         //to how they are, then redraw the drag card image just before
00610         //the cards land
00611         /*if(attarget == true)
00612         {
00613             for(int i = 0; i < iNumDragCards; i++)
00614             {
00615                 int xdraw = pDestStack->xoffset*i;
00616                 int ydraw = pDestStack->yoffset*i;
00617 
00618                 if(pDestStack->yoffset < 0)
00619                     ydraw = -pDestStack->yoffset * (iNumDragCards-i-1);
00620                 if(pDestStack->xoffset < 0)
00621                     xdraw = -pDestStack->xoffset * (iNumDragCards-i-1);
00622 
00623                 if(pDestStack->facedirection == CS_FACEUP &&
00624                     pDestStack->numcards+i >= dest->numfacedown)
00625                 {
00626                     //cdtDraw(hdcDragCard, xdraw, ydraw, iDragCards[i], ectFACES, 0);
00627                 }
00628                 else
00629                 {
00630                     //cdtDraw(hdcDragCard, xdraw, ydraw, CARDSTACK::backcard, ectBACKS, 0);
00631                 }
00632             }
00633         }*/
00634 
00635         MoveDragCardTo(hdc, ix, iy);
00636 
00637         if(attarget || (ix == idestx && iy == idesty))
00638             break;
00639 
00640         oldx = (int)x;
00641         oldy = (int)y;
00642 
00643         //dx *= 1.2;
00644         //dy *= 1.2;
00645 
00646         Sleep(10);
00647     }
00648     TRACE ( "EXIT ZoomCard()\n" );
00649 }
00650 #endif

Generated on Fri Feb 10 04:59:08 2012 for ReactOS by doxygen 1.6.3

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.