mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-03 12:19:33 +01:00
[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:
parent
5d4d42b1fa
commit
930b87d8e1
10 changed files with 102 additions and 96 deletions
|
|
@ -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*);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 &);
|
||||
|
|
|
|||
|
|
@ -140,7 +140,8 @@ void
|
|||
Selection::clear_time ()
|
||||
{
|
||||
time.clear();
|
||||
|
||||
time.tracks_in_range.clear();
|
||||
|
||||
TimeChanged ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue