Merged with trunk R861
[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
26 using namespace ARDOUR;
27 using namespace PBD;
28 using namespace sigc;
29
30
31 bool 
32 RegionComparator::operator() (const RegionView* a, const RegionView* b) const
33 {
34         if (a == b) {
35                 return false;
36         } else {
37                 return a < b;
38         }
39 }
40
41 RegionSelection::RegionSelection ()
42 {
43         _current_start = 0;
44         _current_end = 0;
45 }
46
47 RegionSelection::RegionSelection (const RegionSelection& other)
48 {
49
50         for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
51                 add (*i, false);
52         }
53         _current_start = other._current_start;
54         _current_end = other._current_end;
55 }
56
57
58
59 RegionSelection&
60 RegionSelection::operator= (const RegionSelection& other)
61 {
62         if (this != &other) {
63
64                 clear_all();
65                 
66                 for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
67                         add (*i, false);
68                 }
69
70                 _current_start = other._current_start;
71                 _current_end = other._current_end;
72         }
73
74         return *this;
75 }
76
77 void
78 RegionSelection::clear_all()
79 {
80         clear();
81         _bylayer.clear();
82 }
83
84 bool RegionSelection::contains (RegionView* rv)
85 {
86         if (this->find (rv) != end()) {
87                 return true;
88         }
89         else {
90                 return false;
91         }
92         
93 }
94
95 void
96 RegionSelection::add (RegionView* rv, bool dosort)
97 {
98         if (this->find (rv) != end()) {
99                 /* we already have it */
100                 return;
101         }
102
103         rv->RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
104
105         if (rv->region()->first_frame() < _current_start || empty()) {
106                 _current_start = rv->region()->first_frame();
107         }
108         
109         if (rv->region()->last_frame() > _current_end || empty()) {
110                 _current_end = rv->region()->last_frame();
111         }
112         
113         insert (rv);
114
115         // add to layer sorted list
116         add_to_layer (rv);
117         
118 }
119
120 void
121 RegionSelection::remove_it (RegionView *rv)
122 {
123         remove (rv);
124 }
125
126 bool
127 RegionSelection::remove (RegionView* rv)
128 {
129         RegionSelection::iterator i;
130
131         if ((i = this->find (rv)) != end()) {
132
133                 erase (i);
134
135                 // remove from layer sorted list
136                 _bylayer.remove (rv);
137                 
138                 if (empty()) {
139
140                         _current_start = 0;
141                         _current_end = 0;
142
143                 } else {
144                         
145                         boost::shared_ptr<Region> region ((*i)->region());
146
147                         if (region->first_frame() == _current_start) {
148                                 
149                                 /* reset current start */
150                                 
151                                 jack_nframes_t ref = max_frames;
152                                 
153                                 for (i = begin (); i != end(); ++i) {
154                                         if (region->first_frame() < ref) {
155                                                 ref = region->first_frame();
156                                         }
157                                 }
158                                 
159                                 _current_start = ref;
160                                 
161                         }
162                         
163                         if (region->last_frame() == _current_end) {
164
165                                 /* reset current end */
166                                 
167                                 jack_nframes_t ref = 0;
168                                 
169                                 for (i = begin (); i != end(); ++i) {
170                                         if (region->first_frame() > ref) {
171                                                 ref = region->first_frame();
172                                         }
173                                 }
174                                 
175                                 _current_end = ref;
176                         }
177                 }
178
179                 return true;
180         }
181
182         return false;
183 }
184
185 void
186 RegionSelection::add_to_layer (RegionView * rv)
187 {
188         // insert it into layer sorted position
189
190         list<RegionView*>::iterator i;
191
192         for (i = _bylayer.begin(); i != _bylayer.end(); ++i)
193         {
194                 if (rv->region()->layer() < (*i)->region()->layer()) {
195                         _bylayer.insert(i, rv);
196                         return;
197                 }
198         }
199
200         // insert at end if we get here
201         _bylayer.insert(i, rv);
202 }
203
204 struct RegionSortByTime {
205     bool operator() (const RegionView* a, const RegionView* b) {
206             return a->region()->position() < b->region()->position();
207     }
208 };
209
210
211 void
212 RegionSelection::by_position (list<RegionView*>& foo) const
213 {
214         list<RegionView*>::const_iterator i;
215         RegionSortByTime sorter;
216
217         for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
218                 foo.push_back (*i);
219         }
220
221         foo.sort (sorter);
222         return;
223 }