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
| Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:51 for The Battle for Wesnoth | Gna! | Forum | Wiki | CIA | devdocs |