Changeset 12955 in josm


Ignore:
Timestamp:
2017-10-09T00:17:55+02:00 (2 months ago)
Author:
bastiK
Message:

applied #15414 - Redesign of SlippyMapBBoxChooser's SourceButton (patch by ris)

Location:
trunk/src/org/openstreetmap/josm/gui
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/bbox/SlippyMapBBoxChooser.java

    r12931 r12955  
    2222import java.util.concurrent.CopyOnWriteArrayList;
    2323
     24import javax.swing.ButtonModel;
     25import javax.swing.JToggleButton;
    2426import javax.swing.JOptionPane;
    2527import javax.swing.SpringLayout;
     28import javax.swing.event.ChangeListener;
     29import javax.swing.event.ChangeEvent;
    2630
    2731import org.openstreetmap.gui.jmapviewer.Coordinate;
     
    4448import org.openstreetmap.josm.data.imagery.TileLoaderFactory;
    4549import org.openstreetmap.josm.data.osm.BBox;
     50import org.openstreetmap.josm.data.preferences.BooleanProperty;
    4651import org.openstreetmap.josm.data.preferences.StringProperty;
    4752import org.openstreetmap.josm.gui.MainApplication;
     
    5661 * This panel displays a map and lets the user chose a {@link BBox}.
    5762 */
    58 public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, MainLayerManager.ActiveLayerChangeListener {
     63public class SlippyMapBBoxChooser extends JMapViewer implements BBoxChooser, ChangeListener, MainLayerManager.ActiveLayerChangeListener {
    5964
    6065    /**
     
    121126
    122127    private static final StringProperty PROP_MAPSTYLE = new StringProperty("slippy_map_chooser.mapstyle", "Mapnik");
     128    private static final BooleanProperty PROP_SHOWDLAREA = new BooleanProperty("slippy_map_chooser.show_downloaded_area", true);
    123129    /**
    124130     * The property name used for the resize button.
     
    131137
    132138    private final SizeButton iSizeButton;
     139    private final ButtonModel showDownloadAreaButtonModel;
    133140    private final SourceButton iSourceButton;
    134141    private transient Bounds bbox;
     
    173180        List<TileSource> tileSources = getAllTileSources();
    174181
    175         iSourceButton = new SourceButton(this, tileSources);
     182        this.showDownloadAreaButtonModel = new JToggleButton.ToggleButtonModel();
     183        this.showDownloadAreaButtonModel.setSelected(PROP_SHOWDLAREA.get());
     184        this.showDownloadAreaButtonModel.addChangeListener(this);
     185        iSourceButton = new SourceButton(this, tileSources, this.showDownloadAreaButtonModel);
    176186        add(iSourceButton);
    177         springLayout.putConstraint(SpringLayout.EAST, iSourceButton, 0, SpringLayout.EAST, this);
    178         springLayout.putConstraint(SpringLayout.NORTH, iSourceButton, 30, SpringLayout.NORTH, this);
     187        springLayout.putConstraint(SpringLayout.EAST, iSourceButton, -2, SpringLayout.EAST, this);
     188        springLayout.putConstraint(SpringLayout.NORTH, iSourceButton, 2, SpringLayout.NORTH, this);
    179189
    180190        iSizeButton = new SizeButton(this);
     
    231241        // enough to make sharing code impractical)
    232242        final OsmDataLayer editLayer = MainApplication.getLayerManager().getEditLayer();
    233         if (editLayer != null && Config.getPref().getBoolean("draw.data.downloaded_area", true) && !editLayer.data.getDataSources().isEmpty()) {
     243        if (editLayer != null && this.showDownloadAreaButtonModel.isSelected() && !editLayer.data.getDataSources().isEmpty()) {
    234244            // initialize area with current viewport
    235245            Rectangle b = this.getBounds();
     
    271281    @Override
    272282    public void activeOrEditLayerChanged(MainLayerManager.ActiveLayerChangeEvent e) {
     283        this.repaint();
     284    }
     285
     286    @Override
     287    public void stateChanged(ChangeEvent e) {
     288        // fired for the stateChanged event of this.showDownloadAreaButtonModel
     289        PROP_SHOWDLAREA.put(this.showDownloadAreaButtonModel.isSelected());
    273290        this.repaint();
    274291    }
     
    342359        this.setTileSource(tileSource);
    343360        PROP_MAPSTYLE.put(tileSource.getName()); // TODO Is name really unique?
     361        if (this.iSourceButton.getCurrentSource() != tileSource) { // prevent infinite recursion
     362            this.iSourceButton.setCurrentMap(tileSource);
     363        }
    344364    }
    345365
  • trunk/src/org/openstreetmap/josm/gui/bbox/SourceButton.java

    r12597 r12955  
    22package org.openstreetmap.josm.gui.bbox;
    33
    4 import java.awt.Color;
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
    56import java.awt.Dimension;
    6 import java.awt.Font;
    7 import java.awt.FontMetrics;
    8 import java.awt.Graphics;
    9 import java.awt.Graphics2D;
    10 import java.awt.Point;
    11 import java.awt.RenderingHints;
    12 import java.awt.event.MouseAdapter;
    13 import java.awt.event.MouseEvent;
    14 import java.awt.event.MouseListener;
     7import java.awt.event.ActionListener;
     8import java.awt.event.ActionEvent;
     9import java.util.ArrayList;
    1510import java.util.Collection;
     11import java.util.Collections;
     12import java.util.Enumeration;
     13import java.util.List;
    1614
    17 import javax.swing.ImageIcon;
    18 import javax.swing.JComponent;
     15import javax.swing.AbstractButton;
     16import javax.swing.ButtonGroup;
     17import javax.swing.ButtonModel;
     18import javax.swing.JCheckBoxMenuItem;
     19import javax.swing.JPopupMenu;
     20import javax.swing.JRadioButtonMenuItem;
     21import javax.swing.JToggleButton;
    1922
    2023import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
     24import org.openstreetmap.josm.gui.widgets.PopupMenuButton;
    2125import org.openstreetmap.josm.tools.CheckParameterUtil;
    2226import org.openstreetmap.josm.tools.ImageProvider;
     
    2630 * @since 1390
    2731 */
    28 public class SourceButton extends JComponent {
     32public class SourceButton extends PopupMenuButton {
     33    protected class TileSourceButtonModel extends JToggleButton.ToggleButtonModel implements ActionListener {
     34        protected final TileSource tileSource;
    2935
    30     private static final int LAYER_HEIGHT = 20;
    31     private static final int LEFT_PADDING = 5;
    32     private static final int TOP_PADDING = 5;
    33     private static final int BOTTOM_PADDING = 5;
     36        public TileSourceButtonModel(TileSource tileSource_) {
     37            super();
     38            this.tileSource = tileSource_;
     39            this.addActionListener(this);
     40        }
    3441
    35     private transient TileSource[] sources;
     42        @Override
     43        public void actionPerformed(ActionEvent e) {
     44            if (SourceButton.this.slippyMapBBoxChooser.getTileController().getTileSource() != this.tileSource) { // prevent infinite recursion
     45                SourceButton.this.slippyMapBBoxChooser.toggleMapSource(this.tileSource);
     46            }
     47        }
     48    }
    3649
    37     private final ImageIcon enlargeImage;
    38     private final ImageIcon shrinkImage;
    39     private final Dimension hiddenDimension;
    40 
    41     // Calculated after component is added to container
    42     private int barWidth;
    43     private Dimension shownDimension;
    44     private Font font;
    45 
    46     private boolean isEnlarged;
    47 
    48     private int currentMap;
    49     private final SlippyMapBBoxChooser slippyMapBBoxChooser;
     50    protected final SlippyMapBBoxChooser slippyMapBBoxChooser;
     51    protected final ButtonModel showDownloadAreaButtonModel;
     52    private List<TileSource> sources;
     53    private ButtonGroup sourceButtonGroup;
    5054
    5155    /**
     
    5458     * @param sources list of imagery sources to display
    5559     */
    56     public SourceButton(SlippyMapBBoxChooser slippyMapBBoxChooser, Collection<TileSource> sources) {
    57         this.slippyMapBBoxChooser = slippyMapBBoxChooser;
    58         setSources(sources);
    59         enlargeImage = ImageProvider.get("layer-switcher-maximize");
    60         shrinkImage = ImageProvider.get("layer-switcher-minimize");
    61 
    62         hiddenDimension = new Dimension(enlargeImage.getIconWidth(), enlargeImage.getIconHeight());
    63         setPreferredSize(hiddenDimension);
    64 
    65         addMouseListener(mouseListener);
     60    public SourceButton(
     61        SlippyMapBBoxChooser slippyMapBBoxChooser_,
     62        Collection<TileSource> sources_,
     63        ButtonModel showDownloadAreaButtonModel_
     64    ) {
     65        super(new ImageProvider("dialogs/layerlist").getResource().getImageIcon(new Dimension(16, 16)));
     66        this.showDownloadAreaButtonModel = showDownloadAreaButtonModel_;
     67        this.slippyMapBBoxChooser = slippyMapBBoxChooser_;
     68        this.setPreferredSize(new Dimension(24, 24));
     69        this.setSources(sources_);
    6670    }
    6771
    68     private final transient MouseListener mouseListener = new MouseAdapter() {
    69         @Override
    70         public void mouseReleased(MouseEvent e) {
    71             if (e.getButton() == MouseEvent.BUTTON1) {
    72                 Point point = e.getPoint();
    73                 if (isEnlarged) {
    74                     if (barWidth < point.x && point.y < shrinkImage.getIconHeight()) {
    75                         toggle();
    76                     } else {
    77                         int result = (point.y - 5) / LAYER_HEIGHT;
    78                         if (result >= 0 && result < SourceButton.this.sources.length) {
    79                             SourceButton.this.slippyMapBBoxChooser.toggleMapSource(SourceButton.this.sources[result]);
    80                             currentMap = result;
    81                             toggle();
    82                         }
    83                     }
    84                 } else {
    85                     toggle();
    86                 }
    87             }
     72    protected void generatePopupMenu() {
     73        JPopupMenu pm = new JPopupMenu();
     74        this.sourceButtonGroup = new ButtonGroup();
     75        for (TileSource ts : this.sources) {
     76            JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(ts.getName());
     77            TileSourceButtonModel buttonModel = new TileSourceButtonModel(ts);
     78            menuItem.setModel(buttonModel);
     79            pm.add(menuItem);
     80            this.sourceButtonGroup.add(menuItem);
     81
     82            // attempt to initialize button group matching current state of slippyMapBBoxChooser
     83            buttonModel.setSelected(this.slippyMapBBoxChooser.getTileController().getTileSource() == ts);
    8884        }
    89     };
     85
     86        pm.addSeparator();
     87
     88        JCheckBoxMenuItem showDownloadAreaItem = new JCheckBoxMenuItem(tr("Show downloaded area"));
     89        showDownloadAreaItem.setModel(this.showDownloadAreaButtonModel);
     90        pm.add(showDownloadAreaItem);
     91
     92        this.setPopupMenu(pm);
     93    }
     94
     95    private void setSourceDefault() {
     96        Enumeration<AbstractButton> elems = this.sourceButtonGroup.getElements();
     97        if (elems.hasMoreElements()) {
     98            elems.nextElement().setSelected(true);
     99        }
     100    }
    90101
    91102    /**
     
    94105     * @since 6364
    95106     */
    96     public final void setSources(Collection<TileSource> sources) {
    97         CheckParameterUtil.ensureParameterNotNull(sources, "sources");
    98         this.sources = sources.toArray(new TileSource[sources.size()]);
    99         shownDimension = null;
    100     }
    101 
    102     @Override
    103     protected void paintComponent(Graphics graphics) {
    104         Graphics2D g = (Graphics2D) graphics.create();
    105         try {
    106             calculateShownDimension();
    107             g.setFont(font);
    108             if (isEnlarged) {
    109                 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    110                 int radioButtonSize = 10;
    111 
    112                 g.setColor(new Color(0, 0, 139, 179));
    113                 g.fillRoundRect(0, 0, barWidth + shrinkImage.getIconWidth(),
    114                         sources.length * LAYER_HEIGHT + TOP_PADDING + BOTTOM_PADDING, 10, 10);
    115                 for (int i = 0; i < sources.length; i++) {
    116                     g.setColor(Color.WHITE);
    117                     g.fillOval(LEFT_PADDING, TOP_PADDING + i * LAYER_HEIGHT + 6, radioButtonSize, radioButtonSize);
    118                     g.drawString(sources[i].getName(), LEFT_PADDING + radioButtonSize + LEFT_PADDING,
    119                             TOP_PADDING + i * LAYER_HEIGHT + g.getFontMetrics().getHeight());
    120                     if (currentMap == i) {
    121                         g.setColor(Color.BLACK);
    122                         g.fillOval(LEFT_PADDING + 1, TOP_PADDING + 7 + i * LAYER_HEIGHT, radioButtonSize - 2, radioButtonSize - 2);
    123                     }
    124                 }
    125 
    126                 g.drawImage(shrinkImage.getImage(), barWidth, 0, null);
    127             } else {
    128                 g.drawImage(enlargeImage.getImage(), 0, 0, null);
    129             }
    130         } finally {
    131             g.dispose();
     107    public final void setSources(Collection<TileSource> sources_) {
     108        CheckParameterUtil.ensureParameterNotNull(sources_, "sources_");
     109        this.sources = new ArrayList<TileSource>(sources_);
     110        this.generatePopupMenu();
     111        if (this.sourceButtonGroup.getSelection() == null) {
     112            this.setSourceDefault();
    132113        }
    133114    }
    134115
    135116    /**
    136      * Toggle the visibility of imagery source list.
     117     * Get the tile sources.
     118     * @return unmodifiable collection of tile sources
    137119     */
    138     public void toggle() {
    139         this.isEnlarged = !this.isEnlarged;
    140         calculateShownDimension();
    141         setPreferredSize(isEnlarged ? shownDimension : hiddenDimension);
    142         revalidate();
     120    public final Collection<TileSource> getSources() {
     121        return Collections.unmodifiableCollection(this.sources);
     122    }
     123
     124    /**
     125     * Get the currently-selected tile source.
     126     */
     127    public final TileSource getCurrentSource() {
     128        TileSourceButtonModel buttonModel = (TileSourceButtonModel) this.sourceButtonGroup.getSelection();
     129        if (buttonModel != null) {
     130            return buttonModel.tileSource;
     131        }
     132        return null;
    143133    }
    144134
     
    148138     */
    149139    public void setCurrentMap(TileSource tileSource) {
    150         for (int i = 0; i < sources.length; i++) {
    151             if (sources[i].equals(tileSource)) {
    152                 currentMap = i;
     140        Enumeration<AbstractButton> elems = this.sourceButtonGroup.getElements();
     141        while (elems.hasMoreElements()) {
     142            AbstractButton b = elems.nextElement();
     143            if (((TileSourceButtonModel) b.getModel()).tileSource == tileSource) {
     144                b.setSelected(true);
    153145                return;
    154146            }
    155147        }
    156         currentMap = 0;
    157     }
    158 
    159     private void calculateShownDimension() {
    160         if (shownDimension == null) {
    161             font = getFont().deriveFont(Font.BOLD).deriveFont(15.0f);
    162             int textWidth = 0;
    163             FontMetrics fm = getFontMetrics(font);
    164             for (TileSource source: sources) {
    165                 int width = fm.stringWidth(source.getName());
    166                 if (width > textWidth) {
    167                     textWidth = width;
    168                 }
    169             }
    170             barWidth = textWidth + 50;
    171             shownDimension = new Dimension(barWidth + shrinkImage.getIconWidth(), sources.length * LAYER_HEIGHT + TOP_PADDING + BOTTOM_PADDING);
    172         }
     148        // failed to find the correct one
     149        this.setSourceDefault();
    173150    }
    174151}
Note: See TracChangeset for help on using the changeset viewer.