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

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

fix #8159 - NPE in imagery providers panel

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