adjusting region fade in/out lengths makes the fade in/out active; new font sizes...
[ardour.git] / gtk2_ardour / utils.cc
index 887494829eab97dbc8c4fd3102cd1bc029e6233d..a1ca5c2eb095d1818e41fb01fdb7081d331c3657 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
 #include <cstdlib>
@@ -23,6 +22,7 @@
 #include <fstream>
 #include <sys/stat.h>
 #include <libart_lgpl/art_misc.h>
+#include <gtkmm/rc.h>
 #include <gtkmm/window.h>
 #include <gtkmm/combo.h>
 #include <gtkmm/label.h>
@@ -45,6 +45,20 @@ using namespace sigc;
 using namespace Glib;
 using namespace PBD;
 
+int
+pixel_width (const ustring& str, Pango::FontDescription& font)
+{
+       Label foo;
+       Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
+
+       layout->set_font_description (font);
+       layout->set_text (str);
+
+       int width, height;
+       Gtkmm2ext::get_ink_pixel_size (layout, width, height);
+       return width;
+}
+
 ustring
 fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses)
 {
@@ -92,7 +106,7 @@ fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font
 gint
 just_hide_it (GdkEventAny *ev, Gtk::Window *win)
 {
-       win->hide_all ();
+       win->hide ();
        return TRUE;
 }
 
@@ -120,7 +134,7 @@ xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h)
                return 0;
        }
 
-       savergb = rgb = (unsigned char*)art_alloc (h * w * 3);
+       savergb = rgb = (unsigned char*) malloc (h * w * 3);
        
        // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
        for (t = 0; t < colors; ++t) {
@@ -163,7 +177,7 @@ xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h)
                return 0;
        }
 
-       savergb = rgb = (unsigned char*)art_alloc (h * w * 4);
+       savergb = rgb = (unsigned char*) malloc (h * w * 4);
        
        // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
 
@@ -221,7 +235,7 @@ get_canvas_points (string who, uint32_t npoints)
        return new ArdourCanvas::Points (npoints);
 }
 
-Pango::FontDescription
+Pango::FontDescription*
 get_font_for_style (string widgetname)
 {
        Gtk::Window window (WINDOW_TOPLEVEL);
@@ -233,7 +247,21 @@ get_font_for_style (string widgetname)
        foobar.ensure_style();
 
        style = foobar.get_style ();
-       return style->get_font();
+
+       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 */
 }
 
 uint32_t
@@ -263,6 +291,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;
@@ -294,6 +323,61 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s
        }
 }
 
+
+Gdk::Color
+color_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;
+               return Gdk::Color ("red");
+       }
+
+       cerr << "got style for " << widget_style_name << endl;
+
+       if (attr == "fg") {
+               return Gdk::Color (&style->fg[state]);
+       }
+
+       if (attr == "bg") {
+               cerr << "returning color from bg\n";
+               return Gdk::Color (&style->bg[state]);
+       }
+
+       if (attr == "light") {
+               return Gdk::Color (&style->light[state]);
+       }
+
+       if (attr == "dark") {
+               return Gdk::Color (&style->dark[state]);
+       }
+
+       if (attr == "mid") {
+               return Gdk::Color (&style->mid[state]);
+       }
+
+       if (attr == "text") {
+               return Gdk::Color (&style->text[state]);
+       }
+
+       if (attr == "base") {
+               return Gdk::Color (&style->base[state]);
+       }
+
+       if (attr == "text_aa") {
+               return Gdk::Color (&style->text_aa[state]);
+       }
+
+       error << string_compose (_("unknown style attribute %1 requested for color; using \"red\""), attr) << endmsg;
+       return Gdk::Color ("red");
+}
+
+
 bool 
 canvas_item_visible (ArdourCanvas::Item* item)
 {
@@ -306,6 +390,12 @@ set_color (Gdk::Color& c, int rgb)
        c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256);
 }
 
