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

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

performance - remove useless boxing of boolean constants

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