root/bdm/uibuilder.h @ 260

Revision 260, 4.6 kB (checked in by smidl, 15 years ago)

working UI example

Line 
1#ifndef UIBUILD
2#define UIBUILD
3
4#include <itpp/itbase.h>
5#include "stat/libBM.h"
6#include "libconfig/libconfig.h++"
7
8namespace bdm {
9
10        using namespace libconfig;
11        using namespace std;
12
13#define CHECK_UITYPE(S,Type) it_assert_debug(S.getType()==Setting::Type, string("Wrong input path \"")+string(S.getPath())+string("\""));
14#define UIREGISTER(UI) UI* UI##_global_instance = new UI();
15
16////////// GLOBAL VAriables
17
18        class UIbuilder;
19//! Internal structure mapping strings to UIBuilder objects
20        typedef map<const string, const UIbuilder*> UImap;
21        extern UImap __uimap__;
22
23        class UIFile : public Config {
24        public:
25                UIFile ( const char * fname ) :Config() {
26                        try{Config::readFile ( fname );}
27                        catch ( ParseException& P ) {
28                                char msg[200];
29                                sprintf ( msg,"Error in file %s  on line %d.", fname, P.getLine() );
30                                it_error ( msg );
31                        }
32                        catch ( FileIOException f ) {it_error ( "File " + string ( fname ) + " not found" );}
33                }
34        };
35
36        /*!\brief Builds computational object from a UserInfo structure
37
38        Return value is a pointer to the created object (memory management issue?)
39        */
40        class UIbuilder {
41        protected:
42                const vec getvec ( Setting& S ) const {
43                        CHECK_UITYPE ( S,TypeArray );
44                        vec tmp;
45                        tmp.set_size ( S.getLength() );
46                        for ( int i=0;i<S.getLength();i++ ) {
47                                switch ( S[i].getType() ) {
48                                        case Setting::TypeFloat :
49                                                tmp[i]=double ( S[i] );break;
50                                        case Setting::TypeInt :
51                                                tmp[i]=int ( S[i] );break;
52                                        case Setting::TypeBoolean :
53                                                tmp[i]=bool ( S[i] );break;
54                                        default: it_error ( "libconfig error?" );
55                                }
56                        }
57                        return tmp;
58                };
59                const vec getivec ( Setting& S ) const {
60                        CHECK_UITYPE ( S,TypeArray );
61                        vec tmp;
62                        tmp.set_size ( S.getLength() );
63                        for ( int i=0;i<S.getLength();i++ ) {
64                                switch ( S[i].getType() ) {
65                                        case Setting::TypeFloat :
66                                                tmp[i]=double ( S[i] );break;
67                                        case Setting::TypeInt :
68                                                tmp[i]=int ( S[i] );break;
69                                        case Setting::TypeBoolean :
70                                                tmp[i]=bool ( S[i] );break;
71                                        default: it_error ( "libconfig error?" );
72                                }
73                        }
74                        return tmp;
75                };
76        public:
77                //!Constructor needs to be run only once macro UIREGISTER
78                UIbuilder ( const string &typ ) {__uimap__.insert ( make_pair ( typ,this ) );}
79                //! Function building the computational object
80                virtual bdmroot* build ( Setting &S ) const =0;
81        };
82
83        class UIexternal:public UIbuilder {
84        public:
85                UIexternal() :UIbuilder ( "external" ) {}
86                bdmroot* build ( Setting &S ) const;
87        };
88
89        class UIinternal:public UIbuilder {
90        public:
91                UIinternal() :UIbuilder ( "internal" ) {}
92                bdmroot* build ( Setting &S ) const;
93        };
94
95        //! [Debugging] Print values in current S to cout
96        void UI_DBG ( Setting &S, const string &spc );
97
98//! Prototype of a UI builder. Return value is by the second argument since it type checking via \c dynamic_cast.
99        template<class T>
100        void UIbuild ( Setting &S, T* &ret ) {
101                CHECK_UITYPE ( S,TypeGroup );
102                // Check if field "type" is present, if not it is not a valid UI
103                it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
104
105                const string typ=S["type"];
106                // Find "type" in list of registred UI builders
107                UImap::const_iterator iter = __uimap__.find ( typ );
108                if ( iter == __uimap__.end() ) {
109                        it_error ( "UI of type \"" + typ + "\" is not registered!" );
110                }
111
112                //BUILD the result
113                try {
114                        ret = dynamic_cast<T*> ( iter->second->build ( S ) );
115                }
116                catch ( SettingTypeException e ) {
117                        UI_DBG(S,""); 
118                        it_error ( "Setting " +string ( e.getPath() ) +" is of incorrect Type" );}
119                catch ( SettingNotFoundException e ) {
120                        UI_DBG(S,"");
121                        it_error ( "Setting " + string ( e.getPath() ) +" was not found" );}
122        };
123
124//! Auxiliary function allowing recursivity in S (too complex, remove?)
125        template<class T>
126        void UIcall ( Setting &S, void ( *func ) ( Setting&, T ), T Tmp ) {
127                CHECK_UITYPE ( S,TypeGroup );
128                // Check if field "type" is present, if not it is not a valid UI
129                it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
130
131                const string typ=S["type"];
132                if ( typ=="internal" ) {
133                        try {
134                                Setting* Stmp = &S;
135                                do {Stmp=& ( Stmp->getParent() );}
136                                while ( !Stmp->isRoot() );
137                                Setting& intS=Stmp->lookup ( ( const char* ) S["path"] );
138                                func ( intS, Tmp ); // <======== calling func
139                                return;
140                        }
141                        catch ( ... ) {
142                                it_error ( "Internal field " + string ( S.getPath() ) + " not valid" );
143                        }
144                }
145                if ( typ=="external" ) {
146                        UIFile C(S["filename"]);
147                        try {
148                                func ( C.lookup ( ( const char* ) S["path"] ), Tmp );
149                        }
150                        catch ( ... ) {
151                                it_error ( "External field " + string ( S.getPath() ) + " not valid" );
152                        }
153                        return;
154                }
155
156                // v======================= calling final func
157                func ( S, Tmp );
158        };
159
160}
161#endif //UIBUILD
Note: See TracBrowser for help on using the browser.