]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGPropertyManager.h
Fix for bug 1304 - crash loading XML route
[flightgear.git] / src / FDM / JSBSim / input_output / FGPropertyManager.h
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Header:       FGPropertyManager.h
4  Author:       Tony Peden
5                Based on work originally by David Megginson
6  Date:         2/2002
7
8  ------------- Copyright (C) 2002 -------------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU Lesser General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
18  details.
19
20  You should have received a copy of the GNU Lesser General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU Lesser General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28 SENTRY
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30
31 #ifndef FGPROPERTYMANAGER_H
32 #define FGPROPERTYMANAGER_H
33
34 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 INCLUDES
36 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
37
38 // This is needed by MSVC9 when included in FlightGear because of
39 // the new Vec4d class in props.hxx
40 #if defined( HAVE_CONFIG_H )
41 # include <config.h>
42 #endif
43
44 #include <string>
45 #include "simgear/props/props.hxx"
46 #if !PROPS_STANDALONE
47 # include "simgear/math/SGMath.hxx"
48 #endif
49
50 #include "FGJSBBase.h"
51
52 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 DEFINITIONS
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
55
56 #define ID_PROPERTYMANAGER "$Id: FGPropertyManager.h,v 1.28 2013/09/28 14:43:15 bcoconni Exp $"
57
58 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59 FORWARD DECLARATIONS
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
61
62 namespace JSBSim {
63
64 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65 CLASS DOCUMENTATION
66 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
67
68 /** Class wrapper for property handling.
69     @author David Megginson, Tony Peden
70   */
71
72 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 CLASS DECLARATION
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
75
76 class FGPropertyNode : public SGPropertyNode
77 {
78   public:
79     /// Destructor
80     virtual ~FGPropertyNode(void) {}
81
82     /**
83      * Get a property node.
84      *
85      * @param path The path of the node, relative to root.
86      * @param create true to create the node if it doesn't exist.
87      * @return The node, or 0 if none exists and none was created.
88      */
89     FGPropertyNode*
90     GetNode (const std::string &path, bool create = false);
91
92     FGPropertyNode*
93     GetNode (const std::string &relpath, int index, bool create = false);
94
95     /**
96      * Test whether a given node exists.
97      *
98      * @param path The path of the node, relative to root.
99      * @return true if the node exists, false otherwise.
100      */
101     bool HasNode (const std::string &path);
102
103     /**
104      * Get the name of a node
105      */
106     std::string GetName( void ) const;
107
108     /**
109      * Get the name of a node without underscores, etc.
110      */
111     std::string GetPrintableName( void ) const;
112
113     /**
114      * Get the fully qualified name of a node
115      * This function is very slow, so is probably useful for debugging only.
116      */
117     std::string GetFullyQualifiedName(void) const;
118
119     /**
120      * Get the qualified name of a node relative to given base path,
121      * otherwise the fully qualified name.
122      * This function is very slow, so is probably useful for debugging only.
123      *
124      * @param path The path to strip off, if found.
125      */
126     std::string GetRelativeName( const std::string &path = "/fdm/jsbsim/" ) const;
127
128     /**
129      * Get a bool value for a property.
130      *
131      * This method is convenient but inefficient.  It should be used
132      * infrequently (i.e. for initializing, loading, saving, etc.),
133      * not in the main loop.  If you need to get a value frequently,
134      * it is better to look up the node itself using GetNode and then
135      * use the node's getBoolValue() method, to avoid the lookup overhead.
136      *
137      * @param name The property name.
138      * @param defaultValue The default value to return if the property
139      *        does not exist.
140      * @return The property's value as a bool, or the default value provided.
141      */
142     bool GetBool (const std::string &name, bool defaultValue = false) const;
143
144
145     /**
146      * Get an int value for a property.
147      *
148      * This method is convenient but inefficient.  It should be used
149      * infrequently (i.e. for initializing, loading, saving, etc.),
150      * not in the main loop.  If you need to get a value frequently,
151      * it is better to look up the node itself using GetNode and then
152      * use the node's getIntValue() method, to avoid the lookup overhead.
153      *
154      * @param name The property name.
155      * @param defaultValue The default value to return if the property
156      *        does not exist.
157      * @return The property's value as an int, or the default value provided.
158      */
159     int GetInt (const std::string &name, int defaultValue = 0) const;
160
161
162     /**
163      * Get a long value for a property.
164      *
165      * This method is convenient but inefficient.  It should be used
166      * infrequently (i.e. for initializing, loading, saving, etc.),
167      * not in the main loop.  If you need to get a value frequently,
168      * it is better to look up the node itself using GetNode and then
169      * use the node's getLongValue() method, to avoid the lookup overhead.
170      *
171      * @param name The property name.
172      * @param defaultValue The default value to return if the property
173      *        does not exist.
174      * @return The property's value as a long, or the default value provided.
175      */
176     int GetLong (const std::string &name, long defaultValue = 0L) const;
177
178
179     /**
180      * Get a float value for a property.
181      *
182      * This method is convenient but inefficient.  It should be used
183      * infrequently (i.e. for initializing, loading, saving, etc.),
184      * not in the main loop.  If you need to get a value frequently,
185      * it is better to look up the node itself using GetNode and then
186      * use the node's getFloatValue() method, to avoid the lookup overhead.
187      *
188      * @param name The property name.
189      * @param defaultValue The default value to return if the property
190      *        does not exist.
191      * @return The property's value as a float, or the default value provided.
192      */
193     float GetFloat (const std::string &name, float defaultValue = 0.0) const;
194
195
196     /**
197      * Get a double value for a property.
198      *
199      * This method is convenient but inefficient.  It should be used
200      * infrequently (i.e. for initializing, loading, saving, etc.),
201      * not in the main loop.  If you need to get a value frequently,
202      * it is better to look up the node itself using GetNode and then
203      * use the node's getDoubleValue() method, to avoid the lookup overhead.
204      *
205      * @param name The property name.
206      * @param defaultValue The default value to return if the property
207      *        does not exist.
208      * @return The property's value as a double, or the default value provided.
209      */
210     double GetDouble (const std::string &name, double defaultValue = 0.0) const;
211
212
213     /**
214      * Get a string value for a property.
215      *
216      * This method is convenient but inefficient.  It should be used
217      * infrequently (i.e. for initializing, loading, saving, etc.),
218      * not in the main loop.  If you need to get a value frequently,
219      * it is better to look up the node itself using GetNode and then
220      * use the node's getStringValue() method, to avoid the lookup overhead.
221      *
222      * @param name The property name.
223      * @param defaultValue The default value to return if the property
224      *        does not exist.
225      * @return The property's value as a string, or the default value provided.
226      */
227     std::string GetString (const std::string &name, std::string defaultValue = "") const;
228
229
230     /**
231      * Set a bool value for a property.
232      *
233      * Assign a bool value to a property.  If the property does not
234      * yet exist, it will be created and its type will be set to
235      * BOOL; if it has a type of UNKNOWN, the type will also be set to
236      * BOOL; otherwise, the bool value will be converted to the property's
237      * type.
238      *
239      * @param name The property name.
240      * @param val The new value for the property.
241      * @return true if the assignment succeeded, false otherwise.
242      */
243     bool SetBool (const std::string &name, bool val);
244
245
246     /**
247      * Set an int value for a property.
248      *
249      * Assign an int value to a property.  If the property does not
250      * yet exist, it will be created and its type will be set to
251      * INT; if it has a type of UNKNOWN, the type will also be set to
252      * INT; otherwise, the bool value will be converted to the property's
253      * type.
254      *
255      * @param name The property name.
256      * @param val The new value for the property.
257      * @return true if the assignment succeeded, false otherwise.
258      */
259     bool SetInt (const std::string &name, int val);
260
261
262     /**
263      * Set a long value for a property.
264      *
265      * Assign a long value to a property.  If the property does not
266      * yet exist, it will be created and its type will be set to
267      * LONG; if it has a type of UNKNOWN, the type will also be set to
268      * LONG; otherwise, the bool value will be converted to the property's
269      * type.
270      *
271      * @param name The property name.
272      * @param val The new value for the property.
273      * @return true if the assignment succeeded, false otherwise.
274      */
275     bool SetLong (const std::string &name, long val);
276
277
278     /**
279      * Set a float value for a property.
280      *
281      * Assign a float value to a property.  If the property does not
282      * yet exist, it will be created and its type will be set to
283      * FLOAT; if it has a type of UNKNOWN, the type will also be set to
284      * FLOAT; otherwise, the bool value will be converted to the property's
285      * type.
286      *
287      * @param name The property name.
288      * @param val The new value for the property.
289      * @return true if the assignment succeeded, false otherwise.
290      */
291     bool SetFloat (const std::string &name, float val);
292
293
294     /**
295      * Set a double value for a property.
296      *
297      * Assign a double value to a property.  If the property does not
298      * yet exist, it will be created and its type will be set to
299      * DOUBLE; if it has a type of UNKNOWN, the type will also be set to
300      * DOUBLE; otherwise, the double value will be converted to the property's
301      * type.
302      *
303      * @param name The property name.
304      * @param val The new value for the property.
305      * @return true if the assignment succeeded, false otherwise.
306      */
307     bool SetDouble (const std::string &name, double val);
308
309
310     /**
311      * Set a string value for a property.
312      *
313      * Assign a string value to a property.  If the property does not
314      * yet exist, it will be created and its type will be set to
315      * STRING; if it has a type of UNKNOWN, the type will also be set to
316      * STRING; otherwise, the string value will be converted to the property's
317      * type.
318      *
319      * @param name The property name.
320      * @param val The new value for the property.
321      * @return true if the assignment succeeded, false otherwise.
322      */
323     bool SetString (const std::string &name, const std::string &val);
324
325
326     ////////////////////////////////////////////////////////////////////////
327     // Convenience functions for setting property attributes.
328     ////////////////////////////////////////////////////////////////////////
329
330
331     /**
332      * Set the state of the archive attribute for a property.
333      *
334      * If the archive attribute is true, the property will be written
335      * when a flight is saved; if it is false, the property will be
336      * skipped.
337      *
338      * A warning message will be printed if the property does not exist.
339      *
340      * @param name The property name.
341      * @param state The state of the archive attribute (defaults to true).
342      */
343     void SetArchivable (const std::string &name, bool state = true);
344
345
346     /**
347      * Set the state of the read attribute for a property.
348      *
349      * If the read attribute is true, the property value will be readable;
350      * if it is false, the property value will always be the default value
351      * for its type.
352      *
353      * A warning message will be printed if the property does not exist.
354      *
355      * @param name The property name.
356      * @param state The state of the read attribute (defaults to true).
357      */
358     void SetReadable (const std::string &name, bool state = true);
359
360
361     /**
362      * Set the state of the write attribute for a property.
363      *
364      * If the write attribute is true, the property value may be modified
365      * (depending on how it is tied); if the write attribute is false, the
366      * property value may not be modified.
367      *
368      * A warning message will be printed if the property does not exist.
369      *
370      * @param name The property name.
371      * @param state The state of the write attribute (defaults to true).
372      */
373     void SetWritable (const std::string &name, bool state = true);
374 };
375
376 typedef SGSharedPtr<FGPropertyNode> FGPropertyNode_ptr;
377 typedef SGSharedPtr<const FGPropertyNode> FGConstPropertyNode_ptr;
378
379 class FGPropertyManager
380 {
381   public:
382     /// Default constructor
383     FGPropertyManager(void) { root = new FGPropertyNode; }
384
385     /// Constructor
386     FGPropertyManager(FGPropertyNode* _root) : root(_root) {};
387
388     /// Destructor
389     virtual ~FGPropertyManager(void) { Unbind(); }
390
391     FGPropertyNode* GetNode(void) const { return root; }
392     FGPropertyNode* GetNode(const std::string &path, bool create = false)
393     { return root->GetNode(path, create); }
394     FGPropertyNode* GetNode(const std::string &relpath, int index, bool create = false)
395     { return root->GetNode(relpath, index, create); }
396     bool HasNode(const std::string& path) const
397     {
398       std::string newPath = path;
399       if (newPath[0] == '-') newPath.erase(0,1);
400       return root->HasNode(newPath);
401     }
402
403     /** Property-ify a name
404      *  replaces spaces with '-' and, optionally, makes name all lower case
405      *  @param name string to change
406      *  @param lowercase true to change all upper case chars to lower
407      *  NOTE: this function changes its argument and thus relies
408      *  on pass by value
409      */
410     std::string mkPropertyName(std::string name, bool lowercase);
411
412     ////////////////////////////////////////////////////////////////////////
413     // Convenience functions for tying properties, with logging.
414     ////////////////////////////////////////////////////////////////////////
415
416
417     /**
418      * Untie a property from an external data source.
419      *
420      * Classes should use this function to release control of any
421      * properties they are managing.
422      */
423     void Untie (const std::string &name);
424
425     /**
426      * Unbind all properties bound by this manager to an external data source.
427      *
428      * Classes should use this function to release control of any
429      * properties they have bound using this property manager.
430      */
431     void Unbind (void);
432
433         // Templates cause ambiguity here
434
435     /**
436      * Tie a property to an external bool variable.
437      *
438      * The property's value will automatically mirror the variable's
439      * value, and vice-versa, until the property is untied.
440      *
441      * @param name The property name to tie (full path).
442      * @param pointer A pointer to the variable.
443      * @param useDefault true if any existing property value should be
444      *        copied to the variable; false if the variable should not
445      *        be modified; defaults to true.
446      */
447     void
448     Tie (const std::string &name, bool *pointer, bool useDefault = true);
449
450
451     /**
452      * Tie a property to an external int variable.
453      *
454      * The property's value will automatically mirror the variable's
455      * value, and vice-versa, until the property is untied.
456      *
457      * @param name The property name to tie (full path).
458      * @param pointer A pointer to the variable.
459      * @param useDefault true if any existing property value should be
460      *        copied to the variable; false if the variable should not
461      *        be modified; defaults to true.
462      */
463     void
464     Tie (const std::string &name, int *pointer, bool useDefault = true);
465
466
467     /**
468      * Tie a property to an external long variable.
469      *
470      * The property's value will automatically mirror the variable's
471      * value, and vice-versa, until the property is untied.
472      *
473      * @param name The property name to tie (full path).
474      * @param pointer A pointer to the variable.
475      * @param useDefault true if any existing property value should be
476      *        copied to the variable; false if the variable should not
477      *        be modified; defaults to true.
478      */
479     void
480     Tie (const std::string &name, long *pointer, bool useDefault = true);
481
482
483     /**
484      * Tie a property to an external float variable.
485      *
486      * The property's value will automatically mirror the variable's
487      * value, and vice-versa, until the property is untied.
488      *
489      * @param name The property name to tie (full path).
490      * @param pointer A pointer to the variable.
491      * @param useDefault true if any existing property value should be
492      *        copied to the variable; false if the variable should not
493      *        be modified; defaults to true.
494      */
495     void
496     Tie (const std::string &name, float *pointer, bool useDefault = true);
497
498     /**
499      * Tie a property to an external double variable.
500      *
501      * The property's value will automatically mirror the variable's
502      * value, and vice-versa, until the property is untied.
503      *
504      * @param name The property name to tie (full path).
505      * @param pointer A pointer to the variable.
506      * @param useDefault true if any existing property value should be
507      *        copied to the variable; false if the variable should not
508      *        be modified; defaults to true.
509      */
510     void
511     Tie (const std::string &name, double *pointer, bool useDefault = true);
512
513 //============================================================================
514 //
515 //  All of the following functions *must* be inlined, otherwise linker
516 //  errors will result
517 //
518 //============================================================================
519
520     /* template <class V> void
521     Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0,
522            bool useDefault = true);
523
524     template <class V> void
525     Tie (const std::string &name, int index, V (*getter)(int),
526            void (*setter)(int, V) = 0, bool useDefault = true);
527
528     template <class T, class V> void
529     Tie (const std::string &name, T * obj, V (T::*getter)() const,
530            void (T::*setter)(V) = 0, bool useDefault = true);
531
532     template <class T, class V> void
533     Tie (const std::string &name, T * obj, int index,
534            V (T::*getter)(int) const, void (T::*setter)(int, V) = 0,
535            bool useDefault = true); */
536
537      /**
538      * Tie a property to a pair of simple functions.
539      *
540      * Every time the property value is queried, the getter (if any) will
541      * be invoked; every time the property value is modified, the setter
542      * (if any) will be invoked.  The getter can be 0 to make the property
543      * unreadable, and the setter can be 0 to make the property
544      * unmodifiable.
545      *
546      * @param name The property name to tie (full path).
547      * @param getter The getter function, or 0 if the value is unreadable.
548      * @param setter The setter function, or 0 if the value is unmodifiable.
549      * @param useDefault true if the setter should be invoked with any existing
550      *        property value should be; false if the old value should be
551      *        discarded; defaults to true.
552      */
553
554     template <class V> inline void
555     Tie (const std::string &name, V (*getter)(), void (*setter)(V) = 0, bool useDefault = true)
556     {
557       SGPropertyNode* property = root->getNode(name.c_str(), true);
558       if (!property) {
559         std::cerr << "Could not get or create property " << name << std::endl;
560         return;
561       }
562
563       if (!property->tie(SGRawValueFunctions<V>(getter, setter), useDefault))
564         std::cerr << "Failed to tie property " << name << " to functions" << std::endl;
565       else {
566         if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
567         if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
568         tied_properties.push_back(property);
569         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
570       }
571     }
572
573
574     /**
575      * Tie a property to a pair of indexed functions.
576      *
577      * Every time the property value is queried, the getter (if any) will
578      * be invoked with the index provided; every time the property value
579      * is modified, the setter (if any) will be invoked with the index
580      * provided.  The getter can be 0 to make the property unreadable, and
581      * the setter can be 0 to make the property unmodifiable.
582      *
583      * @param name The property name to tie (full path).
584      * @param index The integer argument to pass to the getter and
585      *        setter functions.
586      * @param getter The getter function, or 0 if the value is unreadable.
587      * @param setter The setter function, or 0 if the value is unmodifiable.
588      * @param useDefault true if the setter should be invoked with any existing
589      *        property value should there be one; false if the old value should be
590      *        discarded; defaults to true.
591      */
592     template <class V> inline void Tie (const std::string &name, int index, V (*getter)(int),
593                                 void (*setter)(int, V) = 0, bool useDefault = true)
594     {
595       SGPropertyNode* property = root->getNode(name.c_str(), true);
596       if (!property) {
597         std::cerr << "Could not get or create property " << name << std::endl;
598         return;
599       }
600
601       if (!property->tie(SGRawValueFunctionsIndexed<V>(index, getter, setter), useDefault))
602         std::cerr << "Failed to tie property " << name << " to indexed functions" << std::endl;
603       else {
604         if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
605         if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
606         tied_properties.push_back(property);
607         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
608       }
609     }
610
611
612     /**
613      * Tie a property to a pair of object methods.
614      *
615      * Every time the property value is queried, the getter (if any) will
616      * be invoked; every time the property value is modified, the setter
617      * (if any) will be invoked.  The getter can be 0 to make the property
618      * unreadable, and the setter can be 0 to make the property
619      * unmodifiable.
620      *
621      * @param name The property name to tie (full path).
622      * @param obj The object whose methods should be invoked.
623      * @param getter The object's getter method, or 0 if the value is
624      *        unreadable.
625      * @param setter The object's setter method, or 0 if the value is
626      *        unmodifiable.
627      * @param useDefault true if the setter should be invoked with any existing
628      *        property value should there be one; false if the old value should be
629      *        discarded; defaults to true.
630      */
631     template <class T, class V> inline void
632     Tie (const std::string &name, T * obj, V (T::*getter)() const,
633            void (T::*setter)(V) = 0, bool useDefault = true)
634     {
635       SGPropertyNode* property = root->getNode(name.c_str(), true);
636       if (!property) {
637         std::cerr << "Could not get or create property " << name << std::endl;
638         return;
639       }
640
641       if (!property->tie(SGRawValueMethods<T,V>(*obj, getter, setter), useDefault))
642         std::cerr << "Failed to tie property " << name << " to object methods" << std::endl;
643       else {
644         if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
645         if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
646         tied_properties.push_back(property);
647         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
648       }
649     }
650
651     /**
652      * Tie a property to a pair of indexed object methods.
653      *
654      * Every time the property value is queried, the getter (if any) will
655      * be invoked with the index provided; every time the property value
656      * is modified, the setter (if any) will be invoked with the index
657      * provided.  The getter can be 0 to make the property unreadable, and
658      * the setter can be 0 to make the property unmodifiable.
659      *
660      * @param name The property name to tie (full path).
661      * @param obj The object whose methods should be invoked.
662      * @param index The integer argument to pass to the getter and
663      *        setter methods.
664      * @param getter The getter method, or 0 if the value is unreadable.
665      * @param setter The setter method, or 0 if the value is unmodifiable.
666      * @param useDefault true if the setter should be invoked with any existing
667      *        property value should be; false if the old value should be
668      *        discarded; defaults to true.
669      */
670     template <class T, class V> inline void
671     Tie (const std::string &name, T * obj, int index, V (T::*getter)(int) const,
672                          void (T::*setter)(int, V) = 0, bool useDefault = true)
673     {
674       SGPropertyNode* property = root->getNode(name.c_str(), true);
675       if (!property) {
676         std::cerr << "Could not get or create property " << name << std::endl;
677         return;
678       }
679
680       if (!property->tie(SGRawValueMethodsIndexed<T,V>(*obj, index, getter, setter), useDefault))
681         std::cerr << "Failed to tie property " << name << " to indexed object methods" << std::endl;
682       else {
683         if (setter == 0) property->setAttribute(SGPropertyNode::WRITE, false);
684         if (getter == 0) property->setAttribute(SGPropertyNode::READ, false);
685         tied_properties.push_back(property);
686         if (FGJSBBase::debug_lvl & 0x20) std::cout << name << std::endl;
687       }
688    }
689
690   private:
691     std::vector<SGPropertyNode_ptr> tied_properties;
692     FGPropertyNode_ptr root;
693 };
694 }
695 #endif // FGPROPERTYMANAGER_H
696