globally remove all trailing whitespace from ardour code base.
[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
115                 g_object_unref (rcstyle);
116                 style_changing = false;
117         }
118 }
119
120 void
121 StateButton::avoid_prelight_on_state_changed (Gtk::StateType old_state, GtkWidget* widget)
122 {
123         GtkStateType state = gtk_widget_get_state (widget);
124
125         if (state == GTK_STATE_PRELIGHT) {
126
127                 state_before_prelight = old_state;
128
129
130                 /* avoid PRELIGHT when currently ACTIVE:
131                    if we just went into PRELIGHT, make sure that the colors
132                    match those of whatever state we were in before.
133                 */
134
135                 GtkRcStyle* rcstyle = gtk_widget_get_modifier_style (widget);
136                 GtkStyle* style = gtk_widget_get_style (widget);
137
138                 rcstyle->fg[GTK_STATE_PRELIGHT] = style->fg[old_state];
139                 rcstyle->bg[GTK_STATE_PRELIGHT] = style->bg[old_state];
140                 rcstyle->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags) (GTK_RC_FG|GTK_RC_BG);
141
142                 g_object_ref (rcstyle);
143                 gtk_widget_modify_style (widget, rcstyle);
144
145                 Widget* child = get_child_widget ();
146
147                 if (child) {
148                         gtk_widget_modify_style (GTK_WIDGET(child->gobj()), rcstyle);
149                 }
150
151                 g_object_unref (rcstyle);
152
153         }
154 }
155
156 /* ----------------------------------------------------------------- */
157
158 StatefulToggleButton::StatefulToggleButton ()
159 {
160         is_toggle = true;
161 }
162
163 StatefulToggleButton::StatefulToggleButton (const std::string& label)
164         : ToggleButton (label)
165 {
166         is_toggle = true;
167 }
168
169 void
170 StatefulToggleButton::on_realize ()
171 {
172         ToggleButton::on_realize ();
173
174         _is_realized = true;
175         visual_state++; // to force transition
176         set_visual_state (visual_state - 1);
177 }
178
179 void
180 StatefulButton::on_realize ()
181 {
182         Button::on_realize ();
183
184         _is_realized = true;
185         visual_state++; // to force transition
186         set_visual_state (visual_state - 1);
187 }
188
189 void
190 StatefulToggleButton::on_toggled ()
191 {
192         if (!_self_managed) {
193                 if (get_active()) {
194                         set_state (Gtk::STATE_ACTIVE);
195                 } else {
196                         set_state (Gtk::STATE_NORMAL);
197                 }
198         }
199 }
200
201
202 void
203 StatefulToggleButton::on_style_changed (const Glib::RefPtr<Gtk::Style>& style)
204 {
205         avoid_prelight_on_style_changed (style, GTK_WIDGET(gobj()));
206         Button::on_style_changed (style);
207 }
208
209 void
210 StatefulToggleButton::on_state_changed (Gtk::StateType old_state)
211 {
212         avoid_prelight_on_state_changed (old_state, GTK_WIDGET(gobj()));
213         Button::on_state_changed (old_state);
214 }
215
216 Widget*
217 StatefulToggleButton::get_child_widget ()
218 {
219         return get_child();
220 }
221
222 void
223 StatefulToggleButton::set_widget_name (const std::string& name)
224 {
225         set_name (name);
226         Widget* w = get_child();
227
228         if (w) {
229                 w->set_name (name);
230         }
231 }
232
233 /*--------------------------------------------- */
234
235 StatefulButton::StatefulButton ()
236 {
237 }
238
239 StatefulButton::StatefulButton (const std::string& label)
240         : Button (label)
241 {
242 }
243
244 void
245 StatefulButton::on_style_changed (const Glib::RefPtr<Gtk::Style>& style)
246 {
247         avoid_prelight_on_style_changed (style, GTK_WIDGET(gobj()));
248         Button::on_style_changed (style);
249 }
250
251 void
252 StatefulButton::on_state_changed (Gtk::StateType old_state)
253 {
254         avoid_prelight_on_state_changed (old_state, GTK_WIDGET(gobj()));
255         Button::on_state_changed (old_state);
256 }
257
258 Widget*
259 StatefulButton::get_child_widget ()
260 {
261         return get_child();
262 }
263
264 void
265 StatefulButton::set_widget_name (const std::string& name)
266 {
267         set_name (name);
268         Widget* w = get_child();
269
270         if (w) {
271                 w->set_name (name);
272         }
273 }