[Summary] Reworked range selection according to PRD

[Details] Eliminated range selection relation to track header selection
Made range drag with region cut/copy reversible
Fixed bugs

Still to do with range selection: shift+click support, Enable Group Edit operation
This commit is contained in:
GZharun 2014-12-04 14:59:26 +02:00
parent 5d4d42b1fa
commit 930b87d8e1
10 changed files with 102 additions and 96 deletions

View file

@ -1200,7 +1200,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void region_from_selection ();
void create_region_from_selection (std::vector<boost::shared_ptr<ARDOUR::Region> >&);
void cut_copy_region_from_selection (RegionSelection& new_regions, RouteTimeAxisView* rtv, bool follow_track_selection = false, bool copy = false);
void cut_copy_region_from_selection (RegionSelection& new_regions, bool copy = false);
void play_from_start ();
void play_from_edit_point ();
@ -1412,7 +1412,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void start_create_region_grab (ArdourCanvas::Item*, GdkEvent*);
void add_region_copy_drag (ArdourCanvas::Item*, GdkEvent*, RegionView*);
void add_region_brush_drag (ArdourCanvas::Item*, GdkEvent*, RegionView*);
void start_selection_grab (ArdourCanvas::Item*, RouteTimeAxisView*, GdkEvent*, bool copy = false);
void start_selection_grab (ArdourCanvas::Item*, GdkEvent*, bool copy = false);
void region_view_item_click (AudioRegionView&, GdkEventButton*);

View file

