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

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

Initial support for Komzpa's osmosnimki imagery offset server

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