2 // CardLib - CardRegion class
5 // Copyright J Brown 2001
10 #include "cardregion.h"
11 #include "cardwindow.h"
12 #include "cardcolor.h"
14 HBITMAP
CreateSinkBmp(HDC hdcCompat
, HDC hdc
, int width
, int height
);
16 void PaintRect(HDC hdc
, RECT
*rect
, COLORREF colour
);
18 CardRegion::CardRegion(CardWindow
&parent
, int Id
, bool visible
, int x
, int y
, int xOffset
, int yOffset
)
19 : parentWnd(parent
), id(Id
), fVisible(visible
), xpos(x
), ypos(y
), xoffset(xOffset
), yoffset(yOffset
)
22 height
= __cardheight
;
24 crBackgnd
= RGB(0, 64, 100);
26 uFaceDirType
= CS_FACE_UP
;
28 uEmptyImage
= CS_EI_SUNK
;
35 Update(); //Update this stack's size+card count
52 uDragRule
= CS_DRAG_ALL
;
53 uDropRule
= CS_DROP_ALL
;
55 xjustify
= yjustify
= xadjust
= yadjust
= 0;
58 fFlashVisible
= false;
61 fMouseDragging
= false;
63 mxlock
= CreateMutex(0, FALSE
, 0);
66 CardRegion::~CardRegion()
71 void CardRegion::SetBackColor(COLORREF cr
)
76 int CardRegion::CalcApparentCards(int realnum
)
78 return ((realnum
+ nThreedCount
- 1) - (realnum
+ nThreedCount
- 1) % nThreedCount
) / nThreedCount
;
81 void CardRegion::CalcApparentCards()
83 nNumApparentCards
= CalcApparentCards(cardstack
.NumCards());
87 void CardRegion::UpdateSize(void)
89 if(cardstack
.NumCards() > 0)
92 width
= (nNumApparentCards
- 1) * xoffset
+ __cardwidth
;
94 width
= (nNumApparentCards
- 1) * -xoffset
+ __cardwidth
;
97 height
= (nNumApparentCards
- 1) * yoffset
+ __cardheight
;
99 height
= (nNumApparentCards
- 1) * -yoffset
+ __cardheight
;
104 height
= __cardheight
;
108 CardRegion
*CardWindow::CreateRegion(int id
, bool fVisible
, int x
, int y
, int xoffset
, int yoffset
)
112 if(nNumCardRegions
== MAXCARDSTACKS
)
115 cr
= new CardRegion(*this, id
, fVisible
, x
, y
, xoffset
, yoffset
);
116 cr
->SetBackColor(crBackgnd
);
117 cr
->SetBackCardIdx(nBackCardIdx
);
119 Regions
[nNumCardRegions
++] = cr
;
124 int CardRegion::GetOverlapRatio(int x
, int y
, int w
, int h
)
128 SetRect(&him
, x
, y
, x
+w
, y
+h
);
129 SetRect(&me
, xpos
, ypos
, xpos
+width
, ypos
+height
);
131 //see if the specified rectangle overlaps us
132 if(IntersectRect(&inter
, &me
, &him
))
134 int wi
= inter
.right
- inter
.left
;
135 int hi
= inter
.bottom
- inter
.top
;
137 int overlap
= wi
* hi
;
138 int total
= width
* height
;
140 int percent
= (overlap
<< 16) / total
;
141 return (percent
* 100) >> 16;
150 bool CardRegion::SetDragRule(UINT uDragType
, pCanDragProc proc
)
154 case CS_DRAG_NONE
: case CS_DRAG_ALL
: case CS_DRAG_TOP
:
155 uDragRule
= uDragType
;
158 case CS_DRAG_CALLBACK
:
159 uDragRule
= uDragType
;
160 CanDragCallback
= proc
;
168 bool CardRegion::SetDropRule(UINT uDropType
, pCanDropProc proc
)
172 case CS_DROP_NONE
: case CS_DROP_ALL
:
173 uDropRule
= uDropType
;
176 case CS_DROP_CALLBACK
:
177 uDropRule
= uDropType
;
178 CanDropCallback
= proc
;
186 void CardRegion::SetClickProc(pClickProc proc
)
188 ClickCallback
= proc
;
191 void CardRegion::SetDblClickProc(pClickProc proc
)
193 DblClickCallback
= proc
;
196 void CardRegion::SetAddCardProc(pAddProc proc
)
201 void CardRegion::SetRemoveCardProc(pRemoveProc proc
)
203 RemoveCallback
= proc
;
206 void CardRegion::Update()
210 UpdateFaceDir(cardstack
);
214 bool CardRegion::SetThreedCount(int count
)
222 nThreedCount
= count
;
227 void CardRegion::SetOffsets(int x
, int y
)
233 void CardRegion::SetPos(int x
, int y
)
239 void CardRegion::Show(bool fShow
)
244 bool CardRegion::IsVisible()
249 void CardRegion::SetPlacement(UINT xJustify
, UINT yJustify
, int xAdjust
, int yAdjust
)
257 void CardRegion::SetFaceDirection(UINT uDirType
, int nOption
)
261 case CS_FACE_UP
: case CS_FACE_DOWN
: case CS_FACE_DOWNUP
:
262 case CS_FACE_UPDOWN
: case CS_FACE_ANY
:
263 uFaceDirType
= uDirType
;
264 nFaceDirOption
= nOption
;
266 UpdateFaceDir(cardstack
);
272 UINT
CardRegion::GetFaceDirection(int *pnOption
)
275 *pnOption
= nFaceDirOption
;
280 void CardRegion::AdjustPosition(int winwidth
, int winheight
)
282 Update(); //Update this stack's card count + size
286 default: case CS_XJUST_NONE
: break;
288 case CS_XJUST_CENTER
: //centered
289 xpos
= (winwidth
- (width
& ~0x1)) / 2;
292 if(xoffset
< 0) xpos
+= (width
- __cardwidth
);
296 case CS_XJUST_RIGHT
: //right-aligned
297 xpos
= winwidth
- __cardwidth
;//width - 20;
304 default: case CS_YJUST_NONE
: break;
306 case CS_YJUST_CENTER
: //centered
307 ypos
= (winheight
- height
) / 2;
309 if(yoffset
< 0) ypos
+= (height
- __cardheight
);
312 case CS_YJUST_BOTTOM
: //bottom-aligned
313 ypos
= winheight
- __cardheight
;//height - 20;
321 void CardRegion::Flash(int count
, int milliseconds
)
323 if(count
<= 0) return;
326 fFlashVisible
= false;
327 uFlashTimer
= SetTimer((HWND
)parentWnd
, (WPARAM
)this, milliseconds
, 0);
332 void CardRegion::StopFlash()
334 if(uFlashTimer
!= -1)
336 KillTimer((HWND
)parentWnd
, uFlashTimer
);
339 fFlashVisible
= true;
343 void CardRegion::DoFlash()
345 if(uFlashTimer
!= -1)
347 fFlashVisible
= !fFlashVisible
;
349 if(--nFlashCount
== 0)
351 KillTimer((HWND
)parentWnd
, uFlashTimer
);
353 fFlashVisible
= true;
365 void CardRegion::SetEmptyImage(UINT uImage
)
369 case CS_EI_NONE
: case CS_EI_SUNK
:
370 uEmptyImage
= uImage
;
374 uEmptyImage
= CS_EI_NONE
;
380 void CardRegion::SetBackCardIdx(UINT uBackIdx
)
382 if(uBackIdx
>= 52 && uBackIdx
<= 68)
383 nBackCardIdx
= uBackIdx
;
386 void CardRegion::SetCardStack(const CardStack
&cs
)
388 //make a complete copy of the specified stack..
391 // Update the face-direction and stack-size
395 const CardStack
& CardRegion::GetCardStack()
397 //return reference to our internal stack
402 // Update specified card-stack using THIS stack's
403 // face direction rules!
405 void CardRegion::UpdateFaceDir(CardStack
&cards
)
409 num
= cards
.NumCards();
411 //Now apply the face direction rules..
416 for(i
= 0; i
< num
; i
++)
418 cards
[i
].SetFaceUp(true);
425 for(i
= 0; i
< num
; i
++)
427 cards
[i
].SetFaceUp(false);
434 num
= cardstack
.NumCards();
435 n
= min(nFaceDirOption
, num
);
438 for(i
= 0; i
< n
; i
++)
440 cards
[num
- i
- 1].SetFaceUp(false);
443 for(i
= n
; i
< num
; i
++)
445 cards
[num
- i
- 1].SetFaceUp(true);
452 num
= cardstack
.NumCards();
453 n
= min(nFaceDirOption
, num
);
455 for(i
= 0; i
< n
; i
++)
457 cards
[num
- i
- 1].SetFaceUp(true);
460 for(i
= n
; i
< num
; i
++)
462 cards
[num
- i
- 1].SetFaceUp(false);
467 case CS_FACE_ANY
: //cards can be any orientation
473 bool CardRegion::MoveCard(CardRegion
*pDestStack
, int nNumCards
, bool fAnimate
)
479 if(pDestStack
== 0) return false; //{ forcedfacedir = -1 ;return 0; }
481 if(nNumCards
< 0 || nNumCards
> cardstack
.NumCards())
484 x
= xpos
+ xoffset
* (nNumApparentCards
- nNumCards
);
485 y
= ypos
+ yoffset
* (nNumApparentCards
- nNumCards
);
490 dragstack
= cardstack
.Pop(nNumCards
);
492 //Alter the drag-stack so that it's cards are the same way up
493 //as the destination. Use the destination's drag-rules
494 //instead of this ones!!
496 temp
.Push(pDestStack
->GetCardStack());
497 temp
.Push(dragstack
);
499 pDestStack
->UpdateFaceDir(temp
);
501 dragstack
= temp
.Pop(nNumCards
);
505 iNumDragCards
= nNumCards
;
506 PrepareDragBitmaps(nNumCards
);
509 Update(); //Update this stack's size+card count
513 hdc
= GetDC((HWND
)parentWnd
);
515 ZoomCard(hdc
, x
, y
, pDestStack
);
517 ReleaseDC((HWND
)parentWnd
, hdc
);
518 ReleaseDragBitmaps();
521 // Get a copy of the cardstack
522 CardStack cs
= pDestStack
->GetCardStack();
525 pDestStack
->SetCardStack(cs
);
527 //cs = pDestStack->GetCardStack();
528 //pDestStack->Update();
529 //pDestStack->UpdateFaceDir(cs);
531 RedrawIfNotDim(pDestStack
, false);
533 //forcedfacedir = -1;
540 int CardRegion::NumCards() const
543 return cardstack
.NumCards() + dragstack
.NumCards();
545 return cardstack
.NumCards();
548 bool CardRegion::Lock()
550 DWORD dw
= WaitForSingleObject(mxlock
, 0);
552 if(dw
== WAIT_OBJECT_0
)
554 //TRACE("LockStack succeeded\n");
559 //TRACE("LockStack failed\n");
565 bool CardRegion::UnLock()
567 if(ReleaseMutex(mxlock
))
569 //TRACE("Unlocking stack\n");
574 //TRACE("Unlocking stack failed\n");
579 bool CardRegion::PlayCard(CardRegion
*pDestStack
, int value
, int num
)
581 //search the stack for the specified card value...
584 for(int i
= 0; i
< cardstack
.NumCards(); i
++)
586 if(cardstack
[i
].HiVal() == value
)
588 //swap the card with one at top pos...
589 Card card
= cardstack
.RemoveCard(i
);
590 cardstack
.Push(card
);
594 MoveCard(pDestStack
, 1, true);
604 // Redraw the current stack if it has a different
605 // layout than the comparison stack.
607 void CardRegion::RedrawIfNotDim(CardRegion
*pCompare
, bool fFullRedraw
)
612 if( pCompare
->xoffset
!= xoffset
||
613 pCompare
->yoffset
!= yoffset
||
614 pCompare
->nThreedCount
!= nThreedCount
||
615 pCompare
->uFaceDirType
!= uFaceDirType
||
616 pCompare
->uFaceDirType
!= CS_FACE_ANY
628 // SimulateDrag mimicks the complete drag+drop process.
629 // It basically just a MoveCard(..), but it calls the
630 // event callbacks as well.
632 bool CardRegion::SimulateDrag(CardRegion
*pDestStack
, int iNumDragCards
, bool fAnimate
)
637 if(CanDragCards(iNumDragCards
) != false)
639 //make a list of the cards that would be in the drag list
640 CardStack tempstack
= cardstack
.Top(iNumDragCards
);
642 if(pDestStack
->CanDropCards(tempstack
))
644 MoveCard(pDestStack
, iNumDragCards
, fAnimate
);
647 RemoveCallback(*this, iNumDragCards
);
649 if(pDestStack
->AddCallback
)
650 pDestStack
->AddCallback(*pDestStack
, pDestStack
->cardstack
);
652 RedrawIfNotDim(pDestStack
, true);