Small cleanups to port matrix context menu.
[ardour.git] / gtk2_ardour / utils.cc
index df922c2d629239b380feb5c585fd9c012a5b070f..0f53b0912f27f05232eef85a7d603c119a1617f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2003 Paul Davis 
+    Copyright (C) 2003 Paul Davis
 
     This program is free software; you an redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
 #include <gtkmm2ext/utils.h>
 #include "ardour/configuration.h"
-#include "ardour/configuration.h"
+#include "ardour/rc_configuration.h"
 
 #include "ardour/filesystem_paths.h"
 
 #include "ardour_ui.h"
+#include "public_editor.h"
 #include "keyboard.h"
 #include "utils.h"
 #include "i18n.h"
@@ -98,7 +99,7 @@ fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font
                        actual_width = width;
                        break;
                }
-               
+
                ustr.erase (last--);
                shorter_by++;
 
@@ -127,7 +128,7 @@ fit_to_pixels (cairo_t* cr, std::string name, double avail)
 
        bool abbreviated = false;
        uint32_t width = 0;
-               
+
        while (1) {
                cairo_text_extents_t ext;
                cairo_text_extents (cr, name.c_str(), &ext);
@@ -186,9 +187,9 @@ xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h)
        uint32_t t, x, y, colors, cpp;
        unsigned char c;
        unsigned char *savergb, *rgb;
-       
+
        // PARSE HEADER
-       
+
        if ( sscanf(xpm[0], "%u%u%u%u", &w, &h, &colors, &cpp) != 4 ) {
                error << string_compose (_("bad XPM header %1"), xpm[0])
                      << endmsg;
@@ -196,13 +197,13 @@ xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h)
        }
 
        savergb = rgb = (unsigned char*) malloc (h * w * 3);
-       
+
        // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
        for (t = 0; t < colors; ++t) {
                sscanf (xpm[t+1], "%c c #%lx", &c, &val);
                vals[c] = val;
        }
-       
+
        // COLORMAP -> RGB CONVERSION
        //    Get low 3 bytes from vals[]
        //
@@ -239,7 +240,7 @@ xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h)
        }
 
        savergb = rgb = (unsigned char*) malloc (h * w * 4);
-       
+
        // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
 
        if (strstr (xpm[1], "None")) {
@@ -254,7 +255,7 @@ xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h)
                sscanf (xpm[t+1], "%c c #%lx", &c, &val);
                vals[c] = val;
        }
-       
+
        // COLORMAP -> RGB CONVERSION
        //    Get low 3 bytes from vals[]
        //
@@ -310,17 +311,17 @@ get_font_for_style (string widgetname)
        style = foobar.get_style ();
 
        Glib::RefPtr<const Pango::Layout> layout = foobar.get_layout();
-       
+
        PangoFontDescription *pfd = (PangoFontDescription *)pango_layout_get_font_description((PangoLayout *)layout->gobj());
-       
+
        if (!pfd) {
-               
+
                /* layout inherited its font description from a PangoContext */
 
                PangoContext* ctxt = (PangoContext*) pango_layout_get_context ((PangoLayout*) layout->gobj());
                pfd =  pango_context_get_font_description (ctxt);
                return new Pango::FontDescription (pfd, true); /* make a copy */
-       } 
+       }
 
        return new Pango::FontDescription (pfd, true); /* make a copy */
 }
@@ -339,12 +340,12 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s
        }
 
        Gtk::Label foo;
-       
+
        window->add (foo);
 
        foo.set_name (style);
        foo.ensure_style ();
-       
+
        GtkRcStyle* waverc = foo.get_style()->gobj()->rc_style;
 
        if (waverc) {
@@ -352,7 +353,7 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s
                        r = waverc->fg[state].red / 257;
                        g = waverc->fg[state].green / 257;
                        b = waverc->fg[state].blue / 257;
+
                        /* what a hack ... "a" is for "active" */
                        if (state == Gtk::STATE_NORMAL && rgba) {
                                a = waverc->fg[GTK_STATE_ACTIVE].red / 257;
@@ -376,7 +377,7 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s
        }
 
        window->remove ();
-       
+
        if (state == Gtk::STATE_NORMAL && rgba) {
                return (uint32_t) RGBA_TO_UINT(r,g,b,a);
        } else {
@@ -490,7 +491,7 @@ gc_from_style (string widget_style_name, int state, string attr)
 }
 
 
-bool 
+bool
 canvas_item_visible (ArdourCanvas::Item* item)
 {
        return (item->gobj()->object.flags & GNOME_CANVAS_ITEM_VISIBLE) ? true : false;
@@ -508,6 +509,16 @@ extern "C" {
 }
 #endif
 
+bool
+relay_key_press (GdkEventKey* ev, Gtk::Window* win)
+{
+       if (!key_press_focus_accelerator_handler (*win, ev)) {
+               return PublicEditor::instance().on_key_press_event(ev);
+       } else {
+               return true;
+       }
+}
+
 bool
 key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 {
@@ -524,8 +535,8 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        if (focus) {
                if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
                        special_handling_of_unmodified_accelerators = true;
-               } 
-       } 
+               }
+       }
 
 #ifdef GTKOSX
        /* should this be universally true? */
