Build plugin menu only when plugins change, and build the first version of it before...
[ardour.git] / gtk2_ardour / time_axis_view_item.cc
index dc4c90989bb91e7accffb828691ec110dab52097..1d8fc2aca7f6bd6defa2349217519b3441b80fb1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2003 Paul Davis 
+    Copyright (C) 2003 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
 #include <gtkmm2ext/utils.h>
 
+#include "ardour_ui.h"
+/*
+ * ardour_ui.h was moved up in the include list
+ * due to a conflicting definition of 'Rect' between
+ * Apple's MacTypes.h file and GTK
+ */
+
 #include "public_editor.h"
 #include "time_axis_view_item.h"
 #include "time_axis_view.h"
@@ -32,7 +39,6 @@
 #include "utils.h"
 #include "canvas_impl.h"
 #include "rgb_macros.h"
-#include "ardour_ui.h"
 
 #include "i18n.h"
 
@@ -50,42 +56,11 @@ bool TimeAxisViewItem::have_name_font = false;
 const double TimeAxisViewItem::NAME_X_OFFSET = 15.0;
 const double TimeAxisViewItem::GRAB_HANDLE_LENGTH = 6 ;
 
+int    TimeAxisViewItem::NAME_HEIGHT;
 double TimeAxisViewItem::NAME_Y_OFFSET;
 double TimeAxisViewItem::NAME_HIGHLIGHT_SIZE;
 double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH;
 
-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;
-               }
-}
-
 //---------------------------------------------------------------------------------------//
 // Constructor / Desctructor
 
@@ -100,8 +75,8 @@ convert_bgra_to_rgba (guint8 const* src,
  * @param start the start point of this item
  * @param duration the duration of this item
  */
-TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group& parent, TimeAxisView& tv, double spu, Gdk::Color& base_color, 
-                                  nframes_t start, nframes_t duration, bool recording,
+TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group& parent, TimeAxisView& tv, double spu, Gdk::Color const & base_color,
+                                  nframes64_t start, nframes64_t duration, bool recording,
                                   Visibility vis)
        : trackview (tv), _recregion(recording)
 {
@@ -110,27 +85,28 @@ TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group&
                /* first constructed item sets up font info */
 
                NAME_FONT = get_font_for_style (N_("TimeAxisViewItemName"));
-               
+
                Gtk::Window win;
                Gtk::Label foo;
                win.add (foo);
 
                Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout (X_("Hg")); /* ascender + descender */
-               int width;
-               int height;
+               int width = 0;
+               int height = 0;
 
                layout->set_font_description (*NAME_FONT);
                Gtkmm2ext::get_ink_pixel_size (layout, width, height);
 
-               NAME_Y_OFFSET = height + 5;
-               NAME_HIGHLIGHT_SIZE = height + 6;
-               NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_SIZE * 2;
+               NAME_HEIGHT = height;
+               NAME_Y_OFFSET = height + 3;
+               NAME_HIGHLIGHT_SIZE = height + 2;
+               NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_SIZE * 3;
 
                have_name_font = true;
        }
 
        group = new ArdourCanvas::Group (parent);
-       
+
        init (it_name, spu, base_color, start, duration, vis);
 
 }
@@ -149,14 +125,14 @@ TimeAxisViewItem::TimeAxisViewItem (const TimeAxisViewItem& other)
        /* share the other's parent, but still create a new group */
 
        Gnome::Canvas::Group* parent = other.group->property_parent();
-       
+
        group = new ArdourCanvas::Group (*parent);
 
        init (other.item_name, other.samples_per_unit, c, other.frame_position, other.item_duration, other.visibility);
 }
 
 void
-TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_color, nframes_t start, nframes_t duration, Visibility vis)
+TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color const & base_color, nframes64_t start, nframes64_t duration, Visibility vis)
 {
        item_name = it_name ;
        samples_per_unit = spu ;
@@ -171,6 +147,8 @@ TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_colo
        show_vestigial = true;
        visibility = vis;
        _sensitive = true;
+       name_pixbuf_width = 0;
+       last_item_width = 0;
 
        if (duration == 0) {
                warning << "Time Axis Item Duration == 0" << endl ;
@@ -205,7 +183,7 @@ TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_colo
                }
 
                frame->property_outline_what() = outline_what;
-                   
+
        } else {
                frame = 0;
        }
