00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "global.hpp"
00016
00017 #include "widgets/slider.hpp"
00018 #include "game_config.hpp"
00019 #include "font.hpp"
00020 #include "image.hpp"
00021 #include "sound.hpp"
00022 #include "video.hpp"
00023
00024 #include <algorithm>
00025 #include <iostream>
00026 #include <sstream>
00027
00028 namespace {
00029 const std::string slider_image = "buttons/slider.png";
00030 const std::string selected_image = "buttons/slider-selected.png";
00031 }
00032
00033 namespace gui {
00034
00035 slider::slider(CVideo &video)
00036 : widget(video), image_(image::get_image(slider_image)),
00037 highlightedImage_(image::get_image(selected_image)),
00038 min_(-100000), max_(100000), value_(0),
00039 increment_(1), value_change_(false), state_(NORMAL)
00040 {
00041 }
00042
00043 void slider::enable(bool new_val)
00044 {
00045 if(new_val != enabled())
00046 {
00047 state_ = NORMAL;
00048 widget::enable(new_val);
00049 }
00050 }
00051
00052 void slider::set_location(SDL_Rect const &rect)
00053 {
00054 SDL_Rect r = rect;
00055 r.h = image_->h;
00056 widget::set_location(r);
00057 }
00058
00059 void slider::set_min(int value)
00060 {
00061 min_ = value;
00062 if (value_ < min_) {
00063 value_ = min_;
00064 value_change_ = true;
00065 }
00066 set_dirty(true);
00067 }
00068
00069 void slider::set_max(int value)
00070 {
00071 max_ = value;
00072 if (value_ > max_) {
00073 value_ = max_;
00074 value_change_ = true;
00075 }
00076 set_dirty(true);
00077 }
00078
00079 void slider::set_value(int value)
00080 {
00081 if (value > max_)
00082 value = max_;
00083 if (value < min_)
00084 value = min_;
00085
00086 if (increment_ > 1) {
00087 int hi = increment_ / 2;
00088 value = ((value + hi) / increment_) * increment_;
00089 }
00090
00091 if (value == value_)
00092 return;
00093
00094 value_ = value;
00095 value_change_ = true;
00096 set_dirty(true);
00097 }
00098
00099 void slider::set_increment(int increment)
00100 {
00101 increment_ = increment;
00102 }
00103
00104 int slider::value() const
00105 {
00106 return value_;
00107 }
00108
00109 int slider::min_value() const
00110 {
00111 return min_;
00112 }
00113
00114 int slider::max_value() const
00115 {
00116 return max_;
00117 }
00118
00119 bool slider::value_change()
00120 {
00121 if (value_change_) {
00122 value_change_ = false;
00123 return true;
00124 }
00125 return false;
00126 }
00127
00128 SDL_Rect slider::slider_area() const
00129 {
00130 static const SDL_Rect default_value = {0,0,0,0};
00131 SDL_Rect const &loc = location();
00132 if (image_.null() || image_->w >= loc.w)
00133 return default_value;
00134
00135 int xpos = loc.x + (value_ - min_) *
00136 static_cast<int>(loc.w - image_->w) / (max_ - min_);
00137 SDL_Rect res = { xpos, loc.y, image_->w, image_->h };
00138 return res;
00139 }
00140
00141 void slider::draw_contents()
00142 {
00143 surface image(state_ != NORMAL ? highlightedImage_ : image_);
00144 if (image == NULL)
00145 return;
00146 SDL_Color line_colour = font::NORMAL_COLOUR;
00147 if (!enabled()) {
00148 image = greyscale_image(image);
00149 line_colour = font::DISABLED_COLOUR;
00150 }
00151
00152 SDL_Rect const &loc = location();
00153 if (image->w >= loc.w)
00154 return;
00155
00156 surface const screen = video().getSurface();
00157
00158 SDL_Rect line_rect = { loc.x + image->w / 2, loc.y + loc.h / 2, loc.w - image->w, 1 };
00159 SDL_FillRect(screen, &line_rect, SDL_MapRGB(screen->format,
00160 line_colour.r, line_colour.g, line_colour.b));
00161
00162 SDL_Rect const &slider = slider_area();
00163 video().blit_surface(slider.x, slider.y, image);
00164 }
00165
00166 void slider::set_slider_position(int x)
00167 {
00168 SDL_Rect const &loc = location();
00169 int tmp = x - loc.x - image_->w / 2;
00170 if (tmp < 0)
00171 tmp = 0;
00172 if (tmp > loc.w - image_->w)
00173 tmp = loc.w - image_->w;
00174
00175 set_value(tmp * (max_ - min_) / static_cast<int>(loc.w - image_->w) + min_);
00176 }
00177
00178 void slider::mouse_motion(const SDL_MouseMotionEvent& event)
00179 {
00180 if (state_ == NORMAL || state_ == ACTIVE) {
00181 bool on = point_in_rect(event.x, event.y, slider_area());
00182 state_ = on ? ACTIVE : NORMAL;
00183 } else if (state_ == CLICKED || state_ == DRAGGED) {
00184 state_ = DRAGGED;
00185 bool prev_change = value_change_;
00186 value_change_ = false;
00187 set_slider_position(event.x);
00188 if(value_change_) {
00189 sound::play_UI_sound(game_config::sounds::slider_adjust);
00190 } else {
00191 value_change_ = prev_change;
00192 }
00193 }
00194 }
00195
00196 void slider::mouse_down(const SDL_MouseButtonEvent& event)
00197 {
00198 if (event.button != SDL_BUTTON_LEFT || !point_in_rect(event.x, event.y, location()))
00199 return;
00200
00201 state_ = CLICKED;
00202 bool prev_change = value_change_;
00203 value_change_ = false;
00204 set_focus(true);
00205 set_slider_position(event.x);
00206 if(value_change_) {
00207 sound::play_UI_sound(game_config::sounds::slider_adjust);
00208 } else {
00209 sound::play_UI_sound(game_config::sounds::button_press);
00210 value_change_ = prev_change;
00211 }
00212 }
00213
00214 bool slider::requires_event_focus(const SDL_Event* event) const
00215 {
00216 if(!focus_ || !enabled() || hidden()) {
00217 return false;
00218 }
00219 if(event == NULL) {
00220
00221 return true;
00222 }
00223
00224 if(event->type == SDL_KEYDOWN) {
00225 SDLKey key = event->key.keysym.sym;
00226 switch(key) {
00227 case SDLK_LEFT:
00228 case SDLK_RIGHT:
00229 return true;
00230 default:
00231 break;
00232 }
00233 }
00234
00235 return false;
00236 }
00237
00238 void slider::handle_event(const SDL_Event& event)
00239 {
00240 if (!enabled() || hidden())
00241 return;
00242
00243 STATE start_state = state_;
00244
00245 switch(event.type) {
00246 case SDL_MOUSEBUTTONUP:
00247 state_ = NORMAL;
00248 break;
00249 case SDL_MOUSEBUTTONDOWN:
00250 mouse_down(event.button);
00251 break;
00252 case SDL_MOUSEMOTION:
00253 mouse_motion(event.motion);
00254 break;
00255 case SDL_KEYDOWN:
00256 if(focus(&event)) {
00257 const SDL_keysym& key = reinterpret_cast<const SDL_KeyboardEvent&>(event).keysym;
00258 const int c = key.sym;
00259 if(c == SDLK_LEFT) {
00260 sound::play_UI_sound(game_config::sounds::slider_adjust);
00261 set_value(value_ - increment_);
00262 } else if(c == SDLK_RIGHT) {
00263 sound::play_UI_sound(game_config::sounds::slider_adjust);
00264 set_value(value_ + increment_);
00265 }
00266 }
00267 break;
00268 default:
00269 return;
00270 }
00271 if (start_state != state_)
00272 set_dirty(true);
00273 }
00274
00275 template<typename T>
00276 list_slider<T>::list_slider(CVideo &video) :
00277 slider(video)
00278 {
00279 set_min(0);
00280 set_increment(1);
00281 slider::set_value(0);
00282 }
00283
00284 template<typename T>
00285 list_slider<T>::list_slider(CVideo &video, const std::vector<T> &items) :
00286 slider(video),
00287 items_(items)
00288 {
00289 set_min(0);
00290 set_increment(1);
00291 if(items.size() > 0)
00292 {
00293 set_max(items.size() - 1);
00294 }
00295 slider::set_value(0);
00296 }
00297
00298 template<typename T>
00299 const T& list_slider<T>::item_selected() const
00300 {
00301 return items_[value()];
00302 }
00303
00304 template<typename T>
00305 bool list_slider<T>::select_item(const T& item)
00306 {
00307 for(unsigned i = 0, nb = items_.size(); i < nb; ++i)
00308 {
00309 if(item == items_[i])
00310 {
00311 slider::set_value(i);
00312 return true;
00313 }
00314 }
00315 return false;
00316 }
00317
00318 template<typename T>
00319 void list_slider<T>::set_items(const std::vector<T> &items)
00320 {
00321 items_ = items;
00322 if(items.size() > 0)
00323 {
00324 set_max(items.size() - 1);
00325 }
00326 slider::set_value(0);
00327 }
00328
00329
00330 template class list_slider< double >;
00331 template class list_slider< int >;
00332 template class list_slider< std::string >;
00333
00334 }