@@ -536,7 +547,7 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 
 #ifdef DEBUG_ACCELERATOR_HANDLING
        if (debug) {
-               cerr << "Win = " << win << " Key event: code = " << ev->keyval << " state = " << hex << ev->state << dec << " special handling ? " 
+               cerr << "Win = " << win << " Key event: code = " << ev->keyval << " state = " << hex << ev->state << dec << " special handling ? "
                     << special_handling_of_unmodified_accelerators
                     << " magic widget focus ? "
                     << Keyboard::some_magic_widget_has_focus()
@@ -555,18 +566,18 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
               the focus widget and/or focus chain
 
           The problem with this is that if the accelerators include
-          keys without modifiers, such as the space bar or the 
+          keys without modifiers, such as the space bar or the
           letter "e", then pressing the key while typing into
           a text entry widget results in the accelerator being
           activated, instead of the desired letter appearing
           in the text entry.
 
           There is no good way of fixing this, but this
-          represents a compromise. The idea is that 
+          represents a compromise. The idea is that
           key events involving modifiers (not Shift)
           get routed into the activation pathway first, then
           get propagated to the focus widget if necessary.
-          
+
           If the key event doesn't involve modifiers,
           we deliver to the focus widget first, thus allowing
           it to get "normal text" without interference
@@ -637,9 +648,9 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 #endif
                return gtk_window_propagate_key_event (win, ev);
        }
-       
+
        /* no modifiers, propagate first */
-       
+
 #ifdef DEBUG_ACCELERATOR_HANDLING
        if (debug) {
                cerr << "\tpropagate, then activate\n";
@@ -653,15 +664,15 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 #endif
 
                if (allow_activating) {
-                       
+
 #ifdef GTKOSX
                        if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
                                return true;
                        }
 #endif
                        return gtk_window_activate_key (win, ev);
-               } 
-                       
+               }
+
        } else {
 #ifdef DEBUG_ACCELERATOR_HANDLING
                if (debug) {
@@ -679,22 +690,22 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        return true;
 }
 
-Glib::RefPtr<Gdk::Pixbuf>      
+Glib::RefPtr<Gdk::Pixbuf>
 get_xpm (std::string name)
 {
        if (!xpm_map[name]) {
 
                SearchPath spath(ARDOUR::ardour_search_path());
                spath += ARDOUR::system_data_search_path();
-               
+
                spath.add_subdirectory_to_paths("pixmaps");
-               
+
                sys::path data_file_path;
-               
+
                if(!find_file_in_search_path (spath, name, data_file_path)) {
                        fatal << string_compose (_("cannot find XPM file for %1"), name) << endmsg;
                }
-               
+
                try {
                        xpm_map[name] =  Gdk::Pixbuf::create_from_file (data_file_path.to_string());
                } catch(const Glib::Error& e)   {
@@ -705,9 +716,8 @@ get_xpm (std::string name)
        return xpm_map[name];
 }
 
-
-Glib::RefPtr<Gdk::Pixbuf>      
-get_icon (const char* cname)
+Glib::ustring
+get_icon_path (const char* cname)
 {
        string name = cname;
        name += X_(".png");
@@ -723,9 +733,15 @@ get_icon (const char* cname)
                fatal << string_compose (_("cannot find icon image for %1"), name) << endmsg;
        }
 
+       return data_file_path.to_string();
+}
+
+Glib::RefPtr<Gdk::Pixbuf>
+get_icon (const char* cname)
+{
        Glib::RefPtr<Gdk::Pixbuf> img;
        try {
-               img = Gdk::Pixbuf::create_from_file (data_file_path.to_string());
+               img = Gdk::Pixbuf::create_from_file (get_icon_path (cname));
        } catch (const Gdk::PixbufError &e) {
                cerr << "Caught PixbufError: " << e.what() << endl;
        } catch (...) {
@@ -744,22 +760,22 @@ longest (vector<string>& strings)
 
        vector<string>::iterator longest = strings.begin();
        string::size_type longest_length = (*longest).length();
-       
+
        vector<string>::iterator i = longest;
        ++i;
 
        while (i != strings.end()) {
-               
+
                string::size_type len = (*i).length();
-               
+
                if (len > longest_length) {
                        longest = i;
                        longest_length = len;
-               } 
-               
+               }
+
                ++i;
        }
-       
+
        return *longest;
 }
 
@@ -803,7 +819,7 @@ key_is_legal_for_numeric_entry (guint keyval)
        case GDK_Left:
        case GDK_Right:
                return true;
-               
+
        default:
                break;
        }
@@ -820,7 +836,7 @@ set_pango_fontsize ()
        pango_ft2_font_map_set_resolution ((PangoFT2FontMap*) pango_ft2_font_map_for_display(), val/1024, val/1024);
 
        /* Cairo rendering, in case there is any */
-       
+
        pango_cairo_font_map_set_resolution ((PangoCairoFontMap*) pango_cairo_font_map_get_default(), val/1024);
 }
 
