1 package tim.prune.function.deletebydate;
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.Dimension;
6 import java.awt.FlowLayout;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.ActionListener;
9 import java.awt.event.KeyAdapter;
10 import java.awt.event.KeyEvent;
11 import java.awt.event.MouseAdapter;
12 import java.awt.event.MouseEvent;
13 import java.util.Date;
15 import javax.swing.BorderFactory;
16 import javax.swing.JButton;
17 import javax.swing.JDialog;
18 import javax.swing.JLabel;
19 import javax.swing.JPanel;
20 import javax.swing.JScrollPane;
21 import javax.swing.JTable;
22 import javax.swing.border.EtchedBorder;
23 import javax.swing.event.ListSelectionEvent;
24 import javax.swing.event.ListSelectionListener;
25 import javax.swing.table.AbstractTableModel;
28 import tim.prune.DataSubscriber;
29 import tim.prune.I18nManager;
30 import tim.prune.UpdateMessageBroker;
31 import tim.prune.config.TimezoneHelper;
32 import tim.prune.data.DataPoint;
33 import tim.prune.function.compress.MarkAndDeleteFunction;
36 * Function to select a date or dates,
37 * and mark the corresponding points for deletion
39 public class DeleteByDateFunction extends MarkAndDeleteFunction
41 /** dialog for selecting dates */
42 private JDialog _dialog = null;
44 private JTable _infoTable = null;
46 private JButton _okButton = null;
47 // panel for selection buttons
48 private JPanel _selButtonPanel = null;
49 private JButton _keepSelectedButton = null;
50 private JButton _delSelectedButton = null;
52 private DateInfoList _infoList = new DateInfoList();
57 * @param inApp App object
59 public DeleteByDateFunction(App inApp)
65 public String getNameKey() {
66 return "function.deletebydate";
72 // Select the current timezone
73 DateInfo.setTimezone(TimezoneHelper.getSelectedTimezone());
75 // Make a list of which dates are present in the track
77 final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
78 for (int i=0; i<numPoints; i++)
80 DataPoint point = _app.getTrackInfo().getTrack().getPoint(i);
83 if (point.hasTimestamp()) {
84 _infoList.addPoint(point.getTimestamp()
85 .getCalendar(TimezoneHelper.getSelectedTimezone()).getTime());
88 _infoList.addPoint(null); // no timestamp available
93 // Complain if there is only one entry in the list - this means all points are on the same day
94 if (_infoList.getNumEntries() < 2)
96 _app.showErrorMessage(getNameKey(), "dialog.deletebydate.onlyonedate");
100 // Create and build dialog if necessary
103 _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
104 _dialog.setLocationRelativeTo(_parentFrame);
105 _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
106 _dialog.getContentPane().add(makeDialogComponents());
109 _selButtonPanel.setVisible(_infoList.getNumEntries() > 4);
112 _dialog.setVisible(true);
117 * Create dialog components
118 * @return Panel containing all gui elements in dialog
120 private Component makeDialogComponents()
122 JPanel dialogPanel = new JPanel();
123 dialogPanel.setLayout(new BorderLayout(5, 5));
125 JLabel topLabel = new JLabel(I18nManager.getText("dialog.deletebydate.intro"));
126 topLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
127 dialogPanel.add(topLabel, BorderLayout.NORTH);
129 // close window if escape pressed
130 KeyAdapter escListener = new KeyAdapter() {
131 public void keyReleased(KeyEvent inE) {
132 if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
138 _infoTable = new JTable(new DeletionTableModel(_infoList));
139 _infoTable.getTableHeader().addMouseListener(new MouseAdapter() {
140 public void mouseClicked(MouseEvent mouseEvent) {
141 int index = _infoTable.convertColumnIndexToModel(_infoTable.columnAtPoint(mouseEvent.getPoint()));
143 modifyAllCheckboxes(index == 3); // parameter is true for delete, false for keep
147 _infoTable.getSelectionModel().addListSelectionListener(
148 new ListSelectionListener() {
149 public void valueChanged(ListSelectionEvent e) {
154 JScrollPane pane = new JScrollPane(_infoTable);
155 pane.setPreferredSize(new Dimension(300, 180));
156 pane.setBorder(BorderFactory.createEmptyBorder(2, 50, 2, 50));
157 JPanel middlePanel = new JPanel();
158 middlePanel.setLayout(new BorderLayout());
159 middlePanel.add(pane, BorderLayout.CENTER);
160 _selButtonPanel = new JPanel();
161 _selButtonPanel.setBorder(BorderFactory.createCompoundBorder(
162 BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(4, 4, 4, 4))
164 _selButtonPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
165 _keepSelectedButton = new JButton(I18nManager.getText("button.keepselected"));
166 _keepSelectedButton.addActionListener(new ActionListener() {
167 public void actionPerformed(ActionEvent e) {
168 changeSelectedRowsToKeep();
171 _selButtonPanel.add(_keepSelectedButton);
172 _delSelectedButton = new JButton(I18nManager.getText("button.deleteselected"));
173 _delSelectedButton.addActionListener(new ActionListener() {
174 public void actionPerformed(ActionEvent e) {
175 changeSelectedRowsToDelete();
178 _selButtonPanel.add(_delSelectedButton);
179 middlePanel.add(_selButtonPanel, BorderLayout.SOUTH);
180 dialogPanel.add(middlePanel, BorderLayout.CENTER);
182 // button panel at bottom
183 JPanel buttonPanel = new JPanel();
184 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
186 _okButton = new JButton(I18nManager.getText("button.ok"));
187 _okButton.addActionListener(new ActionListener() {
188 public void actionPerformed(ActionEvent e) {
192 buttonPanel.add(_okButton);
193 _okButton.addKeyListener(escListener);
195 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
196 cancelButton.addActionListener(new ActionListener() {
197 public void actionPerformed(ActionEvent e) {
201 cancelButton.addKeyListener(new KeyAdapter() {
202 public void keyPressed(KeyEvent inE) {
203 if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
206 buttonPanel.add(cancelButton);
207 dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
212 * Select a column of checkboxes
213 * @param isDelete true for delete all, false for keep all
215 private void modifyAllCheckboxes(boolean isDelete)
217 for (int rowIndex=0; rowIndex<_infoList.getNumEntries(); rowIndex++)
219 _infoList.getDateInfo(rowIndex).setDeleteFlag(isDelete);
224 private void changeSelectedRowsToKeep()
226 changeSelectedRows(false);
228 private void changeSelectedRowsToDelete()
230 changeSelectedRows(true);
234 * Change the selected rows to either all keep or all delete
235 * @param isDelete true for delete, false for keep
237 private void changeSelectedRows(boolean isDelete)
239 int firstRow = -1, lastRow = -1;
240 for (int rowIndex : _infoTable.getSelectedRows())
242 if (firstRow == -1) {firstRow = rowIndex;}
243 _infoList.getDateInfo(rowIndex).setDeleteFlag(isDelete);
246 // Make sure all rows between first and last updated ones are updated in the table
247 ((AbstractTableModel) _infoTable.getModel()).fireTableRowsUpdated(firstRow, lastRow);
252 * Enable or disable the keepSelected and deleteSelected buttons
253 * according to the current selection
255 private void enableButtons()
257 boolean hasKeep = false, hasDelete = false;
258 for (int rowIndex : _infoTable.getSelectedRows())
260 if (_infoList.getDateInfo(rowIndex).getDeleteFlag()) {
267 _delSelectedButton.setEnabled(hasKeep);
268 _keepSelectedButton.setEnabled(hasDelete);
272 * Do the actual point deletion according to the
273 * selected rows in the table
275 private void performDelete()
278 final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
279 final int numDates = _infoList.getNumEntries();
280 // Loop over all points to mark each one for deletion or not
281 for (int p=0; p<numPoints; p++)
283 DataPoint point = _app.getTrackInfo().getTrack().getPoint(p);
286 final Date date = (point.hasTimestamp() ?
287 point.getTimestamp().getCalendar(TimezoneHelper.getSelectedTimezone()).getTime()
289 boolean pointMarked = false;
290 // Try to match each of the date info objects in the list
291 for (int d=0; d<numDates; d++)
293 DateInfo info = _infoList.getDateInfo(d);
294 if ( (info.isDateless() && date == null) // matches dateless
295 || (!info.isDateless() && date != null && info.isSameDate(date)))
297 pointMarked = info.getDeleteFlag();
301 point.setMarkedForDeletion(pointMarked);
307 // Now points have been marked, we can ask user to delete them (or delete automatically)
309 optionallyDeleteMarkedPoints(numMarked);
313 // Nothing to be deleted
314 // Delete flags might have been reset, so refresh display
315 UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED);