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