ardour
utils.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 1999 Paul Barton-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  $Id$
19 */
20 
21 #include <map>
22 #include <algorithm>
23 
24 #include <gtk/gtkpaned.h>
25 #include <gtk/gtk.h>
26 
27 #include <gtkmm/widget.h>
28 #include <gtkmm/button.h>
29 #include <gtkmm/window.h>
30 #include <gtkmm/paned.h>
31 #include <gtkmm/label.h>
32 #include <gtkmm/comboboxtext.h>
33 #include <gtkmm/tooltip.h>
34 
35 #include "gtkmm2ext/utils.h"
36 
37 #include "i18n.h"
38 
39 using namespace std;
40 
41 void
43 {
44 #ifdef ENABLE_NLS
45  (void) bindtextdomain(PACKAGE, localedir);
46  (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
47 #endif
48 }
49 
50 void
51 Gtkmm2ext::get_ink_pixel_size (Glib::RefPtr<Pango::Layout> layout,
52  int& width,
53  int& height)
54 {
55  Pango::Rectangle ink_rect = layout->get_ink_extents ();
56 
57  width = (ink_rect.get_width() + PANGO_SCALE / 2) / PANGO_SCALE;
58  height = (ink_rect.get_height() + PANGO_SCALE / 2) / PANGO_SCALE;
59 }
60 
61 void
62 Gtkmm2ext::get_pixel_size (Glib::RefPtr<Pango::Layout> layout,
63  int& width,
64  int& height)
65 {
66  layout->get_pixel_size (width, height);
67 }
68 
69 void
70 Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, const gchar *text,
71  gint hpadding, gint vpadding)
72 {
73  int width, height;
74  w.ensure_style ();
75 
76  get_pixel_size (w.create_pango_layout (text), width, height);
77  w.set_size_request(width + hpadding, height + vpadding);
78 }
79 
82 void
84  const gchar* htext,
85  gint hpadding,
86  gint vpadding)
87 {
88  static const gchar* vtext = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
89 
90  w.ensure_style ();
91 
92  int hwidth, hheight;
93  get_pixel_size (w.create_pango_layout (htext), hwidth, hheight);
94 
95  int vwidth, vheight;
96  get_pixel_size (w.create_pango_layout (vtext), vwidth, vheight);
97 
98  w.set_size_request(hwidth + hpadding, vheight + vpadding);
99 }
100 
101 void
103 {
104  static const gchar* vtext = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
105 
106  w.ensure_style ();
107 
108  int width, height;
109  get_pixel_size (w.create_pango_layout (vtext), width, height);
110 
111  w.set_size_request(-1, height + vpadding);
112 }
113 
114 void
115 Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, std::string const & text,
116  gint hpadding, gint vpadding)
117 {
118  int width, height;
119  w.ensure_style ();
120 
121  get_pixel_size (w.create_pango_layout (text), width, height);
122  w.set_size_request(width + hpadding, height + vpadding);
123 }
124 
125 void
127  const std::vector<std::string>& strings,
128  gint hpadding, gint vpadding)
129 {
130  int width, height;
131  int width_max = 0;
132  int height_max = 0;
133  w.ensure_style ();
134  vector<string> copy;
135  const vector<string>* to_use;
136  vector<string>::const_iterator i;
137 
138  for (i = strings.begin(); i != strings.end(); ++i) {
139  if ((*i).find_first_of ("gy") != string::npos) {
140  /* contains a descender */
141  break;
142  }
143  }
144 
145  if (i == strings.end()) {
146  /* make a copy of the strings then add one that has a descender */
147  copy = strings;
148  copy.push_back ("g");
149  to_use = &copy;
150  } else {
151  to_use = &strings;
152  }
153 
154  for (vector<string>::const_iterator i = to_use->begin(); i != to_use->end(); ++i) {
155  get_pixel_size (w.create_pango_layout (*i), width, height);
156  width_max = max(width_max,width);
157  height_max = max(height_max, height);
158  }
159 
160  w.set_size_request(width_max + hpadding, height_max + vpadding);
161 }
162 
166 void
168  const std::vector<std::string>& strings,
169  const std::string& hpadding,
170  gint vpadding)
171 {
172  int width_max = 0;
173  int height_max = 0;
174  w.ensure_style ();
175 
176  for (vector<string>::const_iterator i = strings.begin(); i != strings.end(); ++i) {
177  int width, height;
178  get_pixel_size (w.create_pango_layout (*i), width, height);
179  width_max = max(width_max,width);
180  height_max = max(height_max, height);
181  }
182 
183  int pad_width;
184  int pad_height;
185  get_pixel_size (w.create_pango_layout (hpadding), pad_width, pad_height);
186 
187  w.set_size_request(width_max + pad_width, height_max + vpadding);
188 }
189 
190 static inline guint8
191 demultiply_alpha (guint8 src,
192  guint8 alpha)
193 {
194  /* cairo pixel buffer data contains RGB values with the alpha
195  values premultiplied.
196 
197  GdkPixbuf pixel buffer data contains RGB values without the
198  alpha value applied.
199 
200  this removes the alpha component from the cairo version and
201  returns the GdkPixbuf version.
202  */
203  return alpha ? ((guint (src) << 8) - src) / alpha : 0;
204 }
205 
206 void
208  guint8* dst,
209  int width,
210  int height)
211 {
212  guint8 const* src_pixel = src;
213  guint8* dst_pixel = dst;
214 
215  /* cairo pixel data is endian-dependent ARGB with A in the most significant 8 bits,
216  with premultipled alpha values (see preceding function)
217 
218  GdkPixbuf pixel data is non-endian-dependent RGBA with R in the lowest addressable
219  8 bits, and non-premultiplied alpha values.
220 
221  convert from the cairo values to the GdkPixbuf ones.
222  */
223 
224  for (int y = 0; y < height; y++) {
225  for (int x = 0; x < width; x++) {
226 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
227  /* Cairo [ B G R A ] is actually [ B G R A ] in memory SOURCE
228  0 1 2 3
229  Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
230  */
231  dst_pixel[0] = demultiply_alpha (src_pixel[2],
232  src_pixel[3]); // R [0] <= [ 2 ]
233  dst_pixel[1] = demultiply_alpha (src_pixel[1],
234  src_pixel[3]); // G [1] <= [ 1 ]
235  dst_pixel[2] = demultiply_alpha (src_pixel[0],
236  src_pixel[3]); // B [2] <= [ 0 ]
237  dst_pixel[3] = src_pixel[3]; // alpha
238 
239 #elif G_BYTE_ORDER == G_BIG_ENDIAN
240  /* Cairo [ B G R A ] is actually [ A R G B ] in memory SOURCE
241  0 1 2 3
242  Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
243  */
244  dst_pixel[0] = demultiply_alpha (src_pixel[1],
245  src_pixel[0]); // R [0] <= [ 1 ]
246  dst_pixel[1] = demultiply_alpha (src_pixel[2],
247  src_pixel[0]); // G [1] <= [ 2 ]
248  dst_pixel[2] = demultiply_alpha (src_pixel[3],
249  src_pixel[0]); // B [2] <= [ 3 ]
250  dst_pixel[3] = src_pixel[0]; // alpha
251 
252 #else
253 #error ardour does not currently support PDP-endianess
254 #endif
255 
256  dst_pixel += 4;
257  src_pixel += 4;
258  }
259  }
260 }
261 
262 Glib::RefPtr<Gdk::Pixbuf>
263 Gtkmm2ext::pixbuf_from_string(const string& name, const Pango::FontDescription& font, int clip_width, int clip_height, Gdk::Color fg)
264 {
265  static Glib::RefPtr<Gdk::Pixbuf>* empty_pixbuf = 0;
266 
267  if (name.empty()) {
268  if (empty_pixbuf == 0) {
269  empty_pixbuf = new Glib::RefPtr<Gdk::Pixbuf>;
270  *empty_pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
271  }
272  return *empty_pixbuf;
273  }
274 
275  Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
276 
277  cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clip_width, clip_height);
278  cairo_t* cr = cairo_create (surface);
279  cairo_text_extents_t te;
280 
281  cairo_set_source_rgba (cr, fg.get_red_p(), fg.get_green_p(), fg.get_blue_p(), 1.0);
282  cairo_select_font_face (cr, font.get_family().c_str(),
283  CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
284  cairo_set_font_size (cr, font.get_size() / Pango::SCALE);
285  cairo_text_extents (cr, name.c_str(), &te);
286 
287  cairo_move_to (cr, 0.5, int (0.5 - te.height / 2 - te.y_bearing + clip_height / 2));
288  cairo_show_text (cr, name.c_str());
289 
290  convert_bgra_to_rgba(cairo_image_surface_get_data (surface), buf->get_pixels(), clip_width, clip_height);
291 
292  cairo_destroy(cr);
293  cairo_surface_destroy(surface);
294 
295  return buf;
296 }
297 
298 void
299 Gtkmm2ext::set_popdown_strings (Gtk::ComboBoxText& cr, const vector<string>& strings)
300 {
301  vector<string>::const_iterator i;
302 
303  cr.clear ();
304 
305  for (i = strings.begin(); i != strings.end(); ++i) {
306  cr.append_text (*i);
307  }
308 }
309 
310 void
311 Gtkmm2ext::get_popdown_strings (Gtk::ComboBoxText& cr, std::vector<std::string>& strings)
312 {
313  strings.clear ();
314  Glib::RefPtr<const Gtk::TreeModel> m = cr.get_model();
315  if (!m) {
316  return;
317  }
318  for(Gtk::TreeModel::iterator i = m->children().begin(); i != m->children().end(); ++i) {
319  Glib::ustring txt;
320  (*i)->get_value(0, txt);
321  strings.push_back (txt);
322  }
323 }
324 
325 bool
326 Gtkmm2ext::contains_value (Gtk::ComboBoxText& cr, const std::string text)
327 {
328  std::vector<std::string> s;
329  get_popdown_strings (cr, s);
330  return (std::find (s.begin(), s.end(), text) != s.end());
331 }
332 
333 bool
334 Gtkmm2ext::set_active_text_if_present (Gtk::ComboBoxText& cr, const std::string text)
335 {
336  if (contains_value(cr, text)) {
337  cr.set_active_text (text);
338  return true;
339  }
340  return false;
341 }
342 
343 GdkWindow*
344 Gtkmm2ext::get_paned_handle (Gtk::Paned& paned)
345 {
346  return GTK_PANED(paned.gobj())->handle;
347 }
348 
349 void
350 Gtkmm2ext::set_decoration (Gtk::Window* win, Gdk::WMDecoration decor)
351 {
352  win->get_window()->set_decorations (decor);
353 }
354 
356 {
357  gtk_tree_view_column_set_widget( c->gobj(), GTK_WIDGET(0) );
358 }
359 
360 void
361 Gtkmm2ext::detach_menu (Gtk::Menu& menu)
362 {
363  /* its possible for a Gtk::Menu to have no gobj() because it has
364  not yet been instantiated. Catch this and provide a safe
365  detach method.
366  */
367  if (menu.gobj()) {
368  if (menu.get_attach_widget()) {
369  menu.detach ();
370  }
371  }
372 }
373 
374 bool
376 {
377 #ifdef GTKOSX
378  /* GTK on OS X is currently (February 2012) setting both
379  the Meta and Mod2 bits in the event modifier state if
380  the Command key is down.
381 
382  gtk_accel_groups_activate() does not invoke any of the logic
383  that gtk_window_activate_key() will that sorts out that stupid
384  state of affairs, and as a result it fails to find a match
385  for the key event and the current set of accelerators.
386 
387  to fix this, if the meta bit is set, remove the mod2 bit
388  from the modifier. this assumes that our bindings use Primary
389  which will have set the meta bit in the accelerator entry.
390  */
391  if (mod & GDK_META_MASK) {
392  mod = GdkModifierType (mod & ~GDK_MOD2_MASK);
393  }
394 #endif
395  return true;
396 }
397 
398 bool
400 {
401  int fakekey = GDK_VoidSymbol;
402 
403  switch (keyval) {
404  case GDK_Tab:
405  case GDK_ISO_Left_Tab:
406  fakekey = GDK_nabla;
407  break;
408 
409  case GDK_Up:
410  fakekey = GDK_uparrow;
411  break;
412 
413  case GDK_Down:
414  fakekey = GDK_downarrow;
415  break;
416 
417  case GDK_Right:
418  fakekey = GDK_rightarrow;
419  break;
420 
421  case GDK_Left:
422  fakekey = GDK_leftarrow;
423  break;
424 
425  case GDK_Return:
426  fakekey = GDK_3270_Enter;
427  break;
428 
429  case GDK_KP_Enter:
430  fakekey = GDK_F35;
431  break;
432 
433  default:
434  break;
435  }
436 
437  if (fakekey != GDK_VoidSymbol) {
438  keyval = fakekey;
439  return true;
440  }
441 
442  return false;
443 }
444 
445 uint32_t
447 {
448  switch (keyval) {
449  case GDK_nabla:
450  return GDK_Tab;
451  break;
452 
453  case GDK_uparrow:
454  return GDK_Up;
455  break;
456 
457  case GDK_downarrow:
458  return GDK_Down;
459  break;
460 
461  case GDK_rightarrow:
462  return GDK_Right;
463  break;
464 
465  case GDK_leftarrow:
466  return GDK_Left;
467  break;
468 
469  case GDK_3270_Enter:
470  return GDK_Return;
471 
472  case GDK_F35:
473  return GDK_KP_Enter;
474  break;
475  }
476 
477  return keyval;
478 }
479 
480 int
481 Gtkmm2ext::physical_screen_height (Glib::RefPtr<Gdk::Window> win)
482 {
483  GdkScreen* scr = gdk_screen_get_default();
484 
485  if (win) {
486  GdkRectangle r;
487  gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
488  gdk_screen_get_monitor_geometry (scr, monitor, &r);
489  return r.height;
490  } else {
491  return gdk_screen_get_height (scr);
492  }
493 }
494 
495 int
496 Gtkmm2ext::physical_screen_width (Glib::RefPtr<Gdk::Window> win)
497 {
498  GdkScreen* scr = gdk_screen_get_default();
499 
500  if (win) {
501  GdkRectangle r;
502  gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
503  gdk_screen_get_monitor_geometry (scr, monitor, &r);
504  return r.width;
505  } else {
506  return gdk_screen_get_width (scr);
507  }
508 }
509 
510 void
511 Gtkmm2ext::container_clear (Gtk::Container& c)
512 {
513  list<Gtk::Widget*> children = c.get_children();
514  for (list<Gtk::Widget*>::iterator child = children.begin(); child != children.end(); ++child) {
515  c.remove (**child);
516  }
517 }
518 
519 void
520 Gtkmm2ext::rounded_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
521 {
522  rounded_rectangle (context->cobj(), x, y, w, h, r);
523 }
524 void
525 Gtkmm2ext::rounded_top_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
526 {
527  rounded_top_rectangle (context->cobj(), x, y, w, h, r);
528 }
529 void
530 Gtkmm2ext::rounded_top_left_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
531 {
532  rounded_top_left_rectangle (context->cobj(), x, y, w, h, r);
533 }
534 void
535 Gtkmm2ext::rounded_top_right_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
536 {
537  rounded_top_right_rectangle (context->cobj(), x, y, w, h, r);
538 }
539 void
540 Gtkmm2ext::rounded_top_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
541 {
542  rounded_top_half_rectangle (context->cobj(), x, y, w, h, r);
543 }
544 void
545 Gtkmm2ext::rounded_bottom_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
546 {
547  rounded_bottom_half_rectangle (context->cobj(), x, y, w, h, r);
548 }
549 
550 void
551 Gtkmm2ext::rounded_left_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
552 {
553  rounded_left_half_rectangle (context->cobj(), x, y, w, h, r);
554 }
555 
556 void
557 Gtkmm2ext::rounded_right_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
558 {
559  rounded_right_half_rectangle (context->cobj(), x, y, w, h, r);
560 }
561 
562 void
563 Gtkmm2ext::rounded_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
564 {
565  double degrees = M_PI / 180.0;
566 
567  cairo_new_sub_path (cr);
568  cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr
569  cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees); //br
570  cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl
571  cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl
572  cairo_close_path (cr);
573 }
574 
575 void
576 Gtkmm2ext::rounded_left_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
577 {
578  double degrees = M_PI / 180.0;
579 
580  cairo_new_sub_path (cr);
581  cairo_line_to (cr, x+w, y); // tr
582  cairo_line_to (cr, x+w, y + h); // br
583  cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl
584  cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl
585  cairo_close_path (cr);
586 }
587 
588 void
589 Gtkmm2ext::rounded_right_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
590 {
591  double degrees = M_PI / 180.0;
592 
593  cairo_new_sub_path (cr);
594  cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr
595  cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees); //br
596  cairo_line_to (cr, x, y + h); // bl
597  cairo_line_to (cr, x, y); // tl
598  cairo_close_path (cr);
599 }
600 
601 void
602 Gtkmm2ext::rounded_top_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
603 {
604  double degrees = M_PI / 180.0;
605 
606  cairo_new_sub_path (cr);
607  cairo_move_to (cr, x+w, y+h);
608  cairo_line_to (cr, x, y+h);
609  cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl
610  cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr
611  cairo_close_path (cr);
612 }
613 
614 void
615 Gtkmm2ext::rounded_bottom_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
616 {
617  double degrees = M_PI / 180.0;
618 
619  cairo_new_sub_path (cr);
620  cairo_move_to (cr, x, y);
621  cairo_line_to (cr, x+w, y);
622  cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees); //br
623  cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl
624  cairo_close_path (cr);
625 }
626 
627 
628 void
629 Gtkmm2ext::rounded_top_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
630 {
631  double degrees = M_PI / 180.0;
632 
633  cairo_new_sub_path (cr);
634  cairo_move_to (cr, x+w, y+h);
635  cairo_line_to (cr, x, y+h);
636  cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl
637  cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr
638  cairo_close_path (cr);
639 }
640 
641 void
642 Gtkmm2ext::rounded_top_left_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
643 {
644 /* A****B
645  H *
646  * *
647  * *
648  F****E
649 */
650  cairo_move_to (cr, x+r,y); // Move to A
651  cairo_line_to (cr, x+w,y); // Straight line to B
652  cairo_line_to (cr, x+w,y+h); // Move to E
653  cairo_line_to (cr, x,y+h); // Line to F
654  cairo_line_to (cr, x,y+r); // Line to H
655  cairo_curve_to (cr, x,y,x,y,x+r,y); // Curve to A
656 }
657 
658 void
659 Gtkmm2ext::rounded_top_right_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
660 {
661 /* A****BQ
662  * C
663  * *
664  * *
665  F****E
666 */
667  cairo_move_to (cr, x,y); // Move to A
668  cairo_line_to (cr, x+w-r,y); // Straight line to B
669  cairo_curve_to (cr, x+w,y,x+w,y,x+w,y+r); // Curve to C, Control points are both at Q
670  cairo_line_to (cr, x+w,y+h); // Move to E
671  cairo_line_to (cr, x,y+h); // Line to F
672  cairo_line_to (cr, x,y); // Line to A
673 }
674 
675 Glib::RefPtr<Gdk::Window>
676 Gtkmm2ext::window_to_draw_on (Gtk::Widget& w, Gtk::Widget** parent)
677 {
678  if (w.get_has_window()) {
679  return w.get_window();
680  }
681 
682  (*parent) = w.get_parent();
683 
684  while (*parent) {
685  if ((*parent)->get_has_window()) {
686  return (*parent)->get_window ();
687  }
688  (*parent) = (*parent)->get_parent ();
689  }
690 
691  return Glib::RefPtr<Gdk::Window> ();
692 }
693 
694 int
695 Gtkmm2ext::pixel_width (const string& str, Pango::FontDescription& font)
696 {
697  Gtk::Label foo;
698  Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
699 
700  layout->set_font_description (font);
701  layout->set_text (str);
702 
703  int width, height;
704  Gtkmm2ext::get_ink_pixel_size (layout, width, height);
705  return width;
706 }
707 
708 #if 0
709 string
710 Gtkmm2ext::fit_to_pixels (const string& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses)
711 {
712  /* DECEMBER 2011: THIS PROTOTYPE OF fit_to_pixels() IS NOT USED
713  ANYWHERE AND HAS NOT BEEN TESTED.
714  */
715  Gtk::Label foo;
716  Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout (str);
717  Glib::RefPtr<const Pango::LayoutLine> line;
718 
719  layout->set_font_description (font);
720  layout->set_width (pixel_width * PANGO_SCALE);
721 
722  if (with_ellipses) {
723  layout->set_ellipsize (Pango::ELLIPSIZE_END);
724  } else {
725  layout->set_wrap (Pango::WRAP_CHAR);
726  }
727 
728  line = layout->get_line (0);
729 
730  /* XXX: might need special care to get the ellipsis character, not sure
731  how that works
732  */
733 
734  string s = string (layout->get_text ().substr(line->get_start_index(), line->get_length()));
735 
736  cerr << "fit to pixels of " << str << " returns " << s << endl;
737 
738  return s;
739 }
740 #endif
741 
749 std::pair<std::string, double>
750 Gtkmm2ext::fit_to_pixels (cairo_t* cr, std::string name, double avail)
751 {
752  /* XXX hopefully there exists a more efficient way of doing this */
753 
754  bool abbreviated = false;
755  uint32_t width = 0;
756 
757  while (1) {
758  cairo_text_extents_t ext;
759  cairo_text_extents (cr, name.c_str(), &ext);
760 
761  if (ext.width < avail || name.length() <= 4) {
762  width = ext.width;
763  break;
764  }
765 
766  if (abbreviated) {
767  name = name.substr (0, name.length() - 4) + "...";
768  } else {
769  name = name.substr (0, name.length() - 3) + "...";
770  abbreviated = true;
771  }
772  }
773 
774  return std::make_pair (name, width);
775 }
776 
777 Gtk::Label *
778 Gtkmm2ext::left_aligned_label (string const & t)
779 {
780  Gtk::Label* l = new Gtk::Label (t);
781  l->set_alignment (0, 0.5);
782  return l;
783 }
784 
785 static bool
786 make_null_tooltip (int, int, bool, const Glib::RefPtr<Gtk::Tooltip>& t)
787 {
788  t->set_tip_area (Gdk::Rectangle (0, 0, 0, 0));
789  return true;
790 }
791 
796 void
798 {
799  w.property_has_tooltip() = true;
800  w.signal_query_tooltip().connect (sigc::ptr_fun (make_null_tooltip));
801 }
802 
803 void
805 {
806  gtk_rc_parse_string ("gtk-enable-tooltips = 1");
807 }
808 
809 void
811 {
812  gtk_rc_parse_string ("gtk-enable-tooltips = 0");
813 }
814 
815 bool
816 Gtkmm2ext::event_inside_widget_window (Gtk::Widget& widget, GdkEvent* ev)
817 {
818  gdouble evx, evy;
819 
820  if (!gdk_event_get_root_coords (ev, &evx, &evy)) {
821  return false;
822  }
823 
824  gint wx;
825  gint wy;
826  gint width, height, depth;
827  gint x, y;
828 
829  Glib::RefPtr<Gdk::Window> widget_window = widget.get_window();
830 
831  widget_window->get_geometry (x, y, width, height, depth);
832  widget_window->get_root_origin (wx, wy);
833 
834  if ((evx >= wx && evx < wx + width) &&
835  (evy >= wy && evy < wy + height)) {
836  return true;
837  }
838 
839  return false;
840 }
841 
842 const char*
844 {
845  switch (event_type) {
846  case GDK_NOTHING:
847  return "nothing";
848  case GDK_DELETE:
849  return "delete";
850  case GDK_DESTROY:
851  return "destroy";
852  case GDK_EXPOSE:
853  return "expose";
854  case GDK_MOTION_NOTIFY:
855  return "motion_notify";
856  case GDK_BUTTON_PRESS:
857  return "button_press";
858  case GDK_2BUTTON_PRESS:
859  return "2button_press";
860  case GDK_3BUTTON_PRESS:
861  return "3button_press";
862  case GDK_BUTTON_RELEASE:
863  return "button_release";
864  case GDK_KEY_PRESS:
865  return "key_press";
866  case GDK_KEY_RELEASE:
867  return "key_release";
868  case GDK_ENTER_NOTIFY:
869  return "enter_notify";
870  case GDK_LEAVE_NOTIFY:
871  return "leave_notify";
872  case GDK_FOCUS_CHANGE:
873  return "focus_change";
874  case GDK_CONFIGURE:
875  return "configure";
876  case GDK_MAP:
877  return "map";
878  case GDK_UNMAP:
879  return "unmap";
880  case GDK_PROPERTY_NOTIFY:
881  return "property_notify";
882  case GDK_SELECTION_CLEAR:
883  return "selection_clear";
884  case GDK_SELECTION_REQUEST:
885  return "selection_request";
886  case GDK_SELECTION_NOTIFY:
887  return "selection_notify";
888  case GDK_PROXIMITY_IN:
889  return "proximity_in";
890  case GDK_PROXIMITY_OUT:
891  return "proximity_out";
892  case GDK_DRAG_ENTER:
893  return "drag_enter";
894  case GDK_DRAG_LEAVE:
895  return "drag_leave";
896  case GDK_DRAG_MOTION:
897  return "drag_motion";
898  case GDK_DRAG_STATUS:
899  return "drag_status";
900  case GDK_DROP_START:
901  return "drop_start";
902  case GDK_DROP_FINISHED:
903  return "drop_finished";
904  case GDK_CLIENT_EVENT:
905  return "client_event";
906  case GDK_VISIBILITY_NOTIFY:
907  return "visibility_notify";
908  case GDK_NO_EXPOSE:
909  return "no_expose";
910  case GDK_SCROLL:
911  return "scroll";
912  case GDK_WINDOW_STATE:
913  return "window_state";
914  case GDK_SETTING:
915  return "setting";
916  case GDK_OWNER_CHANGE:
917  return "owner_change";
918  case GDK_GRAB_BROKEN:
919  return "grab_broken";
920  case GDK_DAMAGE:
921  return "damage";
922  }
923 
924  return "unknown";
925 }
static guint8 demultiply_alpha(guint8 src, guint8 alpha)
Definition: utils.cc:191
LIBGTKMM2EXT_API void get_pixel_size(Glib::RefPtr< Pango::Layout >, int &width, int &height)
Definition: utils.cc:62
LIBGTKMM2EXT_API bool event_inside_widget_window(Gtk::Widget &widget, GdkEvent *ev)
Definition: utils.cc:816
LIBGTKMM2EXT_API void set_size_request_to_display_given_text(Gtk::Widget &w, const gchar *text, gint hpadding, gint vpadding)
Definition: utils.cc:70
LIBGTKMM2EXT_API bool possibly_translate_mod_to_make_legal_accelerator(GdkModifierType &mod)
Definition: utils.cc:375
static bool make_null_tooltip(int, int, bool, const Glib::RefPtr< Gtk::Tooltip > &t)
Definition: utils.cc:786
#define bind_textdomain_codeset(Domainname, Codeset)
Definition: gettext.h:69
LIBGTKMM2EXT_API int physical_screen_width(Glib::RefPtr< Gdk::Window >)
Definition: utils.cc:496
LIBGTKMM2EXT_API void rounded_left_half_rectangle(Cairo::RefPtr< Cairo::Context >, double x, double y, double w, double h, double r=10)
Definition: utils.cc:551
LIBGTKMM2EXT_API bool set_active_text_if_present(Gtk::ComboBoxText &, const std::string)
Definition: utils.cc:334
LIBGTKMM2EXT_API int physical_screen_height(Glib::RefPtr< Gdk::Window >)
Definition: utils.cc:481
Definition: Beats.hpp:239
LIBGTKMM2EXT_API void rounded_bottom_half_rectangle(Cairo::RefPtr< Cairo::Context >, double x, double y, double w, double h, double r=10)
Definition: utils.cc:545
LIBGTKMM2EXT_API Glib::RefPtr< Gdk::Window > window_to_draw_on(Gtk::Widget &w, Gtk::Widget **parent)
Definition: utils.cc:676
LIBGTKMM2EXT_API bool contains_value(Gtk::ComboBoxText &, const std::string)
Definition: utils.cc:326
LIBGTKMM2EXT_API void set_popdown_strings(Gtk::ComboBoxText &, const std::vector< std::string > &)
LIBGTKMM2EXT_API void set_size_request_to_display_given_text_width(Gtk::Widget &w, const gchar *htext, gint hpadding, gint vpadding)
Definition: utils.cc:83
LIBGTKMM2EXT_API uint32_t possibly_translate_legal_accelerator_to_real_key(uint32_t keyval)
Definition: utils.cc:446
LIBGTKMM2EXT_API void rounded_top_half_rectangle(Cairo::RefPtr< Cairo::Context >, double x, double y, double w, double h, double r=10)
Definition: utils.cc:540
LIBGTKMM2EXT_API std::string fit_to_pixels(const std::string &, int pixel_width, Pango::FontDescription &font, int &actual_width, bool with_ellipses=false)
LIBGTKMM2EXT_API void set_no_tooltip_whatsoever(Gtk::Widget &)
Definition: utils.cc:797
static const char * localedir
Definition: load_session.cc:12
LIBGTKMM2EXT_API void rounded_top_rectangle(Cairo::RefPtr< Cairo::Context > context, double x, double y, double w, double h, double r=10)
Definition: utils.cc:525
LIBGTKMM2EXT_API void disable_tooltips()
Definition: utils.cc:810
LIBGTKMM2EXT_API void set_treeview_header_as_default_label(Gtk::TreeViewColumn *c)
Definition: utils.cc:355
LIBGTKMM2EXT_API Glib::RefPtr< Gdk::Pixbuf > pixbuf_from_string(const std::string &name, const Pango::FontDescription &font, int clip_width, int clip_height, Gdk::Color fg)
LIBGTKMM2EXT_API Gtk::Label * left_aligned_label(std::string const &)
LIBGTKMM2EXT_API GdkWindow * get_paned_handle(Gtk::Paned &paned)
Definition: utils.cc:344
LIBGTKMM2EXT_API void rounded_right_half_rectangle(Cairo::RefPtr< Cairo::Context >, double x, double y, double w, double h, double r=10)
Definition: utils.cc:557
LIBGTKMM2EXT_API void enable_tooltips()
Definition: utils.cc:804
LIBGTKMM2EXT_API bool possibly_translate_keyval_to_make_legal_accelerator(uint32_t &keyval)
Definition: utils.cc:399
#define bindtextdomain(Domainname, Dirname)
Definition: gettext.h:68
LIBGTKMM2EXT_API void convert_bgra_to_rgba(guint8 const *, guint8 *dst, int, int)
Definition: utils.cc:207
LIBGTKMM2EXT_API void get_popdown_strings(Gtk::ComboBoxText &, std::vector< std::string > &)
Definition: utils.cc:311
LIBGTKMM2EXT_API const char * event_type_string(int event_type)
Definition: utils.cc:843
LIBGTKMM2EXT_API void set_decoration(Gtk::Window *win, Gdk::WMDecoration decor)
Definition: utils.cc:350
LIBGTKMM2EXT_API void set_height_request_to_display_any_text(Gtk::Widget &w, gint vpadding)
Definition: utils.cc:102
LIBGTKMM2EXT_API void get_ink_pixel_size(Glib::RefPtr< Pango::Layout >, int &width, int &height)
Definition: utils.cc:51
const char * name
LIBGTKMM2EXT_API void init(const char *)
Definition: utils.cc:42
LIBGTKMM2EXT_API void rounded_rectangle(Cairo::RefPtr< Cairo::Context > context, double x, double y, double w, double h, double r=10)
Definition: utils.cc:520
LIBGTKMM2EXT_API int pixel_width(const std::string &str, Pango::FontDescription &font)
LIBGTKMM2EXT_API void detach_menu(Gtk::Menu &)
Definition: utils.cc:361
LIBGTKMM2EXT_API void rounded_top_left_rectangle(Cairo::RefPtr< Cairo::Context > context, double x, double y, double w, double h, double r=10)
Definition: utils.cc:530
LIBGTKMM2EXT_API void rounded_top_right_rectangle(Cairo::RefPtr< Cairo::Context > context, double x, double y, double w, double h, double r=10)
Definition: utils.cc:535
LIBGTKMM2EXT_API void container_clear(Gtk::Container &)
Definition: utils.cc:511