make -D VSTCallbacks readable
[ardour.git] / libs / gtkmm2ext / persistent_tooltip.cc
1 /*
2     Copyright (C) 2012 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 <gtkmm/window.h>
21 #include <gtkmm/label.h>
22 #include "gtkmm2ext/persistent_tooltip.h"
23
24 #include "pbd/stacktrace.h"
25
26 #include "i18n.h"
27
28 using namespace std;
29 using namespace Gtk;
30 using namespace Gtkmm2ext;
31
32 bool PersistentTooltip::_tooltips_enabled = true;
33
34 /** @param target The widget to provide the tooltip for */
35 PersistentTooltip::PersistentTooltip (Gtk::Widget* target, bool  draggable, int margin_y)
36         : _target (target)
37         , _window (0)
38         , _label (0)
39         , _draggable (draggable)
40         , _maybe_dragging (false)
41         , _align_to_center (true)
42         , _margin_y (margin_y)
43 {
44         target->signal_enter_notify_event().connect (sigc::mem_fun (*this, &PersistentTooltip::enter), false);
45         target->signal_leave_notify_event().connect (sigc::mem_fun (*this, &PersistentTooltip::leave), false);
46         target->signal_button_press_event().connect (sigc::mem_fun (*this, &PersistentTooltip::press), false);
47         target->signal_button_release_event().connect (sigc::mem_fun (*this, &PersistentTooltip::release), false);
48 }
49
50 PersistentTooltip::~PersistentTooltip ()
51 {
52         delete _window;
53 }
54
55 bool
56 PersistentTooltip::enter (GdkEventCrossing *)
57 {
58         if (_timeout.connected()) {
59                 leave(NULL);
60         }
61         _timeout = Glib::signal_timeout().connect (sigc::mem_fun (*this, &PersistentTooltip::timeout), 500);
62         return false;
63 }
64
65 bool
66 PersistentTooltip::timeout ()
67 {
68         show ();
69         return false;
70 }
71
72 bool
73 PersistentTooltip::leave (GdkEventCrossing *)
74 {
75         _timeout.disconnect ();
76         if (!dragging ()) {
77                 hide ();
78         }
79
80         return false;
81 }
82
83 bool
84 PersistentTooltip::press (GdkEventButton* ev)
85 {
86         if (ev->type == GDK_BUTTON_PRESS && ev->button == 1) {
87                 _maybe_dragging = true;
88         }
89
90         return false;
91 }
92
93 bool
94 PersistentTooltip::release (GdkEventButton* ev)
95 {
96         if (ev->type == GDK_BUTTON_RELEASE && ev->button == 1) {
97                 _maybe_dragging = false;
98         }
99
100         return false;
101 }
102
103 bool
104 PersistentTooltip::dragging () const
105 {
106         return _maybe_dragging && _draggable;
107 }
108
109 void
110 PersistentTooltip::hide ()
111 {
112         if (_window) {
113                 _window->hide ();
114         }
115 }
116
117 void
118 PersistentTooltip::show ()
119 {
120         if (_tip.empty() || !_tooltips_enabled) {
121                 return;
122         }
123
124         if (!_window) {
125                 _window = new Window (WINDOW_POPUP);
126                 _window->set_name (X_("ContrastingPopup"));
127                 _window->set_position (WIN_POS_MOUSE);
128                 _window->set_decorated (false);
129
130                 _label = manage (new Label);
131                 _label->modify_font (_font);
132                 _label->set_use_markup (true);
133
134                 _window->set_border_width (6);
135                 _window->add (*_label);
136                 _label->show ();
137
138                 Gtk::Window* tlw = dynamic_cast<Gtk::Window*> (_target->get_toplevel ());
139                 if (tlw) {
140                         _window->set_transient_for (*tlw);
141                 }
142         }
143
144         set_tip (_tip);
145
146         if (!_window->is_visible ()) {
147                 int rx, ry;
148                 int sw = gdk_screen_width ();
149
150                 _target->get_window()->get_origin (rx, ry);
151
152                 /* the window needs to be realized first
153                  * for _window->get_width() to be correct.
154                  */
155
156
157                 if (sw < rx + _window->get_width()) {
158                         /* right edge of window would be off the right edge of
159                            the screen, so don't show it in the usual place.
160                         */
161                         rx = sw - _window->get_width();
162                         _window->move (rx, ry + _target->get_height() + _margin_y);
163                 } else {
164                         if (_align_to_center) {
165                                 _window->move (rx + (_target->get_width () - _window->get_width ()) / 2, ry + _target->get_height());
166                         } else {
167                                 _window->move (rx, ry + _target->get_height());
168                         }
169                 }
170
171                 _window->present ();
172
173         }
174 }
175
176 void
177 PersistentTooltip::set_tip (string t)
178 {
179         _tip = t;
180
181         if (_label) {
182                 _label->set_markup (t);
183         }
184 }
185
186 void
187 PersistentTooltip::set_font (Pango::FontDescription font)
188 {
189         _font = font;
190
191         if (_label) {
192                 _label->modify_font (_font);
193         }
194 }
195
196 void
197 PersistentTooltip::set_center_alignment (bool align_to_center)
198 {
199         _align_to_center = align_to_center;
200 }