File: RearrangePhotosFunction.java

package info (click to toggle)
gpsprune 13.4-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 3,008 kB
  • sloc: java: 28,802; sh: 25; makefile: 17; python: 15
file content (224 lines) | stat: -rw-r--r-- 6,992 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
package tim.prune.function;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Comparator;

import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

import tim.prune.App;
import tim.prune.GenericFunction;
import tim.prune.I18nManager;
import tim.prune.data.DataPoint;
import tim.prune.data.Track;
import tim.prune.undo.UndoRearrangePhotos;

/**
 * Class to provide the function for rearranging photo points
 */
public class RearrangePhotosFunction extends GenericFunction
{
	/** Function dialog */
	private JDialog _dialog = null;
	/** Radio buttons for start/end */
	private JRadioButton[] _positionRadios = null;
	/** Radio buttons for sorting */
	private JRadioButton[] _sortRadios = null;


	/**
	 * Constructor
	 * @param inApp app object
	 */
	public RearrangePhotosFunction(App inApp)
	{
		super(inApp);
	}

	/** Begin the rearrange */
	public void begin()
	{
		// Make dialog window
		if (_dialog == null)
		{
			_dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
			_dialog.setLocationRelativeTo(_parentFrame);
			_dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
			_dialog.getContentPane().add(makeDialogComponents());
			_dialog.pack();
		}
		// Reset dialog and show
		_dialog.setVisible(true);
	}

	/** Get the name key (not needed) */
	public String getNameKey() {
		return "function.rearrangephotos";
	}


	/**
	 * Create dialog components
	 * @return Panel containing all gui elements in dialog
	 */
	private JPanel makeDialogComponents()
	{
		JPanel dialogPanel = new JPanel();
		dialogPanel.setLayout(new BorderLayout());
		dialogPanel.add(new JLabel(I18nManager.getText("dialog.rearrangephotos.desc")), BorderLayout.NORTH);
		// Radios for position (start / end)
		_positionRadios = new JRadioButton[2];
		final String[] posNames = {"tostart", "toend"};
		ButtonGroup posGroup = new ButtonGroup();
		JPanel posPanel = new JPanel();
		posPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		for (int i=0; i<2; i++)
		{
			_positionRadios[i] = new JRadioButton(I18nManager.getText("dialog.rearrangephotos." + posNames[i]));
			posGroup.add(_positionRadios[i]);
			posPanel.add(_positionRadios[i]);
		}
		_positionRadios[0].setSelected(true);
		// Radios for sort (none / filename / time)
		_sortRadios = new JRadioButton[3];
		final String[] sortNames = {"nosort", "sortbyfilename", "sortbytime"};
		ButtonGroup sortGroup = new ButtonGroup();
		JPanel sortPanel = new JPanel();
		sortPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		for (int i=0; i<3; i++)
		{
			_sortRadios[i] = new JRadioButton(I18nManager.getText("dialog.rearrangephotos." + sortNames[i]));
			sortGroup.add(_sortRadios[i]);
			sortPanel.add(_sortRadios[i]);
		}
		_sortRadios[0].setSelected(true);
		// add to middle of dialog
		JPanel centrePanel = new JPanel();
		centrePanel.setLayout(new BoxLayout(centrePanel, BoxLayout.Y_AXIS));
		centrePanel.add(posPanel);
		centrePanel.add(sortPanel);
		dialogPanel.add(centrePanel, BorderLayout.CENTER);
		// button panel at bottom
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
		JButton okButton = new JButton(I18nManager.getText("button.ok"));
		okButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				finish();
				_dialog.dispose();
			}
		});
		buttonPanel.add(okButton);
		JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
		cancelButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				_dialog.dispose();
			}
		});
		buttonPanel.add(cancelButton);
		dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
		return dialogPanel;
	}

	/**
	 * Perform the rearrange
	 */
	private void finish()
	{
		Track track = _app.getTrackInfo().getTrack();
		UndoRearrangePhotos undo = new UndoRearrangePhotos(track);
		// Loop through track collecting non-photo points and photo points
		final int numPoints = track.getNumPoints();
		DataPoint[] nonPhotos = new DataPoint[numPoints];
		DataPoint[] photos = new DataPoint[numPoints];
		int numNonPhotos = 0;
		int numPhotos = 0;
		for (int i=0; i<numPoints; i++)
		{
			DataPoint point = track.getPoint(i);
			if (point.getPhoto() != null) {
				photos[numPhotos] = point;
				numPhotos++;
			}
			else {
				nonPhotos[numNonPhotos] = point;
				numNonPhotos++;
			}
		}
		// Sort photos if necessary
		if (!_sortRadios[0].isSelected() && numPhotos > 1) {
			sortPhotos(photos, _sortRadios[1].isSelected());
		}
		// Put the non-photo points and photo points together
		DataPoint[] neworder = new DataPoint[numPoints];
		if (_positionRadios[0].isSelected()) {
			// photos at front
			System.arraycopy(photos, 0, neworder, 0, numPhotos);
			System.arraycopy(nonPhotos, 0, neworder, numPhotos, numNonPhotos);
		}
		else {
			// photos at end
			System.arraycopy(nonPhotos, 0, neworder, 0, numNonPhotos);
			System.arraycopy(photos, 0, neworder, numNonPhotos, numPhotos);
		}
		// Give track the new point order
		if (track.replaceContents(neworder))
		{
			_app.getTrackInfo().getSelection().clearAll();
			_app.completeFunction(undo, I18nManager.getText("confirm.rearrangephotos"));
			// Note: subscribers are informed up to three times now
		}
		else
		{
			JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.rearrange.noop"),
				I18nManager.getText("error.function.noop.title"), JOptionPane.WARNING_MESSAGE);
		}
	}

	/**
	 * Sort the given photo list either by filename or by time
	 * @param inPhotos array of DataPoint objects to sort
	 * @param inSortByFile true to sort by filename, false to sort by timestamp
	 * @return sorted array
	 */
	private static void sortPhotos(DataPoint[] inPhotos, boolean inSortByFile)
	{
		Comparator<DataPoint> comparator = null;
		if (inSortByFile)
		{
			// sort by filename
			comparator = new Comparator<DataPoint>() {
				public int compare(DataPoint inP1, DataPoint inP2) {
					if (inP2 == null) return -1; // all nulls at end
					if (inP1 == null) return 1;
					if (inP1.getPhoto().getFile() == null || inP2.getPhoto().getFile() == null)
						return inP1.getPhoto().getName().compareTo(inP2.getPhoto().getName());
					return inP1.getPhoto().getFile().compareTo(inP2.getPhoto().getFile());
				}
			};
		}
		else
		{
			// sort by photo timestamp
			comparator = new Comparator<DataPoint>() {
				public int compare(DataPoint inP1, DataPoint inP2) {
					if (inP2 == null) return -1; // all nulls at end
					if (inP1 == null) return 1;
					long secDiff = inP1.getPhoto().getTimestamp().getSecondsSince(inP2.getPhoto().getTimestamp());
					return (secDiff<0?-1:(secDiff==0?0:1));
				}
			};
		}
		Arrays.sort(inPhotos, comparator);
	}
}