1 package tim.prune.function;
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.FlowLayout;
6 import java.awt.GridBagConstraints;
7 import java.awt.GridBagLayout;
8 import java.awt.Insets;
9 import java.awt.event.ActionEvent;
10 import java.awt.event.ActionListener;
11 import java.awt.event.KeyAdapter;
12 import java.awt.event.KeyEvent;
14 import javax.swing.BorderFactory;
15 import javax.swing.ButtonGroup;
16 import javax.swing.JButton;
17 import javax.swing.JComboBox;
18 import javax.swing.JDialog;
19 import javax.swing.JLabel;
20 import javax.swing.JPanel;
21 import javax.swing.JRadioButton;
22 import javax.swing.JTextField;
24 import tim.prune.I18nManager;
25 import tim.prune.gui.map.MapSource;
26 import tim.prune.gui.map.MapSourceLibrary;
27 import tim.prune.gui.map.OsmMapSource;
30 * Class to handle the adding of a new map source
32 public class AddMapSourceDialog
34 private SetMapBgFunction _parent = null;
35 private JDialog _addDialog = null;
36 private MapSource _originalSource = null;
37 // controls for osm panel
38 private JTextField _oNameField = null;
39 private JTextField _baseUrlField = null, _topUrlField = null;
40 private JRadioButton[] _baseTypeRadios = null, _topTypeRadios = null;
41 private JComboBox<Integer> _oZoomCombo = null;
42 private JButton _okButton = null;
44 /** array of file types */
45 private static final String[] FILE_TYPES = {"png", "jpg", "gif"};
50 * @param inParent parent dialog
52 public AddMapSourceDialog(JDialog inParentDialog, SetMapBgFunction inParentFunction)
54 _parent = inParentFunction;
55 _addDialog = new JDialog(inParentDialog, I18nManager.getText("dialog.addmapsource.title"), true);
56 _addDialog.add(makeDialogComponents());
57 _addDialog.setLocationRelativeTo(inParentDialog);
63 * Create dialog components
64 * @return Panel containing all gui elements in dialog
66 private Component makeDialogComponents()
68 JPanel dialogPanel = new JPanel();
69 dialogPanel.setLayout(new BorderLayout());
70 // Top panel with spacer
71 dialogPanel.add(new JLabel(" "), BorderLayout.NORTH);
74 KeyAdapter keyListener = new KeyAdapter() {
75 public void keyReleased(KeyEvent e) {
77 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
85 // Listener for any gui changes (to enable ok when anything changes on an edit)
86 ActionListener okEnabler = new ActionListener() {
87 public void actionPerformed(ActionEvent arg0) {
92 // openstreetmap panel
93 JPanel osmPanel = new JPanel();
94 osmPanel.setLayout(new BorderLayout());
95 osmPanel.setBorder(BorderFactory.createEmptyBorder(6, 3, 4, 3));
96 JPanel gbPanel = new JPanel();
97 GridBagLayout gridbag = new GridBagLayout();
98 GridBagConstraints c = new GridBagConstraints();
99 gbPanel.setLayout(gridbag);
100 c.gridx = 0; c.gridy = 0;
101 c.gridheight = 1; c.gridwidth = 1;
102 c.weightx = 0.0; c.weighty = 0.0;
103 c.ipadx = 3; c.ipady = 5;
104 c.insets = new Insets(0, 0, 5, 0);
105 c.anchor = GridBagConstraints.FIRST_LINE_START;
106 gbPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.sourcename")), c);
107 _oNameField = new JTextField(18);
108 _oNameField.addKeyListener(keyListener);
109 c.gridx = 1; c.weightx = 1.0;
110 gbPanel.add(_oNameField, c);
112 c.gridx = 0; c.gridy = 1;
114 c.insets = new Insets(0, 0, 0, 0);
115 gbPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.layer1url")), c);
116 _baseUrlField = new JTextField(18);
117 _baseUrlField.addKeyListener(keyListener);
118 c.gridx = 1; c.weightx = 1.0;
119 gbPanel.add(_baseUrlField, c);
120 _baseTypeRadios = new JRadioButton[3];
121 ButtonGroup radioGroup = new ButtonGroup();
122 for (int i=0; i<3; i++)
124 _baseTypeRadios[i] = new JRadioButton(FILE_TYPES[i]);
125 radioGroup.add(_baseTypeRadios[i]);
126 c.gridx = 2+i; c.weightx = 0.0;
127 gbPanel.add(_baseTypeRadios[i], c);
128 // Each type radio needs listener to call enableOk()
129 _baseTypeRadios[i].addActionListener(okEnabler);
133 c.gridx = 0; c.gridy = 2;
134 gbPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.layer2url")), c);
135 _topUrlField = new JTextField(18);
136 _topUrlField.addKeyListener(keyListener);
137 c.gridx = 1; c.weightx = 1.0;
138 gbPanel.add(_topUrlField, c);
139 _topTypeRadios = new JRadioButton[3];
140 radioGroup = new ButtonGroup();
141 for (int i=0; i<3; i++)
143 _topTypeRadios[i] = new JRadioButton(FILE_TYPES[i]);
144 radioGroup.add(_topTypeRadios[i]);
145 c.gridx = 2+i; c.weightx = 0.0;
146 gbPanel.add(_topTypeRadios[i], c);
147 // Each type radio needs listener to call enableOk()
148 _topTypeRadios[i].addActionListener(okEnabler);
151 c.gridx = 0; c.gridy = 3;
152 gbPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.maxzoom")), c);
153 _oZoomCombo = new JComboBox<Integer>();
154 for (int i=10; i<=20; i++) {
155 _oZoomCombo.addItem(i);
157 // zoom dropdown needs listener to call enableOk()
158 _oZoomCombo.addActionListener(okEnabler);
160 gbPanel.add(_oZoomCombo, c);
161 osmPanel.add(gbPanel, BorderLayout.NORTH);
164 JPanel holderPanel = new JPanel();
165 holderPanel.setLayout(new BorderLayout());
166 holderPanel.add(osmPanel, BorderLayout.NORTH);
167 dialogPanel.add(holderPanel, BorderLayout.CENTER);
169 // button panel at bottom
170 JPanel buttonPanel = new JPanel();
171 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
172 _okButton = new JButton(I18nManager.getText("button.ok"));
173 ActionListener okListener = new ActionListener() {
174 public void actionPerformed(ActionEvent e)
179 _okButton.addActionListener(okListener);
180 buttonPanel.add(_okButton);
181 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
182 cancelButton.addActionListener(new ActionListener() {
183 public void actionPerformed(ActionEvent e)
185 _addDialog.dispose();
188 buttonPanel.add(cancelButton);
189 dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
195 * Init and show the dialog
196 * @param inSource source object before edit, or null to add
198 public void showDialog(MapSource inSource)
200 _originalSource = inSource;
205 * Clear all the dialog fields to prepare for an add
207 private void clearAllFields()
209 _oNameField.setText("");
210 _baseUrlField.setText("");
211 _baseTypeRadios[0].setSelected(true);
212 _topUrlField.setText("");
213 _topTypeRadios[0].setSelected(true);
214 _oZoomCombo.setSelectedIndex(8);
215 _okButton.setEnabled(false);
216 _addDialog.setVisible(true);
220 * Init the dialog fields from the given source object
222 private void populateFields()
224 if (_originalSource == null)
230 // See if it's an osm source
233 OsmMapSource osmSource = (OsmMapSource) _originalSource;
234 _oNameField.setText(osmSource.getName());
235 _baseUrlField.setText(osmSource.getBaseUrl(0));
236 int baseType = getBaseType(osmSource.getFileExtension(0));
237 _baseTypeRadios[baseType].setSelected(true);
238 _topUrlField.setText(osmSource.getNumLayers()==0?"":osmSource.getBaseUrl(1));
239 int topType = getBaseType(osmSource.getFileExtension(1));
240 _topTypeRadios[topType].setSelected(true);
241 _oZoomCombo.setSelectedIndex(getZoomIndex(osmSource.getMaxZoomLevel()));
243 catch (ClassCastException cce) {} // ignore, sourceFound flag stays false
245 _okButton.setEnabled(false);
246 _addDialog.setVisible(true);
250 * Check the currently entered details and enable the OK button if it looks OK
252 private void enableOK()
254 _okButton.setEnabled(isOsmPanelOk());
258 * Check the openstreetmap panel if all details are complete
259 * @return true if details look ok
261 private boolean isOsmPanelOk()
263 boolean ok = _oNameField.getText().trim().length() > 1;
264 String baseUrl = null, topUrl = null;
265 // Try to parse base url if given
266 String baseText = _baseUrlField.getText().trim();
267 baseUrl = MapSource.fixBaseUrl(baseText);
268 if (baseText.length() > 0 && baseUrl == null) {ok = false;}
269 // Same again for top url if given
270 String topText = _topUrlField.getText().trim();
271 topUrl = MapSource.fixBaseUrl(topText);
272 if (topText.length() > 0 && topUrl == null) {ok = false;}
273 // looks ok if at least one url given
274 return (ok && (baseUrl != null || topUrl != null));
278 * Finish by adding the requested source and refreshing the parent
280 private void finish()
282 MapSource newSource = null;
283 String origName = (_originalSource == null ? null : _originalSource.getName());
287 // Openstreetmap source
288 String sourceName = getValidSourcename(_oNameField.getText(), origName);
289 String url1 = _baseUrlField.getText().trim();
290 String ext1 = getFileExtension(_baseTypeRadios);
291 String url2 = _topUrlField.getText().trim();
292 String ext2 = getFileExtension(_topTypeRadios);
293 newSource = new OsmMapSource(sourceName, url1, ext1, url2, ext2, _oZoomCombo.getSelectedIndex()+10);
296 // Add new source if ok
297 if (newSource != null)
299 if (_originalSource == null) {
300 MapSourceLibrary.addSource(newSource);
303 MapSourceLibrary.editSource(_originalSource, newSource);
305 // inform setmapbg dialog
306 _parent.updateList();
307 _addDialog.setVisible(false);
312 * Check the given source name is valid and whether it exists in library already
313 * @param inName name to check
314 * @param inOriginalName name of source before edit (or null for new source)
315 * @return valid name for the new source
317 private static String getValidSourcename(String inName, String inOriginalName)
319 String name = inName;
320 if (name == null) {name = "";}
321 else {name = name.trim();}
322 if (name.equals("")) {
323 name = I18nManager.getText("dialog.addmapsource.noname");
325 // Check there isn't already a map source with this name
326 if (inOriginalName == null || !inOriginalName.equals(name))
328 if (MapSourceLibrary.hasSourceName(name))
331 while (MapSourceLibrary.hasSourceName(name + suffix)) {
341 * Get the selected file extension
342 * @param inRadios array of radio buttons for selection
343 * @return selected file extension
345 private String getFileExtension(JRadioButton[] inRadios)
347 if (inRadios != null)
349 for (int i=0; i<inRadios.length; i++) {
350 if (inRadios[i] != null && inRadios[i].isSelected()) {
351 return FILE_TYPES[i];
355 return FILE_TYPES[0];
359 * Get the index of the given image extension
360 * @param inExt file extension, such as "png"
361 * @return index from 0 to 2
363 private static int getBaseType(String inExt)
365 for (int i=0; i<FILE_TYPES.length; i++) {
366 if (FILE_TYPES[i].equals(inExt)) {
370 // Not found so default to png
375 * Get the dropdown index of the given zoom level
376 * @param inZoomLevel zoom level, eg 18
377 * @return index of dropdown to select
379 private static int getZoomIndex(int inZoomLevel)
381 return Math.max(0, inZoomLevel - 10);