patch from mantis user cth103 to fix up fixed-time cross-track drags
[ardour.git] / gtk2_ardour / time_axis_view.cc
index e30c8def43ae4bb0075ce2697486889ca39bb485..2a0087dc2ccd2798804ce4f2cb361db67a4d5b30 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>
@@ -24,7 +23,7 @@
 #include <string>
 #include <list>
 
-#include <libgnomecanvasmm/libgnomecanvasmm.h>
+#include <libgnomecanvasmm.h>
 #include <libgnomecanvasmm/canvas.h>
 #include <libgnomecanvasmm/item.h>
 
@@ -55,6 +54,7 @@ using namespace Gtk;
 using namespace Gdk;
 using namespace sigc; 
 using namespace ARDOUR;
+using namespace PBD;
 using namespace Editing;
 using namespace ArdourCanvas;
 
@@ -71,7 +71,7 @@ bool TimeAxisView::need_size_info = true;
 TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* rent, Canvas& canvas) 
        : AxisView (sess), 
          editor (ed),
-         controls_table (2, 9)
+         controls_table (2, 8)
 {
        if (need_size_info) {
                compute_controls_size_info ();
@@ -125,8 +125,9 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie
        controls_table.set_col_spacings (0);
        controls_table.set_homogeneous (true);
 
-       controls_table.attach (name_hbox, 0, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+       controls_table.attach (name_hbox, 0, 4, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
        controls_table.show_all ();
+       controls_table.set_no_show_all ();
 
        controls_vbox.pack_start (controls_table, false, false);
        controls_vbox.show ();
@@ -147,6 +148,8 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie
        controls_frame.add (controls_hbox);
        controls_frame.set_name ("TimeAxisViewControlsBaseUnselected");
        controls_frame.set_shadow_type (Gtk::SHADOW_OUT);
+
+       ColorChanged.connect (mem_fun (*this, &TimeAxisView::color_handler));
 }
 
 TimeAxisView::~TimeAxisView()
@@ -230,7 +233,7 @@ TimeAxisView::show_at (double y, int& nth, VBox *parent)
                
                if (canvas_item_visible ((*i)->canvas_display)) {
                        ++nth;
-                       effective_height += (*i)->show_at (y + effective_height, nth, parent);
+                       effective_height += (*i)->show_at (y + 1 + effective_height, nth, parent);
                }
        }
 
@@ -242,14 +245,14 @@ TimeAxisView::controls_ebox_scroll (GdkEventScroll* ev)
 {
        switch (ev->direction) {
        case GDK_SCROLL_UP:
-               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
                        step_height (true);
                        return true;
                }
                break;
                
        case GDK_SCROLL_DOWN:
-               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
                        step_height (false);
                        return true;
                }
@@ -282,18 +285,8 @@ TimeAxisView::controls_ebox_button_release (GdkEventButton* ev)
 void
 TimeAxisView::selection_click (GdkEventButton* ev)
 {
-       if (Keyboard::modifier_state_contains (ev->state, Keyboard::Shift)) {
-
-               if (editor.get_selection().selected (this)) {
-                       editor.get_selection().remove (this);
-               } else {
-                       editor.get_selection().add (this);
-               }
-
-       } else {
-
-               editor.get_selection().set (this);
-       }
+       Selection::Operation op = Keyboard::selection_type (ev->state);
+       editor.set_selected_track (*this, op, false);
 }
 
 void
@@ -326,30 +319,35 @@ TimeAxisView::hide ()
 void
 TimeAxisView::step_height (bool bigger)
 {
-       switch (height) {
-       case Largest:
-               if (!bigger) set_height (Large);
-               break;
-       case Large:
-               if (bigger) set_height (Largest);
-               else set_height (Larger);
-               break;
-       case Larger:
-               if (bigger) set_height (Large);
-               else set_height (Normal);
-               break;
-       case Normal:
-               if (bigger) set_height (Larger);
-               else set_height (Smaller);
-               break;
-       case Smaller:
-               if (bigger) set_height (Normal);
-               else set_height (Small);
-               break;
-       case Small:
-               if (bigger) set_height (Smaller);
-               break;
-       }
+  
+       if (height == hLargest) {
+               if (!bigger) set_height (Large);
+               return;
+       }
+       if (height == hLarge) {
+               if (bigger) set_height (Largest);
+                else set_height (Larger);
+               return;
+       }
+       if (height == hLarger) {
+                if (bigger) set_height (Large);
+                else set_height (Normal);
+               return;
+       }
+       if (height == hNormal) {
+                if (bigger) set_height (Larger);
+                else set_height (Smaller);
+               return;
+       }
+       if (height == hSmaller) {
+                if (bigger) set_height (Normal);
+                else set_height (Small);
+               return;
+       }
+       if (height == hSmall) {
+                if (bigger) set_height (Smaller);
+               return;
+       }
 }
 
 void
@@ -374,8 +372,48 @@ TimeAxisView::set_height_pixels (uint32_t h)
 bool
 TimeAxisView::name_entry_key_release (GdkEventKey* ev)
 {
+       PublicEditor::TrackViewList *allviews = 0;
+       PublicEditor::TrackViewList::iterator i;
+
        switch (ev->keyval) {
+       case GDK_Escape:
+               name_entry.select_region (0,0);
+               controls_ebox.grab_focus ();
+               name_entry_changed ();
+               return true;
+
+       /* Shift+Tab Keys Pressed. Note that for Shift+Tab, GDK actually
+        * generates a different ev->keyval, rather than setting 
+        * ev->state.
+        */
+       case GDK_ISO_Left_Tab:
        case GDK_Tab:
+               name_entry_changed ();
+               allviews = editor.get_valid_views (0);
+               if (allviews != 0) {
+                       i = find (allviews->begin(), allviews->end(), this);
+                       if (ev->keyval == GDK_Tab) {
+                               if (i != allviews->end()) {
+                                       do {
+                                               if (++i == allviews->end()) { return true; }
+                                       } while((*i)->hidden());
+                               }
+                       } else {
+                               if (i != allviews->begin()) {
+                                       do {
+                                               if (--i == allviews->begin()) { return true; }
+                                       } while ((*i)->hidden());
+                               }
+                       }
+
+                       if ((*i)->height_style == Small) {
+                               (*i)->set_height(Smaller);
+                       }
+                       
+                       (*i)->name_entry.grab_focus();
+               }
+               return true;
+
        case GDK_Up:
        case GDK_Down:
                name_entry_changed ();
@@ -425,6 +463,7 @@ TimeAxisView::name_entry_focus_out (GdkEventFocus* ev)
        last_name_entry_key_press_event = 0;
        name_entry_key_timeout.disconnect ();
        name_entry.set_name ("EditorTrackNameDisplay");
+       name_entry.select_region (0,0);
        
        /* do the real stuff */
 
@@ -476,12 +515,14 @@ TimeAxisView::popup_display_menu (guint32 when)
        if (display_menu == 0) {
                build_display_menu ();
        }
+       editor.set_selected_track (*this, Selection::Add);
        display_menu->popup (1, when);  
 }
 
 gint
 TimeAxisView::size_click (GdkEventButton *ev)
 {
+       editor.set_selected_track (*this, Selection::Add);
        popup_size_menu (ev->time);
        return TRUE;
 }
@@ -566,7 +607,7 @@ TimeAxisView::set_samples_per_unit (double spu)
 }
 
 void
-TimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end)
+TimeAxisView::show_timestretch (nframes_t start, nframes_t end)
 {
        for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
                (*i)->show_timestretch (start, end);
@@ -608,7 +649,7 @@ TimeAxisView::show_selection (TimeSelection& ts)
        selection_group->raise_to_top();
        
        for (list<AudioRange>::iterator i = ts.begin(); i != ts.end(); ++i) {
-               jack_nframes_t start, end, cnt;
+               nframes_t start, end, cnt;
 
                start = (*i).start;
                end = (*i).end;
@@ -616,8 +657,8 @@ TimeAxisView::show_selection (TimeSelection& ts)
 
                rect = get_selection_rect ((*i).id);
                
-               x1 = start / editor.get_current_zoom();
-               x2 = (start + cnt - 1) / editor.get_current_zoom();
+               x1 = editor.frame_to_unit (start);
+               x2 = editor.frame_to_unit (start + cnt - 1);
                y2 = height;
 
                rect->rect->property_x1() = x1;
@@ -719,8 +760,9 @@ TimeAxisView::get_selection_rect (uint32_t id)
 
        for (list<SelectionRect*>::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i) {
                if ((*i)->id == id) {
+                       SelectionRect* ret = (*i);
                        free_selection_rects.erase (i);
-                       return (*i);
+                       return ret;
                }
        }
 
@@ -786,7 +828,7 @@ TimeAxisView::remove_child (TimeAxisView* child)
 }
 
 void
-TimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& result)
+TimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& result)
 {
        return;
 }
