]> gitweb.fperrin.net Git - GpsPrune.git/blob - src/tim/prune/data/Selection.java
Version 20.4, May 2021
[GpsPrune.git] / src / tim / prune / data / Selection.java
1 package tim.prune.data;
2
3 import tim.prune.DataSubscriber;
4 import tim.prune.UpdateMessageBroker;
5
6 /**
7  * Class to represent a selected portion of a Track
8  * and its properties
9  */
10 public class Selection
11 {
12         private Track _track = null;
13         private int _currentPoint = -1;
14         private int _prevNumPoints = 0;
15         private int _startIndex = -1, _endIndex = -1;
16         private int _currentPhotoIndex = -1;
17         private int _currentAudioIndex = -1;
18         private RangeStats _rangeStats = null;
19
20
21         /**
22          * Constructor
23          * @param inTrack track object
24          */
25         public Selection(Track inTrack)
26         {
27                 _track = inTrack;
28         }
29
30
31         /**
32          * Mark selection invalid so it will be recalculated
33          */
34         public void markInvalid()
35         {
36                 _rangeStats = null;
37         }
38
39
40         /**
41          * @return the current point index
42          */
43         public int getCurrentPointIndex()
44         {
45                 return _currentPoint;
46         }
47
48
49         /**
50          * @return true if range is selected
51          */
52         public boolean hasRangeSelected()
53         {
54                 return _startIndex >= 0 && _endIndex > _startIndex;
55         }
56
57
58         /**
59          * Recalculate all selection details
60          */
61         private void recalculate()
62         {
63                 if (_rangeStats != null) {
64                         return;
65                 }
66                 final int numPoints = _track.getNumPoints();
67                 // Recheck if the number of points has changed
68                 if (numPoints != _prevNumPoints)
69                 {
70                         _prevNumPoints = numPoints;
71                         check();
72                 }
73                 if (numPoints > 0 && hasRangeSelected())
74                 {
75                         _rangeStats = new RangeStats(_track, _startIndex, _endIndex);
76                 }
77                 else
78                 {
79                         _rangeStats = new RangeStats();
80                 }
81         }
82
83
84         /**
85          * @return start index
86          */
87         public int getStart()
88         {
89                 recalculate();
90                 return _startIndex;
91         }
92
93
94         /**
95          * @return end index
96          */
97         public int getEnd()
98         {
99                 recalculate();
100                 return _endIndex;
101         }
102
103         /**
104          * @return altitude range
105          */
106         public AltitudeRange getAltitudeRange()
107         {
108                 recalculate();
109                 return _rangeStats.getTotalAltitudeRange();
110         }
111
112
113         /**
114          * @return number of seconds spanned by segments within selection
115          */
116         public long getMovingSeconds()
117         {
118                 recalculate();
119                 return _rangeStats.getMovingDurationInSeconds();
120         }
121
122         /**
123          * @return moving distance of Selection in current units
124          */
125         public double getMovingDistance()
126         {
127                 return _rangeStats.getMovingDistance();
128         }
129
130         /**
131          * Clear selected point, range, photo and audio
132          */
133         public void clearAll()
134         {
135                 _currentPoint = -1;
136                 selectRange(-1, -1);
137                 _currentPhotoIndex = -1;
138                 _currentAudioIndex = -1;
139                 markInvalid();
140                 check();
141         }
142
143
144         /**
145          * Select range from start to end
146          * @param inStartIndex index of start of range
147          * @param inEndIndex index of end of range
148          */
149         public void selectRange(int inStartIndex, int inEndIndex)
150         {
151                 _startIndex = inStartIndex;
152                 _endIndex = inEndIndex;
153                 markInvalid();
154                 check();
155         }
156
157
158         /**
159          * Select the range from the current point
160          */
161         public void selectRangeStart()
162         {
163                 selectRangeStart(_currentPoint);
164         }
165
166
167         /**
168          * Set the index for the start of the range selection
169          * @param inStartIndex start index
170          */
171         private void selectRangeStart(int inStartIndex)
172         {
173                 if (inStartIndex < 0)
174                 {
175                         _startIndex = _endIndex = -1;
176                 }
177                 else
178                 {
179                         _startIndex = inStartIndex;
180                         // Move end of selection to max if necessary
181                         if (_endIndex <= _startIndex)
182                         {
183                                 _endIndex = _track.getNumPoints() - 1;
184                         }
185                 }
186                 markInvalid();
187                 UpdateMessageBroker.informSubscribers();
188         }
189
190
191         /**
192          * Select the range up to the current point
193          */
194         public void selectRangeEnd()
195         {
196                 selectRangeEnd(_currentPoint);
197         }
198
199
200         /**
201          * Set the index for the end of the range selection
202          * @param inEndIndex end index
203          */
204         public void selectRangeEnd(int inEndIndex)
205         {
206                 if (inEndIndex < 0)
207                 {
208                         _startIndex = _endIndex = -1;
209                 }
210                 else
211                 {
212                         _endIndex = inEndIndex;
213                         // Move start of selection to min if necessary
214                         if (_startIndex > _endIndex || _startIndex < 0) {
215                                 _startIndex = 0;
216                         }
217                 }
218                 markInvalid();
219                 UpdateMessageBroker.informSubscribers();
220         }
221
222
223         /**
224          * Modify the selection given that the selected range has been deleted
225          */
226         public void modifyRangeDeleted()
227         {
228                 // Modify current point, if any
229                 if (_currentPoint > _endIndex)
230                 {
231                         _currentPoint -= (_endIndex - _startIndex);
232                 }
233                 else if (_currentPoint > _startIndex)
234                 {
235                         _currentPoint = _startIndex;
236                 }
237                 // Clear selected range
238                 _startIndex = _endIndex = -1;
239                 // Check for consistency and fire update
240                 markInvalid();
241                 check();
242         }
243
244
245         /**
246          * Modify the selection when a point is deleted
247          */
248         public void modifyPointDeleted()
249         {
250                 // current point index doesn't change, just gets checked
251                 // range needs to get altered if deleted point is inside or before
252                 if (hasRangeSelected() && _currentPoint <= _endIndex)
253                 {
254                         _endIndex--;
255                         if (_currentPoint < _startIndex)
256                                 _startIndex--;
257                         markInvalid();
258                 }
259                 check();
260         }
261
262
263         /**
264          * Select the specified photo and point
265          * @param inPointIndex index of selected point
266          * @param inPhotoIndex index of selected photo in PhotoList
267          * @param inAudioIndex index of selected audio item
268          */
269         public void selectPointPhotoAudio(int inPointIndex, int inPhotoIndex, int inAudioIndex)
270         {
271                 _currentPoint = inPointIndex;
272                 _currentPhotoIndex = inPhotoIndex;
273                 _currentAudioIndex = inAudioIndex;
274                 check();
275         }
276
277
278         /**
279          * @return currently selected photo index
280          */
281         public int getCurrentPhotoIndex()
282         {
283                 return _currentPhotoIndex;
284         }
285
286         /**
287          * @return currently selected audio index
288          */
289         public int getCurrentAudioIndex()
290         {
291                 return _currentAudioIndex;
292         }
293
294         /**
295          * Check that the selection still makes sense
296          * and fire update message to listeners
297          */
298         private void check()
299         {
300                 if (_track != null && _track.getNumPoints() > 0)
301                 {
302                         int maxIndex = _track.getNumPoints() - 1;
303                         if (_currentPoint > maxIndex)
304                         {
305                                 _currentPoint = maxIndex;
306                         }
307                         if (_endIndex > maxIndex)
308                         {
309                                 _endIndex = maxIndex;
310                         }
311                         if (_startIndex > maxIndex)
312                         {
313                                 _startIndex = maxIndex;
314                         }
315                 }
316                 else
317                 {
318                         // track is empty, clear selections
319                         _currentPoint = _startIndex = _endIndex = -1;
320                         markInvalid();
321                 }
322                 UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED);
323         }
324 }