]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/data/TrackInfo.java
58344142d390faf734df76edbf8fc557d5649c8e
[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 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                         return true;
212                 }
213                 return false;
214         }
215
216
217         /**
218          * Delete the currently selected photo and optionally its point too
219          * @param inPointToo true to also delete associated point
220          * @return true if delete successful
221          */
222         public boolean deleteCurrentPhoto(boolean inPointToo)
223         {
224                 int photoIndex = _selection.getCurrentPhotoIndex();
225                 if (photoIndex >= 0)
226                 {
227                         Photo photo = _photoList.getPhoto(photoIndex);
228                         _photoList.deletePhoto(photoIndex);
229                         // has it got a point?
230                         if (photo.getDataPoint() != null)
231                         {
232                                 if (inPointToo)
233                                 {
234                                         // delete point
235                                         int pointIndex = _track.getPointIndex(photo.getDataPoint());
236                                         _track.deletePoint(pointIndex);
237                                 }
238                                 else
239                                 {
240                                         // disconnect point from photo
241                                         photo.getDataPoint().setPhoto(null);
242                                         photo.setDataPoint(null);
243                                 }
244                         }
245                         // update subscribers
246                         _selection.modifyPointDeleted();
247                         UpdateMessageBroker.informSubscribers();
248                 }
249                 return true;
250         }
251
252         /**
253          * Delete the currently selected audio item and optionally its point too
254          * @param inPointToo true to also delete associated point
255          * @return true if delete successful
256          */
257         public boolean deleteCurrentAudio(boolean inPointToo)
258         {
259                 int audioIndex = _selection.getCurrentAudioIndex();
260                 if (audioIndex >= 0)
261                 {
262                         AudioClip audio = _audioList.getAudio(audioIndex);
263                         _audioList.deleteAudio(audioIndex);
264                         // has it got a point?
265                         if (audio.getDataPoint() != null)
266                         {
267                                 if (inPointToo)
268                                 {
269                                         // delete point
270                                         int pointIndex = _track.getPointIndex(audio.getDataPoint());
271                                         _track.deletePoint(pointIndex);
272                                 }
273                                 else
274                                 {
275                                         // disconnect point from audio
276                                         audio.getDataPoint().setAudio(null);
277                                         audio.setDataPoint(null);
278                                 }
279                         }
280                         // update subscribers
281                         _selection.modifyPointDeleted();
282                         UpdateMessageBroker.informSubscribers();
283                 }
284                 return true;
285         }
286
287
288         /**
289          * Delete all the points which have been marked for deletion
290          * @return number of points deleted
291          */
292         public int deleteMarkedPoints()
293         {
294                 int numDeleted = _track.deleteMarkedPoints();
295                 if (numDeleted > 0) {
296                         _selection.clearAll();
297                         UpdateMessageBroker.informSubscribers();
298                 }
299                 return numDeleted;
300         }
301
302
303         /**
304          * Clone the selected range of data points
305          * @return shallow copy of DataPoint objects
306          */
307         public DataPoint[] cloneSelectedRange()
308         {
309                 return _track.cloneRange(_selection.getStart(), _selection.getEnd());
310         }
311
312         /**
313          * Merge the track segments within the given range
314          * @param inStart start index
315          * @param inEnd end index
316          * @return true if successful
317          */
318         public boolean mergeTrackSegments(int inStart, int inEnd)
319         {
320                 boolean firstTrackPoint = true;
321                 // Loop between start and end
322                 for (int i=inStart; i<=inEnd; i++) {
323                         DataPoint point = _track.getPoint(i);
324                         // Set all segments to false apart from first track point
325                         if (point != null && !point.isWaypoint()) {
326                                 point.setSegmentStart(firstTrackPoint);
327                                 firstTrackPoint = false;
328                         }
329                 }
330                 // Find following track point, if any
331                 DataPoint nextPoint = _track.getNextTrackPoint(inEnd+1);
332                 if (nextPoint != null) {nextPoint.setSegmentStart(true);}
333                 _selection.markInvalid();
334                 UpdateMessageBroker.informSubscribers();
335                 return true;
336         }
337
338         /**
339          * Interpolate extra points between two selected ones
340          * @param inNumPoints num points to insert
341          * @return true if successful
342          */
343         public boolean interpolate(int inNumPoints)
344         {
345                 boolean success = _track.interpolate(_selection.getStart(), inNumPoints);
346                 if (success) {
347                         _selection.selectRangeEnd(_selection.getEnd() + inNumPoints);
348                 }
349                 return success;
350         }
351
352
353         /**
354          * Average selected points to create a new one
355          * @return true if successful
356          */
357         public boolean average()
358         {
359                 boolean success = _track.average(_selection.getStart(), _selection.getEnd());
360                 if (success) {
361                         selectPoint(_selection.getEnd()+1);
362                 }
363                 return success;
364         }
365
366
367         /**
368          * Select the given DataPoint
369          * @param inPoint DataPoint object to select
370          */
371         public void selectPoint(DataPoint inPoint)
372         {
373                 selectPoint(_track.getPointIndex(inPoint));
374         }
375
376         /**
377          * Increment the selected point index by the given increment
378          * @param inPointIncrement +1 for next point, -1 for previous etc
379          */
380         public void incrementPointIndex(int inPointIncrement)
381         {
382                 int index = _selection.getCurrentPointIndex() + inPointIncrement;
383                 if (index < 0) index = 0;
384                 else if (index >= _track.getNumPoints()) index = _track.getNumPoints()-1;
385                 selectPoint(index);
386         }
387
388         /**
389          * Select the data point with the given index
390          * @param inPointIndex index of DataPoint to select, or -1 for none
391          */
392         public void selectPoint(int inPointIndex)
393         {
394                 if (_selection.getCurrentPointIndex() == inPointIndex || inPointIndex >= _track.getNumPoints()) {return;}
395                 DataPoint selectedPoint = _track.getPoint(inPointIndex);
396                 // get the index of the current photo
397                 int photoIndex = _selection.getCurrentPhotoIndex();
398                 // Check if point has photo or not
399                 boolean pointHasPhoto = inPointIndex >= 0 && selectedPoint.getPhoto() != null;
400                 if (pointHasPhoto) {
401                         photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
402                 }
403                 else if (photoIndex < 0 || _photoList.getPhoto(photoIndex).isConnected()) {
404                         // selected point hasn't got a photo - deselect photo if necessary
405                         photoIndex = -1;
406                 }
407                 // Check if point has an audio item or not
408                 int audioIndex = _selection.getCurrentAudioIndex();
409                 boolean pointHasAudio = inPointIndex >= 0 && selectedPoint.getAudio() != null;
410                 if (pointHasAudio) {
411                         audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
412                 }
413                 else if (audioIndex < 0 || _audioList.getAudio(audioIndex).isConnected()) {
414                         // deselect current audio clip
415                         audioIndex = -1;
416                 }
417                 // give to selection
418                 _selection.selectPointPhotoAudio(inPointIndex, photoIndex, audioIndex);
419         }
420
421         /**
422          * Select the given Photo and its point if any
423          * @param inPhotoIndex index of photo to select
424          */
425         public void selectPhoto(int inPhotoIndex)
426         {
427                 if (_selection.getCurrentPhotoIndex() == inPhotoIndex) {return;}
428                 // Photo is primary selection here, not as a result of a point selection
429                 // Therefore the photo selection takes priority, deselecting point if necessary
430                 // Find Photo object
431                 Photo photo = _photoList.getPhoto(inPhotoIndex);
432                 int pointIndex = _selection.getCurrentPointIndex();
433                 DataPoint currPoint = getCurrentPoint();
434                 if (photo != null)
435                 {
436                         // Has the photo got a point?
437                         if (photo.isConnected()) {
438                                 pointIndex = _track.getPointIndex(photo.getDataPoint());
439                         }
440                         else {
441                                 // Check whether to deselect current point or not if photo not correlated
442                                 if (pointIndex >= 0 && _track.getPoint(pointIndex).getPhoto() != null) {
443                                         pointIndex = -1;
444                                 }
445                         }
446                 }
447                 else {
448                         // no photo, but maybe need to deselect point
449                         if (currPoint != null && currPoint.getPhoto() != null) {
450                                 pointIndex = -1;
451                         }
452                 }
453                 // Has the new point got an audio clip?
454                 DataPoint selectedPoint = _track.getPoint(pointIndex);
455                 int audioIndex = _selection.getCurrentAudioIndex();
456                 if (selectedPoint != null) {
457                         if (selectedPoint.getAudio() != null) audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
458                 }
459                 else {
460                         if (selectedPoint != currPoint && currPoint.getAudio() != null) {audioIndex = -1;}
461                 }
462                 // give to selection object
463                 _selection.selectPointPhotoAudio(pointIndex, inPhotoIndex, audioIndex);
464         }
465
466         /**
467          * Select the given audio object and its point if any
468          * @param inAudioIndex index of audio item to select
469          */
470         public void selectAudio(int inAudioIndex)
471         {
472                 if (_selection.getCurrentAudioIndex() == inAudioIndex) {return;}
473                 // Audio selection takes priority, deselecting point if necessary
474                 AudioClip audio = _audioList.getAudio(inAudioIndex);
475                 int pointIndex = _selection.getCurrentPointIndex();
476                 DataPoint currPoint = getCurrentPoint();
477                 if (audio != null)
478                 {
479                         // Find point object and its index
480                         if (audio.isConnected()) {
481                                 pointIndex = _track.getPointIndex(audio.getDataPoint());
482                         }
483                         else {
484                                 // Check whether to deselect current point or not if audio not correlated
485                                 if (pointIndex >= 0 && _track.getPoint(pointIndex).getAudio() != null) {
486                                         pointIndex = -1;
487                                 }
488                         }
489                 }
490                 else {
491                         // check if current point has audio or not
492                         if (currPoint != null && currPoint.getAudio() != null) {
493                                 pointIndex = -1;
494                         }
495                 }
496                 // Has the new point got a photo?
497                 DataPoint selectedPoint = _track.getPoint(pointIndex);
498                 int photoIndex = _selection.getCurrentPhotoIndex();
499                 if (selectedPoint != null) {
500                         if (selectedPoint.getPhoto() != null) photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
501                 }
502                 else {
503                         if (selectedPoint != currPoint && currPoint.getPhoto() != null) {photoIndex = -1;}
504                 }
505                 // give to selection object
506                 _selection.selectPointPhotoAudio(pointIndex, photoIndex, inAudioIndex);
507         }
508
509
510         /**
511          * Extend the current selection to end at the given point, eg by shift-clicking
512          * @param inPointNum index of end point
513          */
514         public void extendSelection(int inPointNum)
515         {
516                 // See whether to start selection from current range start or current point
517                 int rangeStart = _selection.getStart();
518                 if (rangeStart < 0 || _selection.getCurrentPointIndex() != _selection.getEnd()) {
519                         rangeStart = _selection.getCurrentPointIndex();
520                 }
521                 selectPoint(inPointNum);
522                 if (rangeStart < inPointNum) {
523                         _selection.selectRange(rangeStart, inPointNum);
524                 }
525         }
526 }