@ -4240,24 +4240,24 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
if (_add) {
/* adding to the selection */
_editor->set_selected_track_as_side_effect (Selection::Add);
_editor->clicked_selection = _editor->selection->add (start, end);
// GZ: Waves TracksLive gives no possibility (by PRD) to add multiple time ranges
// but there used to be such possibility.
// kept the flag "_add" in case if we need it again
_add = false;
} else {
/* new selection */
if (_editor->clicked_axisview && !_editor->selection->selected (_editor->clicked_axisview)) {
_editor->set_selected_track_as_side_effect (Selection::Set);
}
_editor->clicked_selection = _editor->selection->set (start, end);
}
/* new selection range selection */
_editor->selection->time.tracks_in_range.clear();
if (_editor->clicked_axisview ) {
_editor->selection->time.tracks_in_range.push_back (_editor->clicked_axisview );
}
_editor->clicked_selection = _editor->selection->set (start, end);
}
/* select all tracks within the rectangle that we've marked out so far */
TrackViewList new_selection;
TrackViewList& tracks_in_range = _editor->selection->time.tracks_in_range;
TrackViewList& all_tracks (_editor->track_views);
ArdourCanvas::Coord const top = grab_y();
@ -4267,37 +4267,35 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
//first, find the tracks that are covered in the y range selection
for (TrackViewList::const_iterator i = all_tracks.begin(); i != all_tracks.end(); ++i) {
if ((*i)->covered_by_y_range (top, bottom)) {
new_selection.push_back (*i);
if ((*i)->covered_by_y_range (top, bottom) && !tracks_in_range.contains(*i) ) {
tracks_in_range.push_back (*i);
}
}
// GZ: Waves TrackLive does not support custom groups now,
// but we may need this in future versions
#if 0
//now find any tracks that are GROUPED with the tracks we selected
TrackViewList grouped_add = new_selection;
for (TrackViewList::const_iterator i = new_selection.begin(); i != new_selection.end(); ++i) {
TrackViewList grouped_tracks_to_add;
for (TrackViewList::const_iterator i = tracks_in_range.begin(); i != tracks_in_range.end(); ++i) {
RouteTimeAxisView *n = dynamic_cast<RouteTimeAxisView *>(*i);
if ( n && n->route()->route_group() && n->route()->route_group()->is_active() && n->route()->route_group()->enabled_property (ARDOUR::Properties::select.property_id) ) {
for (TrackViewList::const_iterator j = all_tracks.begin(); j != all_tracks.end(); ++j) {
RouteTimeAxisView *check = dynamic_cast<RouteTimeAxisView *>(*j);
if ( check && (n != check) && (check->route()->route_group() == n->route()->route_group()) )
grouped_add.push_back (*j);
if ( n && n->route()->route_group() && n->route()->route_group()->is_active() ) {
boost::shared_ptr<RouteList> grouped_routes;
grouped_routes = n->route()->route_group()->route_list();
RouteList::iterator j = grouped_routes->begin();
for (; j != grouped_routes->end(); ++j) {
RouteTimeAxisView *check = _editor->axis_view_from_route(*j);
if ( check && (n != check) )
grouped_tracks_to_add.push_back(check);
}
}
}
//now compare our list with the current selection, and add or remove as necessary
//( NOTE: most mouse moves don't change the selection so we can't just SET it for every mouse move; it gets clunky )
TrackViewList tracks_to_add;
TrackViewList tracks_to_remove;
for (TrackViewList::const_iterator i = grouped_add.begin(); i != grouped_add.end(); ++i)
if ( !_editor->selection->tracks.contains ( *i ) )
tracks_to_add.push_back ( *i );
for (TrackViewList::const_iterator i = _editor->selection->tracks.begin(); i != _editor->selection->tracks.end(); ++i)
if ( !grouped_add.contains ( *i ) )
tracks_to_remove.push_back ( *i );
_editor->selection->add(tracks_to_add);
_editor->selection->remove(tracks_to_remove);
tracks_in_range.add(grouped_tracks_to_add);
#endif
}
}
break;
@ -4412,10 +4410,6 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
}
}
}
if (_editor->clicked_axisview && !_editor->selection->selected (_editor->clicked_axisview)) {
_editor->selection->set (_editor->clicked_axisview);
}
if (s && s->get_play_range () && s->transport_rolling()) {
s->request_stop (false, false);

View file

@ -778,8 +778,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
separate-drag the selection. Well actually, Igor@Waves
decided this, so here it is.
*/
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
start_selection_grab (item, rtv, event, copy);
start_selection_grab (item, event, copy);
return true;
}
}
@ -900,8 +899,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
separate-drag the selection. Well actually, Igor@Waves
decided this, so here it is.
*/
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
start_selection_grab (item, rtv, event, copy);
start_selection_grab (item, event, copy);
return true;
}
}
@ -2458,13 +2456,13 @@ Editor::add_region_brush_drag (ArdourCanvas::Item* item, GdkEvent*, RegionView*
* the section of the clicked region that lies within the time range.
*/
void
Editor::start_selection_grab (ArdourCanvas::Item* item, RouteTimeAxisView* rtv, GdkEvent* event, bool copy/*=false*/)
Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event, bool copy/*=false*/)
{
/* lets try to create new Region for the selection */
begin_reversible_command (_("new region for selection drag"));
RegionSelection new_regions;
cut_copy_region_from_selection (new_regions, rtv, true, copy);
cut_copy_region_from_selection (new_regions, copy);
commit_reversible_command ();

View file

@ -2714,24 +2714,19 @@ Editor::create_region_from_selection (vector<boost::shared_ptr<Region> >& new_re
}
void
Editor::cut_copy_region_from_selection (RegionSelection& new_regions, RouteTimeAxisView* rtv, bool follow_track_selection/*=false*/, bool copy /*=false*/)
Editor::cut_copy_region_from_selection (RegionSelection& new_regions, bool copy /*=false*/)
{
new_regions.clear();
if (selection->time.empty() || selection->tracks.empty() ) {
if (selection->time.empty() || selection->time.tracks_in_range.empty() ) {
return;
}
TrackViewList ts;
if (follow_track_selection) {
ts = selection->tracks.filter_to_unique_playlists ();
sort_track_selection (ts);
} else {
if (rtv) {
ts.push_back(rtv);
}
}
// get track views associated with time selection
TrackViewList ts = selection->time.tracks_in_range.filter_to_unique_playlists ();
sort_track_selection (ts);
// latest_regionviews contains latest processed regions
latest_regionviews.clear();
for (TrackSelection::iterator i = ts.begin(); i != ts.end(); ++i) {
@ -2741,11 +2736,15 @@ Editor::cut_copy_region_from_selection (RegionSelection& new_regions, RouteTimeA
continue;
}
// form selection object to get new cut/copied regions
Selection new_items(this);
route_view->cut_copy_range(*selection, copy, new_items);
route_view->cut_copy_region_from_range(*selection, copy, new_items);
// connect this collect_new_region_view method to RegionViewAdded signal
// to collect newly pasted regions in latest_regionviews container
sigc::connection c = route_view->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view));
// paste cut/copied regions back
AudioRange range = selection->time[clicked_selection];
route_view->paste(range.start, 1, new_items, 0);
@ -4373,7 +4372,7 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
void
Editor::cut_copy_ranges (CutCopyOp op)
{
TrackViewList ts = selection->tracks.filter_to_unique_playlists ();
TrackViewList ts = selection->time.tracks_in_range.filter_to_unique_playlists ();
/* Sort the track selection now, so that it if is used, the playlists
selected by the calls below to cut_copy_clear are in the order that

View file

@ -1005,13 +1005,6 @@ Editor::track_selection_changed ()
(*j)->set_selected (std::find (selection->tracks.begin(), selection->tracks.end(), j->get()) != selection->tracks.end());
}
if (yn) {
(*i)->reshow_selection (selection->time);
} else {
(*i)->hide_selection ();
}
if (yn) {
RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*i);
if (rtav) {
@ -1060,9 +1053,13 @@ Editor::time_selection_changed ()
(*i)->hide_selection ();
}
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
(*i)->show_selection (selection->time);
}
{ // Now show time range selection on all affected tracks
TrackViewList& track_to_process = selection->time.tracks_in_range;
TrackViewList::iterator i = track_to_process.begin();
for (; i != track_to_process.end(); ++i) {
(*i)->show_selection (selection->time);
}
}
if (selection->time.empty()) {
ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);

View file

@ -1454,12 +1454,13 @@ RouteTimeAxisView::fade_range (TimeSelection& selection)
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (playlist));
}
void
RouteTimeAxisView::cut_copy_range (Selection& selection, bool copy, Selection& new_items)
RouteTimeAxisView::cut_copy_region_from_range (Selection& selection, bool copy, Selection& new_items)
{
new_items.clear();
@ -1498,11 +1499,18 @@ RouteTimeAxisView::cut_copy_range (Selection& selection, bool copy, Selection& n
new_items.set (what_we_got);
if (Config->get_edit_mode() == Ripple)
playlist->ripple(time.start(), -time.length(), NULL);
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (playlist));
}
}
}
void
RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
{
@ -1526,8 +1534,8 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
}
}
playlist->clear_changes ();
playlist->clear_owned_changes ();
playlist->clear_changes ();
playlist->clear_owned_changes ();
switch (op) {
case Delete:
@ -1536,11 +1544,11 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
playlist->ripple(time.start(), -time.length(), NULL);
// no need to exclude any regions from rippling here
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (playlist));
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (playlist));
}
break;
@ -1551,11 +1559,11 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
playlist->ripple(time.start(), -time.length(), NULL);
// no need to exclude any regions from rippling here
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (playlist));
_session->add_command (new StatefulDiffCommand (playlist));
}
break;
case Copy:
@ -1570,10 +1578,12 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
playlist->ripple(time.start(), -time.length(), NULL);
// no need to exclude any regions from rippling here
vector<Command*> cmds;
playlist->rdiff (cmds);
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (playlist));
_session->add_command (new StatefulDiffCommand (playlist));
what_we_got->release ();
}
break;

View file

@ -111,7 +111,7 @@ public:
void uncombine_region (RegionView*);
void toggle_automation_track (const Evoral::Parameter& param);
void fade_range (TimeSelection&);
void cut_copy_range (Selection& selection, bool copy, Selection& new_items);
void cut_copy_region_from_range (Selection& selection, bool copy, Selection& new_items);
/* The editor calls these when mapping an operation across multiple tracks */
void use_new_playlist (bool prompt, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);

View file

@ -140,7 +140,8 @@ void
Selection::clear_time ()
{
time.clear();
time.tracks_in_range.clear();
TimeChanged ();
}

View file

@ -709,9 +709,9 @@ TimeAxisView::popup_display_menu (guint32 when)
void
TimeAxisView::set_selected (bool yn)
{
if (can_edit_name() && name_entry.get_visible()) {
end_name_edit (RESPONSE_CANCEL);
}
if (can_edit_name() && name_entry.get_visible()) {
end_name_edit (RESPONSE_CANCEL);
}
if (yn == _selected) {
return;
@ -721,9 +721,9 @@ TimeAxisView::set_selected (bool yn)
if (_selected) {
controls_event_box.set_state (Gtk::STATE_ACTIVE);
} else {
controls_event_box.set_state (Gtk::STATE_NORMAL);
hide_selection ();
/* children will be set for the yn=true case. but when deselecting
the editor only has a list of top-level trackviews, so we
@ -775,6 +775,10 @@ TimeAxisView::hide_timestretch ()
void
TimeAxisView::show_selection (TimeSelection& ts)
{
if (!ts.tracks_in_range.contains(this) ) {
return;
}
double x1;
double x2;
double y2;

View file

@ -22,6 +22,7 @@
#include <list>
#include "ardour/types.h"
#include "track_view_list.h"
namespace ARDOUR {
class RouteGroup;
@ -32,11 +33,13 @@ class TimeSelection : public std::list<ARDOUR::AudioRange>
public:
ARDOUR::AudioRange& operator[](uint32_t);
ARDOUR::framepos_t start();
ARDOUR::framepos_t end_frame();
ARDOUR::framepos_t length();
ARDOUR::framepos_t start();
ARDOUR::framepos_t end_frame();
ARDOUR::framepos_t length();
bool consolidate ();
TrackViewList tracks_in_range;
};