@@ -226,23 +204,17 @@ TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_colo
                name_pixbuf = new ArdourCanvas::Pixbuf(*group);
                name_pixbuf->property_x() = NAME_X_OFFSET;
                name_pixbuf->property_y() = trackview.current_height() - 1.0 - NAME_Y_OFFSET;
-       
+
+       } else {
+               name_pixbuf = 0;
        }
 
        /* create our grab handles used for trimming/duration etc */
+       frame_handle_start = new ArdourCanvas::SimpleRect (*group, 0.0, TimeAxisViewItem::GRAB_HANDLE_LENGTH, 5.0, trackview.current_height());
+       frame_handle_start->property_outline_what() = 0x0;
 
-       if (visibility & ShowHandles) {
-       
-               frame_handle_start = new ArdourCanvas::SimpleRect (*group, 0.0, TimeAxisViewItem::GRAB_HANDLE_LENGTH, 1.0, TimeAxisViewItem::GRAB_HANDLE_LENGTH+1);
-               frame_handle_start->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_FrameHandle.get();
-
-               frame_handle_end = new ArdourCanvas::SimpleRect (*group, trackview.editor().frame_to_pixel(get_duration()) - TimeAxisViewItem::GRAB_HANDLE_LENGTH, trackview.editor().frame_to_pixel(get_duration()), 1.0, TimeAxisViewItem::GRAB_HANDLE_LENGTH + 1);
-               frame_handle_end->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_FrameHandle.get();
-
-       } else {
-               frame_handle_start = 0;
-               frame_handle_end = 0;
-       }
+       frame_handle_end = new ArdourCanvas::SimpleRect (*group, 0.0, TimeAxisViewItem::GRAB_HANDLE_LENGTH, 5.0, trackview.current_height());
+       frame_handle_end->property_outline_what() = 0x0;
 
        set_color (base_color) ;
 
@@ -270,14 +242,14 @@ TimeAxisViewItem::~TimeAxisViewItem()
  * @return true if the position change was a success, false otherwise
  */
 bool
