wvar.h

Go to the documentation of this file.
00001 /*
00002   libwt - Vassilis Virvilis Toolkit - a widget library
00003   Copyright (C) 2006 Vassilis Virvilis <vasvir2@fastmail.fm>
00004  
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Lesser General Public
00007   License as published by the Free Software Foundation; either
00008   version 2.1 of the License, or (at your option) any later version.
00009   
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Lesser General Public License for more details.
00014   
00015   You should have received a copy of the GNU Lesser General Public
00016   License along with this library; if not, write to the
00017   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018   Boston, MA  02111-1307, SA.
00019 */
00020 
00021 #ifndef WT_WVAR_H
00022 #define WT_WVAR_H
00023 
00024 #include <boost/lexical_cast.hpp>
00025 
00026 #include <wt/wsignal.h>
00027 
00028 namespace Wt {
00029 
00030 /// Watched variable avoids the need for get/set methods
00031 /*!
00032     A WVar watched variable is a templated attempt to
00033     vanquish the get set methods that accompanies object oriented
00034     programming.
00035     
00036     \note The WVar class is good only for arithmetic (builtin)
00037     types and not generic classes due to c++'s C ish background. Maybe
00038     later we will build a WClass class. The problem is that WVar has
00039     a value of VARTYPE instead of inheriting from VARTYPE. This has
00040     the ugly effect that VARTYPE's members cannot be accessed through
00041     WVar without ugly casts, and of course in C++ is not possible to
00042     inherit from builtin types (int, bool) etc.
00043     
00044     A WVar variable can be read through the cast operator and
00045     be written through the assign operator. The WVar variable
00046     emits a signal when it is about to change, after it
00047     has been changed, and when it is accessed for read.
00048  
00049     if a slot from the ones that are called during aboutToChange
00050     returns true then the change is aborted.    
00051     
00052     A WVar variable can be publically read/write or protected. The
00053     default is to be publically read/write. If you do not wish for
00054     your variable to be publically readable just make your damn
00055     variable protected/private.
00056     
00057     WVar<int> a is a read/write int variable.
00058     WVar<int, C> a is a publically readable and read/write for class C.
00059  
00060 Example:
00061     see test/vars.c 
00062 */
00063 
00064 template<typename VARTYPE>
00065 class WVarBase : public sigc::trackable {
00066 protected:
00067     /// Marshaler
00068     class Blocker {
00069     public:
00070         typedef bool result_type;
00071         template<typename T_iterator>
00072         result_type operator()(T_iterator first, T_iterator last) const {
00073             for (; first != last; ++first)
00074                 if (*first)
00075                     return true;
00076             return false;
00077         }
00078     };
00079 
00080     class OverideValue {
00081     public:
00082         OverideValue(bool valid_ = false, const VARTYPE& value_ = VARTYPE())
00083                 : valid_(valid_),
00084         value_(value_) {}
00085 
00086         OverideValue& operator=(VARTYPE v) {
00087             valid_ = true;
00088             value_ = v;
00089             return *this;
00090         }
00091 
00092         bool isValid() const {
00093             return valid_;
00094         }
00095 
00096         VARTYPE value() const {
00097             return value_;
00098         }
00099 
00100     private:
00101         bool valid_;
00102         VARTYPE value_;
00103     };
00104 
00105     typedef std::pair<bool, VARTYPE> ValidValue;
00106     /// Marshaler to override all values but the last
00107     class Overrider {
00108     public:
00109         typedef OverideValue result_type;
00110         template<typename T_iterator>
00111         result_type operator()(T_iterator first, T_iterator last) const {
00112             OverideValue result(false, VARTYPE());
00113             for (; first != last; ++first) {
00114                 result = (*first);
00115             }
00116             return result;
00117         }
00118     };
00119 
00120     /// avoids emitting read signal
00121     const VARTYPE& getValue() const {
00122         return value_;
00123     }
00124 
00125     /// avoids emitting aboutToChange, changed signal
00126     void setValue(const VARTYPE & value) {
00127         value_ = value;
00128     }
00129 
00130     WVarBase& operator=(VARTYPE value) {
00131         if (!aboutToChange.emit(value, value_)) {
00132             VARTYPE old(value_);
00133             setValue(value);
00134             changed.emit(value, old);
00135         }
00136         return *this;
00137     }
00138 
00139     WVarBase& operator=(const WVarBase& value) {
00140         *this = static_cast<VARTYPE>(value);
00141         return *this;
00142     }
00143 
00144 private:
00145     VARTYPE value_;
00146 
00147 public:
00148     class RW {
00149     public:
00150     };
00151 
00152     WVarBase(VARTYPE value = 0) {
00153         value_ = value;
00154     }
00155 
00156     Signal012M<bool, VARTYPE, VARTYPE, Blocker> aboutToChange;
00157     Signal012<void, VARTYPE, VARTYPE> changed;
00158     mutable Signal01<void, VARTYPE> read;
00159     mutable sigc::signal1<VARTYPE, VARTYPE, Overrider> override;
00160 
00161     VARTYPE readValue() const {
00162         read.emit(value_);
00163         const OverideValue v = override.emit(value_);
00164         return (v.isValid()) ? v.value() : value_;
00165     }
00166 
00167     ///\todo get, set and other they should really
00168     ///use const& where possible
00169 
00170     /// usefull for overrides and variables connection
00171     VARTYPE get
00172         (VARTYPE ) const {
00173             return readValue();
00174         }
00175 
00176     void set
00177         (VARTYPE value) {
00178         *this = value;
00179     }
00180 
00181     /// connect as a proxy to another WVar
00182     void connect(WVarBase& var) {
00183         // set the real variable to the proxy value
00184         var = getValue();
00185 
00186         changed.connect(
00187             sigc::slot1<void, VARTYPE>(
00188                 sigc::mem_fun(var, &WVarBase::set
00189                                  )));
00190 
00191         override.connect(sigc::mem_fun(var, &WVarBase::get
00192                                           ));
00193     }
00194 
00195     operator VARTYPE() const {
00196         return readValue();
00197     }
00198 
00199     operator const std::string() const {
00200         return boost::lexical_cast<std::string>(readValue());
00201     }
00202 
00203     WVarBase& operator+=(const VARTYPE& value) {
00204         if (value) {
00205             *this = getValue() + value;
00206         }
00207         return *this;
00208     }
00209 
00210     WVarBase& operator-=(const VARTYPE & value) {
00211         if (value) {
00212             *this = getValue() - value;
00213         }
00214         return *this;
00215     }
00216 
00217     /// prefix operator
00218     WVarBase& operator++() {
00219         VARTYPE other(*this);
00220         ++other;
00221         *this = other;
00222         return *this;
00223     }
00224 
00225     WVarBase& operator--() {
00226         VARTYPE other(*this);
00227         --other;
00228         *this = other;
00229         return *this;
00230     }
00231 
00232     /// postfix operator
00233     WVarBase& operator++(int) {
00234         VARTYPE other(*this);
00235         other++;
00236         *this = other;
00237         return *this;
00238     }
00239 
00240     WVarBase& operator--(int) {
00241         VARTYPE other(*this);
00242         other--;
00243         *this = other;
00244         return *this;
00245     }
00246 };
00247 
00248 #define OPERATORS \
00249     WVar& operator=(const VARTYPE & value) {\
00250         return static_cast<WVar &>(WVarBase<VARTYPE>::operator=(value));\
00251     }\
00252 \
00253     WVar& operator=(const WVarBase<VARTYPE>& value) {\
00254         return static_cast<WVar &>(WVarBase<VARTYPE>::operator=(value));\
00255     }\
00256 \
00257     WVar& operator+=(const VARTYPE & value) {\
00258         return static_cast<WVar &>(WVarBase<VARTYPE>::operator+=(value));\
00259     }\
00260 \
00261     WVar& operator-=(const VARTYPE & value) {\
00262         return static_cast<WVar &>(WVarBase<VARTYPE>::operator-=(value));\
00263     }\
00264 \
00265     WVar& operator++() {\
00266         return static_cast<WVar &>(WVarBase<VARTYPE>::operator++());\
00267     }\
00268 \
00269     WVar& operator--() {\
00270         return static_cast<WVar &>(WVarBase<VARTYPE>::operator--());\
00271     }\
00272 \
00273     WVar& operator++(int) {\
00274         return static_cast<WVar &>(WVarBase<VARTYPE>::operator++(0));\
00275     }\
00276 \
00277     WVar& operator--(int) {\
00278         return static_cast<WVar &>(WVarBase<VARTYPE>::operator--(0));\
00279     }
00280 
00281 /// read only
00282 template<typename VARTYPE, typename PARENT = WVarBase<int>::RW>
00283 class WVar : public WVarBase<VARTYPE> {
00284 public:
00285     WVar(VARTYPE value = 0)
00286             : WVarBase<VARTYPE>(value) {}
00287 
00288 protected:
00289     OPERATORS
00290 
00291     // this wrapper bullshit here is required because g++ does
00292     // not compile the following simple statement
00293     // friend class PARENT;
00294 #if 1
00295     class WrappedParent {
00296     public:
00297         typedef PARENT Parent;
00298     };
00299 
00300     friend class WrappedParent::Parent;
00301 #else
00302 
00303     friend class PARENT;
00304 #endif
00305 
00306 };
00307 
00308 /// read write specialization
00309 template<>
00310 template<typename VARTYPE>
00311 class WVar<VARTYPE, WVarBase<int>::RW> : public WVarBase<VARTYPE> {
00312 
00313 public:
00314     WVar(VARTYPE value = 0)
00315             : WVarBase<VARTYPE>(value) {}
00316 
00317     OPERATORS
00318 };
00319 
00320 } // namespace
00321 
00322 #endif // WT_WVAR_H

Generated Fri Jul 28 19:23:01 2006.
Copyright © 1998-2003 by the respective authors.

This document is licensed under the terms of the GNU Free Documentation License and may be freely distributed under the conditions given by this license.