// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui.dialogs.changeset.query;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.gui.HelpAwareOptionPane;
import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
import org.openstreetmap.josm.gui.help.HelpUtil;
import org.openstreetmap.josm.io.ChangesetQuery;
import org.openstreetmap.josm.tools.ImageProvider;
import org.openstreetmap.josm.tools.InputMapUtils;
import org.openstreetmap.josm.tools.WindowGeometry;
/**
* This is a modal dialog for entering query criteria to search for changesets.
* @since 2689
*/
public class ChangesetQueryDialog extends JDialog {
private JTabbedPane tpQueryPanels;
private final BasicChangesetQueryPanel pnlBasicChangesetQueries = new BasicChangesetQueryPanel();
private final UrlBasedQueryPanel pnlUrlBasedQueries = new UrlBasedQueryPanel();
private final AdvancedChangesetQueryPanel pnlAdvancedQueries = new AdvancedChangesetQueryPanel();
private boolean canceled;
/**
* Constructs a new {@code ChangesetQueryDialog}.
* @param parent parent window
*/
public ChangesetQueryDialog(Window parent) {
super(parent, ModalityType.DOCUMENT_MODAL);
build();
}
protected JPanel buildContentPanel() {
tpQueryPanels = new JTabbedPane();
tpQueryPanels.add(pnlBasicChangesetQueries);
tpQueryPanels.add(pnlUrlBasedQueries);
tpQueryPanels.add(pnlAdvancedQueries);
tpQueryPanels.setTitleAt(0, tr("Basic"));
tpQueryPanels.setToolTipTextAt(0, tr("Download changesets using predefined queries"));
tpQueryPanels.setTitleAt(1, tr("From URL"));
tpQueryPanels.setToolTipTextAt(1, tr("Query changesets from a server URL"));
tpQueryPanels.setTitleAt(2, tr("Advanced"));
tpQueryPanels.setToolTipTextAt(2, tr("Use a custom changeset query"));
JPanel pnl = new JPanel(new BorderLayout());
pnl.add(tpQueryPanels, BorderLayout.CENTER);
return pnl;
}
protected JPanel buildButtonPanel() {
JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
pnl.add(new JButton(new QueryAction()));
pnl.add(new JButton(new CancelAction()));
pnl.add(new JButton(new ContextSensitiveHelpAction(HelpUtil.ht("/Dialog/ChangesetQuery"))));
return pnl;
}
protected final void build() {
setTitle(tr("Query changesets"));
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(buildContentPanel(), BorderLayout.CENTER);
cp.add(buildButtonPanel(), BorderLayout.SOUTH);
// cancel on ESC
InputMapUtils.addEscapeAction(getRootPane(), new CancelAction());
// context sensitive help
HelpUtil.setHelpContext(getRootPane(), HelpUtil.ht("/Dialog/ChangesetQueryDialog"));
addWindowListener(new WindowEventHandler());
}
/**
* Determines if the dialog has been canceled.
* @return {@code true} if the dialog has been canceled
*/
public boolean isCanceled() {
return canceled;
}
/**
* Initializes HMI for user input.
*/
public void initForUserInput() {
pnlBasicChangesetQueries.init();
}
protected void setCanceled(boolean canceled) {
this.canceled = canceled;
}
/**
* Returns the changeset query.
* @return the changeset query
*/
public ChangesetQuery getChangesetQuery() {
if (isCanceled())
return null;
switch(tpQueryPanels.getSelectedIndex()) {
case 0:
return pnlBasicChangesetQueries.buildChangesetQuery();
case 1:
return pnlUrlBasedQueries.buildChangesetQuery();
case 2:
return pnlAdvancedQueries.buildChangesetQuery();
default:
// FIXME: extend with advanced queries
return null;
}
}
/**
* Initializes HMI for user input.
*/
public void startUserInput() {
pnlUrlBasedQueries.startUserInput();
pnlAdvancedQueries.startUserInput();
}
@Override
public void setVisible(boolean visible) {
if (visible) {
new WindowGeometry(
getClass().getName() + ".geometry",
WindowGeometry.centerInWindow(
getParent(),
new Dimension(400, 400)
)
).applySafe(this);
setCanceled(false);
startUserInput();
} else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
new WindowGeometry(this).remember(getClass().getName() + ".geometry");
pnlAdvancedQueries.rememberSettings();
}
super.setVisible(visible);
}
class QueryAction extends AbstractAction {
QueryAction() {
putValue(NAME, tr("Query"));
new ImageProvider("dialogs", "search").getResource().attachImageIcon(this);
putValue(SHORT_DESCRIPTION, tr("Query and download changesets"));
}
protected void alertInvalidChangesetQuery() {
HelpAwareOptionPane.showOptionDialog(
ChangesetQueryDialog.this,
tr("Please enter a valid changeset query URL first."),
tr("Illegal changeset query URL"),
JOptionPane.WARNING_MESSAGE,
HelpUtil.ht("/Dialog/ChangesetQueryDialog#EnterAValidChangesetQueryUrlFirst")
);
}
@Override
public void actionPerformed(ActionEvent arg0) {
try {
switch(tpQueryPanels.getSelectedIndex()) {
case 0:
// currently, query specifications can't be invalid in the basic query panel.
// We select from a couple of predefined queries and there is always a query
// selected
break;
case 1:
if (getChangesetQuery() == null) {
alertInvalidChangesetQuery();
pnlUrlBasedQueries.startUserInput();
return;
}
break;
case 2:
if (getChangesetQuery() == null) {
pnlAdvancedQueries.displayMessageIfInvalid();
return;
}
}
setCanceled(false);
setVisible(false);
} catch (IllegalStateException e) {
Main.error(e);
JOptionPane.showMessageDialog(ChangesetQueryDialog.this, e.getMessage(), tr("Error"), JOptionPane.ERROR_MESSAGE);
}
}
}
class CancelAction extends AbstractAction {
CancelAction() {
putValue(NAME, tr("Cancel"));
new ImageProvider("cancel").getResource().attachImageIcon(this);
putValue(SHORT_DESCRIPTION, tr("Close the dialog and abort querying of changesets"));
}
public void cancel() {
setCanceled(true);
setVisible(false);
}
@Override
public void actionPerformed(ActionEvent arg0) {
cancel();
}
}
class WindowEventHandler extends WindowAdapter {
@Override
public void windowClosing(WindowEvent arg0) {
new CancelAction().cancel();
}
}
}