X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fgtkmm2ext%2Futils.cc;h=6efa95ac1a36e83ae57ea703a386d4ddf2f5a439;hb=93a64cb4fc1817bc0640e76de6b826d4fbfbd8c0;hp=63d7655331f3ec1c9f55c3f662b40d7653a1f911;hpb=eaf58fdd50a79aa4fa2760ca5dbeb2dd4cda2e15;p=ardour.git diff --git a/libs/gtkmm2ext/utils.cc b/libs/gtkmm2ext/utils.cc index 63d7655331..6efa95ac1a 100644 --- a/libs/gtkmm2ext/utils.cc +++ b/libs/gtkmm2ext/utils.cc @@ -19,27 +19,32 @@ */ #include +#include #include #include -#include #include #include #include #include #include #include +#include + +#include "gtkmm2ext/utils.h" #include "i18n.h" using namespace std; void -Gtkmm2ext::init () +Gtkmm2ext::init (const char* localedir) { - // Necessary for gettext - (void) bindtextdomain(PACKAGE, LOCALEDIR); +#ifdef ENABLE_NLS + (void) bindtextdomain(PACKAGE, localedir); + (void) bind_textdomain_codeset (PACKAGE, "UTF-8"); +#endif } void @@ -54,9 +59,9 @@ Gtkmm2ext::get_ink_pixel_size (Glib::RefPtr layout, } void -get_pixel_size (Glib::RefPtr layout, - int& width, - int& height) +Gtkmm2ext::get_pixel_size (Glib::RefPtr layout, + int& width, + int& height) { layout->get_pixel_size (width, height); } @@ -72,6 +77,51 @@ Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, const gchar * w.set_size_request(width + hpadding, height + vpadding); } +/** Set width request to display given text, and height to display anything. + This is useful for setting many widgets to the same height for consistency. */ +void +Gtkmm2ext::set_size_request_to_display_given_text_width (Gtk::Widget& w, + const gchar* htext, + gint hpadding, + gint vpadding) +{ + static const gchar* vtext = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + w.ensure_style (); + + int hwidth, hheight; + get_pixel_size (w.create_pango_layout (htext), hwidth, hheight); + + int vwidth, vheight; + get_pixel_size (w.create_pango_layout (vtext), vwidth, vheight); + + w.set_size_request(hwidth + hpadding, vheight + vpadding); +} + +void +Gtkmm2ext::set_height_request_to_display_any_text (Gtk::Widget& w, gint vpadding) +{ + static const gchar* vtext = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + w.ensure_style (); + + int width, height; + get_pixel_size (w.create_pango_layout (vtext), width, height); + + w.set_size_request(-1, height + vpadding); +} + +void +Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, std::string const & text, + gint hpadding, gint vpadding) +{ + int width, height; + w.ensure_style (); + + get_pixel_size (w.create_pango_layout (text), width, height); + w.set_size_request(width + hpadding, height + vpadding); +} + void Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, const std::vector& strings, @@ -110,6 +160,33 @@ Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, w.set_size_request(width_max + hpadding, height_max + vpadding); } +/** This version specifies horizontal padding in text to avoid assumptions + about font size. Should be used anywhere padding is used to avoid text, + like combo boxes. */ +void +Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget& w, + const std::vector& strings, + const std::string& hpadding, + gint vpadding) +{ + int width_max = 0; + int height_max = 0; + w.ensure_style (); + + for (vector::const_iterator i = strings.begin(); i != strings.end(); ++i) { + int width, height; + get_pixel_size (w.create_pango_layout (*i), width, height); + width_max = max(width_max,width); + height_max = max(height_max, height); + } + + int pad_width; + int pad_height; + get_pixel_size (w.create_pango_layout (hpadding), pad_width, pad_height); + + w.set_size_request(width_max + pad_width, height_max + vpadding); +} + static inline guint8 demultiply_alpha (guint8 src, guint8 alpha) @@ -126,11 +203,11 @@ demultiply_alpha (guint8 src, return alpha ? ((guint (src) << 8) - src) / alpha : 0; } -static void -convert_bgra_to_rgba (guint8 const* src, - guint8* dst, - int width, - int height) +void +Gtkmm2ext::convert_bgra_to_rgba (guint8 const* src, + guint8* dst, + int width, + int height) { guint8 const* src_pixel = src; guint8* dst_pixel = dst; @@ -230,6 +307,39 @@ Gtkmm2ext::set_popdown_strings (Gtk::ComboBoxText& cr, const vector& str } } +void +Gtkmm2ext::get_popdown_strings (Gtk::ComboBoxText& cr, std::vector& strings) +{ + strings.clear (); + Glib::RefPtr m = cr.get_model(); + if (!m) { + return; + } + for(Gtk::TreeModel::iterator i = m->children().begin(); i != m->children().end(); ++i) { + Glib::ustring txt; + (*i)->get_value(0, txt); + strings.push_back (txt); + } +} + +bool +Gtkmm2ext::contains_value (Gtk::ComboBoxText& cr, const std::string text) +{ + std::vector s; + get_popdown_strings (cr, s); + return (std::find (s.begin(), s.end(), text) != s.end()); +} + +bool +Gtkmm2ext::set_active_text_if_present (Gtk::ComboBoxText& cr, const std::string text) +{ + if (contains_value(cr, text)) { + cr.set_active_text (text); + return true; + } + return false; +} + GdkWindow* Gtkmm2ext::get_paned_handle (Gtk::Paned& paned) { @@ -261,6 +371,30 @@ Gtkmm2ext::detach_menu (Gtk::Menu& menu) } } +bool +Gtkmm2ext::possibly_translate_mod_to_make_legal_accelerator (GdkModifierType& mod) +{ +#ifdef GTKOSX + /* GTK on OS X is currently (February 2012) setting both + the Meta and Mod2 bits in the event modifier state if + the Command key is down. + + gtk_accel_groups_activate() does not invoke any of the logic + that gtk_window_activate_key() will that sorts out that stupid + state of affairs, and as a result it fails to find a match + for the key event and the current set of accelerators. + + to fix this, if the meta bit is set, remove the mod2 bit + from the modifier. this assumes that our bindings use Primary + which will have set the meta bit in the accelerator entry. + */ + if (mod & GDK_META_MASK) { + mod = GdkModifierType (mod & ~GDK_MOD2_MASK); + } +#endif + return true; +} + bool Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval) { @@ -413,79 +547,95 @@ Gtkmm2ext::rounded_bottom_half_rectangle (Cairo::RefPtr context, rounded_bottom_half_rectangle (context->cobj(), x, y, w, h, r); } +void +Gtkmm2ext::rounded_left_half_rectangle (Cairo::RefPtr context, double x, double y, double w, double h, double r) +{ + rounded_left_half_rectangle (context->cobj(), x, y, w, h, r); +} + +void +Gtkmm2ext::rounded_right_half_rectangle (Cairo::RefPtr context, double x, double y, double w, double h, double r) +{ + rounded_right_half_rectangle (context->cobj(), x, y, w, h, r); +} + void Gtkmm2ext::rounded_rectangle (cairo_t* cr, double x, double y, double w, double h, double r) { -/* A****BQ - H C - * * - G D - F****E -*/ - cairo_move_to (cr, x+r,y); // Move to A - cairo_line_to (cr, x+w-r,y); // Straight line to B - cairo_curve_to (cr, x+w,y,x+w,y,x+w,y+r); // Curve to C, Control points are both at Q - cairo_line_to (cr, x+w,y+h-r); // Move to D - cairo_curve_to (cr, x+w,y+h,x+w,y+h,x+w-r,y+h); // Curve to E - cairo_line_to (cr, x+r,y+h); // Line to F - cairo_curve_to (cr, x,y+h,x,y+h,x,y+h-r); // Curve to G - cairo_line_to (cr, x,y+r); // Line to H - cairo_curve_to (cr, x,y,x,y,x+r,y); // Curve to A + double degrees = M_PI / 180.0; + + cairo_new_sub_path (cr); + cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr + cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees); //br + cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl + cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl + cairo_close_path (cr); +} + +void +Gtkmm2ext::rounded_left_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r) +{ + double degrees = M_PI / 180.0; + + cairo_new_sub_path (cr); + cairo_line_to (cr, x+w, y); // tr + cairo_line_to (cr, x+w, y + h); // br + cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl + cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl + cairo_close_path (cr); +} + +void +Gtkmm2ext::rounded_right_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r) +{ + double degrees = M_PI / 180.0; + + cairo_new_sub_path (cr); + cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr + cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees); //br + cairo_line_to (cr, x, y + h); // bl + cairo_line_to (cr, x, y); // tl + cairo_close_path (cr); } void Gtkmm2ext::rounded_top_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r) { -/* A****BQ - H C - * * - G D - F****E -*/ - cairo_move_to (cr, x+r,y); // Move to A - cairo_line_to (cr, x+w-r,y); // Straight line to B - cairo_curve_to (cr, x+w,y,x+w,y,x+w,y+r); // Curve to C, Control points are both at Q - cairo_line_to (cr, x+w,y+h); // Move to E - cairo_line_to (cr, x,y+h); // Line to F - cairo_line_to (cr, x,y+r); // Line to H - cairo_curve_to (cr, x,y,x,y,x+r,y); // Curve to A + double degrees = M_PI / 180.0; + + cairo_new_sub_path (cr); + cairo_move_to (cr, x+w, y+h); + cairo_line_to (cr, x, y+h); + cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl + cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr + cairo_close_path (cr); } void Gtkmm2ext::rounded_bottom_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r) { -/* A****BQ - H C - * * - G D - F****E -*/ - cairo_move_to (cr, x,y); // Move to A - cairo_line_to (cr, x+w,y); // Straight line to B - cairo_line_to (cr, x+w,y+h-r); // Move to D - cairo_curve_to (cr, x+w,y+h,x+w,y+h,x+w-r,y+h); // Curve to E - cairo_line_to (cr, x+r,y+h); // Line to F - cairo_curve_to (cr, x,y+h,x,y+h,x,y+h-r); // Curve to G - cairo_line_to (cr, x,y); // Line to A + double degrees = M_PI / 180.0; + + cairo_new_sub_path (cr); + cairo_move_to (cr, x, y); + cairo_line_to (cr, x+w, y); + cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees); //br + cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl + cairo_close_path (cr); } void Gtkmm2ext::rounded_top_rectangle (cairo_t* cr, double x, double y, double w, double h, double r) { -/* A****BQ - H C - * * - * * - F****E -*/ - cairo_move_to (cr, x+r,y); // Move to A - cairo_line_to (cr, x+w-r,y); // Straight line to B - cairo_curve_to (cr, x+w,y,x+w,y,x+w,y+r); // Curve to C, Control points are both at Q - cairo_line_to (cr, x+w,y+h); // Move to E - cairo_line_to (cr, x,y+h); // Line to F - cairo_line_to (cr, x,y+r); // Line to H - cairo_curve_to (cr, x,y,x,y,x+r,y); // Curve to A + double degrees = M_PI / 180.0; + + cairo_new_sub_path (cr); + cairo_move_to (cr, x+w, y+h); + cairo_line_to (cr, x, y+h); + cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl + cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr + cairo_close_path (cr); } void @@ -555,6 +705,18 @@ Gtkmm2ext::pixel_width (const string& str, Pango::FontDescription& font) return width; } +void +Gtkmm2ext::pixel_size (const string& str, Pango::FontDescription& font, int& width, int& height) +{ + Gtk::Label foo; + Glib::RefPtr layout = foo.create_pango_layout (""); + + layout->set_font_description (font); + layout->set_text (str); + + Gtkmm2ext::get_ink_pixel_size (layout, width, height); +} + #if 0 string Gtkmm2ext::fit_to_pixels (const string& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses) @@ -631,3 +793,145 @@ Gtkmm2ext::left_aligned_label (string const & t) l->set_alignment (0, 0.5); return l; } + +static bool +make_null_tooltip (int, int, bool, const Glib::RefPtr& t) +{ + t->set_tip_area (Gdk::Rectangle (0, 0, 0, 0)); + return true; +} + +/** Hackily arrange for the provided widget to have no tooltip, + * and also to stop any other widget from providing one while + * the mouse is over w. + */ +void +Gtkmm2ext::set_no_tooltip_whatsoever (Gtk::Widget& w) +{ + w.property_has_tooltip() = true; + w.signal_query_tooltip().connect (sigc::ptr_fun (make_null_tooltip)); +} + +void +Gtkmm2ext::enable_tooltips () +{ + gtk_rc_parse_string ("gtk-enable-tooltips = 1"); +} + +void +Gtkmm2ext::disable_tooltips () +{ + gtk_rc_parse_string ("gtk-enable-tooltips = 0"); +} + +bool +Gtkmm2ext::event_inside_widget_window (Gtk::Widget& widget, GdkEvent* ev) +{ + gdouble evx, evy; + + if (!gdk_event_get_root_coords (ev, &evx, &evy)) { + return false; + } + + gint wx; + gint wy; + gint width, height, depth; + gint x, y; + + Glib::RefPtr widget_window = widget.get_window(); + + widget_window->get_geometry (x, y, width, height, depth); + widget_window->get_root_origin (wx, wy); + + if ((evx >= wx && evx < wx + width) && + (evy >= wy && evy < wy + height)) { + return true; + } + + return false; +} + +const char* +Gtkmm2ext::event_type_string (int event_type) +{ + switch (event_type) { + case GDK_NOTHING: + return "nothing"; + case GDK_DELETE: + return "delete"; + case GDK_DESTROY: + return "destroy"; + case GDK_EXPOSE: + return "expose"; + case GDK_MOTION_NOTIFY: + return "motion_notify"; + case GDK_BUTTON_PRESS: + return "button_press"; + case GDK_2BUTTON_PRESS: + return "2button_press"; + case GDK_3BUTTON_PRESS: + return "3button_press"; + case GDK_BUTTON_RELEASE: + return "button_release"; + case GDK_KEY_PRESS: + return "key_press"; + case GDK_KEY_RELEASE: + return "key_release"; + case GDK_ENTER_NOTIFY: + return "enter_notify"; + case GDK_LEAVE_NOTIFY: + return "leave_notify"; + case GDK_FOCUS_CHANGE: + return "focus_change"; + case GDK_CONFIGURE: + return "configure"; + case GDK_MAP: + return "map"; + case GDK_UNMAP: + return "unmap"; + case GDK_PROPERTY_NOTIFY: + return "property_notify"; + case GDK_SELECTION_CLEAR: + return "selection_clear"; + case GDK_SELECTION_REQUEST: + return "selection_request"; + case GDK_SELECTION_NOTIFY: + return "selection_notify"; + case GDK_PROXIMITY_IN: + return "proximity_in"; + case GDK_PROXIMITY_OUT: + return "proximity_out"; + case GDK_DRAG_ENTER: + return "drag_enter"; + case GDK_DRAG_LEAVE: + return "drag_leave"; + case GDK_DRAG_MOTION: + return "drag_motion"; + case GDK_DRAG_STATUS: + return "drag_status"; + case GDK_DROP_START: + return "drop_start"; + case GDK_DROP_FINISHED: + return "drop_finished"; + case GDK_CLIENT_EVENT: + return "client_event"; + case GDK_VISIBILITY_NOTIFY: + return "visibility_notify"; + case GDK_NO_EXPOSE: + return "no_expose"; + case GDK_SCROLL: + return "scroll"; + case GDK_WINDOW_STATE: + return "window_state"; + case GDK_SETTING: + return "setting"; + case GDK_OWNER_CHANGE: + return "owner_change"; + case GDK_GRAB_BROKEN: + return "grab_broken"; + case GDK_DAMAGE: + return "damage"; + } + + return "unknown"; +}