X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fgtkmm2ext%2Futils.cc;h=6efa95ac1a36e83ae57ea703a386d4ddf2f5a439;hb=93a64cb4fc1817bc0640e76de6b826d4fbfbd8c0;hp=a11b431ef0c4a3e8bcb2d805e39b5127c38a4cc6;hpb=b0e4f81eb3a38b7236ec39f11d5211840a064d15;p=ardour.git diff --git a/libs/gtkmm2ext/utils.cc b/libs/gtkmm2ext/utils.cc index a11b431ef0..6efa95ac1a 100644 --- a/libs/gtkmm2ext/utils.cc +++ b/libs/gtkmm2ext/utils.cc @@ -19,6 +19,7 @@ */ #include +#include #include #include @@ -42,6 +43,7 @@ Gtkmm2ext::init (const char* localedir) { #ifdef ENABLE_NLS (void) bindtextdomain(PACKAGE, localedir); + (void) bind_textdomain_codeset (PACKAGE, "UTF-8"); #endif } @@ -57,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); } @@ -75,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, @@ -113,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) @@ -233,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) { @@ -264,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) { @@ -415,6 +546,13 @@ 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) { @@ -434,6 +572,19 @@ Gtkmm2ext::rounded_rectangle (cairo_t* cr, double x, double y, double w, double 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) { @@ -554,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) @@ -661,3 +824,114 @@ 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"; +}