1 /*
2 * this file is part of the oxygen gtk engine
3 * Copyright (c) 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
4 *
5 * This  library is free  software; you can  redistribute it and/or
6 * modify it  under  the terms  of the  GNU Lesser  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 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License  along  with  this library;  if not,  write to  the Free
17 * Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 */
20 
21 #include "oxygengtkrc.h"
22 
23 #include <gtk/gtk.h>
24 #include <algorithm>
25 #include <cassert>
26 
27 namespace Oxygen
28 {
29 
30     //_________________________________________________
31     const std::string Gtk::RC::_headerSectionName = "__head__";
32     const std::string Gtk::RC::_rootSectionName = "__root__";
33     const std::string Gtk::RC::_defaultSectionName = "oxygen-default-internal";
34 
35     //_________________________________________________
commit(void)36     void Gtk::RC::commit( void )
37     {
38         gtk_rc_parse_string( toString().c_str() );
39         clear();
40     }
41 
42     //_________________________________________________
merge(const Gtk::RC & other)43     void Gtk::RC::merge( const Gtk::RC& other )
44     {
45 
46         // loop over sections in other
47         for( Section::List::const_iterator iter = other._sections.begin(); iter != other._sections.end(); ++iter )
48         {
49             Section::List::iterator sectionIter = std::find_if( _sections.begin(), _sections.end(), Section::SameNameFTor( *iter ) );
50             if( sectionIter == _sections.end() ) _sections.push_back( *iter );
51             else {
52 
53                 assert( sectionIter->_parent == iter->_parent );
54                 sectionIter->add( iter->_content );
55 
56             }
57 
58         }
59 
60         return;
61     }
62 
63     //_________________________________________________
addSection(const std::string & name,const std::string & parent)64     void Gtk::RC::addSection( const std::string& name, const std::string& parent )
65     {
66         if( std::find( _sections.begin(), _sections.end(), name ) != _sections.end() )
67         {
68 
69             std::cerr << "Gtk::RC::addSection - section named " << name << " already exists" << std::endl;
70 
71         } else {
72 
73             _sections.push_back( Section( name, parent ) );
74 
75         }
76 
77         setCurrentSection( name );
78 
79     }
80 
81     //_________________________________________________
addToSection(const std::string & name,const std::string & content)82     void Gtk::RC::addToSection( const std::string& name, const std::string& content )
83     {
84         Section::List::iterator iter( std::find( _sections.begin(), _sections.end(), name ) );
85         if( iter == _sections.end() )
86         {
87             std::cerr << "Gtk::RC::addToSection - unable to find section named " << name << std::endl;
88             return;
89         }
90 
91         iter->add( content );
92     }
93 
94     //_________________________________________________
matchClassToSection(const std::string & content,const std::string & name)95     void Gtk::RC::matchClassToSection( const std::string& content, const std::string& name )
96     {
97         if( std::find( _sections.begin(), _sections.end(), name ) == _sections.end() )
98         { std::cerr << "Gtk::RC::matchClassToSection - unable to find section named " << name << std::endl; }
99 
100         std::ostringstream what;
101         what << "class \"" << content << "\" style \"" << name << "\"";
102         addToRootSection( what.str() );
103     }
104 
105     //_________________________________________________
matchWidgetToSection(const std::string & content,const std::string & name)106     void Gtk::RC::matchWidgetToSection( const std::string& content, const std::string& name )
107     {
108         if( std::find( _sections.begin(), _sections.end(), name ) == _sections.end() )
109         { std::cerr << "Gtk::RC::matchWidgetToSection - unable to find section named " << name << std::endl; }
110 
111         std::ostringstream what;
112         what << "widget \"" << content << "\" style \"" << name << "\"";
113         addToRootSection( what.str() );
114     }
115 
116     //_________________________________________________
matchWidgetClassToSection(const std::string & content,const std::string & name)117     void Gtk::RC::matchWidgetClassToSection( const std::string& content, const std::string& name )
118     {
119         if( std::find( _sections.begin(), _sections.end(), name ) == _sections.end() )
120         { std::cerr << "Gtk::RC::matchWidgetClassToSection - unable to find section named " << name << std::endl; }
121 
122         std::ostringstream what;
123         what << "widget_class \"" << content << "\" style \"" << name << "\"";
124         addToRootSection( what.str() );
125     }
126 
127     //_________________________________________________
setCurrentSection(const std::string & name)128     void Gtk::RC::setCurrentSection( const std::string& name )
129     {
130         if( std::find( _sections.begin(), _sections.end(), name ) == _sections.end() )
131         {
132 
133             std::cerr << "Gtk::RC::setCurrentSection - unable to find section named " << name << std::endl;
134             return;
135 
136         } else {
137 
138             _currentSection = name;
139 
140         }
141     }
142 
143     //_________________________________________________
add(const Gtk::RC::Section::ContentList & content)144     void Gtk::RC::Section::add( const Gtk::RC::Section::ContentList& content )
145     {
146         for( ContentList::const_iterator iter = content.begin(); iter != content.end(); ++iter )
147         {
148             if( std::find( _content.begin(), _content.end(), *iter ) == _content.end() )
149             { _content.push_back( *iter ); }
150         }
151     }
152 
153     namespace Gtk
154     {
155         //_______________________________________________________________________
operator <<(std::ostream & out,const RC::Section & section)156         std::ostream& operator << (std::ostream& out, const RC::Section& section )
157         {
158             if( section._name == RC::_rootSectionName || section._name == RC::_headerSectionName )
159             {
160 
161                 // add contents
162                 for( RC::Section::ContentList::const_iterator iter = section._content.begin(); iter != section._content.end(); ++iter )
163                 { out << *iter << std::endl; }
164 
165             } else {
166 
167                 out << "style \"" << section._name << "\"";
168                 if( !section._parent.empty() ) out << " = \"" << section._parent << "\"";
169                 out << std::endl;
170                 out << "{" << std::endl;
171 
172                 // add contents
173                 for( RC::Section::ContentList::const_iterator iter = section._content.begin(); iter != section._content.end(); ++iter )
174                 { out << *iter << std::endl; }
175 
176                 out << "}" << std::endl;
177 
178             }
179 
180             return out;
181         }
182 
183         //_______________________________________________________________________
operator <<(std::ostream & out,const RC & rc)184         std::ostream& operator << (std::ostream& out, const RC& rc )
185         {
186             // dump header section
187             RC::Section::List::const_iterator iter( std::find( rc._sections.begin(), rc._sections.end(), RC::_headerSectionName ) );
188             assert( iter != rc._sections.end() );
189             out << *iter << std::endl;
190 
191             // dump all section except root
192             for( RC::Section::List::const_iterator iter = rc._sections.begin(); iter != rc._sections.end(); ++iter )
193             { if( !(*iter == RC::_rootSectionName || *iter == RC::_headerSectionName ) ) out << *iter << std::endl; }
194 
195             // dump root section
196             iter = std::find( rc._sections.begin(), rc._sections.end(), RC::_rootSectionName );
197             assert( iter != rc._sections.end() );
198             out << *iter << std::endl;
199 
200             return out;
201         }
202 
203     }
204 }
205