Use boost::shared_ptr instead of raw pointers for RouteUI track (etc) accessors ...
[ardour.git] / gtk2_ardour / time_axis_view_item.cc
index 99d5cec4d9ff0a664bfc1238e223f667296e30d0..0e66ab2bae2b1372344f565c1572471e7a97df30 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
 #include <pbd/error.h>
 */
 
 #include <pbd/error.h>
+#include <pbd/stacktrace.h>
 
 #include <ardour/types.h>
 #include <ardour/ardour.h>
 
 
 #include <ardour/types.h>
 #include <ardour/ardour.h>
 
+#include <gtkmm2ext/utils.h>
+
 #include "public_editor.h"
 #include "time_axis_view_item.h"
 #include "time_axis_view.h"
 #include "public_editor.h"
 #include "time_axis_view_item.h"
 #include "time_axis_view.h"
-#include "canvas-simplerect.h"
-#include "canvas-imageframe.h"
+#include "simplerect.h"
 #include "utils.h"
 #include "utils.h"
+#include "canvas_impl.h"
 #include "rgb_macros.h"
 
 #include "i18n.h"
 
 using namespace std;
 using namespace Editing;
 #include "rgb_macros.h"
 
 #include "i18n.h"
 
 using namespace std;
 using namespace Editing;
+using namespace Glib;
+using namespace PBD;
 
 //------------------------------------------------------------------------------
 
 //------------------------------------------------------------------------------
-/** Initialize static memeber data */
-std::string TimeAxisViewItem::NAME_FONT;
+/** Initialize const static memeber data */
+
+Pango::FontDescription TimeAxisViewItem::NAME_FONT;
+bool TimeAxisViewItem::have_name_font = false;
 const double TimeAxisViewItem::NAME_X_OFFSET = 15.0;
 const double TimeAxisViewItem::NAME_X_OFFSET = 15.0;
-const double TimeAxisViewItem::NAME_Y_OFFSET = 15.0 ;           /* XXX depends a lot on the font size, sigh. */
-const double TimeAxisViewItem::NAME_HIGHLIGHT_SIZE = 15.0 ;     /* ditto */
-const double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH = 32.0 ;     /* ditto */
 const double TimeAxisViewItem::GRAB_HANDLE_LENGTH = 6 ;
 
 const double TimeAxisViewItem::GRAB_HANDLE_LENGTH = 6 ;
 
+double TimeAxisViewItem::NAME_Y_OFFSET;
+double TimeAxisViewItem::NAME_HIGHLIGHT_SIZE;
+double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH;
+
 
 //---------------------------------------------------------------------------------------//
 // Constructor / Desctructor
 
 //---------------------------------------------------------------------------------------//
 // Constructor / Desctructor
@@ -60,82 +67,155 @@ const double TimeAxisViewItem::GRAB_HANDLE_LENGTH = 6 ;
  * @param start the start point of this item
  * @param duration the duration of this item
  */
  * @param start the start point of this item
  * @param duration the duration of this item
  */
