remove additional "mid" color from ArdourButton; replace Active/Mid widget state...
[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)
17         : left (lw)
18         , right (rw)
19         , name (str)
20         , active_fill_pattern (0)
21         , inactive_fill_pattern (0)
22 {
23         packer.set_homogeneous (true);
24         packer.pack_start (left);
25         packer.pack_start (right);
26         packer.show ();
27
28         align.add (packer);
29         align.set (0.5, 1.0);
30         align.set_padding (9, 0, 9, 9);
31         align.show ();
32
33         add (align);
34
35         add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|
36                     Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
37
38         uint32_t border_color;
39         uint32_t r, g, b, a;
40
41         border_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: border end", name));
42         UINT_TO_RGBA (border_color, &r, &g, &b, &a);
43         
44         border_r = r/255.0;
45         border_g = g/255.0;
46         border_b = b/255.0;
47
48         /* child cairo widgets need the color of the inner edge as their
49          * "background"
50          */
51
52         Gdk::Color col;
53         col.set_rgb_p (border_r, border_g, border_b);
54         provide_background_for_cairo_widget (*this, col);
55 }
56
57 ButtonJoiner::~ButtonJoiner ()
58 {
59         if (active_fill_pattern) {
60                 cairo_pattern_destroy (active_fill_pattern);
61                 cairo_pattern_destroy (inactive_fill_pattern);
62         }
63 }
64
65 void
66 ButtonJoiner::render (cairo_t* cr)
67 {
68         double h = get_height();
69         
70         if (!get_active()) {
71                 cairo_set_source (cr, inactive_fill_pattern);
72         } else {
73                 cairo_set_source (cr, active_fill_pattern);
74         }
75
76         /* outer rect */
77
78         Gtkmm2ext::rounded_top_rectangle (cr, 0, 0, get_width(), h, 12);
79         cairo_fill_preserve (cr);
80
81         /* outer edge */
82
83         cairo_set_line_width (cr, 1);
84         cairo_set_source_rgb (cr, border_r, border_g, border_b);
85         cairo_stroke (cr);
86
87         /* inner "edge" */
88
89         Gtkmm2ext::rounded_top_rectangle (cr, 8, 8, get_width() - 16, h - 8, 10);
90         cairo_stroke (cr);
91
92 }
93
94 void
95 ButtonJoiner::on_size_allocate (Allocation& alloc)
96 {
97         CairoWidget::on_size_allocate (alloc);
98         set_colors ();
99 }
100
101 bool
102 ButtonJoiner::on_button_release_event (GdkEventButton* ev)
103 {
104         if (_action) {
105                 _action->activate ();
106         }
107
108         return true;
109 }
110
111 void
112 ButtonJoiner::on_size_request (Gtk::Requisition* r)
113 {
114         CairoWidget::on_size_request (r);
115 }
116
117 void
118 ButtonJoiner::set_related_action (Glib::RefPtr<Action> act)
119 {
120         Gtkmm2ext::Activatable::set_related_action (act);
121
122         if (_action) {
123
124                 action_tooltip_changed ();
125
126                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (_action);
127                 if (tact) {
128                         action_toggled ();
129                         tact->signal_toggled().connect (sigc::mem_fun (*this, &ButtonJoiner::action_toggled));
130                 } 
131
132                 _action->connect_property_changed ("sensitive", sigc::mem_fun (*this, &ButtonJoiner::action_sensitivity_changed));
133                 _action->connect_property_changed ("visible", sigc::mem_fun (*this, &ButtonJoiner::action_visibility_changed));
134                 _action->connect_property_changed ("tooltip", sigc::mem_fun (*this, &ButtonJoiner::action_tooltip_changed));
135         }
136 }
137
138 void
139 ButtonJoiner::action_sensitivity_changed ()
140 {
141         if (_action->property_sensitive ()) {
142                 set_visual_state (Gtkmm2ext::VisualState (visual_state() & ~Gtkmm2ext::Insensitive));
143         } else {
144                 set_visual_state (Gtkmm2ext::VisualState (visual_state() | Gtkmm2ext::Insensitive));
145         }
146         
147 }
148
149 void
150 ButtonJoiner::action_visibility_changed ()
151 {
152         if (_action->property_visible ()) {
153                 show ();
154         } else {
155                 hide ();
156         }
157 }
158
159 void
160 ButtonJoiner::action_tooltip_changed ()
161 {
162         std::string str = _action->property_tooltip().get_value();
163         ARDOUR_UI::instance()->set_tip (*this, str);
164 }
165
166 void
167 ButtonJoiner::action_toggled ()
168 {
169         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (_action);
170
171         if (tact) {
172                 set_active (tact->get_active());
173         }
174 }       
175
176 void
177 ButtonJoiner::set_active_state (Gtkmm2ext::ActiveState s)
178 {
179         bool changed = (_active_state != s);
180         CairoWidget::set_active_state (s);
181         if (changed) {
182                 set_colors ();
183         }
184 }
185
186 void
187 ButtonJoiner::set_colors ()
188 {
189         uint32_t start_color;
190         uint32_t end_color;
191         uint32_t r, g, b, a;
192
193         if (active_fill_pattern) {
194                 cairo_pattern_destroy (active_fill_pattern);
195                 cairo_pattern_destroy (inactive_fill_pattern);
196         }
197
198         active_fill_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
199         inactive_fill_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
200
201         start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start", name));
202         end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end", name));
203         UINT_TO_RGBA (start_color, &r, &g, &b, &a);
204         cairo_pattern_add_color_stop_rgba (inactive_fill_pattern, 0, r/255.0,g/255.0,b/255.0, a/255.0);
205         UINT_TO_RGBA (end_color, &r, &g, &b, &a);
206         cairo_pattern_add_color_stop_rgba (inactive_fill_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0);
207
208         start_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start active", name));
209         end_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end active", name));
210         UINT_TO_RGBA (start_color, &r, &g, &b, &a);
211         cairo_pattern_add_color_stop_rgba (active_fill_pattern, 0, r/255.0,g/255.0,b/255.0, a/255.0);
212         UINT_TO_RGBA (end_color, &r, &g, &b, &a);
213         cairo_pattern_add_color_stop_rgba (active_fill_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0);
214
215         queue_draw ();
216 }
217