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