imported catch-22 sol clone with authors permission
[reactos.git] / rosapps / games / solitaire / cardlib / cardbutton.cpp
1 //
2 // CardLib - CardButton class
3 //
4 // Freeware
5 // Copyright J Brown 2001
6 //
7 #include <windows.h>
8 #include <tchar.h>
9
10 #include "cardlib.h"
11 #include "cardwindow.h"
12 #include "cardbutton.h"
13 #include "cardcolor.h"
14
15 HPALETTE UseNicePalette(HDC, HPALETTE);
16 void RestorePalette(HDC, HPALETTE);
17
18 void PaintRect(HDC hdc, RECT *rect, COLORREF colour);
19
20 CardButton::CardButton(CardWindow &parent, int Id, TCHAR *szText, UINT Style, bool visible,
21 int x, int y, int width, int height)
22
23 : parentWnd(parent), id(Id), fVisible(visible), uStyle(Style), ButtonCallback(0)
24 {
25 crText = RGB(255,255,255);
26 crBack = RGB(0, 128, 0);
27
28 xadjust = 0;
29 yadjust = 0;
30 xjustify = 0;
31 yjustify = 0;
32
33 fMouseDown = false;
34 fButtonDown = false;
35
36 hIcon = 0;
37
38 SetText(szText);
39 Move(x, y, width, height);
40
41 mxlock = CreateMutex(0, FALSE, 0);
42
43 hFont = 0;
44 }
45
46 CardButton::~CardButton()
47 {
48 CloseHandle(mxlock);
49 }
50
51 void CardButton::DrawRect(HDC hdc, RECT *rect, bool fNormal)
52 {
53 RECT fill;
54
55 HANDLE hOld;
56
57 HPEN hhi = CreatePen(0, 0, MAKE_PALETTERGB(crHighlight));
58 HPEN hsh = CreatePen(0, 0, MAKE_PALETTERGB(crShadow));
59 HPEN hbl = (HPEN)GetStockObject(BLACK_PEN);
60
61 int x = rect->left;
62 int y = rect->top;
63 int width = rect->right-rect->left - 1;
64 int height = rect->bottom-rect->top - 1;
65
66 SetRect(&fill, x+1, y+1, x+width-1, y+height-1);
67
68 int one = 1;
69
70 if(!fNormal)
71 {
72 x += width;
73 y += height;
74 width = -width;
75 height = -height;
76 one = -1;
77 OffsetRect(&fill, 1, 1);
78 }
79
80 if(fNormal)
81 hOld = SelectObject(hdc, hhi);
82 else
83 hOld = SelectObject(hdc, hhi);
84
85 MoveToEx(hdc, x, y+height, 0);
86 LineTo(hdc, x, y);
87 LineTo(hdc, x+width, y);
88 SelectObject(hdc, hOld);
89
90 hOld = SelectObject(hdc, hbl);
91 LineTo(hdc, x+width, y+height);
92 LineTo(hdc, x-one, y+height);
93 SelectObject(hdc, hOld);
94
95 hOld = SelectObject(hdc, hsh);
96 MoveToEx(hdc, x+one, y+height-one, 0);
97 LineTo(hdc, x+width-one, y+height-one);
98 LineTo(hdc, x+width-one, y);
99 SelectObject(hdc, hOld);
100
101 PaintRect(hdc, &fill, MAKE_PALETTERGB(crBack));
102
103 DeleteObject(hhi);
104 DeleteObject(hsh);
105 }
106
107 void CardButton::Clip(HDC hdc)
108 {
109 if(fVisible == false) return;
110
111 ExcludeClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom);
112 }
113
114 void CardButton::Draw(HDC hdc, bool fNormal)
115 {
116 SIZE textsize;
117 int x, y; //text x, y
118 int ix, iy; //icon x, y
119 int iconwidth = 0;
120
121 RECT cliprect;
122
123 if(fVisible == 0) return;
124
125 if(hFont == 0)
126 SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
127 else
128 SelectObject(hdc, hFont);
129
130 GetTextExtentPoint32(hdc, szText, lstrlen(szText), &textsize);
131
132 if(hIcon)
133 {
134 x = rect.left + 32 + 8;
135 }
136 else
137 {
138 if(uStyle & CB_ALIGN_LEFT)
139 {
140 x = rect.left + iconwidth;
141 }
142 else if(uStyle & CB_ALIGN_RIGHT)
143 {
144 x = rect.left + (rect.right-rect.left-iconwidth-textsize.cx);
145 }
146 else //centered
147 {
148 x = rect.right - rect.left - iconwidth;
149 x = (x - textsize.cx) / 2;
150 x += rect.left + iconwidth;
151 }
152 }
153
154 y = rect.bottom - rect.top;
155 y = (y - textsize.cy) / 2;
156 y += rect.top;
157
158 //calc icon position..
159 ix = rect.left + 4;
160 iy = rect.top + (rect.bottom-rect.top-32) / 2;
161
162 //if button is pressed, then shift text
163 if(fNormal == false && (uStyle & CB_PUSHBUTTON))
164 {
165 x += 1;
166 y += 1;
167 ix += 1;
168 iy += 1;
169 }
170
171 SetRect(&cliprect, x, y, x+textsize.cx, y+textsize.cy);
172 ExcludeClipRect(hdc, x, y, x+textsize.cx, y+textsize.cy);
173
174 //
175 // Calc icon pos
176 //
177
178 if(hIcon)
179 {
180 ExcludeClipRect(hdc, ix, iy, ix + 32, iy + 32);
181 }
182
183 if(uStyle & CB_PUSHBUTTON)
184 {
185 DrawRect(hdc, &rect, fNormal);
186
187 SetBkColor(hdc, MAKE_PALETTERGB(crBack));
188 SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));
189
190 SelectClipRgn(hdc, 0);
191
192 ExtTextOut(hdc, x, y, ETO_OPAQUE, &cliprect, szText, lstrlen(szText), 0);
193 }
194 else
195 {
196 SetBkColor(hdc, MAKE_PALETTERGB(crBack));
197 SetTextColor(hdc, crText);//MAKE_PALETTERGB(crText));
198
199 SelectClipRgn(hdc, 0);
200
201 ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0);
202 }
203
204 if(hIcon)
205 {
206 HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBack));
207 DrawIconEx(hdc, ix, iy, hIcon, 32, 32, 0, hbr, 0);
208 DeleteObject(hbr);
209 }
210
211 }
212
213 void CardButton::AdjustPosition(int winwidth, int winheight)
214 {
215 int width = rect.right-rect.left;
216 int height = rect.bottom-rect.top;
217
218 width = width & ~0x1;
219
220 switch(xjustify)
221 {
222 case CS_XJUST_NONE:
223 break;
224
225 case CS_XJUST_CENTER: //centered
226 rect.left = (winwidth - (width)) / 2;
227 rect.left += xadjust;
228 rect.right = rect.left+width;
229 break;
230
231 case CS_XJUST_RIGHT: //right-aligned
232 rect.left = winwidth - width;
233 rect.left += xadjust;
234 rect.right = rect.left+width;
235 break;
236 }
237
238 switch(yjustify)
239 {
240 case CS_YJUST_NONE:
241 break;
242
243 case CS_YJUST_CENTER: //centered
244 rect.top = (winheight - (height)) / 2;
245 rect.top += yadjust;
246 rect.bottom = rect.top+height;
247 break;
248
249 case CS_YJUST_BOTTOM: //right-aligned
250 rect.top = winheight - height;
251 rect.top += yadjust;
252 rect.bottom = rect.top+height;
253 break;
254 }
255
256 }
257
258 int CardButton::OnLButtonDown(HWND hwnd, int x, int y)
259 {
260 if((uStyle & CB_PUSHBUTTON) == 0)
261 return 0;
262
263 //make sure that the user is allowed to do something
264 if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
265 {
266 return 0;
267 }
268 else
269 {
270 ReleaseMutex(mxlock);
271 }
272
273 fMouseDown = true;
274 fButtonDown = true;
275
276 Redraw();
277
278 SetCapture(hwnd);
279
280 return 1;
281 }
282
283 int CardButton::OnMouseMove(HWND hwnd, int x, int y)
284 {
285 if(fMouseDown)
286 {
287 bool fOldButtonDown = fButtonDown;
288
289 POINT pt;
290
291 pt.x = x;
292 pt.y = y;
293
294 if(PtInRect(&rect, pt))
295 fButtonDown = true;
296 else
297 fButtonDown = false;
298
299 if(fButtonDown != fOldButtonDown)
300 Redraw();
301 }
302
303 return 0;
304 }
305
306 int CardButton::OnLButtonUp(HWND hwnd, int x, int y)
307 {
308 if(fMouseDown)
309 {
310 fMouseDown = false;
311 fButtonDown = false;
312
313 if(uStyle & CB_PUSHBUTTON)
314 {
315 Redraw();
316 ReleaseCapture();
317 }
318
319 //if have clicked the button
320 if(parentWnd.CardButtonFromPoint(x, y) == this)
321 {
322 if(ButtonCallback)
323 {
324 ButtonCallback(*this);
325 }
326 else
327 {
328 HWND hwnd = (HWND)parentWnd;
329 SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LONG)hwnd);
330 }
331 }
332 }
333
334 return 0;
335 }
336
337 #define _countof(array) (sizeof(array)/sizeof(array[0]))
338
339 CardButton *CardWindow::CreateButton(int id, TCHAR *szText, UINT uStyle, bool fVisible, int x, int y, int width, int height)
340 {
341 CardButton *cb;
342
343 if(nNumButtons == MAXBUTTONS)
344 return 0;
345
346 cb = new CardButton(*this, id, szText, uStyle, fVisible, x, y, width, height);
347 Buttons[nNumButtons++] = cb;
348
349 if(uStyle & CB_PUSHBUTTON)
350 {
351 cb->SetBackColor(CardButton::GetFace(crBackgnd));
352 //cb->SetBackColor(ScaleLumRGB(crBackgnd, 0.1));
353 cb->SetForeColor(RGB(255,255,255));
354 }
355 else
356 {
357 cb->SetBackColor(crBackgnd);
358 cb->SetForeColor(RGB(255,255,255));
359 }
360
361 return cb;
362 }
363
364 void CardButton::SetText(TCHAR *lpszFormat, ...)
365 {
366 int count;
367
368 va_list args;
369 va_start(args, lpszFormat);
370
371 count = wvsprintf(szText, lpszFormat, args);
372 va_end(args);
373 }
374
375 int CardButton::Id()
376 {
377 return id;
378 }
379
380 void CardButton::Show(bool fShow)
381 {
382 fVisible = fShow;
383 }
384
385 void CardButton::Move(int x, int y, int width, int height)
386 {
387 SetRect(&rect, x, y, x+width, y+height);
388 }
389
390 void CardButton::Redraw()
391 {
392 HDC hdc = GetDC((HWND)parentWnd);
393
394 HPALETTE hOldPal = UseNicePalette(hdc, __hPalette);
395
396 Draw(hdc, !fButtonDown);
397
398 RestorePalette(hdc, hOldPal);
399
400 ReleaseDC((HWND)parentWnd, hdc);
401 }
402
403 void CardButton::SetForeColor(COLORREF cr)
404 {
405 crText = cr;
406 }
407
408 void CardButton::SetBackColor(COLORREF cr)
409 {
410 crBack = cr;
411
412 crHighlight = GetHighlight(cr);
413 crShadow = GetShadow(cr);
414
415 //crHighlight = ScaleLumRGB(cr, +0.25);
416 //crShadow = ScaleLumRGB(cr, -0.25);
417 }
418
419 // Static member
420 COLORREF CardButton::GetHighlight(COLORREF crBase)
421 {
422 return ColorScaleRGB(crBase, RGB(255,255,255), 0.25);
423 }
424
425 // Static member
426 COLORREF CardButton::GetShadow(COLORREF crBase)
427 {
428 return ColorScaleRGB(crBase, RGB(0, 0, 0), 0.25);
429 }
430
431 COLORREF CardButton::GetFace(COLORREF crBase)
432 {
433 return ColorScaleRGB(crBase, RGB(255,255,255), 0.1);
434 }
435
436 void CardButton::SetPlacement(UINT xJustify, UINT yJustify, int xAdjust, int yAdjust)
437 {
438 xadjust = xAdjust;
439 yadjust = yAdjust;
440 xjustify = xJustify;
441 yjustify = yJustify;
442 }
443
444 void CardButton::SetIcon(HICON hicon, bool fRedraw)
445 {
446 hIcon = hicon;
447
448 if(fRedraw)
449 Redraw();
450 }
451
452 void CardButton::SetFont(HFONT font)
453 {
454 //don't delete the existing font..
455 hFont = font;
456 }
457
458 void CardButton::SetButtonProc(pButtonProc proc)
459 {
460 ButtonCallback = proc;
461 }
462
463 bool CardButton::Lock()
464 {
465 DWORD dw = WaitForSingleObject(mxlock, 0);
466
467 if(dw == WAIT_OBJECT_0)
468 return true;
469 else
470 return false;
471 }
472
473 bool CardButton::UnLock()
474 {
475 if(ReleaseMutex(mxlock))
476 return true;
477 else
478 return false;
479 }
480
481 void CardButton::SetStyle(UINT style)
482 {
483 uStyle = style;
484 }
485
486 UINT CardButton::GetStyle()
487 {
488 return uStyle;
489 }