1 package tim.prune.data;
4 import tim.prune.UpdateMessageBroker;
7 * Class to hold all track information, including data
8 * and the selection information
10 public class TrackInfo
12 private Track _track = null;
13 private Selection _selection = null;
14 private FileInfo _fileInfo = null;
15 private PhotoList _photoList = null;
16 private AudioList _audioList = null;
21 * @param inTrack Track object
23 public TrackInfo(Track inTrack)
26 _selection = new Selection(_track);
27 _fileInfo = new FileInfo();
28 _photoList = new PhotoList();
29 _audioList = new AudioList();
34 * @return the Track object
36 public Track getTrack() {
42 * @return the Selection object
44 public Selection getSelection() {
50 * @return the FileInfo object
52 public FileInfo getFileInfo() {
57 * Replace the file info with a previously made clone
58 * @param inInfo cloned file info
60 public void setFileInfo(FileInfo inInfo) {
65 * @return the PhotoList object
67 public PhotoList getPhotoList() {
72 * @return the AudioList object
74 public AudioList getAudioList() {
79 * Get the currently selected point, if any
80 * @return DataPoint if single point selected, otherwise null
82 public DataPoint getCurrentPoint() {
83 return _track.getPoint(_selection.getCurrentPointIndex());
87 * Get the currently selected photo, if any
88 * @return Photo if selected, otherwise null
90 public Photo getCurrentPhoto() {
91 return _photoList.getPhoto(_selection.getCurrentPhotoIndex());
95 * Get the currently selected audio file, if any
96 * @return AudioFile if selected, otherwise null
98 public AudioFile getCurrentAudio() {
99 return _audioList.getAudio(_selection.getCurrentAudioIndex());
104 * Add a Set of Photos
105 * @param inSet Set containing Photo objects
106 * @return array containing number of photos and number of points added
108 public int[] addPhotos(Set<Photo> inSet)
110 // Firstly count number of points and photos to add
111 int numPhotosToAdd = 0;
112 int numPointsToAdd = 0;
113 if (inSet != null && !inSet.isEmpty())
115 for (Photo photo : inSet)
117 if (photo != null && !_photoList.contains(photo))
120 if (photo.getDataPoint() != null) {
126 // If there are any photos to add, add them
127 if (numPhotosToAdd > 0)
129 DataPoint[] dataPoints = new DataPoint[numPointsToAdd];
131 boolean hasAltitude = false;
132 // Add each Photo in turn
133 for (Photo photo : inSet)
135 if (photo != null && !_photoList.contains(photo))
138 _photoList.addPhoto(photo);
139 // Add point if there is one
140 if (photo.getDataPoint() != null)
142 dataPoints[pointNum] = photo.getDataPoint();
143 // Check if any points have altitudes
144 hasAltitude |= (photo.getDataPoint().getAltitude() != null);
149 if (numPointsToAdd > 0)
151 // add points to track
152 _track.appendPoints(dataPoints);
153 // modify track field list
154 _track.getFieldList().extendList(Field.LATITUDE);
155 _track.getFieldList().extendList(Field.LONGITUDE);
156 if (hasAltitude) {_track.getFieldList().extendList(Field.ALTITUDE);}
159 int[] result = {numPhotosToAdd, numPointsToAdd};
164 * Add a Set of Audio objects
165 * @param inSet Set containing Audio objects
166 * @return number of audio objects added
168 public int addAudios(Set<AudioFile> inSet)
170 int numAudiosAdded = 0;
171 if (inSet != null && !inSet.isEmpty())
173 for (AudioFile audio : inSet)
175 if (audio != null && !_audioList.contains(audio))
178 _audioList.addAudio(audio);
180 // audio objects never have points when they're loaded
184 return numAudiosAdded;
188 * Delete the currently selected range of points
189 * @return true if successful
191 public boolean deleteRange()
193 int startSel = _selection.getStart();
194 int endSel = _selection.getEnd();
195 boolean answer = _track.deleteRange(startSel, endSel);
196 // clear range selection
197 _selection.modifyRangeDeleted();
203 * Delete the currently selected point
204 * @return true if point deleted
206 public boolean deletePoint()
208 if (_track.deletePoint(_selection.getCurrentPointIndex()))
210 _selection.modifyPointDeleted();
211 UpdateMessageBroker.informSubscribers();
219 * Delete the currently selected photo and optionally its point too
220 * @param inPointToo true to also delete associated point
221 * @return true if delete successful
223 public boolean deleteCurrentPhoto(boolean inPointToo)
225 int photoIndex = _selection.getCurrentPhotoIndex();
228 Photo photo = _photoList.getPhoto(photoIndex);
229 _photoList.deletePhoto(photoIndex);
230 // has it got a point?
231 if (photo.getDataPoint() != null)
236 int pointIndex = _track.getPointIndex(photo.getDataPoint());
237 _track.deletePoint(pointIndex);
241 // disconnect point from photo
242 photo.getDataPoint().setPhoto(null);
243 photo.setDataPoint(null);
246 // update subscribers
247 _selection.modifyPointDeleted();
248 UpdateMessageBroker.informSubscribers();
254 * Delete the currently selected audio item and optionally its point too
255 * @param inPointToo true to also delete associated point
256 * @return true if delete successful
258 public boolean deleteCurrentAudio(boolean inPointToo)
260 int audioIndex = _selection.getCurrentAudioIndex();
263 AudioFile audio = _audioList.getAudio(audioIndex);
264 _audioList.deleteAudio(audioIndex);
265 // has it got a point?
266 if (audio.getDataPoint() != null)
271 int pointIndex = _track.getPointIndex(audio.getDataPoint());
272 _track.deletePoint(pointIndex);
276 // disconnect point from audio
277 audio.getDataPoint().setAudio(null);
278 audio.setDataPoint(null);
281 // update subscribers
282 _selection.modifyPointDeleted();
283 UpdateMessageBroker.informSubscribers();
290 * Delete all the points which have been marked for deletion
291 * @return number of points deleted
293 public int deleteMarkedPoints()
295 int numDeleted = _track.deleteMarkedPoints();
296 if (numDeleted > 0) {
297 _selection.clearAll();
298 UpdateMessageBroker.informSubscribers();
305 * Clone the selected range of data points
306 * @return shallow copy of DataPoint objects
308 public DataPoint[] cloneSelectedRange()
310 return _track.cloneRange(_selection.getStart(), _selection.getEnd());
314 * Merge the track segments within the given range
315 * @param inStart start index
316 * @param inEnd end index
317 * @return true if successful
319 public boolean mergeTrackSegments(int inStart, int inEnd)
321 boolean firstTrackPoint = true;
322 // Loop between start and end
323 for (int i=inStart; i<=inEnd; i++) {
324 DataPoint point = _track.getPoint(i);
325 // Set all segments to false apart from first track point
326 if (point != null && !point.isWaypoint()) {
327 point.setSegmentStart(firstTrackPoint);
328 firstTrackPoint = false;
331 // Find following track point, if any
332 DataPoint nextPoint = _track.getNextTrackPoint(inEnd+1);
333 if (nextPoint != null) {nextPoint.setSegmentStart(true);}
334 _selection.markInvalid();
335 UpdateMessageBroker.informSubscribers();
340 * Interpolate extra points between two selected ones
341 * @param inNumPoints num points to insert
342 * @return true if successful
344 public boolean interpolate(int inNumPoints)
346 boolean success = _track.interpolate(_selection.getStart(), inNumPoints);
348 _selection.selectRangeEnd(_selection.getEnd() + inNumPoints);
355 * Average selected points to create a new one
356 * @return true if successful
358 public boolean average()
360 boolean success = _track.average(_selection.getStart(), _selection.getEnd());
362 selectPoint(_selection.getEnd()+1);
369 * Select the given DataPoint
370 * @param inPoint DataPoint object to select
372 public void selectPoint(DataPoint inPoint)
374 selectPoint(_track.getPointIndex(inPoint));
378 * Select the data point with the given index
379 * @param inPointIndex index of DataPoint to select, or -1 for none
381 public void selectPoint(int inPointIndex)
383 if (_selection.getCurrentPointIndex() == inPointIndex || inPointIndex >= _track.getNumPoints()) {return;}
384 DataPoint selectedPoint = _track.getPoint(inPointIndex);
385 // get the index of the current photo
386 int photoIndex = _selection.getCurrentPhotoIndex();
387 // Check if point has photo or not
388 boolean pointHasPhoto = inPointIndex >= 0 && selectedPoint.getPhoto() != null;
390 photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
392 else if (photoIndex < 0 || _photoList.getPhoto(photoIndex).isConnected()) {
393 // selected point hasn't got a photo - deselect photo if necessary
396 // Check if point has an audio item or not
397 int audioIndex = _selection.getCurrentAudioIndex();
398 boolean pointHasAudio = inPointIndex >= 0 && selectedPoint.getAudio() != null;
400 audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
402 else if (audioIndex < 0 || _audioList.getAudio(audioIndex).isConnected()) {
403 // deselect current audio file
407 _selection.selectPointPhotoAudio(inPointIndex, photoIndex, audioIndex);
411 * Select the given Photo and its point if any
412 * @param inPhotoIndex index of photo to select
414 public void selectPhoto(int inPhotoIndex)
416 if (_selection.getCurrentPhotoIndex() == inPhotoIndex) {return;}
417 // Photo is primary selection here, not as a result of a point selection
418 // Therefore the photo selection takes priority, deselecting point if necessary
420 Photo photo = _photoList.getPhoto(inPhotoIndex);
421 int pointIndex = _selection.getCurrentPointIndex();
422 DataPoint currPoint = getCurrentPoint();
425 // Has the photo got a point?
426 if (photo.isConnected()) {
427 pointIndex = _track.getPointIndex(photo.getDataPoint());
430 // Check whether to deselect current point or not if photo not correlated
431 if (pointIndex >= 0 && _track.getPoint(pointIndex).getPhoto() != null) {
437 // no photo, but maybe need to deselect point
438 if (currPoint != null && currPoint.getPhoto() != null) {
442 // Has the new point got an audio file?
443 DataPoint selectedPoint = _track.getPoint(pointIndex);
444 int audioIndex = _selection.getCurrentAudioIndex();
445 if (selectedPoint != null) {
446 if (selectedPoint.getAudio() != null) audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
449 if (selectedPoint != currPoint && currPoint.getAudio() != null) {audioIndex = -1;}
451 // give to selection object
452 _selection.selectPointPhotoAudio(pointIndex, inPhotoIndex, audioIndex);
456 * Select the given audio object and its point if any
457 * @param inAudioIndex index of audio item to select
459 public void selectAudio(int inAudioIndex)
461 if (_selection.getCurrentAudioIndex() == inAudioIndex) {return;}
462 // Audio selection takes priority, deselecting point if necessary
463 AudioFile audio = _audioList.getAudio(inAudioIndex);
464 int pointIndex = _selection.getCurrentPointIndex();
465 DataPoint currPoint = getCurrentPoint();
468 // Find point object and its index
469 if (audio.isConnected()) {
470 pointIndex = _track.getPointIndex(audio.getDataPoint());
473 // Check whether to deselect current point or not if audio not correlated
474 if (pointIndex >= 0 && _track.getPoint(pointIndex).getAudio() != null) {
480 // check if current point has audio or not
481 if (currPoint != null && currPoint.getAudio() != null) {
485 // Has the new point got a photo?
486 DataPoint selectedPoint = _track.getPoint(pointIndex);
487 int photoIndex = _selection.getCurrentPhotoIndex();
488 if (selectedPoint != null) {
489 if (selectedPoint.getPhoto() != null) photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
492 if (selectedPoint != currPoint && currPoint.getPhoto() != null) {photoIndex = -1;}
494 // give to selection object
495 _selection.selectPointPhotoAudio(pointIndex, photoIndex, inAudioIndex);
500 * Extend the current selection to end at the given point, eg by shift-clicking
501 * @param inPointNum index of end point
503 public void extendSelection(int inPointNum)
505 // See whether to start selection from current range start or current point
506 int rangeStart = _selection.getStart();
507 if (rangeStart < 0 || _selection.getCurrentPointIndex() != _selection.getEnd()) {
508 rangeStart = _selection.getCurrentPointIndex();
510 selectPoint(inPointNum);
511 if (rangeStart < inPointNum) {
512 _selection.selectRange(rangeStart, inPointNum);