1 package tim.prune.data;
3 import tim.prune.DataSubscriber;
4 import tim.prune.UpdateMessageBroker;
7 * Class to represent a selected portion of a Track
10 public class Selection
12 private Track _track = null;
13 private int _currentPoint = -1;
14 private boolean _valid = false;
15 private int _prevNumPoints = 0;
16 private int _startIndex = -1, _endIndex = -1;
17 private int _currentPhotoIndex = -1;
18 private int _currentAudioIndex = -1;
19 private AltitudeRange _altitudeRange = null;
20 private long _movingMilliseconds = 0L;
21 private double _angMovingDistance = -1.0;
26 * @param inTrack track object
28 public Selection(Track inTrack)
35 * Mark selection invalid so it will be recalculated
37 public void markInvalid()
44 * @return the current point index
46 public int getCurrentPointIndex()
53 * @return true if range is selected
55 public boolean hasRangeSelected()
57 return _startIndex >= 0 && _endIndex > _startIndex;
62 * Recalculate all selection details
64 private void recalculate()
66 final int numPoints = _track.getNumPoints();
67 // Recheck if the number of points has changed
68 if (numPoints != _prevNumPoints)
70 _prevNumPoints = numPoints;
73 if (numPoints > 0 && hasRangeSelected())
75 _altitudeRange = new AltitudeRange();
76 Altitude altitude = null;
77 Timestamp time = null, previousTime = null;
78 DataPoint lastPoint = null, currPoint = null;
79 _angMovingDistance = 0.0;
80 _movingMilliseconds = 0L;
81 // Loop over points in selection
82 for (int i=_startIndex; i<=_endIndex; i++)
84 currPoint = _track.getPoint(i);
85 altitude = currPoint.getAltitude();
86 // Ignore waypoints in altitude calculations
87 if (!currPoint.isWaypoint() && altitude.isValid())
89 if (currPoint.getSegmentStart()) {
90 _altitudeRange.ignoreValue(altitude);
93 _altitudeRange.addValue(altitude);
96 // Compare timestamps within the segments
97 time = currPoint.getTimestamp();
101 if (!currPoint.getSegmentStart() && previousTime != null && time.isAfter(previousTime)) {
102 _movingMilliseconds += time.getMillisecondsSince(previousTime);
106 // Calculate distances, again ignoring waypoints
107 if (!currPoint.isWaypoint())
109 if (lastPoint != null)
111 double radians = DataPoint.calculateRadiansBetween(lastPoint, currPoint);
112 if (!currPoint.getSegmentStart()) {
113 _angMovingDistance += radians;
116 lastPoint = currPoint;
125 * @return start index
127 public int getStart()
129 if (!_valid) recalculate();
139 if (!_valid) recalculate();
144 * @return altitude range
146 public AltitudeRange getAltitudeRange()
148 if (!_valid) recalculate();
149 return _altitudeRange;
154 * @return number of seconds spanned by segments within selection
156 public long getMovingSeconds()
158 if (!_valid) recalculate();
159 return _movingMilliseconds / 1000L;
163 * @return moving distance of Selection in current units
165 public double getMovingDistance()
167 return Distance.convertRadiansToDistance(_angMovingDistance);
171 * Clear selected point, range, photo and audio
173 public void clearAll()
177 _currentPhotoIndex = -1;
178 _currentAudioIndex = -1;
184 * Select range from start to end
185 * @param inStartIndex index of start of range
186 * @param inEndIndex index of end of range
188 public void selectRange(int inStartIndex, int inEndIndex)
190 _startIndex = inStartIndex;
191 _endIndex = inEndIndex;
198 * Select the range from the current point
200 public void selectRangeStart()
202 selectRangeStart(_currentPoint);
207 * Set the index for the start of the range selection
208 * @param inStartIndex start index
210 private void selectRangeStart(int inStartIndex)
212 if (inStartIndex < 0)
214 _startIndex = _endIndex = -1;
218 _startIndex = inStartIndex;
219 // Move end of selection to max if necessary
220 if (_endIndex <= _startIndex)
222 _endIndex = _track.getNumPoints() - 1;
226 UpdateMessageBroker.informSubscribers();
231 * Select the range up to the current point
233 public void selectRangeEnd()
235 selectRangeEnd(_currentPoint);
240 * Set the index for the end of the range selection
241 * @param inEndIndex end index
243 public void selectRangeEnd(int inEndIndex)
247 _startIndex = _endIndex = -1;
251 _endIndex = inEndIndex;
252 // Move start of selection to min if necessary
253 if (_startIndex > _endIndex || _startIndex < 0) {
258 UpdateMessageBroker.informSubscribers();
263 * Modify the selection given that the selected range has been deleted
265 public void modifyRangeDeleted()
267 // Modify current point, if any
268 if (_currentPoint > _endIndex)
270 _currentPoint -= (_endIndex - _startIndex);
272 else if (_currentPoint > _startIndex)
274 _currentPoint = _startIndex;
276 // Clear selected range
277 _startIndex = _endIndex = -1;
278 // Check for consistency and fire update
284 * Modify the selection when a point is deleted
286 public void modifyPointDeleted()
288 // current point index doesn't change, just gets checked
289 // range needs to get altered if deleted point is inside or before
290 if (hasRangeSelected() && _currentPoint <= _endIndex)
293 if (_currentPoint < _startIndex)
302 * Select the specified photo and point
303 * @param inPointIndex index of selected point
304 * @param inPhotoIndex index of selected photo in PhotoList
305 * @param inAudioIndex index of selected audio item
307 public void selectPointPhotoAudio(int inPointIndex, int inPhotoIndex, int inAudioIndex)
309 _currentPoint = inPointIndex;
310 _currentPhotoIndex = inPhotoIndex;
311 _currentAudioIndex = inAudioIndex;
317 * @return currently selected photo index
319 public int getCurrentPhotoIndex()
321 return _currentPhotoIndex;
325 * @return currently selected audio index
327 public int getCurrentAudioIndex()
329 return _currentAudioIndex;
333 * Check that the selection still makes sense
334 * and fire update message to listeners
338 if (_track != null && _track.getNumPoints() > 0)
340 int maxIndex = _track.getNumPoints() - 1;
341 if (_currentPoint > maxIndex)
343 _currentPoint = maxIndex;
345 if (_endIndex > maxIndex)
347 _endIndex = maxIndex;
349 if (_startIndex > maxIndex)
351 _startIndex = maxIndex;
356 // track is empty, clear selections
357 _currentPoint = _startIndex = _endIndex = -1;
359 UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED);