gui/auxiliary/formula.hpp

Go to the documentation of this file.
00001 /* $Id: formula.hpp 53834 2012-04-07 15:58:08Z loonycyborg $ */
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 #ifndef GUI_WIDGETS_FORMULA_HPP_INCLUDED
00017 #define GUI_WIDGETS_FORMULA_HPP_INCLUDED
00018 
00019 #include "formula_callable.hpp"
00020 #include "../../formula.hpp"
00021 #include "gui/auxiliary/log.hpp"
00022 #include "gui/widgets/helper.hpp"
00023 #include "serialization/string_utils.hpp"
00024 #include "util.hpp"
00025 #include "tstring.hpp"
00026 
00027 #include <boost/static_assert.hpp>
00028 
00029 #include <cassert>
00030 
00031 namespace gui2{
00032 
00033 /**
00034  * Template class can hold a value or a formula to calculate the value.
00035  *
00036  * A string is a formula when it starts with a right paren, no other validation
00037  * is done by this function, leading whitespace is significant.
00038  *
00039  * Upon getting the value of the formula a variable map is send. The variables
00040  * in the map can be used in the formula. The 'owners' of the class need to
00041  * document the variables available.
00042  *
00043  * @tparam T                      The type of the formula. This type needs to
00044  *                                be constructable form a string, either by a
00045  *                                lexical_cast or a template specialization in
00046  *                                this header.
00047  */
00048 template <class T>
00049 class tformula
00050 {
00051 public:
00052     /**
00053      * Constructor.
00054      *
00055      * @param str                 The string used to initialize the class, this
00056      *                            can either be a formula or a string which can
00057      *                            be converted to the type T.
00058      * @param value               The default value for the object.
00059      */
00060     explicit tformula<T>(const std::string& str, const T value = T());
00061 
00062     /**
00063      * Returns the value, can only be used if the data is no formula.
00064      *
00065      * Another option would be to cache the output of the formula in value_
00066      * and always allow this function. But for now decided that the caller
00067      * needs to do the caching. It might be changed later.
00068      */
00069     T operator()() const
00070     {
00071         assert(!has_formula());
00072         return value_;
00073     }
00074 
00075     /** Returns the value, can always be used. */
00076     T operator() (const game_logic::map_formula_callable& variables) const;
00077 
00078     /** Determine whether the class contains a formula. */
00079     bool has_formula() const { return !formula_.empty(); }
00080 
00081 private:
00082 
00083     /**
00084      * Converts the string to the template type.
00085      *
00086      * This function is used by the constructor to convert the string to the
00087      * wanted value, if not a formula.
00088      *
00089      * @param str                 The str send to the constructor.
00090      */
00091     void convert(const std::string& str);
00092 
00093     /**
00094      * Executes the formula.
00095      *
00096      * This function does the calculation and can only be called if the object
00097      * contains a formula.
00098      *
00099      * @param variables           The state variables which might be used in
00100      *                            the formula. For example a screen_width can
00101      *                            be set so the formula can return the half
00102      *                            width of the screen.
00103      *
00104      * @returns                   The calculated value.
00105      */
00106     T execute(const game_logic::map_formula_callable& variables) const;
00107 
00108     /**
00109      * Contains the formuale for the variable.
00110      *
00111      * If the string is empty, there's no formula.
00112      */
00113     std::string formula_;
00114 
00115     /** If there's no formula it contains the value. */
00116     T value_;
00117 };
00118 
00119 template<class T>
00120 tformula<T>::tformula(const std::string& str, const T value) :
00121     formula_(),
00122     value_(value)
00123 {
00124     if(str.empty()) {
00125         return;
00126     }
00127 
00128     if(str[0] == '(') {
00129         formula_ = str;
00130     } else {
00131         convert(str);
00132     }
00133 }
00134 
00135 template<class T>
00136 inline T tformula<T>::operator()(
00137         const game_logic::map_formula_callable& variables) const
00138 {
00139     if(has_formula()) {
00140         const T& result = execute(variables);
00141         LOG_GUI_D << "Formula: execute '" << formula_
00142             << "' result '" << result
00143             << "'.\n";
00144         return result;
00145     } else {
00146         return value_;
00147     }
00148 }
00149 
00150 template<>
00151 inline bool tformula<bool>::execute(
00152         const game_logic::map_formula_callable& variables) const
00153 {
00154     return game_logic::formula(formula_).evaluate(variables).as_bool();
00155 }
00156 
00157 template<>
00158 inline int tformula<int>::execute(
00159         const game_logic::map_formula_callable& variables) const
00160 {
00161     return game_logic::formula(formula_).evaluate(variables).as_int();
00162 }
00163 
00164 template<>
00165 inline unsigned tformula<unsigned>::execute(
00166         const game_logic::map_formula_callable& variables) const
00167 {
00168     return game_logic::formula(formula_).evaluate(variables).as_int();
00169 }
00170 
00171 template<>
00172 inline std::string tformula<std::string>::execute(
00173         const game_logic::map_formula_callable& variables) const
00174 {
00175     return game_logic::formula(formula_).evaluate(variables).as_string();
00176 }
00177 
00178 template<>
00179 inline t_string tformula<t_string>::execute(
00180         const game_logic::map_formula_callable& variables) const
00181 {
00182     return game_logic::formula(formula_).evaluate(variables).as_string();
00183 }
00184 
00185 template<>
00186 inline PangoAlignment tformula<PangoAlignment>::execute(
00187         const game_logic::map_formula_callable& variables) const
00188 {
00189     return decode_text_alignment(
00190             game_logic::formula(formula_).evaluate(variables).as_string());
00191 }
00192 
00193 template<class T>
00194 inline T tformula<T>::execute(
00195         const game_logic::map_formula_callable& /*variables*/) const
00196 {
00197     // Every type needs its own execute function avoid instantiation of the
00198     // default execute.
00199     BOOST_STATIC_ASSERT(sizeof(T) == 0);
00200     return T();
00201 }
00202 
00203 template<>
00204 inline void tformula<bool>::convert(const std::string& str)
00205 {
00206     value_ = utils::string_bool(str);
00207 }
00208 
00209 template<>
00210 inline void tformula<std::string>::convert(const std::string& str)
00211 {
00212     value_ = str;
00213 }
00214 
00215 template<>
00216 inline void tformula<t_string>::convert(const std::string& str)
00217 {
00218     value_ = str;
00219 }
00220 
00221 template<>
00222 inline void tformula<PangoAlignment>::convert(const std::string& str)
00223 {
00224     value_ = decode_text_alignment(str);
00225 }
00226 
00227 template<class T>
00228 inline void tformula<T>::convert(const std::string& str)
00229 {
00230     value_ = lexical_cast_default<T>(str);
00231 }
00232 
00233 } // namespace gui2
00234 
00235 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

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