destroy splash when hiding it to workaround odd bug on OS X where the window will...
[ardour.git] / gtk2_ardour / ardour_button.cc
1 /*
2     Copyright (C) 2010 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 <iostream>
21 #include <cmath>
22 #include <algorithm>
23
24 #include <pangomm/layout.h>
25
26 #include "pbd/compose.h"
27 #include "pbd/error.h"
28
29 #include "gtkmm2ext/utils.h"
30 #include "gtkmm2ext/rgb_macros.h"
31 #include "gtkmm2ext/gui_thread.h"
32
33 #include "ardour/rc_configuration.h" // for widget prelight preference
34
35 #include "ardour_button.h"
36 #include "ardour_ui.h"
37 #include "global_signals.h"
38
39 #include "i18n.h"
40
41 using namespace Gdk;
42 using namespace Gtk;
43 using namespace Glib;
44 using namespace PBD;
45 using std::max;
46 using std::min;
47 using namespace std;
48
49 ArdourButton::Element ArdourButton::default_elements = ArdourButton::Element (ArdourButton::Edge|ArdourButton::Body|ArdourButton::Text);
50 ArdourButton::Element ArdourButton::led_default_elements = ArdourButton::Element (ArdourButton::default_elements|ArdourButton::Indicator);
51 ArdourButton::Element ArdourButton::just_led_default_elements = ArdourButton::Element (ArdourButton::Edge|ArdourButton::Body|ArdourButton::Indicator);
52 bool ArdourButton::_flat_buttons = false;
53
54 ArdourButton::ArdourButton (Element e)
55         : _elements (e)
56         , _tweaks (Tweaks (0))
57         , _text_width (0)
58         , _text_height (0)
59         , _diameter (11.0)
60         , _corner_radius (5.0)
61         , _corner_mask (0xf)
62         , edge_pattern (0)
63         , active_pattern (0)
64         , inactive_pattern (0)
65         , led_inset_pattern (0)
66         , reflection_pattern (0)
67         , _led_rect (0)
68         , _act_on_release (true)
69         , _led_left (false)
70         , _fixed_diameter (true)
71         , _distinct_led_click (false)
72         , _hovering (false)
73 {
74         ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler));
75 }
76
77 ArdourButton::ArdourButton (const std::string& str, Element e)
78         : _elements (e)
79         , _tweaks (Tweaks (0))
80         , _text_width (0)
81         , _text_height (0)
82         , _diameter (11.0)
83         , _corner_radius (9.0)
84         , _corner_mask (0xf)
85         , edge_pattern (0)
86         , active_pattern (0)
87         , inactive_pattern (0)
88         , led_inset_pattern (0)
89         , reflection_pattern (0)
90         , _led_rect (0)
91         , _act_on_release (true)
92         , _led_left (false)
93         , _fixed_diameter (true)
94         , _distinct_led_click (false)
95         , _hovering (false)
96 {
97         set_text (str);
98 }
99
100 ArdourButton::~ArdourButton()
101 {
102         delete _led_rect;
103
104         if (edge_pattern) {
105                 cairo_pattern_destroy (edge_pattern);
106         }
107
108         if (active_pattern) {
109                 cairo_pattern_destroy (active_pattern);
110         }
111
112         if (inactive_pattern) {
113                 cairo_pattern_destroy (inactive_pattern);
114         }
115 }
116
117 void
118 ArdourButton::set_text (const std::string& str)
119 {
120         _text = str;
121
122         if (!_layout && !_text.empty()) {
123                 _layout = Pango::Layout::create (get_pango_context());
124         } 
125
126         if (_layout) {
127                 _layout->set_text (str);
128         }
129
130         queue_resize ();
131 }
132
133 void
134 ArdourButton::set_markup (const std::string& str)
135 {
136         _text = str;
137
138         if (!_layout) {
139                 _layout = Pango::Layout::create (get_pango_context());
140         } 
141
142         _layout->set_text (str);
143         queue_resize ();
144 }
145
146 void
147 ArdourButton::render (cairo_t* cr)
148 {
149         void (*rounded_function)(cairo_t*, double, double, double, double, double);
150
151         switch (_corner_mask) {
152         case 0x1: /* upper left only */
153                 rounded_function = Gtkmm2ext::rounded_top_left_rectangle;
154                 break;
155         case 0x2: /* upper right only */
156                 rounded_function = Gtkmm2ext::rounded_top_right_rectangle;
157                 break;
158         case 0x3: /* upper only */
159                 rounded_function = Gtkmm2ext::rounded_top_rectangle;
160                 break;
161                 /* should really have functions for lower right, lower left,
162                    lower only, but for now, we don't
163                 */
164         default:
165                 rounded_function = Gtkmm2ext::rounded_rectangle;
166         }
167
168         if (!_fixed_diameter) {
169                 _diameter = std::min (get_width(), get_height());
170         }
171
172         if (_elements & Edge) {
173                 rounded_function (cr, 0, 0, get_width(), get_height(), _corner_radius);
174                 cairo_set_source (cr, edge_pattern);
175                 cairo_fill (cr);
176         }
177
178         if (_elements & Body) {
179                 if (_elements & Edge) {
180                         rounded_function (cr, 1, 1, get_width()-2, get_height()-2, _corner_radius - 1.0);
181                 } else {
182                         rounded_function (cr, 0, 0, get_width(), get_height(), _corner_radius - 1.0);
183                 }
184
185                 if (active_state() == Gtkmm2ext::ImplicitActive) {
186                         cairo_set_source (cr, inactive_pattern);
187                         cairo_fill_preserve (cr);
188                         cairo_set_line_width (cr, 2.0);
189                         cairo_set_source (cr, active_pattern);
190                         cairo_stroke (cr);
191                 } else if (active_state() == Gtkmm2ext::ExplicitActive) {
192                         cairo_set_source (cr, active_pattern);
193                         cairo_fill (cr);
194                 } else {
195                         cairo_set_source (cr, inactive_pattern);
196                         cairo_fill (cr);
197                 }
198         }
199
200         if (_pixbuf) {
201
202                 double x,y;
203                 x = (get_width() - _pixbuf->get_width())/2.0;
204                 y = (get_height() - _pixbuf->get_height())/2.0;
205
206                 cairo_rectangle (cr, x, y, _pixbuf->get_width(), _pixbuf->get_height());
207                 gdk_cairo_set_source_pixbuf (cr, _pixbuf->gobj(), x, y);
208                 cairo_fill (cr);
209         }
210
211         /* text, if any */
212
213         int text_margin;
214
215         if (get_width() < 75) {
216                 text_margin = 3;
217         } else {
218                 text_margin = 10;
219         }
220
221         if ((_elements & Text) && !_text.empty()) {
222
223                 cairo_new_path (cr);    
224
225                 if (_elements & Indicator) {
226                         if (_led_left) {
227                                 cairo_move_to (cr, text_margin + _diameter + 4, get_height()/2.0 - _text_height/2.0);
228                         } else {
229                                 cairo_move_to (cr, text_margin, get_height()/2.0 - _text_height/2.0);
230                         }
231                 } else {
232                         /* center text */
233                         cairo_move_to (cr, (get_width() - _text_width)/2.0, get_height()/2.0 - _text_height/2.0);
234                 }
235
236                 cairo_set_source_rgba (cr, text_r, text_g, text_b, text_a);
237                 pango_cairo_show_layout (cr, _layout->gobj());
238         } 
239
240         if (_elements & Indicator) {
241
242                 /* move to the center of the indicator/led */
243
244                 cairo_save (cr);
245
246                 if (_elements & Text) {
247                         if (_led_left) {
248                                 cairo_translate (cr, text_margin + (_diameter/2.0), get_height()/2.0);
249                         } else {
250                                 cairo_translate (cr, get_width() - ((_diameter/2.0) + 4.0), get_height()/2.0);
251                         }
252                 } else {
253                         cairo_translate (cr, get_width()/2.0, get_height()/2.0);
254                 }
255                 
256                 //inset
257                 cairo_arc (cr, 0, 0, _diameter/2, 0, 2 * M_PI);
258                 cairo_set_source (cr, led_inset_pattern);
259                 cairo_fill (cr);
260                 
261                 //black ring
262                 cairo_set_source_rgb (cr, 0, 0, 0);
263                 cairo_arc (cr, 0, 0, _diameter/2-2, 0, 2 * M_PI);
264                 cairo_fill(cr);
265                 
266                 //led color
267                 cairo_set_source_rgba (cr, led_r, led_g, led_b, led_a);
268                 cairo_arc (cr, 0, 0, _diameter/2-3, 0, 2 * M_PI);
269                 cairo_fill(cr);
270                 
271                 //reflection
272                 cairo_scale(cr, 0.7, 0.7);
273                 cairo_arc (cr, 0, 0, _diameter/2-3, 0, 2 * M_PI);
274                 cairo_set_source (cr, reflection_pattern);
275                 cairo_fill (cr);
276
277                 cairo_restore (cr);
278
279         }
280
281
282         /* a partially transparent gray layer to indicate insensitivity */
283
284         if ((visual_state() & Gtkmm2ext::Insensitive)) {
285                 rounded_function (cr, 0, 0, get_width(), get_height(), _corner_radius);
286                 cairo_set_source_rgba (cr, 0.905, 0.917, 0.925, 0.5);
287                 cairo_fill (cr);
288         }
289
290         /* if requested, show hovering */
291         
292         if (ARDOUR::Config->get_widget_prelight()) {
293                 if (_hovering) {
294                         rounded_function (cr, 0, 0, get_width(), get_height(), _corner_radius);
295                         cairo_set_source_rgba (cr, 0.905, 0.917, 0.925, 0.2);
296                         cairo_fill (cr);
297                 }
298         }
299 }
300
301 void
302 ArdourButton::set_diameter (float d)
303 {
304         _diameter = (d*2) + 5.0;
305
306         if (_diameter != 0.0) {
307                 _fixed_diameter = true;
308         }
309
310         set_colors ();
311 }
312
313 void
314 ArdourButton::set_corner_radius (float r)
315 {
316         _corner_radius = r;
317         set_dirty ();
318 }
319
320 void
321 ArdourButton::on_size_request (Gtk::Requisition* req)
322 {
323         int xpad = 0;
324         int ypad = 6;
325
326         CairoWidget::on_size_request (req);
327
328         if ((_elements & Text) && !_text.empty()) {
329                 _layout->get_pixel_size (_text_width, _text_height);
330                 if (_text_width + _diameter < 75) {
331                         xpad = 7;
332                 } else {
333                         xpad = 20;
334                 }
335         } else {
336                 _text_width = 0;
337                 _text_height = 0;
338         }
339
340         if (_pixbuf) {
341                 xpad = 6;
342         }
343
344         if ((_elements & Indicator) && _fixed_diameter) {
345                 if (_pixbuf) {
346                         req->width = _pixbuf->get_width() + lrint (_diameter) + xpad;
347                         req->height = max (_pixbuf->get_height(), (int) lrint (_diameter)) + ypad;
348                 } else {
349                         req->width = _text_width + lrint (_diameter) + xpad;
350                         req->height = max (_text_height, (int) lrint (_diameter)) + ypad;
351                 }
352         } else {
353                 if (_pixbuf) {
354                         req->width = _pixbuf->get_width() + xpad;
355                         req->height = _pixbuf->get_height() + ypad;
356                 }  else {
357                         req->width = _text_width + xpad;
358                         req->height = _text_height + ypad;
359                 }
360         }
361 }
362
363 void
364 ArdourButton::set_colors ()
365 {
366         uint32_t start_color;
367         uint32_t end_color;
368         uint32_t r, g, b, a;
369         uint32_t text_color;
370         uint32_t led_color;
371
372         /* we use the edge of the button to show Selected state, so the
373          * color/pattern used there will vary depending on that
374          */
375         
376         if (edge_pattern) {
377                 cairo_pattern_destroy (edge_pattern);
378                 edge_pattern = 0;
379         }
380
381         if (_elements & Edge) {
382
383                 edge_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
384                 if (visual_state() & Gtkmm2ext::Selected) {
385                         start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: border start selected", get_name()));
386                         if (_flat_buttons) {
387                                 end_color = start_color;
388                         } else {
389                                 end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: border end selected", get_name()));
390                         }
391                 } else {
392                         start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: border start", get_name()));
393                         if (_flat_buttons) {
394                                 end_color = start_color;
395                         } else {
396                                 end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: border end", get_name()));
397                         }
398                 }
399                 UINT_TO_RGBA (start_color, &r, &g, &b, &a);
400                 cairo_pattern_add_color_stop_rgba (edge_pattern, 0, r/255.0,g/255.0,b/255.0, 0.7);
401                 UINT_TO_RGBA (end_color, &r, &g, &b, &a);
402                 cairo_pattern_add_color_stop_rgba (edge_pattern, 1, r/255.0,g/255.0,b/255.0, 0.7);
403         }
404
405         if (active_pattern) {
406                 cairo_pattern_destroy (active_pattern);
407                 active_pattern = 0;
408         }
409
410         if (inactive_pattern) {
411                 cairo_pattern_destroy (inactive_pattern);
412                 inactive_pattern = 0;
413         }
414
415         if (_elements & Body) {
416
417                 active_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
418                 start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start active", get_name()));
419
420                 if (_flat_buttons) {
421                         end_color = start_color;
422                 } else {
423                         end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end active", get_name()));
424                 }
425                 UINT_TO_RGBA (start_color, &r, &g, &b, &a);
426
427                 active_r = r/255.0;
428                 active_g = g/255.0;
429                 active_b = b/255.0;
430                 active_a = a/255.0;
431
432                 cairo_pattern_add_color_stop_rgba (active_pattern, 0, r/255.0,g/255.0,b/255.0, a/255.0);
433                 UINT_TO_RGBA (end_color, &r, &g, &b, &a);
434                 cairo_pattern_add_color_stop_rgba (active_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0);
435
436                 inactive_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
437                 start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start", get_name()));
438                 if (_flat_buttons) {
439                         end_color = start_color;
440                 } else {
441                         end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end", get_name()));
442                 }
443                 UINT_TO_RGBA (start_color, &r, &g, &b, &a);
444                 cairo_pattern_add_color_stop_rgba (inactive_pattern, 0, r/255.0,g/255.0,b/255.0, a/255.0);
445                 UINT_TO_RGBA (end_color, &r, &g, &b, &a);
446                 cairo_pattern_add_color_stop_rgba (inactive_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0);
447         }
448
449         if (led_inset_pattern) {
450                 cairo_pattern_destroy (led_inset_pattern);
451         }
452         
453         if (reflection_pattern) {
454                 cairo_pattern_destroy (reflection_pattern);
455         }
456
457         if (_elements & Indicator) {
458                 led_inset_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, _diameter);
459                 cairo_pattern_add_color_stop_rgba (led_inset_pattern, 0, 0,0,0, 0.4);
460                 cairo_pattern_add_color_stop_rgba (led_inset_pattern, 1, 1,1,1, 0.7);
461
462                 reflection_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, _diameter/2-3);
463                 cairo_pattern_add_color_stop_rgba (reflection_pattern, 0, 1,1,1, active_state() ? 0.4 : 0.2);
464                 cairo_pattern_add_color_stop_rgba (reflection_pattern, 1, 1,1,1, 0.0);
465         }
466         
467         /* text and LED colors */
468
469         if (active_state() == Gtkmm2ext::ExplicitActive) {
470                 text_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: text active", get_name()));
471                 led_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led active", get_name()));
472         } else {
473                 text_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: text", get_name()));
474                 led_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led", get_name()));
475         }
476
477         UINT_TO_RGBA (text_color, &r, &g, &b, &a);
478         text_r = r/255.0;
479         text_g = g/255.0;
480         text_b = b/255.0;
481         text_a = a/255.0;
482         UINT_TO_RGBA (led_color, &r, &g, &b, &a);
483         led_r = r/255.0;
484         led_g = g/255.0;
485         led_b = b/255.0;
486         led_a = a/255.0;
487
488         set_dirty ();
489 }
490
491 void
492 ArdourButton::set_led_left (bool yn)
493 {
494         _led_left = yn;
495 }
496
497 bool
498 ArdourButton::on_button_press_event (GdkEventButton *ev)
499 {
500         if ((_elements & Indicator) && _led_rect && _distinct_led_click) {
501                 if (ev->x >= _led_rect->x && ev->x < _led_rect->x + _led_rect->width && 
502                     ev->y >= _led_rect->y && ev->y < _led_rect->y + _led_rect->height) {
503                         return true;
504                 }
505         }
506
507         if (_tweaks & ShowClick) {
508                 set_active_state (Gtkmm2ext::ExplicitActive);
509         }
510
511         if (binding_proxy.button_press_handler (ev)) {
512                 return true;
513         }
514
515         if (!_act_on_release) {
516                 if (_action) {
517                         _action->activate ();
518                         return true;
519                 }
520         }
521
522         return false;
523 }
524
525 bool
526 ArdourButton::on_button_release_event (GdkEventButton *ev)
527 {
528         if ((_elements & Indicator) && _led_rect && _distinct_led_click) {
529                 if (ev->x >= _led_rect->x && ev->x < _led_rect->x + _led_rect->width && 
530                     ev->y >= _led_rect->y && ev->y < _led_rect->y + _led_rect->height) {
531                         signal_led_clicked(); /* EMIT SIGNAL */
532                         return true;
533                 }
534         }
535
536         if (_tweaks & ShowClick) {
537                 unset_active_state ();
538         }
539
540         signal_clicked ();
541
542         if (_act_on_release) {
543                 if (_action) {
544                         _action->activate ();
545                         return true;
546                 }
547         }
548
549
550         return false;
551 }
552
553 void
554 ArdourButton::set_distinct_led_click (bool yn)
555 {
556         _distinct_led_click = yn;
557         setup_led_rect ();
558 }
559
560 void
561 ArdourButton::color_handler ()
562 {
563         set_colors ();
564         set_dirty ();
565 }
566
567 void
568 ArdourButton::on_size_allocate (Allocation& alloc)
569 {
570         CairoWidget::on_size_allocate (alloc);
571         setup_led_rect ();
572         set_colors ();
573 }
574
575 void
576 ArdourButton::set_controllable (boost::shared_ptr<Controllable> c)
577 {
578         watch_connection.disconnect ();
579         binding_proxy.set_controllable (c);
580 }
581
582 void
583 ArdourButton::watch ()
584 {
585         boost::shared_ptr<Controllable> c (binding_proxy.get_controllable ());
586
587         if (!c) {
588                 warning << _("button cannot watch state of non-existing Controllable\n") << endmsg;
589                 return;
590         }
591
592         c->Changed.connect (watch_connection, invalidator(*this), boost::bind (&ArdourButton::controllable_changed, this), gui_context());
593 }
594
595 void
596 ArdourButton::controllable_changed ()
597 {
598         float val = binding_proxy.get_controllable()->get_value();
599
600         if (fabs (val) >= 0.5f) {
601                 set_active_state (Gtkmm2ext::ExplicitActive);
602         } else {
603                 unset_active_state ();
604         }
605 }
606
607 void
608 ArdourButton::set_related_action (RefPtr<Action> act)
609 {
610         Gtkmm2ext::Activatable::set_related_action (act);
611
612         if (_action) {
613
614                 action_tooltip_changed ();
615
616                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (_action);
617                 if (tact) {
618                         action_toggled ();
619                         tact->signal_toggled().connect (sigc::mem_fun (*this, &ArdourButton::action_toggled));
620                 } 
621
622                 _action->connect_property_changed ("sensitive", sigc::mem_fun (*this, &ArdourButton::action_sensitivity_changed));
623                 _action->connect_property_changed ("visible", sigc::mem_fun (*this, &ArdourButton::action_visibility_changed));
624                 _action->connect_property_changed ("tooltip", sigc::mem_fun (*this, &ArdourButton::action_tooltip_changed));
625         }
626 }
627
628 void
629 ArdourButton::action_toggled ()
630 {
631         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (_action);
632
633         if (tact) {
634                 if (tact->get_active()) {
635                         set_active_state (Gtkmm2ext::ExplicitActive);
636                 } else {
637                         unset_active_state ();
638                 }
639         }
640 }       
641
642 void
643 ArdourButton::on_style_changed (const RefPtr<Gtk::Style>&)
644 {
645         set_colors ();
646 }
647
648 void
649 ArdourButton::setup_led_rect ()
650 {
651         int text_margin;
652
653         if (get_width() < 75) {
654                 text_margin = 3;
655         } else {
656                 text_margin = 10;
657         }
658
659         if (_elements & Indicator) {
660                 _led_rect = new cairo_rectangle_t;
661                 
662                 if (_elements & Text) {
663                         if (_led_left) {
664                                 _led_rect->x = text_margin;
665                         } else {
666                                 _led_rect->x = get_width() - text_margin - _diameter/2.0;
667                         }
668                 } else {
669                         /* centered */
670                         _led_rect->x = get_width()/2.0 - _diameter/2.0;
671                 }
672
673                 _led_rect->y = get_height()/2.0 - _diameter/2.0;
674                 _led_rect->width = _diameter;
675                 _led_rect->height = _diameter;
676
677         } else {
678                 delete _led_rect;
679                 _led_rect = 0;
680         }
681 }
682
683 void
684 ArdourButton::set_image (const RefPtr<Gdk::Pixbuf>& img)
685 {
686         _pixbuf = img;
687         queue_draw ();
688 }
689
690 void
691 ArdourButton::set_active_state (Gtkmm2ext::ActiveState s)
692 {
693         bool changed = (_active_state != s);
694         CairoWidget::set_active_state (s);
695         if (changed) {
696                 set_colors ();
697         }
698 }
699         
700 void
701 ArdourButton::set_visual_state (Gtkmm2ext::VisualState s)
702 {
703         bool changed = (_visual_state != s);
704         CairoWidget::set_visual_state (s);
705         if (changed) {
706                 set_colors ();
707         }
708 }
709         
710 bool
711 ArdourButton::on_enter_notify_event (GdkEventCrossing* ev)
712 {
713         _hovering = true;
714
715         if (ARDOUR::Config->get_widget_prelight()) {
716                 queue_draw ();
717         }
718
719         return CairoWidget::on_enter_notify_event (ev);
720 }
721
722 bool
723 ArdourButton::on_leave_notify_event (GdkEventCrossing* ev)
724 {
725         _hovering = false;
726
727         if (ARDOUR::Config->get_widget_prelight()) {
728                 queue_draw ();
729         }
730
731         return CairoWidget::on_leave_notify_event (ev);
732 }
733
734 void
735 ArdourButton::set_tweaks (Tweaks t)
736 {
737         if (_tweaks != t) {
738                 _tweaks = t;
739                 queue_draw ();
740         }
741 }
742
743 void
744 ArdourButton::action_sensitivity_changed ()
745 {
746         if (_action->property_sensitive ()) {
747                 set_visual_state (Gtkmm2ext::VisualState (visual_state() & ~Gtkmm2ext::Insensitive));
748         } else {
749                 set_visual_state (Gtkmm2ext::VisualState (visual_state() | Gtkmm2ext::Insensitive));
750         }
751         
752 }
753
754
755 void
756 ArdourButton::action_visibility_changed ()
757 {
758         if (_action->property_visible ()) {
759                 show ();
760         } else {
761                 hide ();
762         }
763 }
764
765 void
766 ArdourButton::action_tooltip_changed ()
767 {
768         string str = _action->property_tooltip().get_value();
769         ARDOUR_UI::instance()->set_tip (*this, str);
770 }
771
772 void
773 ArdourButton::set_rounded_corner_mask (int mask)
774 {
775         _corner_mask = mask;
776         queue_draw ();
777 }
778
779 void
780 ArdourButton::set_elements (Element e)
781 {
782         _elements = e;
783         set_colors ();
784 }
785
786 void
787 ArdourButton::set_flat_buttons (bool yn)
788 {
789         _flat_buttons = yn;
790 }