include fixes from ohnobinki, video_systems.cpp should fall back to SDL now if GL...
[supertux.git] / src / gui / button_group.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include "gui/button_group.hpp"
18
19 #include "supertux/globals.hpp"
20 #include "video/drawing_context.hpp"
21
22 ButtonGroup::ButtonGroup(Vector pos_, Vector buttons_size_, Vector buttons_box_) :
23   pos(pos_), 
24   buttons_size(buttons_size_), 
25   buttons_box(buttons_box_),
26   buttons(),
27   button_selected(),
28   row(),
29   mouse_hover(),
30   mouse_left_button(),
31   buttons_pair_nb()
32 {
33   buttons.clear();
34   row = 0;
35   button_selected = -1;
36   mouse_hover = false;
37   mouse_left_button = false;
38   buttons_pair_nb = 0;
39 }
40
41 ButtonGroup::~ButtonGroup()
42 {
43 }
44
45 void
46 ButtonGroup::add_button(Button button, int id, bool select)
47 {
48   button.pos.x = ((buttons.size()-buttons_pair_nb) % (int)buttons_box.x) * buttons_size.x;
49   button.pos.y = ((int)((buttons.size()-buttons_pair_nb) / buttons_box.x)) * buttons_size.y;
50   button.size = buttons_size;
51   button.id = id;
52   if(select)
53     button_selected = id;
54
55   buttons.push_back(button);
56 }
57
58 void
59 ButtonGroup::add_pair_of_buttons(Button button1, int id1, Button button2, int id2)
60 {
61   button1.pos.x = button2.pos.x = ((buttons.size()-buttons_pair_nb) % (int)buttons_box.x) * buttons_size.x;
62   button1.pos.y = button2.pos.y = ((int)((buttons.size()-buttons_pair_nb) / buttons_box.x)) * buttons_size.y;
63   button1.size.x = button2.size.x = buttons_size.x;
64   button1.size.y = button2.size.y = buttons_size.y / 2;
65   button2.pos.y += buttons_size.y / 2;
66   button1.id = id1;
67   button2.id = id2;
68
69   buttons_pair_nb++;
70   buttons.push_back(button1);
71   buttons.push_back(button2);
72 }
73
74 void
75 ButtonGroup::draw(DrawingContext &context)
76 {
77   context.draw_filled_rect(pos - Vector(12,4),
78                            Vector(buttons_size.x*buttons_box.x + 16, buttons_size.y*buttons_box.y + 8),
79                            Color (0,0,0, 128), LAYER_GUI-1);
80
81   context.push_transform();
82   context.set_translation(Vector(-pos.x, -pos.y + buttons_size.y*row));
83   for(Buttons::iterator i = buttons.begin(); i != buttons.end(); ++i)
84   {
85     if(i->pos.y < row*buttons_size.y ||
86        i->pos.y + i->size.y > (row + buttons_box.y) * buttons_size.y)
87       continue;
88
89     i->draw(context, i->id == button_selected);
90   }
91   context.pop_transform();
92 }
93
94 bool
95 ButtonGroup::event(SDL_Event &event)
96 {
97   bool caught_event = false;
98
99   switch(event.type)
100   {
101     case SDL_MOUSEMOTION:
102       mouse_hover = false;
103
104       if(mouse_left_button)
105       {
106         pos.x += int(event.motion.xrel * float(SCREEN_SIZE.width)/g_screen->w);
107         pos.y += int(event.motion.yrel * float(SCREEN_SIZE.height)/g_screen->h);
108         caught_event = true;
109       }
110       if(event.button.x > pos.x-12 && event.button.x < pos.x+16 + buttons_box.x*buttons_size.x &&
111          event.button.y > pos.y-4 && event.button.y < pos.y+8 + buttons_box.y*buttons_size.y)
112         mouse_hover = true;
113       break;
114     case SDL_MOUSEBUTTONDOWN:
115       if(event.button.x < pos.x-12 || event.button.x > pos.x+16 +
116          buttons_box.x*buttons_size.x || event.button.y < pos.y-4 ||
117          event.button.y > pos.y+8 + buttons_box.y*buttons_size.y)
118         break;
119
120       caught_event = true;
121
122       if(event.button.button == SDL_BUTTON_WHEELUP)
123       {
124         row--;
125         if(row < 0)
126           row = 0;
127       }
128       else if(event.button.button == SDL_BUTTON_WHEELDOWN)
129       {
130         row++;
131         if(row > (int)((buttons.size()-buttons_pair_nb)/buttons_box.x) - (int)buttons_box.y +
132            ((int)(buttons.size()-buttons_pair_nb)%(int)buttons_box.x != 0 ? 1 : 0))
133           row = (int)((buttons.size()-buttons_pair_nb)/buttons_box.x) - (int)buttons_box.y +
134             ((int)(buttons.size()-buttons_pair_nb)%(int)buttons_box.x != 0 ? 1 : 0);
135       }
136       else if(event.button.button == SDL_BUTTON_LEFT)
137         mouse_left_button = true;
138       else
139         caught_event = false;
140       break;
141     case SDL_MOUSEBUTTONUP:
142       mouse_left_button = false;
143       break;
144     default:
145       break;
146   }
147
148   if(caught_event)
149     return true;
150
151   for(Buttons::iterator i = buttons.begin(); i != buttons.end(); ++i)
152   {
153     if(i->pos.y < row*buttons_size.y ||
154        i->pos.y + i->size.y > (row + buttons_box.y) * buttons_size.y)
155       continue;
156
157     if(i->event(event, (int)pos.x,
158                 (int)pos.y - row*(int)buttons_size.y) == BT_SELECTED)
159     {
160       button_selected = i->id;
161       caught_event = true;
162       break;
163     }
164   }
165
166   return caught_event;
167 }
168
169 int
170 ButtonGroup::selected_id()
171 {
172   return button_selected;
173 }
174
175 void
176 ButtonGroup::set_unselected()
177 {
178   button_selected = -1;
179 }
180
181 bool
182 ButtonGroup::is_hover()
183 {
184   return mouse_hover;
185 }
186
187 /* EOF */