Ignore:
Timestamp:
2008-09-14T17:02:09+02:00 (16 years ago)
Author:
stoecker
Message:

added search and selection improvements by Jan Peter Stotz. Closes #1306

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java

    r758 r967  
    22package org.openstreetmap.josm.gui.dialogs;
    33
     4import static org.openstreetmap.josm.tools.I18n.marktr;
    45import static org.openstreetmap.josm.tools.I18n.tr;
    5 import static org.openstreetmap.josm.tools.I18n.marktr;
    66
    77import java.awt.BorderLayout;
     8import java.awt.Color;
    89import java.awt.GridLayout;
     10import java.awt.Rectangle;
    911import java.awt.event.ActionEvent;
    1012import java.awt.event.ActionListener;
     
    1214import java.awt.event.MouseAdapter;
    1315import java.awt.event.MouseEvent;
    14 import java.util.Arrays;
    1516import java.util.Collection;
    1617import java.util.LinkedList;
    17 
     18import java.util.NoSuchElementException;
     19
     20import javax.swing.BorderFactory;
    1821import javax.swing.DefaultListModel;
    1922import javax.swing.JList;
     23import javax.swing.JMenuItem;
    2024import javax.swing.JPanel;
     25import javax.swing.JPopupMenu;
    2126import javax.swing.JScrollPane;
    2227import javax.swing.ListSelectionModel;
     28import javax.swing.SwingConstants;
     29import javax.swing.plaf.basic.BasicArrowButton;
    2330
    2431import org.openstreetmap.josm.Main;
     32import org.openstreetmap.josm.actions.AutoScaleAction;
     33import org.openstreetmap.josm.actions.search.SearchAction;
     34import org.openstreetmap.josm.actions.search.SearchAction.SearchSetting;
    2535import org.openstreetmap.josm.data.SelectionChangedListener;
    2636import org.openstreetmap.josm.data.osm.DataSet;
     37import org.openstreetmap.josm.data.osm.Node;
    2738import org.openstreetmap.josm.data.osm.OsmPrimitive;
     39import org.openstreetmap.josm.data.osm.Way;
     40import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
    2841import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
    2942import org.openstreetmap.josm.gui.SideButton;
     
    3851public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener {
    3952
    40         /**
    41          * The selection's list data.
    42          */
    43         private final DefaultListModel list = new DefaultListModel();
    44         /**
    45          * The display list.
    46          */
    47         private JList displaylist = new JList(list);
    48 
    49         public SelectionListDialog() {
    50                 super(tr("Current Selection"), "selectionlist", tr("Open a selection list window."), KeyEvent.VK_T, 150);
    51                 displaylist.setCellRenderer(new OsmPrimitivRenderer());
    52                 displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    53                 displaylist.addMouseListener(new MouseAdapter(){
    54                         @Override public void mouseClicked(MouseEvent e) {
    55                                 if (e.getClickCount() < 2)
    56                                         return;
    57                                 updateMap();
    58                         }
    59                 });
    60 
    61                 add(new JScrollPane(displaylist), BorderLayout.CENTER);
    62 
    63                 JPanel buttonPanel = new JPanel(new GridLayout(1,2));
    64 
    65                 buttonPanel.add(new SideButton(marktr("Select"), "select", "SelectionList",
    66                 tr("Set the selected elements on the map to the selected items in the list above."), new ActionListener(){
    67                         public void actionPerformed(ActionEvent e) {
    68                                 updateMap();
    69                         }
    70                 }));
    71 
    72                 buttonPanel.add(new SideButton(marktr("Reload"), "refresh", "SelectionList", tr("Refresh the selection list."), new ActionListener(){
    73                         public void actionPerformed(ActionEvent e) {
    74                                 selectionChanged(Main.ds.getSelected());
    75             }
    76                 }));
    77 
    78                 buttonPanel.add(new SideButton(marktr("Search"), "search", "SelectionList", tr("Search for objects."), Main.main.menu.search));
    79 
    80                 add(buttonPanel, BorderLayout.SOUTH);
    81                 selectionChanged(Main.ds.getSelected());
    82 
    83                 DataSet.selListeners.add(this);
    84         }
    85 
    86         @Override public void setVisible(boolean b) {
    87                 super.setVisible(b);
    88                 if (b)
    89                         selectionChanged(Main.ds.getSelected());
    90         }
    91 
    92 
    93         /**
    94          * Called when the selection in the dataset changed.
    95          * @param newSelection The new selection array.
    96          */
    97         public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
    98                 if (list == null || !isVisible())
    99                         return; // selection changed may be received in base class constructor before init
    100                 OsmPrimitive selArr[] = Main.ds.sort(newSelection);
    101                 list.setSize(selArr.length);
    102                 int i = 0;
    103                 for (OsmPrimitive osm : selArr)
    104                         list.setElementAt(osm, i++);
    105         }
    106 
    107         /**
    108          * Sets the selection of the map to the current selected items.
    109          */
    110         public void updateMap() {
    111                 Collection<OsmPrimitive> sel = new LinkedList<OsmPrimitive>();
    112                 for (int i = 0; i < list.getSize(); ++i)
    113                         if (displaylist.isSelectedIndex(i))
    114                                 sel.add((OsmPrimitive)list.get(i));
    115                 Main.ds.setSelected(sel);
    116         }
     53    private static final int SELECTION_HISTORY_SIZE = 10;
     54
     55    /**
     56     * The selection's list data.
     57     */
     58    private final DefaultListModel list = new DefaultListModel();
     59
     60    private LinkedList<Collection<? extends OsmPrimitive>> selectionHistory;
     61
     62    /**
     63     * The display list.
     64     */
     65    private JList displaylist = new JList(list);
     66    private SideButton selectButton;
     67    private SideButton searchButton;
     68    private JPopupMenu popupMenu;
     69    private JMenuItem zoomToElement;
     70
     71    /**
     72     * If the selection changed event is triggered with newSelection equals
     73     * this element, the newSelection will not be added to the selection history
     74     */
     75    private Collection<? extends OsmPrimitive> historyIgnoreSelection = null;
     76
     77    public SelectionListDialog() {
     78        super(tr("Current Selection"), "selectionlist", tr("Open a selection list window."), KeyEvent.VK_T, 150);
     79
     80        selectionHistory = new LinkedList<Collection<? extends OsmPrimitive>>();
     81        popupMenu = new JPopupMenu();
     82        displaylist.setCellRenderer(new OsmPrimitivRenderer());
     83        displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
     84        displaylist.addMouseListener(new MouseAdapter() {
     85            @Override
     86            public void mouseClicked(MouseEvent e) {
     87                if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1)
     88                    updateMap();
     89            }
     90
     91            @Override
     92            public void mousePressed(MouseEvent e) {
     93                showPopupMenu(e);
     94            }
     95
     96            @Override
     97            public void mouseReleased(MouseEvent e) {
     98                showPopupMenu(e);
     99            }
     100
     101        });
     102
     103        add(new JScrollPane(displaylist), BorderLayout.CENTER);
     104
     105        JPanel buttonPanel = new JPanel(new GridLayout(1, 2));
     106
     107        selectButton = new SideButton(marktr("Select"), "select", "SelectionList",
     108                tr("Set the selected elements on the map to the selected items in the list above."),
     109                new ActionListener() {
     110                    public void actionPerformed(ActionEvent e) {
     111                        updateMap();
     112                    }
     113                });
     114        buttonPanel.add(selectButton);
     115        BasicArrowButton selectionHistoryMenuButton = createArrowButton(selectButton);
     116        selectionHistoryMenuButton.addActionListener(new ActionListener() {
     117            public void actionPerformed(ActionEvent e) {
     118                showSelectionHistoryMenu();
     119            }
     120        });
     121        add(buttonPanel, BorderLayout.SOUTH);
     122
     123        zoomToElement = new JMenuItem(tr("Zoom to selected element(s)"));
     124        zoomToElement.addActionListener(new ActionListener() {
     125            public void actionPerformed(ActionEvent e) {
     126                zoomToSelectedElement();
     127            }
     128        });
     129
     130        buttonPanel.add(new SideButton(marktr("Reload"), "refresh", "SelectionList", tr("Refresh the selection list."),
     131                new ActionListener() {
     132                    public void actionPerformed(ActionEvent e) {
     133                        selectionChanged(Main.ds.getSelected());
     134                    }
     135                }));
     136
     137        searchButton = new SideButton(marktr("Search"), "search", "SelectionList", tr("Search for objects."),
     138                Main.main.menu.search);
     139        buttonPanel.add(searchButton);
     140
     141        BasicArrowButton searchHistoryMenuButton = createArrowButton(searchButton);
     142        searchHistoryMenuButton.addActionListener(new ActionListener() {
     143            public void actionPerformed(ActionEvent e) {
     144                showSearchHistoryMenu();
     145            }
     146        });
     147
     148        popupMenu.add(zoomToElement);
     149        JMenuItem zoomToSelection = new JMenuItem(tr("Zoom to selection"));
     150        zoomToSelection.addActionListener(new ActionListener() {
     151            public void actionPerformed(ActionEvent e) {
     152                zoomToSelection();
     153            }
     154        });
     155        popupMenu.add(zoomToSelection);
     156
     157        selectionChanged(Main.ds.getSelected());
     158
     159        DataSet.selListeners.add(this);
     160    }
     161
     162    private BasicArrowButton createArrowButton(SideButton parentButton) {
     163        BasicArrowButton arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null);
     164        arrowButton.setBorder(BorderFactory.createEmptyBorder());
     165        //        selectionHistoryMenuButton.setContentAreaFilled(false);
     166        //        selectionHistoryMenuButton.setOpaque(false);
     167        //        selectionHistoryMenuButton.setBorderPainted(false);
     168        //        selectionHistoryMenuButton.setBackground(null);
     169        parentButton.setLayout(new BorderLayout());
     170        parentButton.add(arrowButton, BorderLayout.EAST);
     171        return arrowButton;
     172    }
     173
     174    @Override
     175    public void setVisible(boolean b) {
     176        super.setVisible(b);
     177        if (b)
     178            selectionChanged(Main.ds.getSelected());
     179    }
     180
     181    protected void showPopupMenu(MouseEvent e) {
     182        if (e.isPopupTrigger()) {
     183            zoomToElement.setVisible(displaylist.getSelectedIndex() >= 0);
     184            popupMenu.show(e.getComponent(), e.getX(), e.getY());
     185        }
     186    }
     187
     188    public void zoomToSelection() {
     189        new AutoScaleAction("selection").actionPerformed(null);
     190    }
     191
     192    /**
     193     * Zooms to the element(s) selected in {@link #displaylist}
     194     */
     195    public void zoomToSelectedElement() {
     196        BoundingXYVisitor box = new BoundingXYVisitor();
     197        int[] selected = displaylist.getSelectedIndices();
     198        if (selected.length == 0)
     199            return;
     200        for (int i = 0; i < selected.length; i++) {
     201            Object o = list.get(selected[i]);
     202            if (o instanceof OsmPrimitive)
     203                ((OsmPrimitive) o).visit(box);
     204        }
     205        if (box.max == null || box.min == null)
     206            return;
     207        box.enlargeBoundingBox();
     208        Main.map.mapView.recalculateCenterScale(box);
     209    }
     210
     211    private void showSelectionHistoryMenu() {
     212        if (selectionHistory.size() == 0)
     213            return;
     214        JPopupMenu historyMenu = new JPopupMenu();
     215        for (Collection<? extends OsmPrimitive> sel : selectionHistory) {
     216            SelectionMenuItem item = new SelectionMenuItem(sel);
     217            historyMenu.add(item);
     218        }
     219        Rectangle r = selectButton.getBounds();
     220        historyMenu.show(selectButton, r.x, r.y + r.height);
     221    }
     222
     223    private void showSearchHistoryMenu() {
     224        if (SearchAction.searchHistory.size() == 0)
     225            return;
     226        JPopupMenu historyMenu = new JPopupMenu();
     227        for (SearchAction.SearchSetting s : SearchAction.searchHistory) {
     228            SearchMenuItem item = new SearchMenuItem(s);
     229            historyMenu.add(item);
     230        }
     231        Rectangle r = searchButton.getBounds();
     232        historyMenu.show(searchButton, r.x, r.y + r.height);
     233    }
     234
     235    /**
     236     * Called when the selection in the dataset changed.
     237     * @param newSelection The new selection array.
     238     */
     239    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
     240        if (list == null || !isVisible())
     241            return; // selection changed may be received in base class constructor before init
     242        OsmPrimitive selArr[] = DataSet.sort(newSelection);
     243        list.setSize(selArr.length);
     244        int i = 0;
     245        for (OsmPrimitive osm : selArr)
     246            list.setElementAt(osm, i++);
     247        if (selectionHistory != null && newSelection.size() > 0 && !newSelection.equals(historyIgnoreSelection)) {
     248            historyIgnoreSelection = null;
     249            try {
     250                // Check if the newSelection has already been added to the history
     251                Collection<? extends OsmPrimitive> first = selectionHistory.getFirst();
     252                if (first.equals(newSelection))
     253                    return;
     254            } catch (NoSuchElementException e) {
     255            }
     256            selectionHistory.addFirst(newSelection);
     257            while (selectionHistory.size() > SELECTION_HISTORY_SIZE)
     258                selectionHistory.removeLast();
     259        }
     260    }
     261
     262    /**
     263     * Sets the selection of the map to the current selected items.
     264     */
     265    public void updateMap() {
     266        Collection<OsmPrimitive> sel = new LinkedList<OsmPrimitive>();
     267        for (int i = 0; i < list.getSize(); ++i)
     268            if (displaylist.isSelectedIndex(i))
     269                sel.add((OsmPrimitive) list.get(i));
     270        Main.ds.setSelected(sel);
     271    }
     272
     273    /**
     274     * A specialized {@link JMenuItem} for presenting one entry of the selection history
     275     *   
     276     * @author Jan Peter Stotz
     277     */
     278    protected class SelectionMenuItem extends JMenuItem implements ActionListener {
     279        protected Collection<? extends OsmPrimitive> sel;
     280
     281        public SelectionMenuItem(Collection<? extends OsmPrimitive> sel) {
     282            super();
     283            this.sel = sel;
     284            int ways = 0;
     285            int nodes = 0;
     286            for (OsmPrimitive o : sel) {
     287                if (o instanceof Way)
     288                    ways++;
     289                else if (o instanceof Node)
     290                    nodes++;
     291            }
     292            setText(String.format(tr("Selection: %d way(s) and %d node(s)"), new Object[] { ways, nodes }));
     293            addActionListener(this);
     294        }
     295
     296        public void actionPerformed(ActionEvent e) {
     297            historyIgnoreSelection = sel;
     298            Main.ds.setSelected(sel);
     299        }
     300
     301    }
     302
     303    /**
     304     * A specialized {@link JMenuItem} for presenting one entry of the search history
     305     *   
     306     * @author Jan Peter Stotz
     307     */
     308    protected class SearchMenuItem extends JMenuItem implements ActionListener {
     309        protected SearchSetting s;
     310
     311        public SearchMenuItem(SearchSetting s) {
     312            super(s.toString());
     313            this.s = s;
     314            addActionListener(this);
     315        }
     316
     317        public void actionPerformed(ActionEvent e) {
     318            SearchAction.searchWithoutHistory(s);
     319        }
     320
     321    }
    117322}
Note: See TracChangeset for help on using the changeset viewer.