00001 /* 00002 * Copyright (C) 2003-2009 Olivier Boudeville 00003 * 00004 * This file is part of the Ceylan library. 00005 * 00006 * The Ceylan library is free software: you can redistribute it and/or modify 00007 * it under the terms of either the GNU Lesser General Public License or 00008 * the GNU General Public License, as they are published by the Free Software 00009 * Foundation, either version 3 of these Licenses, or (at your option) 00010 * any later version. 00011 * 00012 * The Ceylan library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License and the GNU General Public License 00016 * for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License and the GNU General Public License along with the Ceylan library. 00020 * If not, see <http://www.gnu.org/licenses/>. 00021 * 00022 * Author: Olivier Boudeville (olivier.boudeville@esperide.com) 00023 * 00024 */ 00025 00026 00027 #ifndef CEYLAN_GENERIC_MODEL_H_ 00028 #define CEYLAN_GENERIC_MODEL_H_ 00029 00030 00031 #include "CeylanGenericMVCDefines.h" // for GenericMVCException 00032 #include "CeylanTextDisplayable.h" // for inheritance 00033 #include "CeylanOperators.h" // for toString 00034 #include "CeylanStringUtils.h" // for formatStringList 00035 #include "CeylanGenericView.h" // for BaseView 00036 00037 00038 #include <string> 00039 #include <list> 00040 00041 00042 00043 /* 00044 * See the CeylanGenericMVCDefines.h file for detailed design explanations 00045 * about this light-weight generic (template-based) MVC framework. 00046 * 00047 */ 00048 00049 00050 /* 00051 * Here the base model (BaseModel) and all necessary templated variations of 00052 * models are defined: 00053 * 00054 * - a model with no view and no controller: NoViewGenericModel 00055 * - a model with a single view and no controller: 00056 * - templated version: SingleViewGenericModel<View> (often overkill) 00057 * - usually sufficient non-template version: SingleViewModel 00058 * - a model with multiple (any number of) views and no controller: 00059 * MultipleViewGenericModel<View> 00060 * - a model with no view and a single controller: 00061 * SingleControllerNoViewGenericModel<Controller> 00062 * - a model with a single view and a single controller: 00063 * SingleControllerSingleViewGenericModel<Controller> 00064 * 00065 */ 00066 00067 00068 /* 00069 * Actually there is apparently little need for a model to know the 00070 * specific class of its view(s), as a model will just manage their life-cycle. 00071 * Hence view-templated models are not strictly necessary: they just deal with 00072 * (not necessarily known) BaseView instances. 00073 * 00074 * On the contrary, a view has to know the actual model class it corresponds 00075 * to (i.e. a view has to be model-templated), as the view needs, to perform 00076 * its rendering, to call class-specific (const) methods from its model(s) 00077 * (to know its state). 00078 * 00079 * Therefore here view-templated models have non-template counterparts, which 00080 * are easier to integrate in user's code and should be nevertheless suitable 00081 * for most usages: 00082 * 00083 * - a model with a single view and no controller: SingleViewGenericModel 00084 * - a model with multiple (any number of) views and no controller: 00085 * MultipleViewGenericModel 00086 * 00087 * @note SingleViewModel could not be named SingleViewGenericModel as the 00088 * compiler would find an ambiguity with the SingleViewGenericModel template. 00089 * However SingleViewModel and al should not by confused with the 00090 * Ceylan::MVC::Model class, which belongs to a different (event-based) MVC 00091 * framework. 00092 * 00093 */ 00094 00095 00096 00097 00098 00099 namespace Ceylan 00100 { 00101 00102 00103 namespace MVC 00104 { 00105 00106 00107 00108 // A model may know its view(s): 00109 class BaseView ; 00110 00111 00112 // A model knows its controller(s): 00113 class BaseController ; 00114 00115 00116 00117 00118 00119 // BaseModel mother class. 00120 00121 00146 class CEYLAN_DLL BaseModel : public TextDisplayable 00147 { 00148 00149 00150 public: 00151 00152 00153 00158 BaseModel() ; 00159 00160 00161 00163 virtual ~BaseModel() throw() ; 00164 00165 00166 00183 virtual void addView( const BaseView & view ) const = 0 ; 00184 00185 00186 // No addController defined, not really useful. 00187 00188 00200 virtual const std::string toString( 00201 Ceylan::VerbosityLevels level = Ceylan::high ) const ; 00202 00203 00204 00205 00206 private: 00207 00208 00209 /* 00210 * No datastructure declared for view(s) nor controller(s), 00211 * as it depends on the actual specialization of the MVC 00212 * framework. 00213 * 00214 * For example, defining a reference would be enough for a 00215 * single view, for multiple views a list could be more 00216 * appropriate, etc. 00217 * 00218 */ 00219 00220 00228 BaseModel( const BaseModel & source ) ; 00229 00230 00238 BaseModel & operator = ( const BaseModel & source ) ; 00239 00240 00241 } ; 00242 00243 00244 00245 00246 00247 00248 // NoViewModel class. No template issues here. 00249 00250 00251 00258 class CEYLAN_DLL NoViewModel : public BaseModel 00259 { 00260 00261 00262 public: 00263 00264 00265 00270 NoViewModel() ; 00271 00272 00273 00275 virtual ~NoViewModel() throw() ; 00276 00277 00278 00290 virtual void addView( const BaseView & view ) const ; 00291 00292 00293 00305 virtual const std::string toString( 00306 Ceylan::VerbosityLevels level = Ceylan::high ) const ; 00307 00308 00309 00310 00311 private: 00312 00313 00321 NoViewModel( const NoViewModel & source ) ; 00322 00323 00331 NoViewModel & operator = ( const NoViewModel & source ) ; 00332 00333 00334 } ; 00335 00336 00337 00338 00339 00340 00341 00342 /* 00343 * SingleViewGenericModel templated class. 00344 * 00345 * @note Usually using this view-templated class is overkill, as 00346 * most, if not all, models do not really need to know the actual class 00347 * of the views they are associated with. 00348 * 00349 * @see the SingleViewModel non-templated class instead. 00350 * 00351 */ 00352 00353 00354 00355 00371 template <typename ActualView> 00372 class SingleViewGenericModel : public BaseModel 00373 { 00374 00375 public: 00376 00377 00388 explicit SingleViewGenericModel( const ActualView & view ) ; 00389 00390 00402 SingleViewGenericModel() ; 00403 00404 00405 00412 virtual ~SingleViewGenericModel() throw() ; 00413 00414 00415 00424 virtual void setView( const ActualView & view ) ; 00425 00426 00427 00446 virtual void addView( const ActualView & view ) const ; 00447 00448 00449 00461 virtual const std::string toString( 00462 Ceylan::VerbosityLevels level = Ceylan::high ) const ; 00463 00464 00465 00466 protected: 00467 00468 00477 const ActualView * _view ; 00478 00479 00480 00481 private: 00482 00483 00491 SingleViewGenericModel( 00492 const SingleViewGenericModel & source ) ; 00493 00494 00502 SingleViewGenericModel & operator = ( 00503 const SingleViewGenericModel & source ) ; 00504 00505 00506 } ; 00507 00508 00509 00510 00511 // Implementation of the SingleViewGenericModel templated class. 00512 00513 00514 template <typename ActualView> 00515 SingleViewGenericModel<ActualView>::SingleViewGenericModel( 00516 const ActualView & view ) : 00517 _view( & view ) 00518 { 00519 00520 } 00521 00522 00523 00524 template <typename ActualView> 00525 SingleViewGenericModel<ActualView>::SingleViewGenericModel() : 00526 _view( 0 ) 00527 { 00528 00529 } 00530 00531 00532 00533 template <typename ActualView> 00534 SingleViewGenericModel<ActualView>::~SingleViewGenericModel() throw() 00535 { 00536 00537 if ( this->_view != 0 ) 00538 { 00539 00540 // View owned here: 00541 delete this->_view ; 00542 00543 } 00544 00545 } 00546 00547 00548 00549 template <typename ActualView> 00550 void 00551 SingleViewGenericModel<ActualView>::setView( const ActualView & view ) 00552 { 00553 00554 addView( view ) ; 00555 00556 } 00557 00558 00559 00560 template <typename ActualView> 00561 void 00562 SingleViewGenericModel<ActualView>::addView( const ActualView & view ) 00563 const 00564 { 00565 00566 if ( this->_view != 0 ) 00567 throw GenericMVCException( 00568 "SingleViewGenericModel<ActualView>::addView failed: " 00569 "a view was already registered." ) ; 00570 00571 // Do as if this instance had not to be 'const': 00572 const_cast< SingleViewGenericModel<ActualView> *>(this)->_view = 00573 & view ; 00574 00575 } 00576 00577 00578 00579 template <typename ActualView> 00580 const std::string 00581 SingleViewGenericModel<ActualView>::toString( 00582 Ceylan::VerbosityLevels level ) const 00583 { 00584 00585 if ( this->_view != 0 ) 00586 { 00587 00588 /* 00589 * Beware to infinite recursion: 00590 * (the view may display in turn this model) 00591 * 00592 */ 00593 00594 if ( level == Ceylan::low ) 00595 return "Single-view controller-less generic model " 00596 "owning a view" ; 00597 else 00598 return "Single-view controller-less generic model " 00599 "associated to " + this->_view->toString( level ) ; 00600 00601 } 00602 else 00603 { 00604 00605 return "Single-view controller-less generic model " 00606 "not associated to any view" ; 00607 00608 } 00609 00610 } 00611 00612 00613 00614 00615 00616 /* 00617 * SingleViewModel non-templated class. 00618 * 00619 * Simpler than the SingleViewGenericModel view-templated 00620 * counterpart, but deals with BaseView instances instead of an actual 00621 * view child class. 00622 * 00623 * Once the actual relationships between a model and its views 00624 * are taken into account, using a non-templated model should not be 00625 * a problem in general. 00626 * 00627 */ 00628 00629 00630 00631 00642 class CEYLAN_DLL SingleViewModel : public BaseModel 00643 { 00644 00645 public: 00646 00647 00648 00659 explicit SingleViewModel( const BaseView & view ) ; 00660 00661 00662 00672 SingleViewModel() ; 00673 00674 00675 00682 virtual ~SingleViewModel() throw() ; 00683 00684 00685 00700 virtual void setView( const BaseView & view ) ; 00701 00702 00703 00722 virtual void addView( const BaseView & view ) const ; 00723 00724 00725 00737 virtual const std::string toString( 00738 Ceylan::VerbosityLevels level = Ceylan::high ) const ; 00739 00740 00741 00742 protected: 00743 00744 00753 const BaseView * _view ; 00754 00755 00756 00757 private: 00758 00759 00767 SingleViewModel( const SingleViewModel & source ) ; 00768 00769 00777 SingleViewModel & operator = ( 00778 const SingleViewModel & source ) ; 00779 00780 00781 } ; 00782 00783 00784 00785 00786 00787 00788 /* 00789 * MultipleViewGenericModel templated class. 00790 * 00791 * @note Usually using this view-templated class is overkill, as 00792 * most if not all models do not really need to know the actual class 00793 * of the views they are associated with. 00794 * 00795 */ 00796 00797 00798 00807 template <typename ActualView> 00808 class MultipleViewGenericModel : public BaseModel 00809 { 00810 00811 00812 public: 00813 00814 00815 00826 explicit MultipleViewGenericModel( const ActualView & view ) ; 00827 00828 00829 00840 explicit MultipleViewGenericModel( 00841 const std::list<const ActualView *> & views ) ; 00842 00843 00844 00855 MultipleViewGenericModel() ; 00856 00857 00858 00865 virtual ~MultipleViewGenericModel() throw() ; 00866 00867 00868 00879 virtual void setViews( 00880 const std::list<const ActualView *> & views ) ; 00881 00882 00883 00898 virtual void addView( const ActualView & view ) const ; 00899 00900 00901 00913 virtual const std::string toString( 00914 Ceylan::VerbosityLevels level = Ceylan::high ) const ; 00915 00916 00917 00918 00919 protected: 00920 00921 00922 00924 virtual void deleteViews() ; 00925 00926 00928 std::list<const ActualView *> _views ; 00929 00930 00931 00932 00933 private: 00934 00935 00943 MultipleViewGenericModel( 00944 const MultipleViewGenericModel & source ) ; 00945 00946 00954 MultipleViewGenericModel & operator = ( 00955 const MultipleViewGenericModel & source ) ; 00956 00957 00958 } ; 00959 00960 00961 00962 00963 // Implementation of the MultipleViewGenericModel templated class. 00964 00965 00966 template <typename ActualView> 00967 MultipleViewGenericModel<ActualView>::MultipleViewGenericModel( 00968 const ActualView & view ) 00969 { 00970 00971 this->_views.push_back( view ) ; 00972 00973 } 00974 00975 00976 template <typename ActualView> 00977 MultipleViewGenericModel<ActualView>::MultipleViewGenericModel( 00978 const std::list<const ActualView *> & views ) 00979 { 00980 00981 this->_views = views ; 00982 00983 } 00984 00985 00986 00987 template <typename ActualView> 00988 MultipleViewGenericModel<ActualView>::MultipleViewGenericModel() 00989 { 00990 00991 } 00992 00993 00994 00995 template <typename ActualView> 00996 MultipleViewGenericModel<ActualView>::~MultipleViewGenericModel() 00997 throw() 00998 { 00999 01000 deleteViews() ; 01001 01002 } 01003 01004 01005 01006 template <typename ActualView> 01007 void MultipleViewGenericModel<ActualView>::setViews( 01008 const std::list<const ActualView *> & views ) 01009 { 01010 01011 if ( ! this->_views.empty() ) 01012 throw GenericMVCException( 01013 "MultipleViewGenericModel<ActualView>::setViews failed: " 01014 "there was at least one view registered." ) ; 01015 01016 this->_views = views ; 01017 01018 } 01019 01020 01021 01022 template <typename ActualView> 01023 void MultipleViewGenericModel<ActualView>::addView( 01024 const ActualView & view ) const 01025 { 01026 01027 this->_views.push_back( & view ) ; 01028 01029 } 01030 01031 01032 01033 template <typename ActualView> 01034 const std::string MultipleViewGenericModel<ActualView>::toString( 01035 Ceylan::VerbosityLevels level ) const 01036 { 01037 01038 if ( this->_views.empty() ) 01039 return "Multiple-view controller-less generic model " 01040 "not associated to any view" ; 01041 01042 /* 01043 * Beware to infinite recursion: 01044 * (the view may display in turn this model) 01045 * 01046 */ 01047 01048 if ( level == Ceylan::low ) 01049 return "Multiple-view controller-less generic model " 01050 "owning " + Ceylan::toString( _views.size() ) + " view(s)" ; 01051 01052 01053 std::list<std::string> res ; 01054 01055 for ( typename std::list<const ActualView *>::const_iterator it = 01056 this->_views.begin(); it != this->_views.end() ; it++ ) 01057 { 01058 01059 res.push_back( (*it)->toString( level ) ) ; 01060 01061 } 01062 01063 return "Multiple-view controller-less generic model " 01064 "associated to following view(s): " 01065 + Ceylan::formatStringList( res ) ; 01066 01067 } 01068 01069 01070 01071 template <typename ActualView> 01072 void MultipleViewGenericModel<ActualView>::deleteViews() 01073 { 01074 01075 for ( typename std::list<const ActualView *>::const_iterator it = 01076 this->_views.begin(); it != this->_views.end(); it++ ) 01077 { 01078 01079 delete *it ; 01080 01081 } 01082 01083 this->_views.clear() ; 01084 01085 } 01086 01087 01088 01089 01090 01091 /* 01092 * MultipleViewModel non-templated class. 01093 * 01094 * Simpler than the MultipleViewGenericModel view-templated 01095 * counterpart, but deals with BaseView instances instead of an actual 01096 * view child class. 01097 * 01098 * Once the actual relationships between a model and its views 01099 * are taken into account, using a non-templated model should not be 01100 * a problem in general. 01101 * 01102 */ 01103 01104 01105 01114 class CEYLAN_DLL MultipleViewModel : public BaseModel 01115 { 01116 01117 01118 public: 01119 01120 01121 01132 explicit MultipleViewModel( const BaseView & view ) ; 01133 01134 01135 01146 explicit MultipleViewModel( 01147 const std::list<const BaseView *> & views ) ; 01148 01149 01150 01161 MultipleViewModel() ; 01162 01163 01164 01171 virtual ~MultipleViewModel() throw() ; 01172 01173 01174 01185 virtual void setViews( 01186 const std::list<const BaseView *> & views ) ; 01187 01188 01189 01204 virtual void addView( const BaseView & view ) 01205 const ; 01206 01207 01208 01220 virtual const std::string toString( 01221 Ceylan::VerbosityLevels level = Ceylan::high ) const ; 01222 01223 01224 01225 protected: 01226 01227 01229 virtual void deleteViews() ; 01230 01231 /* 01232 * Takes care of the awful issue of Windows DLL with templates. 01233 * 01234 * @see Ceylan's developer guide and README-build-for-windows.txt 01235 * to understand it, and to be aware of the associated risks. 01236 * 01237 */ 01238 #pragma warning( push ) 01239 #pragma warning( disable : 4251 ) 01240 01242 std::list<const BaseView *> _views ; 01243 01244 #pragma warning( pop ) 01245 01246 01247 private: 01248 01249 01257 MultipleViewModel( const MultipleViewModel & source ) ; 01258 01259 01267 MultipleViewModel & operator = ( 01268 const MultipleViewModel & source ) ; 01269 01270 01271 } ; 01272 01273 01274 01275 01276 01277 01278 01279 // SingleControllerNoViewGenericModel templated class. 01280 01281 01282 01295 template <typename ActualController> 01296 class SingleControllerNoViewGenericModel : public BaseModel 01297 { 01298 01299 01300 public: 01301 01302 01303 01317 explicit SingleControllerNoViewGenericModel( 01318 const ActualController & controller ) ; 01319 01320 01321 01332 SingleControllerNoViewGenericModel() ; 01333 01334 01335 01340 virtual ~SingleControllerNoViewGenericModel() throw() ; 01341 01342 01343 01355 virtual const std::string toString( 01356 Ceylan::VerbosityLevels level = Ceylan::high ) const ; 01357 01358 01359 01360 protected: 01361 01362 01371 const ActualController * _controller ; 01372 01373 01374 01375 private: 01376 01377 01385 SingleControllerNoViewGenericModel( 01386 const SingleControllerNoViewGenericModel & source ) ; 01387 01388 01396 SingleControllerNoViewGenericModel & operator = ( 01397 const SingleControllerNoViewGenericModel & source ) ; 01398 01399 01400 } ; 01401 01402 01403 01404 /* 01405 * Implementation of the SingleControllerNoViewGenericModel templated 01406 * class. 01407 * 01408 */ 01409 01410 01411 template <typename ActualController> 01412 SingleControllerNoViewGenericModel<ActualController>::SingleControllerNoViewGenericModel( const ActualController & controller ) : 01413 _controller( & controller ) 01414 { 01415 01416 } 01417 01418 01419 01420 template <typename ActualController> 01421 SingleControllerNoViewGenericModel<ActualController>::SingleControllerNoViewGenericModel() : 01422 _controller( 0 ) 01423 { 01424 01425 } 01426 01427 01428 01429 template <typename ActualController> 01430 SingleControllerNoViewGenericModel<ActualController>::~SingleControllerNoViewGenericModel() throw() 01431 { 01432 01433 if ( this->controller != 0 ) 01434 { 01435 01436 // Controller owned here: 01437 delete this->_controller ; 01438 01439 } 01440 01441 } 01442 01443 01444 01445 template <typename ActualController> 01446 const std::string 01447 SingleControllerNoViewGenericModel<ActualController>::toString( 01448 Ceylan::VerbosityLevels level ) const 01449 { 01450 01451 if ( this->_controller != 0 ) 01452 { 01453 01454 /* 01455 * Beware to infinite recursion: 01456 * (the controller may display in turn this model) 01457 * 01458 */ 01459 01460 if ( level == Ceylan::low ) 01461 return "Single-controller view-less generic model " 01462 "owning a controller" ; 01463 else 01464 return "Single-controller view-less generic model " 01465 "associated to " 01466 + this->_controller->toString( level ) ; 01467 01468 } 01469 else 01470 return "Single-controller view-less generic model " 01471 "not associated to any controller" ; 01472 01473 } 01474 01475 01476 01477 01478 // SingleControllerSingleViewGenericModel templated class. 01479 01480 01481 01495 template <typename ActualController> 01496 class SingleControllerSingleViewGenericModel : public BaseModel 01497 { 01498 01499 01500 public: 01501 01502 01503 01517 explicit SingleControllerSingleViewGenericModel( 01518 const ActualController & controller ) ; 01519 01520 01521 01532 SingleControllerSingleViewGenericModel() ; 01533 01534 01535 01540 virtual ~SingleControllerSingleViewGenericModel() throw() ; 01541 01542 01543 01558 virtual void setView( const BaseView & view ) ; 01559 01560 01561 01580 virtual void addView( const BaseView & view ) const ; 01581 01582 01583 01590 virtual void removeView() ; 01591 01592 01593 01604 virtual void setController( 01605 const ActualController & controller ) ; 01606 01607 01608 01620 virtual const std::string toString( 01621 Ceylan::VerbosityLevels level = Ceylan::high ) const ; 01622 01623 01624 01625 01626 protected: 01627 01628 01637 const BaseView * _view ; 01638 01639 01648 const ActualController * _controller ; 01649 01650 01651 01652 private: 01653 01654 01662 SingleControllerSingleViewGenericModel( 01663 const SingleControllerSingleViewGenericModel & source ) ; 01664 01665 01673 SingleControllerSingleViewGenericModel & operator = ( 01674 const SingleControllerSingleViewGenericModel & source ) ; 01675 01676 01677 } ; 01678 01679 01680 01681 /* 01682 * Implementation of the SingleControllerSingleViewGenericModel 01683 * templated class. 01684 * 01685 */ 01686 01687 01688 template <typename ActualController> 01689 SingleControllerSingleViewGenericModel<ActualController>::SingleControllerSingleViewGenericModel( const ActualController & controller ) : 01690 _view( 0 ), 01691 _controller( & controller ) 01692 { 01693 01694 } 01695 01696 01697 01698 template <typename ActualController> 01699 SingleControllerSingleViewGenericModel<ActualController>::SingleControllerSingleViewGenericModel() : 01700 _view( 0 ), 01701 _controller( 0 ) 01702 { 01703 01704 } 01705 01706 01707 01708 template <typename ActualController> 01709 SingleControllerSingleViewGenericModel<ActualController>::~SingleControllerSingleViewGenericModel() throw() 01710 { 01711 01712 if ( this->_view != 0 ) 01713 { 01714 01715 // View owned here: 01716 delete this->_view ; 01717 01718 } 01719 01720 01721 if ( _controller != 0 ) 01722 { 01723 01724 // Controller owned here: 01725 delete this->_controller ; 01726 01727 } 01728 01729 } 01730 01731 01732 01733 template <typename ActualController> 01734 void SingleControllerSingleViewGenericModel<ActualController>::setView( 01735 const BaseView & view ) 01736 { 01737 01738 addView( view ) ; 01739 01740 } 01741 01742 01743 01744 template <typename ActualController> 01745 void SingleControllerSingleViewGenericModel<ActualController>::addView( 01746 const BaseView & view ) const 01747 { 01748 01749 if ( this->_view != 0 ) 01750 throw GenericMVCException( 01751 "SingleControllerSingleViewGenericModel<ActualController>::" 01752 "addView failed: a view was already registered." ) ; 01753 01754 // Do as if this instance had not to be 'const': 01755 const_cast< 01756 SingleControllerSingleViewGenericModel<ActualController> *>( 01757 this )->_view = & view ; 01758 01759 } 01760 01761 01762 template <typename ActualController> 01763 void SingleControllerSingleViewGenericModel<ActualController>::removeView() 01764 { 01765 01766 if ( this->_view == 0 ) 01767 throw GenericMVCException( 01768 "SingleControllerSingleViewGenericModel<ActualController>::" 01769 "removeView failed: no view was currently registered." ) ; 01770 01771 delete this->_view ; 01772 01773 this->_view = 0 ; 01774 01775 } 01776 01777 01778 template <typename ActualController> 01779 void 01780 SingleControllerSingleViewGenericModel<ActualController>::setController( 01781 const ActualController & controller ) 01782 { 01783 01784 if ( _controller != 0 ) 01785 throw GenericMVCException( 01786 "SingleControllerSingleViewGenericModel<ActualController>::" 01787 "setController failed: a controller was already registered." 01788 ) ; 01789 01790 this->_controller = & controller ; 01791 01792 } 01793 01794 01795 01796 template <typename ActualController> 01797 const std::string 01798 SingleControllerSingleViewGenericModel<ActualController>::toString( 01799 Ceylan::VerbosityLevels level ) const 01800 { 01801 01802 std::string res ; 01803 01804 if ( this->_view != 0 ) 01805 { 01806 01807 /* 01808 * Beware to infinite recursion: 01809 * (the view may display in turn this model) 01810 * 01811 */ 01812 01813 if ( level == Ceylan::low ) 01814 res = "Single-controller single-view generic model " 01815 "owning a view" ; 01816 else 01817 res = "Single-controller single-view generic model " 01818 "associated to view " + this->_view->toString( level ) ; 01819 01820 } 01821 else 01822 res = "Single-controller single-view generic model " 01823 "not associated to any view" ; 01824 01825 01826 if ( this->_controller != 0 ) 01827 { 01828 01829 /* 01830 * Beware to infinite recursion: 01831 * (the controller may display in turn this model) 01832 * 01833 */ 01834 01835 if ( level == Ceylan::low ) 01836 return res + ", owning a controller" ; 01837 else 01838 return res + ", associated to " 01839 + this->_controller->toString( level ) ; 01840 01841 } 01842 else 01843 return res + ", not associated to any controller" ; 01844 01845 } 01846 01847 01848 01849 } // MVC namespace 01850 01851 01852 } // Ceylan namespace 01853 01854 01855 01856 #endif // CEYLAN_GENERIC_MODEL_H_ 01857