]> git.mxchange.org Git - flightgear.git/blob - src/Main/fg_props.hxx
Fixes for default chase view values.
[flightgear.git] / src / Main / fg_props.hxx
1 // fg_props.hxx - Declarations and inline methods for property handling.
2 // Written by David Megginson, started 2000.
3 //
4 // This file is in the Public Domain, and comes with no warranty.
5
6 #ifndef __FG_PROPS_HXX
7 #define __FG_PROPS_HXX 1
8
9 #include <simgear/debug/logstream.hxx>
10 #include <simgear/misc/props.hxx>
11 #include "globals.hxx"
12
13 \f
14 ////////////////////////////////////////////////////////////////////////
15 // Property management.
16 ////////////////////////////////////////////////////////////////////////
17
18
19 /**
20  * Initialize the default FlightGear properties.
21  *
22  * These are mostly properties that haven't been claimed by a
23  * specific module yet.  This function should be invoked once,
24  * while the program is starting (and after the global property
25  * tree has been created).
26  */
27 extern void fgInitProps ();     // fixme: how are they untied?
28
29
30 /**
31  * Update the default FlightGear properties.
32  *
33  * This function should be invoked once in each loop to update all
34  * of the default properties.
35  */
36 extern void fgUpdateProps ();
37
38
39 /**
40  * Save a flight to disk.
41  *
42  * This function saves all of the archivable properties to a stream
43  * so that the current flight can be restored later.
44  *
45  * @param output The output stream to write the XML save file to.
46  * @return true if the flight was saved successfully.
47  */
48 extern bool fgSaveFlight (ostream &output);
49
50
51 /**
52  * Load a flight from disk.
53  *
54  * This function loads an XML save file from a stream to restore
55  * a flight.
56  *
57  * @param input The input stream to read the XML from.
58  * @return true if the flight was restored successfully.
59  */
60 extern bool fgLoadFlight (istream &input);
61
62
63 \f
64 ////////////////////////////////////////////////////////////////////////
65 // Convenience functions for getting property values.
66 ////////////////////////////////////////////////////////////////////////
67
68
69 /**
70  * Get a property node.
71  *
72  * @param path The path of the node, relative to root.
73  * @param create true to create the node if it doesn't exist.
74  * @return The node, or 0 if none exists and none was created.
75  */
76 inline SGPropertyNode * 
77 fgGetNode (const string &path, bool create = false)
78 {
79   return globals->get_props()->getNode(path, create);
80 }
81
82
83 /**
84  * Get a property node with separate index.
85  *
86  * This method separates the index from the path string, to make it
87  * easier to iterate through multiple components without using sprintf
88  * to add indices.  For example, fgGetNode("foo[1]/bar", 3) will
89  * return the same result as fgGetNode("foo[1]/bar[3]").
90  *
91  * @param path The path of the node, relative to root.
92  * @param index The index for the last member of the path (overrides
93  * any given in the string).
94  * @param create true to create the node if it doesn't exist.
95  * @return The node, or 0 if none exists and none was created.
96  */
97 inline SGPropertyNode * 
98 fgGetNode (const string &path, int index, bool create = false)
99 {
100   return globals->get_props()->getNode(path, index, create);
101 }
102
103
104 /**
105  * Test whether a given node exists.
106  *
107  * @param path The path of the node, relative to root.
108  * @return true if the node exists, false otherwise.
109  */
110 inline bool
111 fgHasNode (const string &path)
112 {
113   return (fgGetNode(path, false) != 0);
114 }
115
116
117 /**
118  * Get a bool value for a property.
119  *
120  * This method is convenient but inefficient.  It should be used
121  * infrequently (i.e. for initializing, loading, saving, etc.),
122  * not in the main loop.  If you need to get a value frequently,
123  * it is better to look up the node itself using fgGetNode and then
124  * use the node's getBoolValue() method, to avoid the lookup overhead.
125  *
126  * @param name The property name.
127  * @param defaultValue The default value to return if the property
128  *        does not exist.
129  * @return The property's value as a bool, or the default value provided.
130  */
131 inline bool fgGetBool (const string &name, bool defaultValue = false)
132 {
133   return globals->get_props()->getBoolValue(name, defaultValue);
134 }
135
136
137 /**
138  * Get an int value for a property.
139  *
140  * This method is convenient but inefficient.  It should be used
141  * infrequently (i.e. for initializing, loading, saving, etc.),
142  * not in the main loop.  If you need to get a value frequently,
143  * it is better to look up the node itself using fgGetNode and then
144  * use the node's getIntValue() method, to avoid the lookup overhead.
145  *
146  * @param name The property name.
147  * @param defaultValue The default value to return if the property
148  *        does not exist.
149  * @return The property's value as an int, or the default value provided.
150  */
151 inline int fgGetInt (const string &name, int defaultValue = 0)
152 {
153   return globals->get_props()->getIntValue(name, defaultValue);
154 }
155
156
157 /**
158  * Get a long value for a property.
159  *
160  * This method is convenient but inefficient.  It should be used
161  * infrequently (i.e. for initializing, loading, saving, etc.),
162  * not in the main loop.  If you need to get a value frequently,
163  * it is better to look up the node itself using fgGetNode and then
164  * use the node's getLongValue() method, to avoid the lookup overhead.
165  *
166  * @param name The property name.
167  * @param defaultValue The default value to return if the property
168  *        does not exist.
169  * @return The property's value as a long, or the default value provided.
170  */
171 inline int fgGetLong (const string &name, long defaultValue = 0L)
172 {
173   return globals->get_props()->getLongValue(name, defaultValue);
174 }
175
176
177 /**
178  * Get a float value for a property.
179  *
180  * This method is convenient but inefficient.  It should be used
181  * infrequently (i.e. for initializing, loading, saving, etc.),
182  * not in the main loop.  If you need to get a value frequently,
183  * it is better to look up the node itself using fgGetNode and then
184  * use the node's getFloatValue() method, to avoid the lookup overhead.
185  *
186  * @param name The property name.
187  * @param defaultValue The default value to return if the property
188  *        does not exist.
189  * @return The property's value as a float, or the default value provided.
190  */
191 inline float fgGetFloat (const string &name, float defaultValue = 0.0)
192 {
193   return globals->get_props()->getFloatValue(name, defaultValue);
194 }
195
196
197 /**
198  * Get a double value for a property.
199  *
200  * This method is convenient but inefficient.  It should be used
201  * infrequently (i.e. for initializing, loading, saving, etc.),
202  * not in the main loop.  If you need to get a value frequently,
203  * it is better to look up the node itself using fgGetNode and then
204  * use the node's getDoubleValue() method, to avoid the lookup overhead.
205  *
206  * @param name The property name.
207  * @param defaultValue The default value to return if the property
208  *        does not exist.
209  * @return The property's value as a double, or the default value provided.
210  */
211 inline double fgGetDouble (const string &name, double defaultValue = 0.0)
212 {
213   return globals->get_props()->getDoubleValue(name, defaultValue);
214 }
215
216
217 /**
218  * Get a string value for a property.
219  *
220  * This method is convenient but inefficient.  It should be used
221  * infrequently (i.e. for initializing, loading, saving, etc.),
222  * not in the main loop.  If you need to get a value frequently,
223  * it is better to look up the node itself using fgGetNode and then
224  * use the node's getStringValue() method, to avoid the lookup overhead.
225  *
226  * @param name The property name.
227  * @param defaultValue The default value to return if the property
228  *        does not exist.
229  * @return The property's value as a string, or the default value provided.
230  */
231 inline string fgGetString (const string &name, string defaultValue = "")
232 {
233   return globals->get_props()->getStringValue(name, defaultValue);
234 }
235
236
237 /**
238  * Set a bool value for a property.
239  *
240  * Assign a bool value to a property.  If the property does not
241  * yet exist, it will be created and its type will be set to
242  * BOOL; if it has a type of UNKNOWN, the type will also be set to
243  * BOOL; otherwise, the bool value will be converted to the property's
244  * type.
245  *
246  * @param name The property name.
247  * @param val The new value for the property.
248  * @return true if the assignment succeeded, false otherwise.
249  */
250 inline bool fgSetBool (const string &name, bool val)
251 {
252   return globals->get_props()->setBoolValue(name, val);
253 }
254
255
256 /**
257  * Set an int value for a property.
258  *
259  * Assign an int value to a property.  If the property does not
260  * yet exist, it will be created and its type will be set to
261  * INT; if it has a type of UNKNOWN, the type will also be set to
262  * INT; otherwise, the bool value will be converted to the property's
263  * type.
264  *
265  * @param name The property name.
266  * @param val The new value for the property.
267  * @return true if the assignment succeeded, false otherwise.
268  */
269 inline bool fgSetInt (const string &name, int val)
270 {
271   return globals->get_props()->setIntValue(name, val);
272 }
273
274
275 /**
276  * Set a long value for a property.
277  *
278  * Assign a long value to a property.  If the property does not
279  * yet exist, it will be created and its type will be set to
280  * LONG; if it has a type of UNKNOWN, the type will also be set to
281  * LONG; otherwise, the bool value will be converted to the property's
282  * type.
283  *
284  * @param name The property name.
285  * @param val The new value for the property.
286  * @return true if the assignment succeeded, false otherwise.
287  */
288 inline bool fgSetLong (const string &name, long val)
289 {
290   return globals->get_props()->setLongValue(name, val);
291 }
292
293
294 /**
295  * Set a float value for a property.
296  *
297  * Assign a float value to a property.  If the property does not
298  * yet exist, it will be created and its type will be set to
299  * FLOAT; if it has a type of UNKNOWN, the type will also be set to
300  * FLOAT; otherwise, the bool value will be converted to the property's
301  * type.
302  *
303  * @param name The property name.
304  * @param val The new value for the property.
305  * @return true if the assignment succeeded, false otherwise.
306  */
307 inline bool fgSetFloat (const string &name, float val)
308 {
309   return globals->get_props()->setFloatValue(name, val);
310 }
311
312
313 /**
314  * Set a double value for a property.
315  *
316  * Assign a double value to a property.  If the property does not
317  * yet exist, it will be created and its type will be set to
318  * DOUBLE; if it has a type of UNKNOWN, the type will also be set to
319  * DOUBLE; otherwise, the double value will be converted to the property's
320  * type.
321  *
322  * @param name The property name.
323  * @param val The new value for the property.
324  * @return true if the assignment succeeded, false otherwise.
325  */
326 inline bool fgSetDouble (const string &name, double val)
327 {
328   return globals->get_props()->setDoubleValue(name, val);
329 }
330
331
332 /**
333  * Set a string value for a property.
334  *
335  * Assign a string value to a property.  If the property does not
336  * yet exist, it will be created and its type will be set to
337  * STRING; if it has a type of UNKNOWN, the type will also be set to
338  * STRING; otherwise, the string value will be converted to the property's
339  * type.
340  *
341  * @param name The property name.
342  * @param val The new value for the property.
343  * @return true if the assignment succeeded, false otherwise.
344  */
345 inline bool fgSetString (const string &name, const string &val)
346 {
347   return globals->get_props()->setStringValue(name, val);
348 }
349
350
351 \f
352 ////////////////////////////////////////////////////////////////////////
353 // Convenience functions for setting property attributes.
354 ////////////////////////////////////////////////////////////////////////
355
356
357 /**
358  * Set the state of the archive attribute for a property.
359  *
360  * If the archive attribute is true, the property will be written
361  * when a flight is saved; if it is false, the property will be
362  * skipped.
363  *
364  * A warning message will be printed if the property does not exist.
365  *
366  * @param name The property name.
367  * @param state The state of the archive attribute (defaults to true).
368  */
369 inline void
370 fgSetArchivable (const string &name, bool state = true)
371 {
372   SGPropertyNode * node = globals->get_props()->getNode(name);
373   if (node == 0)
374     SG_LOG(SG_GENERAL, SG_ALERT,
375            "Attempt to set archive flag for non-existant property "
376            << name);
377   else
378     node->setAttribute(SGPropertyNode::ARCHIVE, state);
379 }
380
381
382 /**
383  * Set the state of the read attribute for a property.
384  *
385  * If the read attribute is true, the property value will be readable;
386  * if it is false, the property value will always be the default value
387  * for its type.
388  *
389  * A warning message will be printed if the property does not exist.
390  *
391  * @param name The property name.
392  * @param state The state of the read attribute (defaults to true).
393  */
394 inline void
395 fgSetReadable (const string &name, bool state = true)
396 {
397   SGPropertyNode * node = globals->get_props()->getNode(name);
398   if (node == 0)
399     SG_LOG(SG_GENERAL, SG_ALERT,
400            "Attempt to set read flag for non-existant property "
401            << name);
402   else
403     node->setAttribute(SGPropertyNode::READ, state);
404 }
405
406
407 /**
408  * Set the state of the write attribute for a property.
409  *
410  * If the write attribute is true, the property value may be modified
411  * (depending on how it is tied); if the write attribute is false, the
412  * property value may not be modified.
413  *
414  * A warning message will be printed if the property does not exist.
415  *
416  * @param name The property name.
417  * @param state The state of the write attribute (defaults to true).
418  */
419 inline void
420 fgSetWritable (const string &name, bool state = true)
421 {
422   SGPropertyNode * node = globals->get_props()->getNode(name);
423   if (node == 0)
424     SG_LOG(SG_GENERAL, SG_ALERT,
425            "Attempt to set write flag for non-existant property "
426            << name);
427   else
428     node->setAttribute(SGPropertyNode::WRITE, state);
429 }
430
431
432 \f
433 ////////////////////////////////////////////////////////////////////////
434 // Convenience functions for tying properties, with logging.
435 ////////////////////////////////////////////////////////////////////////
436
437
438 /**
439  * Untie a property from an external data source.
440  *
441  * Classes should use this function to release control of any
442  * properties they are managing.
443  */
444 inline void
445 fgUntie (const string &name)
446 {
447   if (!globals->get_props()->untie(name))
448     SG_LOG(SG_GENERAL, SG_WARN, "Failed to untie property " << name);
449 }
450
451
452                                 // Templates cause ambiguity here
453
454 /**
455  * Tie a property to an external bool variable.
456  *
457  * The property's value will automatically mirror the variable's
458  * value, and vice-versa, until the property is untied.
459  *
460  * @param name The property name to tie (full path).
461  * @param pointer A pointer to the variable.
462  * @param useDefault true if any existing property value should be
463  *        copied to the variable; false if the variable should not
464  *        be modified; defaults to true.
465  */
466 inline void
467 fgTie (const string &name, bool *pointer, bool useDefault = true)
468 {
469   if (!globals->get_props()->tie(name, SGRawValuePointer<bool>(pointer),
470                                  useDefault))
471     SG_LOG(SG_GENERAL, SG_WARN,
472            "Failed to tie property " << name << " to a pointer");
473 }
474
475
476 /**
477  * Tie a property to an external int variable.
478  *
479  * The property's value will automatically mirror the variable's
480  * value, and vice-versa, until the property is untied.
481  *
482  * @param name The property name to tie (full path).
483  * @param pointer A pointer to the variable.
484  * @param useDefault true if any existing property value should be
485  *        copied to the variable; false if the variable should not
486  *        be modified; defaults to true.
487  */
488 inline void
489 fgTie (const string &name, int *pointer, bool useDefault = true)
490 {
491   if (!globals->get_props()->tie(name, SGRawValuePointer<int>(pointer),
492                                  useDefault))
493     SG_LOG(SG_GENERAL, SG_WARN,
494            "Failed to tie property " << name << " to a pointer");
495 }
496
497
498 /**
499  * Tie a property to an external long variable.
500  *
501  * The property's value will automatically mirror the variable's
502  * value, and vice-versa, until the property is untied.
503  *
504  * @param name The property name to tie (full path).
505  * @param pointer A pointer to the variable.
506  * @param useDefault true if any existing property value should be
507  *        copied to the variable; false if the variable should not
508  *        be modified; defaults to true.
509  */
510 inline void
511 fgTie (const string &name, long *pointer, bool useDefault = true)
512 {
513   if (!globals->get_props()->tie(name, SGRawValuePointer<long>(pointer),
514                                  useDefault))
515     SG_LOG(SG_GENERAL, SG_WARN,
516            "Failed to tie property " << name << " to a pointer");
517 }
518
519
520 /**
521  * Tie a property to an external float variable.
522  *
523  * The property's value will automatically mirror the variable's
524  * value, and vice-versa, until the property is untied.
525  *
526  * @param name The property name to tie (full path).
527  * @param pointer A pointer to the variable.
528  * @param useDefault true if any existing property value should be
529  *        copied to the variable; false if the variable should not
530  *        be modified; defaults to true.
531  */
532 inline void
533 fgTie (const string &name, float *pointer, bool useDefault = true)
534 {
535   if (!globals->get_props()->tie(name, SGRawValuePointer<float>(pointer),
536                                  useDefault))
537     SG_LOG(SG_GENERAL, SG_WARN,
538            "Failed to tie property " << name << " to a pointer");
539 }
540
541
542 /**
543  * Tie a property to an external double variable.
544  *
545  * The property's value will automatically mirror the variable's
546  * value, and vice-versa, until the property is untied.
547  *
548  * @param name The property name to tie (full path).
549  * @param pointer A pointer to the variable.
550  * @param useDefault true if any existing property value should be
551  *        copied to the variable; false if the variable should not
552  *        be modified; defaults to true.
553  */
554 inline void
555 fgTie (const string &name, double *pointer, bool useDefault = true)
556 {
557   if (!globals->get_props()->tie(name, SGRawValuePointer<double>(pointer),
558                                  useDefault))
559     SG_LOG(SG_GENERAL, SG_WARN,
560            "Failed to tie property " << name << " to a pointer");
561 }
562
563
564 /**
565  * Tie a property to an external string variable.
566  *
567  * The property's value will automatically mirror the variable's
568  * value, and vice-versa, until the property is untied.
569  *
570  * @param name The property name to tie (full path).
571  * @param pointer A pointer to the variable.
572  * @param useDefault true if any existing property value should be
573  *        copied to the variable; false if the variable should not
574  *        be modified; defaults to true.
575  */
576 inline void
577 fgTie (const string &name, string *pointer, bool useDefault = true)
578 {
579   if (!globals->get_props()->tie(name, SGRawValuePointer<string>(pointer),
580                                  useDefault))
581     SG_LOG(SG_GENERAL, SG_WARN,
582            "Failed to tie property " << name << " to a pointer");
583 }
584
585
586 /**
587  * Tie a property to a pair of simple functions.
588  *
589  * Every time the property value is queried, the getter (if any) will
590  * be invoked; every time the property value is modified, the setter
591  * (if any) will be invoked.  The getter can be 0 to make the property
592  * unreadable, and the setter can be 0 to make the property
593  * unmodifiable.
594  *
595  * @param name The property name to tie (full path).
596  * @param getter The getter function, or 0 if the value is unreadable.
597  * @param setter The setter function, or 0 if the value is unmodifiable.
598  * @param useDefault true if the setter should be invoked with any existing 
599  *        property value should be; false if the old value should be
600  *        discarded; defaults to true.
601  */
602 template <class V>
603 inline void
604 fgTie (const string &name, V (*getter)(), void (*setter)(V) = 0,
605        bool useDefault = true)
606 {
607   if (!globals->get_props()->tie(name, SGRawValueFunctions<V>(getter, setter),
608                                  useDefault))
609     SG_LOG(SG_GENERAL, SG_WARN,
610            "Failed to tie property " << name << " to functions");
611 }
612
613
614 /**
615  * Tie a property to a pair of indexed functions.
616  *
617  * Every time the property value is queried, the getter (if any) will
618  * be invoked with the index provided; every time the property value
619  * is modified, the setter (if any) will be invoked with the index
620  * provided.  The getter can be 0 to make the property unreadable, and
621  * the setter can be 0 to make the property unmodifiable.
622  *
623  * @param name The property name to tie (full path).
624  * @param index The integer argument to pass to the getter and
625  *        setter functions.
626  * @param getter The getter function, or 0 if the value is unreadable.
627  * @param setter The setter function, or 0 if the value is unmodifiable.
628  * @param useDefault true if the setter should be invoked with any existing 
629  *        property value should be; false if the old value should be
630  *        discarded; defaults to true.
631  */
632 template <class V>
633 inline void
634 fgTie (const string &name, int index, V (*getter)(int),
635        void (*setter)(int, V) = 0, bool useDefault = true)
636 {
637   if (!globals->get_props()->tie(name,
638                                  SGRawValueFunctionsIndexed<V>(index,
639                                                                getter,
640                                                                setter),
641                                  useDefault))
642     SG_LOG(SG_GENERAL, SG_WARN,
643            "Failed to tie property " << name << " to indexed functions");
644 }
645
646
647 /**
648  * Tie a property to a pair of object methods.
649  *
650  * Every time the property value is queried, the getter (if any) will
651  * be invoked; every time the property value is modified, the setter
652  * (if any) will be invoked.  The getter can be 0 to make the property
653  * unreadable, and the setter can be 0 to make the property
654  * unmodifiable.
655  *
656  * @param name The property name to tie (full path).
657  * @param obj The object whose methods should be invoked.
658  * @param getter The object's getter method, or 0 if the value is
659  *        unreadable.
660  * @param setter The object's setter method, or 0 if the value is
661  *        unmodifiable.
662  * @param useDefault true if the setter should be invoked with any existing 
663  *        property value should be; false if the old value should be
664  *        discarded; defaults to true.
665  */
666 template <class T, class V>
667 inline void
668 fgTie (const string &name, T * obj, V (T::*getter)() const,
669        void (T::*setter)(V) = 0, bool useDefault = true)
670 {
671   if (!globals->get_props()->tie(name,
672                                  SGRawValueMethods<T,V>(*obj, getter, setter),
673                                  useDefault))
674     SG_LOG(SG_GENERAL, SG_WARN,
675            "Failed to tie property " << name << " to object methods");
676 }
677
678
679 /**
680  * Tie a property to a pair of indexed object methods.
681  *
682  * Every time the property value is queried, the getter (if any) will
683  * be invoked with the index provided; every time the property value
684  * is modified, the setter (if any) will be invoked with the index
685  * provided.  The getter can be 0 to make the property unreadable, and
686  * the setter can be 0 to make the property unmodifiable.
687  *
688  * @param name The property name to tie (full path).
689  * @param obj The object whose methods should be invoked.
690  * @param index The integer argument to pass to the getter and
691  *        setter methods.
692  * @param getter The getter method, or 0 if the value is unreadable.
693  * @param setter The setter method, or 0 if the value is unmodifiable.
694  * @param useDefault true if the setter should be invoked with any existing 
695  *        property value should be; false if the old value should be
696  *        discarded; defaults to true.
697  */
698 template <class T, class V>
699 inline void 
700 fgTie (const string &name, T * obj, int index,
701        V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
702        bool useDefault = true)
703 {
704   if (!globals->get_props()->tie(name,
705                                  SGRawValueMethodsIndexed<T,V>(*obj,
706                                                                index,
707                                                                getter,
708                                                                setter),
709                                  useDefault))
710     SG_LOG(SG_GENERAL, SG_WARN,
711            "Failed to tie property " << name << " to indexed object methods");
712 }
713
714
715 \f
716 ////////////////////////////////////////////////////////////////////////
717 // Conditions.
718 ////////////////////////////////////////////////////////////////////////
719
720
721 /**
722  * An encoded condition.
723  *
724  * This class encodes a single condition of some sort, possibly
725  * connected with properties.
726  *
727  * This class should migrate to somewhere more general.
728  */
729 class FGCondition
730 {
731 public:
732   FGCondition ();
733   virtual ~FGCondition ();
734   virtual bool test () const = 0;
735 };
736
737
738 /**
739  * Condition for a single property.
740  *
741  * This condition is true only if the property returns a boolean
742  * true value.
743  */
744 class FGPropertyCondition : public FGCondition
745 {
746 public:
747   FGPropertyCondition (const string &propname);
748   virtual ~FGPropertyCondition ();
749   virtual bool test () const { return _node->getBoolValue(); }
750 private:
751   const SGPropertyNode * _node;
752 };
753
754
755 /**
756  * Condition for a 'not' operator.
757  *
758  * This condition is true only if the child condition is false.
759  */
760 class FGNotCondition : public FGCondition
761 {
762 public:
763                                 // transfer pointer ownership
764   FGNotCondition (FGCondition * condition);
765   virtual ~FGNotCondition ();
766   virtual bool test () const;
767 private:
768   FGCondition * _condition;
769 };
770
771
772 /**
773  * Condition for an 'and' group.
774  *
775  * This condition is true only if all of the conditions
776  * in the group are true.
777  */
778 class FGAndCondition : public FGCondition
779 {
780 public:
781   FGAndCondition ();
782   virtual ~FGAndCondition ();
783   virtual bool test () const;
784                                 // transfer pointer ownership
785   virtual void addCondition (FGCondition * condition);
786 private:
787   vector<FGCondition *> _conditions;
788 };
789
790
791 /**
792  * Condition for an 'or' group.
793  *
794  * This condition is true if at least one of the conditions in the
795  * group is true.
796  */
797 class FGOrCondition : public FGCondition
798 {
799 public:
800   FGOrCondition ();
801   virtual ~FGOrCondition ();
802   virtual bool test () const;
803                                 // transfer pointer ownership
804   virtual void addCondition (FGCondition * condition);
805 private:
806   vector<FGCondition *> _conditions;
807 };
808
809
810 /**
811  * Abstract base class for property comparison conditions.
812  */
813 class FGComparisonCondition : public FGCondition
814 {
815 public:
816   enum Type {
817     LESS_THAN,
818     GREATER_THAN,
819     EQUALS
820   };
821   FGComparisonCondition (Type type, bool reverse = false);
822   virtual ~FGComparisonCondition ();
823   virtual bool test () const;
824   virtual void setLeftProperty (const string &propname);
825   virtual void setRightProperty (const string &propname);
826                                 // will make a local copy
827   virtual void setRightValue (const SGPropertyNode * value);
828 private:
829   Type _type;
830   bool _reverse;
831   const SGPropertyNode * _left_property;
832   const SGPropertyNode * _right_property;
833   const SGPropertyNode * _right_value;
834 };
835
836
837 /**
838  * Base class for a conditional components.
839  *
840  * This class manages the conditions and tests; the component should
841  * invoke the test() method whenever it needs to decide whether to
842  * active itself, draw itself, and so on.
843  */
844 class FGConditional
845 {
846 public:
847   FGConditional ();
848   virtual ~FGConditional ();
849                                 // transfer pointer ownership
850   virtual void setCondition (FGCondition * condition);
851   virtual const FGCondition * getCondition () const { return _condition; }
852   virtual bool test () const;
853 private:
854   FGCondition * _condition;
855 };
856
857
858 /**
859  * Global function to make a condition out of properties.
860  *
861  * The top-level is always an implicit 'and' group, whatever the
862  * node's name (it should usually be "condition").
863  *
864  * @param node The top-level condition node (usually named "condition").
865  * @return A pointer to a newly-allocated condition; it is the
866  *         responsibility of the caller to delete the condition when
867  *         it is no longer needed.
868  */
869 FGCondition * fgReadCondition (const SGPropertyNode * node);
870
871
872 #endif // __FG_PROPS_HXX
873