f6541d90a679097d7e0f65dd442a8c54a510b372
[supertux.git] / src / button.cpp
1 //
2 // C Implementation: button
3 //
4 // Description:
5 //
6 //
7 // Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12
13 #include <string.h>
14 #include <stdlib.h>
15 #include "setup.h"
16 #include "screen.h"
17 #include "globals.h"
18 #include "button.h"
19
20 Button::Button(std::string icon_file, std::string ninfo, SDLKey nshortcut, int x, int y, int mw, int mh)
21 {
22   char filename[1024];
23
24   if(!icon_file.empty())
25     {
26       snprintf(filename, 1024, "%s/%s", datadir.c_str(), icon_file.c_str());
27       if(!faccessible(filename))
28         snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str());
29     }
30   else
31     {
32       snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str());
33     }
34
35   if(mw != -1 || mh != -1)
36     {
37       texture_load(&icon,filename,USE_ALPHA);
38       if(mw != -1)
39         icon.w = mw;
40       if(mh != -1)
41         icon.h = mh;
42
43       SDL_Rect dest;
44       dest.x = 0;
45       dest.y = 0;
46       dest.w = icon.w;
47       dest.h = icon.h;
48       SDL_SoftStretch(icon.sdl_surface, NULL, icon.sdl_surface, &dest);
49     }
50   else
51     texture_load(&icon,filename,USE_ALPHA);
52
53   info = ninfo;
54
55   shortcut = nshortcut;
56
57   rect.x = x;
58   rect.y = y;
59   rect.w = icon.w;
60   rect.h = icon.h;
61   tag = -1;
62   state = BUTTON_NONE;
63   show_info = false;
64   bkgd = NULL;
65 }
66
67 void Button::change_icon(std::string icon_file, int mw, int mh)
68 {
69   char filename[1024];
70
71   if(!icon_file.empty())
72     {
73       snprintf(filename, 1024, "%s/%s", datadir.c_str(), icon_file.c_str());
74       if(!faccessible(filename))
75         snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str());
76     }
77   else
78     {
79       snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str());
80     }
81
82   texture_free(&icon);
83   texture_load(&icon,filename,USE_ALPHA);
84 }
85
86 void Button::draw()
87 {
88   fillrect(rect.x,rect.y,rect.w,rect.h,75,75,75,200);
89   fillrect(rect.x+1,rect.y+1,rect.w-2,rect.h-2,175,175,175,200);
90   if(bkgd != NULL)
91     {
92       texture_draw(bkgd,rect.x,rect.y);
93     }
94   texture_draw(&icon,rect.x,rect.y);
95   if(show_info)
96     {
97       char str[80];
98       int i = -32;
99
100       if(0 > rect.x - (int)strlen(info.c_str()) * white_small_text.w)
101         i = rect.w + strlen(info.c_str()) * white_small_text.w;
102
103       if(!info.empty())
104         text_draw(&white_small_text, info.c_str(), i + rect.x - strlen(info.c_str()) * white_small_text.w, rect.y, 1);
105       sprintf(str,"(%s)", SDL_GetKeyName(shortcut));
106       text_draw(&white_small_text, str, i + rect.x - strlen(str) * white_small_text.w, rect.y + white_small_text.h+2, 1);
107     }
108   if(state == BUTTON_PRESSED)
109     fillrect(rect.x,rect.y,rect.w,rect.h,75,75,75,200);
110   else if(state == BUTTON_HOVER)
111     fillrect(rect.x,rect.y,rect.w,rect.h,150,150,150,128);
112 }
113
114 Button::~Button()
115 {
116   texture_free(&icon);
117 }
118
119 void Button::event(SDL_Event &event)
120 {
121   SDLKey key = event.key.keysym.sym;
122
123   if(event.motion.x > rect.x && event.motion.x < rect.x + rect.w &&
124       event.motion.y > rect.y && event.motion.y < rect.y + rect.h)
125     {
126       if(event.type == SDL_MOUSEBUTTONDOWN)
127         {
128           if(event.button.button == SDL_BUTTON_LEFT)
129             {
130               state = BUTTON_PRESSED;
131             }
132           else
133             {
134               show_info = true;
135             }
136         }
137       else if(event.type == SDL_MOUSEBUTTONUP)
138         {
139           if(event.button.button == SDL_BUTTON_LEFT && state == BUTTON_PRESSED)
140             {
141               state = BUTTON_CLICKED;
142             }
143           else if(event.button.button != SDL_BUTTON_LEFT && state != BUTTON_PRESSED)
144             {
145               show_info = true;
146             }
147         }
148
149       if(state != BUTTON_PRESSED && state != BUTTON_CLICKED)
150         {
151           state = BUTTON_HOVER;
152           mouse_cursor->set_state(MC_LINK);
153         }
154     }
155   else if(event.type != SDL_KEYDOWN && event.type != SDL_KEYUP)
156     {
157       state = BUTTON_NONE;
158       if(show_info)
159         {
160           show_info = false;
161         }
162     }
163
164   if(event.type == SDL_KEYDOWN)
165     {
166       if(key == shortcut)
167         state = BUTTON_PRESSED;
168     }
169   else if(event.type == SDL_KEYUP)
170     {
171       if(state == BUTTON_PRESSED && key == shortcut)
172         state = BUTTON_CLICKED;
173     }
174   else if(event.type == SDL_MOUSEMOTION)
175     {
176
177       if(show_info)
178         {
179           show_info = false;
180         }
181     }
182 }
183
184 int Button::get_state()
185 {
186   int rstate;
187   if(state == BUTTON_CLICKED)
188     {
189       rstate = state;
190       state = BUTTON_NONE;
191       return rstate;
192     }
193   else
194     {
195       return state;
196     }
197 }
198
199 ButtonPanel::ButtonPanel(int x, int y, int w, int h)
200
201   bw = 32;
202   bh = 32;
203   rect.x = x;
204   rect.y = y;
205   rect.w = w;
206   rect.h = h;
207   hidden = false;
208 }
209
210 Button* ButtonPanel::event(SDL_Event& event)
211 {
212   if(!hidden)
213     {
214       for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
215         {
216           (*it)->event(event);
217           if((*it)->state != -1)
218             return (*it);
219         }
220       return NULL;
221     }
222   else
223     {
224       return NULL;
225     }
226 }
227
228 ButtonPanel::~ButtonPanel()
229 {
230   for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
231     {
232       delete (*it);
233     }
234   item.clear();
235 }
236
237 void ButtonPanel::draw()
238 {
239   if(hidden == false)
240     {
241       fillrect(rect.x,rect.y,rect.w,rect.h,100,100,100,200);
242       for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
243         {
244           (*it)->draw();
245         }
246     }
247 }
248
249 void ButtonPanel::additem(Button* pbutton, int tag)
250 {
251   int max_cols, row, col;
252
253   item.push_back(pbutton);
254
255   /* A button_panel takes control of the buttons it contains and arranges them */
256
257   max_cols = rect.w / bw;
258
259   row = (item.size()-1) / max_cols;
260   col = (item.size()-1) % max_cols;
261
262   item[item.size()-1]->rect.x = rect.x + col * bw;
263   item[item.size()-1]->rect.y = rect.y + row * bh;
264   item[item.size()-1]->tag = tag;
265
266 }
267