]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/function/DeleteBitOfTrackFunction.java
Version 14, October 2012
[GpsPrune.git] / tim / prune / function / DeleteBitOfTrackFunction.java
1 package tim.prune.function;
2
3 import javax.swing.JOptionPane;
4
5 import tim.prune.App;
6 import tim.prune.DataSubscriber;
7 import tim.prune.GenericFunction;
8 import tim.prune.I18nManager;
9 import tim.prune.UpdateMessageBroker;
10 import tim.prune.data.DataPoint;
11 import tim.prune.data.TrackInfo;
12 import tim.prune.undo.UndoDeleteRange;
13
14
15 /**
16  * Abstract class to hold general deletion routines to delete
17  * either one or two track sections.  Forms parent class to
18  * the DeleteSelection and CropToSelection functions
19  */
20 public abstract class DeleteBitOfTrackFunction extends GenericFunction
21 {
22         /**
23          * Constructor
24          * @param inApp application object for callback
25          */
26         public DeleteBitOfTrackFunction(App inApp)
27         {
28                 super(inApp);
29         }
30
31         /**
32          * @return key of undo text
33          */
34         protected abstract String getUndoNameKey();
35
36         /**
37          * Delete a single section
38          * @param inStart1 start index of section
39          * @param inEnd1 end index of section
40          */
41         protected void deleteSection(int inStart1, int inEnd1)
42         {
43                 deleteTwoSections(inStart1, inEnd1, -1, -1);
44         }
45
46         /**
47          * Delete the two specified sections
48          * @param inStart1 start index of first section to delete
49          * @param inEnd1 end index of first section
50          * @param inStart2 start index of second section to delete
51          * @param inEnd2 end index of second section
52          */
53         protected void deleteTwoSections(int inStart1, int inEnd1, int inStart2, int inEnd2)
54         {
55                 boolean[] deleteAllOrNone = {false, false};
56                 // TODO: Check for range overlap?  And test!
57                 if (inStart1 < 0 || inEnd1 < 0 || inEnd1 < inStart1) {
58                         inStart1 = inEnd1 = -1;
59                 }
60                 if (inStart2 < 0 || inEnd2 < 0 || inEnd2 < inStart2) {
61                         inStart2 = inEnd2 = -1;
62                 }
63                 if ((inStart1 >= 0 && inEnd1 < inStart1)
64                         || (inStart2 >= 0 && (inStart2 < inEnd1 || inEnd2 <= inStart2)))
65                 {
66                         System.err.println("Invalid ranges: (" + inStart1 + " - " + inEnd1 + "), (" + inStart2 + " - " + inEnd2 + ")");
67                         return;
68                 }
69                 // First section (if any)
70                 int numPoints = inEnd1 - inStart1 + 1;
71                 boolean[] deleteMedia1 = new boolean[numPoints];
72                 int numDeleted1 = prepareDeleteMedia(inStart1, inEnd1, deleteAllOrNone, deleteMedia1);
73                 if (numDeleted1 < 0) return;
74
75                 // Second section (if any)
76                 numPoints = inEnd2 - inStart2 + 1;
77                 boolean[] deleteMedia2 = new boolean[numPoints];
78                 int numDeleted2 = prepareDeleteMedia(inStart2, inEnd2, deleteAllOrNone, deleteMedia2);
79                 if (numDeleted2 < 0) return;
80                 int numDeleted = numDeleted1 + numDeleted2;
81                 if (numDeleted <= 0) return;
82
83                 // create undo object
84                 UndoDeleteRange undo = new UndoDeleteRange(_app.getTrackInfo(), getUndoNameKey(),
85                         inStart1, deleteMedia1, inStart2, deleteMedia2);
86
87                 // Loop through media to remove or disconnect
88                 if (numDeleted1 > 0) {
89                         resolveMedia(_app.getTrackInfo(), inStart1, deleteMedia1);
90                 }
91                 if (numDeleted2 > 0) {
92                         resolveMedia(_app.getTrackInfo(), inStart2, deleteMedia2);
93                 }
94
95                 // Call track to delete ranges 1 and 2
96                 if (numDeleted2 > 0) { // delete range2 first
97                         _app.getTrackInfo().getTrack().deleteRange(inStart2, inEnd2);
98                 }
99                 if (numDeleted1 > 0) { // delete range1 first
100                         _app.getTrackInfo().getTrack().deleteRange(inStart1, inEnd1);
101                 }
102
103                 // clear selection and notify
104                 _app.getTrackInfo().getSelection().clearAll();
105                 UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_ADDED_OR_REMOVED);
106
107                 // pass back to _app
108                 _app.completeFunction(undo, "" + numDeleted + " "
109                         + I18nManager.getText("confirm.deletepoint.multi"));
110         }
111
112         /**
113          * Prepare to delete the media in the given section, including prompting to delete or not
114          * @param inStart start index of the range to delete
115          * @param inEnd end index
116          * @param inDeleteAllOrNone boolean flags for delete all and delete none, held in an array
117          * @param inDeleteMedia boolean flag for each point, whether to delete media or not
118          * @return number of points to delete
119          */
120         private int prepareDeleteMedia(int inStart, int inEnd, boolean[] inDeleteAllOrNone, boolean[] inDeleteMedia)
121         {
122                 // Check sanity of inputs
123                 if (inStart < 0 || inEnd < 0 || inEnd < inStart) return 0;
124                 final int numPoints = inEnd - inStart + 1;
125                 if (inDeleteAllOrNone == null || inDeleteAllOrNone.length != 2
126                         || inDeleteMedia == null || inDeleteMedia.length != numPoints) {
127                         return 0;
128                 }
129
130                 // define buttons on prompt
131                 String[] questionOptions = {I18nManager.getText("button.yes"), I18nManager.getText("button.no"),
132                         I18nManager.getText("button.yestoall"), I18nManager.getText("button.notoall"),
133                         I18nManager.getText("button.cancel")};
134
135                 // Loop over points to check for media
136                 for (int i=0; i<numPoints; i++)
137                 {
138                         DataPoint point = _app.getTrackInfo().getTrack().getPoint(inStart + i);
139                         if (point.hasMedia())
140                         {
141                                 // point has either photo or audio
142                                 if (inDeleteAllOrNone[0]) // delete all has already been selected
143                                 {
144                                         inDeleteMedia[i] = true;
145                                 }
146                                 else if (inDeleteAllOrNone[1]) // delete none has already been selected
147                                 {
148                                         inDeleteMedia[i] = false;
149                                 }
150                                 else
151                                 {
152                                         int response = JOptionPane.showOptionDialog(_app.getFrame(),
153                                                 I18nManager.getText("dialog.deletepoint.deletephoto") + " " + point.getMediaName(),
154                                                 I18nManager.getText("dialog.deletepoint.title"),
155                                                 JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null,
156                                                 questionOptions, questionOptions[1]);
157                                         // check for cancel or close
158                                         if (response == 4 || response == -1) {return -1;}
159                                         // check for yes or yes to all
160                                         if (response == 0 || response == 2)
161                                         {
162                                                 inDeleteMedia[i] = true;
163                                                 if (response == 2) {inDeleteAllOrNone[0] = true;}
164                                         }
165                                         // check for no to all
166                                         if (response == 3) {inDeleteAllOrNone[1] = true;}
167                                 }
168                         }
169                 }
170                 return numPoints;
171         }
172
173         /**
174          * Resolve the media from the given points by either detaching or deleting
175          * @param inTrack track object
176          * @param inStart start index of range
177          * @param inDeleteFlags media deletion flags
178          */
179         private static void resolveMedia(TrackInfo inTrackInfo, int inStart, boolean[] inDeleteFlags)
180         {
181                 for (int i=0; i<inDeleteFlags.length; i++)
182                 {
183                         DataPoint point = inTrackInfo.getTrack().getPoint(i + inStart);
184                         if (point != null && point.hasMedia())
185                         {
186                                 if (inDeleteFlags[i])
187                                 {
188                                         // delete photo and/or audio from lists
189                                         if (point.getPhoto() != null) {
190                                                 inTrackInfo.getPhotoList().deletePhoto(inTrackInfo.getPhotoList().getPhotoIndex(point.getPhoto()));
191                                         }
192                                         if (point.getAudio() != null) {
193                                                 inTrackInfo.getAudioList().deleteAudio(inTrackInfo.getAudioList().getAudioIndex(point.getAudio()));
194                                         }
195                                 }
196                                 else
197                                 {
198                                         // decouple photo and/or audio from point
199                                         if (point.getPhoto() != null) {
200                                                 point.getPhoto().setDataPoint(null);
201                                         }
202                                         if (point.getAudio() != null) {
203                                                 point.getAudio().setDataPoint(null);
204                                         }
205                                 }
206                         }
207                 }
208         }
209 }