001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.download; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.GridBagConstraints; 007import java.awt.GridBagLayout; 008import java.awt.Insets; 009import java.awt.event.ActionEvent; 010import java.awt.event.MouseAdapter; 011import java.awt.event.MouseEvent; 012import java.util.List; 013 014import javax.swing.AbstractAction; 015import javax.swing.DefaultListModel; 016import javax.swing.JButton; 017import javax.swing.JOptionPane; 018import javax.swing.JPanel; 019import javax.swing.JScrollPane; 020import javax.swing.SwingUtilities; 021import javax.swing.event.ListSelectionEvent; 022import javax.swing.event.ListSelectionListener; 023 024import org.openstreetmap.josm.Main; 025import org.openstreetmap.josm.data.Bounds; 026import org.openstreetmap.josm.gui.download.BookmarkList.Bookmark; 027import org.openstreetmap.josm.gui.widgets.JMultilineLabel; 028import org.openstreetmap.josm.gui.widgets.JosmTextArea; 029import org.openstreetmap.josm.tools.ImageProvider; 030 031/** 032 * DownloadAreaSelector which manages a list of "bookmarks", i.e. a list of 033 * name download areas. 034 * 035 */ 036public class BookmarkSelection implements DownloadSelection { 037 038 /** the currently selected download area. One can add bookmarks for this 039 * area, if not null 040 */ 041 private Bounds currentArea; 042 /** the list of bookmarks */ 043 private BookmarkList bookmarks; 044 045 /** the parent download GUI */ 046 private DownloadDialog parent; 047 048 /** displays information about the current download area */ 049 private JMultilineLabel lblCurrentDownloadArea; 050 private final JosmTextArea bboxDisplay = new JosmTextArea(); 051 /** the add action */ 052 private AddAction actAdd; 053 054 /** 055 * Creates the panel with the action buttons on the left 056 * 057 * @return the panel with the action buttons on the left 058 */ 059 protected JPanel buildButtonPanel() { 060 JPanel pnl = new JPanel(); 061 pnl.setLayout(new GridBagLayout()); 062 GridBagConstraints gc = new GridBagConstraints(); 063 gc.gridy = 0; 064 RemoveAction removeAction = new RemoveAction(); 065 bookmarks.addListSelectionListener(removeAction); 066 pnl.add(new JButton(removeAction), gc); 067 068 gc.gridy = 1; 069 RenameAction renameAction = new RenameAction(); 070 bookmarks.addListSelectionListener(renameAction); 071 pnl.add(new JButton(renameAction), gc); 072 073 gc.fill = GridBagConstraints.BOTH; 074 gc.weightx = 1.0; 075 gc.weighty = 1.0; 076 gc.gridy = 3; 077 pnl.add(new JPanel(), gc); // just a filler 078 return pnl; 079 } 080 081 protected JPanel buildDownloadAreaAddPanel() { 082 JPanel pnl = new JPanel(); 083 pnl.setLayout(new GridBagLayout()); 084 085 GridBagConstraints gc = new GridBagConstraints(); 086 gc.anchor = GridBagConstraints.NORTHWEST; 087 gc.insets = new Insets(5, 5, 5, 5); 088 pnl.add(lblCurrentDownloadArea = new JMultilineLabel(""), gc); 089 090 gc.weightx = 1.0; 091 gc.weighty = 1.0; 092 bboxDisplay.setEditable(false); 093 bboxDisplay.setBackground(pnl.getBackground()); 094 bboxDisplay.addFocusListener(new BoundingBoxSelection.SelectAllOnFocusHandler(bboxDisplay)); 095 pnl.add(bboxDisplay, gc); 096 097 gc.anchor = GridBagConstraints.NORTHEAST; 098 gc.fill = GridBagConstraints.HORIZONTAL; 099 gc.weightx = 0.0; 100 gc.weighty = 0.0; 101 gc.insets = new Insets(5, 5, 5, 5); 102 pnl.add(new JButton(actAdd = new AddAction()), gc); 103 return pnl; 104 } 105 106 @Override 107 public void addGui(final DownloadDialog gui) { 108 JPanel dlg = new JPanel(new GridBagLayout()); 109 gui.addDownloadAreaSelector(dlg, tr("Bookmarks")); 110 GridBagConstraints gc = new GridBagConstraints(); 111 112 bookmarks = new BookmarkList(); 113 bookmarks.getSelectionModel().addListSelectionListener(new ListSelectionListener() { 114 @Override 115 public void valueChanged(ListSelectionEvent e) { 116 Bookmark b = bookmarks.getSelectedValue(); 117 if (b != null) { 118 gui.boundingBoxChanged(b.getArea(), BookmarkSelection.this); 119 } 120 } 121 }); 122 bookmarks.addMouseListener(new DoubleClickAdapter()); 123 124 gc.fill = GridBagConstraints.HORIZONTAL; 125 gc.weightx = 1.0; 126 gc.weighty = 0.0; 127 gc.gridwidth = 2; 128 dlg.add(buildDownloadAreaAddPanel(), gc); 129 130 gc.gridwidth = 1; 131 gc.gridx = 0; 132 gc.gridy = 1; 133 gc.fill = GridBagConstraints.VERTICAL; 134 gc.weightx = 0.0; 135 gc.weighty = 1.0; 136 dlg.add(buildButtonPanel(), gc); 137 138 gc.gridwidth = 1; 139 gc.gridx = 1; 140 gc.gridy = 1; 141 gc.fill = GridBagConstraints.BOTH; 142 gc.weightx = 1.0; 143 gc.weighty = 1.0; 144 gc.gridx = 1; 145 dlg.add(new JScrollPane(bookmarks), gc); 146 147 this.parent = gui; 148 } 149 150 protected void updateDownloadAreaLabel() { 151 if (currentArea == null) { 152 lblCurrentDownloadArea.setText(tr("<html>There is currently no download area selected.</html>")); 153 } else { 154 lblCurrentDownloadArea.setText(tr("<html><strong>Current download area</strong> (minlon, minlat, maxlon, maxlat): </html>")); 155 bboxDisplay.setText(currentArea.toBBox().toStringCSV(",")); 156 } 157 } 158 159 /** 160 * Sets the current download area 161 * 162 * @param area the download area. 163 */ 164 @Override 165 public void setDownloadArea(Bounds area) { 166 if (area == null) return; 167 this.currentArea = area; 168 bookmarks.clearSelection(); 169 updateDownloadAreaLabel(); 170 actAdd.setEnabled(true); 171 } 172 173 /** 174 * The action to add a new bookmark for the current download area. 175 * 176 */ 177 class AddAction extends AbstractAction { 178 AddAction() { 179 putValue(NAME, tr("Create bookmark")); 180 putValue(SMALL_ICON, ImageProvider.get("dialogs", "bookmark-new")); 181 putValue(SHORT_DESCRIPTION, tr("Add a bookmark for the currently selected download area")); 182 } 183 184 @Override 185 public void actionPerformed(ActionEvent e) { 186 if (currentArea == null) { 187 JOptionPane.showMessageDialog( 188 Main.parent, 189 tr("Currently, there is no download area selected. Please select an area first."), 190 tr("Information"), 191 JOptionPane.INFORMATION_MESSAGE 192 ); 193 return; 194 } 195 Bookmark b = new Bookmark(); 196 b.setName( 197 JOptionPane.showInputDialog( 198 Main.parent, tr("Please enter a name for the bookmarked download area."), 199 tr("Name of location"), 200 JOptionPane.QUESTION_MESSAGE) 201 ); 202 b.setArea(currentArea); 203 if (b.getName() != null && !b.getName().isEmpty()) { 204 ((DefaultListModel<BookmarkList.Bookmark>) bookmarks.getModel()).addElement(b); 205 bookmarks.save(); 206 } 207 } 208 } 209 210 class RemoveAction extends AbstractAction implements ListSelectionListener { 211 /** 212 * Constructs a new {@code RemoveAction}. 213 */ 214 RemoveAction() { 215 putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete")); 216 putValue(SHORT_DESCRIPTION, tr("Remove the currently selected bookmarks")); 217 updateEnabledState(); 218 } 219 220 @Override 221 public void actionPerformed(ActionEvent e) { 222 List<Bookmark> sels = bookmarks.getSelectedValuesList(); 223 if (sels == null || sels.isEmpty()) 224 return; 225 for (Object sel: sels) { 226 ((DefaultListModel<Bookmark>) bookmarks.getModel()).removeElement(sel); 227 } 228 bookmarks.save(); 229 } 230 231 protected final void updateEnabledState() { 232 setEnabled(bookmarks.getSelectedIndices().length > 0); 233 } 234 235 @Override 236 public void valueChanged(ListSelectionEvent e) { 237 updateEnabledState(); 238 } 239 } 240 241 class RenameAction extends AbstractAction implements ListSelectionListener { 242 /** 243 * Constructs a new {@code RenameAction}. 244 */ 245 RenameAction() { 246 putValue(SMALL_ICON, ImageProvider.get("dialogs", "edit")); 247 putValue(SHORT_DESCRIPTION, tr("Rename the currently selected bookmark")); 248 updateEnabledState(); 249 } 250 251 @Override 252 public void actionPerformed(ActionEvent e) { 253 List<Bookmark> sels = bookmarks.getSelectedValuesList(); 254 if (sels == null || sels.size() != 1) 255 return; 256 Bookmark b = sels.get(0); 257 Object value = 258 JOptionPane.showInputDialog( 259 Main.parent, tr("Please enter a name for the bookmarked download area."), 260 tr("Name of location"), 261 JOptionPane.QUESTION_MESSAGE, 262 null, 263 null, 264 b.getName() 265 ); 266 if (value != null) { 267 b.setName(value.toString()); 268 bookmarks.save(); 269 bookmarks.repaint(); 270 } 271 } 272 273 protected final void updateEnabledState() { 274 setEnabled(bookmarks.getSelectedIndices().length == 1); 275 } 276 277 @Override 278 public void valueChanged(ListSelectionEvent e) { 279 updateEnabledState(); 280 } 281 } 282 283 class DoubleClickAdapter extends MouseAdapter { 284 @Override 285 public void mouseClicked(MouseEvent e) { 286 if (!(SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2)) 287 return; 288 int idx = bookmarks.locationToIndex(e.getPoint()); 289 if (idx < 0 || idx >= bookmarks.getModel().getSize()) 290 return; 291 Bookmark b = bookmarks.getModel().getElementAt(idx); 292 parent.startDownload(b.getArea()); 293 } 294 } 295}