-TimeAxisViewItem::TimeAxisViewItem(std::string it_name, GtkCanvasGroup* parent, TimeAxisView& tv, double spu, GdkColor& base_color, 
-                                  jack_nframes_t start, jack_nframes_t duration,
-                                  Visibility visibility)
+TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group& parent, TimeAxisView& tv, double spu, Gdk::Color& base_color, 
+                                  nframes_t start, nframes_t duration,
+                                  Visibility vis)
        : trackview (tv)
 {
        : trackview (tv)
 {
-       if (NAME_FONT.empty()) {
+       if (!have_name_font) {
+
+               /* first constructed item sets up font info */
+
                NAME_FONT = get_font_for_style (N_("TimeAxisViewItemName"));
                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;
+
+               layout->set_font_description (NAME_FONT);
+               Gtkmm2ext::get_ink_pixel_size (layout, width, height);
+
+               NAME_Y_OFFSET = height + 6;
+               NAME_HIGHLIGHT_SIZE = height + 6;
+               NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_SIZE * 2;
+
+               have_name_font = true;
        }
 
        }
 
+       group = new ArdourCanvas::Group (parent);
+       
+       init (it_name, spu, base_color, start, duration, vis);
+
+}
+
+TimeAxisViewItem::TimeAxisViewItem (const TimeAxisViewItem& other)
+       : trackview (other.trackview)
+{
+
+       Gdk::Color c;
+       int r,g,b,a;
+
+       UINT_TO_RGBA (other.fill_color, &r, &g, &b, &a);
+       c.set_rgb_p (r/255.0, g/255.0, b/255.0);
+
+       /* 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)
+{
        item_name = it_name ;
        item_name = it_name ;
+       name_text_width = ::pixel_width (it_name, NAME_FONT);
+       last_name_text_width = 0;
        samples_per_unit = spu ;
        should_show_selection = true;
        frame_position = start ;
        item_duration = duration ;
        name_connected = false;
        samples_per_unit = spu ;
        should_show_selection = true;
        frame_position = start ;
        item_duration = duration ;
        name_connected = false;
-       fill_opacity = 50;
+       fill_opacity = 60;
        position_locked = false ;
        max_item_duration = ARDOUR::max_frames;
        min_item_duration = 0 ;
        show_vestigial = true;
        position_locked = false ;
        max_item_duration = ARDOUR::max_frames;
        min_item_duration = 0 ;
        show_vestigial = true;
+       visibility = vis;
+       _sensitive = true;
 
        if (duration == 0) {
                warning << "Time Axis Item Duration == 0" << endl ;
        }
 
 
        if (duration == 0) {
                warning << "Time Axis Item Duration == 0" << endl ;
        }
 
-       group = gtk_canvas_item_new(GTK_CANVAS_GROUP(parent),gtk_canvas_group_get_type(),NULL) ;
-
-       vestigial_frame = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
-                                             gtk_canvas_simplerect_get_type(),
-                                             "x1", (double) 0.0,
-                                             "y1", (double) 1.0,
-                                             "x2", 2.0,
-                                             "y2", (double) trackview.height,
-                                             "outline_color_rgba", color_map[cVestigialFrameOutline],
-                                             "fill_color_rgba", color_map[cVestigialFrameFill],
-                                             NULL);
-       gtk_canvas_item_hide (vestigial_frame);
+       vestigial_frame = new ArdourCanvas::SimpleRect (*group);
+       vestigial_frame->property_x1() = (double) 0.0;
+       vestigial_frame->property_y1() = (double) 1.0;
+       vestigial_frame->property_x2() = 2.0;
+       vestigial_frame->property_y2() = (double) trackview.height;
+       vestigial_frame->property_outline_color_rgba() = color_map[cVestigialFrameOutline];
+       vestigial_frame->property_fill_color_rgba() = color_map[cVestigialFrameFill];
+       vestigial_frame->hide ();
 
        if (visibility & ShowFrame) {
 
        if (visibility & ShowFrame) {
-               frame = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
-                                           gtk_canvas_simplerect_get_type(),
-                                           "x1", (double) 0.0,
-                                           "y1", (double) 1.0,
-                                           "x2", (double) trackview.editor.frame_to_pixel(duration),
-                                           "y2", (double) trackview.height,
-                                           "outline_color_rgba", color_map[cTimeAxisFrameOutline],
-                                           "fill_color_rgba", color_map[cTimeAxisFrameFill],
-                                           NULL);
+               frame = new ArdourCanvas::SimpleRect (*group);
+               frame->property_x1() = (double) 0.0;
+               frame->property_y1() = (double) 1.0;
+               frame->property_x2() = (double) trackview.editor.frame_to_pixel(duration);
+               frame->property_y2() = (double) trackview.height;
+               frame->property_outline_color_rgba() = color_map[cTimeAxisFrameOutline];
+               frame->property_fill_color_rgba() = color_map[cTimeAxisFrameFill];
+
+               /* by default draw all 4 edges */
+
+               uint32_t outline_what = 0x1|0x2|0x4|0x8;
+
+               if (visibility & HideFrameLeft) {
+                       outline_what &= ~(0x1);
+               }
+
+               if (visibility & HideFrameRight) {
+                       outline_what &= ~(0x2);
+               }
+
+               if (visibility & HideFrameTB) {
+                       outline_what &= ~(0x4 | 0x8);
+               }
+
+               frame->property_outline_what() = outline_what;
+                   
        } else {
                frame = 0;
        }
 
        if (visibility & ShowNameHighlight) {
        } else {
                frame = 0;
        }
 
        if (visibility & ShowNameHighlight) {
-               name_highlight = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
-                                                    gtk_canvas_simplerect_get_type(),
-                                                    "x1", (double) 1.0,
-                                                    "x2", (double) (trackview.editor.frame_to_pixel(item_duration)) - 1,
-                                                    "y1", (double) (trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE),
-                                                    "y2", (double) (trackview.height - 1),
-                                                    "outline_color_rgba", color_map[cNameHighlightFill],
-                                                    "fill_color_rgba", color_map[cNameHighlightOutline],
-                                                    NULL) ;
-               gtk_object_set_data(GTK_OBJECT(name_highlight), "timeaxisviewitem", this) ;
+               name_highlight = new ArdourCanvas::SimpleRect (*group);
+               if (visibility & FullWidthNameHighlight) {
+                       name_highlight->property_x1() = (double) 0.0;
+                       name_highlight->property_x2() = (double) (trackview.editor.frame_to_pixel(item_duration));
+               } else {
+                       name_highlight->property_x1() = (double) 1.0;
+                       name_highlight->property_x2() = (double) (trackview.editor.frame_to_pixel(item_duration)) - 1;
+               }
+               name_highlight->property_y1() = (double) (trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE);
+               name_highlight->property_y2() = (double) (trackview.height - 1);
+               name_highlight->property_outline_color_rgba() = color_map[cNameHighlightFill];
+               name_highlight->property_fill_color_rgba() = color_map[cNameHighlightOutline];
+
+               name_highlight->set_data ("timeaxisviewitem", this);
+
        } else {
                name_highlight = 0;
        }
 
        if (visibility & ShowNameText) {
        } else {
                name_highlight = 0;
        }
 
        if (visibility & ShowNameText) {
-               name_text = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
-                                               gtk_canvas_text_get_type(),
-                                               "x", (double) TimeAxisViewItem::NAME_X_OFFSET,
-                                               "y", (double) trackview.height + 1.0 - TimeAxisViewItem::NAME_Y_OFFSET,
-                                               "font", NAME_FONT.c_str(),
-                                               "anchor", GTK_ANCHOR_NW,
-                                               NULL) ;
-               gtk_object_set_data(GTK_OBJECT(name_text), "timeaxisviewitem", this) ;
+               name_text = new ArdourCanvas::Text (*group);
+               name_text->property_x() = (double) TimeAxisViewItem::NAME_X_OFFSET;
+               /* trackview.height is the bottom of the trackview. subtract 1 to get back to the bottom of the highlight,
+                  then NAME_Y_OFFSET to position the text in the vertical center of the highlight
+               */
+               name_text->property_y() = (double) trackview.height - 1.0 - TimeAxisViewItem::NAME_Y_OFFSET;
+               name_text->property_font_desc() = NAME_FONT;
+               name_text->property_anchor() = Gtk::ANCHOR_NW;
+
+               name_text->set_data ("timeaxisviewitem", this);
                
        } else {
                name_text = 0;
                
        } else {
                name_text = 0;
@@ -144,25 +224,22 @@ TimeAxisViewItem::TimeAxisViewItem(std::string it_name, GtkCanvasGroup* parent,
        /* create our grab handles used for trimming/duration etc */
 
        if (visibility & ShowHandles) {
        /* create our grab handles used for trimming/duration etc */
 
        if (visibility & ShowHandles) {
-               frame_handle_start = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
-                                                        gtk_canvas_simplerect_get_type(),
-                                                        "x1", (double) 0.0,
-                                                        "x2", (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH,
-                                                        "y1", (double) 1.0,
-                                                        "y2", (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH+1,
-                                                        "outline_color_rgba", color_map[cFrameHandleStartOutline],
-                                                        "fill_color_rgba", color_map[cFrameHandleStartFill],
-                                                        NULL) ;
+               frame_handle_start = new ArdourCanvas::SimpleRect (*group);
+               frame_handle_start->property_x1() = (double) 0.0;
+               frame_handle_start->property_x2() = (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH;
+               frame_handle_start->property_y1() = (double) 1.0;
+               frame_handle_start->property_y2() = (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH+1;
+               frame_handle_start->property_outline_color_rgba() = color_map[cFrameHandleStartOutline];
+               frame_handle_start->property_fill_color_rgba() = color_map[cFrameHandleStartFill];
                
                
-               frame_handle_end = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
-                                                      gtk_canvas_simplerect_get_type(),
-                                                      "x1", (double) (trackview.editor.frame_to_pixel(get_duration())) - (TimeAxisViewItem::GRAB_HANDLE_LENGTH),
-                                                      "x2", (double) trackview.editor.frame_to_pixel(get_duration()),
-                                                      "y1", (double) 1,
-                                                      "y2", (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH + 1,
-                                                      "outline_color_rgba", color_map[cFrameHandleEndOutline],
-                                                      "fill_color_rgba", color_map[cFrameHandleEndFill],
-                                                      NULL) ;
+               frame_handle_end = new ArdourCanvas::SimpleRect (*group);
+               frame_handle_end->property_x1() = (double) (trackview.editor.frame_to_pixel(get_duration())) - (TimeAxisViewItem::GRAB_HANDLE_LENGTH);
+               frame_handle_end->property_x2() = (double) trackview.editor.frame_to_pixel(get_duration());
+               frame_handle_end->property_y1() = (double) 1;
+               frame_handle_end->property_y2() = (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH + 1;
+               frame_handle_end->property_outline_color_rgba() = color_map[cFrameHandleEndOutline];
+               frame_handle_end->property_fill_color_rgba() = color_map[cFrameHandleEndFill];
+
        } else {
                frame_handle_start = 0;
                frame_handle_end = 0;
        } else {
                frame_handle_start = 0;
                frame_handle_end = 0;
@@ -174,13 +251,12 @@ TimeAxisViewItem::TimeAxisViewItem(std::string it_name, GtkCanvasGroup* parent,
        set_position (start, this) ;
 }
 
        set_position (start, this) ;
 }
 
-
 /**
  * Destructor
  */
 TimeAxisViewItem::~TimeAxisViewItem()
 {
 /**
  * Destructor
  */
 TimeAxisViewItem::~TimeAxisViewItem()
 {
-       gtk_object_destroy (GTK_OBJECT(group));
+       delete group;
 }
 
 
 }
 
 
@@ -195,7 +271,7 @@ TimeAxisViewItem::~TimeAxisViewItem()
  * @return true if the position change was a success, false otherwise
  */
 bool
  * @return true if the position change was a success, false otherwise
  */
 bool
-TimeAxisViewItem::set_position(jack_nframes_t pos, void* src, double* delta)
+TimeAxisViewItem::set_position(nframes_t pos, void* src, double* delta)
 {
        if (position_locked) {
                return false;
 {
        if (position_locked) {
                return false;
@@ -203,32 +279,29 @@ TimeAxisViewItem::set_position(jack_nframes_t pos, void* src, double* delta)
 
        frame_position = pos;
        
 
        frame_position = pos;
        
-       /*  This sucks. The GtkCanvas version I am using
-           doesn't correctly implement gtk_canvas_group_set_arg(),
+       /*  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
            fails to move the group. Instead, we have to
            so that simply setting the "x" arg of the group
            fails to move the group. Instead, we have to
-           use gtk_canvas_item_move(), which does the right
+           use gnome_canvas_item_move(), which does the right
            thing. I see that in GNOME CVS, the current (Sept 2001)
            version of GNOME Canvas rectifies this issue cleanly.
        */
        
            thing. I see that in GNOME CVS, the current (Sept 2001)
            version of GNOME Canvas rectifies this issue cleanly.
        */
        
-       GtkArg args[1] ;
        double old_unit_pos ;
        double new_unit_pos = pos / samples_per_unit ;
 
        double old_unit_pos ;
        double new_unit_pos = pos / samples_per_unit ;
 
-       args[0].name = "x" ;
-       gtk_object_getv (GTK_OBJECT(group), 1, args) ;
-       old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ;
+       old_unit_pos = group->property_x();
 
        if (new_unit_pos != old_unit_pos) {
 
        if (new_unit_pos != old_unit_pos) {
-               gtk_canvas_item_move (group, new_unit_pos - old_unit_pos, 0.0) ;
+               group->move (new_unit_pos - old_unit_pos, 0.0);
        }
        }
-
+       
        if (delta) {
                (*delta) = new_unit_pos - old_unit_pos;
        }
        
        if (delta) {
                (*delta) = new_unit_pos - old_unit_pos;
        }
        
-        PositionChanged (frame_position, src) ; /* EMIT_SIGNAL */
+       PositionChanged (frame_position, src) ; /* EMIT_SIGNAL */
 
        return true;
 }
 
        return true;
 }
@@ -238,7 +311,7 @@ TimeAxisViewItem::set_position(jack_nframes_t pos, void* src, double* delta)
  *
  * @return the position of this item
  */
  *
  * @return the position of this item
  */
-jack_nframes_t
+nframes_t
 TimeAxisViewItem::get_position() const
 {
        return frame_position;
 TimeAxisViewItem::get_position() const
 {
        return frame_position;
@@ -252,25 +325,23 @@ TimeAxisViewItem::get_position() const
  * @return true if the duration change was succesful, false otherwise
  */
 bool
  * @return true if the duration change was succesful, false otherwise
  */
 bool
-TimeAxisViewItem::set_duration (jack_nframes_t dur, void* src)
+TimeAxisViewItem::set_duration (nframes_t dur, void* src)
 {
        if ((dur > max_item_duration) || (dur < min_item_duration)) {
 {
        if ((dur > max_item_duration) || (dur < min_item_duration)) {
-               warning << compose (_("new duration %1 frames is out of bounds for %2"), get_item_name(), dur)
+               warning << string_compose (_("new duration %1 frames is out of bounds for %2"), get_item_name(), dur)
                        << endmsg;
                return false;
        }
 
        if (dur == 0) {
                        << endmsg;
                return false;
        }
 
        if (dur == 0) {
-               gtk_canvas_item_hide (group);
+               group->hide();
        }
 
        item_duration = dur;
        
        }
 
        item_duration = dur;
        
-       double pixel_width = trackview.editor.frame_to_pixel (dur);
-
-       reset_width_dependent_items (pixel_width);
+       reset_width_dependent_items (trackview.editor.frame_to_pixel (dur));
        
        
-        DurationChanged (dur, src) ; /* EMIT_SIGNAL */
+       DurationChanged (dur, src) ; /* EMIT_SIGNAL */
        return true;
 }
 
        return true;
 }
 
@@ -278,7 +349,7 @@ TimeAxisViewItem::set_duration (jack_nframes_t dur, void* src)
  * Returns the duration of this item
  *
  */
  * Returns the duration of this item
  *
  */
-jack_nframes_t
+nframes_t
 TimeAxisViewItem::get_duration() const
 {
        return (item_duration);
 TimeAxisViewItem::get_duration() const
 {
        return (item_duration);
@@ -291,10 +362,10 @@ TimeAxisViewItem::get_duration() const
  * @param src the identity of the object that initiated the change
  */
 void
  * @param src the identity of the object that initiated the change
  */
 void
-TimeAxisViewItem::set_max_duration(jack_nframes_t dur, void* src)
+TimeAxisViewItem::set_max_duration(nframes_t dur, void* src)
 {
        max_item_duration = dur ;
 {
        max_item_duration = dur ;
-        MaxDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
+       MaxDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
 }
                
 /**
 }
                
 /**
@@ -302,10 +373,10 @@ TimeAxisViewItem::set_max_duration(jack_nframes_t dur, void* src)
  *
  * @return the maximum duration that this item may be set to
  */
  *
  * @return the maximum duration that this item may be set to
  */
-jack_nframes_t
+nframes_t
 TimeAxisViewItem::get_max_duration() const
 {
 TimeAxisViewItem::get_max_duration() const
 {
-       return(max_item_duration) ;
+       return (max_item_duration) ;
 }
 
 /**
 }
 
 /**
@@ -315,10 +386,10 @@ TimeAxisViewItem::get_max_duration() const
  * @param src the identity of the object that initiated the change
  */
 void
  * @param src the identity of the object that initiated the change
  */
 void
-TimeAxisViewItem::set_min_duration(jack_nframes_t dur, void* src)
+TimeAxisViewItem::set_min_duration(nframes_t dur, void* src)
 {
        min_item_duration = dur ;
 {
        min_item_duration = dur ;
-        MinDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
+       MinDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
 }
                
 /**
 }
                
 /**
@@ -326,7 +397,7 @@ TimeAxisViewItem::set_min_duration(jack_nframes_t dur, void* src)
  *
  * @return the nimum duration that this item mey be set to
  */
  *
  * @return the nimum duration that this item mey be set to
  */
-jack_nframes_t
+nframes_t
 TimeAxisViewItem::get_min_duration() const
 {
        return(min_item_duration) ;
 TimeAxisViewItem::get_min_duration() const
 {
        return(min_item_duration) ;
@@ -420,6 +491,7 @@ TimeAxisViewItem::set_item_name(std::string new_name, void* src)
        if (new_name != item_name) {
                std::string temp_name = item_name ;
                item_name = new_name ;
        if (new_name != item_name) {
                std::string temp_name = item_name ;
                item_name = new_name ;
+               name_text_width = ::pixel_width (new_name, NAME_FONT);
                NameChanged (item_name, temp_name, src) ; /* EMIT_SIGNAL */
        }
 }
                NameChanged (item_name, temp_name, src) ; /* EMIT_SIGNAL */
        }
 }
@@ -445,26 +517,14 @@ TimeAxisViewItem::get_item_name() const
  * @param src the identity of the object that initiated the change
  */
 void
  * @param src the identity of the object that initiated the change
  */
 void
-TimeAxisViewItem::set_selected(bool yn, void* src)
+TimeAxisViewItem::set_selected(bool yn)
 {
        if (_selected != yn) {
 {
        if (_selected != yn) {
-               _selected = yn ;
+               Selectable::set_selected (yn);
                set_frame_color ();
                set_frame_color ();
-               Selected (_selected) ; /* EMIT_SIGNAL */
        }
 }
 
        }
 }
 
-/**
- * Returns whether this item is currently selected.
- *
- * @return true if this item is currently selected, false otherwise
- */
-bool
-TimeAxisViewItem::get_selected() const
-{
-       return (_selected) ;
-}
-
 void 
 TimeAxisViewItem::set_should_show_selection (bool yn)
 {
 void 
 TimeAxisViewItem::set_should_show_selection (bool yn)
 {
@@ -497,67 +557,72 @@ TimeAxisViewItem::get_time_axis_view()
  * @param new_name the new name text to display
  */
 void
  * @param new_name the new name text to display
  */
 void
-TimeAxisViewItem::set_name_text(std::string new_name)
+TimeAxisViewItem::set_name_text(const ustring& new_name)
 {
        if (name_text) {
 {
        if (name_text) {
-               gtk_canvas_item_set (name_text, "text", new_name.c_str(), NULL);
+               name_text->property_text() = new_name;
+               name_text_width = pixel_width (new_name, NAME_FONT);
+               name_text_size_cache.clear ();
        }
 }
 
 /**
        }
 }
 
 /**
- * Set the height of this item
+ * Set the y position and height of this item.
  *
  *
+ * @param y the new y position
  * @param h the new height
  */            
 void
  * @param h the new height
  */            
 void
-TimeAxisViewItem::set_height(double height)
+TimeAxisViewItem::set_y_position_and_height (double y, double h)
 {
        if (name_highlight) {
 {
        if (name_highlight) {
-               if (height < NAME_HIGHLIGHT_THRESH) {
-                       gtk_canvas_item_hide (name_highlight);
-                       gtk_canvas_item_hide (name_text);
+               if (h < NAME_HIGHLIGHT_THRESH) {
+                       name_highlight->hide();
+                       if (name_text) {
+                               name_text->hide();
+                       }
                } else {
                } else {
-                       gtk_canvas_item_show (name_highlight);
-                       gtk_canvas_item_show (name_text);
+                       name_highlight->show();
+                       if (name_text) {
+                               name_text->show();
+                       }
                }
 
                }
 
-               if (height > NAME_HIGHLIGHT_SIZE) {
-                       gtk_canvas_item_set (name_highlight, 
-                                            "y1", (double) height+1 - NAME_HIGHLIGHT_SIZE,
-                                            "y2", (double) height,
-                                            NULL);
+               if (h > NAME_HIGHLIGHT_SIZE) {
+                       name_highlight->property_y1() = (double) y + h + 1 - NAME_HIGHLIGHT_SIZE;
+                       name_highlight->property_y2() = (double) y + h;
                }
                else {
                        /* it gets hidden now anyway */
                }
                else {
                        /* it gets hidden now anyway */
-                       gtk_canvas_item_set (name_highlight, 
-                                            "y1", (double) 1.0,
-                                            "y2", (double) height,
-                                            NULL);
+                       name_highlight->property_y1() = (double) y;
+                       name_highlight->property_y2() = (double) y + h;
                }
        }
 
        if (name_text) {
                }
        }
 
        if (name_text) {
-               gtk_canvas_item_set (name_text, "y", height+1 - NAME_Y_OFFSET, NULL);
-               if (height < NAME_HIGHLIGHT_THRESH) {
-                       gtk_canvas_item_set(name_text, "fill_color_rgba",  fill_color, NULL) ;
+               name_text->property_y() = y + h + 1 - NAME_Y_OFFSET;
+               if (h < NAME_HIGHLIGHT_THRESH) {
+                       name_text->property_fill_color_rgba() =  fill_color;
                }
                else {
                }
                else {
-                       gtk_canvas_item_set(name_text, "fill_color_rgba", label_color, NULL) ;
+                       name_text->property_fill_color_rgba() = label_color;
                }
        }
 
        if (frame) {
                }
        }
 
        if (frame) {
-               gtk_canvas_item_set (frame, "y2", height+1, NULL) ;
+               frame->property_y1() = y;
+               frame->property_y2() = y + h + 1;
        }
 
        }
 
-       gtk_canvas_item_set (vestigial_frame, "y2", height+1, NULL) ;
+       vestigial_frame->property_y1() = y;
+       vestigial_frame->property_y2() = y + h + 1;
 }
 
 /**
  * 
  */
 void
 }
 
 /**
  * 
  */
 void
-TimeAxisViewItem::set_color(GdkColor& base_color)
+TimeAxisViewItem::set_color(Gdk::Color& base_color)
 {
        compute_colors (base_color);
        set_colors ();
 {
        compute_colors (base_color);
        set_colors ();
@@ -566,7 +631,7 @@ TimeAxisViewItem::set_color(GdkColor& base_color)
 /**
  * 
  */
 /**
  * 
  */
-GtkCanvasItem*
+ArdourCanvas::Item*
 TimeAxisViewItem::get_canvas_frame()
 {
        return(frame) ;
 TimeAxisViewItem::get_canvas_frame()
 {
        return(frame) ;
@@ -575,28 +640,28 @@ TimeAxisViewItem::get_canvas_frame()
 /**
  * 
  */
 /**
  * 
  */
-GtkCanvasItem*
+ArdourCanvas::Item*
 TimeAxisViewItem::get_canvas_group()
 {
 TimeAxisViewItem::get_canvas_group()
 {
-       return(group) ;
+       return (group) ;
 }
 
 /**
  * 
  */
 }
 
 /**
  * 
  */
-GtkCanvasItem*
+ArdourCanvas::Item*
 TimeAxisViewItem::get_name_highlight()
 {
 TimeAxisViewItem::get_name_highlight()
 {
-       return(name_highlight) ;
+       return (name_highlight) ;
 }
 
 /**
  * 
  */
 }
 
 /**
  * 
  */
-GtkCanvasItem*
+ArdourCanvas::Text*
 TimeAxisViewItem::get_name_text()
 {
 TimeAxisViewItem::get_name_text()
 {
-       return(name_text) ;
+       return (name_text) ;
 }
 
 /**
 }
 
 /**
@@ -605,7 +670,7 @@ TimeAxisViewItem::get_name_text()
  * @param color the base color of the item
  */
 void
  * @param color the base color of the item
  */
 void
-TimeAxisViewItem::compute_colors(GdkColor& base_color)
+TimeAxisViewItem::compute_colors(Gdk::Color& base_color)
 {
        unsigned char radius ;
        char minor_shift ;
 {
        unsigned char radius ;
        char minor_shift ;
@@ -613,9 +678,9 @@ TimeAxisViewItem::compute_colors(GdkColor& base_color)
        unsigned char r,g,b ;
 
        /* FILL: this is simple */
        unsigned char r,g,b ;
 
        /* FILL: this is simple */
-       r = base_color.red/256 ;
-       g = base_color.green/256 ;
-       b = base_color.blue/256 ;
+       r = base_color.get_red()/256 ;
+       g = base_color.get_green()/256 ;
+       b = base_color.get_blue()/256 ;
        fill_color = RGBA_TO_UINT(r,g,b,255) ;
 
        /*  for minor colors:
        fill_color = RGBA_TO_UINT(r,g,b,255) ;
 
        /*  for minor colors:
@@ -631,9 +696,9 @@ TimeAxisViewItem::compute_colors(GdkColor& base_color)
 
        /* LABEL: rotate around color wheel by 120 degrees anti-clockwise */
 
 
        /* LABEL: rotate around color wheel by 120 degrees anti-clockwise */
 
-       r = base_color.red/256;
-       g = base_color.green/256;
-       b = base_color.blue/256;
+       r = base_color.get_red()/256;
+       g = base_color.get_green()/256;
+       b = base_color.get_blue()/256;
   
        if (r > b)
        {
   
        if (r > b)
        {
@@ -667,9 +732,9 @@ TimeAxisViewItem::compute_colors(GdkColor& base_color)
        g += minor_shift;
   
        label_color = RGBA_TO_UINT(r,g,b,255);
        g += minor_shift;
   
        label_color = RGBA_TO_UINT(r,g,b,255);
-       r = (base_color.red/256)   + 127 ;
-       g = (base_color.green/256) + 127 ;
-       b = (base_color.blue/256)  + 127 ;
+       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);
 
   
        label_color = RGBA_TO_UINT(r,g,b,255);
 
@@ -704,23 +769,20 @@ TimeAxisViewItem::set_colors()
                double height = NAME_HIGHLIGHT_THRESH;
 
                if (frame) {
                double height = NAME_HIGHLIGHT_THRESH;
 
                if (frame) {
-                       GtkArg args[1] ;
-                       args[0].name = "y2" ;
-                       gtk_object_getv (GTK_OBJECT(frame), 1, args);
-                       height = GTK_VALUE_DOUBLE (args[0]);
+                       height = frame->property_y2();
                }
 
                if (height < NAME_HIGHLIGHT_THRESH) {
                }
 
                if (height < NAME_HIGHLIGHT_THRESH) {
-                       gtk_canvas_item_set(name_text, "fill_color_rgba",  fill_color, NULL) ;
+                       name_text->property_fill_color_rgba() =  fill_color;
                }
                else {
                }
                else {
-                       gtk_canvas_item_set(name_text, "fill_color_rgba", label_color, NULL) ;
+                       name_text->property_fill_color_rgba() = label_color;
                }
        }
 
        if (name_highlight) {
                }
        }
 
        if (name_highlight) {
-               gtk_canvas_item_set(name_highlight, "fill_color_rgba", fill_color, NULL) ;
-               gtk_canvas_item_set(name_highlight, "outline_color_rgba", fill_color, NULL) ;
+               name_highlight->property_fill_color_rgba() = fill_color;
+               name_highlight->property_outline_color_rgba() = fill_color;
        }
        set_trim_handle_colors() ;
 }
        }
        set_trim_handle_colors() ;
 }
@@ -736,10 +798,10 @@ TimeAxisViewItem::set_frame_color()
                
                if (_selected && should_show_selection) {
                        UINT_TO_RGBA(color_map[cSelectedFrameBase], &r, &g, &b, &a);
                
                if (_selected && should_show_selection) {
                        UINT_TO_RGBA(color_map[cSelectedFrameBase], &r, &g, &b, &a);
-                       gtk_canvas_item_set(frame, "fill_color_rgba", RGBA_TO_UINT(r, g, b, fill_opacity), NULL) ;
+                       frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity);
                } else {
                        UINT_TO_RGBA(color_map[cFrameBase], &r, &g, &b, &a);
                } else {
                        UINT_TO_RGBA(color_map[cFrameBase], &r, &g, &b, &a);
-                       gtk_canvas_item_set(frame, "fill_color_rgba", RGBA_TO_UINT(r, g, b, fill_opacity), NULL) ;
+                       frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity);
                }
        }
 }
                }
        }
 }
@@ -753,11 +815,11 @@ TimeAxisViewItem::set_trim_handle_colors()
 {
        if (frame_handle_start) {
                if (position_locked) {
 {
        if (frame_handle_start) {
                if (position_locked) {
-                       gtk_canvas_item_set(frame_handle_start, "fill_color_rgba", color_map[cTrimHandleLockedStart], NULL);
-                       gtk_canvas_item_set(frame_handle_end, "fill_color_rgba", color_map[cTrimHandleLockedEnd], NULL) ;
+                       frame_handle_start->property_fill_color_rgba() = color_map[cTrimHandleLockedStart];
+                       frame_handle_end->property_fill_color_rgba() = color_map[cTrimHandleLockedEnd];
                } else {
                } else {
-                       gtk_canvas_item_set(frame_handle_start, "fill_color_rgba", color_map[cTrimHandleStart], NULL) ;
-                       gtk_canvas_item_set(frame_handle_end, "fill_color_rgba", color_map[cTrimHandleEnd], NULL) ;
+                       frame_handle_start->property_fill_color_rgba() = color_map[cTrimHandleStart];
+                       frame_handle_end->property_fill_color_rgba() = color_map[cTrimHandleEnd];
                }
        }
 }
                }
        }
 }
@@ -782,66 +844,74 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
        if (pixel_width < GRAB_HANDLE_LENGTH * 2) {
 
                if (frame_handle_start) {
        if (pixel_width < GRAB_HANDLE_LENGTH * 2) {
 
                if (frame_handle_start) {
-                       gtk_canvas_item_hide (frame_handle_start);
-                       gtk_canvas_item_hide (frame_handle_end);
+                       frame_handle_start->hide();
+                       frame_handle_end->hide();
                }
 
        } if (pixel_width < 2.0) {
 
                if (show_vestigial) {
                }
 
        } if (pixel_width < 2.0) {
 
                if (show_vestigial) {
-                       gtk_canvas_item_show (vestigial_frame);
+                       vestigial_frame->show();
                }
 
                if (name_highlight) {
                }
 
                if (name_highlight) {
-                       gtk_canvas_item_hide (name_highlight);
-                       gtk_canvas_item_hide (name_text);
+                       name_highlight->hide();
+                       if (name_text) {
+                               name_text->hide();
+                       }
                }
 
                if (frame) {
                }
 
                if (frame) {
-                       gtk_canvas_item_hide (frame);
+                       frame->hide();
                }
 
                if (frame_handle_start) {
                }
 
                if (frame_handle_start) {
-                       gtk_canvas_item_hide (frame_handle_start);
-                       gtk_canvas_item_hide (frame_handle_end);
+                       frame_handle_start->hide();
+                       frame_handle_end->hide();
                }
                
        } else {
                }
                
        } else {
-               gtk_canvas_item_hide (vestigial_frame);
+               vestigial_frame->hide();
 
                if (name_highlight) {
 
 
                if (name_highlight) {
 
-                       GtkArg args[1] ;
-                       args[0].name = "y2" ;
-                       gtk_object_getv (GTK_OBJECT(name_highlight), 1, args);
-                       double height = GTK_VALUE_DOUBLE (args[0]);
+                       double height = name_highlight->property_y2 ();
 
                        if (height < NAME_HIGHLIGHT_THRESH) {
 
                        if (height < NAME_HIGHLIGHT_THRESH) {
-                               gtk_canvas_item_hide (name_highlight);
-                               gtk_canvas_item_hide (name_text);
+                               name_highlight->hide();
+                               if (name_text) {
+                                       name_text->hide();
+                               }
+                       } else {
+                               name_highlight->show();
+                               if (name_text && !get_item_name().empty()) {
+                                       name_text->show();
+                                       reset_name_width (pixel_width);
+                               }
+                       }
+
+                       if (visibility & FullWidthNameHighlight) {
+                               name_highlight->property_x2() = pixel_width;
                        } else {
                        } else {
-                               gtk_canvas_item_show (name_highlight);
-                               gtk_canvas_item_show (name_text);
-                               reset_name_width (pixel_width);
+                               name_highlight->property_x2() = pixel_width - 1.0;
                        }
 
                        }
 
-                       gtk_canvas_item_set (name_highlight, "x2", pixel_width - 1.0, NULL);
                }
 
                if (frame) {
                }
 
                if (frame) {
-                       gtk_canvas_item_show (frame);
-                       gtk_canvas_item_set (frame, "x2", pixel_width, NULL);
+                       frame->show();
+                       frame->property_x2() = pixel_width;
                }
 
                if (frame_handle_start) {
                        if (pixel_width < (2*TimeAxisViewItem::GRAB_HANDLE_LENGTH)) {
                }
 
                if (frame_handle_start) {
                        if (pixel_width < (2*TimeAxisViewItem::GRAB_HANDLE_LENGTH)) {
-                               gtk_canvas_item_hide (frame_handle_start);
-                               gtk_canvas_item_hide (frame_handle_end);
+                               frame_handle_start->hide();
+                               frame_handle_end->hide();
                        }
                        }
-                       gtk_canvas_item_show (frame_handle_start);
-                       gtk_canvas_item_set(GTK_CANVAS_ITEM(frame_handle_end), "x1", pixel_width - (TimeAxisViewItem::GRAB_HANDLE_LENGTH ), NULL) ;
-                       gtk_canvas_item_show (frame_handle_end);
-                       gtk_canvas_item_set(GTK_CANVAS_ITEM(frame_handle_end), "x2", pixel_width, NULL) ;
+                       frame_handle_start->show();
+                       frame_handle_end->property_x1() = pixel_width - (TimeAxisViewItem::GRAB_HANDLE_LENGTH);
+                       frame_handle_end->show();
+                       frame_handle_end->property_x2() = pixel_width;
                }
        }
 }
                }
        }
 }
@@ -849,63 +919,90 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
 void
 TimeAxisViewItem::reset_name_width (double pixel_width)
 {
 void
 TimeAxisViewItem::reset_name_width (double pixel_width)
 {
-       gint width;
-       gint lbearing;
-       gint rbearing;
-       gint ascent;
-       gint descent;
-       Gdk_Font font (NAME_FONT);
-
        if (name_text == 0) {
                return;
        }
 
        if (name_text == 0) {
                return;
        }
 
-       int namelen = item_name.length();
-       char cstr[namelen+1];
-       strcpy (cstr, item_name.c_str());
-       
-       while (namelen) {
-               
-               gdk_string_extents (font,
-                                   cstr,
-                                   &lbearing,
-                                   &rbearing,
-                                   &width,
-                                   &ascent,
-                                   &descent);
-
-               if (width < (pixel_width - NAME_X_OFFSET)) {
-                       break;
-               }
+       int limit = (int) floor (pixel_width - NAME_X_OFFSET);
+       bool shrinking = (last_name_text_width > pixel_width);
+       int actual_width;
+       ustring ustr;
+       ustring::size_type n;
+
+       if ((last_name_text_width &&                                       // we did this once
+            shrinking &&                                                  // we're getting smaller
+            (name_text_width <= limit) &&                                 // fits the new size
+            (name_text_width <= last_name_text_width - NAME_X_OFFSET))) { // fit into the old size too
+               last_name_text_width = pixel_width;
+               return;
+       }
 
 
-               --namelen;
-               cstr[namelen] = '\0';
+       /* now check the cache of existing truncations */
 
 
-       }
+       Gtk::Label foo;
+       Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
 
 
-       if (namelen == 0) {
-               
-               gtk_canvas_item_hide (name_text);
+       for (n = item_name.length(); n > 0; --n) {
                
                
-       } else {
-               
-               /* don't use name for event handling if it leaves no room
-                  for trimming to work.
-               */
-               
-               if (pixel_width - width < (NAME_X_OFFSET * 2.0)) {
-                       if (name_connected) {
-                               name_connected = false;
+               map<ustring::size_type,int>::iterator i;
+
+               if ((i = name_text_size_cache.find (n)) != name_text_size_cache.end()) {
+
+                       /* we know the length of this substring already */
+                       
+                       if ((actual_width = (*i).second) < limit) {
+
+                               /* it fits, use it */
+                               
+                               ustr = item_name.substr (0, n);
+                               break;
                        }
                        }
+                                               
                } else {
                } else {
-                       if (!name_connected) {
-                               name_connected = true;
+                       
+                       /* we don't know the length of this substring already, so compute
+                          it and put it into the cache.
+                        */
+
+                       layout->set_text (item_name.substr (0, n));
+                       
+                       int width, height;
+                       Gtkmm2ext::get_ink_pixel_size (layout, width, height);
+                       
+                       name_text_size_cache[n] = width;
+
+                       if ((actual_width = width) < limit) {
+                               ustr = item_name.substr (0, n);
+                               break;
                        }
                }
                        }
                }
-               
-               gtk_canvas_item_set (name_text, "text", cstr, NULL);
-               gtk_canvas_item_show (name_text);
        }
        }
+
+       if (n == 0) {
+               name_text->property_text() = "";
+               last_name_text_width = pixel_width;
+               return;
+       } 
+
+       /* don't use name for event handling if it leaves no room
+          for trimming to work.
+       */
+       
+       if (pixel_width - actual_width < (NAME_X_OFFSET * 2.0)) {
+               if (name_connected) {
+                       name_connected = false;
+               }
+       } else {
+               if (!name_connected) {
+                       name_connected = true;
+               }
+       }
+       
+       name_text->property_text() = ustr;
+       name_text_width = actual_width;
+       name_text->show();
+       last_name_text_width = pixel_width;
+
 }
 
 
 }
 
 
@@ -929,7 +1026,7 @@ TimeAxisViewItem::remove_this_item(void* src)
           defer to idle loop, otherwise we'll delete this object
           while we're still inside this function ...
        */
           defer to idle loop, otherwise we'll delete this object
           while we're still inside this function ...
        */
-       Gtk::Main::idle.connect(bind(mem_fun(&TimeAxisViewItem::idle_remove_this_item), this, src));
+        Glib::signal_idle().connect(bind (sigc::ptr_fun (&TimeAxisViewItem::idle_remove_this_item), this, src));
 }
 
 /**
 }
 
 /**
@@ -937,14 +1034,14 @@ TimeAxisViewItem::remove_this_item(void* src)
  * This is used to avoid deleting the obejct while inside the remove_this_item
  * method
  *
  * This is used to avoid deleting the obejct while inside the remove_this_item
  * method
  *
- * @param item the ImageFrameTimeAxisGroup to remove
+ * @param item the TimeAxisViewItem to remove
  * @param src the identity of the object that initiated the change
  */
 gint
 TimeAxisViewItem::idle_remove_this_item(TimeAxisViewItem* item, void* src)
 {
  * @param src the identity of the object that initiated the change
  */
 gint
 TimeAxisViewItem::idle_remove_this_item(TimeAxisViewItem* item, void* src)
 {
-        item->ItemRemoved(item->get_item_name(), src) ; /* EMIT_SIGNAL */
-       delete item ;
-       item = 0 ;
-       return(false) ;
+       item->ItemRemoved (item->get_item_name(), src) ; /* EMIT_SIGNAL */
+       delete item;
+       item = 0;
+       return false;
 }
 }