(1) use select next/previous row functions for tab/shift-tab navigation in region...
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 28 Sep 2010 17:27:58 +0000 (17:27 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 28 Sep 2010 17:27:58 +0000 (17:27 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@7850 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_regions.cc
gtk2_ardour/editor_regions.h
gtk2_ardour/editor_selection.cc

index aad0f7b11a81d8e5d8a0b691247f2d7ab7a0cefd..ce174630279b19d5fdf34c21bf0f38b9217aaf65 100644 (file)
@@ -306,7 +306,7 @@ Editor::Editor ()
        , _pending_initial_locate (false)
        , _last_cut_copy_source_track (0)
 
-       , _block_region_list_update_if_empty (false)
+       , _region_selection_change_updates_region_list (true)
 {
        constructed = false;
 
index f99ab00189a4417119a1b88e8f1f656e49038871..c1573b99a5ef603df45a520fbd4b533ac19a72a7 100644 (file)
@@ -2060,10 +2060,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        */
        TimeAxisView* _last_cut_copy_source_track;
 
-       /** true if the update of the region list's selection from the current Selection
-           should be blocked if the Selection is empty.  See EditorRegions::selection_changed.
+       /** true if a change in Selection->regions should change the selection in the region list.
+           See EditorRegions::selection_changed.
        */
-       bool _block_region_list_update_if_empty;
+       bool _region_selection_change_updates_region_list;
 
        void setup_fade_images ();
        std::map<ARDOUR::FadeShape, Gtk::Image*> _fade_in_images;
index ed27ab76401a549313ef9694ef7b546c8cff585e..426ee2b544e74f4fec00660be27232e5d696b1bd 100644 (file)
@@ -34,6 +34,8 @@
 #include "ardour/silentfilesource.h"
 #include "ardour/profile.h"
 
+#include "gtkmm2ext/treeutils.h"
+
 #include "editor.h"
 #include "editing.h"
 #include "keyboard.h"
@@ -78,10 +80,12 @@ EditorRegions::EditorRegions (Editor* e)
        _model->set_sort_column (0, SORT_ASCENDING);
 
        _display.set_model (_model);
+
        _display.append_column (_("Regions"), _columns.name);
        _display.append_column (_("Position"), _columns.position);
        _display.append_column (_("End"), _columns.end);
        _display.append_column (_("Length"), _columns.length);
+       _display.append_column (_("Start"), _columns.start);
        _display.append_column (_("Sync"), _columns.sync);
        _display.append_column (_("Fade In"), _columns.fadein);
        _display.append_column (_("Fade Out"), _columns.fadeout);
@@ -94,6 +98,9 @@ EditorRegions::EditorRegions (Editor* e)
        _display.set_headers_visible (true);
        //_display.set_grid_lines (TREE_VIEW_GRID_LINES_BOTH);
 
+        /* show path as the row tooltip */
+        _display.set_tooltip_column (15); /* path */
+
        CellRendererText* region_name_cell = dynamic_cast<CellRendererText*>(_display.get_column_cell_renderer (0));
        region_name_cell->property_editable() = true;
        region_name_cell->signal_edited().connect (sigc::mem_fun (*this, &EditorRegions::name_edit));
@@ -105,28 +112,28 @@ EditorRegions::EditorRegions (Editor* e)
        tv_col->add_attribute(renderer->property_text(), _columns.name);
        tv_col->add_attribute(renderer->property_foreground_gdk(), _columns.color_);
 
-       CellRendererToggle* locked_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (7));
+       CellRendererToggle* locked_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (8));
        locked_cell->property_activatable() = true;
        locked_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::locked_changed));
-       TreeViewColumn* locked_col = _display.get_column (7);
+       TreeViewColumn* locked_col = _display.get_column (8);
        locked_col->add_attribute (locked_cell->property_visible(), _columns.property_toggles_visible);
 
