fix ordering of cut/copied regions when pasting; ctrl-click now does the right thing...
[ardour.git] / gtk2_ardour / region_selection.cc
1 /*
2     Copyright (C) 2006 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <algorithm>
20
21 #include <ardour/region.h>
22
23 #include "region_view.h"
24 #include "region_selection.h"
25 #include "time_axis_view.h"
26
27 using namespace ARDOUR;
28 using namespace PBD;
29 using namespace sigc;
30
31
32 RegionSelection::RegionSelection ()
33 {
34         _current_start = 0;
35         _current_end = 0;
36 }
37
38 RegionSelection::RegionSelection (const RegionSelection& other)
39 {
40         for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
41                 add (*i);
42         }
43         _current_start = other._current_start;
44         _current_end = other._current_end;
45 }
46
47
48
49 RegionSelection&
50 RegionSelection::operator= (const RegionSelection& other)
51 {
52         if (this != &other) {
53
54                 clear_all();
55                 
56                 for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
57                         add (*i);
58                 }
59
60                 _current_start = other._current_start;
61                 _current_end = other._current_end;
62         }
63
64         return *this;
65 }
66
67 void
68 RegionSelection::clear_all()
69 {
70         clear();
71         _bylayer.clear();
72         _current_start = 0;
73         _current_end = 0;
74 }
75
76 bool RegionSelection::contains (RegionView* rv)
77 {
78         return find (begin(), end(), rv) != end();
79 }
80
81 void
82 RegionSelection::add (RegionView* rv)
83 {
84         if (contains (rv)) {
85                 /* we already have it */
86                 return;
87         }
88
89         rv->RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
90
91         if (rv->region()->first_frame() < _current_start || empty()) {
92                 _current_start = rv->region()->first_frame();
93         }
94         
95         if (rv->region()->last_frame() > _current_end || empty()) {
96                 _current_end = rv->region()->last_frame();
97         }
98         
99         push_back (rv);
100
101         // add to layer sorted list
102
103         add_to_layer (rv);
104 }
105
106 void
107 RegionSelection::remove_it (RegionView *rv)
108 {
109         remove (rv);
110 }
111
112 bool
113 RegionSelection::remove (RegionView* rv)
114 {
115         RegionSelection::iterator i;
116
117         if ((i = find (begin(), end(), rv)) != end()) {
118
119                 erase (i);
120
121                 // remove from layer sorted list
122                 _bylayer.remove (rv);
123                 
124                 if (empty()) {
125
126                         _current_start = 0;
127                         _current_end = 0;
128
129                 } else {
130                         
131                         boost::shared_ptr<Region> region ((*i)->region());
132
133                         if (region->first_frame() == _current_start) {
134                                 
135                                 /* reset current start */
136                                 
137                                 nframes_t ref = max_frames;
138                                 
139                                 for (i = begin (); i != end(); ++i) {
140                                         if (region->first_frame() < ref) {
141                                                 ref = region->first_frame();
142                                         }
143                                 }
144                                 
145                                 _current_start = ref;
146                                 
147                         }
148                         
149                         if (region->last_frame() == _current_end) {
150
151                                 /* reset current end */
152                                 
153                                 nframes_t ref = 0;
154                                 
155                                 for (i = begin (); i != end(); ++i) {
156                                         if (region->first_frame() > ref) {
157                                                 ref = region->first_frame();
158                                         }
159                                 }
160                                 
161                                 _current_end = ref;
162                         }
163                 }
164
165                 return true;
166         }
167
168         return false;
169 }
170
171 void
172 RegionSelection::add_to_layer (RegionView * rv)
173 {
174         // insert it into layer sorted position
175
176         list<RegionView*>::iterator i;
177
178         for (i = _bylayer.begin(); i != _bylayer.end(); ++i)
179         {
180                 if (rv->region()->layer() < (*i)->region()->layer()) {
181                         _bylayer.insert(i, rv);
182                         return;
183                 }
184         }
185
186         // insert at end if we get here
187         _bylayer.insert(i, rv);
188 }
189
190 struct RegionSortByTime {
191     bool operator() (const RegionView* a, const RegionView* b) const {
192             return a->region()->position() < b->region()->position();
193     }
194 };
195
196
197 void
198 RegionSelection::by_position (list<RegionView*>& foo) const
199 {
200         list<RegionView*>::const_iterator i;
201         RegionSortByTime sorter;
202
203         for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
204                 foo.push_back (*i);
205         }
206
207         foo.sort (sorter);
208         return;
209 }
210
211 struct RegionSortByTrack {
212     bool operator() (const RegionView* a, const RegionView* b) const {
213             
214             /* really, track and position */
215
216             if (a->get_trackview().order == b->get_trackview().order) {
217                     return a->region()->position() < b->region()->position();
218             } else {
219                     return a->get_trackview().order < b->get_trackview().order;
220             }
221     }
222 };
223         
224 void
225 RegionSelection::by_track (list<RegionView*>& foo) const
226 {
227         list<RegionView*>::const_iterator i;
228         RegionSortByTrack sorter;
229
230         for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
231                 foo.push_back (*i);
232         }
233
234         foo.sort (sorter);
235         return;
236 }
237
238 void
239 RegionSelection::sort_by_position_and_track ()
240 {
241         RegionSortByTrack sorter;
242         sort (sorter);
243 }