]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGBinding.cxx
Command-manager supports functors.
[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/structure/exception.hxx>
19
20 SGBinding::SGBinding()
21   : _command(0),
22     _arg(new SGPropertyNode),
23     _setting(0)
24 {
25 }
26
27 SGBinding::SGBinding(const std::string& commandName)
28     : _command(0),
29     _arg(0),
30     _setting(0)
31 {
32     _command_name = commandName;
33 }
34
35 SGBinding::SGBinding(const SGPropertyNode* node, SGPropertyNode* root)
36   : _command(0),
37     _arg(0),
38     _setting(0)
39 {
40   read(node, root);
41 }
42
43 SGBinding::~SGBinding()
44 {
45   if(_arg && _arg->getParent())
46     _arg->getParent()->removeChild(_arg->getName(), _arg->getIndex(), false);
47 }
48
49 void
50 SGBinding::read(const SGPropertyNode* node, SGPropertyNode* root)
51 {
52   const SGPropertyNode * conditionNode = node->getChild("condition");
53   if (conditionNode != 0)
54     setCondition(sgReadCondition(root, conditionNode));
55
56   _command_name = node->getStringValue("command", "");
57   if (_command_name.empty()) {
58     SG_LOG(SG_INPUT, SG_WARN, "No command supplied for binding.");
59     _command = 0;
60   }
61
62   _arg = const_cast<SGPropertyNode*>(node);
63   _setting = 0;
64 }
65
66 void
67 SGBinding::fire () const
68 {
69   if (test()) {
70     if (_command == 0)
71       _command = SGCommandMgr::instance()->getCommand(_command_name);
72     if (_command == 0) {
73       SG_LOG(SG_INPUT, SG_WARN, "No command attached to binding");
74     } else
75     {
76         try {
77             if (!(*_command)(_arg)) {
78                   SG_LOG(SG_INPUT, SG_ALERT, "Failed to execute command "
79                          << _command_name);
80             }
81         } catch (sg_exception& e) {
82           SG_LOG(SG_GENERAL, SG_ALERT, "command '" << _command_name << "' failed with exception\n"
83             << "\tmessage:" << e.getMessage() << " (from " << e.getOrigin() << ")");
84         }
85     }
86   }
87 }
88
89 void
90 SGBinding::fire (double offset, double max) const
91 {
92   if (test()) {
93     _arg->setDoubleValue("offset", offset/max);
94     fire();
95   }
96 }
97
98 void
99 SGBinding::fire (double setting) const
100 {
101   if (test()) {
102                                 // A value is automatically added to
103                                 // the args
104     if (_setting == 0)          // save the setting node for efficiency
105       _setting = _arg->getChild("setting", 0, true);
106     _setting->setDoubleValue(setting);
107     fire();
108   }
109 }
110
111 void fireBindingList(const SGBindingList& aBindings)
112 {
113     BOOST_FOREACH(SGBinding_ptr b, aBindings) {
114         b->fire();
115     }
116 }
117
118 void fireBindingListWithOffset(const SGBindingList& aBindings, double offset, double max)
119 {
120     BOOST_FOREACH(SGBinding_ptr b, aBindings) {
121         b->fire(offset, max);
122     }
123 }
124
125 SGBindingList readBindingList(const simgear::PropertyList& aNodes, SGPropertyNode* aRoot)
126 {
127     SGBindingList result;
128     BOOST_FOREACH(SGPropertyNode* node, aNodes) {
129         result.push_back(new SGBinding(node, aRoot));
130     }
131     
132     return result;
133 }