gui/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) 2008 - 2012 by Mark de Wever <koraq@xs4all.nl>
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 "gui/widgets/slider.hpp"
00019 
00020 #include "foreach.hpp"
00021 #include "formatter.hpp"
00022 #include "gui/auxiliary/log.hpp"
00023 #include "gui/auxiliary/widget_definition/slider.hpp"
00024 #include "gui/auxiliary/window_builder/slider.hpp"
00025 #include "gui/widgets/window.hpp"
00026 #include "gui/widgets/settings.hpp"
00027 #include "sound.hpp"
00028 
00029 #include <boost/bind.hpp>
00030 
00031 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
00032 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
00033 
00034 namespace gui2 {
00035 
00036 REGISTER_WIDGET(slider)
00037 
00038 static int distance(const int a, const int b)
00039 {
00040     /**
00041      * @todo once this works properly the assert can be removed and the code
00042      * inlined.
00043      */
00044     int result =  b - a;
00045     assert(result >= 0);
00046     return result;
00047 }
00048 
00049 tslider::tslider():
00050         tscrollbar_(),
00051         best_slider_length_(0),
00052         minimum_value_(0),
00053         minimum_value_label_(),
00054         maximum_value_label_(),
00055         value_labels_()
00056 {
00057     connect_signal<event::SDL_KEY_DOWN>(boost::bind(
00058         &tslider::signal_handler_sdl_key_down, this, _2, _3, _5));
00059     connect_signal<event::LEFT_BUTTON_UP>(boost::bind(
00060         &tslider::signal_handler_left_button_up, this, _2, _3));
00061 
00062 }
00063 
00064 tpoint tslider::calculate_best_size() const
00065 {
00066     log_scope2(log_gui_layout, LOG_SCOPE_HEADER);
00067 
00068     // Inherited.
00069     tpoint result = tcontrol::calculate_best_size();
00070     if(best_slider_length_ != 0) {
00071 
00072         // Override length.
00073         boost::intrusive_ptr<const tslider_definition::tresolution> conf =
00074             boost::dynamic_pointer_cast<const tslider_definition::tresolution>
00075             (config());
00076 
00077         assert(conf);
00078 
00079         result.x = conf->left_offset + best_slider_length_ + conf->right_offset;
00080     }
00081 
00082     DBG_GUI_L << LOG_HEADER
00083         << " best_slider_length " << best_slider_length_
00084         << " result " << result
00085         << ".\n";
00086     return result;
00087 
00088 }
00089 
00090 void tslider::set_value(const int value)
00091 {
00092     if(value == get_value()) {
00093         return;
00094     }
00095 
00096     if(value < minimum_value_) {
00097         set_value(minimum_value_);
00098     } else if(value > get_maximum_value()) {
00099         set_value(get_maximum_value());
00100     } else {
00101         set_item_position(distance(minimum_value_, value));
00102     }
00103 }
00104 
00105 void tslider::set_minimum_value(const int minimum_value)
00106 {
00107     if(minimum_value == minimum_value_) {
00108         return;
00109     }
00110 
00111     /** @todo maybe make it a VALIDATE. */
00112     assert(minimum_value <= get_maximum_value());
00113 
00114     const int value = get_value();
00115     const int maximum_value = get_maximum_value();
00116     minimum_value_ = minimum_value;
00117 
00118     // The number of items needs to include the begin and end so distance + 1.
00119     set_item_count(distance(minimum_value_, maximum_value) + 1);
00120 
00121     if(value < minimum_value_) {
00122         set_item_position(0);
00123     } else {
00124         set_item_position(minimum_value_ + value);
00125     }
00126 }
00127 
00128 void tslider::set_maximum_value(const int maximum_value)
00129 {
00130     if(maximum_value == get_maximum_value()) {
00131         return;
00132     }
00133 
00134     /** @todo maybe make it a VALIDATE. */
00135     assert(minimum_value_ <= maximum_value);
00136 
00137     const int value = get_value();
00138 
00139     // The number of items needs to include the begin and end so distance + 1.
00140     set_item_count(distance(minimum_value_, maximum_value) + 1);
00141 
00142     if(value > maximum_value) {
00143         set_item_position(get_maximum_value());
00144     } else {
00145         set_item_position(minimum_value_ + value);
00146     }
00147 }
00148 
00149 t_string tslider::get_value_label() const
00150 {
00151     if(!value_labels_.empty()) {
00152         assert(value_labels_.size() == get_item_count());
00153         return value_labels_[get_item_position()];
00154     } else if(!minimum_value_label_.empty()
00155             && get_value() == get_minimum_value()) {
00156         return minimum_value_label_;
00157     } else if(!maximum_value_label_.empty()
00158             && get_value() == get_maximum_value()) {
00159         return maximum_value_label_;
00160     } else {
00161         return t_string((formatter() << get_value()).str());
00162     }
00163 }
00164 
00165 void tslider::child_callback_positioner_moved()
00166 {
00167     sound::play_UI_sound(settings::sound_slider_adjust);
00168 }
00169 
00170 unsigned tslider::minimum_positioner_length() const
00171 {
00172     boost::intrusive_ptr<const tslider_definition::tresolution> conf =
00173         boost::dynamic_pointer_cast<const tslider_definition::tresolution>(config());
00174     assert(conf);
00175     return conf->minimum_positioner_length;
00176 }
00177 
00178 unsigned tslider::maximum_positioner_length() const
00179 {
00180     boost::intrusive_ptr<const tslider_definition::tresolution> conf =
00181         boost::dynamic_pointer_cast<const tslider_definition::tresolution>(config());
00182     assert(conf);
00183     return conf->maximum_positioner_length;
00184 }
00185 
00186 unsigned tslider::offset_before() const
00187 {
00188     boost::intrusive_ptr<const tslider_definition::tresolution> conf =
00189         boost::dynamic_pointer_cast<const tslider_definition::tresolution>(config());
00190     assert(conf);
00191     return conf->left_offset;
00192 }
00193 
00194 unsigned tslider::offset_after() const
00195 {
00196     boost::intrusive_ptr<const tslider_definition::tresolution> conf =
00197         boost::dynamic_pointer_cast<const tslider_definition::tresolution>(config());
00198     assert(conf);
00199     return conf->right_offset;
00200 }
00201 
00202 bool tslider::on_positioner(const tpoint& coordinate) const
00203 {
00204     // Note we assume the positioner is over the entire height of the widget.
00205     return coordinate.x >= static_cast<int>(get_positioner_offset())
00206         && coordinate.x < static_cast<int>(get_positioner_offset() + get_positioner_length())
00207         && coordinate.y > 0
00208         && coordinate.y < static_cast<int>(get_height());
00209 }
00210 
00211 int tslider::on_bar(const tpoint& coordinate) const
00212 {
00213     // Not on the widget, leave.
00214     if(static_cast<size_t>(coordinate.x) > get_width()
00215             || static_cast<size_t>(coordinate.y) > get_height()) {
00216         return 0;
00217     }
00218 
00219     // we also assume the bar is over the entire height of the widget.
00220     if(static_cast<size_t>(coordinate.x) < get_positioner_offset()) {
00221         return -1;
00222     } else if(static_cast<size_t>(coordinate.x) >get_positioner_offset() + get_positioner_length()) {
00223         return 1;
00224     } else {
00225         return 0;
00226     }
00227 }
00228 
00229 void tslider::update_canvas()
00230 {
00231 
00232     // Inherited.
00233     tscrollbar_::update_canvas();
00234 
00235     foreach(tcanvas& tmp, canvas()) {
00236         tmp.set_variable("text", variant(get_value_label()));
00237     }
00238 }
00239 
00240 const std::string& tslider::get_control_type() const
00241 {
00242     static const std::string type = "slider";
00243     return type;
00244 }
00245 
00246 void tslider::handle_key_decrease(bool& handled)
00247 {
00248     DBG_GUI_E << LOG_HEADER << '\n';
00249 
00250     handled = true;
00251 
00252     scroll(tscrollbar_::ITEM_BACKWARDS);
00253 }
00254 
00255 void tslider::handle_key_increase(bool& handled)
00256 {
00257     DBG_GUI_E << LOG_HEADER << '\n';
00258 
00259     handled = true;
00260 
00261     scroll(tscrollbar_::ITEM_FORWARD);
00262 }
00263 
00264 void tslider::signal_handler_sdl_key_down(const event::tevent event
00265         , bool& handled
00266         , const SDLKey key)
00267 {
00268 
00269     DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
00270 
00271     if (key == SDLK_DOWN || key == SDLK_LEFT) {
00272         handle_key_decrease(handled);
00273     } else if (key == SDLK_UP || key == SDLK_RIGHT) {
00274         handle_key_increase(handled);
00275     } else {
00276         // Do nothing. Ignore other keys.
00277     }
00278 }
00279 
00280 void tslider::signal_handler_left_button_up(
00281         const event::tevent event, bool& handled)
00282 {
00283     DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
00284 
00285     get_window()->keyboard_capture(this);
00286 
00287     handled = true;
00288 }
00289 
00290 } // namespace gui2
00291 
 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