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 : id(Id
), parentWnd(parent
), xpos(x
), ypos(y
), xoffset(xOffset
), yoffset(yOffset
), fVisible(visible
)
22 height
= __cardheight
;
24 crBackgnd
= RGB(0, 64, 100);
26 uFaceDirType
= CS_FACE_UP
;
28 uEmptyImage
= CS_EI_SUNK
;
34 Update(); //Update this stack's size+card count
51 uDragRule
= CS_DRAG_ALL
;
52 uDropRule
= CS_DROP_ALL
;
54 xjustify
= yjustify
= xadjust
= yadjust
= 0;
57 fFlashVisible
= false;
58 uFlashTimer
= (UINT
)-1;
60 fMouseDragging
= false;
62 mxlock
= CreateMutex(0, FALSE
, 0);
65 CardRegion::~CardRegion()
70 void CardRegion::SetBackColor(COLORREF cr
)
75 int CardRegion::CalcApparentCards(int realnum
)
77 return ((realnum
+ nThreedCount
- 1) - (realnum
+ nThreedCount
- 1) % nThreedCount
) / nThreedCount
;
80 void CardRegion::CalcApparentCards()
82 nNumApparentCards
= CalcApparentCards(cardstack
.NumCards());
86 void CardRegion::UpdateSize(void)
88 if(cardstack
.NumCards() > 0)
91 width
= (nNumApparentCards
- 1) * xoffset
+ __cardwidth
;
93 width
= (nNumApparentCards
- 1) * -xoffset
+ __cardwidth
;
96 height
= (nNumApparentCards
- 1) * yoffset
+ __cardheight
;
98 height
= (nNumApparentCards
- 1) * -yoffset
+ __cardheight
;
103 height
= __cardheight
;
107 CardRegion
*CardWindow::CreateRegion(int id
, bool fVisible
, int x
, int y
, int xoffset
, int yoffset
)
111 if(nNumCardRegions
== MAXCARDSTACKS
)
114 cr
= new CardRegion(*this, id
, fVisible
, x
, y
, xoffset
, yoffset
);
115 cr
->SetBackColor(crBackgnd
);
116 cr
->SetBackCardIdx(nBackCardIdx
);
118 Regions
[nNumCardRegions
++] = cr
;
123 int CardRegion::GetOverlapRatio(int x
, int y
, int w
, int h
)
127 SetRect(&him
, x
, y
, x
+w
, y
+h
);
128 SetRect(&me
, xpos
, ypos
, xpos
+width
, ypos
+height
);
130 //see if the specified rectangle overlaps us
131 if(IntersectRect(&inter
, &me
, &him
))
133 int wi
= inter
.right
- inter
.left
;
134 int hi
= inter
.bottom
- inter
.top
;
136 int overlap
= wi
* hi
;
137 int total
= width
* height
;
139 int percent
= (overlap
<< 16) / total
;
140 return (percent
* 100) >> 16;
149 bool CardRegion::SetDragRule(UINT uDragType
, pCanDragProc proc
)
153 case CS_DRAG_NONE
: case CS_DRAG_ALL
: case CS_DRAG_TOP
:
154 uDragRule
= uDragType
;
157 case CS_DRAG_CALLBACK
:
158 uDragRule
= uDragType
;
159 CanDragCallback
= proc
;
167 bool CardRegion::SetDropRule(UINT uDropType
, pCanDropProc proc
)
171 case CS_DROP_NONE
: case CS_DROP_ALL
:
172 uDropRule
= uDropType
;
175 case CS_DROP_CALLBACK
:
176 uDropRule
= uDropType
;
177 CanDropCallback
= proc
;
185 void CardRegion::SetClickProc(pClickProc proc
)
187 ClickCallback
= proc
;
190 void CardRegion::SetDblClickProc(pClickProc proc
)
192 DblClickCallback
= proc
;
195 void CardRegion::SetAddCardProc(pAddProc proc
)
200 void CardRegion::SetRemoveCardProc(pRemoveProc proc
)
202 RemoveCallback
= proc
;
205 void CardRegion::Update()
209 UpdateFaceDir(cardstack
);
213 bool CardRegion::SetThreedCount(int count
)
221 nThreedCount
= count
;
226 void CardRegion::SetOffsets(int x
, int y
)
232 void CardRegion::SetPos(int x
, int y
)
238 void CardRegion::Show(bool fShow
)
243 bool CardRegion::IsVisible()
248 void CardRegion::SetPlacement(UINT xJustify
, UINT yJustify
, int xAdjust
, int yAdjust
)
256 void CardRegion::SetFaceDirection(UINT uDirType
, int nOption
)
260 case CS_FACE_UP
: case CS_FACE_DOWN
: case CS_FACE_DOWNUP
:
261 case CS_FACE_UPDOWN
: case CS_FACE_ANY
:
262 uFaceDirType
= uDirType
;
263 nFaceDirOption
= nOption
;
265 UpdateFaceDir(cardstack
);
271 UINT
CardRegion::GetFaceDirection(int *pnOption
)
274 *pnOption
= nFaceDirOption
;
279 void CardRegion::AdjustPosition(int winwidth
, int winheight
)
281 Update(); //Update this stack's card count + size
285 default: case CS_XJUST_NONE
: break;
287 case CS_XJUST_CENTER
: //centered
288 xpos
= (winwidth
- (width
& ~0x1)) / 2;
291 if(xoffset
< 0) xpos
+= (width
- __cardwidth
);
295 case CS_XJUST_RIGHT
: //right-aligned
296 xpos
= winwidth
- __cardwidth
;//width - 20;
303 default: case CS_YJUST_NONE
: break;
305 case CS_YJUST_CENTER
: //centered
306 ypos
= (winheight
- height
) / 2;
308 if(yoffset
< 0) ypos
+= (height
- __cardheight
);
311 case CS_YJUST_BOTTOM
: //bottom-aligned
312 ypos
= winheight
- __cardheight
;//height - 20;
320 void CardRegion::Flash(int count
, int milliseconds
)
322 if(count
<= 0) return;
325 fFlashVisible
= false;
326 uFlashTimer
= SetTimer((HWND
)parentWnd
, (WPARAM
)this, milliseconds
, 0);
331 void CardRegion::StopFlash()
333 if(uFlashTimer
!= (UINT
)-1)
335 KillTimer((HWND
)parentWnd
, uFlashTimer
);
337 uFlashTimer
= (UINT
)-1;
338 fFlashVisible
= true;
342 void CardRegion::DoFlash()
344 if(uFlashTimer
!= (UINT
)-1)
346 fFlashVisible
= !fFlashVisible
;
348 if(--nFlashCount
== 0)
350 KillTimer((HWND
)parentWnd
, uFlashTimer
);
351 uFlashTimer
= (UINT
)-1;
352 fFlashVisible
= true;
364 void CardRegion::SetEmptyImage(UINT uImage
)
372 uEmptyImage
= uImage
;
376 uEmptyImage
= CS_EI_NONE
;
382 void CardRegion::SetBackCardIdx(UINT uBackIdx
)
384 if(uBackIdx
>= 52 && uBackIdx
<= 68)
385 nBackCardIdx
= uBackIdx
;
388 void CardRegion::SetCardStack(const CardStack
&cs
)
390 //make a complete copy of the specified stack..
393 // Update the face-direction and stack-size
397 const CardStack
& CardRegion::GetCardStack()
399 //return reference to our internal stack
404 // Update specified card-stack using THIS stack's
405 // face direction rules!
407 void CardRegion::UpdateFaceDir(CardStack
&cards
)
411 num
= cards
.NumCards();
413 //Now apply the face direction rules..
418 for(i
= 0; i
< num
; i
++)
420 cards
[i
].SetFaceUp(true);
427 for(i
= 0; i
< num
; i
++)
429 cards
[i
].SetFaceUp(false);
436 num
= cardstack
.NumCards();
437 n
= min(nFaceDirOption
, num
);
440 for(i
= 0; i
< n
; i
++)
442 cards
[num
- i
- 1].SetFaceUp(false);
445 for(i
= n
; i
< num
; i
++)
447 cards
[num
- i
- 1].SetFaceUp(true);
454 num
= cardstack
.NumCards();
455 n
= min(nFaceDirOption
, num
);
457 for(i
= 0; i
< n
; i
++)
459 cards
[num
- i
- 1].SetFaceUp(true);
462 for(i
= n
; i
< num
; i
++)
464 cards
[num
- i
- 1].SetFaceUp(false);
469 case CS_FACE_ANY
: //cards can be any orientation
475 bool CardRegion::MoveCard(CardRegion
*pDestStack
, int nNumCards
, bool fAnimate
)
481 if(pDestStack
== 0) return false; //{ forcedfacedir = -1 ;return 0; }
483 if(nNumCards
< 0 || nNumCards
> cardstack
.NumCards())
486 x
= xpos
+ xoffset
* (nNumApparentCards
- nNumCards
);
487 y
= ypos
+ yoffset
* (nNumApparentCards
- nNumCards
);
492 dragstack
= cardstack
.Pop(nNumCards
);
494 //Alter the drag-stack so that it's cards are the same way up
495 //as the destination. Use the destination's drag-rules
496 //instead of this ones!!
498 temp
.Push(pDestStack
->GetCardStack());
499 temp
.Push(dragstack
);
501 pDestStack
->UpdateFaceDir(temp
);
503 dragstack
= temp
.Pop(nNumCards
);
507 iNumDragCards
= nNumCards
;
508 PrepareDragBitmaps(nNumCards
);
511 Update(); //Update this stack's size+card count
515 hdc
= GetDC((HWND
)parentWnd
);
517 ZoomCard(hdc
, x
, y
, pDestStack
);
519 ReleaseDC((HWND
)parentWnd
, hdc
);
520 ReleaseDragBitmaps();
523 // Get a copy of the cardstack
524 CardStack cs
= pDestStack
->GetCardStack();
527 pDestStack
->SetCardStack(cs
);
529 //cs = pDestStack->GetCardStack();
530 //pDestStack->Update();
531 //pDestStack->UpdateFaceDir(cs);
533 RedrawIfNotDim(pDestStack
, false);
535 //forcedfacedir = -1;
542 int CardRegion::NumCards() const
545 return cardstack
.NumCards() + dragstack
.NumCards();
547 return cardstack
.NumCards();
550 bool CardRegion::Lock()
552 DWORD dw
= WaitForSingleObject(mxlock
, 0);
554 if(dw
== WAIT_OBJECT_0
)
556 //TRACE("LockStack succeeded\n");
561 //TRACE("LockStack failed\n");
567 bool CardRegion::UnLock()
569 if(ReleaseMutex(mxlock
))
571 //TRACE("Unlocking stack\n");
576 //TRACE("Unlocking stack failed\n");
581 bool CardRegion::PlayCard(CardRegion
*pDestStack
, int value
, int num
)
583 //search the stack for the specified card value...
586 for(int i
= 0; i
< cardstack
.NumCards(); i
++)
588 if(cardstack
[i
].HiVal() == value
)
590 //swap the card with one at top pos...
591 Card card
= cardstack
.RemoveCard(i
);
592 cardstack
.Push(card
);
596 MoveCard(pDestStack
, 1, true);
606 // Redraw the current stack if it has a different
607 // layout than the comparison stack.
609 void CardRegion::RedrawIfNotDim(CardRegion
*pCompare
, bool fFullRedraw
)
614 if( pCompare
->xoffset
!= xoffset
||
615 pCompare
->yoffset
!= yoffset
||
616 pCompare
->nThreedCount
!= nThreedCount
||
617 pCompare
->uFaceDirType
!= uFaceDirType
||
618 pCompare
->uFaceDirType
!= CS_FACE_ANY
630 // SimulateDrag mimicks the complete drag+drop process.
631 // It basically just a MoveCard(..), but it calls the
632 // event callbacks as well.
634 bool CardRegion::SimulateDrag(CardRegion
*pDestStack
, int iNumDragCards
, bool fAnimate
)
639 if(CanDragCards(iNumDragCards
) != false)
641 //make a list of the cards that would be in the drag list
642 CardStack tempstack
= cardstack
.Top(iNumDragCards
);
644 if(pDestStack
->CanDropCards(tempstack
))
646 MoveCard(pDestStack
, iNumDragCards
, fAnimate
);
649 RemoveCallback(*this, iNumDragCards
);
651 if(pDestStack
->AddCallback
)
652 pDestStack
->AddCallback(*pDestStack
, pDestStack
->cardstack
);
654 RedrawIfNotDim(pDestStack
, true);