+#ifdef GTKOSX
+extern "C" {
+       gboolean gdk_quartz_possibly_forward (GdkEvent*);
+}
+#endif
+
 bool
 key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 {
@@ -313,20 +403,19 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        GtkWidget* focus = gtk_window_get_focus (win);
        bool special_handling_of_unmodified_accelerators = false;
 
-#undef  DEBUG_ACCELERATOR_HANDLING
+#undef DEBUG_ACCELERATOR_HANDLING
 #ifdef  DEBUG_ACCELERATOR_HANDLING
        bool debug = (getenv ("ARDOUR_DEBUG_ACCELERATOR_HANDLING") != 0);
 #endif
-
        if (focus) {
-               if (GTK_IS_ENTRY(focus)) {
+               if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
                        special_handling_of_unmodified_accelerators = true;
                } 
        } 
 
 #ifdef DEBUG_ACCELERATOR_HANDLING
        if (debug) {
-               cerr << "Key event: code = " << ev->keyval << " state = " << hex << ev->state << dec << " focus is an entry ? " 
+               cerr << "Win = " << win << " Key event: code = " << ev->keyval << " state = " << hex << ev->state << dec << " special handling ? " 
                     << special_handling_of_unmodified_accelerators
                     << endl;
        }
@@ -371,55 +460,83 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                   it does allow.
                */
 
+               int fakekey = GDK_VoidSymbol;
                int ret = false;
 
                switch (ev->keyval) {
+               case GDK_Tab:
+               case GDK_ISO_Left_Tab:
+                       fakekey = GDK_nabla;
+                       break;
+
                case GDK_Up:
-                       ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_uparrow, GdkModifierType(ev->state));
+                       fakekey = GDK_uparrow;
                        break;
 
                case GDK_Down:
-                       ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_downarrow, GdkModifierType(ev->state));
+                       fakekey = GDK_downarrow;
                        break;
 
                case GDK_Right:
-                       ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_rightarrow, GdkModifierType(ev->state));
+                       fakekey = GDK_rightarrow;
                        break;
 
                case GDK_Left:
-                       ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_leftarrow, GdkModifierType(ev->state));
+                       fakekey = GDK_leftarrow;
                        break;
 
                default:
                        break;
                }
 
-               if (ret) {
-                       return true;
+               if (fakekey != GDK_VoidSymbol) {
+                       ret = gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state));
+                       
+                       if (ret) {
+                               return true;
+                       }
+
+#ifdef GTKOSX
+                       int oldval = ev->keyval;
+                       ev->keyval = fakekey;
+                       if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
+                               return true;
+                       }
+                       ev->keyval = oldval;
+#endif
                }
        }
-               
-       if (!special_handling_of_unmodified_accelerators ||
-           ev->state & (Gdk::MOD1_MASK|
-                        Gdk::MOD3_MASK|
-                        Gdk::MOD4_MASK|
-                        Gdk::MOD5_MASK|
-                        Gdk::CONTROL_MASK)) {
 
-               /* no special handling or modifiers in effect: accelerate first */
+       /* consider all relevant modifiers but not LOCK or SHIFT */
+
+       guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
+
+       if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
+
+               /* no special handling or there are modifiers in effect: accelerate first */
 
 #ifdef DEBUG_ACCELERATOR_HANDLING
                if (debug) {
                        cerr << "\tactivate, then propagate\n";
                }
+#endif
+#ifdef GTKOSX
+               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";
+                       }
+#endif
                        return gtk_window_propagate_key_event (win, ev);
                } else {
 #ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\tnot handled\n";
-               }
+                       if (debug) {
+                               cerr << "\taccelerated - done.\n";
+                       }
 #endif
                        return true;
                } 
@@ -427,15 +544,31 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        
        /* no modifiers, propagate first */
        
+#ifdef DEBUG_ACCELERATOR_HANDLING
+       if (debug) {
+               cerr << "\tpropagate, then activate\n";
+       }
+#endif
+       if (!gtk_window_propagate_key_event (win, ev)) {
 #ifdef DEBUG_ACCELERATOR_HANDLING
                if (debug) {
-                       cerr << "\tactivate, then propagate\n";
+                       cerr << "\tpropagation didn't handle, so activate\n";
+               }
+#endif
+#ifdef GTKOSX
+               if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
+                       return true;
                }
 #endif
-       if (!gtk_window_propagate_key_event (win, ev)) {
                return gtk_window_activate_key (win, ev);
-       } 
-
+       } else {
+#ifdef DEBUG_ACCELERATOR_HANDLING
+               if (debug) {
+                       cerr << "\thandled by propagate\n";
+               }
+#endif
+               return true;
+       }
 
 #ifdef DEBUG_ACCELERATOR_HANDLING
        if (debug) {
@@ -468,7 +601,20 @@ get_icon (const char* cname)
                /*NOTREACHED*/
        }
 
-       return Gdk::Pixbuf::create_from_file (path);
+       Glib::RefPtr<Gdk::Pixbuf> img;
+       try {
+               img = Gdk::Pixbuf::create_from_file (path);
+       }
+       catch (const Gdk::PixbufError &e)
+    {
+        cerr << "Caught PixbufError: " << e.what() << endl;
+    }
+    catch (...)
+    {
+        g_message("Caught ... ");
+    }
+
+       return img;
 }
 
 string
@@ -547,3 +693,5 @@ key_is_legal_for_numeric_entry (guint keyval)
        return false;
 }
 
+
+