1 // Crimson Fields -- a game of tactical warfare
2 // Copyright (C) 2000-2007 Jens Granseuer
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
19 ////////////////////////////////////////////////////////////////////////
20 // button.cpp
21 ////////////////////////////////////////////////////////////////////////
22 
23 #include "button.h"
24 #include "misc.h"
25 #include "sound.h"
26 
27 ////////////////////////////////////////////////////////////////////////
28 // NAME       : ButtonWidget::ButtonWidget
29 // DESCRIPTION: Create a button widget.
30 // PARAMETERS : id     - widget identifier
31 //              x      - left edge of widget relative to window border
32 //              y      - top edge of widget
33 //              w      - widget width
34 //              h      - widget height
35 //              flags  - see widget.h for details
36 //              title  - widget title (may be NULL)
37 //              window - widget parent window
38 // RETURNS    : -
39 ////////////////////////////////////////////////////////////////////////
40 
ButtonWidget(short id,short x,short y,unsigned short w,unsigned short h,unsigned short flags,const char * title,Window * window)41 ButtonWidget::ButtonWidget( short id, short x, short y, unsigned short w,
42                        unsigned short h, unsigned short flags,
43                        const char *title, Window *window ) :
44      Widget( id, x, y, w, h, flags, title, window ) {
45   if ( !(this->flags & (WIDGET_ALIGN_CENTER|WIDGET_ALIGN_LEFT|
46                         WIDGET_ALIGN_RIGHT|WIDGET_ALIGN_TOP)) )
47     this->flags |= WIDGET_ALIGN_CENTER;
48 }
49 
50 ////////////////////////////////////////////////////////////////////////
51 // NAME       : ButtonWidget::Draw
52 // DESCRIPTION: Draw the button widget.
53 // PARAMETERS : -
54 // RETURNS    : -
55 ////////////////////////////////////////////////////////////////////////
56 
Draw(void)57 void ButtonWidget::Draw( void ) {
58   surface->DrawBack( *this );
59 
60   if ( (flags & WIDGET_STYLE_MENU) && Clicked() ) {
61     surface->DrawBox( *this, BOX_RECESSED );
62     surface->FillRectAlpha( x+1, y+1, w-2, h-2, Color(CF_COLOR_SHADOW) );
63   } else if ( flags & WIDGET_STYLE_HIGHLIGHT ) {
64     surface->FillRectAlpha( *this, surface->GetFGPen() );
65   } else if ( !(flags & WIDGET_STYLE_NOBORDER) ) {
66     surface->DrawBox( *this, BOX_RECESSED );
67     surface->DrawBox( Rect(x+1,y+1,w-2,h-2), Clicked() ? BOX_RECESSED : BOX_RAISED );
68     if ( Clicked() )
69       surface->FillRectAlpha( x+2, y+2, w-4, h-4, Color(CF_COLOR_SHADOW) );
70   }
71 
72   if ( flags & WIDGET_STYLE_GFX ) {
73     Image &img = image[Clicked()];
74 
75     // the flags designate the label alignment; image alignment is opposite
76     int xoff;
77     if ( (flags & (WIDGET_ALIGN_LEFT|WIDGET_ALIGN_WITHIN)) ==
78          (WIDGET_ALIGN_LEFT|WIDGET_ALIGN_WITHIN) ) {
79       xoff = x + (w - img.Width()) - 2;
80     } else if ( (flags & (WIDGET_ALIGN_RIGHT|WIDGET_ALIGN_WITHIN)) ==
81          (WIDGET_ALIGN_RIGHT|WIDGET_ALIGN_WITHIN) ) {
82       xoff = x + 2;
83     } else {
84       xoff = x + (w - img.Width()) / 2;
85     }
86     img.Draw( surface, xoff, y + (h - img.Height()) / 2 );
87   }
88 
89   PrintTitle( ((flags & WIDGET_STYLE_HIGHLIGHT) && !Clicked()) ?
90               surface->GetBGPen() : surface->GetFGPen() );
91   if ( flags & WIDGET_STYLE_SUBMENU )
92     image[0].Draw( surface, x + w - 3 - image[0].Width(),
93                    y + (h - image[0].Height())/2 + (Clicked() ? 1 : 0) );
94 }
95 
96 ////////////////////////////////////////////////////////////////////////
97 // NAME       : ButtonWidget::SetImage
98 // DESCRIPTION: For widgets which have the WIDGET_STYLE_GFX flag set,
99 //              define the images to use for displaying them.
100 // PARAMETERS : image  - the surface containing the images
101 //              state1 - rectangle containing the position of the image
102 //                       to show when the widget is not selected
103 //              state2 - rectangle containing the position of the image
104 //                       to show when the widget is selected
105 // RETURNS    : -
106 ////////////////////////////////////////////////////////////////////////
107 
SetImage(Surface * image,const Rect & state1,const Rect & state2)108 void ButtonWidget::SetImage( Surface *image,
109                              const Rect &state1, const Rect &state2 ) {
110   this->image[0] = Image( image, state1.x, state1.y, state1.w, state1.h );
111   this->image[1] = Image( image, state2.x, state2.y, state2.w, state2.h );
112 }
113 
114 ////////////////////////////////////////////////////////////////////////
115 // NAME       : ButtonWidget::MouseDown
116 // DESCRIPTION: Show the widget in depressed state if it was selected.
117 // PARAMETERS : button - SDL_MouseButtonEvent received from the event
118 //                       handler
119 // RETURNS    : GUI_OK
120 ////////////////////////////////////////////////////////////////////////
121 
MouseDown(const SDL_MouseButtonEvent & button)122 GUI_Status ButtonWidget::MouseDown( const SDL_MouseButtonEvent &button ) {
123   if ( (button.button == SDL_BUTTON_LEFT) &&
124        Contains( button.x - surface->LeftEdge(),
125                  button.y - surface->TopEdge() ) ) Push();
126   else if ( Clicked() ) Release();
127   return GUI_OK;
128 }
129 
130 ////////////////////////////////////////////////////////////////////////
131 // NAME       : ButtonWidget::MouseUp
132 // DESCRIPTION: Release the button and activate it if the mouse pointer
133 //              is still over it.
134 // PARAMETERS : button - SDL_MouseButtonEvent received from the event
135 //                       handler
136 // RETURNS    : GUI status
137 ////////////////////////////////////////////////////////////////////////
138 
MouseUp(const SDL_MouseButtonEvent & button)139 GUI_Status ButtonWidget::MouseUp( const SDL_MouseButtonEvent &button ) {
140   if ( Clicked() && (button.button == SDL_BUTTON_LEFT) ) {
141     Release();
142     if ( Contains( button.x - surface->LeftEdge(),
143                    button.y - surface->TopEdge() ) ) return Activate();
144   }
145   return GUI_OK;
146 }
147 
148 ////////////////////////////////////////////////////////////////////////
149 // NAME       : ButtonWidget::KeyDown
150 // DESCRIPTION: Depress button if the correct key was hit.
151 // PARAMETERS : key - SDL_keysym received from the event handler
152 // RETURNS    : GUI_OK
153 ////////////////////////////////////////////////////////////////////////
154 
KeyDown(const SDL_keysym & key)155 GUI_Status ButtonWidget::KeyDown( const SDL_keysym &key ) {
156   if ( (key.sym == this->key) ||
157        ((flags & WIDGET_DEFAULT) && (key.sym == SDLK_RETURN)) ) Push();
158   else if ( Clicked() ) Release();
159   return GUI_OK;
160 }
161 
162 ////////////////////////////////////////////////////////////////////////
163 // NAME       : ButtonWidget::KeyUp
164 // DESCRIPTION: Activate widget if correct key was released.
165 // PARAMETERS : key - SDL_keysym received from the event handler
166 // RETURNS    : GUI status
167 ////////////////////////////////////////////////////////////////////////
168 
KeyUp(const SDL_keysym & key)169 GUI_Status ButtonWidget::KeyUp( const SDL_keysym &key ) {
170   if ( Clicked() && ((key.sym == this->key) ||
171        ((flags & WIDGET_DEFAULT) && (key.sym == SDLK_RETURN))) ) {
172     Release();
173     return Activate();
174   }
175   return GUI_OK;
176 }
177 
178 ////////////////////////////////////////////////////////////////////////
179 // NAME       : ButtonWidget::Push
180 // DESCRIPTION: Change the widget state to 'clicked', redraw, and play
181 //              a sound effect.
182 // PARAMETERS : -
183 // RETURNS    : -
184 ////////////////////////////////////////////////////////////////////////
185 
Push(void)186 void ButtonWidget::Push( void ) {
187   if ( !clicked ) {
188     Audio::PlaySfx( Audio::SND_GUI_PRESSED, 0 );
189     Widget::Push();
190   }
191 }
192 
193 ////////////////////////////////////////////////////////////////////////
194 // NAME       : ButtonWidget::Activate
195 // DESCRIPTION: Activate widget, i.e. call the activation function of
196 //              the hook class.
197 // PARAMETERS : -
198 // RETURNS    : return code of the activation function
199 ////////////////////////////////////////////////////////////////////////
200 
Activate(void)201 GUI_Status ButtonWidget::Activate( void ) {
202   if ( hook ) return hook->WidgetActivated( this, surface );
203   return (GUI_Status)id;
204 }
205 
206 
207 ////////////////////////////////////////////////////////////////////////
208 // NAME       : CheckboxWidget::CheckboxWidget
209 // DESCRIPTION: Create a checkbox widget.
210 // PARAMETERS : id     - widget identifier
211 //              x      - left edge of widget relative to window border
212 //              y      - top edge of widget
213 //              w      - widget width
214 //              h      - widget height
215 //              state  - initial state (checked or unchecked)
216 //              flags  - see widget.h for details
217 //              title  - widget title (may be NULL)
218 //              window - widget parent window
219 // RETURNS    : -
220 ////////////////////////////////////////////////////////////////////////
221 
222 #define GFX_CHECK_SIZE    15
223 #define GFX_CHECK_OFF_X   64
224 #define GFX_CHECK_OFF_Y   46
225 #define GFX_CHECK_ON_X    79
226 #define GFX_CHECK_ON_Y    46
227 
CheckboxWidget(short id,short x,short y,unsigned short w,unsigned short h,bool state,unsigned short flags,const char * title,Window * window)228 CheckboxWidget::CheckboxWidget( short id, short x, short y, unsigned short w,
229                        unsigned short h, bool state, unsigned short flags,
230                        const char *title, Window *window ) :
231      ButtonWidget( id, x, y, w, h, flags, title, window ) {
232   clicked = state;
233 
234   // set default graphics
235   if ( flags & WIDGET_STYLE_GFX ) {
236     Surface *icons = surface->GetView()->GetSystemIcons();
237     image[0] = Image( icons, GFX_CHECK_OFF_X, GFX_CHECK_OFF_Y,
238                       GFX_CHECK_SIZE, GFX_CHECK_SIZE );
239     image[1] = Image( icons, GFX_CHECK_ON_X, GFX_CHECK_ON_Y,
240                       GFX_CHECK_SIZE, GFX_CHECK_SIZE );
241   }
242 }
243 
244 ////////////////////////////////////////////////////////////////////////
245 // NAME       : CheckboxWidget::MouseDown
246 // DESCRIPTION: Check or uncheck the widget, depending on its current
247 //              state.
248 // PARAMETERS : button - SDL_MouseButtonEvent received from the event
249 //                       handler
250 // RETURNS    : GUI status
251 ////////////////////////////////////////////////////////////////////////
252 
MouseDown(const SDL_MouseButtonEvent & button)253 GUI_Status CheckboxWidget::MouseDown( const SDL_MouseButtonEvent &button ) {
254   if ( (button.button == SDL_BUTTON_LEFT) &&
255        Contains( button.x - surface->LeftEdge(),
256                  button.y - surface->TopEdge() ) ) {
257     if ( Clicked() ) {
258       Audio::PlaySfx( Audio::SND_GUI_PRESSED, 0 );
259       Release();
260     } else Push();
261     return Activate();
262   }
263   return GUI_OK;
264 }
265 
266 ////////////////////////////////////////////////////////////////////////
267 // NAME       : CheckboxWidget::KeyDown
268 // DESCRIPTION: Toggle the widget status when the corresponding key was
269 //              hit.
270 // PARAMETERS : key - SDL_keysym received from the event handler
271 // RETURNS    : GUI status
272 ////////////////////////////////////////////////////////////////////////
273 
KeyDown(const SDL_keysym & key)274 GUI_Status CheckboxWidget::KeyDown( const SDL_keysym &key ) {
275   if ( (key.sym == this->key) ||
276        ((flags & WIDGET_DEFAULT) && (key.sym == SDLK_RETURN)) ) {
277     if ( Clicked() ) {
278       Audio::PlaySfx( Audio::SND_GUI_PRESSED, 0 );
279       Release();
280     } else Push();
281     return Activate();
282   }
283   return GUI_OK;
284 }
285 
286 
287 ////////////////////////////////////////////////////////////////////////
288 // NAME       : MenuButtonWidget::MenuButtonWidget
289 // DESCRIPTION: Create a button widget for a MenuWindow.
290 // PARAMETERS : id     - widget identifier
291 //              x      - left edge of widget relative to window border
292 //              y      - top edge of widget
293 //              w      - widget width
294 //              h      - widget height
295 //              flags  - see widget.h for details
296 //              title  - widget title (may be NULL)
297 //              window - widget parent window
298 // RETURNS    : -
299 ////////////////////////////////////////////////////////////////////////
300 
MenuButtonWidget(short id,short x,short y,unsigned short w,unsigned short h,unsigned short flags,const char * title,Window * window)301 MenuButtonWidget::MenuButtonWidget( short id, short x, short y, unsigned short w,
302                   unsigned short h, unsigned short flags,
303                   const char *title, Window *window ) :
304       ButtonWidget( id, x, y, w, h, flags, title, window ) {
305   image[0] = Image( window->GetView()->GetSystemIcons(), 175, 46, 7, 11 );
306 }
307 
308 ////////////////////////////////////////////////////////////////////////
309 // NAME       : MenuButtonWidget::MouseMove
310 // DESCRIPTION: When the mouse is moved over the button, highlight it.
311 // PARAMETERS : motion - SDL_MouseMotionEvent received from the event
312 //                       handler
313 // RETURNS    : GUI_OK
314 ////////////////////////////////////////////////////////////////////////
315 
MouseMove(const SDL_MouseMotionEvent & motion)316 GUI_Status MenuButtonWidget::MouseMove( const SDL_MouseMotionEvent &motion ) {
317   bool contain = Contains( motion.x - surface->LeftEdge(), motion.y - surface->TopEdge() );
318 
319   if ( ((flags & WIDGET_STYLE_HIGHLIGHT) && !contain) ||
320        (!(flags & WIDGET_STYLE_HIGHLIGHT) && contain) ) {
321     ToggleCurrent();
322     Draw();
323     Show();
324   }
325 
326   return GUI_OK;
327 }
328 
329 
330 #define GFX_CYCLE_W 7
331 #define GFX_CYCLE_H 12
332 #define GFX_CYCLE_X 138
333 #define GFX_CYCLE_Y 46
334 
335 ////////////////////////////////////////////////////////////////////////
336 // NAME       : CycleWidget::CycleWidget
337 // DESCRIPTION: Create a new cycle widget.
338 // PARAMETERS : id     - widget identifier
339 //              x      - left edge of widget relative to window border
340 //              y      - top edge of widget
341 //              w      - widget width
342 //              h      - widget height
343 //              flags  - see widget.h for details (default title
344 //                       placement is WIDGET_ALIGN_LEFT)
345 //              title  - widget title (may be NULL)
346 //              defval - default value, starting with 0
347 //              labels - array of available choices, terminated by a
348 //                       NULL-string
349 //              window - widget parent window
350 // RETURNS    : -
351 ////////////////////////////////////////////////////////////////////////
352 
CycleWidget(short id,short x,short y,unsigned short w,unsigned short h,unsigned short flags,const char * title,unsigned short defval,const char * labels[],Window * window)353 CycleWidget::CycleWidget( short id, short x, short y, unsigned short w,
354              unsigned short h, unsigned short flags, const char *title,
355              unsigned short defval, const char *labels[], Window *window ) :
356      ButtonWidget( id, x, y, w, h, flags, title, window ),
357      maxval(0) {
358 
359   if ( !(flags & (WIDGET_ALIGN_CENTER|WIDGET_ALIGN_LEFT|
360                   WIDGET_ALIGN_RIGHT|WIDGET_ALIGN_TOP)) )
361     // button widget defaults to center which we must revert
362     this->flags ^= WIDGET_ALIGN_LEFT|WIDGET_ALIGN_CENTER;
363 
364   image[0] = Image( window->GetView()->GetSystemIcons(),
365                     GFX_CYCLE_X, GFX_CYCLE_Y,
366                     GFX_CYCLE_W, GFX_CYCLE_H );
367 
368   int i;
369   for ( i = 1; labels[i]; ++i ) ++maxval;
370   choices = new string[maxval+1];
371   for ( i = 0; i <= maxval; ++i ) choices[i].assign( labels[i] );
372 
373   val = MIN( defval, maxval );
374 }
375 
376 ////////////////////////////////////////////////////////////////////////
377 // NAME       : CycleWidget::Draw
378 // DESCRIPTION: Draw the cycle widget.
379 // PARAMETERS : -
380 // RETURNS    : -
381 ////////////////////////////////////////////////////////////////////////
382 
Draw(void)383 void CycleWidget::Draw( void ) {
384   ButtonWidget::Draw();
385 
386   short off = (Clicked() ? 1 : 0);
387   Color fcol;
388 
389   surface->FillRect( x + w - image[0].Width() - 8 + off, y + 4 + off, 1, h - 8, Color(CF_COLOR_SHADOW) );
390   surface->FillRect( x + w - image[0].Width() - 7 + off, y + 4 + off, 1, h - 8, Color(CF_COLOR_HIGHLIGHT) );
391 
392   image[0].Draw( surface, x + w - image[0].Width() - 4 + off, y + (h - image[0].Height())/2 + off );
393 
394   if ( Disabled() ) {
395     fcol = font->GetColor();
396     font->SetColor( Color(CF_COLOR_GHOSTED) );
397   }
398 
399   // draw current label
400   font->Write( choices[val].c_str(), surface,
401                x + (w - image[0].Width() - 10 - font->TextWidth(choices[val].c_str()))/2 + off,
402                y + (h - font->Height()) / 2 + off, *this );
403 
404   if ( Disabled() ) font->SetColor( fcol );
405 }
406 
407 ////////////////////////////////////////////////////////////////////////
408 // NAME       : CycleWidget::MouseDown
409 // DESCRIPTION: Show the widget in depressed state if it was selected.
410 // PARAMETERS : button - SDL_MouseButtonEvent received from the event
411 //                       handler
412 // RETURNS    : GUI_OK
413 ////////////////////////////////////////////////////////////////////////
414 
MouseDown(const SDL_MouseButtonEvent & button)415 GUI_Status CycleWidget::MouseDown( const SDL_MouseButtonEvent &button ) {
416   if ( ((button.button == SDL_BUTTON_LEFT) ||
417        (button.button == SDL_BUTTON_RIGHT)) &&
418        Contains( button.x - surface->LeftEdge(),
419                  button.y - surface->TopEdge() ) ) {
420     up = (button.button == SDL_BUTTON_LEFT);
421     Push();
422   } else if ( Clicked() ) Release();
423   return GUI_OK;
424 }
425 
426 ////////////////////////////////////////////////////////////////////////
427 // NAME       : CycleWidget::MouseUp
428 // DESCRIPTION: Release the button and activate it if the mouse pointer
429 //              is still over it.
430 // PARAMETERS : button - SDL_MouseButtonEvent received from the event
431 //                       handler
432 // RETURNS    : GUI status
433 ////////////////////////////////////////////////////////////////////////
434 
MouseUp(const SDL_MouseButtonEvent & button)435 GUI_Status CycleWidget::MouseUp( const SDL_MouseButtonEvent &button ) {
436   if ( Clicked() &&
437        ((button.button == SDL_BUTTON_LEFT) ||
438         (button.button == SDL_BUTTON_RIGHT)) ) {
439     bool hit = Contains( button.x - surface->LeftEdge(),
440                          button.y - surface->TopEdge() );
441     if ( hit ) CycleValue();
442     Release();
443     if ( hit ) return Activate();
444   }
445   return GUI_OK;
446 }
447 
448 ////////////////////////////////////////////////////////////////////////
449 // NAME       : CycleWidget::KeyUp
450 // DESCRIPTION: Activate widget if correct key was released.
451 // PARAMETERS : key - SDL_keysym received from the event handler
452 // RETURNS    : GUI status
453 ////////////////////////////////////////////////////////////////////////
454 
KeyUp(const SDL_keysym & key)455 GUI_Status CycleWidget::KeyUp( const SDL_keysym &key ) {
456   if ( Clicked() && ((key.sym == this->key) ||
457        ((flags & WIDGET_DEFAULT) && (key.sym == SDLK_RETURN))) ) {
458     up = ((key.mod & (KMOD_LSHIFT|KMOD_RSHIFT)) == 0);
459     CycleValue();
460     Release();
461     return Activate();
462   }
463   return GUI_OK;
464 }
465 
466 ////////////////////////////////////////////////////////////////////////
467 // NAME       : CycleWidget::CycleValue
468 // DESCRIPTION: Update the widget value according to the button pressed.
469 // PARAMETERS : -
470 // RETURNS    : -
471 ////////////////////////////////////////////////////////////////////////
472 
CycleValue(void)473 void CycleWidget::CycleValue( void ) {
474   if (up) val = (val + 1) % (maxval + 1);
475   else if ( val == 0 ) val = maxval;
476   else --val;
477 }
478 
479 ////////////////////////////////////////////////////////////////////////
480 // NAME       : CycleWidget::SetValue
481 // DESCRIPTION: Set the cycle value.
482 // PARAMETERS : value - new value
483 // RETURNS    : -
484 ////////////////////////////////////////////////////////////////////////
485 
SetValue(unsigned short value)486 void CycleWidget::SetValue( unsigned short value ) {
487   val = value % (maxval + 1);
488   Draw();
489   Show();
490 }
491 
492 ////////////////////////////////////////////////////////////////////////
493 // NAME       : DropWidget::DropWidget
494 // DESCRIPTION: Create a dropd-own widget, which is a ButtonWidget with
495 //              a small arrow image.
496 // PARAMETERS : id     - widget identifier
497 //              x      - left edge of widget relative to window border
498 //              y      - top edge of widget
499 //              w      - widget width
500 //              h      - widget height
501 //              flags  - see widget.h for details
502 //              title  - widget title (may be NULL)
503 //              window - widget parent window
504 // RETURNS    : -
505 ////////////////////////////////////////////////////////////////////////
506 
DropWidget(short id,short x,short y,unsigned short w,unsigned short h,unsigned short flags,const char * title,Window * window)507 DropWidget::DropWidget( short id, short x, short y, unsigned short w,
508              unsigned short h, unsigned short flags, const char *title,
509              Window *window ) :
510      ButtonWidget( id, x, y, w, h, flags, title, window ) {
511   image[0] = Image( window->GetView()->GetSystemIcons(), 157, 53, 11, 7 );
512 }
513 
514 ////////////////////////////////////////////////////////////////////////
515 // NAME       : DropWidget::Draw
516 // DESCRIPTION: Draw the drop-down widget.
517 // PARAMETERS : -
518 // RETURNS    : -
519 ////////////////////////////////////////////////////////////////////////
520 
Draw(void)521 void DropWidget::Draw( void ) {
522   surface->DrawBack( *this );
523 
524   surface->DrawBox( *this, BOX_RECESSED );
525   surface->DrawBox( Rect(x+1,y+1,w-2,h-2), Clicked() ? BOX_RECESSED : BOX_RAISED );
526   if ( Clicked() )
527     surface->FillRectAlpha( x+2, y+2, w-4, h-4, Color(CF_COLOR_SHADOW) );
528 
529   short off = (Clicked() ? 1 : 0);
530   short xoff = x + (w - font->TextWidth(title.c_str()) - image[0].Width() - 8) / 2;
531   short yoff = y + (h - font->Height()) / 2;
532   PrintTitle( xoff + off, yoff + off, surface->GetFGPen() );
533 
534   surface->FillRect( x + w - image[0].Width() - 8 + off, y + 4 + off, 1, h - 8, Color(CF_COLOR_SHADOW) );
535   surface->FillRect( x + w - image[0].Width() - 7 + off, y + 4 + off, 1, h - 8, Color(CF_COLOR_HIGHLIGHT) );
536 
537   image[0].Draw( surface, x + w - image[0].Width() - 4 + off, y + (h - image[0].Height())/2 + off );
538 }
539 
540