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

Last change on this file since 5729 was 5729, checked in by bastiK, 11 years ago

applied #8441 - show local imagery sources in menu instead of popup

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