Writing: finished (hopefully) part about quick convergency.
[fic.git] / modules.h
blobe844f172dfe9114bbe15154ba9174e94335d16f0
1 #ifndef MODULES_HEADER_
2 #define MODULES_HEADER_
4 #include "util.h"
6 // Forwards for all classes visible outside this header
7 class Module;
8 class ModuleFactory;
9 template <class Iface> class Interface;
12 /** A common base class for all modules */
13 class Module {
14 friend class ModuleFactory; ///< Permission for the ModuleFactory to manipulate Modules
16 // Type definitions
17 public:
18 /** Two types of cloning, used in #clone */
19 enum CloneMethod { ShallowCopy, DeepCopy };
20 /** Types of a setting */
21 enum ChoiceType {
22 Stop, ///< a list-terminator
23 Int, ///< integer from an interval
24 IntLog2, ///< integer from an interval prefixed with 2^
25 Float, ///< real number from an interval
26 ModuleCombo,///< a connection to another module (shown as a combo-box)
27 Combo /// choice from a list of strings
29 /** Represents one setting - one number, real or integer */
30 union SettingValue {
31 int i; ///< Setting value for integer/module types (see Module::ChoiceType)
32 float f; ///< Setting value for real-number type (see Module::ChoiceType)
34 /** Represent the type of one module's setting - without label and description */
35 struct SettingsType {
36 ChoiceType type; ///< The type of the item
37 SettingValue defaults; ///< The default setting
39 union {
40 int i[2]; ///< Lower and upper bound (type==Int,IntLog2)
41 float f[2]; ///< Lower and upper bound (type==Float)
42 const char *text; ///< Lines of the combo-box (type==Combo)
43 /** Pointer to the vector of IDs of compatible modules (type==ModuleCombo),
44 * meant to be one of Interface::getCompMods() */
45 const std::vector<int> *compatIDs;
46 } data; ///< Additional data, differs for different #type
49 /** Represents the type of one setting - including label, description, etc.\ */
50 struct SettingsTypeItem {
51 static const SettingsTypeItem stopper; ///< Predefined list terminator
53 const char *label /// The text label of the setting
54 , *desc; ///< Description text
55 SettingsType type; ///< The type of this setting
58 /** Represents one setting value in a module */
59 struct SettingsItem {
60 Module *m; ///< Pointer to the connected module (if type is Module::ModuleCombo)
61 SettingValue val; ///< The setting value
63 /** Just nulls the module pointer */
64 SettingsItem(): m(0) { DEBUG_ONLY( val.f= std::numeric_limits<float>::quiet_NaN(); ) }
66 /** Creates a default settings-item for a settings-item-type */
67 SettingsItem(const SettingsTypeItem &typeItem): m(0), val(typeItem.type.defaults) {}
69 /** Just deletes the module pointer */
70 ~SettingsItem() { delete m; }
73 /** Information about one module-type */
74 struct TypeInfo {
75 int id; ///< The module-type's ID
76 const char *name /// The module-type's name
77 , *desc; ///< The module-type's description
78 int setLength; ///< The number of setting items
79 const SettingsTypeItem *setType; ///< The types of module's settings
82 // Data definitions
83 protected:
84 SettingsItem *settings; ///< The current setting values of this Module
86 /** \name Construction, destruction and related methods
87 * @{ - all private, only to be used by ModuleFactory */
88 private:
89 /** Creates a copy of module's settings (includes the whole module subtree) */
90 SettingsItem* copySettings(CloneMethod method) const;
91 /** Called for prototypes to initialize the default links to other modules */
92 void initDefaultModuleLinks();
93 /** Called for prototypes to null links to other modules */
94 void nullModuleLinks();
95 /** Called for prototypes to create the settings and inicialize them with defaults */
96 void createDefaultSettings();
98 /** Denial of assigment */
99 Module& operator=(const Module&);
100 /** Denial of copying */
101 Module(const Module&);
102 protected:
103 /** Initializes an empty module */
104 Module(): settings(0) {}
106 /** Cloning method, implemented in all modules via macros \return a new module
107 * \param method determines creation of a deep or a shallow copy (zeroed children) */
108 virtual Module* abstractClone(CloneMethod method) const =0;
109 /** Concrete cloning method - templated by the actual type of the module */
110 template<class M> M* concreteClone(CloneMethod method) const;
112 /** Saves all the settings, icluding child modules */
113 void saveAllSettings(std::ostream &stream);
114 void loadAllSettings(std::istream &stream);
115 public:
116 /** Friend non-member cloning function (returns the type it gets) */
117 template<class M> friend M* clone( const M *module, CloneMethod method=Module::DeepCopy )
118 { return debugCast<M*>( module->abstractClone(method) ); }
120 /** Deletes the settings, destroying child modules as well */
121 virtual ~Module()
122 { delete[] settings; }
124 virtual const TypeInfo& info() const =0;
126 #ifndef NDEBUG
127 DECLARE_debugModule { return 0; }
128 #endif
129 /// @}
132 /** \name Settings visualization and related methods
133 * @{ - all implemented in gui.cpp */
134 public:
135 /** Creates or updates settings-box and/or settings-tree,
136 * if overridden in derived modules, it is recommended to call this one at first */
137 virtual void adjustSettings( int which, QTreeWidgetItem *myTree, QGroupBox *setBox );
138 protected:
139 /** Reads a setting value from a widget */
140 void widget2settings( const QWidget *widget, int which );
141 /** Writes a setting value into a widget */
142 void settings2widget( QWidget *widget, int which );
143 /** Initializes a widget according to a setting-item type */
144 void settingsType2widget( QWidget *widget, const SettingsTypeItem &typeItem );
145 /// @}
147 // Other methods
148 protected:
149 /** Puts a module-identifier in a stream (which = the index in settings) */
150 void file_saveModuleType( std::ostream &os, int which );
151 /** Gets an module-identifier from the stream, initializes the pointer in settings
152 * with a new empty instance and does some checking (bounds,Iface) */
153 void file_loadModuleType( std::istream &is, int which );
154 /** A shortcut method for working with integer settings */
155 int& settingsInt(int index)
156 { return settings[index].val.i; }
157 int settingsInt(int index) const
158 { return settings[index].val.i; }
161 static SettingsType settingInt(int min,int defaults,int max,ChoiceType type=Int) {
162 assert( type==Int || type==IntLog2 );
163 SettingsType result;
164 result.type= type;
165 result.defaults.i= defaults;
166 result.data.i[0]= min;
167 result.data.i[1]= max;
168 return result;
170 static SettingsType settingFloat(float min,float defaults,float max) {
171 SettingsType result;
172 result.type= Float;
173 result.defaults.f= defaults;
174 result.data.f[0]= min;
175 result.data.f[1]= max;
176 return result;
178 static SettingsType settingCombo(const char *text,int defaults) {
179 assert( defaults>=0 && defaults<1+countEOLs(text) );
180 SettingsType result;
181 result.type= Combo;
182 result.defaults.i= defaults;
183 result.data.text= text;
184 return result;
186 template<class Iface> static SettingsType settingModule(int index=0) {
187 const std::vector<int> &compMods= Iface::getCompMods();
188 assert( index < (int)compMods.size() );
189 SettingsType result;
190 result.type= ModuleCombo;
191 result.defaults.i= index;
192 result.data.compatIDs= &compMods;
193 return result;
195 }; // Module class
198 #define DECLARE_TypeInfo_helper(CNAME_,NAME_,DESC_,SETTYPE_...) \
199 friend class Module; \
200 friend class ModuleFactory; \
201 friend struct ModuleFactory::Creator<CNAME_>; /* Needed for GCC-3 */ \
202 public: \
203 CNAME_* abstractClone(CloneMethod method=DeepCopy) const \
204 { return concreteClone<CNAME_>(method); } \
206 const TypeInfo& info() const { \
207 static SettingsTypeItem setType_[]= {SETTYPE_}; \
208 static TypeInfo info_= { \
209 id: ModuleFactory::getModuleID<CNAME_>(), \
210 name: NAME_, \
211 desc: DESC_, \
212 setLength: sizeof(setType_)/sizeof(*setType_)-1, \
213 setType: setType_ \
214 }; \
215 return info_; \
218 /** Macros for easier Module-writing */
219 #define DECLARE_TypeInfo(CNAME_,NAME_,DESC_,SETTYPE_...) \
220 DECLARE_TypeInfo_helper(CNAME_,NAME_,DESC_,SETTYPE_,SettingsTypeItem::stopper)
222 #define DECLARE_TypeInfo_noSettings(CNAME_,NAME_,DESC_) \
223 DECLARE_TypeInfo_helper(CNAME_,NAME_,DESC_,SettingsTypeItem::stopper)
226 /** A singleton factory class for creating modules */
227 class ModuleFactory {
228 /** Static pointer to the only instance of the ModuleFactory */
229 static ModuleFactory *instance;
231 /** Pointers to the prototypes for every module type (indexed by their ID's) */
232 std::vector<Module*> prototypes;
234 /** Private constructor to avoid uncontrolled instantiation */
235 ModuleFactory() {}
236 /** Deletes the prototypes */
237 ~ModuleFactory() {
238 for_each( prototypes.begin(), prototypes.end(), std::mem_fun(&Module::nullModuleLinks) );
239 for_each( prototypes.begin(), prototypes.end(), SingleDeleter<Module>() );
241 /** The real constructing routine */
242 void initialize();
244 public:
245 /** Returns the ID of a module-type */
246 template<class M> static int getModuleID();
248 /** Method to instantiate the singleton */
249 static void init()
250 { assert(!instance); (instance=new ModuleFactory)->initialize(); }
251 /** Method to delete the singleton */
252 static void destroy()
253 { delete instance; instance=0; }
255 /** Returns a reference to the prototype of the module with given id */
256 static const Module& prototype(int id) {
257 assert( instance && instance->prototypes.at(id) );
258 return *instance->prototypes[id];
260 /** Returns the name of the module-type with given id */
261 static const char* moduleName(int id)
262 { return prototype(id).info().name; }
263 /** Returns the description of the module-type with given id */
264 static const char* moduleDescription(int id)
265 { return prototype(id).info().desc; }
266 /** Returns a new instance of the module-type with given id */
267 static Module* newModule( int id, Module::CloneMethod method=Module::DeepCopy )
268 { return prototype(id).abstractClone(method); }
270 /** Sets appropriate prototype settings according to given module's settings */
271 static void changeDefaultSettings(const Module &module);
273 private:
274 // some helper stuff
275 template<class T> struct Creator {
276 T* operator()() const
277 { return new T; }
279 template<class T> struct Instantiator {
280 int operator()() const;
282 /** Never called, only exists for certain templates to be instantiated in modules.cpp */
283 static void instantiateModules();
286 /** A base class for all interfaces, parametrized by the interface's type */
287 template<class Iface> class Interface: public Module {
288 static std::vector<int> compMods_; ///< IDs of modules derived from this interface
289 public:
290 /** Returns a reference to #compMods_ (initializes it if empty) */
291 static const std::vector<int>& getCompMods();
292 /** Returns a reference to the index-th prototype implementing this interface */
293 static const Iface& compatiblePrototype(int index=0) {
294 assert( index>=0 && index<(int)getCompMods().size() );
295 return *debugCast<const Iface*>(&ModuleFactory::prototype( getCompMods()[index] ));
297 /** Creates a new instance of the index-th compatible module */
298 static Iface* newCompatibleModule(int index=0)
299 { return clone( &compatiblePrototype(index) ); }
302 #endif // MODULES_HEADER_