// License: GPL. For details, see LICENSE file.
package reverter;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.gui.ExtendedDialog;
import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
import org.openstreetmap.josm.tools.GBC;
import reverter.ChangesetReverter.RevertType;
@SuppressWarnings("serial")
public class ChangesetIdQuery extends ExtendedDialog {
private final JPanel panel = new JPanel(new GridBagLayout());
private final ChangesetIdsTextField tcid = new ChangesetIdsTextField();
private final HistoryComboBox cbId = new HistoryComboBox();
private final ButtonGroup bgRevertType = new ButtonGroup();
private final JRadioButton rbFull = new JRadioButton(tr("Revert changeset fully"));
private final JRadioButton rbSelection = new JRadioButton(tr("Revert selection only"));
private final JRadioButton rbSelectionUndelete = new JRadioButton(tr("Revert selection and restore deleted objects"));
private final JCheckBox cbNewLayer = new JCheckBox(tr("Download as new layer"));
public Collection<Integer> getIdsInReverseOrder() {
return tcid.getIdsInReverseOrder();
}
/**
* Replies true if the user requires to download into a new layer
*
* @return true if the user requires to download into a new layer
*/
public boolean isNewLayerRequired() {
return cbNewLayer.isSelected();
}
public RevertType getRevertType() {
if (rbFull.isSelected()) return RevertType.FULL;
if (rbSelection.isSelected()) return RevertType.SELECTION;
if (rbSelectionUndelete.isSelected()) return RevertType.SELECTION_WITH_UNDELETE;
return null;
}
public ChangesetIdQuery() {
super(Main.parent, tr("Revert changeset"), new String[] {tr("Revert"), tr("Cancel")}, true);
contentInsets = new Insets(10, 10, 10, 5);
panel.add(new JLabel(tr("Changeset id:")));
cbId.setEditor(new BasicComboBoxEditor() {
@Override
protected JTextField createEditorComponent() {
return tcid;
}
});
cbId.setToolTipText(tr("Enter the ID of the changeset that should be reverted"));
restoreChangesetsHistory(cbId);
// forward the enter key stroke to the revert button
tcid.getKeymap().removeKeyStrokeBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false));
panel.add(cbId, GBC.eol().fill(GBC.HORIZONTAL));
bgRevertType.add(rbFull);
bgRevertType.add(rbSelection);
bgRevertType.add(rbSelectionUndelete);
rbFull.setSelected(true);
panel.add(rbFull, GBC.eol().insets(0, 10, 0, 0).fill(GBC.HORIZONTAL));
panel.add(rbSelection, GBC.eol().fill(GBC.HORIZONTAL));
panel.add(rbSelectionUndelete, GBC.eol().fill(GBC.HORIZONTAL));
cbNewLayer.setToolTipText(tr("<html>Select to download data into a new data layer.<br>"
+"Unselect to download into the currently active data layer.</html>"));
panel.add(cbNewLayer, GBC.eol().fill(GBC.HORIZONTAL));
}
@Override
public void setupDialog() {
setContent(panel, false);
setButtonIcons(new String[] {"ok.png", "cancel.png" });
setDefaultButton(1);
addWindowListener(new InternalWindowListener());
super.setupDialog();
final DataSet ds = Main.getLayerManager().getEditDataSet();
// Disables "Download in new layer" choice if there is no current data set (i.e no data layer)
if (ds == null) {
cbNewLayer.setSelected(true);
cbNewLayer.setEnabled(false);
}
// Disables selection-related choices of there is no current selected objects
if (ds == null || ds.getAllSelected().isEmpty()) {
rbSelection.setEnabled(false);
rbSelectionUndelete.setEnabled(false);
}
// Enables/disables the Revert button when a changeset id is correctly set or not
tcid.getDocument().addDocumentListener(new DocumentListener() {
@Override public void removeUpdate(DocumentEvent e) {
idChanged();
}
@Override public void insertUpdate(DocumentEvent e) {
idChanged();
}
@Override public void changedUpdate(DocumentEvent e) {
idChanged();
}
private void idChanged() {
if (tcid.hasFocus()) {
buttons.get(0).setEnabled(tcid.readIds());
}
}
});
if (Main.pref.getBoolean("downloadchangeset.autopaste", true)) {
tcid.tryToPasteFromClipboard();
}
// Initially sets the revert button consistent with text id field contents
buttons.get(0).setEnabled(tcid.readIds());
}
/**
* Restore the current history from the preferences
*
* @param cbHistory history combobox
*/
protected void restoreChangesetsHistory(HistoryComboBox cbHistory) {
List<String> cmtHistory = new LinkedList<>(
Main.pref.getCollection(getClass().getName() + ".changesetsHistory", new LinkedList<String>()));
// we have to reverse the history, because ComboBoxHistory will reverse it again in addElement()
Collections.reverse(cmtHistory);
cbHistory.setPossibleItems(cmtHistory);
}
/**
* Remind the current history in the preferences
* @param cbHistory history combobox
*/
protected void remindChangesetsHistory(HistoryComboBox cbHistory) {
cbHistory.addCurrentItemToHistory();
Main.pref.putCollection(getClass().getName() + ".changesetsHistory", cbHistory.getHistory());
}
private class InternalWindowListener implements WindowListener {
@Override public void windowClosed(WindowEvent e) {
if (e != null && e.getComponent() == ChangesetIdQuery.this && getValue() == 1) {
if (!tcid.readIds()) {
return;
}
remindChangesetsHistory(cbId);
}
}
@Override public void windowOpened(WindowEvent e) {}
@Override public void windowClosing(WindowEvent e) {}
@Override public void windowIconified(WindowEvent e) {}
@Override public void windowDeiconified(WindowEvent e) {}
@Override public void windowActivated(WindowEvent e) {}
@Override public void windowDeactivated(WindowEvent e) {}
}
}