Changeset 15115 in josm


Ignore:
Timestamp:
2019-05-25T21:14:13+02:00 (5 months ago)
Author:
Don-vip
Message:

see #16301 - extract ImageryProvidersPanel

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

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java

    r15114 r15115  
    22package org.openstreetmap.josm.gui.preferences.imagery;
    33
    4 import static org.openstreetmap.josm.tools.I18n.marktr;
    54import static org.openstreetmap.josm.tools.I18n.tr;
    65
    7 import java.awt.Color;
    86import java.awt.Component;
    97import java.awt.Dimension;
     
    1311import java.awt.GridBagConstraints;
    1412import java.awt.GridBagLayout;
    15 import java.awt.event.ActionEvent;
    16 import java.awt.event.MouseAdapter;
    1713import java.awt.event.MouseEvent;
    18 import java.io.IOException;
    19 import java.net.MalformedURLException;
    20 import java.net.URL;
    21 import java.util.ArrayList;
    22 import java.util.HashMap;
    23 import java.util.HashSet;
    2414import java.util.List;
    25 import java.util.Locale;
    26 import java.util.Map;
    2715import java.util.Objects;
    28 import java.util.Optional;
    29 import java.util.Set;
    30 import java.util.function.BiConsumer;
    31 import java.util.function.Function;
    3216import java.util.stream.Collectors;
    3317
    34 import javax.swing.AbstractAction;
    3518import javax.swing.BorderFactory;
    36 import javax.swing.Box;
    37 import javax.swing.ImageIcon;
    3819import javax.swing.JButton;
    3920import javax.swing.JLabel;
     
    4425import javax.swing.JTabbedPane;
    4526import javax.swing.JTable;
    46 import javax.swing.JToolBar;
    47 import javax.swing.UIManager;
    48 import javax.swing.event.ListSelectionEvent;
    49 import javax.swing.event.ListSelectionListener;
    50 import javax.swing.table.DefaultTableCellRenderer;
    5127import javax.swing.table.DefaultTableModel;
    5228import javax.swing.table.TableColumnModel;
    5329
    54 import org.openstreetmap.gui.jmapviewer.Coordinate;
    55 import org.openstreetmap.gui.jmapviewer.JMapViewer;
    56 import org.openstreetmap.gui.jmapviewer.MapPolygonImpl;
    57 import org.openstreetmap.gui.jmapviewer.MapRectangleImpl;
    58 import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
    59 import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
    6030import org.openstreetmap.josm.data.coor.EastNorth;
    6131import org.openstreetmap.josm.data.imagery.ImageryInfo;
    62 import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds;
    63 import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryCategory;
    6432import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
    6533import org.openstreetmap.josm.data.imagery.OffsetBookmark;
    66 import org.openstreetmap.josm.data.imagery.Shape;
    67 import org.openstreetmap.josm.data.preferences.NamedColorProperty;
    6834import org.openstreetmap.josm.data.projection.ProjectionRegistry;
    6935import org.openstreetmap.josm.gui.MainApplication;
    70 import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser;
    7136import org.openstreetmap.josm.gui.download.DownloadDialog;
    7237import org.openstreetmap.josm.gui.help.HelpUtil;
     
    7641import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
    7742import org.openstreetmap.josm.gui.util.GuiHelper;
    78 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    79 import org.openstreetmap.josm.gui.widgets.JosmEditorPane;
    80 import org.openstreetmap.josm.spi.preferences.Config;
    8143import org.openstreetmap.josm.tools.GBC;
    82 import org.openstreetmap.josm.tools.ImageProvider;
    83 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
    84 import org.openstreetmap.josm.tools.LanguageInfo;
    8544import org.openstreetmap.josm.tools.Logging;
    8645
     
    221180        }
    222181        return null;
    223     }
    224 
    225     /**
    226      * A panel displaying imagery providers.
    227      */
    228     public static class ImageryProvidersPanel extends JPanel {
    229         // Public JTables and JMapViewer
    230         /** The table of active providers **/
    231         public final JTable activeTable;
    232         /** The table of default providers **/
    233         public final JTable defaultTable;
    234         /** The selection listener synchronizing map display with table of default providers **/
    235         private final transient DefListSelectionListener defaultTableListener;
    236         /** The map displaying imagery bounds of selected default providers **/
    237         public final JMapViewer defaultMap;
    238 
    239         // Public models
    240         /** The model of active providers **/
    241         public final ImageryLayerTableModel activeModel;
    242         /** The model of default providers **/
    243         public final ImageryDefaultLayerTableModel defaultModel;
    244 
    245         // Public JToolbars
    246         /** The toolbar on the right of active providers **/
    247         public final JToolBar activeToolbar;
    248         /** The toolbar on the middle of the panel **/
    249         public final JToolBar middleToolbar;
    250         /** The toolbar on the right of default providers **/
    251         public final JToolBar defaultToolbar;
    252 
    253         // Private members
    254         private final PreferenceTabbedPane gui;
    255         private final transient ImageryLayerInfo layerInfo;
    256 
    257         /**
    258          * class to render the URL information of Imagery source
    259          * @since 8065
    260          */
    261         private static class ImageryURLTableCellRenderer extends DefaultTableCellRenderer {
    262 
    263             private static final NamedColorProperty IMAGERY_BACKGROUND_COLOR = new NamedColorProperty(
    264                     marktr("Imagery Background: Default"),
    265                     new Color(200, 255, 200));
    266 
    267             private final transient List<ImageryInfo> layers;
    268 
    269             ImageryURLTableCellRenderer(List<ImageryInfo> layers) {
    270                 this.layers = layers;
    271             }
    272 
    273             @Override
    274             public Component getTableCellRendererComponent(JTable table, Object value, boolean
    275                     isSelected, boolean hasFocus, int row, int column) {
    276                 JLabel label = (JLabel) super.getTableCellRendererComponent(
    277                         table, value, isSelected, hasFocus, row, column);
    278                 GuiHelper.setBackgroundReadable(label, UIManager.getColor("Table.background"));
    279                 if (value != null) { // Fix #8159
    280                     String t = value.toString();
    281                     for (ImageryInfo l : layers) {
    282                         if (l.getExtendedUrl().equals(t)) {
    283                             GuiHelper.setBackgroundReadable(label, IMAGERY_BACKGROUND_COLOR.get());
    284                             break;
    285                         }
    286                     }
    287                     label.setToolTipText((String) value);
    288                 }
    289                 return label;
    290             }
    291         }
    292 
    293         /**
    294          * class to render an information of Imagery source
    295          * @param <T> type of information
    296          */
    297         private static class ImageryTableCellRenderer<T> extends DefaultTableCellRenderer {
    298             private final Function<T, Object> mapper;
    299             private final Function<T, String> tooltip;
    300             private final BiConsumer<T, JLabel> decorator;
    301 
    302             ImageryTableCellRenderer(Function<T, Object> mapper, Function<T, String> tooltip, BiConsumer<T, JLabel> decorator) {
    303                 this.mapper = mapper;
    304                 this.tooltip = tooltip;
    305                 this.decorator = decorator;
    306             }
    307 
    308             @Override
    309             @SuppressWarnings("unchecked")
    310             public final Component getTableCellRendererComponent(JTable table, Object value, boolean
    311                     isSelected, boolean hasFocus, int row, int column) {
    312                 T obj = (T) value;
    313                 JLabel label = (JLabel) super.getTableCellRendererComponent(
    314                         table, mapper.apply(obj), isSelected, hasFocus, row, column);
    315                 GuiHelper.setBackgroundReadable(label, UIManager.getColor("Table.background"));
    316                 if (obj != null) {
    317                     label.setToolTipText(tooltip.apply(obj));
    318                     if (decorator != null) {
    319                         decorator.accept(obj, label);
    320                     }
    321                 }
    322                 return label;
    323             }
    324         }
    325 
    326         /**
    327          * class to render the category information of Imagery source
    328          */
    329         private static class ImageryCategoryTableCellRenderer extends ImageryTableCellRenderer<ImageryCategory> {
    330             ImageryCategoryTableCellRenderer() {
    331                 super(cat -> null, cat -> tr("Imagery category: {0}", cat.getDescription()),
    332                       (cat, label) -> label.setIcon(cat.getIcon(ImageSizes.TABLE)));
    333             }
    334         }
    335 
    336         /**
    337          * class to render the country information of Imagery source
    338          */
    339         private static class ImageryCountryTableCellRenderer extends ImageryTableCellRenderer<String> {
    340             ImageryCountryTableCellRenderer() {
    341                 super(code -> code, code -> code.isEmpty() ? tr("Worldwide") : new Locale("en", code).getDisplayCountry(), null);
    342             }
    343         }
    344 
    345         /**
    346          * class to render the name information of Imagery source
    347          */
    348         private static class ImageryNameTableCellRenderer extends ImageryTableCellRenderer<ImageryInfo> {
    349             ImageryNameTableCellRenderer() {
    350                 super(info -> info == null ? null : info.getName(), ImageryInfo::getToolTipText, null);
    351             }
    352         }
    353 
    354         /**
    355          * Constructs a new {@code ImageryProvidersPanel}.
    356          * @param gui The parent preference tab pane
    357          * @param layerInfoArg The list of imagery entries to display
    358          */
    359         public ImageryProvidersPanel(final PreferenceTabbedPane gui, ImageryLayerInfo layerInfoArg) {
    360             super(new GridBagLayout());
    361             this.gui = gui;
    362             this.layerInfo = layerInfoArg;
    363             this.activeModel = new ImageryLayerTableModel();
    364 
    365             activeTable = new JTable(activeModel) {
    366                 @Override
    367                 public String getToolTipText(MouseEvent e) {
    368                     java.awt.Point p = e.getPoint();
    369                     try {
    370                         return activeModel.getValueAt(rowAtPoint(p), columnAtPoint(p)).toString();
    371                     } catch (ArrayIndexOutOfBoundsException ex) {
    372                         Logging.debug(ex);
    373                         return null;
    374                     }
    375                 }
    376             };
    377             activeTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
    378 
    379             defaultModel = new ImageryDefaultLayerTableModel();
    380             defaultTable = new JTable(defaultModel);
    381 
    382             defaultModel.addTableModelListener(e -> activeTable.repaint());
    383             activeModel.addTableModelListener(e -> defaultTable.repaint());
    384 
    385             TableColumnModel mod = defaultTable.getColumnModel();
    386             mod.getColumn(3).setPreferredWidth(775);
    387             mod.getColumn(3).setCellRenderer(new ImageryURLTableCellRenderer(layerInfo.getLayers()));
    388             mod.getColumn(2).setPreferredWidth(475);
    389             mod.getColumn(2).setCellRenderer(new ImageryNameTableCellRenderer());
    390             mod.getColumn(1).setCellRenderer(new ImageryCountryTableCellRenderer());
    391             mod.getColumn(0).setPreferredWidth(50);
    392             mod.getColumn(0).setCellRenderer(new ImageryCategoryTableCellRenderer());
    393             mod.getColumn(0).setPreferredWidth(50);
    394 
    395             mod = activeTable.getColumnModel();
    396             mod.getColumn(1).setPreferredWidth(800);
    397             mod.getColumn(1).setCellRenderer(new ImageryURLTableCellRenderer(layerInfo.getAllDefaultLayers()));
    398             mod.getColumn(0).setPreferredWidth(200);
    399 
    400             RemoveEntryAction remove = new RemoveEntryAction();
    401             activeTable.getSelectionModel().addListSelectionListener(remove);
    402 
    403             add(new JLabel(tr("Available default entries:")), GBC.std().insets(5, 5, 0, 0));
    404             add(new JLabel(tr("Boundaries of selected imagery entries:")), GBC.eol().insets(5, 5, 0, 0));
    405 
    406             // Add default item list
    407             JScrollPane scrolldef = new JScrollPane(defaultTable);
    408             scrolldef.setPreferredSize(new Dimension(200, 200));
    409             add(scrolldef, GBC.std().insets(0, 5, 0, 0).fill(GridBagConstraints.BOTH).weight(1.0, 0.6).insets(5, 0, 0, 0));
    410 
    411             // Add default item map
    412             defaultMap = new JMapViewer();
    413             defaultMap.setTileSource(SlippyMapBBoxChooser.DefaultOsmTileSourceProvider.get()); // for attribution
    414             defaultMap.addMouseListener(new MouseAdapter() {
    415                 @Override
    416                 public void mouseClicked(MouseEvent e) {
    417                     if (e.getButton() == MouseEvent.BUTTON1) {
    418                         defaultMap.getAttribution().handleAttribution(e.getPoint(), true);
    419                     }
    420                 }
    421             });
    422             defaultMap.setZoomControlsVisible(false);
    423             defaultMap.setMinimumSize(new Dimension(100, 200));
    424             add(defaultMap, GBC.std().insets(5, 5, 0, 0).fill(GridBagConstraints.BOTH).weight(0.33, 0.6).insets(5, 0, 0, 0));
    425 
    426             defaultTableListener = new DefListSelectionListener();
    427             defaultTable.getSelectionModel().addListSelectionListener(defaultTableListener);
    428 
    429             defaultToolbar = new JToolBar(JToolBar.VERTICAL);
    430             defaultToolbar.setFloatable(false);
    431             defaultToolbar.setBorderPainted(false);
    432             defaultToolbar.setOpaque(false);
    433             defaultToolbar.add(new ReloadAction());
    434             add(defaultToolbar, GBC.eol().anchor(GBC.SOUTH).insets(0, 0, 5, 0));
    435 
    436             HtmlPanel help = new HtmlPanel(tr("New default entries can be added in the <a href=\"{0}\">Wiki</a>.",
    437                 Config.getUrls().getJOSMWebsite()+"/wiki/Maps"));
    438             help.enableClickableHyperlinks();
    439             add(help, GBC.eol().insets(10, 0, 0, 0).fill(GBC.HORIZONTAL));
    440 
    441             ActivateAction activate = new ActivateAction();
    442             defaultTable.getSelectionModel().addListSelectionListener(activate);
    443             JButton btnActivate = new JButton(activate);
    444 
    445             middleToolbar = new JToolBar(JToolBar.HORIZONTAL);
    446             middleToolbar.setFloatable(false);
    447             middleToolbar.setBorderPainted(false);
    448             middleToolbar.setOpaque(false);
    449             middleToolbar.add(btnActivate);
    450             add(middleToolbar, GBC.eol().anchor(GBC.CENTER).insets(5, 5, 5, 0));
    451 
    452             add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
    453 
    454             add(new JLabel(tr("Selected entries:")), GBC.eol().insets(5, 0, 0, 0));
    455             JScrollPane scroll = new JScrollPane(activeTable);
    456             add(scroll, GBC.std().fill(GridBagConstraints.BOTH).span(GridBagConstraints.RELATIVE).weight(1.0, 0.4).insets(5, 0, 0, 5));
    457             scroll.setPreferredSize(new Dimension(200, 200));
    458 
    459             activeToolbar = new JToolBar(JToolBar.VERTICAL);
    460             activeToolbar.setFloatable(false);
    461             activeToolbar.setBorderPainted(false);
    462             activeToolbar.setOpaque(false);
    463             activeToolbar.add(new NewEntryAction(ImageryInfo.ImageryType.WMS));
    464             activeToolbar.add(new NewEntryAction(ImageryInfo.ImageryType.TMS));
    465             activeToolbar.add(new NewEntryAction(ImageryInfo.ImageryType.WMTS));
    466             //activeToolbar.add(edit); TODO
    467             activeToolbar.add(remove);
    468             add(activeToolbar, GBC.eol().anchor(GBC.NORTH).insets(0, 0, 5, 5));
    469         }
    470 
    471         // Listener of default providers list selection
    472         private final class DefListSelectionListener implements ListSelectionListener {
    473             // The current drawn rectangles and polygons
    474             private final Map<Integer, MapRectangle> mapRectangles;
    475             private final Map<Integer, List<MapPolygon>> mapPolygons;
    476 
    477             private DefListSelectionListener() {
    478                 this.mapRectangles = new HashMap<>();
    479                 this.mapPolygons = new HashMap<>();
    480             }
    481 
    482             private void clearMap() {
    483                 defaultMap.removeAllMapRectangles();
    484                 defaultMap.removeAllMapPolygons();
    485                 mapRectangles.clear();
    486                 mapPolygons.clear();
    487             }
    488 
    489             @Override
    490             public void valueChanged(ListSelectionEvent e) {
    491                 // First index can be set to -1 when the list is refreshed, so discard all map rectangles and polygons
    492                 if (e.getFirstIndex() == -1) {
    493                     clearMap();
    494                 } else if (!e.getValueIsAdjusting()) {
    495                     // Only process complete (final) selection events
    496                     for (int i = e.getFirstIndex(); i <= e.getLastIndex(); i++) {
    497                         updateBoundsAndShapes(i);
    498                     }
    499                     // If needed, adjust map to show all map rectangles and polygons
    500                     if (!mapRectangles.isEmpty() || !mapPolygons.isEmpty()) {
    501                         defaultMap.setDisplayToFitMapElements(false, true, true);
    502                         defaultMap.zoomOut();
    503                     }
    504                 }
    505             }
    506 
    507             private void updateBoundsAndShapes(int i) {
    508                 ImageryBounds bounds = defaultModel.getRow(i).getBounds();
    509                 if (bounds != null) {
    510                     List<Shape> shapes = bounds.getShapes();
    511                     if (shapes != null && !shapes.isEmpty()) {
    512                         if (defaultTable.getSelectionModel().isSelectedIndex(i)) {
    513                             if (!mapPolygons.containsKey(i)) {
    514                                 List<MapPolygon> list = new ArrayList<>();
    515                                 mapPolygons.put(i, list);
    516                                 // Add new map polygons
    517                                 for (Shape shape : shapes) {
    518                                     MapPolygon polygon = new MapPolygonImpl(shape.getPoints());
    519                                     list.add(polygon);
    520                                     defaultMap.addMapPolygon(polygon);
    521                                 }
    522                             }
    523                         } else if (mapPolygons.containsKey(i)) {
    524                             // Remove previously drawn map polygons
    525                             for (MapPolygon polygon : mapPolygons.get(i)) {
    526                                 defaultMap.removeMapPolygon(polygon);
    527                             }
    528                             mapPolygons.remove(i);
    529                         }
    530                         // Only display bounds when no polygons (shapes) are defined for this provider
    531                     } else {
    532                         if (defaultTable.getSelectionModel().isSelectedIndex(i)) {
    533                             if (!mapRectangles.containsKey(i)) {
    534                                 // Add new map rectangle
    535                                 Coordinate topLeft = new Coordinate(bounds.getMaxLat(), bounds.getMinLon());
    536                                 Coordinate bottomRight = new Coordinate(bounds.getMinLat(), bounds.getMaxLon());
    537                                 MapRectangle rectangle = new MapRectangleImpl(topLeft, bottomRight);
    538                                 mapRectangles.put(i, rectangle);
    539                                 defaultMap.addMapRectangle(rectangle);
    540                             }
    541                         } else if (mapRectangles.containsKey(i)) {
    542                             // Remove previously drawn map rectangle
    543                             defaultMap.removeMapRectangle(mapRectangles.get(i));
    544                             mapRectangles.remove(i);
    545                         }
    546                     }
    547                 }
    548             }
    549         }
    550 
    551         private class NewEntryAction extends AbstractAction {
    552 
    553             private final ImageryInfo.ImageryType type;
    554 
    555             NewEntryAction(ImageryInfo.ImageryType type) {
    556                 putValue(NAME, type.toString());
    557                 putValue(SHORT_DESCRIPTION, tr("Add a new {0} entry by entering the URL", type.toString()));
    558                 String icon = /* ICON(dialogs/) */ "add";
    559                 switch (type) {
    560                 case WMS:
    561                     icon = /* ICON(dialogs/) */ "add_wms";
    562                     break;
    563                 case TMS:
    564                     icon = /* ICON(dialogs/) */ "add_tms";
    565                     break;
    566                 case WMTS:
    567                     icon = /* ICON(dialogs/) */ "add_wmts";
    568                     break;
    569                 default:
    570                     break;
    571                 }
    572                 new ImageProvider("dialogs", icon).getResource().attachImageIcon(this, true);
    573                 this.type = type;
    574             }
    575 
    576             @Override
    577             public void actionPerformed(ActionEvent evt) {
    578                 final AddImageryPanel p;
    579                 switch (type) {
    580                 case WMS:
    581                     p = new AddWMSLayerPanel();
    582                     break;
    583                 case TMS:
    584                     p = new AddTMSLayerPanel();
    585                     break;
    586                 case WMTS:
    587                     p = new AddWMTSLayerPanel();
    588                     break;
    589                 default:
    590                     throw new IllegalStateException("Type " + type + " not supported");
    591                 }
    592 
    593                 final AddImageryDialog addDialog = new AddImageryDialog(gui, p);
    594                 addDialog.showDialog();
    595 
    596                 if (addDialog.getValue() == 1) {
    597                     try {
    598                         activeModel.addRow(p.getImageryInfo());
    599                     } catch (IllegalArgumentException ex) {
    600                         if (ex.getMessage() == null || ex.getMessage().isEmpty())
    601                             throw ex;
    602                         else {
    603                             JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
    604                                     ex.getMessage(), tr("Error"),
    605                                     JOptionPane.ERROR_MESSAGE);
    606                         }
    607                     }
    608                 }
    609             }
    610         }
    611 
    612         private class RemoveEntryAction extends AbstractAction implements ListSelectionListener {
    613 
    614             /**
    615              * Constructs a new {@code RemoveEntryAction}.
    616              */
    617             RemoveEntryAction() {
    618                 putValue(NAME, tr("Remove"));
    619                 putValue(SHORT_DESCRIPTION, tr("Remove entry"));
    620                 new ImageProvider("dialogs", "delete").getResource().attachImageIcon(this, true);
    621                 updateEnabledState();
    622             }
    623 
    624             protected final void updateEnabledState() {
    625                 setEnabled(activeTable.getSelectedRowCount() > 0);
    626             }
    627 
    628             @Override
    629             public void valueChanged(ListSelectionEvent e) {
    630                 updateEnabledState();
    631             }
    632 
    633             @Override
    634             public void actionPerformed(ActionEvent e) {
    635                 Integer i;
    636                 while ((i = activeTable.getSelectedRow()) != -1) {
    637                     activeModel.removeRow(i);
    638                 }
    639             }
    640         }
    641 
    642         private class ActivateAction extends AbstractAction implements ListSelectionListener {
    643 
    644             /**
    645              * Constructs a new {@code ActivateAction}.
    646              */
    647             ActivateAction() {
    648                 putValue(NAME, tr("Activate"));
    649                 putValue(SHORT_DESCRIPTION, tr("Copy selected default entries from the list above into the list below."));
    650                 new ImageProvider("preferences", "activate-down").getResource().attachImageIcon(this, true);
    651             }
    652 
    653             protected void updateEnabledState() {
    654                 setEnabled(defaultTable.getSelectedRowCount() > 0);
    655             }
    656 
    657             @Override
    658             public void valueChanged(ListSelectionEvent e) {
    659                 updateEnabledState();
    660             }
    661 
    662             @Override
    663             public void actionPerformed(ActionEvent e) {
    664                 int[] lines = defaultTable.getSelectedRows();
    665                 if (lines.length == 0) {
    666                     JOptionPane.showMessageDialog(
    667                             gui,
    668                             tr("Please select at least one row to copy."),
    669                             tr("Information"),
    670                             JOptionPane.INFORMATION_MESSAGE);
    671                     return;
    672                 }
    673 
    674                 Set<String> acceptedEulas = new HashSet<>();
    675 
    676                 outer:
    677                 for (int line : lines) {
    678                     ImageryInfo info = defaultModel.getRow(line);
    679 
    680                     // Check if an entry with exactly the same values already exists
    681                     for (int j = 0; j < activeModel.getRowCount(); j++) {
    682                         if (info.equalsBaseValues(activeModel.getRow(j))) {
    683                             // Select the already existing row so the user has
    684                             // some feedback in case an entry exists
    685                             activeTable.getSelectionModel().setSelectionInterval(j, j);
    686                             activeTable.scrollRectToVisible(activeTable.getCellRect(j, 0, true));
    687                             continue outer;
    688                         }
    689                     }
    690 
    691                     String eulaURL = info.getEulaAcceptanceRequired();
    692                     // If set and not already accepted, ask for EULA acceptance
    693                     if (eulaURL != null && !acceptedEulas.contains(eulaURL)) {
    694                         if (confirmEulaAcceptance(gui, eulaURL)) {
    695                             acceptedEulas.add(eulaURL);
    696                         } else {
    697                             continue outer;
    698                         }
    699                     }
    700 
    701                     activeModel.addRow(new ImageryInfo(info));
    702                     int lastLine = activeModel.getRowCount() - 1;
    703                     activeTable.getSelectionModel().setSelectionInterval(lastLine, lastLine);
    704                     activeTable.scrollRectToVisible(activeTable.getCellRect(lastLine, 0, true));
    705                 }
    706             }
    707         }
    708 
    709         private class ReloadAction extends AbstractAction {
    710 
    711             /**
    712              * Constructs a new {@code ReloadAction}.
    713              */
    714             ReloadAction() {
    715                 putValue(SHORT_DESCRIPTION, tr("Update default entries"));
    716                 new ImageProvider("dialogs", "refresh").getResource().attachImageIcon(this, true);
    717             }
    718 
    719             @Override
    720             public void actionPerformed(ActionEvent evt) {
    721                 layerInfo.loadDefaults(true, MainApplication.worker, false);
    722                 defaultModel.fireTableDataChanged();
    723                 defaultTable.getSelectionModel().clearSelection();
    724                 defaultTableListener.clearMap();
    725                 /* loading new file may change active layers */
    726                 activeModel.fireTableDataChanged();
    727             }
    728         }
    729 
    730         /**
    731          * The table model for imagery layer list
    732          */
    733         public class ImageryLayerTableModel extends DefaultTableModel {
    734             /**
    735              * Constructs a new {@code ImageryLayerTableModel}.
    736              */
    737             public ImageryLayerTableModel() {
    738                 setColumnIdentifiers(new String[] {tr("Menu Name"), tr("Imagery URL")});
    739             }
    740 
    741             /**
    742              * Returns the imagery info at the given row number.
    743              * @param row The row number
    744              * @return The imagery info at the given row number
    745              */
    746             public ImageryInfo getRow(int row) {
    747                 return layerInfo.getLayers().get(row);
    748             }
    749 
    750             /**
    751              * Adds a new imagery info as the last row.
    752              * @param i The imagery info to add
    753              */
    754             public void addRow(ImageryInfo i) {
    755                 layerInfo.add(i);
    756                 int p = getRowCount() - 1;
    757                 fireTableRowsInserted(p, p);
    758             }
    759 
    760             @Override
    761             public void removeRow(int i) {
    762                 layerInfo.remove(getRow(i));
    763                 fireTableRowsDeleted(i, i);
    764             }
    765 
    766             @Override
    767             public int getRowCount() {
    768                 return layerInfo.getLayers().size();
    769             }
    770 
    771             @Override
    772             public Object getValueAt(int row, int column) {
    773                 ImageryInfo info = layerInfo.getLayers().get(row);
    774                 switch (column) {
    775                 case 0:
    776                     return info.getName();
    777                 case 1:
    778                     return info.getExtendedUrl();
    779                 default:
    780                     throw new ArrayIndexOutOfBoundsException(Integer.toString(column));
    781                 }
    782             }
    783 
    784             @Override
    785             public void setValueAt(Object o, int row, int column) {
    786                 if (layerInfo.getLayers().size() <= row) return;
    787                 ImageryInfo info = layerInfo.getLayers().get(row);
    788                 switch (column) {
    789                 case 0:
    790                     info.setName((String) o);
    791                     info.clearId();
    792                     break;
    793                 case 1:
    794                     info.setExtendedUrl((String) o);
    795                     info.clearId();
    796                     break;
    797                 default:
    798                     throw new ArrayIndexOutOfBoundsException(Integer.toString(column));
    799                 }
    800             }
    801         }
    802 
    803         /**
    804          * The table model for the default imagery layer list
    805          */
    806         public class ImageryDefaultLayerTableModel extends DefaultTableModel {
    807             /**
    808              * Constructs a new {@code ImageryDefaultLayerTableModel}.
    809              */
    810             public ImageryDefaultLayerTableModel() {
    811                 setColumnIdentifiers(new String[]{"", "", tr("Menu Name (Default)"), tr("Imagery URL (Default)")});
    812             }
    813 
    814             /**
    815              * Returns the imagery info at the given row number.
    816              * @param row The row number
    817              * @return The imagery info at the given row number
    818              */
    819             public ImageryInfo getRow(int row) {
    820                 return layerInfo.getAllDefaultLayers().get(row);
    821             }
    822 
    823             @Override
    824             public int getRowCount() {
    825                 return layerInfo.getAllDefaultLayers().size();
    826             }
    827 
    828             @Override
    829             public Class<?> getColumnClass(int columnIndex) {
    830                 return columnIndex == 0 ? ImageIcon.class : super.getColumnClass(columnIndex);
    831             }
    832 
    833             @Override
    834             public Object getValueAt(int row, int column) {
    835                 ImageryInfo info = layerInfo.getAllDefaultLayers().get(row);
    836                 switch (column) {
    837                 case 0:
    838                     return Optional.ofNullable(info.getImageryCategory()).orElse(ImageryCategory.OTHER);
    839                 case 1:
    840                     return info.getCountryCode();
    841                 case 2:
    842                     return info;
    843                 case 3:
    844                     return info.getExtendedUrl();
    845                 }
    846                 return null;
    847             }
    848 
    849             @Override
    850             public boolean isCellEditable(int row, int column) {
    851                 return false;
    852             }
    853         }
    854 
    855         private static boolean confirmEulaAcceptance(PreferenceTabbedPane gui, String eulaUrl) {
    856             URL url;
    857             try {
    858                 url = new URL(eulaUrl.replaceAll("\\{lang\\}", LanguageInfo.getWikiLanguagePrefix()));
    859                 JosmEditorPane htmlPane;
    860                 try {
    861                     htmlPane = new JosmEditorPane(url);
    862                 } catch (IOException e1) {
    863                     Logging.trace(e1);
    864                     // give a second chance with a default Locale 'en'
    865                     try {
    866                         url = new URL(eulaUrl.replaceAll("\\{lang\\}", ""));
    867                         htmlPane = new JosmEditorPane(url);
    868                     } catch (IOException e2) {
    869                         Logging.debug(e2);
    870                         JOptionPane.showMessageDialog(gui, tr("EULA license URL not available: {0}", eulaUrl));
    871                         return false;
    872                     }
    873                 }
    874                 Box box = Box.createVerticalBox();
    875                 htmlPane.setEditable(false);
    876                 JScrollPane scrollPane = new JScrollPane(htmlPane);
    877                 scrollPane.setPreferredSize(new Dimension(400, 400));
    878                 box.add(scrollPane);
    879                 int option = JOptionPane.showConfirmDialog(MainApplication.getMainFrame(), box, tr("Please abort if you are not sure"),
    880                         JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
    881                 if (option == JOptionPane.YES_OPTION)
    882                     return true;
    883             } catch (MalformedURLException e2) {
    884                 JOptionPane.showMessageDialog(gui, tr("Malformed URL for the EULA licence: {0}", eulaUrl));
    885             }
    886             return false;
    887         }
    888182    }
    889183
Note: See TracChangeset for help on using the changeset viewer.