7ac7763773a6848aa90d871d4e0df8d09de27ab0
[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         RegionView::RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
35
36         _current_start = 0;
37         _current_end = 0;
38 }
39
40 RegionSelection::RegionSelection (const RegionSelection& other)
41 {
42         RegionView::RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
43
44         for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
45                 add (*i);
46         }
47         _current_start = other._current_start;
48         _current_end = other._current_end;
49 }
50
51 RegionSelection&
52 RegionSelection::operator= (const RegionSelection& other)
53 {
54         if (this != &other) {
55
56                 clear_all();
57                 
58                 for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
59                         add (*i);
60                 }
61
62                 _current_start = other._current_start;
63                 _current_end = other._current_end;
64         }
65
66         return *this;
67 }
68
69 void
70 RegionSelection::clear_all()
71 {
72         clear();
73         _bylayer.clear();
74         _current_start = 0;
75         _current_end = 0;
76 }
77
78 bool RegionSelection::contains (RegionView* rv) const
79 {
80         return find (begin(), end(), rv) != end();
81 }
82
83 bool
84 RegionSelection::add (RegionView* rv)
85 {
86         if (contains (rv)) {
87                 /* we already have it */
88                 return false;
89         }
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         return true;
106 }
107
108 void
109 RegionSelection::remove_it (RegionView *rv)
110 {
111         remove (rv);
112 }
113
114 bool
115 RegionSelection::remove (RegionView* rv)
116 {
117         RegionSelection::iterator i;
118
119         if ((i = find (begin(), end(), rv)) != end()) {
120
121                 erase (i);
122
123                 // remove from layer sorted list
124                 _bylayer.remove (rv);
125                 
126                 if (empty()) {
127
128                         _current_start = 0;
129                         _current_end = 0;
130
131                 } else {
132                         
133                         boost::shared_ptr<Region> region ((*i)->region());
134
135                         if (region->first_frame() == _current_start) {
136                                 
137                                 /* reset current start */
138                                 
139                                 nframes_t ref = max_frames;
140                                 
141                                 for (i = begin (); i != end(); ++i) {
142                                         if (region->first_frame() < ref) {
143                                                 ref = region->first_frame();
144                                         }
145                                 }
146                                 
147                                 _current_start = ref;
148                                 
149                         }
150                         
151                         if (region->last_frame() == _current_end) {
152
153                                 /* reset current end */
154                                 
155                                 nframes_t ref = 0;
156                                 
157                                 for (i = begin (); i != end(); ++i) {
158                                         if (region->first_frame() > ref) {
159                                                 ref = region->first_frame();
160                                         }
161                                 }
162                                 
163                                 _current_end = ref;
164                         }
165                 }
166
167                 return true;
168         }
169
170         return false;
171 }
172
173 void
174 RegionSelection::add_to_layer (RegionView * rv)
175 {
176         // insert it into layer sorted position
177
178         list<RegionView*>::iterator i;
179
180         for (i = _bylayer.begin(); i != _bylayer.end(); ++i)
181         {
182                 if (rv->region()->layer() < (*i)->region()->layer()) {
183                         _bylayer.insert(i, rv);
184                         return;
185                 }
186         }
187
188         // insert at end if we get here
189         _bylayer.insert(i, rv);
190 }
191
192 struct RegionSortByTime {
193     bool operator() (const RegionView* a, const RegionView* b) const {
194             return a->region()->position() < b->region()->position();
195     }
196 };
197
198
199 void
200 RegionSelection::by_position (list<RegionView*>& foo) const
201 {
202         list<RegionView*>::const_iterator i;
203         RegionSortByTime sorter;
204
205         for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
206                 foo.push_back (*i);
207         }
208
209         foo.sort (sorter);
210         return;
211 }
212
213 struct RegionSortByTrack {
214     bool operator() (const RegionView* a, const RegionView* b) const {
215             
216             /* really, track and position */
217
218             if (a->get_trackview().order == b->get_trackview().order) {
219                     return a->region()->position() < b->region()->position();
220             } else {
221                     return a->get_trackview().order < b->get_trackview().order;
222             }
223     }
224 };
225         
226 void
227 RegionSelection::by_track (list<RegionView*>& foo) const
228 {
229         list<RegionView*>::const_iterator i;
230         RegionSortByTrack sorter;
231
232         for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
233                 foo.push_back (*i);
234         }
235
236         foo.sort (sorter);
237         return;
238 }
239
240 void
241 RegionSelection::sort_by_position_and_track ()
242 {
243         RegionSortByTrack sorter;
244         sort (sorter);
245 }
246
247 bool
248 RegionSelection::involves (const TimeAxisView& tv) const
249 {
250         for (RegionSelection::const_iterator i = begin(); i != end(); ++i) {
251                 if (&(*i)->get_trackview() == &tv) {
252                         return true;
253                 }
254         }
255         return false;
256 }
257