@@ -846,35 +862,35 @@ possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval)
        case GDK_ISO_Left_Tab:
                fakekey = GDK_nabla;
                break;
-               
+
        case GDK_Up:
                fakekey = GDK_uparrow;
                break;
-               
+
        case GDK_Down:
                fakekey = GDK_downarrow;
                break;
-               
+
        case GDK_Right:
                fakekey = GDK_rightarrow;
                break;
-               
+
        case GDK_Left:
                fakekey = GDK_leftarrow;
                break;
-               
+
        default:
                break;
        }
-       
+
        if (fakekey != GDK_VoidSymbol) {
                keyval = fakekey;
                return true;
-       } 
+       }
 
        return false;
 }
-               
+
 
 inline guint8
 convert_color_channel (guint8 src,
@@ -891,7 +907,7 @@ convert_bgra_to_rgba (guint8 const* src,
 {
        guint8 const* src_pixel = src;
        guint8*       dst_pixel = dst;
-       
+
        for (int y = 0; y < height; y++)
                for (int x = 0; x < width; x++)
                {
@@ -902,8 +918,58 @@ convert_bgra_to_rgba (guint8 const* src,
                        dst_pixel[2] = convert_color_channel (src_pixel[0],
                                                              src_pixel[3]);
                        dst_pixel[3] = src_pixel[3];
-                       
+
                        dst_pixel += 4;
                        src_pixel += 4;
                }
 }
+
+void
+resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int max_height)
+{
+       Glib::RefPtr<Gdk::Screen> screen = window->get_screen ();
+       Gdk::Rectangle monitor_rect;
+       screen->get_monitor_geometry (0, monitor_rect);
+
+       int const w = std::min (monitor_rect.get_width(), max_width) * 0.8;
+       int const h = std::min (monitor_rect.get_height(), max_height) * 0.8;
+
+       window->resize (w, h);
+}
+
+Glib::RefPtr<Gdk::Pixbuf>
+pixbuf_from_ustring(const ustring& name, Pango::FontDescription* font, int clip_width, int clip_height)
+{
+       static Glib::RefPtr<Gdk::Pixbuf>* empty_pixbuf = 0;
+
+       if (name.empty()) {
+               if (empty_pixbuf == 0) {
+                       empty_pixbuf = new Glib::RefPtr<Gdk::Pixbuf>;
+                       *empty_pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
+               }
+               cerr << "\n\nUSE EMPTY PIXBUF\n";
+               return *empty_pixbuf;
+       }
+
+       Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
+
+       cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clip_width, clip_height);
+       cairo_t* cr = cairo_create (surface);
+       cairo_text_extents_t te;
+       
+       cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
+       cairo_select_font_face (cr, font->get_family().c_str(),
+                               CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+       cairo_set_font_size (cr,  font->get_size() / Pango::SCALE);
+       cairo_text_extents (cr, name.c_str(), &te);
+       
+       cairo_move_to (cr, 0.5, 0.5 - te.height / 2 - te.y_bearing + clip_height / 2);
+       cairo_show_text (cr, name.c_str());
+       
+       convert_bgra_to_rgba(cairo_image_surface_get_data (surface), buf->get_pixels(), clip_width, clip_height);
+
+       cairo_destroy(cr);
+       cairo_surface_destroy(surface);
+
+       return buf;
+}