X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=gtk2_ardour%2Futils.cc;h=e353d609cc1dbd3f9efb84c51dfda0b9f5ebd45f;hb=137425faf1420e41231a11438c08efca3be40284;hp=e6dc2c57903941321426bfaca27d9ba05bcc433e;hpb=680c64246e4ee9f3eb53da079dea6a7ecf996e92;p=ardour.git diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index e6dc2c5790..e353d609cc 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -45,7 +45,9 @@ #include #include "ardour/rc_configuration.h" #include "ardour/filesystem_paths.h" + #include "canvas/item.h" +#include "canvas/utils.h" #include "ardour_ui.h" #include "debug.h" @@ -62,7 +64,13 @@ using namespace Glib; using namespace PBD; using Gtkmm2ext::Keyboard; -sigc::signal DPIReset; +namespace ARDOUR_UI_UTILS { + sigc::signal DPIReset; +} + +#ifdef PLATFORM_WINDOWS +#define random() rand() +#endif /** Add an element to a menu, settings its sensitivity. @@ -71,7 +79,7 @@ sigc::signal DPIReset; * @param s true to make sensitive, false to make insensitive */ void -add_item_with_sensitivity (Menu_Helpers::MenuList& m, Menu_Helpers::MenuElem e, bool s) +ARDOUR_UI_UTILS::add_item_with_sensitivity (Menu_Helpers::MenuList& m, Menu_Helpers::MenuElem e, bool s) { m.push_back (e); if (!s) { @@ -81,7 +89,7 @@ add_item_with_sensitivity (Menu_Helpers::MenuList& m, Menu_Helpers::MenuElem e, gint -just_hide_it (GdkEventAny */*ev*/, Gtk::Window *win) +ARDOUR_UI_UTILS::just_hide_it (GdkEventAny */*ev*/, Gtk::Window *win) { win->hide (); return 0; @@ -96,7 +104,7 @@ just_hide_it (GdkEventAny */*ev*/, Gtk::Window *win) */ unsigned char* -xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h) +ARDOUR_UI_UTILS::xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h) { static long vals[256], val; uint32_t t, x, y, colors, cpp; @@ -138,7 +146,7 @@ xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h) } unsigned char* -xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h) +ARDOUR_UI_UTILS::xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h) { static long vals[256], val; uint32_t t, x, y, colors, cpp; @@ -200,8 +208,34 @@ xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h) return (savergb); } +/** Returns a Pango::FontDescription given a string describing the font. + * + * If the returned FontDescription does not specify a family, then + * the family is set to "Sans". This mirrors GTK's behaviour in + * gtkstyle.c. + * + * Some environments will force Pango to specify the family + * even if it was not specified in the string describing the font. + * Such environments should be left unaffected by this function, + * since the font family will be left alone. + * + * There may be other similar font specification enforcement + * that we might add here later. + */ Pango::FontDescription -get_font_for_style (string widgetname) +ARDOUR_UI_UTILS::sanitized_font (std::string const& name) +{ + Pango::FontDescription fd (name); + + if (fd.get_family().empty()) { + fd.set_family ("Sans"); + } + + return fd; +} + +Pango::FontDescription +ARDOUR_UI_UTILS::get_font_for_style (string widgetname) { Gtk::Window window (WINDOW_TOPLEVEL); Gtk::Label foobar; @@ -230,7 +264,7 @@ get_font_for_style (string widgetname) } uint32_t -rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, string attr, int state, bool rgba) +ARDOUR_UI_UTILS::rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, string attr, int state, bool rgba) { /* In GTK+2, styles aren't set up correctly if the widget is not attached to a toplevel window that has a screen pointer. @@ -262,7 +296,6 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s a = rc->fg[GTK_STATE_ACTIVE].red / 257; } } else if (attr == "bg") { - r = g = b = 0; r = rc->bg[state].red / 257; g = rc->bg[state].green / 257; b = rc->bg[state].blue / 257; @@ -284,12 +317,12 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s if (state == Gtk::STATE_NORMAL && rgba) { return (uint32_t) RGBA_TO_UINT(r,g,b,a); } else { - return (uint32_t) RGB_TO_UINT(r,g,b); + return (uint32_t) RGBA_TO_UINT(r,g,b,255); } } bool -rgba_p_from_style (string style, float *r, float *g, float *b, string attr, int state) +ARDOUR_UI_UTILS::rgba_p_from_style (string style, float *r, float *g, float *b, string attr, int state) { static Gtk::Window* window = 0; assert (r && g && b); @@ -336,13 +369,41 @@ rgba_p_from_style (string style, float *r, float *g, float *b, string attr, int } void -set_color (Gdk::Color& c, int rgb) +ARDOUR_UI_UTILS::set_color_from_rgb (Gdk::Color& c, uint32_t rgb) +{ + /* Gdk::Color color ranges are 16 bit, so scale from 8 bit by + multiplying by 256. + */ + c.set_rgb ((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256); +} + +void +ARDOUR_UI_UTILS::set_color_from_rgba (Gdk::Color& c, uint32_t rgba) { - c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256); + /* Gdk::Color color ranges are 16 bit, so scale from 8 bit by + multiplying by 256. + */ + c.set_rgb ((rgba >> 24)*256, ((rgba & 0xff0000) >> 16)*256, ((rgba & 0xff00) >> 8)*256); } +uint32_t +ARDOUR_UI_UTILS::gdk_color_to_rgba (Gdk::Color const& c) +{ + /* since alpha value is not available from a Gdk::Color, it is + hardcoded as 0xff (aka 255 or 1.0) + */ + + const uint32_t r = c.get_red_p () * 255.0; + const uint32_t g = c.get_green_p () * 255.0; + const uint32_t b = c.get_blue_p () * 255.0; + const uint32_t a = 0xff; + + return RGBA_TO_UINT (r,g,b,a); +} + + bool -relay_key_press (GdkEventKey* ev, Gtk::Window* win) +ARDOUR_UI_UTILS::relay_key_press (GdkEventKey* ev, Gtk::Window* win) { PublicEditor& ed (PublicEditor::instance()); @@ -358,13 +419,13 @@ relay_key_press (GdkEventKey* ev, Gtk::Window* win) } bool -forward_key_press (GdkEventKey* ev) +ARDOUR_UI_UTILS::forward_key_press (GdkEventKey* ev) { - return PublicEditor::instance().on_key_press_event(ev); + return PublicEditor::instance().on_key_press_event(ev); } bool -emulate_key_event (Gtk::Widget* w, unsigned int keyval) +ARDOUR_UI_UTILS::emulate_key_event (Gtk::Widget* w, unsigned int keyval) { GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET(w->gobj())); GdkKeymap *keymap = gdk_keymap_get_for_display (display); @@ -393,7 +454,7 @@ emulate_key_event (Gtk::Widget* w, unsigned int keyval) } bool -key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) +ARDOUR_UI_UTILS::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) { GtkWindow* win = window.gobj(); GtkWidget* focus = gtk_window_get_focus (win); @@ -421,14 +482,15 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) #endif - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 allow_activation ? %6\n", + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 allow_activation ? %6\n", win, ev->keyval, ev->state, special_handling_of_unmodified_accelerators, Keyboard::some_magic_widget_has_focus(), allow_activating, - focus)); + focus, + (focus ? gtk_widget_get_name (focus) : "no focus widget"))); /* This exists to allow us to override the way GTK handles key events. The normal sequence is: @@ -524,8 +586,8 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) /* no special handling or there are modifiers in effect: accelerate first */ DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n"); - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 string:%4 hardware_keycode:%5 group:%6\n", - ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group)); + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n", + ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval))); if (allow_activating) { DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n"); @@ -564,17 +626,17 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) } Glib::RefPtr -get_xpm (std::string name) +ARDOUR_UI_UTILS::get_xpm (std::string name) { if (!xpm_map[name]) { - SearchPath spath(ARDOUR::ardour_data_search_path()); + Searchpath spath(ARDOUR::ardour_data_search_path()); spath.add_subdirectory_to_paths("pixmaps"); std::string data_file_path; - if(!find_file_in_search_path (spath, name, data_file_path)) { + if(!find_file (spath, name, data_file_path)) { fatal << string_compose (_("cannot find XPM file for %1"), name) << endmsg; } @@ -588,25 +650,89 @@ get_xpm (std::string name) return xpm_map[name]; } +vector +ARDOUR_UI_UTILS::get_icon_sets () +{ + Searchpath spath(ARDOUR::ardour_data_search_path()); + spath.add_subdirectory_to_paths ("icons"); + vector r; + + r.push_back (_("default")); + + for (vector::iterator s = spath.begin(); s != spath.end(); ++s) { + + vector entries; + + get_paths (entries, *s, false, false); + + for (vector::iterator e = entries.begin(); e != entries.end(); ++e) { + if (Glib::file_test (*e, Glib::FILE_TEST_IS_DIR)) { + r.push_back (Glib::filename_to_utf8 (Glib::path_get_basename(*e))); + } + } + } + + return r; +} + std::string -get_icon_path (const char* cname) +ARDOUR_UI_UTILS::get_icon_path (const char* cname, string icon_set, bool is_image) { + std::string data_file_path; string name = cname; - name += X_(".png"); - SearchPath spath(ARDOUR::ardour_data_search_path()); + if (is_image) { + name += X_(".png"); + } - spath.add_subdirectory_to_paths("icons"); + Searchpath spath(ARDOUR::ardour_data_search_path()); - std::string data_file_path; + if (!icon_set.empty() && icon_set != _("default")) { - if (!find_file_in_search_path (spath, name, data_file_path)) { - fatal << string_compose (_("cannot find icon image for %1 using %2"), name, spath.to_string()) << endmsg; + /* add "icons/icon_set" but .. not allowed to add both of these at once */ + spath.add_subdirectory_to_paths ("icons"); + spath.add_subdirectory_to_paths (icon_set); + + find_file (spath, name, data_file_path); + } else { + spath.add_subdirectory_to_paths ("icons"); + find_file (spath, name, data_file_path); + } + + if (is_image && data_file_path.empty()) { + + if (!icon_set.empty() && icon_set != _("default")) { + warning << string_compose (_("icon \"%1\" not found for icon set \"%2\", fallback to default"), cname, icon_set) << endmsg; + } + + Searchpath def (ARDOUR::ardour_data_search_path()); + def.add_subdirectory_to_paths ("icons"); + + if (!find_file (def, name, data_file_path)) { + fatal << string_compose (_("cannot find icon image for %1 using %2"), name, spath.to_string()) << endmsg; + abort(); /*NOTREACHED*/ + } } return data_file_path; } +Glib::RefPtr +ARDOUR_UI_UTILS::get_icon (const char* cname, string icon_set) +{ + Glib::RefPtr img; + try { + img = Gdk::Pixbuf::create_from_file (get_icon_path (cname, icon_set)); + } catch (const Gdk::PixbufError &e) { + cerr << "Caught PixbufError: " << e.what() << endl; + } catch (...) { + error << string_compose (_("Caught exception while loading icon named %1"), cname) << endmsg; + } + + return img; +} + +namespace ARDOUR_UI_UTILS { Glib::RefPtr get_icon (const char* cname) { @@ -621,9 +747,10 @@ get_icon (const char* cname) return img; } +} string -longest (vector& strings) +ARDOUR_UI_UTILS::longest (vector& strings) { if (strings.empty()) { return string (""); @@ -651,7 +778,7 @@ longest (vector& strings) } bool -key_is_legal_for_numeric_entry (guint keyval) +ARDOUR_UI_UTILS::key_is_legal_for_numeric_entry (guint keyval) { /* we assume that this does not change over the life of the process */ @@ -734,14 +861,17 @@ key_is_legal_for_numeric_entry (guint keyval) return false; } + void -set_pango_fontsize () +ARDOUR_UI_UTILS::set_pango_fontsize () { long val = ARDOUR::Config->get_font_scale(); /* FT2 rendering - used by GnomeCanvas, sigh */ +#ifndef PLATFORM_WINDOWS pango_ft2_font_map_set_resolution ((PangoFT2FontMap*) pango_ft2_font_map_new(), val/1024, val/1024); +#endif /* Cairo rendering, in case there is any */ @@ -749,7 +879,7 @@ set_pango_fontsize () } void -reset_dpi () +ARDOUR_UI_UTILS::reset_dpi () { long val = ARDOUR::Config->get_font_scale(); set_pango_fontsize (); @@ -761,7 +891,7 @@ reset_dpi () } void -resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int max_height) +ARDOUR_UI_UTILS::resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int max_height) { Glib::RefPtr screen = window->get_screen (); Gdk::Rectangle monitor_rect; @@ -776,7 +906,7 @@ resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int /** Replace _ with __ in a string; for use with menu item text to make underscores displayed correctly */ string -escape_underscores (string const & s) +ARDOUR_UI_UTILS::escape_underscores (string const & s) { string o; string::size_type const N = s.length (); @@ -794,7 +924,7 @@ escape_underscores (string const & s) /** Replace < and > with < and > respectively to make < > display correctly in markup strings */ string -escape_angled_brackets (string const & s) +ARDOUR_UI_UTILS::escape_angled_brackets (string const & s) { string o = s; boost::replace_all (o, "<", "<"); @@ -803,7 +933,7 @@ escape_angled_brackets (string const & s) } Gdk::Color -unique_random_color (list& used_colors) +ARDOUR_UI_UTILS::unique_random_color (list& used_colors) { Gdk::Color newcolor; @@ -844,7 +974,7 @@ unique_random_color (list& used_colors) } string -rate_as_string (float r) +ARDOUR_UI_UTILS::rate_as_string (float r) { char buf[32]; if (fmod (r, 1000.0f)) {