4 // Graphical User Interface button class
7 // JLH = James L. Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 02/02/2006 Created this file
15 #include "guimisc.h" // Various support functions
17 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
18 #define MASK_R 0xFF000000
19 #define MASK_G 0x00FF0000
20 #define MASK_B 0x0000FF00
21 #define MASK_A 0x000000FF
23 #define MASK_R 0x000000FF
24 #define MASK_G 0x0000FF00
25 #define MASK_B 0x00FF0000
26 #define MASK_A 0xFF000000
30 // Button class implementation
34 Some notes about this class:
36 - Button colors are hardwired (for plain text buttons)
39 Button::Button(uint32 x/*= 0*/, uint32 y/*= 0*/, uint32 w/*= 0*/, uint32 h/*= 0*/,
40 Element * parent/*= NULL*/):
41 Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
42 activated(false), clicked(false), inside(false),
43 buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(false),
44 activatedSave(false), clickedSave(false), insideSave(false)
46 // Should we make a local button bitmap here?
49 Button::Button(uint32 x, uint32 y, uint32 w, uint32 h, SDL_Surface * upImg, Element * parent/*= NULL*/):
50 Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
51 activated(false), clicked(false), inside(false),
52 buttonUp(upImg), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(false),
53 activatedSave(false), clickedSave(false), insideSave(false)
58 // uint32 width = ((Bitmap *)upImg)->width, height = ((Bitmap *)upImg)->height;
60 // buttonUp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
61 // 32, MASK_R, MASK_G, MASK_B, MASK_A);
62 // memcpy(buttonUp->pixels, ((Bitmap *)upImg)->pixelData, width * height * 4);
64 // Should we make a local button bitmap here? NO--it's passed in!
67 Button::Button(uint32 x, uint32 y, SDL_Surface * bU, SDL_Surface * bH/*= NULL*/,
68 SDL_Surface * bD/*= NULL*/, Element * parent/*= NULL*/):
69 Element(x, y, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
70 activated(false), clicked(false), inside(false),
71 buttonUp(bU), buttonDown(bD), buttonHover(bH), surfacesAreLocal(false),
72 activatedSave(false), clickedSave(false), insideSave(false)
75 extents.w = buttonUp->w,
76 extents.h = buttonUp->h;
79 Button::Button(uint32 x, uint32 y, uint32 w, uint32 h, std::string s, Element * parent/*= NULL*/):
80 Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
81 activated(false), clicked(false), inside(false),
82 buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(true),
83 activatedSave(false), clickedSave(false), insideSave(false)
85 // Create the button surfaces here...
88 Button::Button(uint32 x, uint32 y, std::string s, Element * parent/*= NULL*/):
89 Element(x, y, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
90 activated(false), clicked(false), inside(false),
91 buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(true),
92 activatedSave(false), clickedSave(false), insideSave(false)
94 extents.w = (s.length() + 2) * GetFontWidth();
95 extents.h = GetFontHeight();
97 // Create the button surfaces here...
99 buttonUp = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
100 MASK_R, MASK_G, MASK_B, MASK_A);
101 buttonDown = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
102 MASK_R, MASK_G, MASK_B, MASK_A);
103 buttonHover = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
104 MASK_R, MASK_G, MASK_B, MASK_A);
106 // Need to create backgrounds before we do this stuff...
107 SDL_FillRect(buttonUp, NULL, bgColor);
108 SDL_FillRect(buttonDown, NULL, fgColor);
109 SDL_FillRect(buttonHover, NULL, bgColor);
111 DrawStringTrans(buttonUp, GetFontWidth(), 0, fgColor, s.c_str());
112 DrawStringTrans(buttonDown, GetFontWidth(), 0, fgColor, s.c_str());
113 DrawStringTrans(buttonHover, GetFontWidth(), 0, fgColor, s.c_str());
118 if (surfacesAreLocal)
121 SDL_FreeSurface(buttonUp);
124 SDL_FreeSurface(buttonDown);
127 SDL_FreeSurface(buttonHover);
131 void Button::HandleKey(SDLKey key)
135 void Button::HandleMouseMove(uint32 x, uint32 y)
137 SaveStateVariables();
138 inside = Inside(x, y);
139 CheckStateAndRedrawIfNeeded();
142 void Button::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
144 SaveStateVariables();
151 if (clicked && !mouseDown)
153 clicked = false, activated = true;
155 // Send a message to our parent widget (if any) that we're activated
157 parent->Notify(this);
161 clicked = activated = false;
163 CheckStateAndRedrawIfNeeded();
166 void Button::Draw(void)
168 if (buttonUp == NULL)
169 return; // Bail out if no surface was created...
171 // Now, draw the appropriate button state!
173 SDL_Surface * picToShow = buttonUp;
175 if (buttonHover != NULL && inside && !clicked)
176 picToShow = buttonHover;
178 if (buttonDown != NULL && inside && clicked)
179 picToShow = buttonDown;
181 SDL_Rect rect = GetScreenCoords();
183 //Need to do coverage list blitting here, to avoid unnecessary drawing when doing mouseovers
184 //Also, need to add suport in Gui()...
185 SDL_BlitSurface(picToShow, NULL, screen, &rect); // This handles alpha blending too! :-D
187 needToRefreshScreen = true;
190 void Button::Notify(Element *)
194 bool Button::ButtonClicked(void)
199 void Button::SaveStateVariables(void)
201 activatedSave = activated;
202 clickedSave = clicked;
206 void Button::CheckStateAndRedrawIfNeeded(void)
208 // Check to see if any of our state variables changed since we last saved them...
209 if (activated != activatedSave || clicked != clickedSave || inside != insideSave)