Added a comment.
[supertux.git] / src / button.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 //  02111-1307, USA.
20
21 #include <string.h>
22 #include <stdlib.h>
23 #include "setup.h"
24 #include "screen.h"
25 #include "globals.h"
26 #include "button.h"
27
28 Timer Button::popup_timer;
29
30 Button::Button(std::string icon_file, std::string ninfo, SDLKey nshortcut, int x, int y, int mw, int mh)
31 {
32   popup_timer.init(false);
33
34   char filename[1024];
35
36   if(!icon_file.empty())
37   {
38     snprintf(filename, 1024, "%s/%s", datadir.c_str(), icon_file.c_str());
39     if(!faccessible(filename))
40       snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str());
41   }
42   else
43   {
44     snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str());
45   }
46
47   if(mw != -1 || mh != -1)
48   {
49     icon = new Surface(filename,USE_ALPHA);
50     icon->resize(mw,mh);
51   }
52   else
53     icon = new Surface(filename,USE_ALPHA);
54
55   info = ninfo;
56
57   shortcut = nshortcut;
58
59   rect.x = x;
60   rect.y = y;
61   rect.w = icon->w;
62   rect.h = icon->h;
63   tag = -1;
64   state = BUTTON_NONE;
65   show_info = false;
66   bkgd = NULL;
67   game_object = NULL;
68 }
69
70 void Button::change_icon(std::string icon_file, int /*mw*/, int /*mh*/)
71 {
72   char filename[1024];
73
74   if(!icon_file.empty())
75   {
76     snprintf(filename, 1024, "%s/%s", datadir.c_str(), icon_file.c_str());
77     if(!faccessible(filename))
78       snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str());
79   }
80   else
81   {
82     snprintf(filename, 1024, "%s/images/icons/default-icon.png", datadir.c_str());
83   }
84
85   delete icon;
86   icon = new Surface(filename,USE_ALPHA);
87 }
88
89 void Button::draw()
90 {
91   if(state == BUTTON_HOVER)
92     if(!popup_timer.check())
93       show_info = true;
94
95   fillrect(rect.x,rect.y,rect.w,rect.h,75,75,75,200);
96   fillrect(rect.x+1,rect.y+1,rect.w-2,rect.h-2,175,175,175,200);
97   if(bkgd != NULL)
98   {
99     bkgd->draw(rect.x,rect.y);
100   }
101   icon->draw(rect.x,rect.y);
102   if(game_object != NULL)
103   {
104     game_object->draw_on_screen();
105   }
106
107   if(show_info)
108   {
109     char str[80];
110     int i = -32;
111
112     if(0 > rect.x - (int)strlen(info.c_str()) * white_small_text->w)
113       i = rect.w + strlen(info.c_str()) * white_small_text->w;
114
115     if(!info.empty())
116       white_small_text->draw(info.c_str(), i + rect.x - strlen(info.c_str()) * white_small_text->w, rect.y, 1);
117     sprintf(str,"(%s)", SDL_GetKeyName(shortcut));
118     white_small_text->draw(str, i + rect.x - strlen(str) * white_small_text->w, rect.y + white_small_text->h+2, 1);
119   }
120   if(state == BUTTON_PRESSED)
121     fillrect(rect.x,rect.y,rect.w,rect.h,75,75,75,200);
122   else if(state == BUTTON_HOVER)
123     fillrect(rect.x,rect.y,rect.w,rect.h,150,150,150,128);
124 }
125
126 Button::~Button()
127 {
128   delete icon;
129   delete game_object;
130 }
131
132 void Button::event(SDL_Event &event)
133 {
134   SDLKey key = event.key.keysym.sym;
135
136   if(event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP)
137   {
138     if(event.button.x < rect.x || event.button.x >= rect.x + rect.w ||
139         event.button.y < rect.y || event.button.y >= rect.y + rect.h)
140       return;
141
142     if(event.button.button != SDL_BUTTON_LEFT)
143     {
144       show_info = true;
145       return;
146     }
147
148     if(event.type == SDL_MOUSEBUTTONDOWN)
149       state = BUTTON_PRESSED;
150     else
151       state = BUTTON_CLICKED;
152   }
153   else if(event.type == SDL_MOUSEMOTION)
154   {
155     if(event.motion.x < rect.x || event.motion.x >= rect.x + rect.w ||
156         event.motion.y < rect.y || event.motion.y >= rect.y + rect.h)
157       state = BUTTON_NONE;
158     else
159       state = BUTTON_HOVER;
160
161     popup_timer.start(1500);
162     if(show_info)
163     {
164       show_info = false;
165     }
166   }
167   else if(event.type == SDL_KEYDOWN)
168   {
169     if(key == shortcut)
170       state = BUTTON_PRESSED;
171   }
172   else if(event.type == SDL_KEYUP)
173   {
174     if(state == BUTTON_PRESSED && key == shortcut)
175       state = BUTTON_CLICKED;
176   }
177 }
178
179 int Button::get_state()
180 {
181   int rstate;
182   if(state == BUTTON_CLICKED)
183   {
184     rstate = state;
185     state = BUTTON_NONE;
186     return rstate;
187   }
188   else
189   {
190     return state;
191   }
192 }
193
194 ButtonPanel::ButtonPanel(int x, int y, int w, int h)
195 {
196   bw = 32;
197   bh = 32;
198   rect.x = x;
199   rect.y = y;
200   rect.w = w;
201   rect.h = h;
202   hidden = false;
203 }
204
205 Button* ButtonPanel::event(SDL_Event& event)
206 {
207   if(!hidden)
208   {
209     for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
210     {
211       (*it)->event(event);
212       if((*it)->state != BUTTON_NONE)
213         return (*it);
214     }
215     return NULL;
216   }
217   else
218   {
219     return NULL;
220   }
221 }
222
223 ButtonPanel::~ButtonPanel()
224 {
225   for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
226   {
227     delete (*it);
228   }
229   item.clear();
230 }
231
232 void ButtonPanel::draw()
233 {
234
235   if(hidden == false)
236   {
237     fillrect(rect.x,rect.y,rect.w,rect.h,100,100,100,200);
238     for(std::vector<Button*>::iterator it = item.begin(); it != item.end(); ++it)
239     {
240       (*it)->draw();
241     }
242   }
243 }
244
245 void ButtonPanel::additem(Button* pbutton, int tag)
246 {
247   int max_cols, row, col;
248
249   item.push_back(pbutton);
250
251   /* A button_panel takes control of the buttons it contains and arranges them */
252
253   max_cols = rect.w / bw;
254
255   row = (item.size()-1) / max_cols;
256   col = (item.size()-1) % max_cols;
257
258   item[item.size()-1]->rect.x = rect.x + col * bw;
259   item[item.size()-1]->rect.y = rect.y + row * bh;
260   item[item.size()-1]->tag = tag;
261
262 }
263
264 void ButtonPanel::set_button_size(int w, int h)
265 {
266   bw = w;
267   bh = h;
268 }
269
270 Button* ButtonPanel::manipulate_button(int i)
271 {
272   if(int(item.size())-1 < i)
273     return item[item.size()-1];
274   else
275     return item[i];
276 }