]> Shamusworld >> Repos - apple2/blob - apple2/src/gui/button.cpp
Creating trunk (should've done this from the start)...
[apple2] / apple2 / src / gui / button.cpp
1 //
2 // BUTTON.CPP
3 //
4 // Graphical User Interface button class
5 // by James L. Hammons
6 //
7 // JLH = James L. 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 using namespace std;                                                            // For STL stuff
30
31 //
32 // Button class implementation
33 //
34
35 /*
36 Some notes about this class:
37
38 - Button colors are hardwired
39 */
40
41 Button::Button(uint32 x/*= 0*/, uint32 y/*= 0*/, uint32 w/*= 0*/, uint32 h/*= 0*/,
42         Element * parent/*= NULL*/):
43         Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
44         activated(false), clicked(false), inside(false),
45         buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(false),
46         activatedSave(false), clickedSave(false), insideSave(false)
47 {
48         // Should we make a local button bitmap here?
49 }
50
51 Button::Button(uint32 x, uint32 y, uint32 w, uint32 h, SDL_Surface * upImg, Element * parent/*= NULL*/):
52         Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
53         activated(false), clicked(false), inside(false),
54         buttonUp(upImg), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(false),
55         activatedSave(false), clickedSave(false), insideSave(false)
56 {
57 //      if (upImg == NULL)
58 //              return;
59 //
60 //      uint32 width = ((Bitmap *)upImg)->width, height = ((Bitmap *)upImg)->height;
61 //
62 //      buttonUp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
63 //              32, MASK_R, MASK_G, MASK_B, MASK_A);
64 //      memcpy(buttonUp->pixels, ((Bitmap *)upImg)->pixelData, width * height * 4);
65
66         // Should we make a local button bitmap here? NO--it's passed in!
67 }
68
69 Button::Button(uint32 x, uint32 y, SDL_Surface * bU, SDL_Surface * bH/*= NULL*/,
70         SDL_Surface * bD/*= NULL*/, Element * parent/*= NULL*/):
71         Element(x, y, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
72         activated(false), clicked(false), inside(false),
73         buttonUp(bU), buttonDown(bD), buttonHover(bH), surfacesAreLocal(false),
74         activatedSave(false), clickedSave(false), insideSave(false)
75 {
76         if (buttonUp)
77                 extents.w = buttonUp->w,
78                 extents.h = buttonUp->h;
79 }
80
81 Button::Button(uint32 x, uint32 y, uint32 w, uint32 h, string s, Element * parent/*= NULL*/):
82         Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
83         activated(false), clicked(false), inside(false),
84         buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(true),
85         activatedSave(false), clickedSave(false), insideSave(false)
86 {
87         // Create the button surfaces here...
88 }
89
90 Button::Button(uint32 x, uint32 y, string s, Element * parent/*= NULL*/):
91         Element(x, y, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, parent),
92         activated(false), clicked(false), inside(false),
93         buttonUp(NULL), buttonDown(NULL), buttonHover(NULL), surfacesAreLocal(true),
94         activatedSave(false), clickedSave(false), insideSave(false)
95 {
96         extents.w = (s.length() + 2) * GetFontWidth();
97         extents.h = GetFontHeight();
98
99         // Create the button surfaces here...
100
101         buttonUp = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
102                 MASK_R, MASK_G, MASK_B, MASK_A);
103         buttonDown = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
104                 MASK_R, MASK_G, MASK_B, MASK_A);
105         buttonHover = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
106                 MASK_R, MASK_G, MASK_B, MASK_A);
107
108         // Need to create backgrounds before we do this stuff...
109         SDL_FillRect(buttonUp, NULL, bgColor);
110         SDL_FillRect(buttonDown, NULL, fgColor);
111         SDL_FillRect(buttonHover, NULL, bgColor);
112
113         DrawStringTrans(buttonUp, GetFontWidth(), 0, fgColor, s.c_str());
114         DrawStringTrans(buttonDown, GetFontWidth(), 0, fgColor, s.c_str());
115         DrawStringTrans(buttonHover, GetFontWidth(), 0, fgColor, s.c_str());
116 }
117
118 Button::~Button()
119 {
120         if (surfacesAreLocal)
121         {
122                 if (buttonUp)
123                         SDL_FreeSurface(buttonUp);
124
125                 if (buttonDown)
126                         SDL_FreeSurface(buttonDown);
127
128                 if (buttonHover)
129                         SDL_FreeSurface(buttonHover);
130         }
131 }
132
133 void Button::HandleKey(SDLKey key)
134 {
135 }
136
137 void Button::HandleMouseMove(uint32 x, uint32 y)
138 {
139         SaveStateVariables();
140         inside = Inside(x, y);
141         CheckStateAndRedrawIfNeeded();
142 }
143
144 void Button::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
145 {
146         SaveStateVariables();
147
148         if (inside)
149         {
150                 if (mouseDown)
151                         clicked = true;
152
153                 if (clicked && !mouseDown)
154                 {
155                         clicked = false, activated = true;
156
157                         // Send a message to our parent widget (if any) that we're activated
158                         if (parent)
159                                 parent->Notify(this);
160                 }
161         }
162         else
163                 clicked = activated = false;
164
165         CheckStateAndRedrawIfNeeded();
166 }
167
168 void Button::Draw(void)
169 {
170         if (buttonUp == NULL)
171                 return;                                                                 // Bail out if no surface was created...
172
173         SDL_Rect rect = GetScreenCoords();
174
175         // Now, draw the appropriate button state!
176
177         SDL_Surface * picToShow = buttonUp;
178
179         if (buttonHover != NULL && inside && !clicked)
180                 picToShow = buttonHover;
181
182         if (buttonDown != NULL && inside && clicked)
183                 picToShow = buttonDown;
184
185         SDL_BlitSurface(picToShow, NULL, screen, &rect);        // This handles alpha blending too! :-D
186
187         needToRefreshScreen = true;
188 }
189
190 void Button::Notify(Element *)
191 {
192 }
193
194 bool Button::ButtonClicked(void)
195 {
196         return activated;
197 }
198
199 void Button::SaveStateVariables(void)
200 {
201         activatedSave = activated;
202         clickedSave = clicked;
203         insideSave = inside;
204 }
205
206 void Button::CheckStateAndRedrawIfNeeded(void)
207 {
208         // Check to see if any of our state variables changed since we last saved them...
209         if (activated != activatedSave || clicked != clickedSave || inside != insideSave)
210                 Draw();
211 }