@@ -872,7 +914,7 @@ TimeAxisView::reset_height()
        set_height_pixels (height);
 
        for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
-               (*i)->set_height ((TrackHeight)(*i)->height);
+               (*i)->set_height_pixels ((TrackHeight)(*i)->height);
        }
 }
        
@@ -903,18 +945,20 @@ void
 TimeAxisView::compute_controls_size_info ()
 {
        Gtk::Window window (Gtk::WINDOW_TOPLEVEL);
-       Gtk::Table two_row_table (2, 9);
-       Gtk::Table one_row_table (1, 9);
+       Gtk::Table two_row_table (2, 8);
+       Gtk::Table one_row_table (1, 8);
        Button* buttons[5];
+       const int border_width = 2;
+       const int extra_height = (2 * border_width) + 2; // 2 pixels for the controls frame
 
        window.add (one_row_table);
 
-       one_row_table.set_border_width (2);
+       one_row_table.set_border_width (border_width);
        one_row_table.set_row_spacings (0);
        one_row_table.set_col_spacings (0);
        one_row_table.set_homogeneous (true);
 
-       two_row_table.set_border_width (2);
+       two_row_table.set_border_width (border_width);
        two_row_table.set_row_spacings (0);
        two_row_table.set_col_spacings (0);
        two_row_table.set_homogeneous (true);
@@ -924,31 +968,30 @@ TimeAxisView::compute_controls_size_info ()
                buttons[i]->set_name ("TrackMuteButton");
        }
 
