MCP: possible support for metering
[ardour.git] / gtk2_ardour / button_joiner.cc
1 #include <iostream>
2 #include <algorithm>
3
4
5 #include <gtkmm/toggleaction.h>
6
7 #include "pbd/compose.h"
8 #include "gtkmm2ext/utils.h"
9 #include "gtkmm2ext/rgb_macros.h"
10
11 #include "ardour_ui.h"
12 #include "button_joiner.h"
13
14 using namespace Gtk;
15
16 ButtonJoiner::ButtonJoiner (const std::string& str, Gtk::Widget& lw, Gtk::Widget& rw, bool central_joiner)
17         : left (lw)
18         , right (rw)
19         , name (str)
20         , active_fill_pattern (0)
21         , inactive_fill_pattern (0)
22         , central_link (central_joiner)
23 {
24         packer.set_homogeneous (true);
25
26         if (central_link) {
27                 packer.set_spacing (20);
28         }
29
30         packer.pack_start (left);
31         packer.pack_start (right);
32         packer.show ();
33
34         /* this alignment is how we position the box that holds the two widgets
35            within our allocation, and how we request more space around them.
36         */
37
38         align.add (packer);
39
40         if (!central_link) {
41                 align.set (0.5, 1.0);
42                 align.set_padding (9, 0, 9, 9);
43         } else {
44                 align.set (0.5, 0.5);
45                 align.set_padding (1, 1, 1, 1);
46         }
47
48         align.show ();
49
50         add (align);
51
52         add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|
53                     Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
54
55         uint32_t border_color;
56         uint32_t r, g, b, a;
57
58         border_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: border end", name));
59         UINT_TO_RGBA (border_color, &r, &g, &b, &a);
60         
61         border_r = r/255.0;
62         border_g = g/255.0;
63         border_b = b/255.0;
64
65         /* child cairo widgets need the color of the inner edge as their
66          * "background"
67          */
68
69         Gdk::Color col;
70         col.set_rgb_p (border_r, border_g, border_b);
71         provide_background_for_cairo_widget (*this, col);
72 }
73
74 ButtonJoiner::~ButtonJoiner ()
75 {
76         if (active_fill_pattern) {
77                 cairo_pattern_destroy (active_fill_pattern);
78                 cairo_pattern_destroy (inactive_fill_pattern);
79         }
80 }
81
82 void
83 ButtonJoiner::render (cairo_t* cr)
84 {
85         double h = get_height();
86         
87         if (!get_active()) {
88                 cairo_set_source (cr, inactive_fill_pattern);
89         } else {
90                 cairo_set_source (cr, active_fill_pattern);
91         }
92
93         if (!central_link) {
94                 /* outer rect */
95                 
96                 Gtkmm2ext::rounded_top_rectangle (cr, 0, 0, get_width(), h, 8);
97                 cairo_fill_preserve (cr);
98                 
99                 /* outer edge */
100                 
101                 cairo_set_line_width (cr, 1.5);
102                 cairo_set_source_rgb (cr, border_r, border_g, border_b);
103                 cairo_stroke (cr);
104                 
105                 /* inner "edge" */
106                 
107                 Gtkmm2ext::rounded_top_rectangle (cr, 8, 8, get_width() - 16, h - 8, 6);
108                 cairo_stroke (cr);
109         } else {
110                 if (get_active()) {
111                         Gtkmm2ext::rounded_top_rectangle (cr, 0, 0, (get_width() - 20.0)/2.0 , h, 8);
112                         cairo_fill_preserve (cr);
113                         
114                         Gtkmm2ext::rounded_top_rectangle (cr, (get_width() - 20.)/2.0 + 20.0, 0.0, 
115                                                           (get_width() - 20.0)/2.0 , h, 8);
116                         cairo_fill_preserve (cr);
117
118                         cairo_move_to (cr, get_width()/2.0 - 10.0, h/2.0);
119                         cairo_set_line_width (cr, 1.5);
120                         cairo_rel_line_to (cr, 20.0, 0.0);
121                         cairo_set_source (cr, active_fill_pattern);
122                         cairo_stroke (cr);
123                 } else {
124                         cairo_arc (cr, get_width()/2.0, h/2.0, 6.0, 0, M_PI*2.0);
125                         cairo_set_line_width (cr, 1.5);
126                         cairo_fill_preserve (cr);
127                         cairo_set_source_rgb (cr, border_r, border_g, border_b);
128                         cairo_stroke (cr);              
129                 }
130         }
131 }
132
133 void
134 ButtonJoiner::on_size_allocate (Allocation& alloc)
135 {
136         CairoWidget::on_size_allocate (alloc);
137         set_colors ();
138 }
139
140 bool
141 ButtonJoiner::on_button_release_event (GdkEventButton* ev)
142 {
143         if (_action) {
144                 _action->activate ();
145         }
146
147         return true;
148 }
149
150 void
151 ButtonJoiner::on_size_request (Gtk::Requisition* r)
152 {
153         CairoWidget::on_size_request (r);
154 }
155
156 void
157 ButtonJoiner::set_related_action (Glib::RefPtr<Action> act)
158 {
159         Gtkmm2ext::Activatable::set_related_action (act);
160
161         if (_action) {
162
163                 action_tooltip_changed ();
164
165                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (_action);
166                 if (tact) {
167                         action_toggled ();
168                         tact->signal_toggled().connect (sigc::mem_fun (*this, &ButtonJoiner::action_toggled));
169                 } 
170
171                 _action->connect_property_changed ("sensitive", sigc::mem_fun (*this, &ButtonJoiner::action_sensitivity_changed));
172                 _action->connect_property_changed ("visible", sigc::mem_fun (*this, &ButtonJoiner::action_visibility_changed));
173                 _action->connect_property_changed ("tooltip", sigc::mem_fun (*this, &ButtonJoiner::action_tooltip_changed));
174         }
175 }
176
177 void
178 ButtonJoiner::action_sensitivity_changed ()
179 {
180         if (_action->property_sensitive ()) {
181                 set_visual_state (Gtkmm2ext::VisualState (visual_state() & ~Gtkmm2ext::Insensitive));
182         } else {
183                 set_visual_state (Gtkmm2ext::VisualState (visual_state() | Gtkmm2ext::Insensitive));
184         }
185         
186 }
187
188 void
189 ButtonJoiner::action_visibility_changed ()
190 {
191         if (_action->property_visible ()) {
192                 show ();
193         } else {
194                 hide ();
195         }
196 }
197
198 void
199 ButtonJoiner::action_tooltip_changed ()
200 {
201         std::string str = _action->property_tooltip().get_value();
202         ARDOUR_UI::instance()->set_tip (*this, str);
203 }
204
205 void
206 ButtonJoiner::action_toggled ()
207 {
208         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (_action);
209
210         if (tact) {
211                 set_active (tact->get_active());
212         }
213 }       
214
215 void
216 ButtonJoiner::set_active_state (Gtkmm2ext::ActiveState s)
217 {
218         bool changed = (_active_state != s);
219         CairoWidget::set_active_state (s);
220         if (changed) {
221                 set_colors ();
222         }
223 }
224
225 void
226 ButtonJoiner::set_colors ()
227 {
228         uint32_t start_color;
229         uint32_t end_color;
230         uint32_t r, g, b, a;
231
232         if (active_fill_pattern) {
233                 cairo_pattern_destroy (active_fill_pattern);
234                 cairo_pattern_destroy (inactive_fill_pattern);
235         }
236
237         active_fill_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
238         inactive_fill_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
239
240         start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start", name));
241         end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end", name));
242         UINT_TO_RGBA (start_color, &r, &g, &b, &a);
243         cairo_pattern_add_color_stop_rgba (inactive_fill_pattern, 0, r/255.0,g/255.0,b/255.0, a/255.0);
244         UINT_TO_RGBA (end_color, &r, &g, &b, &a);
245         cairo_pattern_add_color_stop_rgba (inactive_fill_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0);
246
247         start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start active", name));
248         end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end active", name));
249         UINT_TO_RGBA (start_color, &r, &g, &b, &a);
250         cairo_pattern_add_color_stop_rgba (active_fill_pattern, 0, r/255.0,g/255.0,b/255.0, a/255.0);
251         UINT_TO_RGBA (end_color, &r, &g, &b, &a);
252         cairo_pattern_add_color_stop_rgba (active_fill_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0);
253
254         queue_draw ();
255 }
256