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

Last change on this file since 3737 was 3737, checked in by Upliner, 13 years ago

make possible to place imagery offset action to the top toolbar and place it there by default; completely fixes #5726

  • Property svn:eol-style set to native
File size: 30.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trc;
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.List;
21import java.util.Locale;
22
23import javax.swing.BorderFactory;
24import javax.swing.Box;
25import javax.swing.JButton;
26import javax.swing.JCheckBox;
27import javax.swing.JColorChooser;
28import javax.swing.JComboBox;
29import javax.swing.JEditorPane;
30import javax.swing.JLabel;
31import javax.swing.JOptionPane;
32import javax.swing.JPanel;
33import javax.swing.JScrollPane;
34import javax.swing.JSeparator;
35import javax.swing.JSlider;
36import javax.swing.JSpinner;
37import javax.swing.JTabbedPane;
38import javax.swing.JTable;
39import javax.swing.SpinnerNumberModel;
40import javax.swing.table.DefaultTableModel;
41import javax.swing.table.TableColumnModel;
42
43import org.openstreetmap.josm.Main;
44import org.openstreetmap.josm.data.imagery.ImageryInfo;
45import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
46import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
47import org.openstreetmap.josm.data.imagery.OffsetBookmark;
48import org.openstreetmap.josm.gui.layer.ImageryLayer;
49import org.openstreetmap.josm.gui.layer.TMSLayer;
50import org.openstreetmap.josm.gui.layer.WMSLayer;
51import org.openstreetmap.josm.io.imagery.HTMLGrabber;
52import org.openstreetmap.josm.tools.ColorHelper;
53import org.openstreetmap.josm.tools.GBC;
54
55public class ImageryPreference implements PreferenceSetting {
56 public static class Factory implements PreferenceSettingFactory {
57 @Override
58 public PreferenceSetting createPreferenceSetting() {
59 return new ImageryPreference();
60 }
61 }
62 ImageryProvidersPanel imageryProviders;
63
64 static ImagerySettingsMigration settingsMigration;
65
66 // Common settings
67 private Color colFadeColor;
68 private JButton btnFadeColor;
69 private JSlider fadeAmount = new JSlider(0, 100);
70 private JComboBox sharpen;
71
72 // WMS Settings
73 private JComboBox browser;
74 JCheckBox overlapCheckBox;
75 JSpinner spinEast;
76 JSpinner spinNorth;
77 JSpinner spinSimConn;
78
79 //TMS settings controls
80 private JCheckBox autozoomActive = new JCheckBox();
81 private JCheckBox autoloadTiles = new JCheckBox();
82 private JSpinner minZoomLvl;
83 private JSpinner maxZoomLvl;
84 private JCheckBox addToSlippyMapChosser = new JCheckBox();
85
86 private JPanel buildCommonSettingsPanel(final PreferenceTabbedPane gui) {
87 final JPanel p = new JPanel(new GridBagLayout());
88
89 this.colFadeColor = ImageryLayer.getFadeColor();
90 this.btnFadeColor = new JButton();
91
92 this.btnFadeColor.addActionListener(new ActionListener() {
93 @Override
94 public void actionPerformed(ActionEvent e) {
95 JColorChooser chooser = new JColorChooser(colFadeColor);
96 int answer = JOptionPane.showConfirmDialog(
97 gui, chooser,
98 tr("Choose a color for {0}", tr("imagery fade")),
99 JOptionPane.OK_CANCEL_OPTION,
100 JOptionPane.PLAIN_MESSAGE);
101 if (answer == JOptionPane.OK_OPTION) {
102 colFadeColor = chooser.getColor();
103 btnFadeColor.setBackground(colFadeColor);
104 btnFadeColor.setText(ColorHelper.color2html(colFadeColor));
105 }
106 }
107 });
108
109 p.add(new JLabel(tr("Fade Color: ")), GBC.std());
110 p.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL));
111 p.add(this.btnFadeColor, GBC.eol().fill(GBC.HORIZONTAL));
112
113 p.add(new JLabel(tr("Fade amount: ")), GBC.std());
114 p.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL));
115 p.add(this.fadeAmount, GBC.eol().fill(GBC.HORIZONTAL));
116
117 this.sharpen = new JComboBox(new String[] {
118 tr("None"),
119 tr("Soft"),
120 tr("Strong")});
121 p.add(new JLabel(tr("Sharpen (requires layer re-add): ")));
122 p.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL));
123 p.add(this.sharpen, GBC.eol().fill(GBC.HORIZONTAL));
124
125 if (settingsMigration != null) {
126 final JButton btnSettingsMigration = new JButton(tr("WMSPlugin/SlippyMap settings migration"));
127 btnSettingsMigration.addActionListener(new ActionListener() {
128 @Override
129 public void actionPerformed(ActionEvent e) {
130 if (settingsMigration == null) return;
131 settingsMigration.settingsMigrationDialog(gui);
132 loadSettings();
133 imageryProviders.model.fireTableDataChanged();
134 if (!settingsMigration.hasConflicts()) {
135 btnSettingsMigration.setEnabled(false);
136 settingsMigration = null;
137 }
138 }
139 });
140 p.add(btnSettingsMigration,GBC.eol().insets(0,5,0,5));
141 }
142 return p;
143 }
144
145 private JPanel buildWMSSettingsPanel() {
146 final JPanel p = new JPanel(new GridBagLayout());
147 browser = new JComboBox(new String[] {
148 "webkit-image {0}",
149 "gnome-web-photo --mode=photo --format=png {0} /dev/stdout",
150 "gnome-web-photo-fixed {0}",
151 "webkit-image-gtk {0}"});
152 browser.setEditable(true);
153 p.add(new JLabel(tr("Downloader:")), GBC.eol().fill(GBC.HORIZONTAL));
154 p.add(browser);
155
156 // Overlap
157 p.add(Box.createHorizontalGlue(), GBC.eol().fill(GBC.HORIZONTAL));
158
159 overlapCheckBox = new JCheckBox(tr("Overlap tiles"));
160 JLabel labelEast = new JLabel(tr("% of east:"));
161 JLabel labelNorth = new JLabel(tr("% of north:"));
162 spinEast = new JSpinner(new SpinnerNumberModel(WMSLayer.PROP_OVERLAP_EAST.get(), 1, 50, 1));
163 spinNorth = new JSpinner(new SpinnerNumberModel(WMSLayer.PROP_OVERLAP_NORTH.get(), 1, 50, 1));
164
165 JPanel overlapPanel = new JPanel(new FlowLayout());
166 overlapPanel.add(overlapCheckBox);
167 overlapPanel.add(labelEast);
168 overlapPanel.add(spinEast);
169 overlapPanel.add(labelNorth);
170 overlapPanel.add(spinNorth);
171
172 p.add(overlapPanel);
173
174 // Simultaneous connections
175 p.add(Box.createHorizontalGlue(), GBC.eol().fill(GBC.HORIZONTAL));
176 JLabel labelSimConn = new JLabel(tr("Simultaneous connections"));
177 spinSimConn = new JSpinner(new SpinnerNumberModel(WMSLayer.PROP_SIMULTANEOUS_CONNECTIONS.get(), 1, 30, 1));
178 JPanel overlapPanelSimConn = new JPanel(new FlowLayout(FlowLayout.LEFT));
179 overlapPanelSimConn.add(labelSimConn);
180 overlapPanelSimConn.add(spinSimConn);
181 p.add(overlapPanelSimConn, GBC.eol().fill(GBC.HORIZONTAL));
182
183 return p;
184 }
185
186 private JPanel buildTMSSettingsPanel() {
187 JPanel tmsTab = new JPanel(new GridBagLayout());
188
189 minZoomLvl = new JSpinner(new SpinnerNumberModel(TMSLayer.DEFAULT_MIN_ZOOM, TMSLayer.MIN_ZOOM, TMSLayer.MAX_ZOOM, 1));
190 maxZoomLvl = new JSpinner(new SpinnerNumberModel(TMSLayer.DEFAULT_MAX_ZOOM, TMSLayer.MIN_ZOOM, TMSLayer.MAX_ZOOM, 1));
191
192 tmsTab.add(new JLabel(tr("Auto zoom by default: ")), GBC.std());
193 tmsTab.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL));
194 tmsTab.add(autozoomActive, GBC.eol().fill(GBC.HORIZONTAL));
195
196 tmsTab.add(new JLabel(tr("Autoload tiles by default: ")), GBC.std());
197 tmsTab.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL));
198 tmsTab.add(autoloadTiles, GBC.eol().fill(GBC.HORIZONTAL));
199
200 tmsTab.add(new JLabel(tr("Min zoom lvl: ")), GBC.std());
201 tmsTab.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL));
202 tmsTab.add(this.minZoomLvl, GBC.eol().fill(GBC.HORIZONTAL));
203
204 tmsTab.add(new JLabel(tr("Max zoom lvl: ")), GBC.std());
205 tmsTab.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL));
206 tmsTab.add(this.maxZoomLvl, GBC.eol().fill(GBC.HORIZONTAL));
207
208 tmsTab.add(new JLabel(tr("Add to slippymap chooser: ")), GBC.std());
209 tmsTab.add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL));
210 tmsTab.add(addToSlippyMapChosser, GBC.eol().fill(GBC.HORIZONTAL));
211
212 return tmsTab;
213 }
214
215 private void addSettingsSection(final JPanel p, String name, JPanel section) {
216 final JLabel lbl = new JLabel(name);
217 lbl.setFont(lbl.getFont().deriveFont(Font.BOLD));
218 p.add(lbl,GBC.std());
219 p.add(new JSeparator(), GBC.eol().fill(GBC.HORIZONTAL).insets(5, 0, 0, 0));
220 p.add(section,GBC.eol().insets(20,5,0,10));
221 }
222
223 private Component buildSettingsPanel(final PreferenceTabbedPane gui) {
224 final JPanel p = new JPanel(new GridBagLayout());
225 p.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
226
227 addSettingsSection(p, tr("Common Settings"), buildCommonSettingsPanel(gui));
228 addSettingsSection(p, tr("WMS Settings"), buildWMSSettingsPanel());
229 addSettingsSection(p, tr("TMS Settings"), buildTMSSettingsPanel());
230
231 p.add(new JPanel(),GBC.eol().fill(GBC.BOTH));
232 return new JScrollPane(p);
233 }
234
235 @Override
236 public void addGui(final PreferenceTabbedPane gui) {
237 JPanel p = gui.createPreferenceTab("imagery", tr("Imagery Preferences"), tr("Modify list of imagery layers displayed in the Imagery menu"));
238 JTabbedPane pane = new JTabbedPane();
239 imageryProviders = new ImageryProvidersPanel(gui, ImageryLayerInfo.instance);
240 pane.add(imageryProviders);
241 pane.add(buildSettingsPanel(gui));
242 pane.add(new OffsetBookmarksPanel(gui));
243 loadSettings();
244 pane.setTitleAt(0, tr("Imagery providers"));
245 pane.setTitleAt(1, tr("Settings"));
246 pane.setTitleAt(2, tr("Offset bookmarks"));
247 p.add(pane,GBC.std().fill(GBC.BOTH));
248 }
249
250 private void loadSettings() {
251 // Common settings
252 this.btnFadeColor.setBackground(colFadeColor);
253 this.btnFadeColor.setText(ColorHelper.color2html(colFadeColor));
254 this.fadeAmount.setValue(ImageryLayer.PROP_FADE_AMOUNT.get());
255 this.sharpen.setSelectedIndex(Math.max(0, Math.min(2, ImageryLayer.PROP_SHARPEN_LEVEL.get())));
256
257 // WMS Settings
258 this.browser.setSelectedItem(HTMLGrabber.PROP_BROWSER.get());
259 this.overlapCheckBox.setSelected(WMSLayer.PROP_OVERLAP.get());
260 this.spinEast.setValue(WMSLayer.PROP_OVERLAP_EAST.get());
261 this.spinNorth.setValue(WMSLayer.PROP_OVERLAP_NORTH.get());
262 this.spinSimConn.setValue(WMSLayer.PROP_SIMULTANEOUS_CONNECTIONS.get());
263
264 // TMS Settings
265 this.autozoomActive.setSelected(TMSLayer.PROP_DEFAULT_AUTOZOOM.get());
266 this.autoloadTiles.setSelected(TMSLayer.PROP_DEFAULT_AUTOLOAD.get());
267 this.addToSlippyMapChosser.setSelected(TMSLayer.PROP_ADD_TO_SLIPPYMAP_CHOOSER.get());
268 this.maxZoomLvl.setValue(TMSLayer.getMaxZoomLvl(null));
269 this.minZoomLvl.setValue(TMSLayer.getMinZoomLvl(null));
270 }
271
272 @Override
273 public boolean ok() {
274 boolean restartRequired = false;
275 ImageryLayerInfo.instance.save();
276 Main.main.menu.imageryMenu.refreshImageryMenu();
277 Main.main.menu.imageryMenu.refreshOffsetMenu();
278 OffsetBookmark.saveBookmarks();
279
280 WMSLayer.PROP_OVERLAP.put(overlapCheckBox.getModel().isSelected());
281 WMSLayer.PROP_OVERLAP_EAST.put((Integer) spinEast.getModel().getValue());
282 WMSLayer.PROP_OVERLAP_NORTH.put((Integer) spinNorth.getModel().getValue());
283 WMSLayer.PROP_SIMULTANEOUS_CONNECTIONS.put((Integer) spinSimConn.getModel().getValue());
284
285 HTMLGrabber.PROP_BROWSER.put(browser.getEditor().getItem().toString());
286
287 if (TMSLayer.PROP_ADD_TO_SLIPPYMAP_CHOOSER.get() != this.addToSlippyMapChosser.isSelected()) {
288 restartRequired = true;
289 }
290 TMSLayer.PROP_ADD_TO_SLIPPYMAP_CHOOSER.put(this.addToSlippyMapChosser.isSelected());
291 TMSLayer.PROP_DEFAULT_AUTOZOOM.put(this.autozoomActive.isSelected());
292 TMSLayer.PROP_DEFAULT_AUTOLOAD.put(this.autoloadTiles.isSelected());
293 TMSLayer.setMaxZoomLvl((Integer)this.maxZoomLvl.getValue());
294 TMSLayer.setMinZoomLvl((Integer)this.minZoomLvl.getValue());
295
296 ImageryLayer.PROP_FADE_AMOUNT.put(this.fadeAmount.getValue());
297 ImageryLayer.setFadeColor(this.colFadeColor);
298 ImageryLayer.PROP_SHARPEN_LEVEL.put(sharpen.getSelectedIndex());
299
300 return restartRequired;
301 }
302
303
304 /**
305 * Updates a server URL in the preferences dialog. Used by plugins.
306 *
307 * @param server
308 * The server name
309 * @param url
310 * The server URL
311 */
312 public void setServerUrl(String server, String url) {
313 for (int i = 0; i < imageryProviders.model.getRowCount(); i++) {
314 if (server.equals(imageryProviders.model.getValueAt(i, 0).toString())) {
315 imageryProviders.model.setValueAt(url, i, 1);
316 return;
317 }
318 }
319 imageryProviders.model.addRow(new String[] { server, url });
320 }
321
322 /**
323 * Gets a server URL in the preferences dialog. Used by plugins.
324 *
325 * @param server
326 * The server name
327 * @return The server URL
328 */
329 public String getServerUrl(String server) {
330 for (int i = 0; i < imageryProviders.model.getRowCount(); i++) {
331 if (server.equals(imageryProviders.model.getValueAt(i, 0).toString()))
332 return imageryProviders.model.getValueAt(i, 1).toString();
333 }
334 return null;
335 }
336
337 static class ImageryProvidersPanel extends JPanel {
338 final ImageryLayerTableModel model;
339 private final ImageryLayerInfo layerInfo;
340
341 public ImageryProvidersPanel(final PreferenceTabbedPane gui, ImageryLayerInfo layerInfo) {
342 super(new GridBagLayout());
343 this.layerInfo = layerInfo;
344 this.model = new ImageryLayerTableModel();
345
346 final JTable list = new JTable(model) {
347 @Override
348 public String getToolTipText(MouseEvent e) {
349 java.awt.Point p = e.getPoint();
350 return model.getValueAt(rowAtPoint(p), columnAtPoint(p)).toString();
351 }
352 };
353 JScrollPane scroll = new JScrollPane(list);
354 add(scroll, GBC.eol().fill(GridBagConstraints.BOTH));
355 scroll.setPreferredSize(new Dimension(200, 200));
356
357 final ImageryDefaultLayerTableModel modeldef = new ImageryDefaultLayerTableModel();
358 final JTable listdef = new JTable(modeldef) {
359 @Override
360 public String getToolTipText(MouseEvent e) {
361 java.awt.Point p = e.getPoint();
362 return (String) modeldef.getValueAt(rowAtPoint(p), columnAtPoint(p));
363 }
364 };
365 JScrollPane scrolldef = new JScrollPane(listdef);
366 // scrolldef is added after the buttons so it's clearer the buttons
367 // control the top list and not the default one
368 scrolldef.setPreferredSize(new Dimension(200, 200));
369
370 TableColumnModel mod = listdef.getColumnModel();
371 mod.getColumn(1).setPreferredWidth(800);
372 mod.getColumn(0).setPreferredWidth(200);
373 mod = list.getColumnModel();
374 mod.getColumn(2).setPreferredWidth(50);
375 mod.getColumn(1).setPreferredWidth(800);
376 mod.getColumn(0).setPreferredWidth(200);
377
378 JPanel buttonPanel = new JPanel(new FlowLayout());
379
380 JButton add = new JButton(tr("Add"));
381 buttonPanel.add(add, GBC.std().insets(0, 5, 0, 0));
382 add.addActionListener(new ActionListener() {
383 @Override
384 public void actionPerformed(ActionEvent e) {
385 AddWMSLayerPanel p = new AddWMSLayerPanel();
386 int answer = JOptionPane.showConfirmDialog(
387 gui, p,
388 tr("Add Imagery URL"),
389 JOptionPane.OK_CANCEL_OPTION);
390 if (answer == JOptionPane.OK_OPTION) {
391 model.addRow(new ImageryInfo(p.getUrlName(), p.getUrl()));
392 }
393 }
394 });
395
396 JButton delete = new JButton(tr("Delete"));
397 buttonPanel.add(delete, GBC.std().insets(0, 5, 0, 0));
398 delete.addActionListener(new ActionListener() {
399 @Override
400 public void actionPerformed(ActionEvent e) {
401 if (list.getSelectedRow() == -1) {
402 JOptionPane.showMessageDialog(gui, tr("Please select the row to delete."));
403 } else {
404 Integer i;
405 while ((i = list.getSelectedRow()) != -1) {
406 model.removeRow(i);
407 }
408 }
409 }
410 });
411
412 JButton copy = new JButton(tr("Copy Selected Default(s)"));
413 buttonPanel.add(copy, GBC.std().insets(0, 5, 0, 0));
414 copy.addActionListener(new ActionListener() {
415 @Override
416 public void actionPerformed(ActionEvent e) {
417 int[] lines = listdef.getSelectedRows();
418 if (lines.length == 0) {
419 JOptionPane.showMessageDialog(
420 gui,
421 tr("Please select at least one row to copy."),
422 tr("Information"),
423 JOptionPane.INFORMATION_MESSAGE);
424 return;
425 }
426
427 outer: for (int i = 0; i < lines.length; i++) {
428 ImageryInfo info = modeldef.getRow(lines[i]);
429
430 // Check if an entry with exactly the same values already
431 // exists
432 for (int j = 0; j < model.getRowCount(); j++) {
433 if (info.equalsBaseValues(model.getRow(j))) {
434 // Select the already existing row so the user has
435 // some feedback in case an entry exists
436 list.getSelectionModel().setSelectionInterval(j, j);
437 list.scrollRectToVisible(list.getCellRect(j, 0, true));
438 continue outer;
439 }
440 }
441
442 if (info.eulaAcceptanceRequired != null) {
443 if (!confirmEulaAcceptance(gui, info.eulaAcceptanceRequired)) {
444 continue outer;
445 }
446 }
447
448 model.addRow(new ImageryInfo(info));
449 int lastLine = model.getRowCount() - 1;
450 list.getSelectionModel().setSelectionInterval(lastLine, lastLine);
451 list.scrollRectToVisible(list.getCellRect(lastLine, 0, true));
452 }
453 }
454 });
455
456 add(buttonPanel);
457 add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
458 // Add default item list
459 add(scrolldef, GBC.eol().insets(0, 5, 0, 0).fill(GridBagConstraints.BOTH));
460 }
461
462 /**
463 * The table model for imagery layer list
464 */
465 class ImageryLayerTableModel extends DefaultTableModel {
466 public ImageryLayerTableModel() {
467 setColumnIdentifiers(new String[] { tr("Menu Name"), tr("Imagery URL"), trc("layer", "Zoom") });
468 }
469
470 public ImageryInfo getRow(int row) {
471 return layerInfo.getLayers().get(row);
472 }
473
474 public void addRow(ImageryInfo i) {
475 layerInfo.add(i);
476 int p = getRowCount() - 1;
477 fireTableRowsInserted(p, p);
478 }
479
480 @Override
481 public void removeRow(int i) {
482 layerInfo.remove(getRow(i));
483 fireTableRowsDeleted(i, i);
484 }
485
486 @Override
487 public int getRowCount() {
488 return layerInfo.getLayers().size();
489 }
490
491 @Override
492 public Object getValueAt(int row, int column) {
493 ImageryInfo info = layerInfo.getLayers().get(row);
494 switch (column) {
495 case 0:
496 return info.getName();
497 case 1:
498 return info.getFullURL();
499 case 2:
500 return (info.getImageryType() == ImageryType.WMS || info.getImageryType() == ImageryType.HTML) ?
501 (info.getPixelPerDegree() == 0.0 ? "" : info.getPixelPerDegree()) :
502 (info.getMaxZoom() == 0 ? "" : info.getMaxZoom());
503 default:
504 throw new ArrayIndexOutOfBoundsException();
505 }
506 }
507
508 @Override
509 public void setValueAt(Object o, int row, int column) {
510 ImageryInfo info = layerInfo.getLayers().get(row);
511 switch (column) {
512 case 0:
513 info.setName((String) o);
514 break;
515 case 1:
516 info.setURL((String)o);
517 break;
518 case 2:
519 info.setPixelPerDegree(0);
520 info.setMaxZoom(0);
521 try {
522 if(info.getImageryType() == ImageryType.WMS || info.getImageryType() == ImageryType.HTML) {
523 info.setPixelPerDegree(Double.parseDouble((String) o));
524 } else {
525 info.setMaxZoom(Integer.parseInt((String) o));
526 }
527 } catch (NumberFormatException e) {
528 }
529 break;
530 default:
531 throw new ArrayIndexOutOfBoundsException();
532 }
533 }
534
535 @Override
536 public boolean isCellEditable(int row, int column) {
537 return true;
538 }
539 }
540
541 /**
542 * The table model for the default imagery layer list
543 */
544 class ImageryDefaultLayerTableModel extends DefaultTableModel {
545 public ImageryDefaultLayerTableModel() {
546 setColumnIdentifiers(new String[] { tr("Menu Name (Default)"), tr("Imagery URL (Default)") });
547 }
548
549 public ImageryInfo getRow(int row) {
550 return layerInfo.getDefaultLayers().get(row);
551 }
552
553 @Override
554 public int getRowCount() {
555 return layerInfo.getDefaultLayers().size();
556 }
557
558 @Override
559 public Object getValueAt(int row, int column) {
560 ImageryInfo info = layerInfo.getDefaultLayers().get(row);
561 switch (column) {
562 case 0:
563 return info.getName();
564 case 1:
565 return info.getFullURL();
566 }
567 return null;
568 }
569
570 @Override
571 public boolean isCellEditable(int row, int column) {
572 return false;
573 }
574 }
575
576 private boolean confirmEulaAcceptance(PreferenceTabbedPane gui, String eulaUrl) {
577 URL url = null;
578 try {
579 url = new URL(eulaUrl.replaceAll("\\{lang\\}", Locale.getDefault().toString()));
580 JEditorPane htmlPane = null;
581 try {
582 htmlPane = new JEditorPane(url);
583 } catch (IOException e1) {
584 // give a second chance with a default Locale 'en'
585 try {
586 url = new URL(eulaUrl.replaceAll("\\{lang\\}", "en"));
587 htmlPane = new JEditorPane(url);
588 } catch (IOException e2) {
589 JOptionPane.showMessageDialog(gui ,tr("EULA license URL not available: {0}", eulaUrl));
590 return false;
591 }
592 }
593 Box box = Box.createVerticalBox();
594 htmlPane.setEditable(false);
595 JScrollPane scrollPane = new JScrollPane(htmlPane);
596 scrollPane.setPreferredSize(new Dimension(400, 400));
597 box.add(scrollPane);
598 int option = JOptionPane.showConfirmDialog(Main.parent, box, tr("Please abort if you are not sure"), JOptionPane.YES_NO_OPTION,
599 JOptionPane.WARNING_MESSAGE);
600 if (option == JOptionPane.YES_OPTION)
601 return true;
602 } catch (MalformedURLException e2) {
603 JOptionPane.showMessageDialog(gui ,tr("Malformed URL for the EULA licence: {0}", eulaUrl));
604 }
605 return false;
606 }
607 }
608
609 static class OffsetBookmarksPanel extends JPanel {
610 List<OffsetBookmark> bookmarks = OffsetBookmark.allBookmarks;
611 OffsetsBookmarksModel model = new OffsetsBookmarksModel();
612
613 public OffsetBookmarksPanel(final PreferenceTabbedPane gui) {
614 super(new GridBagLayout());
615 final JTable list = new JTable(model) {
616 @Override
617 public String getToolTipText(MouseEvent e) {
618 java.awt.Point p = e.getPoint();
619 return model.getValueAt(rowAtPoint(p), columnAtPoint(p)).toString();
620 }
621 };
622 JScrollPane scroll = new JScrollPane(list);
623 add(scroll, GBC.eol().fill(GridBagConstraints.BOTH));
624 scroll.setPreferredSize(new Dimension(200, 200));
625
626 TableColumnModel mod = list.getColumnModel();
627 mod.getColumn(0).setPreferredWidth(150);
628 mod.getColumn(1).setPreferredWidth(200);
629 mod.getColumn(2).setPreferredWidth(300);
630 mod.getColumn(3).setPreferredWidth(150);
631 mod.getColumn(4).setPreferredWidth(150);
632
633 JPanel buttonPanel = new JPanel(new FlowLayout());
634
635 JButton add = new JButton(tr("Add"));
636 buttonPanel.add(add, GBC.std().insets(0, 5, 0, 0));
637 add.addActionListener(new ActionListener() {
638 @Override
639 public void actionPerformed(ActionEvent e) {
640 OffsetBookmark b = new OffsetBookmark(Main.proj,"","",0,0);
641 model.addRow(b);
642 }
643 });
644
645 JButton delete = new JButton(tr("Delete"));
646 buttonPanel.add(delete, GBC.std().insets(0, 5, 0, 0));
647 delete.addActionListener(new ActionListener() {
648 @Override
649 public void actionPerformed(ActionEvent e) {
650 if (list.getSelectedRow() == -1) {
651 JOptionPane.showMessageDialog(gui, tr("Please select the row to delete."));
652 } else {
653 Integer i;
654 while ((i = list.getSelectedRow()) != -1) {
655 model.removeRow(i);
656 }
657 }
658 }
659 });
660
661 add(buttonPanel,GBC.eol());
662 }
663
664 /**
665 * The table model for imagery offsets list
666 */
667 class OffsetsBookmarksModel extends DefaultTableModel {
668 public OffsetsBookmarksModel() {
669 setColumnIdentifiers(new String[] { tr("Projection"), tr("Layer"), tr("Name"), tr("Easting"), tr("Northing"),});
670 }
671
672 public OffsetBookmark getRow(int row) {
673 return bookmarks.get(row);
674 }
675
676 public void addRow(OffsetBookmark i) {
677 bookmarks.add(i);
678 int p = getRowCount() - 1;
679 fireTableRowsInserted(p, p);
680 }
681
682 @Override
683 public void removeRow(int i) {
684 bookmarks.remove(getRow(i));
685 fireTableRowsDeleted(i, i);
686 }
687
688 @Override
689 public int getRowCount() {
690 return bookmarks.size();
691 }
692
693 @Override
694 public Object getValueAt(int row, int column) {
695 OffsetBookmark info = bookmarks.get(row);
696 switch (column) {
697 case 0:
698 return info.proj.toString();
699 case 1:
700 return info.layerName;
701 case 2:
702 return info.name;
703 case 3:
704 return info.dx;
705 case 4:
706 return info.dy;
707 default:
708 throw new ArrayIndexOutOfBoundsException();
709 }
710 }
711
712 @Override
713 public void setValueAt(Object o, int row, int column) {
714 OffsetBookmark info = bookmarks.get(row);
715 switch (column) {
716 case 1:
717 info.layerName = o.toString();
718 break;
719 case 2:
720 info.name = o.toString();
721 break;
722 case 3:
723 info.dx = Double.parseDouble((String) o);
724 break;
725 case 4:
726 info.dy = Double.parseDouble((String) o);
727 break;
728 default:
729 throw new ArrayIndexOutOfBoundsException();
730 }
731 }
732
733 @Override
734 public boolean isCellEditable(int row, int column) {
735 return column >= 1;
736 }
737 }
738 }
739
740 public static void initialize() {
741 settingsMigration = new ImagerySettingsMigration();
742 settingsMigration.migrateSettings();
743 if (!settingsMigration.hasConflicts()) {
744 settingsMigration = null;
745 }
746 ImageryLayerInfo.instance.load();
747 OffsetBookmark.loadBookmarks();
748 Main.main.menu.imageryMenu.refreshImageryMenu();
749 Main.main.menu.imageryMenu.refreshOffsetMenu();
750 }
751}
Note: See TracBrowser for help on using the repository browser.