]> git.mxchange.org Git - simgear.git/blob - simgear/props/PropertyBasedMgr.cxx
Canvas: clear elements in shutdown()
[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     _elements.clear();
41   }
42
43   //----------------------------------------------------------------------------
44   void PropertyBasedMgr::update(double delta_time_sec)
45   {
46     for( size_t i = 0; i < _elements.size(); ++i )
47       if( _elements[i] )
48         _elements[i]->update(delta_time_sec);
49   }
50
51   //----------------------------------------------------------------------------
52   PropertyBasedElementPtr
53   PropertyBasedMgr::createElement(const std::string& name)
54   {
55     SGPropertyNode* node = _props->addChild(_name_elements, 0, false);
56     if( !name.empty() )
57       node->setStringValue("name", name);
58
59     return getElement( node->getIndex() );
60   }
61
62   //----------------------------------------------------------------------------
63   PropertyBasedElementPtr PropertyBasedMgr::getElement(size_t index) const
64   {
65     if( index >= _elements.size() )
66       return PropertyBasedElementPtr();
67
68     return _elements[index];
69   }
70
71   //----------------------------------------------------------------------------
72   PropertyBasedElementPtr
73   PropertyBasedMgr::getElement(const std::string& name) const
74   {
75     if( name.empty() )
76       return PropertyBasedElementPtr();
77
78     BOOST_FOREACH(PropertyBasedElementPtr el, _elements)
79       if( el->getProps()->getStringValue("name") == name )
80         return el;
81
82     return PropertyBasedElementPtr();
83   }
84
85   //----------------------------------------------------------------------------
86   const SGPropertyNode* PropertyBasedMgr::getPropertyRoot() const
87   {
88     return _props;
89   }
90
91   //----------------------------------------------------------------------------
92   PropertyBasedMgr::PropertyBasedMgr( SGPropertyNode_ptr props,
93                                       const std::string& name_elements,
94                                       ElementFactory element_factory ):
95     _props( props ),
96     _name_elements( name_elements ),
97     _element_factory( element_factory )
98   {
99
100   }
101
102   //----------------------------------------------------------------------------
103   PropertyBasedMgr::~PropertyBasedMgr()
104   {
105
106   }
107
108   //----------------------------------------------------------------------------
109   void PropertyBasedMgr::childAdded( SGPropertyNode * parent,
110                                      SGPropertyNode * child )
111   {
112     if( parent != _props || child->getNameString() != _name_elements )
113       return;
114
115     size_t index = child->getIndex();
116
117     if( index >= _elements.size() )
118     {
119       if( index > _elements.size() )
120         SG_LOG
121         (
122           SG_GENERAL,
123           SG_WARN,
124           "Skipping unused " << _name_elements << " slot(s)!"
125         );
126
127       _elements.resize(index + 1);
128     }
129     else if( _elements[index] )
130     {
131       SG_LOG
132       (
133         SG_GENERAL,
134         SG_WARN,
135         _name_elements << "[" << index << "] already exists!"
136       );
137
138       // Give anything holding a reference to this element to release it
139       _elements[index]->onDestroy();
140     }
141
142     PropertyBasedElementPtr el = _element_factory(child);
143     el->setSelf( el );
144     _elements[index] = el;
145     elementCreated( el );
146   }
147
148   //----------------------------------------------------------------------------
149   void PropertyBasedMgr::childRemoved( SGPropertyNode * parent,
150                                        SGPropertyNode * child )
151   {
152     if( parent != _props )
153       return child->fireChildrenRemovedRecursive();
154     else if( child->getNameString() != _name_elements )
155       return;
156
157     size_t index = child->getIndex();
158
159     if( index >= _elements.size() )
160       SG_LOG
161       (
162         SG_GENERAL,
163         SG_WARN,
164         "can't removed unknown " << _name_elements << "[" << index << "]!"
165       );
166     else
167     {
168       // remove the element...
169       _elements[index]->onDestroy();
170       _elements[index].reset();
171     }
172   }
173
174 } // namespace simgear