]> Shamusworld >> Repos - apple2/blob - src/gui/button.cpp
b5af684a92c9e1d0492116f514fc5568c1fc7bec
[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 //
30 // Button class implementation
31 //
32
33 /*
34 Some notes about this class:
35
36 - Button colors are hardwired (for plain text buttons)
37 */
38
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)
45 {
46         // Should we make a local button bitmap here?
47 }
48
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)
54 {
55 //      if (upImg == NULL)
56 //              return;
57 //
58 //      uint32 width = ((Bitmap *)upImg)->width, height = ((Bitmap *)upImg)->height;
59 //
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);
63
64         // Should we make a local button bitmap here? NO--it's passed in!
65 }
66
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)
73 {
74         if (buttonUp)
75                 extents.w = buttonUp->w,
76                 extents.h = buttonUp->h;
77 }
78
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)
84 {
85         // Create the button surfaces here...
86 }
87
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)
93 {
94         extents.w = (s.length() + 2) * GetFontWidth();
95         extents.h = GetFontHeight();
96
97         // Create the button surfaces here...
98
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);
105
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);
110
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());
114 }
115
116 Button::~Button()
117 {
118         if (surfacesAreLocal)
119         {
120                 if (buttonUp)
121                         SDL_FreeSurface(buttonUp);
122
123                 if (buttonDown)
124                         SDL_FreeSurface(buttonDown);
125
126                 if (buttonHover)
127                         SDL_FreeSurface(buttonHover);
128         }
129 }
130
131 void Button::HandleKey(SDLKey key)
132 {
133 }
134
135 void Button::HandleMouseMove(uint32 x, uint32 y)
136 {
137         SaveStateVariables();
138         inside = Inside(x, y);
139         CheckStateAndRedrawIfNeeded();
140 }
141
142 void Button::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
143 {
144         SaveStateVariables();
145
146         if (inside)
147         {
148                 if (mouseDown)
149                         clicked = true;
150
151                 if (clicked && !mouseDown)
152                 {
153                         clicked = false, activated = true;
154
155                         // Send a message to our parent widget (if any) that we're activated
156                         if (parent)
157                                 parent->Notify(this);
158                 }
159         }
160         else
161                 clicked = activated = false;
162
163         CheckStateAndRedrawIfNeeded();
164 }
165
166 void Button::Draw(void)
167 {
168         if (buttonUp == NULL)
169                 return;                                                                 // Bail out if no surface was created...
170
171         // Now, draw the appropriate button state!
172
173         SDL_Surface * picToShow = buttonUp;
174
175         if (buttonHover != NULL && inside && !clicked)
176                 picToShow = buttonHover;
177
178         if (buttonDown != NULL && inside && clicked)
179                 picToShow = buttonDown;
180
181         SDL_Rect rect = GetScreenCoords();
182
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
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 }