Changeset 12576 in josm for trunk/src/org


Ignore:
Timestamp:
2017-08-06T20:41:20+02:00 (7 years ago)
Author:
michael2402
Message:

See #15057: Move the overpass query wizard dialog to a new file.

Location:
trunk/src/org/openstreetmap/josm
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/OverpassDownloadAction.java

    r12575 r12576  
    88import java.awt.Component;
    99import java.awt.Dimension;
    10 import java.awt.GridBagLayout;
    1110import java.awt.event.ActionEvent;
    1211import java.awt.event.FocusEvent;
    1312import java.awt.event.FocusListener;
    1413import java.awt.event.KeyEvent;
    15 import java.util.ArrayList;
    16 import java.util.Arrays;
    1714import java.util.Collection;
    18 import java.util.Collections;
    1915import java.util.Optional;
    2016import java.util.concurrent.Future;
     
    2521import javax.swing.ActionMap;
    2622import javax.swing.JButton;
    27 import javax.swing.JEditorPane;
    2823import javax.swing.JLabel;
    2924import javax.swing.JOptionPane;
    3025import javax.swing.JPanel;
    3126import javax.swing.JScrollPane;
    32 import javax.swing.event.HyperlinkEvent;
    3327import javax.swing.plaf.basic.BasicArrowButton;
    34 import javax.swing.text.JTextComponent;
    3528
    3629import org.openstreetmap.josm.Main;
     
    3932import org.openstreetmap.josm.data.Bounds;
    4033import org.openstreetmap.josm.data.preferences.BooleanProperty;
    41 import org.openstreetmap.josm.data.preferences.CollectionProperty;
    42 import org.openstreetmap.josm.gui.ExtendedDialog;
    4334import org.openstreetmap.josm.gui.download.DownloadDialog;
    4435import org.openstreetmap.josm.gui.download.OverpassQueryList;
     36import org.openstreetmap.josm.gui.download.OverpassQueryWizardDialog;
    4537import org.openstreetmap.josm.gui.preferences.server.OverpassServerPreference;
    4638import org.openstreetmap.josm.gui.util.GuiHelper;
    47 import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
    4839import org.openstreetmap.josm.gui.widgets.JosmTextArea;
    4940import org.openstreetmap.josm.io.OverpassDownloadReader;
    5041import org.openstreetmap.josm.tools.GBC;
    51 import org.openstreetmap.josm.tools.OpenBrowser;
    52 import org.openstreetmap.josm.tools.OverpassTurboQueryWizard;
    5342import org.openstreetmap.josm.tools.Shortcut;
    54 import org.openstreetmap.josm.tools.UncheckedParseException;
    55 import org.openstreetmap.josm.tools.Utils;
    5643
    5744/**
     
    160147    }
    161148
    162     private static final class OverpassDownloadDialog extends DownloadDialog {
     149    /**
     150     * The download dialog that overpass uses.
     151     * @since 12576 public
     152     */
     153    public static final class OverpassDownloadDialog extends DownloadDialog {
    163154
    164155        private JosmTextArea overpassQuery;
     
    196187                @Override
    197188                public void actionPerformed(ActionEvent e) {
    198                     QueryWizardDialog.getInstance().showDialog();
     189                    new OverpassQueryWizardDialog(instance).showDialog();
    199190                }
    200191            };
     
    262253        }
    263254
    264         void setOverpassQuery(String text) {
     255        /**
     256         * Sets the query that is displayed
     257         * @param text The multiline query text.
     258         * @since 12576 public
     259         */
     260        public void setOverpassQuery(String text) {
    265261            overpassQuery.setText(text);
    266262        }
     
    280276        /**
    281277         * Triggers the download action to fire.
    282          */
    283         private void triggerDownload() {
     278         * @since 12576 public
     279         */
     280        public void triggerDownload() {
    284281            super.btnDownload.doClick();
    285282        }
    286283    }
    287 
    288     private static final class QueryWizardDialog extends ExtendedDialog {
    289 
    290         private static final String HEADLINE_START = "<h3>";
    291         private static final String HEADLINE_END = "</h3>";
    292         private static final String TR_START = "<tr>";
    293         private static final String TR_END = "</tr>";
    294         private static final String TD_START = "<td>";
    295         private static final String TD_END = "</td>";
    296         private static QueryWizardDialog dialog;
    297         private final HistoryComboBox queryWizard;
    298         private final OverpassTurboQueryWizard overpassQueryBuilder;
    299         private static final CollectionProperty OVERPASS_WIZARD_HISTORY =
    300                 new CollectionProperty("download.overpass.wizard", new ArrayList<String>());
    301 
    302         // dialog buttons
    303         private static final int BUILD_QUERY = 0;
    304         private static final int BUILD_AN_EXECUTE_QUERY = 1;
    305         private static final int CANCEL = 2;
    306 
    307         /**
    308          * Get an instance of {@link QueryWizardDialog}.
    309          * @return The instance
    310          */
    311         public static QueryWizardDialog getInstance() {
    312             if (dialog == null) {
    313                 dialog = new QueryWizardDialog();
    314             }
    315 
    316             return dialog;
    317         }
    318 
    319         private static final String DESCRIPTION_STYLE =
    320                 "<style type=\"text/css\">\n"
    321                 + "table { border-spacing: 0pt;}\n"
    322                 + "h3 {text-align: center; padding: 8px;}\n"
    323                 + "td {border: 1px solid #dddddd; text-align: left; padding: 8px;}\n"
    324                 + "#desc {width: 350px;}"
    325                 + "</style>\n";
    326 
    327         private QueryWizardDialog() {
    328             super(OverpassDownloadDialog.getInstance(), tr("Overpass Turbo Query Wizard"),
    329                     tr("Build query"), tr("Build query and execute"), tr("Cancel"));
    330 
    331             this.queryWizard = new HistoryComboBox();
    332             this.overpassQueryBuilder = OverpassTurboQueryWizard.getInstance();
    333 
    334             JPanel panel = new JPanel(new GridBagLayout());
    335 
    336             JLabel searchLabel = new JLabel(tr("Search :"));
    337             JTextComponent descPane = buildDescriptionSection();
    338             JScrollPane scroll = GuiHelper.embedInVerticalScrollPane(descPane);
    339             scroll.getVerticalScrollBar().setUnitIncrement(10); // make scrolling smooth
    340 
    341             panel.add(searchLabel, GBC.std().insets(0, 0, 0, 20).anchor(GBC.SOUTHEAST));
    342             panel.add(queryWizard, GBC.eol().insets(0, 0, 0, 15).fill(GBC.HORIZONTAL).anchor(GBC.SOUTH));
    343             panel.add(scroll, GBC.eol().fill(GBC.BOTH).anchor(GBC.CENTER));
    344 
    345             queryWizard.setPossibleItems(OVERPASS_WIZARD_HISTORY.get());
    346 
    347             setCancelButton(CANCEL);
    348             setDefaultButton(BUILD_AN_EXECUTE_QUERY + 1); // Build and execute button
    349             setContent(panel, false);
    350         }
    351 
    352         @Override
    353         public void buttonAction(int buttonIndex, ActionEvent evt) {
    354             switch (buttonIndex) {
    355                 case BUILD_QUERY:
    356                     if (this.buildQueryAction()) {
    357                         this.saveHistory();
    358                         super.buttonAction(BUILD_QUERY, evt);
    359                     }
    360                     break;
    361                 case BUILD_AN_EXECUTE_QUERY:
    362                     if (this.buildQueryAction()) {
    363                         this.saveHistory();
    364                         super.buttonAction(BUILD_AN_EXECUTE_QUERY, evt);
    365 
    366                         OverpassDownloadDialog.getInstance().triggerDownload();
    367                     }
    368                     break;
    369                 default:
    370                     super.buttonAction(buttonIndex, evt);
    371 
    372             }
    373         }
    374 
    375         /**
    376          * Saves the latest, successfully parsed search term.
    377          */
    378         private void saveHistory() {
    379             queryWizard.addCurrentItemToHistory();
    380             OVERPASS_WIZARD_HISTORY.put(queryWizard.getHistory());
    381         }
    382 
    383         /**
    384          * Tries to process a search term using {@link OverpassTurboQueryWizard}. If the term cannot
    385          * be parsed, the the corresponding dialog is shown.
    386          * @param searchTerm The search term to parse.
    387          * @return {@link Optional#empty()} if an exception was thrown when parsing, meaning
    388          * that the term cannot be processed, or non-empty {@link Optional} containing the result
    389          * of parsing.
    390          */
    391         private Optional<String> tryParseSearchTerm(String searchTerm) {
    392             try {
    393                 String query = this.overpassQueryBuilder.constructQuery(searchTerm);
    394 
    395                 return Optional.of(query);
    396             } catch (UncheckedParseException ex) {
    397                 Main.error(ex);
    398                 JOptionPane.showMessageDialog(
    399                         OverpassDownloadDialog.getInstance(),
    400                         "<html>" +
    401                          tr("The Overpass wizard could not parse the following query:") +
    402                          Utils.joinAsHtmlUnorderedList(Collections.singleton(searchTerm)) +
    403                          "</html>",
    404                         tr("Parse error"),
    405                         JOptionPane.ERROR_MESSAGE
    406                 );
    407 
    408                 return Optional.empty();
    409             }
    410         }
    411 
    412         /**
    413          * Builds an Overpass query out from {@link QueryWizardDialog#queryWizard} contents.
    414          * @return {@code true} if the query successfully built, {@code false} otherwise.
    415          */
    416         private boolean buildQueryAction() {
    417             final String wizardSearchTerm = this.queryWizard.getText();
    418 
    419             Optional<String> q = this.tryParseSearchTerm(wizardSearchTerm);
    420             if (q.isPresent()) {
    421                 String query = q.get();
    422                 OverpassDownloadDialog.getInstance().setOverpassQuery(query);
    423 
    424                 return true;
    425             }
    426 
    427             return false;
    428         }
    429 
    430         private static JTextComponent buildDescriptionSection() {
    431             JEditorPane descriptionSection = new JEditorPane("text/html", getDescriptionContent());
    432             descriptionSection.setEditable(false);
    433             descriptionSection.addHyperlinkListener(e -> {
    434                 if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType())) {
    435                     OpenBrowser.displayUrl(e.getURL().toString());
    436                 }
    437             });
    438 
    439             return descriptionSection;
    440         }
    441 
    442         private static String getDescriptionContent() {
    443             return new StringBuilder("<html>")
    444                     .append(DESCRIPTION_STYLE)
    445                     .append("<body>")
    446                     .append(HEADLINE_START)
    447                     .append(tr("Query Wizard"))
    448                     .append(HEADLINE_END)
    449                     .append("<p>")
    450                     .append(tr("Allows you to interact with <i>Overpass API</i> by writing declarative, human-readable terms."))
    451                     .append(tr("The <i>Query Wizard</i> tool will transform those to a valid overpass query."))
    452                     .append(tr("For more detailed description see "))
    453                     .append(tr("<a href=\"{0}\">OSM Wiki</a>.", Main.getOSMWebsite() + "/wiki/Overpass_turbo/Wizard"))
    454                     .append("</p>")
    455                     .append(HEADLINE_START).append(tr("Hints")).append(HEADLINE_END)
    456                     .append("<table>").append(TR_START).append(TD_START)
    457                     .append(Utils.joinAsHtmlUnorderedList(Arrays.asList("<i>type:node</i>", "<i>type:relation</i>", "<i>type:way</i>")))
    458                     .append(TD_END).append(TD_START)
    459                     .append("<span>").append(tr("Download objects of a certain type.")).append("</span>")
    460                     .append(TD_END).append(TR_END)
    461                     .append(TR_START).append(TD_START)
    462                     .append(Utils.joinAsHtmlUnorderedList(
    463                             Arrays.asList("<i>key=value in <u>location</u></i>",
    464                                     "<i>key=value around <u>location</u></i>",
    465                                     "<i>key=value in bbox</i>")))
    466                     .append(TD_END).append(TD_START)
    467                     .append(tr("Download object by specifying a specific location. For example,"))
    468                     .append(Utils.joinAsHtmlUnorderedList(Arrays.asList(
    469                             tr("{0} all objects having {1} as attribute are downloaded.", "<i>tourism=hotel in Berlin</i> -", "'tourism=hotel'"),
    470                             tr("{0} all object with the corresponding key/value pair located around Berlin. Note, the default value for radius "+
    471                                     "is set to 1000m, but it can be changed in the generated query.", "<i>tourism=hotel around Berlin</i> -"),
    472                             tr("{0} all objects within the current selection that have {1} as attribute.", "<i>tourism=hotel in bbox</i> -",
    473                                     "'tourism=hotel'"))))
    474                     .append("<span>")
    475                     .append(tr("Instead of <i>location</i> any valid place name can be used like address, city, etc."))
    476                     .append("</span>")
    477                     .append(TD_END).append(TR_END)
    478                     .append(TR_START).append(TD_START)
    479                     .append(Utils.joinAsHtmlUnorderedList(Arrays.asList("<i>key=value</i>", "<i>key=*</i>", "<i>key~regex</i>",
    480                             "<i>key!=value</i>", "<i>key!~regex</i>", "<i>key=\"combined value\"</i>")))
    481                     .append(TD_END).append(TD_START)
    482                     .append(tr("<span>Download objects that have some concrete key/value pair, only the key with any contents for the value, " +
    483                             "the value matching some regular expression. 'Not equal' operators are supported as well.</span>"))
    484                     .append(TD_END).append(TR_END)
    485                     .append(TR_START).append(TD_START)
    486                     .append(Utils.joinAsHtmlUnorderedList(Arrays.asList(
    487                             tr("<i>expression1 {0} expression2</i>", "or"),
    488                             tr("<i>expression1 {0} expression2</i>", "and"))))
    489                     .append(TD_END).append(TD_START)
    490                     .append("<span>")
    491                     .append(tr("Basic logical operators can be used to create more sophisticated queries. Instead of 'or' - '|', '||' " +
    492                             "can be used, and instead of 'and' - '&', '&&'."))
    493                     .append("</span>")
    494                     .append(TD_END).append(TR_END).append("</table>")
    495                     .append("</body>")
    496                     .append("</html>")
    497                     .toString();
    498         }
    499     }
    500284}
Note: See TracChangeset for help on using the changeset viewer.