001    // License: GPL. Copyright 2007 by Immanuel Scholz and others
002    package org.openstreetmap.josm.gui.download;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.awt.GridBagConstraints;
007    import java.awt.GridBagLayout;
008    import java.awt.Insets;
009    import java.awt.event.ActionEvent;
010    import java.awt.event.MouseAdapter;
011    import java.awt.event.MouseEvent;
012    
013    import javax.swing.AbstractAction;
014    import javax.swing.DefaultListModel;
015    import javax.swing.JButton;
016    import javax.swing.JOptionPane;
017    import javax.swing.JPanel;
018    import javax.swing.JScrollPane;
019    import javax.swing.JTextArea;
020    import javax.swing.SwingUtilities;
021    import javax.swing.event.ListSelectionEvent;
022    import javax.swing.event.ListSelectionListener;
023    
024    import org.openstreetmap.josm.Main;
025    import org.openstreetmap.josm.data.Bounds;
026    import org.openstreetmap.josm.data.coor.CoordinateFormat;
027    import org.openstreetmap.josm.data.osm.BBox;
028    import org.openstreetmap.josm.gui.BookmarkList;
029    import org.openstreetmap.josm.gui.BookmarkList.Bookmark;
030    import org.openstreetmap.josm.gui.JMultilineLabel;
031    import org.openstreetmap.josm.tools.ImageProvider;
032    
033    /**
034     * DownloadAreaSelector which manages a list of "bookmarks", i.e. a list of
035     * name download areas.
036     *
037     */
038    public class BookmarkSelection implements DownloadSelection {
039    
040        /** the currently selected download area. One can add bookmarks for this
041         * area, if not null
042         */
043        private Bounds currentArea;
044        /** the list of bookmarks */
045        private BookmarkList bookmarks;
046    
047        /** the parent download GUI */
048        private DownloadDialog parent;
049    
050        /** displays information about the current download area */
051        private JMultilineLabel lblCurrentDownloadArea;
052        final private JTextArea bboxDisplay = new JTextArea();
053        /** the add action */
054        private AddAction actAdd;
055    
056        /**
057         * Creates the panel with the action buttons on the left
058         *
059         * @return the panel with the action buttons on the left
060         */
061        protected JPanel buildButtonPanel() {
062            JPanel pnl = new JPanel();
063            pnl.setLayout(new GridBagLayout());
064            GridBagConstraints gc = new GridBagConstraints();
065            gc.gridy = 0;
066            RemoveAction removeAction = new RemoveAction();
067            bookmarks.addListSelectionListener(removeAction);
068            pnl.add(new JButton(removeAction), gc);
069    
070            gc.gridy = 1;
071            RenameAction renameAction = new RenameAction();
072            bookmarks.addListSelectionListener(renameAction);
073            pnl.add(new JButton(renameAction), gc);
074    
075            gc.fill = GridBagConstraints.BOTH;
076            gc.weightx = 1.0;
077            gc.weighty = 1.0;
078            gc.gridy = 3;
079            pnl.add(new JPanel(), gc); // just a filler
080            return pnl;
081        }
082    
083        protected JPanel buildDownloadAreaAddPanel() {
084            JPanel pnl = new JPanel();
085            pnl.setLayout(new GridBagLayout());
086    
087            GridBagConstraints  gc = new GridBagConstraints();
088            gc.anchor = GridBagConstraints.NORTHWEST;
089            gc.insets = new Insets(5,5,5,5);
090            pnl.add(lblCurrentDownloadArea = new JMultilineLabel(""), gc);
091    
092            gc.weightx = 1.0;
093            gc.weighty = 1.0;
094            bboxDisplay.setEditable(false);
095            bboxDisplay.setBackground(pnl.getBackground());
096            bboxDisplay.addFocusListener(new BoundingBoxSelection.SelectAllOnFocusHandler(bboxDisplay));
097            pnl.add(bboxDisplay, gc);
098    
099            gc.anchor = GridBagConstraints.NORTHEAST;
100            gc.fill = GridBagConstraints.HORIZONTAL;
101            gc.weightx = 0.0;
102            gc.weighty = 0.0;
103            gc.insets = new Insets(5,5,5,5);
104            pnl.add(new JButton(actAdd = new AddAction()), gc);
105            return pnl;
106        }
107    
108        public void addGui(final DownloadDialog gui) {
109            JPanel dlg = new JPanel(new GridBagLayout());
110            gui.addDownloadAreaSelector(dlg, tr("Bookmarks"));
111            GridBagConstraints gc = new GridBagConstraints();
112    
113            bookmarks = new BookmarkList();
114            bookmarks.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
115                public void valueChanged(ListSelectionEvent e) {
116                    Bookmark b = (Bookmark)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(new BBox(currentArea).toStringCSV(","));
156            }
157        }
158    
159        /**
160         * Sets the current download area
161         *
162         * @param area the download area.
163         */
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            public 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            public void actionPerformed(ActionEvent e) {
184                if (currentArea == null) {
185                    JOptionPane.showMessageDialog(
186                            Main.parent,
187                            tr("Currently, there is no download area selected. Please select an area first."),
188                            tr("Information"),
189                            JOptionPane.INFORMATION_MESSAGE
190                    );
191                    return;
192                }
193                Bookmark b = new Bookmark();
194                b.setName(
195                        JOptionPane.showInputDialog(
196                                Main.parent,tr("Please enter a name for the bookmarked download area."),
197                                tr("Name of location"),
198                                JOptionPane.QUESTION_MESSAGE)
199                );
200                b.setArea(currentArea);
201                if (b.getName() != null && !b.getName().equals("")) {
202                    ((DefaultListModel)bookmarks.getModel()).addElement(b);
203                    bookmarks.save();
204                }
205            }
206        }
207    
208        class RemoveAction extends AbstractAction implements ListSelectionListener{
209            public RemoveAction() {
210                //putValue(NAME, tr("Remove"));
211                putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
212                putValue(SHORT_DESCRIPTION, tr("Remove the currently selected bookmarks"));
213                updateEnabledState();
214            }
215    
216            public void actionPerformed(ActionEvent e) {
217                Object[] sels = bookmarks.getSelectedValues();
218                if (sels == null || sels.length == 0)
219                    return;
220                for (Object sel: sels) {
221                    ((DefaultListModel)bookmarks.getModel()).removeElement(sel);
222                }
223                bookmarks.save();
224            }
225            protected void updateEnabledState() {
226                setEnabled(bookmarks.getSelectedIndices().length > 0);
227            }
228            public void valueChanged(ListSelectionEvent e) {
229                updateEnabledState();
230            }
231        }
232    
233        class RenameAction extends AbstractAction implements ListSelectionListener{
234            public RenameAction() {
235                //putValue(NAME, tr("Remove"));
236                putValue(SMALL_ICON, ImageProvider.get("dialogs", "edit"));
237                putValue(SHORT_DESCRIPTION, tr("Rename the currently selected bookmark"));
238                updateEnabledState();
239            }
240    
241            public void actionPerformed(ActionEvent e) {
242                Object[] sels = bookmarks.getSelectedValues();
243                if (sels == null || sels.length != 1)
244                    return;
245                Bookmark b = (Bookmark)sels[0];
246                Object value =
247                    JOptionPane.showInputDialog(
248                            Main.parent,tr("Please enter a name for the bookmarked download area."),
249                            tr("Name of location"),
250                            JOptionPane.QUESTION_MESSAGE,
251                            null,
252                            null,
253                            b.getName()
254                    );
255                if (value != null) {
256                    b.setName(value.toString());
257                    bookmarks.save();
258                    bookmarks.repaint();
259                }
260            }
261            protected void updateEnabledState() {
262                setEnabled(bookmarks.getSelectedIndices().length == 1);
263            }
264            public void valueChanged(ListSelectionEvent e) {
265                updateEnabledState();
266            }
267        }
268    
269        class DoubleClickAdapter extends MouseAdapter {
270            @Override
271            public void mouseClicked(MouseEvent e) {
272                if (!(SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2))
273                    return;
274                int idx = bookmarks.locationToIndex(e.getPoint());
275                if (idx < 0 || idx >= bookmarks.getModel().getSize())
276                    return;
277                Bookmark b = (Bookmark)bookmarks.getModel().getElementAt(idx);
278                parent.startDownload(b.getArea());
279            }
280        }
281    }