waf build works on OS X ; new bindings file and processing system in place for mnemon...
[ardour.git] / gtk2_ardour / utils.cc
index d083b17a1eee7958c0ad377d78855e29f9ed3237..7a1c9c696841861c56bdc6cf995899b335cb41f8 100644 (file)
 #include <gtkmm/paned.h>
 #include <gtk/gtkpaned.h>
 
-#include <pbd/file_utils.h>
+#include "pbd/file_utils.h"
 
 #include <gtkmm2ext/utils.h>
-#include <ardour/configuration.h>
-#include <ardour/configuration.h>
+#include "ardour/configuration.h"
+#include "ardour/configuration.h"
 
-#include <ardour/filesystem_paths.h>
+#include "ardour/filesystem_paths.h"
 
 #include "ardour_ui.h"
 #include "keyboard.h"
@@ -113,11 +113,62 @@ fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font
        return txt;
 }
 
+/** Try to fit a string into a given horizontal space by ellipsizing it.
+ *  @param cr Cairo context in which the text will be plotted.
+ *  @param name Text.
+ *  @param avail Available horizontal space.
+ *  @return (Text, possibly ellipsized) and (horizontal size of text)
+ */
+
+std::pair<std::string, double>
+fit_to_pixels (cairo_t* cr, std::string name, double avail)
+{
+       /* XXX hopefully there exists a more efficient way of doing this */
+
+       bool abbreviated = false;
+       uint32_t width = 0;
+               
+       while (1) {
+               cairo_text_extents_t ext;
+               cairo_text_extents (cr, name.c_str(), &ext);
+
+               if (ext.width < avail || name.length() <= 4) {
+                       width = ext.width;
+                       break;
+               }
+
+               if (abbreviated) {
+                       name = name.substr (0, name.length() - 4) + "...";
+               } else {
+                       name = name.substr (0, name.length() - 3) + "...";
+                       abbreviated = true;
+               }
+       }
+
+       return std::make_pair (name, width);
+}
+
+
+/** Add an element to a menu, settings its sensitivity.
+ * @param m Menu to add to.
+ * @param e Element to add.
+ * @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)
+{
+       m.push_back (e);
+       if (!s) {
+               m.back().set_sensitive (false);
+       }
+}
+
+
 gint
-just_hide_it (GdkEventAny *ev, Gtk::Window *win)
+just_hide_it (GdkEventAny */*ev*/, Gtk::Window *win)
 {
        win->hide ();
-       return TRUE;
+       return 0;
 }
 
 /* xpm2rgb copied from nixieclock, which bore the legend:
@@ -234,7 +285,7 @@ xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h)
 }
 
 ArdourCanvas::Points*
-get_canvas_points (string who, uint32_t npoints)
+get_canvas_points (string /*who*/, uint32_t npoints)
 {
        // cerr << who << ": wants " << npoints << " canvas points" << endl;
 #ifdef TRAP_EXCESSIVE_POINT_REQUESTS
@@ -384,6 +435,61 @@ color_from_style (string widget_style_name, int state, string attr)
        return Gdk::Color ("red");
 }
 
+Glib::RefPtr<Gdk::GC>
+gc_from_style (string widget_style_name, int state, string attr)
+{
+        GtkStyle* style;
+
+        style = gtk_rc_get_style_by_paths (gtk_settings_get_default(),
+                                           widget_style_name.c_str(),
+                                           0, G_TYPE_NONE);
+
+        if (!style) {
+                error << string_compose (_("no style found for %1, using red"), style) << endmsg;
+               Glib::RefPtr<Gdk::GC> ret = Gdk::GC::create();
+               ret->set_rgb_fg_color(Gdk::Color("red"));
+                return ret;
+        }
+
+        if (attr == "fg") {
+                return Glib::wrap(style->fg_gc[state]);
+        }
+
+        if (attr == "bg") {
+                return Glib::wrap(style->bg_gc[state]);
+        }
+
+        if (attr == "light") {
+                return Glib::wrap(style->light_gc[state]);
+        }
+
+        if (attr == "dark") {
+                return Glib::wrap(style->dark_gc[state]);
+        }
+
+        if (attr == "mid") {
+                return Glib::wrap(style->mid_gc[state]);
+        }
+
+        if (attr == "text") {
+                return Glib::wrap(style->text_gc[state]);
+        }
+
+        if (attr == "base") {
+                return Glib::wrap(style->base_gc[state]);
+        }
+
+        if (attr == "text_aa") {
+                return Glib::wrap(style->text_aa_gc[state]);
+        }
+
+        error << string_compose (_("unknown style attribute %1 requested for color; using \"red\""), attr) << endmsg;
+       Glib::RefPtr<Gdk::GC> ret = Gdk::GC::create();
+       ret->set_rgb_fg_color(Gdk::Color("red"));
+        return ret;
+}
+
+
 bool 
 canvas_item_visible (ArdourCanvas::Item* item)
 {
@@ -396,7 +502,7 @@ set_color (Gdk::Color& c, int rgb)
        c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256);
 }
 
