source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java@ 10853

Last change on this file since 10853 was 10853, checked in by Don-vip, 8 years ago

see #13309 - fix most of deprecation warnings

  • Property svn:eol-style set to native
File size: 37.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.imagery;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.Color;
8import java.awt.Component;
9import java.awt.Dimension;
10import java.awt.FlowLayout;
11import java.awt.Font;
12import java.awt.GraphicsEnvironment;
13import java.awt.GridBagConstraints;
14import java.awt.GridBagLayout;
15import java.awt.event.ActionEvent;
16import java.awt.event.MouseEvent;
17import java.io.IOException;
18import java.net.MalformedURLException;
19import java.net.URL;
20import java.util.ArrayList;
21import java.util.HashMap;
22import java.util.HashSet;
23import java.util.List;
24import java.util.Map;
25import java.util.Set;
26
27import javax.swing.AbstractAction;
28import javax.swing.BorderFactory;
29import javax.swing.Box;
30import javax.swing.JButton;
31import javax.swing.JLabel;
32import javax.swing.JOptionPane;
33import javax.swing.JPanel;
34import javax.swing.JScrollPane;
35import javax.swing.JSeparator;
36import javax.swing.JTabbedPane;
37import javax.swing.JTable;
38import javax.swing.JToolBar;
39import javax.swing.UIManager;
40import javax.swing.event.ListSelectionEvent;
41import javax.swing.event.ListSelectionListener;
42import javax.swing.table.DefaultTableCellRenderer;
43import javax.swing.table.DefaultTableModel;
44import javax.swing.table.TableColumnModel;
45
46import org.openstreetmap.gui.jmapviewer.Coordinate;
47import org.openstreetmap.gui.jmapviewer.JMapViewer;
48import org.openstreetmap.gui.jmapviewer.MapPolygonImpl;
49import org.openstreetmap.gui.jmapviewer.MapRectangleImpl;
50import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
51import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
52import org.openstreetmap.josm.Main;
53import org.openstreetmap.josm.data.imagery.ImageryInfo;
54import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds;
55import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
56import org.openstreetmap.josm.data.imagery.OffsetBookmark;
57import org.openstreetmap.josm.data.imagery.Shape;
58import org.openstreetmap.josm.data.preferences.ColorProperty;
59import org.openstreetmap.josm.gui.download.DownloadDialog;
60import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
61import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
62import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
63import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
64import org.openstreetmap.josm.gui.util.GuiHelper;
65import org.openstreetmap.josm.gui.widgets.JosmEditorPane;
66import org.openstreetmap.josm.tools.GBC;
67import org.openstreetmap.josm.tools.ImageProvider;
68import org.openstreetmap.josm.tools.LanguageInfo;
69
70/**
71 * Imagery preferences, including imagery providers, settings and offsets.
72 * @since 3715
73 */
74public final class ImageryPreference extends DefaultTabPreferenceSetting {
75
76 private ImageryProvidersPanel imageryProviders;
77 private ImageryLayerInfo layerInfo;
78
79 private final CommonSettingsPanel commonSettings = new CommonSettingsPanel();
80 private final WMSSettingsPanel wmsSettings = new WMSSettingsPanel();
81 private final TMSSettingsPanel tmsSettings = new TMSSettingsPanel();
82
83 /**
84 * Factory used to create a new {@code ImageryPreference}.
85 */
86 public static class Factory implements PreferenceSettingFactory {
87 @Override
88 public PreferenceSetting createPreferenceSetting() {
89 return new ImageryPreference();
90 }
91 }
92
93 private ImageryPreference() {
94 super(/* ICON(preferences/) */ "imagery", tr("Imagery Preferences"), tr("Modify list of imagery layers displayed in the Imagery menu"),
95 false, new JTabbedPane());
96 }
97
98 private static void addSettingsSection(final JPanel p, String name, JPanel section) {
99 addSettingsSection(p, name, section, GBC.eol());
100 }
101
102 private static void addSettingsSection(final JPanel p, String name, JPanel section, GBC gbc) {
103 final JLabel lbl = new JLabel(name);
104 lbl.setFont(lbl.getFont().deriveFont(Font.BOLD));
105 lbl.setLabelFor(section);
106 p.add(lbl, GBC.std());
107 p.add(new JSeparator(), GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 0));
108 p.add(section, gbc.insets(20, 5, 0, 10));
109 }
110
111 private Component buildSettingsPanel() {
112 final JPanel p = new JPanel(new GridBagLayout());
113 p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
114
115 addSettingsSection(p, tr("Common Settings"), commonSettings);
116 addSettingsSection(p, tr("WMS Settings"), wmsSettings,
117 GBC.eol().fill(GBC.HORIZONTAL));
118 addSettingsSection(p, tr("TMS Settings"), tmsSettings,
119 GBC.eol().fill(GBC.HORIZONTAL));
120
121 p.add(new JPanel(), GBC.eol().fill(GBC.BOTH));
122 return GuiHelper.setDefaultIncrement(new JScrollPane(p));
123 }
124
125 @Override
126 public void addGui(final PreferenceTabbedPane gui) {
127 JPanel p = gui.createPreferenceTab(this);
128 JTabbedPane pane = getTabPane();
129 layerInfo = new ImageryLayerInfo(ImageryLayerInfo.instance);
130 imageryProviders = new ImageryProvidersPanel(gui, layerInfo);
131 pane.addTab(tr("Imagery providers"), imageryProviders);
132 pane.addTab(tr("Settings"), buildSettingsPanel());
133 pane.addTab(tr("Offset bookmarks"), new OffsetBookmarksPanel(gui));
134 pane.addTab(tr("Cache contents"), new CacheContentsPanel());
135 loadSettings();
136 p.add(pane, GBC.std().fill(GBC.BOTH));
137 }
138
139 /**
140 * Returns the imagery providers panel.
141 * @return The imagery providers panel.
142 */
143 public ImageryProvidersPanel getProvidersPanel() {
144 return imageryProviders;
145 }
146
147 private void loadSettings() {
148 commonSettings.loadSettings();
149 wmsSettings.loadSettings();
150 tmsSettings.loadSettings();
151 }
152
153 @Override
154 public boolean ok() {
155 layerInfo.save();
156 ImageryLayerInfo.instance.clear();
157 ImageryLayerInfo.instance.load(false);
158 Main.main.menu.imageryMenu.refreshOffsetMenu();
159 OffsetBookmark.saveBookmarks();
160
161 if (!GraphicsEnvironment.isHeadless()) {
162 DownloadDialog.getInstance().refreshTileSources();
163 }
164
165 boolean commonRestartRequired = commonSettings.saveSettings();
166 boolean wmsRestartRequired = wmsSettings.saveSettings();
167 boolean tmsRestartRequired = tmsSettings.saveSettings();
168
169 return commonRestartRequired || wmsRestartRequired || tmsRestartRequired;
170 }
171
172 /**
173 * Updates a server URL in the preferences dialog. Used by plugins.
174 *
175 * @param server
176 * The server name
177 * @param url
178 * The server URL
179 */
180 public void setServerUrl(String server, String url) {
181 for (int i = 0; i < imageryProviders.activeModel.getRowCount(); i++) {
182 if (server.equals(imageryProviders.activeModel.getValueAt(i, 0).toString())) {
183 imageryProviders.activeModel.setValueAt(url, i, 1);
184 return;
185 }
186 }
187 imageryProviders.activeModel.addRow(new String[] {server, url});
188 }
189
190 /**
191 * Gets a server URL in the preferences dialog. Used by plugins.
192 *
193 * @param server The server name
194 * @return The server URL
195 */
196 public String getServerUrl(String server) {
197 for (int i = 0; i < imageryProviders.activeModel.getRowCount(); i++) {
198 if (server.equals(imageryProviders.activeModel.getValueAt(i, 0).toString()))
199 return imageryProviders.activeModel.getValueAt(i, 1).toString();
200 }
201 return null;
202 }
203
204 /**
205 * A panel displaying imagery providers.
206 */
207 public static class ImageryProvidersPanel extends JPanel {
208 // Public JTables and JMapViewer
209 /** The table of active providers **/
210 public final JTable activeTable;
211 /** The table of default providers **/
212 public final JTable defaultTable;
213 /** The selection listener synchronizing map display with table of default providers **/
214 private final transient DefListSelectionListener defaultTableListener;
215 /** The map displaying imagery bounds of selected default providers **/
216 public final JMapViewer defaultMap;
217
218 // Public models
219 /** The model of active providers **/
220 public final ImageryLayerTableModel activeModel;
221 /** The model of default providers **/
222 public final ImageryDefaultLayerTableModel defaultModel;
223
224 // Public JToolbars
225 /** The toolbar on the right of active providers **/
226 public final JToolBar activeToolbar;
227 /** The toolbar on the middle of the panel **/
228 public final JToolBar middleToolbar;
229 /** The toolbar on the right of default providers **/
230 public final JToolBar defaultToolbar;
231
232 // Private members
233 private final PreferenceTabbedPane gui;
234 private final transient ImageryLayerInfo layerInfo;
235
236 /**
237 * class to render the URL information of Imagery source
238 * @since 8065
239 */
240 private static class ImageryURLTableCellRenderer extends DefaultTableCellRenderer {
241
242 private static final ColorProperty IMAGERY_BACKGROUND_COLOR = new ColorProperty(
243 marktr("Imagery Background: Default"),
244 new Color(200, 255, 200));
245
246 private final transient List<ImageryInfo> layers;
247
248 ImageryURLTableCellRenderer(List<ImageryInfo> layers) {
249 this.layers = layers;
250 }
251
252 @Override
253 public Component getTableCellRendererComponent(JTable table, Object value, boolean
254 isSelected, boolean hasFocus, int row, int column) {
255 JLabel label = (JLabel) super.getTableCellRendererComponent(
256 table, value, isSelected, hasFocus, row, column);
257 GuiHelper.setBackgroundReadable(label, UIManager.getColor("Table.background"));
258 if (value != null) { // Fix #8159
259 String t = value.toString();
260 for (ImageryInfo l : layers) {
261 if (l.getExtendedUrl().equals(t)) {
262 GuiHelper.setBackgroundReadable(label, IMAGERY_BACKGROUND_COLOR.get());
263 break;
264 }
265 }
266 label.setToolTipText((String) value);
267 }
268 return label;
269 }
270 }
271
272 /**
273 * class to render the name information of Imagery source
274 * @since 8064
275 */
276 private static class ImageryNameTableCellRenderer extends DefaultTableCellRenderer {
277 @Override
278 public Component getTableCellRendererComponent(JTable table, Object value, boolean
279 isSelected, boolean hasFocus, int row, int column) {
280 ImageryInfo info = (ImageryInfo) value;
281 JLabel label = (JLabel) super.getTableCellRendererComponent(
282 table, info == null ? null : info.getName(), isSelected, hasFocus, row, column);
283 GuiHelper.setBackgroundReadable(label, UIManager.getColor("Table.background"));
284 if (info != null) {
285 label.setToolTipText(info.getToolTipText());
286 }
287 return label;
288 }
289 }
290
291 /**
292 * Constructs a new {@code ImageryProvidersPanel}.
293 * @param gui The parent preference tab pane
294 * @param layerInfoArg The list of imagery entries to display
295 */
296 public ImageryProvidersPanel(final PreferenceTabbedPane gui, ImageryLayerInfo layerInfoArg) {
297 super(new GridBagLayout());
298 this.gui = gui;
299 this.layerInfo = layerInfoArg;
300 this.activeModel = new ImageryLayerTableModel();
301
302 activeTable = new JTable(activeModel) {
303 @Override
304 public String getToolTipText(MouseEvent e) {
305 java.awt.Point p = e.getPoint();
306 return activeModel.getValueAt(rowAtPoint(p), columnAtPoint(p)).toString();
307 }
308 };
309 activeTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
310
311 defaultModel = new ImageryDefaultLayerTableModel();
312 defaultTable = new JTable(defaultModel);
313
314 defaultModel.addTableModelListener(e -> activeTable.repaint());
315 activeModel.addTableModelListener(e -> defaultTable.repaint());
316
317 TableColumnModel mod = defaultTable.getColumnModel();
318 mod.getColumn(2).setPreferredWidth(800);
319 mod.getColumn(2).setCellRenderer(new ImageryURLTableCellRenderer(layerInfo.getLayers()));
320 mod.getColumn(1).setPreferredWidth(400);
321 mod.getColumn(1).setCellRenderer(new ImageryNameTableCellRenderer());
322 mod.getColumn(0).setPreferredWidth(50);
323
324 mod = activeTable.getColumnModel();
325 mod.getColumn(1).setPreferredWidth(800);
326 mod.getColumn(1).setCellRenderer(new ImageryURLTableCellRenderer(layerInfo.getDefaultLayers()));
327 mod.getColumn(0).setPreferredWidth(200);
328
329 RemoveEntryAction remove = new RemoveEntryAction();
330 activeTable.getSelectionModel().addListSelectionListener(remove);
331
332 add(new JLabel(tr("Available default entries:")), GBC.eol().insets(5, 5, 0, 0));
333 // Add default item list
334 JScrollPane scrolldef = new JScrollPane(defaultTable);
335 scrolldef.setPreferredSize(new Dimension(200, 200));
336 add(scrolldef, GBC.std().insets(0, 5, 0, 0).fill(GridBagConstraints.BOTH).weight(1.0, 0.6).insets(5, 0, 0, 0));
337
338 // Add default item map
339 defaultMap = new JMapViewer();
340 defaultMap.setZoomContolsVisible(false);
341 defaultMap.setMinimumSize(new Dimension(100, 200));
342 add(defaultMap, GBC.std().insets(5, 5, 0, 0).fill(GridBagConstraints.BOTH).weight(0.33, 0.6).insets(5, 0, 0, 0));
343
344 defaultTableListener = new DefListSelectionListener();
345 defaultTable.getSelectionModel().addListSelectionListener(defaultTableListener);
346
347 defaultToolbar = new JToolBar(JToolBar.VERTICAL);
348 defaultToolbar.setFloatable(false);
349 defaultToolbar.setBorderPainted(false);
350 defaultToolbar.setOpaque(false);
351 defaultToolbar.add(new ReloadAction());
352 add(defaultToolbar, GBC.eol().anchor(GBC.SOUTH).insets(0, 0, 5, 0));
353
354 ActivateAction activate = new ActivateAction();
355 defaultTable.getSelectionModel().addListSelectionListener(activate);
356 JButton btnActivate = new JButton(activate);
357
358 middleToolbar = new JToolBar(JToolBar.HORIZONTAL);
359 middleToolbar.setFloatable(false);
360 middleToolbar.setBorderPainted(false);
361 middleToolbar.setOpaque(false);
362 middleToolbar.add(btnActivate);
363 add(middleToolbar, GBC.eol().anchor(GBC.CENTER).insets(5, 15, 5, 0));
364
365 add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
366
367 add(new JLabel(tr("Selected entries:")), GBC.eol().insets(5, 0, 0, 0));
368 JScrollPane scroll = new JScrollPane(activeTable);
369 add(scroll, GBC.std().fill(GridBagConstraints.BOTH).span(GridBagConstraints.RELATIVE).weight(1.0, 0.4).insets(5, 0, 0, 5));
370 scroll.setPreferredSize(new Dimension(200, 200));
371
372 activeToolbar = new JToolBar(JToolBar.VERTICAL);
373 activeToolbar.setFloatable(false);
374 activeToolbar.setBorderPainted(false);
375 activeToolbar.setOpaque(false);
376 activeToolbar.add(new NewEntryAction(ImageryInfo.ImageryType.WMS));
377 activeToolbar.add(new NewEntryAction(ImageryInfo.ImageryType.TMS));
378 activeToolbar.add(new NewEntryAction(ImageryInfo.ImageryType.WMTS));
379 //activeToolbar.add(edit); TODO
380 activeToolbar.add(remove);
381 add(activeToolbar, GBC.eol().anchor(GBC.NORTH).insets(0, 0, 5, 5));
382 }
383
384 // Listener of default providers list selection
385 private final class DefListSelectionListener implements ListSelectionListener {
386 // The current drawn rectangles and polygons
387 private final Map<Integer, MapRectangle> mapRectangles;
388 private final Map<Integer, List<MapPolygon>> mapPolygons;
389
390 private DefListSelectionListener() {
391 this.mapRectangles = new HashMap<>();
392 this.mapPolygons = new HashMap<>();
393 }
394
395 private void clearMap() {
396 defaultMap.removeAllMapRectangles();
397 defaultMap.removeAllMapPolygons();
398 mapRectangles.clear();
399 mapPolygons.clear();
400 }
401
402 @Override
403 public void valueChanged(ListSelectionEvent e) {
404 // First index can be set to -1 when the list is refreshed, so discard all map rectangles and polygons
405 if (e.getFirstIndex() == -1) {
406 clearMap();
407 } else if (!e.getValueIsAdjusting()) {
408 // Only process complete (final) selection events
409 for (int i = e.getFirstIndex(); i <= e.getLastIndex(); i++) {
410 updateBoundsAndShapes(i);
411 }
412 // If needed, adjust map to show all map rectangles and polygons
413 if (!mapRectangles.isEmpty() || !mapPolygons.isEmpty()) {
414 defaultMap.setDisplayToFitMapElements(false, true, true);
415 defaultMap.zoomOut();
416 }
417 }
418 }
419
420 private void updateBoundsAndShapes(int i) {
421 ImageryBounds bounds = defaultModel.getRow(i).getBounds();
422 if (bounds != null) {
423 List<Shape> shapes = bounds.getShapes();
424 if (shapes != null && !shapes.isEmpty()) {
425 if (defaultTable.getSelectionModel().isSelectedIndex(i)) {
426 if (!mapPolygons.containsKey(i)) {
427 List<MapPolygon> list = new ArrayList<>();
428 mapPolygons.put(i, list);
429 // Add new map polygons
430 for (Shape shape : shapes) {
431 MapPolygon polygon = new MapPolygonImpl(shape.getPoints());
432 list.add(polygon);
433 defaultMap.addMapPolygon(polygon);
434 }
435 }
436 } else if (mapPolygons.containsKey(i)) {
437 // Remove previously drawn map polygons
438 for (MapPolygon polygon : mapPolygons.get(i)) {
439 defaultMap.removeMapPolygon(polygon);
440 }
441 mapPolygons.remove(i);
442 }
443 // Only display bounds when no polygons (shapes) are defined for this provider
444 } else {
445 if (defaultTable.getSelectionModel().isSelectedIndex(i)) {
446 if (!mapRectangles.containsKey(i)) {
447 // Add new map rectangle
448 Coordinate topLeft = new Coordinate(bounds.getMaxLat(), bounds.getMinLon());
449 Coordinate bottomRight = new Coordinate(bounds.getMinLat(), bounds.getMaxLon());
450 MapRectangle rectangle = new MapRectangleImpl(topLeft, bottomRight);
451 mapRectangles.put(i, rectangle);
452 defaultMap.addMapRectangle(rectangle);
453 }
454 } else if (mapRectangles.containsKey(i)) {
455 // Remove previously drawn map rectangle
456 defaultMap.removeMapRectangle(mapRectangles.get(i));
457 mapRectangles.remove(i);
458 }
459 }
460 }
461 }
462 }
463
464 private class NewEntryAction extends AbstractAction {
465
466 private final ImageryInfo.ImageryType type;
467
468 NewEntryAction(ImageryInfo.ImageryType type) {
469 putValue(NAME, type.toString());
470 putValue(SHORT_DESCRIPTION, tr("Add a new {0} entry by entering the URL", type.toString()));
471 String icon = /* ICON(dialogs/) */ "add";
472 switch (type) {
473 case WMS:
474 icon = /* ICON(dialogs/) */ "add_wms";
475 break;
476 case TMS:
477 icon = /* ICON(dialogs/) */ "add_tms";
478 break;
479 case WMTS:
480 icon = /* ICON(dialogs/) */ "add_wmts";
481 break;
482 default:
483 break;
484 }
485 putValue(SMALL_ICON, ImageProvider.get("dialogs", icon));
486 this.type = type;
487 }
488
489 @Override
490 public void actionPerformed(ActionEvent evt) {
491 final AddImageryPanel p;
492 switch (type) {
493 case WMS:
494 p = new AddWMSLayerPanel();
495 break;
496 case TMS:
497 p = new AddTMSLayerPanel();
498 break;
499 case WMTS:
500 p = new AddWMTSLayerPanel();
501 break;
502 default:
503 throw new IllegalStateException("Type " + type + " not supported");
504 }
505
506 final AddImageryDialog addDialog = new AddImageryDialog(gui, p);
507 addDialog.showDialog();
508
509 if (addDialog.getValue() == 1) {
510 try {
511 activeModel.addRow(p.getImageryInfo());
512 } catch (IllegalArgumentException ex) {
513 if (ex.getMessage() == null || ex.getMessage().isEmpty())
514 throw ex;
515 else {
516 JOptionPane.showMessageDialog(Main.parent,
517 ex.getMessage(), tr("Error"),
518 JOptionPane.ERROR_MESSAGE);
519 }
520 }
521 }
522 }
523 }
524
525 private class RemoveEntryAction extends AbstractAction implements ListSelectionListener {
526
527 /**
528 * Constructs a new {@code RemoveEntryAction}.
529 */
530 RemoveEntryAction() {
531 putValue(NAME, tr("Remove"));
532 putValue(SHORT_DESCRIPTION, tr("Remove entry"));
533 putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
534 updateEnabledState();
535 }
536
537 protected final void updateEnabledState() {
538 setEnabled(activeTable.getSelectedRowCount() > 0);
539 }
540
541 @Override
542 public void valueChanged(ListSelectionEvent e) {
543 updateEnabledState();
544 }
545
546 @Override
547 public void actionPerformed(ActionEvent e) {
548 Integer i;
549 while ((i = activeTable.getSelectedRow()) != -1) {
550 activeModel.removeRow(i);
551 }
552 }
553 }
554
555 private class ActivateAction extends AbstractAction implements ListSelectionListener {
556
557 /**
558 * Constructs a new {@code ActivateAction}.
559 */
560 ActivateAction() {
561 putValue(NAME, tr("Activate"));
562 putValue(SHORT_DESCRIPTION, tr("copy selected defaults"));
563 putValue(SMALL_ICON, ImageProvider.get("preferences", "activate-down"));
564 }
565
566 protected void updateEnabledState() {
567 setEnabled(defaultTable.getSelectedRowCount() > 0);
568 }
569
570 @Override
571 public void valueChanged(ListSelectionEvent e) {
572 updateEnabledState();
573 }
574
575 @Override
576 public void actionPerformed(ActionEvent e) {
577 int[] lines = defaultTable.getSelectedRows();
578 if (lines.length == 0) {
579 JOptionPane.showMessageDialog(
580 gui,
581 tr("Please select at least one row to copy."),
582 tr("Information"),
583 JOptionPane.INFORMATION_MESSAGE);
584 return;
585 }
586
587 Set<String> acceptedEulas = new HashSet<>();
588
589 outer:
590 for (int line : lines) {
591 ImageryInfo info = defaultModel.getRow(line);
592
593 // Check if an entry with exactly the same values already exists
594 for (int j = 0; j < activeModel.getRowCount(); j++) {
595 if (info.equalsBaseValues(activeModel.getRow(j))) {
596 // Select the already existing row so the user has
597 // some feedback in case an entry exists
598 activeTable.getSelectionModel().setSelectionInterval(j, j);
599 activeTable.scrollRectToVisible(activeTable.getCellRect(j, 0, true));
600 continue outer;
601 }
602 }
603
604 String eulaURL = info.getEulaAcceptanceRequired();
605 // If set and not already accepted, ask for EULA acceptance
606 if (eulaURL != null && !acceptedEulas.contains(eulaURL)) {
607 if (confirmEulaAcceptance(gui, eulaURL)) {
608 acceptedEulas.add(eulaURL);
609 } else {
610 continue outer;
611 }
612 }
613
614 activeModel.addRow(new ImageryInfo(info));
615 int lastLine = activeModel.getRowCount() - 1;
616 activeTable.getSelectionModel().setSelectionInterval(lastLine, lastLine);
617 activeTable.scrollRectToVisible(activeTable.getCellRect(lastLine, 0, true));
618 }
619 }
620 }
621
622 private class ReloadAction extends AbstractAction {
623
624 /**
625 * Constructs a new {@code ReloadAction}.
626 */
627 ReloadAction() {
628 putValue(SHORT_DESCRIPTION, tr("Update default entries"));
629 putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
630 }
631
632 @Override
633 public void actionPerformed(ActionEvent evt) {
634 layerInfo.loadDefaults(true, false, false);
635 defaultModel.fireTableDataChanged();
636 defaultTable.getSelectionModel().clearSelection();
637 defaultTableListener.clearMap();
638 /* loading new file may change active layers */
639 activeModel.fireTableDataChanged();
640 }
641 }
642
643 /**
644 * The table model for imagery layer list
645 */
646 public class ImageryLayerTableModel extends DefaultTableModel {
647 /**
648 * Constructs a new {@code ImageryLayerTableModel}.
649 */
650 public ImageryLayerTableModel() {
651 setColumnIdentifiers(new String[] {tr("Menu Name"), tr("Imagery URL")});
652 }
653
654 /**
655 * Returns the imagery info at the given row number.
656 * @param row The row number
657 * @return The imagery info at the given row number
658 */
659 public ImageryInfo getRow(int row) {
660 return layerInfo.getLayers().get(row);
661 }
662
663 /**
664 * Adds a new imagery info as the last row.
665 * @param i The imagery info to add
666 */
667 public void addRow(ImageryInfo i) {
668 layerInfo.add(i);
669 int p = getRowCount() - 1;
670 fireTableRowsInserted(p, p);
671 }
672
673 @Override
674 public void removeRow(int i) {
675 layerInfo.remove(getRow(i));
676 fireTableRowsDeleted(i, i);
677 }
678
679 @Override
680 public int getRowCount() {
681 return layerInfo.getLayers().size();
682 }
683
684 @Override
685 public Object getValueAt(int row, int column) {
686 ImageryInfo info = layerInfo.getLayers().get(row);
687 switch (column) {
688 case 0:
689 return info.getName();
690 case 1:
691 return info.getExtendedUrl();
692 default:
693 throw new ArrayIndexOutOfBoundsException();
694 }
695 }
696
697 @Override
698 public void setValueAt(Object o, int row, int column) {
699 if (layerInfo.getLayers().size() <= row) return;
700 ImageryInfo info = layerInfo.getLayers().get(row);
701 switch (column) {
702 case 0:
703 info.setName((String) o);
704 info.clearId();
705 break;
706 case 1:
707 info.setExtendedUrl((String) o);
708 info.clearId();
709 break;
710 default:
711 throw new ArrayIndexOutOfBoundsException();
712 }
713 }
714 }
715
716 /**
717 * The table model for the default imagery layer list
718 */
719 public class ImageryDefaultLayerTableModel extends DefaultTableModel {
720 /**
721 * Constructs a new {@code ImageryDefaultLayerTableModel}.
722 */
723 public ImageryDefaultLayerTableModel() {
724 setColumnIdentifiers(new String[]{"", tr("Menu Name (Default)"), tr("Imagery URL (Default)")});
725 }
726
727 /**
728 * Returns the imagery info at the given row number.
729 * @param row The row number
730 * @return The imagery info at the given row number
731 */
732 public ImageryInfo getRow(int row) {
733 return layerInfo.getDefaultLayers().get(row);
734 }
735
736 @Override
737 public int getRowCount() {
738 return layerInfo.getDefaultLayers().size();
739 }
740
741 @Override
742 public Object getValueAt(int row, int column) {
743 ImageryInfo info = layerInfo.getDefaultLayers().get(row);
744 switch (column) {
745 case 0:
746 return info.getCountryCode();
747 case 1:
748 return info;
749 case 2:
750 return info.getExtendedUrl();
751 }
752 return null;
753 }
754
755 @Override
756 public boolean isCellEditable(int row, int column) {
757 return false;
758 }
759 }
760
761 private static boolean confirmEulaAcceptance(PreferenceTabbedPane gui, String eulaUrl) {
762 URL url = null;
763 try {
764 url = new URL(eulaUrl.replaceAll("\\{lang\\}", LanguageInfo.getWikiLanguagePrefix()));
765 JosmEditorPane htmlPane = null;
766 try {
767 htmlPane = new JosmEditorPane(url);
768 } catch (IOException e1) {
769 Main.trace(e1);
770 // give a second chance with a default Locale 'en'
771 try {
772 url = new URL(eulaUrl.replaceAll("\\{lang\\}", ""));
773 htmlPane = new JosmEditorPane(url);
774 } catch (IOException e2) {
775 Main.debug(e2);
776 JOptionPane.showMessageDialog(gui, tr("EULA license URL not available: {0}", eulaUrl));
777 return false;
778 }
779 }
780 Box box = Box.createVerticalBox();
781 htmlPane.setEditable(false);
782 JScrollPane scrollPane = new JScrollPane(htmlPane);
783 scrollPane.setPreferredSize(new Dimension(400, 400));
784 box.add(scrollPane);
785 int option = JOptionPane.showConfirmDialog(Main.parent, box, tr("Please abort if you are not sure"),
786 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
787 if (option == JOptionPane.YES_OPTION)
788 return true;
789 } catch (MalformedURLException e2) {
790 JOptionPane.showMessageDialog(gui, tr("Malformed URL for the EULA licence: {0}", eulaUrl));
791 }
792 return false;
793 }
794 }
795
796 static class OffsetBookmarksPanel extends JPanel {
797 private final transient List<OffsetBookmark> bookmarks = OffsetBookmark.allBookmarks;
798 private final OffsetsBookmarksModel model = new OffsetsBookmarksModel();
799
800 /**
801 * Constructs a new {@code OffsetBookmarksPanel}.
802 * @param gui the preferences tab pane
803 */
804 OffsetBookmarksPanel(final PreferenceTabbedPane gui) {
805 super(new GridBagLayout());
806 final JTable list = new JTable(model) {
807 @Override
808 public String getToolTipText(MouseEvent e) {
809 java.awt.Point p = e.getPoint();
810 return model.getValueAt(rowAtPoint(p), columnAtPoint(p)).toString();
811 }
812 };
813 JScrollPane scroll = new JScrollPane(list);
814 add(scroll, GBC.eol().fill(GridBagConstraints.BOTH));
815 scroll.setPreferredSize(new Dimension(200, 200));
816
817 TableColumnModel mod = list.getColumnModel();
818 mod.getColumn(0).setPreferredWidth(150);
819 mod.getColumn(1).setPreferredWidth(200);
820 mod.getColumn(2).setPreferredWidth(300);
821 mod.getColumn(3).setPreferredWidth(150);
822 mod.getColumn(4).setPreferredWidth(150);
823
824 JPanel buttonPanel = new JPanel(new FlowLayout());
825
826 JButton add = new JButton(tr("Add"));
827 buttonPanel.add(add, GBC.std().insets(0, 5, 0, 0));
828 add.addActionListener(e -> model.addRow(new OffsetBookmark(Main.getProjection().toCode(), "", "", 0, 0)));
829
830 JButton delete = new JButton(tr("Delete"));
831 buttonPanel.add(delete, GBC.std().insets(0, 5, 0, 0));
832 delete.addActionListener(e -> {
833 if (list.getSelectedRow() == -1) {
834 JOptionPane.showMessageDialog(gui, tr("Please select the row to delete."));
835 } else {
836 Integer i;
837 while ((i = list.getSelectedRow()) != -1) {
838 model.removeRow(i);
839 }
840 }
841 });
842
843 add(buttonPanel, GBC.eol());
844 }
845
846 /**
847 * The table model for imagery offsets list
848 */
849 private class OffsetsBookmarksModel extends DefaultTableModel {
850
851 /**
852 * Constructs a new {@code OffsetsBookmarksModel}.
853 */
854 OffsetsBookmarksModel() {
855 setColumnIdentifiers(new String[] {tr("Projection"), tr("Layer"), tr("Name"), tr("Easting"), tr("Northing")});
856 }
857
858 private OffsetBookmark getRow(int row) {
859 return bookmarks.get(row);
860 }
861
862 private void addRow(OffsetBookmark i) {
863 bookmarks.add(i);
864 int p = getRowCount() - 1;
865 fireTableRowsInserted(p, p);
866 }
867
868 @Override
869 public void removeRow(int i) {
870 bookmarks.remove(getRow(i));
871 fireTableRowsDeleted(i, i);
872 }
873
874 @Override
875 public int getRowCount() {
876 return bookmarks.size();
877 }
878
879 @Override
880 public Object getValueAt(int row, int column) {
881 OffsetBookmark info = bookmarks.get(row);
882 switch (column) {
883 case 0:
884 if (info.projectionCode == null) return "";
885 return info.projectionCode;
886 case 1:
887 return info.layerName;
888 case 2:
889 return info.name;
890 case 3:
891 return info.dx;
892 case 4:
893 return info.dy;
894 default:
895 throw new ArrayIndexOutOfBoundsException();
896 }
897 }
898
899 @Override
900 public void setValueAt(Object o, int row, int column) {
901 OffsetBookmark info = bookmarks.get(row);
902 switch (column) {
903 case 1:
904 info.layerName = o.toString();
905 break;
906 case 2:
907 info.name = o.toString();
908 break;
909 case 3:
910 info.dx = Double.parseDouble((String) o);
911 break;
912 case 4:
913 info.dy = Double.parseDouble((String) o);
914 break;
915 default:
916 throw new ArrayIndexOutOfBoundsException();
917 }
918 }
919
920 @Override
921 public boolean isCellEditable(int row, int column) {
922 return column >= 1;
923 }
924 }
925 }
926
927 /**
928 * Initializes imagery preferences.
929 */
930 public static void initialize() {
931 ImageryLayerInfo.instance.load(true);
932 OffsetBookmark.loadBookmarks();
933 Main.main.menu.imageryMenu.refreshImageryMenu();
934 Main.main.menu.imageryMenu.refreshOffsetMenu();
935 }
936}
Note: See TracBrowser for help on using the repository browser.