00001 #ifndef SIMGEAR_ATOMICCHANGELISTENER_HXX
00002 #define SIMGEAR_ATOMICCHANGELISTENER_HXX 1
00003
00004 #include <algorithm>
00005 #include <iterator>
00006 #include <vector>
00007
00008 #include <boost/bind.hpp>
00009
00010 #include <simgear/structure/Singleton.hxx>
00011
00012 #include "props.hxx"
00013 #include "ExtendedPropertyAdapter.hxx"
00014
00015 namespace simgear
00016 {
00017
00018 class MultiChangeListener : public SGPropertyChangeListener
00019 {
00020 public:
00021 MultiChangeListener();
00022 template<typename Pitr>
00023 void listenToProperties(Pitr propsBegin, Pitr propsEnd)
00024 {
00025 for (Pitr itr = propsBegin, end = propsEnd; itr != end; ++itr)
00026 (*itr)->addChangeListener(this);
00027 }
00028 private:
00029 void valueChanged(SGPropertyNode* node);
00030 virtual void valueChangedImplementation();
00031
00032 };
00033
00034 class AtomicChangeListener : public MultiChangeListener,
00035 public virtual SGReferenced
00036 {
00037 public:
00038 AtomicChangeListener(std::vector<SGPropertyNode*>& nodes);
00042 template<typename Itr>
00043 AtomicChangeListener(SGPropertyNode* parent, Itr childNamesBegin,
00044 Itr childNamesEnd)
00045 : _dirty(false), _valid(true)
00046 {
00047 using namespace std;
00048 for (Itr itr = childNamesBegin, end = childNamesEnd;
00049 itr != end;
00050 ++itr)
00051 _watched.push_back(makeNode(parent, *itr));
00052 listenToProperties(_watched.begin(), _watched.end());
00053 }
00054 bool isDirty() { return _dirty; }
00055 bool isValid() { return _valid; }
00056 void unregister_property(SGPropertyNode* node);
00057 static void fireChangeListeners();
00058 private:
00059 virtual void valueChangedImplementation();
00060 virtual void valuesChanged();
00061 bool _dirty;
00062 bool _valid;
00063 struct ListenerListSingleton : public Singleton<ListenerListSingleton>
00064 {
00065 std::vector<SGSharedPtr<AtomicChangeListener> > listeners;
00066 };
00067 protected:
00068 std::vector<SGPropertyNode*> _watched;
00069 };
00070
00071 template<typename T, typename Func>
00072 class ExtendedPropListener : public AtomicChangeListener
00073 {
00074 public:
00075 ExtendedPropListener(std::vector<SGPropertyNode*>& nodes, const Func& func,
00076 bool initial = false)
00077 : AtomicChangeListener(nodes), _func(func)
00078 {
00079 if (initial)
00080 valuesChanged();
00081
00082 }
00083 template<typename Itr>
00084 ExtendedPropListener(SGPropertyNode* parent, Itr childNamesBegin,
00085 Itr childNamesEnd, const Func& func,
00086 bool initial = false)
00087 : AtomicChangeListener(parent, childNamesBegin, childNamesEnd),
00088 _func(func)
00089 {
00090 if (initial)
00091 valuesChanged();
00092 }
00093 virtual void valuesChanged()
00094 {
00095 ExtendedPropertyAdapter<T, std::vector<SGPropertyNode*> > adaptor(_watched);
00096 T val = adaptor();
00097 _func(val);
00098 }
00099 private:
00100 Func _func;
00101 };
00102
00103 }
00104 #endif