]> git.mxchange.org Git - simgear.git/blob - simgear/props/PropertyBasedElement.cxx
canvas::Layout: support for contents margins.
[simgear.git] / simgear / props / PropertyBasedElement.cxx
1 // Base class for elements of 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 "PropertyBasedElement.hxx"
20 #include <boost/algorithm/string/predicate.hpp>
21
22 namespace simgear
23 {
24
25   //----------------------------------------------------------------------------
26   PropertyBasedElement::PropertyBasedElement(SGPropertyNode* node):
27     _node(node)
28   {
29     _node->addChangeListener(this);
30   }
31
32   //----------------------------------------------------------------------------
33   PropertyBasedElement::~PropertyBasedElement()
34   {
35     onDestroy();
36     removeListener();
37   }
38
39   //----------------------------------------------------------------------------
40   void PropertyBasedElement::removeListener()
41   {
42     if( _node )
43       _node->removeChangeListener(this);
44   }
45
46   //----------------------------------------------------------------------------
47   void PropertyBasedElement::destroy()
48   {
49     if( !_node )
50       return;
51
52     // TODO check if really not in use anymore
53     if( _node->getParent() )
54       _node->getParent()
55            ->removeChild(_node->getName(), _node->getIndex());
56   }
57
58   //----------------------------------------------------------------------------
59   SGConstPropertyNode_ptr PropertyBasedElement::getProps() const
60   {
61     return _node;
62   }
63
64   //----------------------------------------------------------------------------
65   SGPropertyNode_ptr PropertyBasedElement::getProps()
66   {
67     return _node;
68   }
69
70   //----------------------------------------------------------------------------
71   bool PropertyBasedElement::hasDataProp(const std::string& name) const
72   {
73     return getDataProp<SGPropertyNode*>(name) != NULL;
74   }
75
76   //----------------------------------------------------------------------------
77   void PropertyBasedElement::removeDataProp(const std::string& name)
78   {
79     SGPropertyNode* node = getDataProp<SGPropertyNode*>(name);
80     if( node )
81       _node->removeChild(node);
82   }
83
84   //----------------------------------------------------------------------------
85   static const std::string DATA_PREFIX("data-");
86
87   //----------------------------------------------------------------------------
88   std::string PropertyBasedElement::dataPropToAttrName(const std::string& name)
89   {
90     // http://www.w3.org/TR/html5/dom.html#attr-data-*
91     //
92     // 3. Insert the string data- at the front of name.
93
94     std::string attr_name;
95     for( std::string::const_iterator cur = name.begin();
96                                      cur != name.end();
97                                    ++cur )
98     {
99       // If name contains a "-" (U+002D) character followed by a lowercase ASCII
100       // letter, throw a SyntaxError exception and abort these steps.
101       if( *cur == '-' )
102       {
103         std::string::const_iterator next = cur + 1;
104         if( next != name.end() && islower(*next) )
105           return std::string();
106       }
107
108       // For each uppercase ASCII letter in name, insert a "-" (U+002D)
109       // character before the character and replace the character with the same
110       // character converted to ASCII lowercase.
111       if( isupper(*cur) )
112       {
113         attr_name.push_back('-');
114         attr_name.push_back( tolower(*cur) );
115       }
116       else
117         attr_name.push_back( *cur );
118     }
119     return DATA_PREFIX + attr_name;
120   }
121
122   //----------------------------------------------------------------------------
123   std::string PropertyBasedElement::attrToDataPropName(const std::string& name)
124   {
125     // http://www.w3.org/TR/html5/dom.html#attr-data-*
126     //
127     // For each "-" (U+002D) character in the name that is followed by a
128     // lowercase ASCII letter, remove the "-" (U+002D) character and replace the
129     // character that followed it by the same character converted to ASCII
130     // uppercase.
131
132     if( !boost::starts_with(name, DATA_PREFIX) )
133       return std::string();
134
135     std::string data_name;
136     for( std::string::const_iterator cur = name.begin() + DATA_PREFIX.length();
137                                      cur != name.end();
138                                    ++cur )
139     {
140       std::string::const_iterator next = cur + 1;
141       if( *cur == '-' && next != name.end() && islower(*next) )
142       {
143         data_name.push_back( toupper(*next) );
144         cur = next;
145       }
146       else
147         data_name.push_back(*cur);
148     }
149     return data_name;
150   }
151
152 } // namespace simgear