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

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

fix #10850 - clear imagery providers map preview when reloading default list

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