-       CellRendererToggle* glued_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (8));
+       CellRendererToggle* glued_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (9));
        glued_cell->property_activatable() = true;
        glued_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::glued_changed));
-       TreeViewColumn* glued_col = _display.get_column (8);
+       TreeViewColumn* glued_col = _display.get_column (9);
        glued_col->add_attribute (glued_cell->property_visible(), _columns.property_toggles_visible);
 
-       CellRendererToggle* muted_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (9));
+       CellRendererToggle* muted_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (10));
        muted_cell->property_activatable() = true;
        muted_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::muted_changed));
-       TreeViewColumn* muted_col = _display.get_column (9);
+       TreeViewColumn* muted_col = _display.get_column (10);
        muted_col->add_attribute (muted_cell->property_visible(), _columns.property_toggles_visible);
 
-       CellRendererToggle* opaque_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (10));
+       CellRendererToggle* opaque_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (11));
        opaque_cell->property_activatable() = true;
        opaque_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::opaque_changed));
-       TreeViewColumn* opaque_col = _display.get_column (10);
+       TreeViewColumn* opaque_col = _display.get_column (11);
        opaque_col->add_attribute (opaque_cell->property_visible(), _columns.property_toggles_visible);
        
        _display.get_selection()->set_mode (SELECTION_MULTIPLE);
@@ -146,7 +153,7 @@ EditorRegions::EditorRegions (Editor* e)
        _scroller.add (_display);
        _scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC);
 
-       _display.signal_key_press_event().connect (sigc::mem_fun(*this, &EditorRegions::key_press));
+       _display.signal_key_press_event().connect (sigc::mem_fun(*this, &EditorRegions::key_press), false);
        _display.signal_button_press_event().connect (sigc::mem_fun(*this, &EditorRegions::button_press), false);
        _change_connection = _display.get_selection()->signal_changed().connect (sigc::mem_fun(*this, &EditorRegions::selection_changed));
        // _display.signal_popup_menu().connect (sigc::bind (sigc::mem_fun (*this, &Editor::show__display_context_menu), 1, 0));
@@ -209,7 +216,6 @@ EditorRegions::add_region (boost::shared_ptr<Region> region)
                                parent = *iter;
                        }
                }
