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