slider.cpp

Go to the documentation of this file.
00001 /* $Id: slider.cpp 23842 2008-02-16 08:47:16Z mordante $ */
00002 /*
00003    Copyright (C) 2003 - 2008 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 version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
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         //when event is not specified, signal that focus may be desired later
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     //mouse events are processed regardless of focus
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 // Force compilation of the following template instantiations
00330 template class list_slider< double >;
00331 template class list_slider< int >;
00332 template class list_slider< std::string >;
00333 
00334 } //end namespace gui

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs