2 // CardLib - CardRegion class
5 // Copyright J Brown 2001
10 HBITMAP
CreateSinkBmp(HDC hdcCompat
, HDC hdc
, int width
, int height
);
12 void PaintRect(HDC hdc
, RECT
*rect
, COLORREF colour
);
14 CardRegion::CardRegion(CardWindow
&parent
, int Id
, bool visible
, int x
, int y
, int xOffset
, int yOffset
)
15 : id(Id
), parentWnd(parent
), xpos(x
), ypos(y
), xoffset(xOffset
), yoffset(yOffset
), fVisible(visible
)
18 height
= __cardheight
;
20 crBackgnd
= RGB(0, 64, 100);
22 uFaceDirType
= CS_FACE_UP
;
24 uEmptyImage
= CS_EI_SUNK
;
30 Update(); //Update this stack's size+card count
45 ClickReleaseCallback
= 0;
48 uDragRule
= CS_DRAG_ALL
;
49 uDropRule
= CS_DROP_ALL
;
51 xjustify
= yjustify
= xadjust
= yadjust
= 0;
54 fFlashVisible
= false;
55 uFlashTimer
= (UINT
)-1;
57 fMouseDragging
= false;
59 mxlock
= CreateMutex(0, FALSE
, 0);
62 CardRegion::~CardRegion()
67 void CardRegion::SetBackColor(COLORREF cr
)
72 int CardRegion::CalcApparentCards(int realnum
)
74 return ((realnum
+ nThreedCount
- 1) - (realnum
+ nThreedCount
- 1) % nThreedCount
) / nThreedCount
;
77 void CardRegion::CalcApparentCards()
79 nNumApparentCards
= CalcApparentCards(cardstack
.NumCards());
83 void CardRegion::UpdateSize(void)
85 if(cardstack
.NumCards() > 0)
88 width
= (nNumApparentCards
- 1) * xoffset
+ __cardwidth
;
90 width
= (nNumApparentCards
- 1) * -xoffset
+ __cardwidth
;
93 height
= (nNumApparentCards
- 1) * yoffset
+ __cardheight
;
95 height
= (nNumApparentCards
- 1) * -yoffset
+ __cardheight
;
100 height
= __cardheight
;
104 CardRegion
*CardWindow::CreateRegion(int id
, bool fVisible
, int x
, int y
, int xoffset
, int yoffset
)
108 if(nNumCardRegions
== MAXCARDSTACKS
)
111 cr
= new CardRegion(*this, id
, fVisible
, x
, y
, xoffset
, yoffset
);
112 cr
->SetBackColor(crBackgnd
);
113 cr
->SetBackCardIdx(nBackCardIdx
);
115 Regions
[nNumCardRegions
++] = cr
;
120 int CardRegion::GetOverlapRatio(int x
, int y
, int w
, int h
)
124 SetRect(&him
, x
, y
, x
+w
, y
+h
);
125 SetRect(&me
, xpos
, ypos
, xpos
+width
, ypos
+height
);
127 //see if the specified rectangle overlaps us
128 if(IntersectRect(&inter
, &me
, &him
))
130 int wi
= inter
.right
- inter
.left
;
131 int hi
= inter
.bottom
- inter
.top
;
133 int overlap
= wi
* hi
;
134 int total
= width
* height
;
136 int percent
= (overlap
<< 16) / total
;
137 return (percent
* 100) >> 16;
146 bool CardRegion::SetDragRule(UINT uDragType
, pCanDragProc proc
)
150 case CS_DRAG_NONE
: case CS_DRAG_ALL
: case CS_DRAG_TOP
:
151 uDragRule
= uDragType
;
154 case CS_DRAG_CALLBACK
:
155 uDragRule
= uDragType
;
156 CanDragCallback
= proc
;
164 bool CardRegion::SetDropRule(UINT uDropType
, pCanDropProc proc
)
168 case CS_DROP_NONE
: case CS_DROP_ALL
:
169 uDropRule
= uDropType
;
172 case CS_DROP_CALLBACK
:
173 uDropRule
= uDropType
;
174 CanDropCallback
= proc
;
182 void CardRegion::SetClickProc(pClickProc proc
)
184 ClickCallback
= proc
;
187 void CardRegion::SetClickReleaseProc(pClickProc proc
)
189 ClickReleaseCallback
= proc
;
192 void CardRegion::SetDblClickProc(pClickProc proc
)
194 DblClickCallback
= proc
;
197 void CardRegion::SetAddCardProc(pAddProc proc
)
202 void CardRegion::SetRemoveCardProc(pRemoveProc proc
)
204 RemoveCallback
= proc
;
207 void CardRegion::Update()
211 UpdateFaceDir(cardstack
);
215 bool CardRegion::SetThreedCount(int count
)
223 nThreedCount
= count
;
228 void CardRegion::SetOffsets(int x
, int y
)
234 void CardRegion::SetPos(int x
, int y
)
240 void CardRegion::Show(bool fShow
)
245 bool CardRegion::IsVisible()
250 void CardRegion::SetPlacement(UINT xJustify
, UINT yJustify
, int xAdjust
, int yAdjust
)
258 void CardRegion::SetFaceDirection(UINT uDirType
, int nOption
)
262 case CS_FACE_UP
: case CS_FACE_DOWN
: case CS_FACE_DOWNUP
:
263 case CS_FACE_UPDOWN
: case CS_FACE_ANY
:
264 uFaceDirType
= uDirType
;
265 nFaceDirOption
= nOption
;
267 UpdateFaceDir(cardstack
);
273 UINT
CardRegion::GetFaceDirection(int *pnOption
)
276 *pnOption
= nFaceDirOption
;
281 void CardRegion::AdjustPosition(int winwidth
, int winheight
)
283 Update(); //Update this stack's card count + size
287 default: case CS_XJUST_NONE
: break;
289 case CS_XJUST_CENTER
: //centered
290 xpos
= (winwidth
- (width
& ~0x1)) / 2;
293 if(xoffset
< 0) xpos
+= (width
- __cardwidth
);
297 case CS_XJUST_RIGHT
: //right-aligned
298 xpos
= winwidth
- __cardwidth
;//width - 20;
305 default: case CS_YJUST_NONE
: break;
307 case CS_YJUST_CENTER
: //centered
308 ypos
= (winheight
- height
) / 2;
310 if(yoffset
< 0) ypos
+= (height
- __cardheight
);
313 case CS_YJUST_BOTTOM
: //bottom-aligned
314 ypos
= winheight
- __cardheight
;//height - 20;
322 void CardRegion::Flash(int count
, int milliseconds
)
324 if(count
<= 0) return;
327 fFlashVisible
= false;
328 uFlashTimer
= SetTimer((HWND
)parentWnd
, (WPARAM
)this, milliseconds
, 0);
333 void CardRegion::StopFlash()
335 if(uFlashTimer
!= (UINT
)-1)
337 KillTimer((HWND
)parentWnd
, uFlashTimer
);
339 uFlashTimer
= (UINT
)-1;
340 fFlashVisible
= true;
344 void CardRegion::DoFlash()
346 if(uFlashTimer
!= (UINT
)-1)
348 fFlashVisible
= !fFlashVisible
;
350 if(--nFlashCount
== 0)
352 KillTimer((HWND
)parentWnd
, uFlashTimer
);
353 uFlashTimer
= (UINT
)-1;
354 fFlashVisible
= true;
366 void CardRegion::SetEmptyImage(UINT uImage
)
374 uEmptyImage
= uImage
;
378 uEmptyImage
= CS_EI_NONE
;
384 void CardRegion::SetBackCardIdx(UINT uBackIdx
)
386 if(uBackIdx
>= 52 && uBackIdx
<= 68)
387 nBackCardIdx
= uBackIdx
;
390 void CardRegion::SetCardStack(const CardStack
&cs
)
392 //make a complete copy of the specified stack..
395 // Update the face-direction and stack-size
399 const CardStack
& CardRegion::GetCardStack()
401 //return reference to our internal stack
406 // Update specified card-stack using THIS stack's
407 // face direction rules!
409 void CardRegion::UpdateFaceDir(CardStack
&cards
)
413 num
= cards
.NumCards();
415 //Now apply the face direction rules..
420 for(i
= 0; i
< num
; i
++)
422 cards
[i
].SetFaceUp(true);
429 for(i
= 0; i
< num
; i
++)
431 cards
[i
].SetFaceUp(false);
438 num
= cardstack
.NumCards();
439 n
= min(nFaceDirOption
, num
);
442 for(i
= 0; i
< n
; i
++)
444 cards
[num
- i
- 1].SetFaceUp(false);
447 for(i
= n
; i
< num
; i
++)
449 cards
[num
- i
- 1].SetFaceUp(true);
456 num
= cardstack
.NumCards();
457 n
= min(nFaceDirOption
, num
);
459 for(i
= 0; i
< n
; i
++)
461 cards
[num
- i
- 1].SetFaceUp(true);
464 for(i
= n
; i
< num
; i
++)
466 cards
[num
- i
- 1].SetFaceUp(false);
471 case CS_FACE_ANY
: //cards can be any orientation
477 bool CardRegion::MoveCard(CardRegion
*pDestStack
, int nNumCards
, bool fAnimate
)
483 if(pDestStack
== 0) return false; //{ forcedfacedir = -1 ;return 0; }
485 if(nNumCards
< 0 || nNumCards
> cardstack
.NumCards())
488 x
= xpos
+ xoffset
* (nNumApparentCards
- nNumCards
);
489 y
= ypos
+ yoffset
* (nNumApparentCards
- nNumCards
);
494 dragstack
= cardstack
.Pop(nNumCards
);
496 //Alter the drag-stack so that it's cards are the same way up
497 //as the destination. Use the destination's drag-rules
498 //instead of this ones!!
500 temp
.Push(pDestStack
->GetCardStack());
501 temp
.Push(dragstack
);
503 pDestStack
->UpdateFaceDir(temp
);
505 dragstack
= temp
.Pop(nNumCards
);
509 iNumDragCards
= nNumCards
;
510 PrepareDragBitmaps(nNumCards
);
513 Update(); //Update this stack's size+card count
517 hdc
= GetDC((HWND
)parentWnd
);
519 ZoomCard(hdc
, x
, y
, pDestStack
);
521 ReleaseDC((HWND
)parentWnd
, hdc
);
522 ReleaseDragBitmaps();
525 // Get a copy of the cardstack
526 CardStack cs
= pDestStack
->GetCardStack();
529 pDestStack
->SetCardStack(cs
);
531 //cs = pDestStack->GetCardStack();
532 //pDestStack->Update();
533 //pDestStack->UpdateFaceDir(cs);
535 RedrawIfNotDim(pDestStack
, false);
537 //forcedfacedir = -1;
544 int CardRegion::NumCards() const
547 return cardstack
.NumCards() + dragstack
.NumCards();
549 return cardstack
.NumCards();
552 bool CardRegion::Lock()
554 DWORD dw
= WaitForSingleObject(mxlock
, 0);
556 if(dw
== WAIT_OBJECT_0
)
558 //TRACE("LockStack succeeded\n");
563 //TRACE("LockStack failed\n");
569 bool CardRegion::UnLock()
571 if(ReleaseMutex(mxlock
))
573 //TRACE("Unlocking stack\n");
578 //TRACE("Unlocking stack failed\n");
583 bool CardRegion::PlayCard(CardRegion
*pDestStack
, int value
, int num
)
585 //search the stack for the specified card value...
588 for(int i
= 0; i
< cardstack
.NumCards(); i
++)
590 if(cardstack
[i
].HiVal() == value
)
592 //swap the card with one at top pos...
593 Card card
= cardstack
.RemoveCard(i
);
594 cardstack
.Push(card
);
598 MoveCard(pDestStack
, 1, true);
608 // Redraw the current stack if it has a different
609 // layout than the comparison stack.
611 void CardRegion::RedrawIfNotDim(CardRegion
*pCompare
, bool fFullRedraw
)
616 if( pCompare
->xoffset
!= xoffset
||
617 pCompare
->yoffset
!= yoffset
||
618 pCompare
->nThreedCount
!= nThreedCount
||
619 pCompare
->uFaceDirType
!= uFaceDirType
||
620 pCompare
->uFaceDirType
!= CS_FACE_ANY
632 // SimulateDrag mimicks the complete drag+drop process.
633 // It basically just a MoveCard(..), but it calls the
634 // event callbacks as well.
636 bool CardRegion::SimulateDrag(CardRegion
*pDestStack
, int iNumDragCards
, bool fAnimate
)
641 if(CanDragCards(iNumDragCards
) != false)
643 if(pDestStack
->CanDropCards(cardstack
))
645 MoveCard(pDestStack
, iNumDragCards
, fAnimate
);
648 RemoveCallback(*this, iNumDragCards
);
650 if(pDestStack
->AddCallback
)
651 pDestStack
->AddCallback(*pDestStack
, pDestStack
->cardstack
);
653 RedrawIfNotDim(pDestStack
, true);