]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/data/TrackInfo.java
3df964b2652643624352a72b4e0c2be93114ed14
[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 file, if any
96          * @return AudioFile if selected, otherwise null
97          */
98         public AudioFile 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<AudioFile> inSet)
169         {
170                 int numAudiosAdded = 0;
171                 if (inSet != null && !inSet.isEmpty())
172                 {
173                         for (AudioFile 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 range of points
189          * @return true if successful
190          */
191         public boolean deleteRange()
192         {
193                 int startSel = _selection.getStart();
194                 int endSel = _selection.getEnd();
195                 boolean answer = _track.deleteRange(startSel, endSel);
196                 // clear range selection
197                 _selection.modifyRangeDeleted();
198                 return answer;
199         }
200
201
202         /**
203          * Delete the currently selected point
204          * @return true if point deleted
205          */
206         public boolean deletePoint()
207         {
208                 if (_track.deletePoint(_selection.getCurrentPointIndex()))
209                 {
210                         _selection.modifyPointDeleted();
211                         UpdateMessageBroker.informSubscribers();
212                         return true;
213                 }
214                 return false;
215         }
216
217
218         /**
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
222          */
223         public boolean deleteCurrentPhoto(boolean inPointToo)
224         {
225                 int photoIndex = _selection.getCurrentPhotoIndex();
226                 if (photoIndex >= 0)
227                 {
228                         Photo photo = _photoList.getPhoto(photoIndex);
229                         _photoList.deletePhoto(photoIndex);
230                         // has it got a point?
231                         if (photo.getDataPoint() != null)
232                         {
233                                 if (inPointToo)
234                                 {
235                                         // delete point
236                                         int pointIndex = _track.getPointIndex(photo.getDataPoint());
237                                         _track.deletePoint(pointIndex);
238                                 }
239                                 else
240                                 {
241                                         // disconnect point from photo
242                                         photo.getDataPoint().setPhoto(null);
243                                         photo.setDataPoint(null);
244                                 }
245                         }
246                         // update subscribers
247                         _selection.modifyPointDeleted();
248                         UpdateMessageBroker.informSubscribers();
249                 }
250                 return true;
251         }
252
253         /**
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
257          */
258         public boolean deleteCurrentAudio(boolean inPointToo)
259         {
260                 int audioIndex = _selection.getCurrentAudioIndex();
261                 if (audioIndex >= 0)
262                 {
263                         AudioFile audio = _audioList.getAudio(audioIndex);
264                         _audioList.deleteAudio(audioIndex);
265                         // has it got a point?
266                         if (audio.getDataPoint() != null)
267                         {
268                                 if (inPointToo)
269                                 {
270                                         // delete point
271                                         int pointIndex = _track.getPointIndex(audio.getDataPoint());
272                                         _track.deletePoint(pointIndex);
273                                 }
274                                 else
275                                 {
276                                         // disconnect point from audio
277                                         audio.getDataPoint().setAudio(null);
278                                         audio.setDataPoint(null);
279                                 }
280                         }
281                         // update subscribers
282                         _selection.modifyPointDeleted();
283                         UpdateMessageBroker.informSubscribers();
284                 }
285                 return true;
286         }
287
288
289         /**
290          * Delete all the points which have been marked for deletion
291          * @return number of points deleted
292          */
293         public int deleteMarkedPoints()
294         {
295                 int numDeleted = _track.deleteMarkedPoints();
296                 if (numDeleted > 0) {
297                         _selection.clearAll();
298                         UpdateMessageBroker.informSubscribers();
299                 }
300                 return numDeleted;
301         }
302
303
304         /**
305          * Clone the selected range of data points
306          * @return shallow copy of DataPoint objects
307          */
308         public DataPoint[] cloneSelectedRange()
309         {
310                 return _track.cloneRange(_selection.getStart(), _selection.getEnd());
311         }
312
313         /**
314          * Merge the track segments within the given range
315          * @param inStart start index
316          * @param inEnd end index
317          * @return true if successful
318          */
319         public boolean mergeTrackSegments(int inStart, int inEnd)
320         {
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;
329                         }
330                 }
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();
336                 return true;
337         }
338
339         /**
340          * Interpolate extra points between two selected ones
341          * @param inNumPoints num points to insert
342          * @return true if successful
343          */
344         public boolean interpolate(int inNumPoints)
345         {
346                 boolean success = _track.interpolate(_selection.getStart(), inNumPoints);
347                 if (success) {
348                         _selection.selectRangeEnd(_selection.getEnd() + inNumPoints);
349                 }
350                 return success;
351         }
352
353
354         /**
355          * Average selected points to create a new one
356          * @return true if successful
357          */
358         public boolean average()
359         {
360                 boolean success = _track.average(_selection.getStart(), _selection.getEnd());
361                 if (success) {
362                         selectPoint(_selection.getEnd()+1);
363                 }
364                 return success;
365         }
366
367
368         /**
369          * Select the given DataPoint
370          * @param inPoint DataPoint object to select
371          */
372         public void selectPoint(DataPoint inPoint)
373         {
374                 selectPoint(_track.getPointIndex(inPoint));
375         }
376
377         /**
378          * Select the data point with the given index
379          * @param inPointIndex index of DataPoint to select, or -1 for none
380          */
381         public void selectPoint(int inPointIndex)
382         {
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;
389                 if (pointHasPhoto) {
390                         photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
391                 }
392                 else if (photoIndex < 0 || _photoList.getPhoto(photoIndex).isConnected()) {
393                         // selected point hasn't got a photo - deselect photo if necessary
394                         photoIndex = -1;
395                 }
396                 // Check if point has an audio item or not
397                 int audioIndex = _selection.getCurrentAudioIndex();
398                 boolean pointHasAudio = inPointIndex >= 0 && selectedPoint.getAudio() != null;
399                 if (pointHasAudio) {
400                         audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
401                 }
402                 else if (audioIndex < 0 || _audioList.getAudio(audioIndex).isConnected()) {
403                         // deselect current audio file
404                         audioIndex = -1;
405                 }
406                 // give to selection
407                 _selection.selectPointPhotoAudio(inPointIndex, photoIndex, audioIndex);
408         }
409
410         /**
411          * Select the given Photo and its point if any
412          * @param inPhotoIndex index of photo to select
413          */
414         public void selectPhoto(int inPhotoIndex)
415         {
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
419                 // Find Photo object
420                 Photo photo = _photoList.getPhoto(inPhotoIndex);
421                 int pointIndex = _selection.getCurrentPointIndex();
422                 DataPoint currPoint = getCurrentPoint();
423                 if (photo != null)
424                 {
425                         // Has the photo got a point?
426                         if (photo.isConnected()) {
427                                 pointIndex = _track.getPointIndex(photo.getDataPoint());
428                         }
429                         else {
430                                 // Check whether to deselect current point or not if photo not correlated
431                                 if (pointIndex >= 0 && _track.getPoint(pointIndex).getPhoto() != null) {
432                                         pointIndex = -1;
433                                 }
434                         }
435                 }
436                 else {
437                         // no photo, but maybe need to deselect point
438                         if (currPoint != null && currPoint.getPhoto() != null) {
439                                 pointIndex = -1;
440                         }
441                 }
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());
447                 }
448                 else {
449                         if (selectedPoint != currPoint && currPoint.getAudio() != null) {audioIndex = -1;}
450                 }
451                 // give to selection object
452                 _selection.selectPointPhotoAudio(pointIndex, inPhotoIndex, audioIndex);
453         }
454
455         /**
456          * Select the given audio object and its point if any
457          * @param inAudioIndex index of audio item to select
458          */
459         public void selectAudio(int inAudioIndex)
460         {
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();
466                 if (audio != null)
467                 {
468                         // Find point object and its index
469                         if (audio.isConnected()) {
470                                 pointIndex = _track.getPointIndex(audio.getDataPoint());
471                         }
472                         else {
473                                 // Check whether to deselect current point or not if audio not correlated
474                                 if (pointIndex >= 0 && _track.getPoint(pointIndex).getAudio() != null) {
475                                         pointIndex = -1;
476                                 }
477                         }
478                 }
479                 else {
480                         // check if current point has audio or not
481                         if (currPoint != null && currPoint.getAudio() != null) {
482                                 pointIndex = -1;
483                         }
484                 }
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());
490                 }
491                 else {
492                         if (selectedPoint != currPoint && currPoint.getPhoto() != null) {photoIndex = -1;}
493                 }
494                 // give to selection object
495                 _selection.selectPointPhotoAudio(pointIndex, photoIndex, inAudioIndex);
496         }
497
498
499         /**
500          * Extend the current selection to end at the given point, eg by shift-clicking
501          * @param inPointNum index of end point
502          */
503         public void extendSelection(int inPointNum)
504         {
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();
509                 }
510                 selectPoint(inPointNum);
511                 if (rangeStart < inPointNum) {
512                         _selection.selectRange(rangeStart, inPointNum);
513                 }
514         }
515 }