]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGBinding.cxx
Fix use count for deleted, reference counted objects.
[simgear.git] / simgear / structure / SGBinding.cxx
1 /**
2  * \file commands.hxx
3  * Interface definition for encapsulated commands.
4  * Started Spring 2001 by David Megginson, david@megginson.com
5  * This code is released into the Public Domain.
6  *
7  * $Id$
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #  include <simgear_config.h>
12 #endif
13
14 #include <boost/foreach.hpp>
15 #include <simgear/compiler.h>
16 #include "SGBinding.hxx"
17
18 #include <simgear/props/props_io.hxx>
19 #include <simgear/structure/exception.hxx>
20
21 SGBinding::SGBinding()
22   : _command(0),
23     _arg(new SGPropertyNode),
24     _setting(0)
25 {
26 }
27
28 SGBinding::SGBinding(const std::string& commandName)
29     : _command(0),
30     _arg(0),
31     _setting(0)
32 {
33     _command_name = commandName;
34 }
35
36 SGBinding::SGBinding(const SGPropertyNode* node, SGPropertyNode* root)
37   : _command(0),
38     _arg(0),
39     _setting(0)
40 {
41   read(node, root);
42 }
43
44 SGBinding::~SGBinding()
45 {
46   if(_arg && _arg->getParent())
47     _arg->getParent()->removeChild(_arg->getName(), _arg->getIndex());
48 }
49
50 void
51 SGBinding::clear()
52 {
53     _command = NULL;
54     _arg.clear();
55     _setting.clear();
56 }
57
58 void
59 SGBinding::read(const SGPropertyNode* node, SGPropertyNode* root)
60 {
61   const SGPropertyNode * conditionNode = node->getChild("condition");
62   if (conditionNode != 0)
63     setCondition(sgReadCondition(root, conditionNode));
64
65   _command_name = node->getStringValue("command", "");
66   if (_command_name.empty()) {
67     SG_LOG(SG_INPUT, SG_WARN, "No command supplied for binding.");
68     _command = 0;
69   }
70
71   _arg = const_cast<SGPropertyNode*>(node);
72   _setting = 0;
73 }
74
75 void
76 SGBinding::fire() const
77 {
78   if (test()) {
79     innerFire();
80   }
81 }
82
83 void
84 SGBinding::innerFire () const
85 {
86   if (_command == 0)
87     _command = SGCommandMgr::instance()->getCommand(_command_name);
88   if (_command == 0) {
89     SG_LOG(SG_INPUT, SG_WARN, "No command attached to binding:" << _command_name);
90   } else {
91       try {
92           if (!(*_command)(_arg)) {
93                 SG_LOG(SG_INPUT, SG_ALERT, "Failed to execute command "
94                        << _command_name);
95           }
96       } catch (sg_exception& e) {
97         SG_LOG(SG_GENERAL, SG_ALERT, "command '" << _command_name << "' failed with exception\n"
98           << "\tmessage:" << e.getMessage() << " (from " << e.getOrigin() << ")");
99       }
100   }
101 }
102
103 void
104 SGBinding::fire (SGPropertyNode* params) const
105 {
106   if (test()) {
107     if (params != NULL) {
108       copyProperties(params, _arg);
109     }
110     
111     innerFire();
112   }
113 }
114
115 void
116 SGBinding::fire (double offset, double max) const
117 {
118   if (test()) {
119     _arg->setDoubleValue("offset", offset/max);
120     innerFire();
121   }
122 }
123
124 void
125 SGBinding::fire (double setting) const
126 {
127   if (test()) {
128                                 // A value is automatically added to
129                                 // the args
130     if (_setting == 0)          // save the setting node for efficiency
131       _setting = _arg->getChild("setting", 0, true);
132     _setting->setDoubleValue(setting);
133     innerFire();
134   }
135 }
136
137 void fireBindingList(const SGBindingList& aBindings, SGPropertyNode* params)
138 {
139     BOOST_FOREACH(SGBinding_ptr b, aBindings) {
140         b->fire(params);
141     }
142 }
143
144 void fireBindingListWithOffset(const SGBindingList& aBindings, double offset, double max)
145 {
146     BOOST_FOREACH(SGBinding_ptr b, aBindings) {
147         b->fire(offset, max);
148     }
149 }
150
151 SGBindingList readBindingList(const simgear::PropertyList& aNodes, SGPropertyNode* aRoot)
152 {
153     SGBindingList result;
154     BOOST_FOREACH(SGPropertyNode* node, aNodes) {
155         result.push_back(new SGBinding(node, aRoot));
156     }
157     
158     return result;
159 }
160
161 void clearBindingList(const SGBindingList& aBindings)
162 {
163     BOOST_FOREACH(SGBinding_ptr b, aBindings) {
164         b->clear();
165     }
166 }
167