tweak search path for export profiles
[ardour.git] / libs / gtkmm2ext / stateful_button.cc
1 /*
2     Copyright (C) 2000-2007 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <string>
21 #include <iostream>
22
23
24 #include <gtkmm/main.h>
25
26 #include <gtkmm2ext/stateful_button.h>
27
28 using namespace Gtk;
29 using namespace Glib;
30 using namespace Gtkmm2ext;
31 using namespace std;
32
33 StateButton::StateButton () 
34         : visual_state (0)
35         , _self_managed (false)
36         , _is_realized (false)
37         , style_changing (false)
38         , state_before_prelight (Gtk::STATE_NORMAL)
39         , is_toggle (false)
40 {
41 }
42
43 void
44 StateButton::set_visual_state (int n)
45 {
46         if (!_is_realized) {
47                 /* not yet realized */
48                 visual_state = n;
49                 return;
50         }
51
52         if (n == visual_state) {
53                 return;
54         }
55
56         string name = get_widget_name ();
57         name = name.substr (0, name.find_last_of ('-'));
58
59         switch (n) {
60         case 0:
61                 /* relax */
62                 break;
63         case 1:
64                 name += "-active";
65                 break;
66
67         case 2:
68                 name += "-alternate";
69                 break;
70
71         case 3:
72                 name += "-alternate2";
73                 break;
74         }
75
76         set_widget_name (name);
77         visual_state = n;
78 }
79
80 void
81 StateButton::avoid_prelight_on_style_changed (const Glib::RefPtr<Gtk::Style>& /* old_style */,  GtkWidget* widget)
82 {
83         /* don't go into an endless recursive loop if we're changing
84            the style in response to an existing style change.
85         */
86
87         if (style_changing) {
88                 return;
89         }
90         
91         if (gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT) {
92                 
93                 /* avoid PRELIGHT: make sure that the prelight colors in this new style match
94                    the colors of the new style in whatever state we were in
95                    before we switched to prelight.
96                 */
97
98                 GtkRcStyle* rcstyle = gtk_widget_get_modifier_style (widget);
99                 GtkStyle* style = gtk_widget_get_style (widget);
100
101                 rcstyle->fg[GTK_STATE_PRELIGHT] = style->fg[state_before_prelight];
102                 rcstyle->bg[GTK_STATE_PRELIGHT] = style->bg[state_before_prelight];
103                 rcstyle->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags) (GTK_RC_FG|GTK_RC_BG);
104                 
105                 style_changing = true;
106                 g_object_ref (rcstyle);
107                 gtk_widget_modify_style (widget, rcstyle);
108
109                 Widget* child = get_child_widget();
110                 if (child) {
111                         gtk_widget_modify_style (GTK_WIDGET(child->gobj()), rcstyle);
112                 }
113
114                 g_object_unref (rcstyle);
115                 style_changing = false;
116         }
117 }
118
119 void
120 StateButton::avoid_prelight_on_state_changed (Gtk::StateType old_state, GtkWidget* widget)
121 {
122         GtkStateType state = gtk_widget_get_state (widget);
123
124         if (state == GTK_STATE_PRELIGHT) {
125
126                 state_before_prelight = old_state;
127                 
128                 
129                 /* avoid PRELIGHT when currently ACTIVE: 
130                    if we just went into PRELIGHT, make sure that the colors 
131                    match those of whatever state we were in before. 
132                 */
133                 
134                 GtkRcStyle* rcstyle = gtk_widget_get_modifier_style (widget);
135                 GtkStyle* style = gtk_widget_get_style (widget);
136                 
137                 rcstyle->fg[GTK_STATE_PRELIGHT] = style->fg[old_state];
138                 rcstyle->bg[GTK_STATE_PRELIGHT] = style->bg[old_state];
139                 rcstyle->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags) (GTK_RC_FG|GTK_RC_BG);
140                 
141                 g_object_ref (rcstyle);
142                 gtk_widget_modify_style (widget, rcstyle);
143
144                 Widget* child = get_child_widget ();
145
146                 if (child) {
147                         gtk_widget_modify_style (GTK_WIDGET(child->gobj()), rcstyle);
148                 }
149
150                 g_object_unref (rcstyle);
151
152         }
153 }
154
155 /* ----------------------------------------------------------------- */
156
157 StatefulToggleButton::StatefulToggleButton ()
158 {
159         is_toggle = true;
160 }
161
162 StatefulToggleButton::StatefulToggleButton (const std::string& label)
163         : ToggleButton (label)
164 {
165         is_toggle = true;
166 }
167
168 void
169 StatefulToggleButton::on_realize ()
170 {
171         ToggleButton::on_realize ();
172
173         _is_realized = true;
174         visual_state++; // to force transition
175         set_visual_state (visual_state - 1);
176 }
177
178 void
179 StatefulButton::on_realize ()
180 {
181         Button::on_realize ();
182
183         _is_realized = true;
184         visual_state++; // to force transition
185         set_visual_state (visual_state - 1);
186 }
187
188 void
189 StatefulToggleButton::on_toggled ()
190 {
191         if (!_self_managed) {
192                 if (get_active()) {
193                         set_state (Gtk::STATE_ACTIVE);
194                 } else {
195                         set_state (Gtk::STATE_NORMAL);
196                 }
197         }
198 }
199
200
201 void
202 StatefulToggleButton::on_style_changed (const Glib::RefPtr<Gtk::Style>& style)
203 {
204         avoid_prelight_on_style_changed (style, GTK_WIDGET(gobj()));
205         Button::on_style_changed (style);
206 }       
207
208 void
209 StatefulToggleButton::on_state_changed (Gtk::StateType old_state)
210 {
211         avoid_prelight_on_state_changed (old_state, GTK_WIDGET(gobj()));
212         Button::on_state_changed (old_state);
213 }       
214
215 Widget*
216 StatefulToggleButton::get_child_widget ()
217 {
218         return get_child();
219 }
220
221 void
222 StatefulToggleButton::set_widget_name (const std::string& name)
223 {
224         set_name (name); 
225         Widget* w = get_child();
226
227         if (w) {
228                 w->set_name (name); 
229         } 
230 }
231
232 /*--------------------------------------------- */
233
234 StatefulButton::StatefulButton ()
235 {
236 }
237
238 StatefulButton::StatefulButton (const std::string& label)
239         : Button (label)
240 {
241 }
242
243 void
244 StatefulButton::on_style_changed (const Glib::RefPtr<Gtk::Style>& style)
245 {
246         avoid_prelight_on_style_changed (style, GTK_WIDGET(gobj()));
247         Button::on_style_changed (style);
248 }       
249
250 void
251 StatefulButton::on_state_changed (Gtk::StateType old_state)
252 {
253         avoid_prelight_on_state_changed (old_state, GTK_WIDGET(gobj()));
254         Button::on_state_changed (old_state);
255 }       
256
257 Widget*
258 StatefulButton::get_child_widget ()
259 {
260         return get_child();
261 }
262
263 void
264 StatefulButton::set_widget_name (const std::string& name)
265 {
266         set_name (name); 
267         Widget* w = get_child();
268
269         if (w) {
270                 w->set_name (name); 
271         } 
272 }