1 // fg_props.hxx - Declarations and inline methods for property handling.
2 // Written by David Megginson, started 2000.
4 // This file is in the Public Domain, and comes with no warranty.
7 #define __FG_PROPS_HXX 1
9 #include <simgear/debug/logstream.hxx>
10 #include <simgear/misc/props.hxx>
11 #include "globals.hxx"
14 ////////////////////////////////////////////////////////////////////////
15 // Property management.
16 ////////////////////////////////////////////////////////////////////////
20 * Initialize the default FlightGear properties.
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).
27 extern void fgInitProps (); // fixme: how are they untied?
31 * Update the default FlightGear properties.
33 * This function should be invoked once in each loop to update all
34 * of the default properties.
36 extern void fgUpdateProps ();
40 * Save a flight to disk.
42 * This function saves all of the archivable properties to a stream
43 * so that the current flight can be restored later.
45 * @param output The output stream to write the XML save file to.
46 * @return true if the flight was saved successfully.
48 extern bool fgSaveFlight (ostream &output);
52 * Load a flight from disk.
54 * This function loads an XML save file from a stream to restore
57 * @param input The input stream to read the XML from.
58 * @return true if the flight was restored successfully.
60 extern bool fgLoadFlight (istream &input);
64 ////////////////////////////////////////////////////////////////////////
65 // Convenience functions for getting property values.
66 ////////////////////////////////////////////////////////////////////////
70 * Get a property node.
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.
76 inline SGPropertyNode *
77 fgGetNode (const string &path, bool create = false)
79 return globals->get_props()->getNode(path, create);
84 * Get a property node with separate index.
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]").
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.
97 inline SGPropertyNode *
98 fgGetNode (const string &path, int index, bool create = false)
100 return globals->get_props()->getNode(path, index, create);
105 * Test whether a given node exists.
107 * @param path The path of the node, relative to root.
108 * @return true if the node exists, false otherwise.
111 fgHasNode (const string &path)
113 return (fgGetNode(path, false) != 0);
118 * Get a bool value for a property.
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.
126 * @param name The property name.
127 * @param defaultValue The default value to return if the property
129 * @return The property's value as a bool, or the default value provided.
131 inline bool fgGetBool (const string &name, bool defaultValue = false)
133 return globals->get_props()->getBoolValue(name, defaultValue);
138 * Get an int value for a property.
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.
146 * @param name The property name.
147 * @param defaultValue The default value to return if the property
149 * @return The property's value as an int, or the default value provided.
151 inline int fgGetInt (const string &name, int defaultValue = 0)
153 return globals->get_props()->getIntValue(name, defaultValue);
158 * Get a long value for a property.
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.
166 * @param name The property name.
167 * @param defaultValue The default value to return if the property
169 * @return The property's value as a long, or the default value provided.
171 inline int fgGetLong (const string &name, long defaultValue = 0L)
173 return globals->get_props()->getLongValue(name, defaultValue);
178 * Get a float value for a property.
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.
186 * @param name The property name.
187 * @param defaultValue The default value to return if the property
189 * @return The property's value as a float, or the default value provided.
191 inline float fgGetFloat (const string &name, float defaultValue = 0.0)
193 return globals->get_props()->getFloatValue(name, defaultValue);
198 * Get a double value for a property.
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.
206 * @param name The property name.
207 * @param defaultValue The default value to return if the property
209 * @return The property's value as a double, or the default value provided.
211 inline double fgGetDouble (const string &name, double defaultValue = 0.0)
213 return globals->get_props()->getDoubleValue(name, defaultValue);
218 * Get a string value for a property.
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.
226 * @param name The property name.
227 * @param defaultValue The default value to return if the property
229 * @return The property's value as a string, or the default value provided.
231 inline string fgGetString (const string &name, string defaultValue = "")
233 return globals->get_props()->getStringValue(name, defaultValue);
238 * Set a bool value for a property.
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
246 * @param name The property name.
247 * @param val The new value for the property.
248 * @return true if the assignment succeeded, false otherwise.
250 inline bool fgSetBool (const string &name, bool val)
252 return globals->get_props()->setBoolValue(name, val);
257 * Set an int value for a property.
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
265 * @param name The property name.
266 * @param val The new value for the property.
267 * @return true if the assignment succeeded, false otherwise.
269 inline bool fgSetInt (const string &name, int val)
271 return globals->get_props()->setIntValue(name, val);
276 * Set a long value for a property.
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
284 * @param name The property name.
285 * @param val The new value for the property.
286 * @return true if the assignment succeeded, false otherwise.
288 inline bool fgSetLong (const string &name, long val)
290 return globals->get_props()->setLongValue(name, val);
295 * Set a float value for a property.
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
303 * @param name The property name.
304 * @param val The new value for the property.
305 * @return true if the assignment succeeded, false otherwise.
307 inline bool fgSetFloat (const string &name, float val)
309 return globals->get_props()->setFloatValue(name, val);
314 * Set a double value for a property.
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
322 * @param name The property name.
323 * @param val The new value for the property.
324 * @return true if the assignment succeeded, false otherwise.
326 inline bool fgSetDouble (const string &name, double val)
328 return globals->get_props()->setDoubleValue(name, val);
333 * Set a string value for a property.
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
341 * @param name The property name.
342 * @param val The new value for the property.
343 * @return true if the assignment succeeded, false otherwise.
345 inline bool fgSetString (const string &name, const string &val)
347 return globals->get_props()->setStringValue(name, val);
352 ////////////////////////////////////////////////////////////////////////
353 // Convenience functions for setting property attributes.
354 ////////////////////////////////////////////////////////////////////////
358 * Set the state of the archive attribute for a property.
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
364 * A warning message will be printed if the property does not exist.
366 * @param name The property name.
367 * @param state The state of the archive attribute (defaults to true).
370 fgSetArchivable (const string &name, bool state = true)
372 SGPropertyNode * node = globals->get_props()->getNode(name);
374 SG_LOG(SG_GENERAL, SG_ALERT,
375 "Attempt to set archive flag for non-existant property "
378 node->setAttribute(SGPropertyNode::ARCHIVE, state);
383 * Set the state of the read attribute for a property.
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
389 * A warning message will be printed if the property does not exist.
391 * @param name The property name.
392 * @param state The state of the read attribute (defaults to true).
395 fgSetReadable (const string &name, bool state = true)
397 SGPropertyNode * node = globals->get_props()->getNode(name);
399 SG_LOG(SG_GENERAL, SG_ALERT,
400 "Attempt to set read flag for non-existant property "
403 node->setAttribute(SGPropertyNode::READ, state);
408 * Set the state of the write attribute for a property.
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.
414 * A warning message will be printed if the property does not exist.
416 * @param name The property name.
417 * @param state The state of the write attribute (defaults to true).
420 fgSetWritable (const string &name, bool state = true)
422 SGPropertyNode * node = globals->get_props()->getNode(name);
424 SG_LOG(SG_GENERAL, SG_ALERT,
425 "Attempt to set write flag for non-existant property "
428 node->setAttribute(SGPropertyNode::WRITE, state);
433 ////////////////////////////////////////////////////////////////////////
434 // Convenience functions for tying properties, with logging.
435 ////////////////////////////////////////////////////////////////////////
439 * Untie a property from an external data source.
441 * Classes should use this function to release control of any
442 * properties they are managing.
445 fgUntie (const string &name)
447 if (!globals->get_props()->untie(name))
448 SG_LOG(SG_GENERAL, SG_WARN, "Failed to untie property " << name);
452 // Templates cause ambiguity here
455 * Tie a property to an external bool variable.
457 * The property's value will automatically mirror the variable's
458 * value, and vice-versa, until the property is untied.
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.
467 fgTie (const string &name, bool *pointer, bool useDefault = true)
469 if (!globals->get_props()->tie(name, SGRawValuePointer<bool>(pointer),
471 SG_LOG(SG_GENERAL, SG_WARN,
472 "Failed to tie property " << name << " to a pointer");
477 * Tie a property to an external int variable.
479 * The property's value will automatically mirror the variable's
480 * value, and vice-versa, until the property is untied.
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.
489 fgTie (const string &name, int *pointer, bool useDefault = true)
491 if (!globals->get_props()->tie(name, SGRawValuePointer<int>(pointer),
493 SG_LOG(SG_GENERAL, SG_WARN,
494 "Failed to tie property " << name << " to a pointer");
499 * Tie a property to an external long variable.
501 * The property's value will automatically mirror the variable's
502 * value, and vice-versa, until the property is untied.
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.
511 fgTie (const string &name, long *pointer, bool useDefault = true)
513 if (!globals->get_props()->tie(name, SGRawValuePointer<long>(pointer),
515 SG_LOG(SG_GENERAL, SG_WARN,
516 "Failed to tie property " << name << " to a pointer");
521 * Tie a property to an external float variable.
523 * The property's value will automatically mirror the variable's
524 * value, and vice-versa, until the property is untied.
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.
533 fgTie (const string &name, float *pointer, bool useDefault = true)
535 if (!globals->get_props()->tie(name, SGRawValuePointer<float>(pointer),
537 SG_LOG(SG_GENERAL, SG_WARN,
538 "Failed to tie property " << name << " to a pointer");
543 * Tie a property to an external double variable.
545 * The property's value will automatically mirror the variable's
546 * value, and vice-versa, until the property is untied.
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.
555 fgTie (const string &name, double *pointer, bool useDefault = true)
557 if (!globals->get_props()->tie(name, SGRawValuePointer<double>(pointer),
559 SG_LOG(SG_GENERAL, SG_WARN,
560 "Failed to tie property " << name << " to a pointer");
565 * Tie a property to an external string variable.
567 * The property's value will automatically mirror the variable's
568 * value, and vice-versa, until the property is untied.
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.
577 fgTie (const string &name, string *pointer, bool useDefault = true)
579 if (!globals->get_props()->tie(name, SGRawValuePointer<string>(pointer),
581 SG_LOG(SG_GENERAL, SG_WARN,
582 "Failed to tie property " << name << " to a pointer");
587 * Tie a property to a pair of simple functions.
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
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.
604 fgTie (const string &name, V (*getter)(), void (*setter)(V) = 0,
605 bool useDefault = true)
607 if (!globals->get_props()->tie(name, SGRawValueFunctions<V>(getter, setter),
609 SG_LOG(SG_GENERAL, SG_WARN,
610 "Failed to tie property " << name << " to functions");
615 * Tie a property to a pair of indexed functions.
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.
623 * @param name The property name to tie (full path).
624 * @param index The integer argument to pass to the getter and
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.
634 fgTie (const string &name, int index, V (*getter)(int),
635 void (*setter)(int, V) = 0, bool useDefault = true)
637 if (!globals->get_props()->tie(name,
638 SGRawValueFunctionsIndexed<V>(index,
642 SG_LOG(SG_GENERAL, SG_WARN,
643 "Failed to tie property " << name << " to indexed functions");
648 * Tie a property to a pair of object methods.
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
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
660 * @param setter The object's setter method, or 0 if the value is
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.
666 template <class T, class V>
668 fgTie (const string &name, T * obj, V (T::*getter)() const,
669 void (T::*setter)(V) = 0, bool useDefault = true)
671 if (!globals->get_props()->tie(name,
672 SGRawValueMethods<T,V>(*obj, getter, setter),
674 SG_LOG(SG_GENERAL, SG_WARN,
675 "Failed to tie property " << name << " to object methods");
680 * Tie a property to a pair of indexed object methods.
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.
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
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.
698 template <class T, class V>
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)
704 if (!globals->get_props()->tie(name,
705 SGRawValueMethodsIndexed<T,V>(*obj,
710 SG_LOG(SG_GENERAL, SG_WARN,
711 "Failed to tie property " << name << " to indexed object methods");
716 ////////////////////////////////////////////////////////////////////////
718 ////////////////////////////////////////////////////////////////////////
722 * An encoded condition.
724 * This class encodes a single condition of some sort, possibly
725 * connected with properties.
727 * This class should migrate to somewhere more general.
733 virtual ~FGCondition ();
734 virtual bool test () const = 0;
739 * Condition for a single property.
741 * This condition is true only if the property returns a boolean
744 class FGPropertyCondition : public FGCondition
747 FGPropertyCondition (const string &propname);
748 virtual ~FGPropertyCondition ();
749 virtual bool test () const { return _node->getBoolValue(); }
751 const SGPropertyNode * _node;
756 * Condition for a 'not' operator.
758 * This condition is true only if the child condition is false.
760 class FGNotCondition : public FGCondition
763 // transfer pointer ownership
764 FGNotCondition (FGCondition * condition);
765 virtual ~FGNotCondition ();
766 virtual bool test () const;
768 FGCondition * _condition;
773 * Condition for an 'and' group.
775 * This condition is true only if all of the conditions
776 * in the group are true.
778 class FGAndCondition : public FGCondition
782 virtual ~FGAndCondition ();
783 virtual bool test () const;
784 // transfer pointer ownership
785 virtual void addCondition (FGCondition * condition);
787 vector<FGCondition *> _conditions;
792 * Condition for an 'or' group.
794 * This condition is true if at least one of the conditions in the
797 class FGOrCondition : public FGCondition
801 virtual ~FGOrCondition ();
802 virtual bool test () const;
803 // transfer pointer ownership
804 virtual void addCondition (FGCondition * condition);
806 vector<FGCondition *> _conditions;
811 * Abstract base class for property comparison conditions.
813 class FGComparisonCondition : public FGCondition
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);
831 const SGPropertyNode * _left_property;
832 const SGPropertyNode * _right_property;
833 const SGPropertyNode * _right_value;
838 * Base class for a conditional components.
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.
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;
854 FGCondition * _condition;
859 * Global function to make a condition out of properties.
861 * The top-level is always an implicit 'and' group, whatever the
862 * node's name (it should usually be "condition").
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.
869 FGCondition * fgReadCondition (const SGPropertyNode * node);
872 #endif // __FG_PROPS_HXX