]> git.mxchange.org Git - flightgear.git/blob - src/Canvas/property_helper.cxx
Refactor PropertyBasedElement and Manager
[flightgear.git] / src / Canvas / property_helper.cxx
1 // Some helper functions for accessing the property tree
2 //
3 // Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18
19 #include "property_helper.hxx"
20
21 #include <boost/algorithm/string/predicate.hpp>
22 #include <boost/algorithm/string/trim.hpp>
23 #include <boost/lexical_cast.hpp>
24 #include <boost/tokenizer.hpp>
25
26 #include <cassert>
27
28 namespace canvas
29 {
30   //----------------------------------------------------------------------------
31   std::vector<float> splitAndConvert(const char del[], const std::string& str)
32   {
33     std::vector<float> values;
34     size_t pos = 0;
35     for(;;)
36     {
37       pos = str.find_first_not_of(del, pos);
38       if( pos == std::string::npos )
39         break;
40
41       char *end = 0;
42       float val = strtod(&str[pos], &end);
43       if( end == &str[pos] || !end )
44         break;
45
46       values.push_back(val);
47       pos = end - &str[0];
48     }
49     return values;
50   }
51
52   //----------------------------------------------------------------------------
53   osg::Vec4 parseColor(std::string str)
54   {
55     boost::trim(str);
56     osg::Vec4 color(0,0,0,1);
57
58     if( str.empty() )
59       return color;
60
61     // #rrggbb
62     if( str[0] == '#' )
63     {
64       const int offsets[] = {2,2,2};
65       const boost::offset_separator hex_separator( boost::begin(offsets),
66                                                    boost::end(offsets) );
67       typedef boost::tokenizer<boost::offset_separator> offset_tokenizer;
68       offset_tokenizer tokens(str.begin() + 1, str.end(), hex_separator);
69
70       int comp = 0;
71       for( offset_tokenizer::const_iterator tok = tokens.begin();
72            tok != tokens.end() && comp < 4;
73            ++tok, ++comp )
74       {
75         color._v[comp] = strtol(std::string(*tok).c_str(), 0, 16) / 255.f;
76       }
77     }
78     // rgb(r,g,b)
79     // rgba(r,g,b,a)
80     else if( boost::ends_with(str, ")") )
81     {
82       const std::string RGB = "rgb(",
83                         RGBA = "rgba(";
84       size_t pos;
85       if( boost::starts_with(str, RGB) )
86         pos = RGB.length();
87       else if( boost::starts_with(str, RGBA) )
88         pos = RGBA.length();
89       else
90         return color;
91
92       typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
93       const boost::char_separator<char> del(", \t\n");
94
95       tokenizer tokens(str.begin() + pos, str.end() - 1, del);
96       int comp = 0;
97       for( tokenizer::const_iterator tok = tokens.begin();
98            tok != tokens.end() && comp < 4;
99            ++tok, ++comp )
100       {
101         color._v[comp] = boost::lexical_cast<float>(*tok)
102                        // rgb = [0,255], a = [0,1]
103                        / (comp < 3 ? 255 : 1);
104       }
105     }
106     else
107       SG_LOG(SG_GENERAL, SG_WARN, "Unknown color: " << str);
108
109     return color;
110   }
111
112   //----------------------------------------------------------------------------
113   void linkColorNodes( const char* name,
114                        SGPropertyNode* parent,
115                        std::vector<SGPropertyNode_ptr>& nodes,
116                        const osg::Vec4& def )
117   {
118     static const char* channels[] = {"red", "green", "blue", "alpha"};
119     static const size_t num_channels = sizeof(channels)/sizeof(channels[0]);
120
121     assert(name);
122     assert(parent);
123
124     // Don't tie to allow the usage of aliases
125     SGPropertyNode_ptr color = parent->getChild(name, 0, true);
126
127     // We need to be carefull do not get any unitialized nodes or null pointers
128     // because while creating the node a valueChanged event will be triggered.
129     nodes.clear();
130     nodes.reserve(num_channels);
131
132     for( size_t i = 0; i < num_channels; ++i )
133       nodes.push_back( getChildDefault(color, channels[i], def[i]) );
134   }
135 }