]> Shamusworld >> Repos - apple2/blob - src/gui/button.cpp
Added missing files. :-P
[apple2] / src / gui / button.cpp
1 //
2 // BUTTON.CPP
3 //
4 // Graphical User Interface button class
5 // by James Hammons
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  02/02/2006  Created this file
12 //
13
14 #include "button.h"
15 #include "guimisc.h"                                                            // Various support functions
16
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
22 #else
23 #define MASK_R 0x000000FF
24 #define MASK_G 0x0000FF00
25 #define MASK_B 0x00FF0000
26 #define MASK_A 0xFF000000
27 #endif
28
29 // Debugging...
30 //#define DEBUG_GUI_BUTTON
31 #ifdef DEBUG_GUI_BUTTON
32 #include "log.h"
33 #endif
34
35 //
36 // Button class implementation
37 //
38
39 /*
40 Some notes about this class:
41
42 - Button colors are hardwired (for plain text buttons)
43 */
44
45 Button::Button(uint32_t x/*= 0*/, uint32_t y/*= 0*/, uint32_t w/*= 0*/, uint32_t h/*= 0*/,
46         Element * parent/*= NULL*/):
47         Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
48         activated(false), clicked(false), inside(false),
49         buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(false),
50         activatedSave(false), clickedSave(false), insideSave(false)
51 {
52         // Should we make a local button bitmap here?
53 }
54
55 Button::Button(uint32_t x, uint32_t y, uint32_t w, uint32_t h, SDL_Surface * upImg, Element * parent/*= NULL*/):
56         Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
57         activated(false), clicked(false), inside(false),
58         buttonUp(upImg), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(false),
59         activatedSave(false), clickedSave(false), insideSave(false)
60 {
61 //      if (upImg == NULL)
62 //              return;
63 //
64 //      uint32_t width = ((Bitmap *)upImg)->width, height = ((Bitmap *)upImg)->height;
65 //
66 //      buttonUp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
67 //              32, MASK_R, MASK_G, MASK_B, MASK_A);
68 //      memcpy(buttonUp->pixels, ((Bitmap *)upImg)->pixelData, width * height * 4);
69
70         // Should we make a local button bitmap here? NO--it's passed in!
71 }
72
73 Button::Button(uint32_t x, uint32_t y, SDL_Surface * bU, SDL_Surface * bH/*= NULL*/,
74         SDL_Surface * bD/*= NULL*/, Element * parent/*= NULL*/):
75         Element(x, y, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
76         activated(false), clicked(false), inside(false),
77         buttonUp(bU), buttonDown(bD), buttonHover(bH), surfacesAreLocal(false),
78         activatedSave(false), clickedSave(false), insideSave(false)
79 {
80         if (buttonUp)
81                 extents.w = buttonUp->w,
82                 extents.h = buttonUp->h;
83 }
84
85 Button::Button(uint32_t x, uint32_t y, uint32_t w, uint32_t h, std::string s, Element * parent/*= NULL*/):
86         Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
87         activated(false), clicked(false), inside(false),
88         buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(true),
89         activatedSave(false), clickedSave(false), insideSave(false)
90 {
91         // Create the button surfaces here...
92 }
93
94 Button::Button(uint32_t x, uint32_t y, std::string s, Element * parent/*= NULL*/):
95         Element(x, y, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xCF, 0x00, 0xFF, parent),
96         activated(false), clicked(false), inside(false),
97         buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(true),
98         activatedSave(false), clickedSave(false), insideSave(false)
99 {
100         extents.w = (s.length() + 2) * GetFontWidth();
101         extents.h = GetFontHeight();
102
103         // Create the button surfaces here...
104
105         buttonUp = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
106                 MASK_R, MASK_G, MASK_B, MASK_A);
107         buttonDown = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
108                 MASK_R, MASK_G, MASK_B, MASK_A);
109         buttonHover = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
110                 MASK_R, MASK_G, MASK_B, MASK_A);
111
112 //bleh
113 uint8_t r1, g1, b1, a1;
114 SDL_GetRGBA(fgColor, screen->format, &r1, &g1, &b1, &a1);
115 fgColor = SDL_MapRGBA(buttonUp->format, r1, g1, b1, a1);
116 SDL_GetRGBA(bgColor, screen->format, &r1, &g1, &b1, &a1);
117 bgColor = SDL_MapRGBA(buttonUp->format, r1, g1, b1, a1);
118 fgColorHL = SDL_MapRGBA(buttonUp->format, 0xFF, 0xFF, 0xFF, 0xFF);
119 bgColorHL = SDL_MapRGBA(buttonUp->format, 0x4F, 0xFF, 0x4F, 0xFF);
120 //helb
121
122         // Need to create backgrounds before we do this stuff...
123         SDL_FillRect(buttonUp, NULL, bgColor);
124         SDL_FillRect(buttonDown, NULL, fgColor);
125         SDL_FillRect(buttonHover, NULL, bgColorHL);
126
127         DrawStringTrans(buttonUp, GetFontWidth(), 0, fgColor, s.c_str());
128         DrawStringTrans(buttonDown, GetFontWidth(), 0, fgColor, s.c_str());
129         DrawStringTrans(buttonHover, GetFontWidth(), 0, fgColorHL, s.c_str());
130
131 #ifdef DEBUG_GUI_BUTTON
132         WriteLog("Button::Button()...\n");
133         WriteLog("\tbuttonUp w/h    = %u/%u\n", buttonUp->w, buttonUp->h);
134         WriteLog("\tbuttonDown w/h  = %u/%u\n", buttonDown->w, buttonDown->h);
135         WriteLog("\tbuttonHover w/h = %u/%u\n", buttonHover->w, buttonHover->h);
136 #endif
137 }
138
139 Button::~Button()
140 {
141         if (surfacesAreLocal)
142         {
143                 if (buttonUp)
144                         SDL_FreeSurface(buttonUp);
145
146                 if (buttonDown)
147                         SDL_FreeSurface(buttonDown);
148
149                 if (buttonHover)
150                         SDL_FreeSurface(buttonHover);
151         }
152 }
153
154 void Button::HandleKey(SDL_Scancode key)
155 {
156 }
157
158 void Button::HandleMouseMove(uint32_t x, uint32_t y)
159 {
160         if (!visible)
161                 return;
162
163         SaveStateVariables();
164         inside = Inside(x, y);
165         CheckStateAndRedrawIfNeeded();
166 }
167
168 void Button::HandleMouseButton(uint32_t x, uint32_t y, bool mouseDown)
169 {
170         if (!visible)
171                 return;
172
173         SaveStateVariables();
174
175         if (inside)
176         {
177                 if (mouseDown)
178                         clicked = true;
179
180                 if (clicked && !mouseDown)
181                 {
182                         clicked = false, activated = true;
183
184                         // Send a message to our parent widget (if any) that we're activated
185                         if (parent)
186                                 parent->Notify(this);
187                 }
188         }
189         else
190                 clicked = activated = false;
191
192         CheckStateAndRedrawIfNeeded();
193 }
194
195 void Button::Draw(void)
196 {
197 #ifdef DEBUG_GUI_BUTTON
198         WriteLog("Button::Draw()...\n");
199 #endif
200         if (!visible)
201                 return;
202
203         if (buttonUp == NULL)
204                 return;                                                                 // Bail out if no surface was created...
205
206         // Now, draw the appropriate button state!
207
208         SDL_Surface * picToShow = buttonUp;
209
210         if (buttonHover != NULL && inside && !clicked)
211                 picToShow = buttonHover;
212
213         if (buttonDown != NULL && inside && clicked)
214                 picToShow = buttonDown;
215
216         SDL_Rect rect = GetScreenCoords();
217 #ifdef DEBUG_GUI_BUTTON
218         WriteLog("        coords: x=%u, y=%u\n", rect.x, rect.y);
219         WriteLog("        picToShow=%08X\n", picToShow);
220 #endif
221
222 //Need to do coverage list blitting here, to avoid unnecessary drawing when doing mouseovers
223 //Also, need to add suport in Gui()...
224         SDL_BlitSurface(picToShow, NULL, screen, &rect);        // This handles alpha blending too! :-D
225 #ifdef DEBUG_GUI_BUTTON
226         WriteLog("        width: w=%u, h=%u\n", rect.w, rect.h);
227 #endif
228
229         needToRefreshScreen = true;
230
231 #ifdef DEBUG_GUI_BUTTON
232 //      SDL_FillRect(screen, &extents, fgColor);
233 #endif
234 }
235
236 void Button::Notify(Element *)
237 {
238 }
239
240 bool Button::ButtonClicked(void)
241 {
242         return activated;
243 }
244
245 void Button::SaveStateVariables(void)
246 {
247         activatedSave = activated;
248         clickedSave = clicked;
249         insideSave = inside;
250 }
251
252 void Button::CheckStateAndRedrawIfNeeded(void)
253 {
254         // Check to see if any of our state variables changed since we last saved them...
255         if (activated != activatedSave || clicked != clickedSave || inside != insideSave)
256                 Draw();
257 }
258
259 void Button::SetText(std::string s)
260 {
261         // Need to create backgrounds before we do this stuff...
262         SDL_FillRect(buttonUp, NULL, bgColor);
263         SDL_FillRect(buttonDown, NULL, fgColor);
264         SDL_FillRect(buttonHover, NULL, bgColorHL);
265
266         DrawStringTrans(buttonUp, GetFontWidth(), 0, fgColor, s.c_str());
267         DrawStringTrans(buttonDown, GetFontWidth(), 0, fgColor, s.c_str());
268         DrawStringTrans(buttonHover, GetFontWidth(), 0, fgColorHL, s.c_str());
269 }