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

Last change on this file since 5666 was 5666, checked in by simon04, 11 years ago

fix #8360 - designated icons for adding WMS/TMS

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