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 clip, if any
96 * @return AudioClip if selected, otherwise null
98 public AudioClip 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<AudioClip> inSet)
170 int numAudiosAdded = 0;
171 if (inSet != null && !inSet.isEmpty())
173 for (AudioClip 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 point
189 * @return true if point deleted
191 public boolean deletePoint()
193 if (_track.deletePoint(_selection.getCurrentPointIndex()))
195 _selection.modifyPointDeleted();
203 * Delete the currently selected photo and optionally its point too
204 * @param inPointToo true to also delete associated point
205 * @return true if delete successful
207 public boolean deleteCurrentPhoto(boolean inPointToo)
209 int photoIndex = _selection.getCurrentPhotoIndex();
212 Photo photo = _photoList.getPhoto(photoIndex);
213 _photoList.deletePhoto(photoIndex);
214 // has it got a point?
215 if (photo.getDataPoint() != null)
220 int pointIndex = _track.getPointIndex(photo.getDataPoint());
221 _track.deletePoint(pointIndex);
225 // disconnect point from photo
226 photo.getDataPoint().setPhoto(null);
227 photo.setDataPoint(null);
230 // update subscribers
231 _selection.modifyPointDeleted();
232 UpdateMessageBroker.informSubscribers();
238 * Delete the currently selected audio item and optionally its point too
239 * @param inPointToo true to also delete associated point
240 * @return true if delete successful
242 public boolean deleteCurrentAudio(boolean inPointToo)
244 int audioIndex = _selection.getCurrentAudioIndex();
247 AudioClip audio = _audioList.getAudio(audioIndex);
248 _audioList.deleteAudio(audioIndex);
249 // has it got a point?
250 if (audio.getDataPoint() != null)
255 int pointIndex = _track.getPointIndex(audio.getDataPoint());
256 _track.deletePoint(pointIndex);
260 // disconnect point from audio
261 audio.getDataPoint().setAudio(null);
262 audio.setDataPoint(null);
265 // update subscribers
266 _selection.modifyPointDeleted();
267 UpdateMessageBroker.informSubscribers();
274 * Delete all the points which have been marked for deletion
275 * @param inSplitSegments true to split segments at deleted points
276 * @return number of points deleted
278 public int deleteMarkedPoints(boolean inSplitSegments)
280 int numDeleted = _track.deleteMarkedPoints(inSplitSegments);
283 _selection.clearAll();
284 UpdateMessageBroker.informSubscribers();
291 * Clone the selected range of data points
292 * @return shallow copy of DataPoint objects
294 public DataPoint[] cloneSelectedRange()
296 return _track.cloneRange(_selection.getStart(), _selection.getEnd());
300 * Merge the track segments within the given range
301 * @param inStart start index
302 * @param inEnd end index
303 * @return true if successful
305 public boolean mergeTrackSegments(int inStart, int inEnd)
307 boolean firstTrackPoint = true;
308 // Loop between start and end
309 for (int i=inStart; i<=inEnd; i++)
311 DataPoint point = _track.getPoint(i);
312 // Set all segments to false apart from first track point
313 if (point != null && !point.isWaypoint()) {
314 point.setSegmentStart(firstTrackPoint);
315 firstTrackPoint = false;
318 // Find following track point, if any
319 DataPoint nextPoint = _track.getNextTrackPoint(inEnd+1);
320 if (nextPoint != null) {
321 nextPoint.setSegmentStart(true);
323 _selection.markInvalid();
324 UpdateMessageBroker.informSubscribers();
330 * Average selected points to create a new one
331 * @return true if successful
333 public boolean average()
335 boolean success = _track.average(_selection.getStart(), _selection.getEnd());
337 selectPoint(_selection.getEnd()+1);
344 * Select the given DataPoint
345 * @param inPoint DataPoint object to select
347 public void selectPoint(DataPoint inPoint)
349 selectPoint(_track.getPointIndex(inPoint));
353 * Increment the selected point index by the given increment
354 * @param inPointIncrement +1 for next point, -1 for previous etc
356 public void incrementPointIndex(int inPointIncrement)
358 int index = _selection.getCurrentPointIndex() + inPointIncrement;
361 else if (index >= _track.getNumPoints())
362 index = _track.getNumPoints()-1;
367 * Select the data point with the given index
368 * @param inPointIndex index of DataPoint to select, or -1 for none
370 public void selectPoint(int inPointIndex)
372 if (_selection.getCurrentPointIndex() == inPointIndex || inPointIndex >= _track.getNumPoints()) {
375 DataPoint selectedPoint = _track.getPoint(inPointIndex);
376 // get the index of the current photo
377 int photoIndex = _selection.getCurrentPhotoIndex();
378 // Check if point has photo or not
379 boolean pointHasPhoto = inPointIndex >= 0 && selectedPoint.getPhoto() != null;
381 photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
383 else if (photoIndex < 0 || _photoList.getPhoto(photoIndex).isConnected()) {
384 // selected point hasn't got a photo - deselect photo if necessary
387 // Check if point has an audio item or not
388 int audioIndex = _selection.getCurrentAudioIndex();
389 boolean pointHasAudio = inPointIndex >= 0 && selectedPoint.getAudio() != null;
391 audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
393 else if (audioIndex < 0 || _audioList.getAudio(audioIndex).isConnected()) {
394 // deselect current audio clip
398 _selection.selectPointPhotoAudio(inPointIndex, photoIndex, audioIndex);
402 * Select the given Photo and its point if any
403 * @param inPhotoIndex index of photo to select
405 public void selectPhoto(int inPhotoIndex)
407 if (_selection.getCurrentPhotoIndex() == inPhotoIndex) {
410 // Photo is primary selection here, not as a result of a point selection
411 // Therefore the photo selection takes priority, deselecting point if necessary
413 Photo photo = _photoList.getPhoto(inPhotoIndex);
414 int pointIndex = _selection.getCurrentPointIndex();
415 DataPoint currPoint = getCurrentPoint();
418 // Has the photo got a point?
419 if (photo.isConnected()) {
420 pointIndex = _track.getPointIndex(photo.getDataPoint());
423 // Check whether to deselect current point or not if photo not correlated
424 if (pointIndex >= 0 && _track.getPoint(pointIndex).getPhoto() != null) {
430 // no photo, but maybe need to deselect point
431 if (currPoint != null && currPoint.getPhoto() != null) {
435 // Has the new point got an audio clip?
436 DataPoint selectedPoint = _track.getPoint(pointIndex);
437 int audioIndex = _selection.getCurrentAudioIndex();
438 if (selectedPoint != null && selectedPoint.getAudio() != null)
440 // New point has an audio, so select it
441 audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
443 else if (currPoint != null && selectedPoint != currPoint && currPoint.getAudio() != null)
445 // Old point had an audio, so deselect it
448 // give to selection object
449 _selection.selectPointPhotoAudio(pointIndex, inPhotoIndex, audioIndex);
453 * Select the given audio object and its point if any
454 * @param inAudioIndex index of audio item to select
456 public void selectAudio(int inAudioIndex)
458 if (_selection.getCurrentAudioIndex() == inAudioIndex) {
461 // Audio selection takes priority, deselecting point if necessary
462 AudioClip audio = _audioList.getAudio(inAudioIndex);
463 int pointIndex = _selection.getCurrentPointIndex();
464 DataPoint currPoint = getCurrentPoint();
467 // Find point object and its index
468 if (audio.isConnected()) {
469 pointIndex = _track.getPointIndex(audio.getDataPoint());
472 // Check whether to deselect current point or not if audio not correlated
473 if (pointIndex >= 0 && _track.getPoint(pointIndex).getAudio() != null) {
479 // check if current point has audio or not
480 if (currPoint != null && currPoint.getAudio() != null) {
484 // Has the new point got a photo?
485 DataPoint selectedPoint = _track.getPoint(pointIndex);
486 int photoIndex = _selection.getCurrentPhotoIndex();
487 if (selectedPoint != null && selectedPoint.getPhoto() != null) {
488 // New point has a photo, so select it
489 photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
491 else if (currPoint != null && selectedPoint != currPoint && currPoint.getPhoto() != null) {
492 // Old point had a photo, so deselect it
495 // give to selection object
496 _selection.selectPointPhotoAudio(pointIndex, photoIndex, inAudioIndex);
501 * Extend the current selection to end at the given point, eg by shift-clicking
502 * @param inPointNum index of end point
504 public void extendSelection(int inPointNum)
506 // See whether to start selection from current range start or current point
507 int rangeStart = _selection.getStart();
508 if (rangeStart < 0 || _selection.getCurrentPointIndex() != _selection.getEnd()) {
509 rangeStart = _selection.getCurrentPointIndex();
511 selectPoint(inPointNum);
512 if (rangeStart < inPointNum) {
513 _selection.selectRange(rangeStart, inPointNum);