widgets/slider.cpp

Go to the documentation of this file.
00001 /* $Id: slider.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #define GETTEXT_DOMAIN "wesnoth-lib"
00017 
00018 #include "global.hpp"
00019 
00020 #include "widgets/slider.hpp"
00021 #include "game_config.hpp"
00022 #include "font.hpp"
00023 #include "image.hpp"
00024 #include "sound.hpp"
00025 #include "video.hpp"
00026 
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::max_value() const
00110 {
00111     return max_;
00112 }
00113 
00114 bool slider::value_change()
00115 {
00116     if (value_change_) {
00117         value_change_ = false;
00118         return true;
00119     }
00120     return false;
00121 }
00122 
00123 SDL_Rect slider::slider_area() const
00124 {
00125     static const SDL_Rect default_value = {0,0,0,0};
00126     SDL_Rect const &loc = location();
00127     if (image_.null() || image_->w >= loc.w)
00128         return default_value;
00129 
00130     int xpos = loc.x + (value_ - min_) *
00131         static_cast<int>(loc.w - image_->w) / (max_ - min_);
00132     return create_rect(xpos, loc.y, image_->w, image_->h);
00133 }
00134 
00135 void slider::draw_contents()
00136 {
00137     surface image(state_ != NORMAL ? highlightedImage_ : image_);
00138     if (image == NULL)
00139         return;
00140     SDL_Color line_color = font::NORMAL_COLOR;
00141     if (!enabled()) {
00142         image = greyscale_image(image);
00143         line_color = font::DISABLED_COLOR;
00144     }
00145 
00146     SDL_Rect const &loc = location();
00147     if (image->w >= loc.w)
00148         return;
00149 
00150     surface screen = video().getSurface();
00151 
00152     SDL_Rect line_rect = create_rect(loc.x + image->w / 2
00153             , loc.y + loc.h / 2
00154             , loc.w - image->w
00155             , 1);
00156 
00157     sdl_fill_rect(screen, &line_rect, SDL_MapRGB(screen->format,
00158         line_color.r, line_color.g, line_color.b));
00159 
00160     SDL_Rect const &slider = slider_area();
00161     video().blit_surface(slider.x, slider.y, image);
00162 }
00163 
00164 void slider::set_slider_position(int x)
00165 {
00166     SDL_Rect const &loc = location();
00167     int tmp = x - loc.x - image_->w / 2;
00168     if (tmp < 0)
00169         tmp = 0;
00170     if (tmp > loc.w - image_->w)
00171         tmp = loc.w - image_->w;
00172 
00173     set_value(tmp * (max_ - min_) / static_cast<int>(loc.w - image_->w) + min_);
00174 }
00175 
00176 void slider::mouse_motion(const SDL_MouseMotionEvent& event)
00177 {
00178     if (state_ == NORMAL || state_ == ACTIVE) {
00179         bool on = point_in_rect(event.x, event.y, slider_area());
00180         state_ = on ? ACTIVE : NORMAL;
00181     } else if (state_ == CLICKED || state_ == DRAGGED) {
00182         state_ = DRAGGED;
00183         bool prev_change = value_change_;
00184         value_change_ = false;
00185         set_slider_position(event.x);
00186         if(value_change_) {
00187             sound::play_UI_sound(game_config::sounds::slider_adjust);
00188         } else {
00189             value_change_ = prev_change;
00190         }
00191     }
00192 }
00193 
00194 void slider::mouse_down(const SDL_MouseButtonEvent& event)
00195 {
00196     if (event.button != SDL_BUTTON_LEFT || !point_in_rect(event.x, event.y, location()))
00197         return;
00198 
00199     state_ = CLICKED;
00200     bool prev_change = value_change_;
00201     value_change_ = false;
00202     set_focus(true);
00203     set_slider_position(event.x);
00204     if(value_change_) {
00205         sound::play_UI_sound(game_config::sounds::slider_adjust);
00206     } else {
00207         sound::play_UI_sound(game_config::sounds::button_press);
00208         value_change_ = prev_change;
00209     }
00210 }
00211 
00212 bool slider::requires_event_focus(const SDL_Event* event) const
00213 {
00214     if(!focus_ || !enabled() || hidden()) {
00215         return false;
00216     }
00217     if(event == NULL) {
00218         //when event is not specified, signal that focus may be desired later
00219         return true;
00220     }
00221 
00222     if(event->type == SDL_KEYDOWN) {
00223         SDLKey key = event->key.keysym.sym;
00224         switch(key) {
00225         case SDLK_LEFT:
00226         case SDLK_RIGHT:
00227             return true;
00228         default:
00229             break;
00230         }
00231     }
00232     //mouse events are processed regardless of focus
00233     return false;
00234 }
00235 
00236 void slider::handle_event(const SDL_Event& event)
00237 {
00238     if (!enabled() || hidden())
00239         return;
00240 
00241     STATE start_state = state_;
00242 
00243     switch(event.type) {
00244     case SDL_MOUSEBUTTONUP:
00245         if (!mouse_locked())
00246             state_ = NORMAL;
00247         break;
00248     case SDL_MOUSEBUTTONDOWN:
00249         if (!mouse_locked())
00250             mouse_down(event.button);
00251         break;
00252     case SDL_MOUSEMOTION:
00253         if (!mouse_locked())
00254             mouse_motion(event.motion);
00255         break;
00256     case SDL_KEYDOWN:
00257         if(focus(&event)) {
00258             const SDL_keysym& key = reinterpret_cast<const SDL_KeyboardEvent&>(event).keysym;
00259             const int c = key.sym;
00260             if(c == SDLK_LEFT) {
00261                 sound::play_UI_sound(game_config::sounds::slider_adjust);
00262                 set_value(value_ - increment_);
00263             } else if(c == SDLK_RIGHT) {
00264                 sound::play_UI_sound(game_config::sounds::slider_adjust);
00265                 set_value(value_ + increment_);
00266             }
00267         }
00268         break;
00269     default:
00270         return;
00271     }
00272     if (start_state != state_)
00273         set_dirty(true);
00274 }
00275 
00276 template<typename T>
00277 list_slider<T>::list_slider(CVideo &video) :
00278     slider(video)
00279 {
00280     set_min(0);
00281     set_increment(1);
00282     slider::set_value(0);
00283 }
00284 
00285 template<typename T>
00286 list_slider<T>::list_slider(CVideo &video, const std::vector<T> &items) :
00287     slider(video),
00288     items_(items)
00289 {
00290     set_min(0);
00291     set_increment(1);
00292     if(items.size() > 0)
00293     {
00294         set_max(items.size() - 1);
00295     }
00296     slider::set_value(0);
00297 }
00298 
00299 template<typename T>
00300 const T& list_slider<T>::item_selected() const
00301 {
00302     return items_[value()];
00303 }
00304 
00305 template<typename T>
00306 bool list_slider<T>::select_item(const T& item)
00307 {
00308     for(unsigned i = 0, nb = items_.size(); i < nb; ++i)
00309     {
00310         if(item == items_[i])
00311         {
00312             slider::set_value(i);
00313             return true;
00314         }
00315     }
00316     return false;
00317 }
00318 
00319 template<typename T>
00320 void list_slider<T>::set_items(const std::vector<T> &items)
00321 {
00322     items_ = items;
00323     if(items.size() > 0)
00324     {
00325         set_max(items.size() - 1);
00326     }
00327     slider::set_value(0);
00328 }
00329 
00330 // Force compilation of the following template instantiations
00331 template class list_slider< double >;
00332 template class list_slider< int >;
00333 template class list_slider< std::string >;
00334 
00335 } //end namespace gui
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:56 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs