]> git.mxchange.org Git - simgear.git/blob - simgear/props/AtomicChangeListener.hxx
Melchior FRANZ: fix SGPropertyNode::LAST_USED_ATTRIBUTE
[simgear.git] / simgear / props / AtomicChangeListener.hxx
1 #ifndef SIMGEAR_ATOMICCHANGELISTENER_HXX
2 #define SIMGEAR_ATOMICCHANGELISTENER_HXX 1
3
4 #include <algorithm>
5 #include <iterator>
6 #include <vector>
7
8 #include <boost/bind.hpp>
9
10 #include <simgear/structure/Singleton.hxx>
11
12 #include "props.hxx"
13 #include "ExtendedPropertyAdapter.hxx"
14
15 namespace simgear
16 {
17 // Performs an action when one of several nodes changes
18 class MultiChangeListener : public SGPropertyChangeListener
19 {
20 public:
21     MultiChangeListener();
22     template<typename Pitr>
23     void listenToProperties(Pitr propsBegin, Pitr propsEnd)
24     {
25         for (Pitr itr = propsBegin, end = propsEnd; itr != end; ++itr)
26             (*itr)->addChangeListener(this);
27     }
28 private:
29     void valueChanged(SGPropertyNode* node);
30     virtual void valueChangedImplementation();
31
32 };
33
34 class AtomicChangeListener : public MultiChangeListener,
35                              public virtual SGReferenced
36 {
37 public:
38     AtomicChangeListener(std::vector<SGPropertyNode*>& nodes);
39     /**
40      * Lookup / create child nodes from their relative names.
41      */
42     template<typename Itr>
43     AtomicChangeListener(SGPropertyNode* parent, Itr childNamesBegin,
44                          Itr childNamesEnd)
45         : _dirty(false), _valid(true)
46     {
47         using namespace std;
48         for (Itr itr = childNamesBegin, end = childNamesEnd;
49              itr != end;
50              ++itr)
51             _watched.push_back(makeNode(parent, *itr));
52         listenToProperties(_watched.begin(), _watched.end());
53     }
54     bool isDirty() { return _dirty; }
55     bool isValid() { return _valid; }
56     void unregister_property(SGPropertyNode* node);
57     static void fireChangeListeners();
58 private:
59     virtual void valueChangedImplementation();
60     virtual void valuesChanged();
61     bool _dirty;
62     bool _valid;
63     struct ListenerListSingleton : public Singleton<ListenerListSingleton>
64     {
65         std::vector<SGSharedPtr<AtomicChangeListener> > listeners;
66     };
67 protected:
68     std::vector<SGPropertyNode*> _watched;
69 };
70
71 template<typename T, typename Func>
72 class ExtendedPropListener : public AtomicChangeListener
73 {
74 public:
75     ExtendedPropListener(std::vector<SGPropertyNode*>& nodes, const Func& func,
76                          bool initial = false)
77         : AtomicChangeListener(nodes), _func(func)
78     {
79         if (initial)
80             valuesChanged();
81
82     }
83     template<typename Itr>
84     ExtendedPropListener(SGPropertyNode* parent, Itr childNamesBegin,
85                          Itr childNamesEnd, const Func& func,
86                          bool initial = false)
87         : AtomicChangeListener(parent, childNamesBegin, childNamesEnd),
88           _func(func)
89     {
90         if (initial)
91             valuesChanged();
92     }
93     virtual void valuesChanged()
94     {
95         ExtendedPropertyAdapter<T, std::vector<SGPropertyNode*> > adaptor(_watched);
96         T val = adaptor();
97         _func(val);
98     }
99 private:
100     Func _func;
101 };
102
103 }
104 #endif