]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/data/TrackInfo.java
00d658828d38bf70e912d640caf85e4f7b824991
[GpsPrune.git] / tim / prune / data / TrackInfo.java
1 package tim.prune.data;
2
3 import java.util.Set;
4 import tim.prune.UpdateMessageBroker;
5
6 /**
7  * Class to hold all track information, including data
8  * and the selection information
9  */
10 public class TrackInfo
11 {
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;
17
18
19         /**
20          * Constructor
21          * @param inTrack Track object
22          */
23         public TrackInfo(Track inTrack)
24         {
25                 _track = inTrack;
26                 _selection = new Selection(_track);
27                 _fileInfo = new FileInfo();
28                 _photoList = new PhotoList();
29                 _audioList = new AudioList();
30         }
31
32
33         /**
34          * @return the Track object
35          */
36         public Track getTrack() {
37                 return _track;
38         }
39
40
41         /**
42          * @return the Selection object
43          */
44         public Selection getSelection() {
45                 return _selection;
46         }
47
48
49         /**
50          * @return the FileInfo object
51          */
52         public FileInfo getFileInfo() {
53                 return _fileInfo;
54         }
55
56         /**
57          * Replace the file info with a previously made clone
58          * @param inInfo cloned file info
59          */
60         public void setFileInfo(FileInfo inInfo) {
61                 _fileInfo = inInfo;
62         }
63
64         /**
65          * @return the PhotoList object
66          */
67         public PhotoList getPhotoList() {
68                 return _photoList;
69         }
70
71         /**
72          * @return the AudioList object
73          */
74         public AudioList getAudioList() {
75                 return _audioList;
76         }
77
78         /**
79          * Get the currently selected point, if any
80          * @return DataPoint if single point selected, otherwise null
81          */
82         public DataPoint getCurrentPoint() {
83                 return _track.getPoint(_selection.getCurrentPointIndex());
84         }
85
86         /**
87          * Get the currently selected photo, if any
88          * @return Photo if selected, otherwise null
89          */
90         public Photo getCurrentPhoto() {
91                 return _photoList.getPhoto(_selection.getCurrentPhotoIndex());
92         }
93
94         /**
95          * Get the currently selected audio clip, if any
96          * @return AudioClip if selected, otherwise null
97          */
98         public AudioClip getCurrentAudio() {
99                 return _audioList.getAudio(_selection.getCurrentAudioIndex());
100         }
101
102
103         /**
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
107          */
108         public int[] addPhotos(Set<Photo> inSet)
109         {
110                 // Firstly count number of points and photos to add
111                 int numPhotosToAdd = 0;
112                 int numPointsToAdd = 0;
113                 if (inSet != null && !inSet.isEmpty())
114                 {
115                         for (Photo photo : inSet)
116                         {
117                                 if (photo != null && !_photoList.contains(photo))
118                                 {
119                                         numPhotosToAdd++;
120                                         if (photo.getDataPoint() != null) {
121                                                 numPointsToAdd++;
122                                         }
123                                 }
124                         }
125                 }
126                 // If there are any photos to add, add them
127                 if (numPhotosToAdd > 0)
128                 {
129                         DataPoint[] dataPoints = new DataPoint[numPointsToAdd];
130                         int pointNum = 0;
131                         boolean hasAltitude = false;
132                         // Add each Photo in turn
133                         for (Photo photo : inSet)
134                         {
135                                 if (photo != null && !_photoList.contains(photo))
136                                 {
137                                         // Add photo
138                                         _photoList.addPhoto(photo);
139                                         // Add point if there is one
140                                         if (photo.getDataPoint() != null)
141                                         {
142                                                 dataPoints[pointNum] = photo.getDataPoint();
143                                                 // Check if any points have altitudes
144                                                 hasAltitude |= (photo.getDataPoint().getAltitude() != null);
145                                                 pointNum++;
146                                         }
147                                 }
148                         }
149                         if (numPointsToAdd > 0)
150                         {
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);}
157                         }
158                 }
159                 int[] result = {numPhotosToAdd, numPointsToAdd};
160                 return result;
161         }
162
163         /**
164          * Add a Set of Audio objects
165          * @param inSet Set containing Audio objects
166          * @return number of audio objects added
167          */
168         public int addAudios(Set<AudioClip> inSet)
169         {
170                 int numAudiosAdded = 0;
171                 if (inSet != null && !inSet.isEmpty())
172                 {
173                         for (AudioClip audio : inSet)
174                         {
175                                 if (audio != null && !_audioList.contains(audio))
176                                 {
177                                         // Add audio object
178                                         _audioList.addAudio(audio);
179                                         numAudiosAdded++;
180                                         // audio objects never have points when they're loaded
181                                 }
182                         }
183                 }
184                 return numAudiosAdded;
185         }
186
187         /**
188          * Delete the currently selected point
189          * @return true if point deleted
190          */
191         public boolean deletePoint()
192         {
193                 if (_track.deletePoint(_selection.getCurrentPointIndex()))
194                 {
195                         _selection.modifyPointDeleted();
196                         return true;
197                 }
198                 return false;
199         }
200
201
202         /**
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
206          */
207         public boolean deleteCurrentPhoto(boolean inPointToo)
208         {
209                 int photoIndex = _selection.getCurrentPhotoIndex();
210                 if (photoIndex >= 0)
211                 {
212                         Photo photo = _photoList.getPhoto(photoIndex);
213                         _photoList.deletePhoto(photoIndex);
214                         // has it got a point?
215                         if (photo.getDataPoint() != null)
216                         {
217                                 if (inPointToo)
218                                 {
219                                         // delete point
220                                         int pointIndex = _track.getPointIndex(photo.getDataPoint());
221                                         _track.deletePoint(pointIndex);
222                                 }
223                                 else
224                                 {
225                                         // disconnect point from photo
226                                         photo.getDataPoint().setPhoto(null);
227                                         photo.setDataPoint(null);
228                                 }
229                         }
230                         // update subscribers
231                         _selection.modifyPointDeleted();
232                         UpdateMessageBroker.informSubscribers();
233                 }
234                 return true;
235         }
236
237         /**
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
241          */
242         public boolean deleteCurrentAudio(boolean inPointToo)
243         {
244                 int audioIndex = _selection.getCurrentAudioIndex();
245                 if (audioIndex >= 0)
246                 {
247                         AudioClip audio = _audioList.getAudio(audioIndex);
248                         _audioList.deleteAudio(audioIndex);
249                         // has it got a point?
250                         if (audio.getDataPoint() != null)
251                         {
252                                 if (inPointToo)
253                                 {
254                                         // delete point
255                                         int pointIndex = _track.getPointIndex(audio.getDataPoint());
256                                         _track.deletePoint(pointIndex);
257                                 }
258                                 else
259                                 {
260                                         // disconnect point from audio
261                                         audio.getDataPoint().setAudio(null);
262                                         audio.setDataPoint(null);
263                                 }
264                         }
265                         // update subscribers
266                         _selection.modifyPointDeleted();
267                         UpdateMessageBroker.informSubscribers();
268                 }
269                 return true;
270         }
271
272
273         /**
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
277          */
278         public int deleteMarkedPoints(boolean inSplitSegments)
279         {
280                 int numDeleted = _track.deleteMarkedPoints(inSplitSegments);
281                 if (numDeleted > 0)
282                 {
283                         _selection.clearAll();
284                         UpdateMessageBroker.informSubscribers();
285                 }
286                 return numDeleted;
287         }
288
289
290         /**
291          * Clone the selected range of data points
292          * @return shallow copy of DataPoint objects
293          */
294         public DataPoint[] cloneSelectedRange()
295         {
296                 return _track.cloneRange(_selection.getStart(), _selection.getEnd());
297         }
298
299         /**
300          * Merge the track segments within the given range
301          * @param inStart start index
302          * @param inEnd end index
303          * @return true if successful
304          */
305         public boolean mergeTrackSegments(int inStart, int inEnd)
306         {
307                 boolean firstTrackPoint = true;
308                 // Loop between start and end
309                 for (int i=inStart; i<=inEnd; i++) {
310                         DataPoint point = _track.getPoint(i);
311                         // Set all segments to false apart from first track point
312                         if (point != null && !point.isWaypoint()) {
313                                 point.setSegmentStart(firstTrackPoint);
314                                 firstTrackPoint = false;
315                         }
316                 }
317                 // Find following track point, if any
318                 DataPoint nextPoint = _track.getNextTrackPoint(inEnd+1);
319                 if (nextPoint != null) {nextPoint.setSegmentStart(true);}
320                 _selection.markInvalid();
321                 UpdateMessageBroker.informSubscribers();
322                 return true;
323         }
324
325
326         /**
327          * Average selected points to create a new one
328          * @return true if successful
329          */
330         public boolean average()
331         {
332                 boolean success = _track.average(_selection.getStart(), _selection.getEnd());
333                 if (success) {
334                         selectPoint(_selection.getEnd()+1);
335                 }
336                 return success;
337         }
338
339
340         /**
341          * Select the given DataPoint
342          * @param inPoint DataPoint object to select
343          */
344         public void selectPoint(DataPoint inPoint)
345         {
346                 selectPoint(_track.getPointIndex(inPoint));
347         }
348
349         /**
350          * Increment the selected point index by the given increment
351          * @param inPointIncrement +1 for next point, -1 for previous etc
352          */
353         public void incrementPointIndex(int inPointIncrement)
354         {
355                 int index = _selection.getCurrentPointIndex() + inPointIncrement;
356                 if (index < 0) index = 0;
357                 else if (index >= _track.getNumPoints()) index = _track.getNumPoints()-1;
358                 selectPoint(index);
359         }
360
361         /**
362          * Select the data point with the given index
363          * @param inPointIndex index of DataPoint to select, or -1 for none
364          */
365         public void selectPoint(int inPointIndex)
366         {
367                 if (_selection.getCurrentPointIndex() == inPointIndex || inPointIndex >= _track.getNumPoints()) {return;}
368                 DataPoint selectedPoint = _track.getPoint(inPointIndex);
369                 // get the index of the current photo
370                 int photoIndex = _selection.getCurrentPhotoIndex();
371                 // Check if point has photo or not
372                 boolean pointHasPhoto = inPointIndex >= 0 && selectedPoint.getPhoto() != null;
373                 if (pointHasPhoto) {
374                         photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
375                 }
376                 else if (photoIndex < 0 || _photoList.getPhoto(photoIndex).isConnected()) {
377                         // selected point hasn't got a photo - deselect photo if necessary
378                         photoIndex = -1;
379                 }
380                 // Check if point has an audio item or not
381                 int audioIndex = _selection.getCurrentAudioIndex();
382                 boolean pointHasAudio = inPointIndex >= 0 && selectedPoint.getAudio() != null;
383                 if (pointHasAudio) {
384                         audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
385                 }
386                 else if (audioIndex < 0 || _audioList.getAudio(audioIndex).isConnected()) {
387                         // deselect current audio clip
388                         audioIndex = -1;
389                 }
390                 // give to selection
391                 _selection.selectPointPhotoAudio(inPointIndex, photoIndex, audioIndex);
392         }
393
394         /**
395          * Select the given Photo and its point if any
396          * @param inPhotoIndex index of photo to select
397          */
398         public void selectPhoto(int inPhotoIndex)
399         {
400                 if (_selection.getCurrentPhotoIndex() == inPhotoIndex) {return;}
401                 // Photo is primary selection here, not as a result of a point selection
402                 // Therefore the photo selection takes priority, deselecting point if necessary
403                 // Find Photo object
404                 Photo photo = _photoList.getPhoto(inPhotoIndex);
405                 int pointIndex = _selection.getCurrentPointIndex();
406                 DataPoint currPoint = getCurrentPoint();
407                 if (photo != null)
408                 {
409                         // Has the photo got a point?
410                         if (photo.isConnected()) {
411                                 pointIndex = _track.getPointIndex(photo.getDataPoint());
412                         }
413                         else {
414                                 // Check whether to deselect current point or not if photo not correlated
415                                 if (pointIndex >= 0 && _track.getPoint(pointIndex).getPhoto() != null) {
416                                         pointIndex = -1;
417                                 }
418                         }
419                 }
420                 else {
421                         // no photo, but maybe need to deselect point
422                         if (currPoint != null && currPoint.getPhoto() != null) {
423                                 pointIndex = -1;
424                         }
425                 }
426                 // Has the new point got an audio clip?
427                 DataPoint selectedPoint = _track.getPoint(pointIndex);
428                 int audioIndex = _selection.getCurrentAudioIndex();
429                 if (selectedPoint != null && selectedPoint.getAudio() != null) {
430                         // New point has an audio, so select it
431                         audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
432                 }
433                 else if (currPoint != null && selectedPoint != currPoint && currPoint.getAudio() != null) {
434                         // Old point had an audio, so deselect it
435                         audioIndex = -1;
436                 }
437                 // give to selection object
438                 _selection.selectPointPhotoAudio(pointIndex, inPhotoIndex, audioIndex);
439         }
440
441         /**
442          * Select the given audio object and its point if any
443          * @param inAudioIndex index of audio item to select
444          */
445         public void selectAudio(int inAudioIndex)
446         {
447                 if (_selection.getCurrentAudioIndex() == inAudioIndex) {return;}
448                 // Audio selection takes priority, deselecting point if necessary
449                 AudioClip audio = _audioList.getAudio(inAudioIndex);
450                 int pointIndex = _selection.getCurrentPointIndex();
451                 DataPoint currPoint = getCurrentPoint();
452                 if (audio != null)
453                 {
454                         // Find point object and its index
455                         if (audio.isConnected()) {
456                                 pointIndex = _track.getPointIndex(audio.getDataPoint());
457                         }
458                         else {
459                                 // Check whether to deselect current point or not if audio not correlated
460                                 if (pointIndex >= 0 && _track.getPoint(pointIndex).getAudio() != null) {
461                                         pointIndex = -1;
462                                 }
463                         }
464                 }
465                 else {
466                         // check if current point has audio or not
467                         if (currPoint != null && currPoint.getAudio() != null) {
468                                 pointIndex = -1;
469                         }
470                 }
471                 // Has the new point got a photo?
472                 DataPoint selectedPoint = _track.getPoint(pointIndex);
473                 int photoIndex = _selection.getCurrentPhotoIndex();
474                 if (selectedPoint != null && selectedPoint.getPhoto() != null) {
475                         // New point has a photo, so select it
476                         photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
477                 }
478                 else if (currPoint != null && selectedPoint != currPoint && currPoint.getPhoto() != null) {
479                         // Old point had a photo, so deselect it
480                         photoIndex = -1;
481                 }
482                 // give to selection object
483                 _selection.selectPointPhotoAudio(pointIndex, photoIndex, inAudioIndex);
484         }
485
486
487         /**
488          * Extend the current selection to end at the given point, eg by shift-clicking
489          * @param inPointNum index of end point
490          */
491         public void extendSelection(int inPointNum)
492         {
493                 // See whether to start selection from current range start or current point
494                 int rangeStart = _selection.getStart();
495                 if (rangeStart < 0 || _selection.getCurrentPointIndex() != _selection.getEnd()) {
496                         rangeStart = _selection.getCurrentPointIndex();
497                 }
498                 selectPoint(inPointNum);
499                 if (rangeStart < inPointNum) {
500                         _selection.selectRange(rangeStart, inPointNum);
501                 }
502         }
503 }