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