]> git.saurik.com Git - wxWidgets.git/blob - demos/forty/pile.cpp
streamlined WM_NOTIFY processing code fixing a bug with toolbar tooltips in presence...
[wxWidgets.git] / demos / forty / pile.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: pile.cpp
3 // Purpose: Forty Thieves patience game
4 // Author: Chris Breeze
5 // Modified by:
6 // Created: 21/07/97
7 // RCS-ID: $Id$
8 // Copyright: (c) 1993-1998 Chris Breeze
9 // Licence: wxWindows licence
10 //---------------------------------------------------------------------------
11 // Last modified: 22nd July 1998 - ported to wxWindows 2.0
12 /////////////////////////////////////////////////////////////////////////////
13 //+-------------------------------------------------------------+
14 //| Description: |
15 //| The base class for holding piles of playing cards. |
16 //+-------------------------------------------------------------+
17
18 #ifdef __GNUG__
19 #pragma implementation
20 #pragma interface
21 #endif
22
23 // For compilers that support precompilation, includes "wx/wx.h".
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29
30 #ifndef WX_PRECOMP
31 #include "wx/wx.h"
32 #endif
33 #ifdef __GNUG__
34 #pragma implementation
35 #endif
36
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <time.h>
40 #include <string.h>
41 #include "card.h"
42 #include "pile.h"
43 #include "forty.h"
44 #include "canvas.h"
45
46 #include "wx/app.h"
47
48 //+-------------------------------------------------------------+
49 //| Pile::Pile() |
50 //+-------------------------------------------------------------+
51 //| Description: |
52 //| Initialise the pile to be empty of cards. |
53 //+-------------------------------------------------------------+
54 Pile::Pile(int x, int y, int dx, int dy)
55 {
56 m_x = x;
57 m_y = y;
58 m_dx = dx;
59 m_dy = dy;
60 for (m_topCard = 0; m_topCard < NumCards; m_topCard++)
61 {
62 m_cards[m_topCard] = 0;
63 }
64 m_topCard = -1; // i.e. empty
65 }
66
67
68 //+-------------------------------------------------------------+
69 //| Pile::Redraw() |
70 //+-------------------------------------------------------------+
71 //| Description: |
72 //| Redraw the pile on the screen. If the pile is empty |
73 //| just draw a NULL card as a place holder for the pile. |
74 //| Otherwise draw the pile from the bottom up, starting |
75 //| at the origin of the pile, shifting each subsequent |
76 //| card by the pile's x and y offsets. |
77 //+-------------------------------------------------------------+
78 void Pile::Redraw(wxDC& dc )
79 {
80 FortyFrame *frame = (FortyFrame*) wxTheApp->GetTopWindow();
81 wxWindow *canvas = (wxWindow *) NULL;
82 if (frame)
83 {
84 canvas = frame->GetCanvas();
85 }
86
87 if (m_topCard >= 0)
88 {
89 if (m_dx == 0 && m_dy == 0)
90 {
91 if ((canvas) && (canvas->IsExposed(m_x,m_y,Card::GetScale()*60,Card::GetScale()*200)))
92 m_cards[m_topCard]->Draw(dc, m_x, m_y);
93 }
94 else
95 {
96 int x = m_x;
97 int y = m_y;
98 for (int i = 0; i <= m_topCard; i++)
99 {
100 if ((canvas) && (canvas->IsExposed(x,y,Card::GetScale()*60,Card::GetScale()*200)))
101 m_cards[i]->Draw(dc, x, y);
102 x += (int)Card::GetScale()*m_dx;
103 y += (int)Card::GetScale()*m_dy;
104 }
105 }
106 }
107 else
108 {
109 if ((canvas) && (canvas->IsExposed(m_x,m_y,Card::GetScale()*60,Card::GetScale()*200)))
110 Card::DrawNullCard(dc, m_x, m_y);
111 }
112 }
113
114
115 //+-------------------------------------------------------------+
116 //| Pile::GetTopCard() |
117 //+-------------------------------------------------------------+
118 //| Description: |
119 //| Return a pointer to the top card in the pile or NULL |
120 //| if the pile is empty. |
121 //| NB: Gets a copy of the card without removing it from the |
122 //| pile. |
123 //+-------------------------------------------------------------+
124 Card* Pile::GetTopCard()
125 {
126 Card* card = 0;
127
128 if (m_topCard >= 0)
129 {
130 card = m_cards[m_topCard];
131 }
132 return card;
133 }
134
135
136 //+-------------------------------------------------------------+
137 //| Pile::RemoveTopCard() |
138 //+-------------------------------------------------------------+
139 //| Description: |
140 //| If the pile is not empty, remove the top card from the |
141 //| pile and return the pointer to the removed card. |
142 //| If the pile is empty return a NULL pointer. |
143 //+-------------------------------------------------------------+
144 Card* Pile::RemoveTopCard()
145 {
146 Card* card = 0;
147
148 if (m_topCard >= 0)
149 {
150 card = m_cards[m_topCard--];
151 }
152 return card;
153 }
154
155
156 //+-------------------------------------------------------------+
157 //| Pile::RemoveTopCard() |
158 //+-------------------------------------------------------------+
159 //| Description: |
160 //| As RemoveTopCard() but also redraw the top of the pile |
161 //| after the card has been removed. |
162 //| NB: the offset allows for the redrawn area to be in a |
163 //| bitmap ready for 'dragging' cards acrosss the screen. |
164 //+-------------------------------------------------------------+
165 Card* Pile::RemoveTopCard(wxDC& dc, int xOffset, int yOffset)
166 {
167 int topX, topY, x, y;
168
169 GetTopCardPos(topX, topY);
170 Card* card = RemoveTopCard();
171
172 if (card)
173 {
174 card->Erase(dc, topX - xOffset, topY - yOffset);
175 GetTopCardPos(x, y);
176 if (m_topCard < 0)
177 {
178 Card::DrawNullCard(dc, x - xOffset, y - yOffset);
179 }
180 else
181 {
182 m_cards[m_topCard]->Draw(dc, x - xOffset, y - yOffset);
183 }
184 }
185
186 return card;
187 }
188
189
190 void Pile::GetTopCardPos(int& x, int& y)
191 {
192 if (m_topCard < 0)
193 {
194 x = m_x;
195 y = m_y;
196 }
197 else
198 {
199 x = m_x + (int)Card::GetScale()*m_dx * m_topCard;
200 y = m_y + (int)Card::GetScale()*m_dy * m_topCard;
201 }
202 }
203
204 void Pile::AddCard(Card* card)
205 {
206 if (m_topCard < -1) m_topCard = -1;
207
208 m_cards[++m_topCard] = card;
209 }
210
211 void Pile::AddCard(wxDC& dc, Card* card)
212 {
213 AddCard(card);
214 int x, y;
215 GetTopCardPos(x, y);
216 card->Draw(dc, x, y);
217 }
218
219 // Can the card leave this pile.
220 // If it is a member of the pile then the answer is yes.
221 // Derived classes may override this behaviour to incorporate
222 // the rules of the game
223 bool Pile::CanCardLeave(Card* card)
224 {
225 for (int i = 0; i <= m_topCard; i++)
226 {
227 if (card == m_cards[i]) return TRUE;
228 }
229 return FALSE;
230 }
231
232 // Calculate how far x, y is from top card in the pile
233 // Returns the square of the distance
234 int Pile::CalcDistance(int x, int y)
235 {
236 int cx, cy;
237 GetTopCardPos(cx, cy);
238 return ((cx - x) * (cx - x) + (cy - y) * (cy - y));
239 }
240
241
242 // Return the card at x, y. Check the top card first, then
243 // work down the pile. If a card is found then return a pointer
244 // to the card, otherwise return NULL
245 Card* Pile::GetCard(int x, int y)
246 {
247 int cardX;
248 int cardY;
249 GetTopCardPos(cardX, cardY);
250
251 for (int i = m_topCard; i >= 0; i--)
252 {
253 if (x >= cardX && x <= cardX + Card::GetWidth() &&
254 y >= cardY && y <= cardY + Card::GetHeight())
255 {
256 return m_cards[i];
257 }
258 cardX -= (int)Card::GetScale()*m_dx;
259 cardY -= (int)Card::GetScale()*m_dy;
260 }
261 return 0;
262 }
263
264
265 // Return the position of the given card. If it is not a member of this pile
266 // return the origin of the pile.
267 void Pile::GetCardPos(Card* card, int& x, int& y)
268 {
269 x = m_x;
270 y = m_y;
271
272 for (int i = 0; i <= m_topCard; i++)
273 {
274 if (card == m_cards[i])
275 {
276 return;
277 }
278 x += (int)Card::GetScale()*m_dx;
279 y += (int)Card::GetScale()*m_dy;
280 }
281
282 // card not found in pile, return origin of pile
283 x = m_x;
284 y = m_y;
285 }
286
287
288 bool Pile::Overlap(int x, int y)
289 {
290 int cardX;
291 int cardY;
292 GetTopCardPos(cardX, cardY);
293
294 if (x >= cardX - Card::GetWidth() && x <= cardX + Card::GetWidth() &&
295 y >= cardY - Card::GetHeight() && y <= cardY + Card::GetHeight())
296 {
297 return TRUE;
298 }
299 return FALSE;
300 }
301
302
303 Pile::~Pile()
304 {
305 // nothing special at the moment
306 }