-       Gtk::Requisition req;
-
        one_row_table.attach (*buttons[0], 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
        
        one_row_table.show_all ();
-       one_row_table.size_request (req);
+       Gtk::Requisition req(one_row_table.size_request ());
+
 
        // height required to show 1 row of buttons
 
-       hSmaller = req.height + 3;
+       hSmaller = req.height + extra_height;
 
        window.remove ();
        window.add (two_row_table);
 
-       two_row_table.attach (*buttons[1], 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
-       two_row_table.attach (*buttons[2], 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
-       two_row_table.attach (*buttons[3], 8, 9, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
-       two_row_table.attach (*buttons[4], 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+       two_row_table.attach (*buttons[1], 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+       two_row_table.attach (*buttons[2], 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+       two_row_table.attach (*buttons[3], 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+       two_row_table.attach (*buttons[4], 8, 9, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
 
        two_row_table.show_all ();
-       two_row_table.size_request (req);
+       req = two_row_table.size_request ();
 
-       // height required to show all normal buttons
+       // height required to show all normal buttons 
 
-       hNormal = req.height + 3;
+       hNormal = req.height + extra_height;
 
        // these heights are all just larger than normal. no more 
        // elements are visible (yet).
@@ -1001,3 +1044,46 @@ TimeAxisView::hide_name_entry ()
                name_packing = NamePackingBits (name_packing & ~NameEntryPacked);
        }
 }
+
+void
+TimeAxisView::color_handler (ColorID id, uint32_t val)
+{
+       switch (id) {
+       case cSelectionRectFill:
+               break;
+       case cSelectionRectOutline:
+               break;
+       case cSelectionStartFill:
+               break;
+       case cSelectionStartOutline:
+               break;
+       case cSelectionEndFill:
+               break;
+       case cSelectionEndOutline:
+               break;
+       default:
+               break;
+       }
+}
+
+TimeAxisView*
+TimeAxisView::covers_y_position (double y)
+{
+       if (hidden()) {
+               return 0;
+       }
+
+       if (y_position <= y && y < (y_position + height)) {
+               return this;
+       }
+
+       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+               TimeAxisView* tv;
+
+               if ((tv = (*i)->covers_y_position (y)) != 0) {
+                       return tv;
+               }
+       }
+
+       return 0;
+}