Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencardrgnmouse.cppGo 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
1.6.3
|