1 /*
2  * Copyright (C) 2010 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2017-2018 Robin Gareus <robin@gareus.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifndef _WIDGETS_ARDOUR_BUTTON_H_
21 #define _WIDGETS_ARDOUR_BUTTON_H_
22 
23 #include <list>
24 #include <stdint.h>
25 
26 #include <gtkmm/action.h>
27 
28 #include "pbd/signals.h"
29 #include "gtkmm2ext/activatable.h"
30 #include "gtkmm2ext/cairo_widget.h"
31 
32 #include "widgets/ardour_icon.h"
33 #include "widgets/binding_proxy.h"
34 #include "widgets/visibility.h"
35 
36 namespace ArdourWidgets {
37 
38 class LIBWIDGETS_API ArdourButton : public CairoWidget , public Gtkmm2ext::Activatable
39 {
40 	public:
41 	enum Element {
42 		Edge = 0x1,
43 		Body = 0x2,
44 		Text = 0x4,
45 		Indicator = 0x8,
46 		unused = 0x10,
47 		Menu = 0x20,
48 		Inactive = 0x40, // no _action is defined AND state is not used
49 		VectorIcon = 0x80,
50 		IconRenderCallback = 0x100,
51 	};
52 
53 	typedef void (* rendercallback_t) (cairo_t*, int, int, uint32_t, void*);
54 
55 	static Element default_elements;
56 	static Element led_default_elements;
57 	static Element just_led_default_elements;
58 
59 	ArdourButton (Element e = default_elements, bool toggle = false);
60 	ArdourButton (const std::string&, Element e = default_elements, bool toggle = false);
61 	virtual ~ArdourButton ();
62 
63 	enum Tweaks {
64 		Square = 0x1,
65 		TrackHeader = 0x2,
66 		OccasionalText = 0x4,
67 		OccasionalLED = 0x8,
68 		ForceBoxy = 0x10,
69 		ForceFlat = 0x20,
70 	};
71 
tweaks()72 	Tweaks tweaks() const { return _tweaks; }
73 	void set_tweaks (Tweaks);
74 
75 	void set_active_state (Gtkmm2ext::ActiveState);
76 	void set_visual_state (Gtkmm2ext::VisualState);
77 
78 	void set_custom_led_color (const uint32_t c, const bool useit = true);
79 
set_act_on_release(bool onRelease)80 	void set_act_on_release (bool onRelease) { _act_on_release = onRelease; }
81 
elements()82 	Element elements() const { return _elements; }
83 	void set_elements (Element);
84 	void add_elements (Element);
85 
icon()86 	ArdourIcon::Icon icon() const { return _icon; }
87 	void set_icon (ArdourIcon::Icon);
88 	void set_icon (rendercallback_t, void*);
89 
90 	void set_corner_radius (float);
91 
92 	void set_text (const std::string&, bool markup = false);
get_text()93 	const std::string& get_text () const { return _text; }
get_markup()94 	bool get_markup () const { return _markup; }
95 	void set_angle (const double);
96 	void set_alignment (const float, const float);
get_alignment(float & xa,float & ya)97 	void get_alignment (float& xa, float& ya) {xa = _xalign; ya = _yalign;};
98 
99 	void set_led_left (bool yn);
100 	void set_distinct_led_click (bool yn);
101 
102 	void set_layout_ellipsize_width (int w);
103 	void set_layout_font (const Pango::FontDescription&);
104 	void set_text_ellipsize (Pango::EllipsizeMode);
105 
106     /* Sets the text used for size request computation. Pass an
107      * empty string to return to the default behavior which uses
108      * the currently displayed text for measurement. */
109 	void set_sizing_text (const std::string&);
get_sizing_text()110 	const std::string& get_sizing_text () {return _sizing_text;}
111 
112 	sigc::signal<void, GdkEventButton*> signal_led_clicked;
113 	sigc::signal<void> signal_clicked;
114 
get_controllable()115 	boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); }
116 	void set_controllable (boost::shared_ptr<PBD::Controllable> c);
117 	void watch ();
118 
119 	void set_related_action (Glib::RefPtr<Gtk::Action>);
120 
121 	bool on_button_press_event (GdkEventButton*);
122 	bool on_button_release_event (GdkEventButton*);
123 
124 	void set_image (const Glib::RefPtr<Gdk::Pixbuf>&);
125 
126 	void set_fixed_colors   (const uint32_t active_color, const uint32_t inactive_color);
127 	void set_active_color   (const uint32_t active_color);
128 	void set_inactive_color (const uint32_t inactive_color);
129 	void reset_fixed_colors ();
130 
set_fallthrough_to_parent(bool fall)131 	void set_fallthrough_to_parent(bool fall) { _fallthrough_to_parent = fall; }
132 
char_pixel_width()133 	unsigned int char_pixel_width() { if (_char_pixel_width < 1) recalc_char_pixel_geometry() ; return _char_pixel_width; }
char_pixel_height()134 	unsigned int char_pixel_height() { if (_char_pixel_height < 1) recalc_char_pixel_geometry() ; return _char_pixel_height; }
char_avg_pixel_width()135 	float char_avg_pixel_width() { if (_char_pixel_width < 1) recalc_char_pixel_geometry() ; return _char_avg_pixel_width; }
136 
137 	protected:
138 	void render (Cairo::RefPtr<Cairo::Context> const&, cairo_rectangle_t*);
139 	void on_size_request (Gtk::Requisition* req);
140 	void on_size_allocate (Gtk::Allocation&);
141 	void on_style_changed (const Glib::RefPtr<Gtk::Style>&);
142 	void on_name_changed ();
143 	void on_realize ();
144 	bool on_enter_notify_event (GdkEventCrossing*);
145 	bool on_leave_notify_event (GdkEventCrossing*);
146 	bool on_grab_broken_event(GdkEventGrabBroken*);
147 	bool on_focus_in_event (GdkEventFocus*);
148 	bool on_focus_out_event (GdkEventFocus*);
149 	bool on_key_release_event (GdkEventKey *);
150 	bool on_key_press_event (GdkEventKey *);
151 
152 	void controllable_changed ();
153 	PBD::ScopedConnection watch_connection;
154 
155 	protected:
156 	Glib::RefPtr<Pango::Layout> _layout;
157 	Glib::RefPtr<Gdk::Pixbuf>   _pixbuf;
158 	std::string                 _text;
159 	std::string                 _sizing_text;
160 	bool                        _markup;
161 	Element                     _elements;
162 	ArdourIcon::Icon            _icon;
163 	rendercallback_t            _icon_render_cb;
164 	void*                       _icon_render_cb_data;
165 	Tweaks                      _tweaks;
166 	BindingProxy                binding_proxy;
167 
168 	void set_text_internal ();
169 	void recalc_char_pixel_geometry ();
170 
171 	unsigned int _char_pixel_width;
172 	unsigned int _char_pixel_height;
173 	float        _char_avg_pixel_width;
174 	bool         _custom_font_set;
175 
176 	int   _text_width;
177 	int   _text_height;
178 	float _diameter;
179 	float _corner_radius;
180 	int   _corner_mask;
181 
182 	double _angle;
183 	float _xalign, _yalign;
184 
185 	uint32_t fill_inactive_color;
186 	uint32_t fill_active_color;
187 
188 	uint32_t text_active_color;
189 	uint32_t text_inactive_color;
190 
191 	uint32_t led_active_color;
192 	uint32_t led_inactive_color;
193 	uint32_t led_custom_color;
194 	bool     use_custom_led_color;
195 
196 	cairo_pattern_t* convex_pattern;
197 	cairo_pattern_t* concave_pattern;
198 	cairo_pattern_t* led_inset_pattern;
199 	cairo_rectangle_t* _led_rect;
200 
201 	bool _act_on_release;
202 	bool _auto_toggle;
203 	bool _led_left;
204 	bool _distinct_led_click;
205 	bool _hovering;
206 	bool _focused;
207 	int  _fixed_colors_set;
208 	bool _fallthrough_to_parent;
209 	int _layout_ellipsize_width;
210 	Pango::EllipsizeMode _ellipsis;
211 	bool _update_colors;
212 	int _pattern_height;
213 
214 	void setup_led_rect ();
215 	void set_colors ();
216 	void color_handler ();
217 	void build_patterns ();
218 	void ensure_layout ();
219 
220 	void action_toggled ();
221 	void action_sensitivity_changed ();
222 	void action_visibility_changed ();
223 	void action_tooltip_changed ();
224 };
225 
226 } /* end namespace */
227 
228 #endif
229