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