-#ifdef GTKOSX_ARDOUR_EVENTS_PATCH
+#ifdef GTKOSX
 extern "C" {
        gboolean gdk_quartz_possibly_forward (GdkEvent*);
 }
@@ -408,10 +514,12 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        GtkWindow* win = window.gobj();
        GtkWidget* focus = gtk_window_get_focus (win);
        bool special_handling_of_unmodified_accelerators = false;
+       bool allow_activating = true;
 
 #undef DEBUG_ACCELERATOR_HANDLING
 #ifdef  DEBUG_ACCELERATOR_HANDLING
-       bool debug = (getenv ("ARDOUR_DEBUG_ACCELERATOR_HANDLING") != 0);
+       //bool debug = (getenv ("ARDOUR_DEBUG_ACCELERATOR_HANDLING") != 0);
+       bool debug=true;
 #endif
        if (focus) {
                if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
@@ -419,10 +527,21 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                } 
        } 
 
+#ifdef GTKOSX
+       /* should this be universally true? */
+       if (Keyboard::some_magic_widget_has_focus ()) {
+               allow_activating = false;
+       }
+#endif
+
 #ifdef DEBUG_ACCELERATOR_HANDLING
        if (debug) {
                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()
+                    << " allow_activation ? "
+                    << allow_activating
                     << endl;
        }
 #endif
@@ -469,17 +588,19 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                uint32_t fakekey = ev->keyval;
 
                if (possibly_translate_keyval_to_make_legal_accelerator (fakekey)) {
-                       if (gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) {
+                       if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) {
                                return true;
                        }
 
-#ifdef GTKOSX_ARDOUR_EVENTS_PATCH
-                       int oldval = ev->keyval;
-                       ev->keyval = fakekey;
-                       if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
-                               return true;
+#ifdef GTKOSX
+                       if (allow_activating) {
+                               int oldval = ev->keyval;
+                               ev->keyval = fakekey;
+                               if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
+                                       return true;
+                               }
+                               ev->keyval = oldval;
                        }
-                       ev->keyval = oldval;
 #endif
                }
        }
@@ -497,26 +618,24 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                        cerr << "\tactivate, then propagate\n";
                }
 #endif
-#ifdef GTKOSX_ARDOUR_EVENTS_PATCH
-               if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
-                       return true;
-               }
-#endif
-               if (!gtk_window_activate_key (win, ev)) {
-#ifdef DEBUG_ACCELERATOR_HANDLING
-                       if (debug) {
-                               cerr << "\tnot accelerated, now propagate\n";
+
+               if (allow_activating) {
+#ifdef GTKOSX
+                       if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
+                               return true;
                        }
 #endif
-                       return gtk_window_propagate_key_event (win, ev);
-               } else {
-#ifdef DEBUG_ACCELERATOR_HANDLING
-                       if (debug) {
-                               cerr << "\taccelerated - done.\n";
+                       if (gtk_window_activate_key (win, ev)) {
+                               return true;
                        }
+               }
+
+#ifdef DEBUG_ACCELERATOR_HANDLING
+               if (debug) {
+                       cerr << "\tnot accelerated, now propagate\n";
+               }
 #endif
-                       return true;
-               } 
+               return gtk_window_propagate_key_event (win, ev);
        }
        
        /* no modifiers, propagate first */
@@ -532,12 +651,17 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                        cerr << "\tpropagation didn't handle, so activate\n";
                }
 #endif
-#ifdef GTKOSX_ARDOUR_EVENTS_PATCH
-               if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
-                       return true;
-               }
+
+               if (allow_activating) {
+                       
+#ifdef GTKOSX
+                       if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
+                               return true;
+                       }
 #endif
-               return gtk_window_activate_key (win, ev);
+                       return gtk_window_activate_key (win, ev);
+               } 
+                       
        } else {
 #ifdef DEBUG_ACCELERATOR_HANDLING
                if (debug) {
@@ -581,9 +705,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");
@@ -599,9 +722,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 (...) {
@@ -751,3 +880,35 @@ possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval)
        return false;
 }
                
+
+inline guint8
+convert_color_channel (guint8 src,
+                      guint8 alpha)
+{
+       return alpha ? ((guint (src) << 8) - src) / alpha : 0;
+}
+
+void
+convert_bgra_to_rgba (guint8 const* src,
+                     guint8*       dst,
+                     int           width,
+                     int           height)
+{
+       guint8 const* src_pixel = src;
+       guint8*       dst_pixel = dst;
+       
+       for (int y = 0; y < height; y++)
+               for (int x = 0; x < width; x++)
+               {
+                       dst_pixel[0] = convert_color_channel (src_pixel[2],
+                                                             src_pixel[3]);
+                       dst_pixel[1] = convert_color_channel (src_pixel[1],
+                                                             src_pixel[3]);
+                       dst_pixel[2] = convert_color_channel (src_pixel[0],
+                                                             src_pixel[3]);
+                       dst_pixel[3] = src_pixel[3];
+                       
+                       dst_pixel += 4;
+                       src_pixel += 4;
+               }
+}