]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/data/TrackInfo.java
Version 14, October 2012
[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          * @return number of points deleted
276          */
277         public int deleteMarkedPoints()
278         {
279                 int numDeleted = _track.deleteMarkedPoints();
280                 if (numDeleted > 0) {
281                         _selection.clearAll();
282                         UpdateMessageBroker.informSubscribers();
283                 }
284                 return numDeleted;
285         }
286
287
288         /**
289          * Clone the selected range of data points
290          * @return shallow copy of DataPoint objects
291          */
292         public DataPoint[] cloneSelectedRange()
293         {
294                 return _track.cloneRange(_selection.getStart(), _selection.getEnd());
295         }
296
297         /**
298          * Merge the track segments within the given range
299          * @param inStart start index
300          * @param inEnd end index
301          * @return true if successful
302          */
303         public boolean mergeTrackSegments(int inStart, int inEnd)
304         {
305                 boolean firstTrackPoint = true;
306                 // Loop between start and end
307                 for (int i=inStart; i<=inEnd; i++) {
308                         DataPoint point = _track.getPoint(i);
309                         // Set all segments to false apart from first track point
310                         if (point != null && !point.isWaypoint()) {
311                                 point.setSegmentStart(firstTrackPoint);
312                                 firstTrackPoint = false;
313                         }
314                 }
315                 // Find following track point, if any
316                 DataPoint nextPoint = _track.getNextTrackPoint(inEnd+1);
317                 if (nextPoint != null) {nextPoint.setSegmentStart(true);}
318                 _selection.markInvalid();
319                 UpdateMessageBroker.informSubscribers();
320                 return true;
321         }
322
323
324         /**
325          * Average selected points to create a new one
326          * @return true if successful
327          */
328         public boolean average()
329         {
330                 boolean success = _track.average(_selection.getStart(), _selection.getEnd());
331                 if (success) {
332                         selectPoint(_selection.getEnd()+1);
333                 }
334                 return success;
335         }
336
337
338         /**
339          * Select the given DataPoint
340          * @param inPoint DataPoint object to select
341          */
342         public void selectPoint(DataPoint inPoint)
343         {
344                 selectPoint(_track.getPointIndex(inPoint));
345         }
346
347         /**
348          * Increment the selected point index by the given increment
349          * @param inPointIncrement +1 for next point, -1 for previous etc
350          */
351         public void incrementPointIndex(int inPointIncrement)
352         {
353                 int index = _selection.getCurrentPointIndex() + inPointIncrement;
354                 if (index < 0) index = 0;
355                 else if (index >= _track.getNumPoints()) index = _track.getNumPoints()-1;
356                 selectPoint(index);
357         }
358
359         /**
360          * Select the data point with the given index
361          * @param inPointIndex index of DataPoint to select, or -1 for none
362          */
363         public void selectPoint(int inPointIndex)
364         {
365                 if (_selection.getCurrentPointIndex() == inPointIndex || inPointIndex >= _track.getNumPoints()) {return;}
366                 DataPoint selectedPoint = _track.getPoint(inPointIndex);
367                 // get the index of the current photo
368                 int photoIndex = _selection.getCurrentPhotoIndex();
369                 // Check if point has photo or not
370                 boolean pointHasPhoto = inPointIndex >= 0 && selectedPoint.getPhoto() != null;
371                 if (pointHasPhoto) {
372                         photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
373                 }
374                 else if (photoIndex < 0 || _photoList.getPhoto(photoIndex).isConnected()) {
375                         // selected point hasn't got a photo - deselect photo if necessary
376                         photoIndex = -1;
377                 }
378                 // Check if point has an audio item or not
379                 int audioIndex = _selection.getCurrentAudioIndex();
380                 boolean pointHasAudio = inPointIndex >= 0 && selectedPoint.getAudio() != null;
381                 if (pointHasAudio) {
382                         audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
383                 }
384                 else if (audioIndex < 0 || _audioList.getAudio(audioIndex).isConnected()) {
385                         // deselect current audio clip
386                         audioIndex = -1;
387                 }
388                 // give to selection
389                 _selection.selectPointPhotoAudio(inPointIndex, photoIndex, audioIndex);
390         }
391
392         /**
393          * Select the given Photo and its point if any
394          * @param inPhotoIndex index of photo to select
395          */
396         public void selectPhoto(int inPhotoIndex)
397         {
398                 if (_selection.getCurrentPhotoIndex() == inPhotoIndex) {return;}
399                 // Photo is primary selection here, not as a result of a point selection
400                 // Therefore the photo selection takes priority, deselecting point if necessary
401                 // Find Photo object
402                 Photo photo = _photoList.getPhoto(inPhotoIndex);
403                 int pointIndex = _selection.getCurrentPointIndex();
404                 DataPoint currPoint = getCurrentPoint();
405                 if (photo != null)
406                 {
407                         // Has the photo got a point?
408                         if (photo.isConnected()) {
409                                 pointIndex = _track.getPointIndex(photo.getDataPoint());
410                         }
411                         else {
412                                 // Check whether to deselect current point or not if photo not correlated
413                                 if (pointIndex >= 0 && _track.getPoint(pointIndex).getPhoto() != null) {
414                                         pointIndex = -1;
415                                 }
416                         }
417                 }
418                 else {
419                         // no photo, but maybe need to deselect point
420                         if (currPoint != null && currPoint.getPhoto() != null) {
421                                 pointIndex = -1;
422                         }
423                 }
424                 // Has the new point got an audio clip?
425                 DataPoint selectedPoint = _track.getPoint(pointIndex);
426                 int audioIndex = _selection.getCurrentAudioIndex();
427                 if (selectedPoint != null && selectedPoint.getAudio() != null) {
428                         // New point has an audio, so select it
429                         audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
430                 }
431                 else if (currPoint != null && selectedPoint != currPoint && currPoint.getAudio() != null) {
432                         // Old point had an audio, so deselect it
433                         audioIndex = -1;
434                 }
435                 // give to selection object
436                 _selection.selectPointPhotoAudio(pointIndex, inPhotoIndex, audioIndex);
437         }
438
439         /**
440          * Select the given audio object and its point if any
441          * @param inAudioIndex index of audio item to select
442          */
443         public void selectAudio(int inAudioIndex)
444         {
445                 if (_selection.getCurrentAudioIndex() == inAudioIndex) {return;}
446                 // Audio selection takes priority, deselecting point if necessary
447                 AudioClip audio = _audioList.getAudio(inAudioIndex);
448                 int pointIndex = _selection.getCurrentPointIndex();
449                 DataPoint currPoint = getCurrentPoint();
450                 if (audio != null)
451                 {
452                         // Find point object and its index
453                         if (audio.isConnected()) {
454                                 pointIndex = _track.getPointIndex(audio.getDataPoint());
455                         }
456                         else {
457                                 // Check whether to deselect current point or not if audio not correlated
458                                 if (pointIndex >= 0 && _track.getPoint(pointIndex).getAudio() != null) {
459                                         pointIndex = -1;
460                                 }
461                         }
462                 }
463                 else {
464                         // check if current point has audio or not
465                         if (currPoint != null && currPoint.getAudio() != null) {
466                                 pointIndex = -1;
467                         }
468                 }
469                 // Has the new point got a photo?
470                 DataPoint selectedPoint = _track.getPoint(pointIndex);
471                 int photoIndex = _selection.getCurrentPhotoIndex();
472                 if (selectedPoint != null && selectedPoint.getPhoto() != null) {
473                         // New point has a photo, so select it
474                         photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
475                 }
476                 else if (currPoint != null && selectedPoint != currPoint && currPoint.getPhoto() != null) {
477                         // Old point had a photo, so deselect it
478                         photoIndex = -1;
479                 }
480                 // give to selection object
481                 _selection.selectPointPhotoAudio(pointIndex, photoIndex, inAudioIndex);
482         }
483
484
485         /**
486          * Extend the current selection to end at the given point, eg by shift-clicking
487          * @param inPointNum index of end point
488          */
489         public void extendSelection(int inPointNum)
490         {
491                 // See whether to start selection from current range start or current point
492                 int rangeStart = _selection.getStart();
493                 if (rangeStart < 0 || _selection.getCurrentPointIndex() != _selection.getEnd()) {
494                         rangeStart = _selection.getCurrentPointIndex();
495                 }
496                 selectPoint(inPointNum);
497                 if (rangeStart < inPointNum) {
498                         _selection.selectRange(rangeStart, inPointNum);
499                 }
500         }
501 }