-
                row = *(_model->append (parent.children()));
 
        } else if (region->whole_file()) {
@@ -274,11 +280,15 @@ EditorRegions::add_region (boost::shared_ptr<Region> region)
                row[_columns.property_toggles_visible] = false;
 
                if (missing_source) {
-                       row[_columns.path] = _("(MISSING) ") + region->source()->name();
+                        row[_columns.path] = _("(MISSING) ") + region->source()->name();
 
                } else {
-                       row[_columns.path] = region->source()->name();
-
+                        boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource>(region->source());
+                        if (fs) {
+                                row[_columns.path] = fs->path();
+                        } else {
+                                row[_columns.path] = region->source()->name();
+                        }
                }
 
                if (region->automatic()) {
@@ -294,29 +304,30 @@ EditorRegions::add_region (boost::shared_ptr<Region> region)
                bool found_parent = false;
 
                for (i = rows.begin(); i != rows.end(); ++i) {
-                       boost::shared_ptr<Region> rr = (*i)[_columns.region];
-                       boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion>(rr);
+                       boost::shared_ptr<Region> r = (*i)[_columns.region];
 
                        if (r && r->whole_file()) {
 
                                if (region->source_equivalent (r)) {
-                                       row = *(_model->append ((*i).children()));
                                        found_parent = true;
-                                       break;
                                }
                        }
-
+                        
                        TreeModel::iterator ii;
                        TreeModel::Children subrows = (*i).children();
 
                        for (ii = subrows.begin(); ii != subrows.end(); ++ii) {
-                               boost::shared_ptr<Region> rrr = (*ii)[_columns.region];
+                               boost::shared_ptr<Region> rr = (*ii)[_columns.region];
 
-                               if (region->region_list_equivalent (rrr)) {
+                               if (region->region_list_equivalent (rr)) {
                                        return;
-
                                }
                        }
+
+                        if (found_parent) {
+                                row = *(_model->append ((*i).children()));
+                                break;
+                        }
                }
 
                if (!found_parent) {
@@ -339,6 +350,7 @@ EditorRegions::region_changed (boost::shared_ptr<Region> r, const PropertyChange
         our_interests.add (ARDOUR::Properties::name);
         our_interests.add (ARDOUR::Properties::position);
         our_interests.add (ARDOUR::Properties::length);
+        our_interests.add (ARDOUR::Properties::start);
         our_interests.add (ARDOUR::Properties::locked);
         our_interests.add (ARDOUR::Properties::position_lock_style);
         our_interests.add (ARDOUR::Properties::muted);
@@ -401,6 +413,10 @@ EditorRegions::region_changed (boost::shared_ptr<Region> r, const PropertyChange
                                         populate_row_end (r, *j, used);
                                         populate_row_length (r, *j);
                                 }
+                                if (what_changed.contains (ARDOUR::Properties::start)) {
+                                        populate_row_start (r, *j, used);
+                                        populate_row_length (r, *j);
+                                }
                                 if (what_changed.contains (ARDOUR::Properties::locked)) {
                                         populate_row_locked (r, *j, used);
                                 }
@@ -439,12 +455,7 @@ EditorRegions::selection_changed ()
                return;
        }
 
-       /* We may have selected a region which is not displayed in the Editor.  If this happens, the
-          result will be no selected regions in the editor's Selection.  Without the following line,
-          this `no-selection' will be mapped back to our list, meaning that the selection will
-          appear not to take.
-       */
-       _editor->_block_region_list_update_if_empty = true;
+       _editor->_region_selection_change_updates_region_list = false;
 
        if (_display.get_selection()->count_selected_rows() > 0) {
 
@@ -459,6 +470,9 @@ EditorRegions::selection_changed ()
                                boost::shared_ptr<Region> region = (*iter)[_columns.region];
 
                                 // they could have clicked on a row that is just a placeholder, like "Hidden"
+                                // although that is not allowed by our selection filter. check it anyway
+                                // since we need a region ptr.
+
                                if (region) {
                                         
                                        if (region->automatic()) {
@@ -478,7 +492,7 @@ EditorRegions::selection_changed ()
                _editor->get_selection().clear_regions ();
        }
 
-       _editor->_block_region_list_update_if_empty = false;
+       _editor->_region_selection_change_updates_region_list = true;
 }
 
 void
@@ -739,6 +753,7 @@ EditorRegions::populate_row (boost::shared_ptr<Region> region, TreeModel::Row co
 
         populate_row_position (region, row, used);
         populate_row_end (region, row, used);
+        populate_row_start (region, row, used);
         populate_row_sync (region, row, used);
         populate_row_fade_in (region, row, used, audioregion);
         populate_row_fade_out (region, row, used, audioregion);
@@ -802,8 +817,10 @@ EditorRegions::populate_row_length (boost::shared_ptr<Region> region, TreeModel:
 void
 EditorRegions::populate_row_end (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used)
 {
-        if (used > 1) {
-                row[_columns.end] = _("Multiple");
+        if (region->whole_file()) {
+                row[_columns.end] = "";
+        } else if (used > 1) {
+                row[_columns.end] = _("Mult.");
         } else {
                 char buf[16];
                 format_position (region->last_frame(), buf, sizeof (buf));
@@ -811,11 +828,27 @@ EditorRegions::populate_row_end (boost::shared_ptr<Region> region, TreeModel::Ro
         }
 }
 
+void
+EditorRegions::populate_row_start (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used)
+{
+        if (region->whole_file()) {
+                row[_columns.start] = "";
+        } else if (used > 1) {
+                row[_columns.start] = _("Mult.");
+        } else {
+                char buf[16];
+                format_position (region->start(), buf, sizeof (buf));
+                row[_columns.start] = buf;
+        }
+}
+
 void
 EditorRegions::populate_row_position (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used)
 {
-        if (used > 1) {
-                row[_columns.position] = _("Multiple");
+        if (region->whole_file()) {
+                row[_columns.position] = "";
+        } else if (used > 1) {
+                row[_columns.position] = _("Mult.");
         } else {
                 char buf[16];
                 format_position (region->position(), buf, sizeof (buf));
@@ -826,8 +859,10 @@ EditorRegions::populate_row_position (boost::shared_ptr<Region> region, TreeMode
 void
 EditorRegions::populate_row_sync (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used)
 {
-        if (used > 1) {
-                row[_columns.sync] = _("Multiple");
+        if (region->whole_file()) {
+                row[_columns.sync] = "";
+        } else if (used > 1) {
+                row[_columns.sync] = _("Mult."); /* translators: a short phrase for "multiple" as in "many" */
         } else {
                if (region->sync_position() == region->position()) {
                        row[_columns.sync] = _("Start");
@@ -844,7 +879,7 @@ EditorRegions::populate_row_sync (boost::shared_ptr<Region> region, TreeModel::R
 void
 EditorRegions::populate_row_fade_in (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used, boost::shared_ptr<AudioRegion> audioregion)
 {
-        if (!audioregion) {
+        if (!audioregion || region->whole_file()) {
                        row[_columns.fadein] = "";
         } else {
                 if (used > 1) {
@@ -867,7 +902,7 @@ EditorRegions::populate_row_fade_in (boost::shared_ptr<Region> region, TreeModel
 void
 EditorRegions::populate_row_fade_out (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used, boost::shared_ptr<AudioRegion> audioregion)
 {
-        if (!audioregion) {
+        if (!audioregion || region->whole_file()) {
                 row[_columns.fadeout] = "";
         } else {
                 if (used > 1) {
@@ -888,7 +923,9 @@ EditorRegions::populate_row_fade_out (boost::shared_ptr<Region> region, TreeMode
 void
 EditorRegions::populate_row_locked (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used)
 {
-        if (used > 1) {
+        if (region->whole_file()) {
+                row[_columns.locked] = false;
+        } else if (used > 1) {
                 row[_columns.locked] = false;
         } else {
                row[_columns.locked] = region->locked();
@@ -898,7 +935,7 @@ EditorRegions::populate_row_locked (boost::shared_ptr<Region> region, TreeModel:
 void
 EditorRegions::populate_row_glued (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used)
 {
-        if (used > 1) {
+        if (region->whole_file() || used > 1) {
                 row[_columns.glued] = false;
         } else {
                if (region->position_lock_style() == MusicTime) {
@@ -912,7 +949,7 @@ EditorRegions::populate_row_glued (boost::shared_ptr<Region> region, TreeModel::
 void
 EditorRegions::populate_row_muted (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used)
 {
-        if (used > 1) {
+        if (region->whole_file() || used > 1) {
                 row[_columns.muted] = false;
         } else {
                row[_columns.muted] = region->muted();
@@ -922,7 +959,7 @@ EditorRegions::populate_row_muted (boost::shared_ptr<Region> region, TreeModel::
 void
 EditorRegions::populate_row_opaque (boost::shared_ptr<Region> region, TreeModel::Row const &row, uint32_t used)
 {
-        if (used > 1) {
+        if (region->whole_file() || used > 1) {
                 row[_columns.opaque] = false;
         } else {
                row[_columns.opaque] = region->opaque();
@@ -1012,12 +1049,31 @@ EditorRegions::show_context_menu (int button, int time)
 }
 
 bool
-EditorRegions::key_press (GdkEventKey* /*ev*/)
+EditorRegions::key_press (GdkEventKey* ev)
 {
+        TreeViewColumn *col;
+
+        switch (ev->keyval) {
+        case GDK_Tab:
+        case GDK_ISO_Left_Tab:
+                col = _display.get_column (0); // select&focus on name column
+
+                if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
+                        treeview_select_previous (_display, _model, col);
+                } else {
+                        treeview_select_next (_display, _model, col);
+                }
+
+                return true;
+                break;
+
+        default:
+                break;
+        }
+
        return false;
 }
 
-
 bool
 EditorRegions::button_press (GdkEventButton *ev)
 {
@@ -1214,10 +1270,15 @@ EditorRegions::drag_data_received (const RefPtr<Gdk::DragContext>& context,
 }
 
 bool
-EditorRegions::selection_filter (const RefPtr<TreeModel>& model, const TreeModel::Path& path, bool /*yn*/)
+EditorRegions::selection_filter (const RefPtr<TreeModel>& model, const TreeModel::Path& path, bool already_selected)
 {
        /* not possible to select rows that do not represent regions, like "Hidden" */
 
+        if (already_selected) {
+                /* deselecting anything is OK with us */
+                return true;
+        }
+
        TreeModel::iterator iter = model->get_iter (path);
 
        if (iter) {
index 8e41327c377da76ea9ac3705c72669b65e385399..ad0a871aecb10f52fdb7ea80beb01a9950befbad 100644 (file)
@@ -80,6 +80,7 @@ private:
                        add (position);
                        add (end);
                        add (length);
+                       add (start);
                        add (sync);
                        add (fadein);
                        add (fadeout);
@@ -98,6 +99,7 @@ private:
                Gtk::TreeModelColumn<std::string> position;
                Gtk::TreeModelColumn<std::string> end;
                Gtk::TreeModelColumn<std::string> length;
+               Gtk::TreeModelColumn<std::string> start;
                Gtk::TreeModelColumn<std::string> sync;
                Gtk::TreeModelColumn<std::string> fadein;
                Gtk::TreeModelColumn<std::string> fadeout;
@@ -143,6 +145,7 @@ private:
         void populate_row_used (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
         void populate_row_position (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
         void populate_row_end (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
+        void populate_row_start (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
         void populate_row_sync (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
         void populate_row_fade_in (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used, boost::shared_ptr<ARDOUR::AudioRegion>);
         void populate_row_fade_out (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used, boost::shared_ptr<ARDOUR::AudioRegion>);
@@ -186,6 +189,11 @@ private:
        bool ignore_region_list_selection_change;
        bool ignore_selected_region_change;
         bool expanded;
+
+        void select_one (Glib::RefPtr<Gtk::TreeSelection>, Glib::RefPtr<Gtk::TreeModel>, Gtk::TreeView&,
+                         Gtk::TreeIter, Gtk::TreePath, Gtk::TreeViewColumn*);
+        void select_next ();
+        void select_previous ();
 };
 
 #endif /* __gtk_ardour_editor_regions_h__ */
index bcd2aab6f095af25cade20bfe40575df4ed6cee2..4fc418b8b3d8023d7cb593e1d813d4144780b937 100644 (file)
@@ -957,7 +957,7 @@ Editor::region_selection_changed ()
        _regions->block_change_connection (true);
        editor_regions_selection_changed_connection.block(true);
 
-       if (!_block_region_list_update_if_empty || !selection->regions.empty()) {
+       if (_region_selection_change_updates_region_list) {
                _regions->unselect_all ();
        }
 
@@ -965,7 +965,9 @@ Editor::region_selection_changed ()
                (*i)->set_selected_regionviews (selection->regions);
        }
 
-       _regions->set_selected (selection->regions);
+        if (_region_selection_change_updates_region_list) {
+                _regions->set_selected (selection->regions);
+        }
 
        sensitize_the_right_region_actions (!selection->regions.empty());