]> git.mxchange.org Git - simgear.git/blob - simgear/props/PropertyBasedMgr.cxx
Restructure Canvas/PropertyBasedElement
[simgear.git] / simgear / props / PropertyBasedMgr.cxx
1 // Base class for property controlled subsystems
2 //
3 // Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Library General Public License for more details.
14 //
15 // You should have received a copy of the GNU Library General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
18
19 #include "PropertyBasedMgr.hxx"
20
21 #include <boost/foreach.hpp>
22
23 #include <stdexcept>
24 #include <string>
25
26 namespace simgear
27 {
28
29   //----------------------------------------------------------------------------
30   void PropertyBasedMgr::init()
31   {
32     _props->addChangeListener(this);
33     _props->fireCreatedRecursive();
34   }
35
36   //----------------------------------------------------------------------------
37   void PropertyBasedMgr::shutdown()
38   {
39     _props->removeChangeListener(this);
40   }
41
42   //----------------------------------------------------------------------------
43   void PropertyBasedMgr::update(double delta_time_sec)
44   {
45     for( size_t i = 0; i < _elements.size(); ++i )
46       if( _elements[i] )
47         _elements[i]->update(delta_time_sec);
48   }
49
50   //----------------------------------------------------------------------------
51   PropertyBasedElementPtr
52   PropertyBasedMgr::createElement(const std::string& name)
53   {
54     SGPropertyNode* node = _props->addChild(_name_elements, 0, false);
55     if( !name.empty() )
56       node->setStringValue("name", name);
57
58     return getElement( node->getIndex() );
59   }
60
61   //----------------------------------------------------------------------------
62   PropertyBasedElementPtr PropertyBasedMgr::getElement(size_t index) const
63   {
64     if( index >= _elements.size() )
65       return PropertyBasedElementPtr();
66
67     return _elements[index];
68   }
69
70   //----------------------------------------------------------------------------
71   PropertyBasedElementPtr
72   PropertyBasedMgr::getElement(const std::string& name) const
73   {
74     if( name.empty() )
75       return PropertyBasedElementPtr();
76
77     BOOST_FOREACH(PropertyBasedElementPtr el, _elements)
78       if( el->getProps()->getStringValue("name") == name )
79         return el;
80
81     return PropertyBasedElementPtr();
82   }
83
84   //----------------------------------------------------------------------------
85   const SGPropertyNode* PropertyBasedMgr::getPropertyRoot() const
86   {
87     return _props;
88   }
89
90   //----------------------------------------------------------------------------
91   PropertyBasedMgr::PropertyBasedMgr( SGPropertyNode_ptr props,
92                                       const std::string& name_elements,
93                                       ElementFactory element_factory ):
94     _props( props ),
95     _name_elements( name_elements ),
96     _element_factory( element_factory )
97   {
98
99   }
100
101   //----------------------------------------------------------------------------
102   PropertyBasedMgr::~PropertyBasedMgr()
103   {
104
105   }
106
107   //----------------------------------------------------------------------------
108   void PropertyBasedMgr::childAdded( SGPropertyNode * parent,
109                                      SGPropertyNode * child )
110   {
111     if( parent != _props || child->getNameString() != _name_elements )
112       return;
113
114     size_t index = child->getIndex();
115
116     if( index >= _elements.size() )
117     {
118       if( index > _elements.size() )
119         SG_LOG
120         (
121           SG_GENERAL,
122           SG_WARN,
123           "Skipping unused " << _name_elements << " slot(s)!"
124         );
125
126       _elements.resize(index + 1);
127     }
128     else if( _elements[index] )
129     {
130       SG_LOG
131       (
132         SG_GENERAL,
133         SG_WARN,
134         _name_elements << "[" << index << "] already exists!"
135       );
136
137       // Give anything holding a reference to this element to release it
138       _elements[index]->onDestroy();
139     }
140
141     PropertyBasedElementPtr el = _element_factory(child);
142     el->setSelf( el );
143     _elements[index] = el;
144     elementCreated( el );
145   }
146
147   //----------------------------------------------------------------------------
148   void PropertyBasedMgr::childRemoved( SGPropertyNode * parent,
149                                        SGPropertyNode * child )
150   {
151     if( parent != _props )
152       return child->fireChildrenRemovedRecursive();
153     else if( child->getNameString() != _name_elements )
154       return;
155
156     size_t index = child->getIndex();
157
158     if( index >= _elements.size() )
159       SG_LOG
160       (
161         SG_GENERAL,
162         SG_WARN,
163         "can't removed unknown " << _name_elements << "[" << index << "]!"
164       );
165     else
166     {
167       // remove the element...
168       _elements[index]->onDestroy();
169       _elements[index].reset();
170     }
171   }
172
173 } // namespace simgear