-TimeAxisViewItem::set_position(nframes_t pos, void* src, double* delta)
+TimeAxisViewItem::set_position(nframes64_t pos, void* src, double* delta)
 {
        if (position_locked) {
                return false;
        }
 
        frame_position = pos;
-       
+
        /*  This sucks. The GnomeCanvas version I am using
            doesn't correctly implement gnome_canvas_group_set_arg(),
            so that simply setting the "x" arg of the group
@@ -286,7 +258,7 @@ TimeAxisViewItem::set_position(nframes_t pos, void* src, double* delta)
            thing. I see that in GNOME CVS, the current (Sept 2001)
            version of GNOME Canvas rectifies this issue cleanly.
        */
-       
+
        double old_unit_pos ;
        double new_unit_pos = pos / samples_per_unit ;
 
@@ -295,11 +267,11 @@ TimeAxisViewItem::set_position(nframes_t pos, void* src, double* delta)
        if (new_unit_pos != old_unit_pos) {
                group->move (new_unit_pos - old_unit_pos, 0.0);
        }
-       
+
        if (delta) {
                (*delta) = new_unit_pos - old_unit_pos;
        }
-       
+
        PositionChanged (frame_position, src) ; /* EMIT_SIGNAL */
 
        return true;
@@ -310,7 +282,7 @@ TimeAxisViewItem::set_position(nframes_t pos, void* src, double* delta)
  *
  * @return the position of this item
  */
-nframes_t
+nframes64_t
 TimeAxisViewItem::get_position() const
 {
        return frame_position;
@@ -324,7 +296,7 @@ TimeAxisViewItem::get_position() const
  * @return true if the duration change was succesful, false otherwise
  */
 bool
-TimeAxisViewItem::set_duration (nframes_t dur, void* src)
+TimeAxisViewItem::set_duration (nframes64_t dur, void* src)
 {
        if ((dur > max_item_duration) || (dur < min_item_duration)) {
                warning << string_compose (_("new duration %1 frames is out of bounds for %2"), get_item_name(), dur)
@@ -337,9 +309,9 @@ TimeAxisViewItem::set_duration (nframes_t dur, void* src)
        }
 
        item_duration = dur;
-       
+
        reset_width_dependent_items (trackview.editor().frame_to_pixel (dur));
-       
+
        DurationChanged (dur, src) ; /* EMIT_SIGNAL */
        return true;
 }
@@ -348,7 +320,7 @@ TimeAxisViewItem::set_duration (nframes_t dur, void* src)
  * Returns the duration of this item
  *
  */
-nframes_t
+nframes64_t
 TimeAxisViewItem::get_duration() const
 {
        return (item_duration);
@@ -361,18 +333,18 @@ TimeAxisViewItem::get_duration() const
  * @param src the identity of the object that initiated the change
  */
 void
-TimeAxisViewItem::set_max_duration(nframes_t dur, void* src)
+TimeAxisViewItem::set_max_duration(nframes64_t dur, void* src)
 {
        max_item_duration = dur ;
        MaxDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
 }
-               
+
 /**
  * Returns the maxmimum duration that this item may be set to
  *
  * @return the maximum duration that this item may be set to
  */
-nframes_t
+nframes64_t
 TimeAxisViewItem::get_max_duration() const
 {
        return (max_item_duration) ;
@@ -385,18 +357,18 @@ TimeAxisViewItem::get_max_duration() const
  * @param src the identity of the object that initiated the change
  */
 void
-TimeAxisViewItem::set_min_duration(nframes_t dur, void* src)
+TimeAxisViewItem::set_min_duration(nframes64_t dur, void* src)
 {
        min_item_duration = dur ;
        MinDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
 }
-               
+
 /**
  * Returns the minimum duration that this item mey be set to
  *
  * @return the nimum duration that this item mey be set to
  */
-nframes_t
+nframes64_t
 TimeAxisViewItem::get_min_duration() const
 {
        return(min_item_duration) ;
@@ -436,11 +408,11 @@ TimeAxisViewItem::get_position_locked() const
  * @param src the identity of the object that initiated the change
  */
 void
-TimeAxisViewItem::set_max_duration_active(bool active, void* src)
+TimeAxisViewItem::set_max_duration_active (bool active, void* /*src*/)
 {
-       max_duration_active = active ;
+       max_duration_active = active;
 }
-               
+
 /**
  * Returns whether the Maximum Duration constraint is active and should be enforced
  *
@@ -451,7 +423,7 @@ TimeAxisViewItem::get_max_duration_active() const
 {
        return(max_duration_active) ;
 }
-               
+
 /**
  * Sets whether the Minimum Duration constraint is active and should be enforced
  *
@@ -459,11 +431,11 @@ TimeAxisViewItem::get_max_duration_active() const
  * @param src the identity of the object that initiated the change
  */
 void
-TimeAxisViewItem::set_min_duration_active(bool active, void* src)
+TimeAxisViewItem::set_min_duration_active (bool active, void* /*src*/)
 {
        min_duration_active = active ;
 }
-               
+
 /**
  * Returns whether the Maximum Duration constraint is active and should be enforced
  *
@@ -523,7 +495,7 @@ TimeAxisViewItem::set_selected(bool yn)
        }
 }
 
-void 
+void
 TimeAxisViewItem::set_should_show_selection (bool yn)
 {
        if (should_show_selection != yn) {
@@ -544,7 +516,7 @@ TimeAxisView&
 TimeAxisViewItem::get_time_axis_view()
 {
        return trackview;
-}              
+}
 //---------------------------------------------------------------------------------------//
 // ui methods & data
 
@@ -557,51 +529,21 @@ TimeAxisViewItem::get_time_axis_view()
 void
 TimeAxisViewItem::set_name_text(const ustring& new_name)
 {
-       uint32_t pb_width, it_width;
-       double font_size;
-
-       font_size = NAME_FONT->get_size() / Pango::SCALE;
-       it_width = trackview.editor().frame_to_pixel(item_duration);
-       pb_width = new_name.length() * font_size;
-
-       if (pb_width > it_width - NAME_X_OFFSET) {
-               pb_width = it_width - NAME_X_OFFSET;
-       }
-
-       if (pb_width <= 0 || it_width < NAME_X_OFFSET) {
-               name_pixbuf->hide();
+       if (!name_pixbuf) {
                return;
-       } else {
-               name_pixbuf->show();
        }
 
-       Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, pb_width, NAME_HIGHLIGHT_SIZE);
-
-       cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pb_width, NAME_HIGHLIGHT_SIZE );
-       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, NAME_FONT->get_family().c_str(),
-                               CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-       cairo_set_font_size (cr, 10);
-       cairo_text_extents (cr, new_name.c_str(), &te);
-       
-       cairo_move_to (cr, 0.5,
-                      0.5 - te.height / 2 - te.y_bearing + NAME_HIGHLIGHT_SIZE / 2);
-       cairo_show_text (cr, new_name.c_str());
-       
-       unsigned char* src = cairo_image_surface_get_data (surface);
-       convert_bgra_to_rgba(src, buf->get_pixels(), pb_width, NAME_HIGHLIGHT_SIZE);
-       
-       cairo_destroy(cr);
-       name_pixbuf->property_pixbuf() = buf;
+       last_item_width = trackview.editor().frame_to_pixel(item_duration);
+       name_pixbuf_width = pixel_width (new_name, *NAME_FONT) + 2;
+       name_pixbuf->property_pixbuf() = pixbuf_from_ustring(new_name, NAME_FONT, name_pixbuf_width, NAME_HEIGHT);
 }
 
+
 /**
  * Set the height of this item
  *
  * @param h the new height
- */            
+ */
 void
 TimeAxisViewItem::set_height (double height)
 {
@@ -609,16 +551,16 @@ TimeAxisViewItem::set_height (double height)
                if (height < NAME_HIGHLIGHT_THRESH) {
                        name_highlight->hide();
                        name_pixbuf->hide();
-                       
+
                } else {
                        name_highlight->show();
                        name_pixbuf->show();
-                       
+
                }
 
                if (height > NAME_HIGHLIGHT_SIZE) {
-                       name_highlight->property_y1() = (double) height+1 - NAME_HIGHLIGHT_SIZE;
-                       name_highlight->property_y2() = (double) height;
+                       name_highlight->property_y1() = (double) height - 1 - NAME_HIGHLIGHT_SIZE;
+                       name_highlight->property_y2() = (double) height - 2;
                }
                else {
                        /* it gets hidden now anyway */
@@ -628,28 +570,30 @@ TimeAxisViewItem::set_height (double height)
        }
 
        if (visibility & ShowNameText) {
-               name_pixbuf->property_y() = height+1 - NAME_Y_OFFSET;
+               name_pixbuf->property_y() =  height - 1 - NAME_Y_OFFSET;
        }
 
        if (frame) {
-               frame->property_y2() = height+1;
+               frame->property_y2() = height - 1;
+               frame_handle_start->property_y2() = height - 1;
+               frame_handle_end->property_y2() = height - 1;
        }
 
-       vestigial_frame->property_y2() = height+1;
+       vestigial_frame->property_y2() = height - 1;
 }
 
 /**
- * 
+ *
  */
 void
-TimeAxisViewItem::set_color(Gdk::Color& base_color)
+TimeAxisViewItem::set_color (Gdk::Color const & base_color)
 {
        compute_colors (base_color);
        set_colors ();
 }
 
 /**
- * 
+ *
  */
 ArdourCanvas::Item*
 TimeAxisViewItem::get_canvas_frame()
@@ -658,7 +602,7 @@ TimeAxisViewItem::get_canvas_frame()
 }
 
 /**
- * 
+ *
  */
 ArdourCanvas::Group*
 TimeAxisViewItem::get_canvas_group()
@@ -667,7 +611,7 @@ TimeAxisViewItem::get_canvas_group()
 }
 
 /**
- * 
+ *
  */
 ArdourCanvas::Item*
 TimeAxisViewItem::get_name_highlight()
@@ -676,7 +620,7 @@ TimeAxisViewItem::get_name_highlight()
 }
 
 /**
- * 
+ *
  */
 ArdourCanvas::Pixbuf*
 TimeAxisViewItem::get_name_pixbuf()
@@ -690,11 +634,11 @@ TimeAxisViewItem::get_name_pixbuf()
  * @param color the base color of the item
  */
 void
-TimeAxisViewItem::compute_colors(Gdk::Color& base_color)
+TimeAxisViewItem::compute_colors (Gdk::Color const & base_color)
 {
        unsigned char radius ;
        char minor_shift ;
-       
+
        unsigned char r,g,b ;
 
        /* FILL: this is simple */
@@ -706,7 +650,7 @@ TimeAxisViewItem::compute_colors(Gdk::Color& base_color)
        /*  for minor colors:
                if the overall saturation is strong, make the minor colors light.
                if its weak, make them dark.
-  
+
                we do this by moving an equal distance to the other side of the
                central circle in the color wheel from where we started.
        */
@@ -719,7 +663,7 @@ TimeAxisViewItem::compute_colors(Gdk::Color& base_color)
        r = base_color.get_red()/256;
        g = base_color.get_green()/256;
        b = base_color.get_blue()/256;
-  
+
        if (r > b)
        {
                if (r > g)
@@ -731,7 +675,7 @@ TimeAxisViewItem::compute_colors(Gdk::Color& base_color)
                {
                        /* green sector => blue */
                        swap (g,b);
-               } 
+               }
        }
        else
        {
@@ -750,26 +694,26 @@ TimeAxisViewItem::compute_colors(Gdk::Color& base_color)
        r += minor_shift;
        b += minor_shift;
        g += minor_shift;
-  
+
        label_color = RGBA_TO_UINT(r,g,b,255);
        r = (base_color.get_red()/256)   + 127 ;
        g = (base_color.get_green()/256) + 127 ;
        b = (base_color.get_blue()/256)  + 127 ;
-  
+
        label_color = RGBA_TO_UINT(r,g,b,255);
 
        /* XXX can we do better than this ? */
        /* We're trying ;) */
        /* NUKECOLORS */
-       
+
        //frame_color_r = 192;
        //frame_color_g = 192;
        //frame_color_b = 194;
-       
+
        //selected_frame_color_r = 182;
        //selected_frame_color_g = 145;
        //selected_frame_color_b = 168;
-       
+
        //handle_color_r = 25 ;
        //handle_color_g = 0 ;
        //handle_color_b = 255 ;
@@ -801,7 +745,7 @@ TimeAxisViewItem::set_frame_color()
 {
        if (frame) {
                uint32_t r,g,b,a;
-               
+
                if (_selected && should_show_selection) {
                        UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_SelectedFrameBase.get(), &r, &g, &b, &a);
                        frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, a);
@@ -827,10 +771,10 @@ TimeAxisViewItem::set_trim_handle_colors()
        if (frame_handle_start) {
                if (position_locked) {
                        frame_handle_start->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TrimHandleLocked.get();
-                       frame_handle_end->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TrimHandleLocked.get();
+                       frame_handle_end->property_fill_color_rgba() =  ARDOUR_UI::config()->canvasvar_TrimHandleLocked.get();
                } else {
-                       frame_handle_start->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TrimHandle.get();
-                       frame_handle_end->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TrimHandle.get();
+                       frame_handle_start->property_fill_color_rgba() = RGBA_TO_UINT(1, 1, 1, 0); //ARDOUR_UI::config()->canvasvar_TrimHandle.get();
+                       frame_handle_end->property_fill_color_rgba() = RGBA_TO_UINT(1, 1, 1, 0); //ARDOUR_UI::config()->canvasvar_TrimHandle.get();
                }
        }
 }
@@ -878,7 +822,7 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
                        frame_handle_start->hide();
                        frame_handle_end->hide();
                }
-               
+
        } else {
                vestigial_frame->hide();
 
@@ -923,9 +867,42 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
 }
 
 void
-TimeAxisViewItem::reset_name_width (double pixel_width)
+TimeAxisViewItem::reset_name_width (double /*pixel_width*/)
 {
-       set_name_text (item_name);
+       uint32_t it_width;
+       int pb_width;
+       bool pixbuf_holds_full_name;
+
+       if (!name_pixbuf) {
+               return;
+       }
+
+       it_width = trackview.editor().frame_to_pixel(item_duration);
+       pb_width = name_pixbuf_width;
+
+       pixbuf_holds_full_name = last_item_width > pb_width + NAME_X_OFFSET;
+       last_item_width = it_width;
+
+       if (pixbuf_holds_full_name && (it_width >= pb_width + NAME_X_OFFSET)) {
+               /*
+                 we've previously had the full name length showing 
+                 and its still showing.
+               */
+               return;
+       }
+       
+       if (pb_width > it_width - NAME_X_OFFSET) {
+               pb_width = it_width - NAME_X_OFFSET;
+       }
+       
+       if (pb_width <= 0 || it_width <= NAME_X_OFFSET) {
+               name_pixbuf->hide();
+               return;
+       } else {
+               name_pixbuf->show();
+       }
+
+       name_pixbuf->property_pixbuf() = pixbuf_from_ustring(item_name, NAME_FONT, pb_width, NAME_HEIGHT);
 }
 
 
@@ -979,4 +956,4 @@ TimeAxisViewItem::set_y (double y)
 }
 
 
-                          
+