001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.bbox;
003
004import java.awt.Color;
005import java.awt.Font;
006import java.awt.FontMetrics;
007import java.awt.Graphics2D;
008import java.awt.Point;
009import java.awt.RenderingHints;
010import java.util.Collection;
011
012import javax.swing.ImageIcon;
013
014import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
015import org.openstreetmap.josm.tools.CheckParameterUtil;
016import org.openstreetmap.josm.tools.ImageProvider;
017
018public class SourceButton {
019
020    // Filled in paint, used in hit
021    private int barX;
022    private int barY;
023    private int barWidth;
024    private int layerHeight;
025
026    private TileSource[] sources;
027
028    private ImageIcon enlargeImage;
029    private ImageIcon shrinkImage;
030
031    private boolean isEnlarged = false;
032
033    private int currentMap;
034
035    public static final int HIDE_OR_SHOW = 1;
036
037    public SourceButton(Collection<TileSource> sources) {
038        setSources(sources);
039        this.currentMap = 2;
040        enlargeImage = ImageProvider.get("layer-switcher-maximize.png");
041        shrinkImage = ImageProvider.get("layer-switcher-minimize.png");
042    }
043    
044    /**
045     * Set the tile sources.
046     * @param sources The tile sources to display
047     * @since 6364
048     */
049    public final void setSources(Collection<TileSource> sources) {
050        CheckParameterUtil.ensureParameterNotNull(sources, "sources");
051        this.sources = sources.toArray(new TileSource[sources.size()]);
052    }
053
054    public void paint(Graphics2D g) {
055        if (isEnlarged) {
056            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
057            int leftPadding = 5;
058            int radioButtonSize = 10;
059            int topPadding = 5;
060            int bottomPadding = 5;
061
062            int textWidth = 0;
063
064            g.setFont(g.getFont().deriveFont(Font.BOLD).deriveFont(15.0f));
065            FontMetrics fm = g.getFontMetrics();
066            for (TileSource source: sources) {
067                int width = fm.stringWidth(source.getName());
068                if (width > textWidth) {
069                    textWidth = width;
070                }
071            }
072
073            barWidth = textWidth + 50;
074            barX = g.getClipBounds().width  - barWidth - shrinkImage.getIconWidth();
075            barY = 30;
076            layerHeight = 20;
077
078            g.setColor(new Color(0, 0, 139, 179));
079            g.fillRoundRect(barX, barY, barWidth + shrinkImage.getIconWidth(), sources.length * layerHeight + topPadding + bottomPadding, 10, 10);
080            for (int i=0; i<sources.length; i++) {
081                g.setColor(Color.WHITE);
082                g.fillOval(barX + leftPadding, barY + topPadding + i * layerHeight + 6, radioButtonSize, radioButtonSize);
083                g.drawString(sources[i].getName(), barX + leftPadding + radioButtonSize + leftPadding, barY + topPadding + i * layerHeight + g.getFontMetrics().getHeight());
084                if (currentMap == i + 2) {
085                    g.setColor(Color.BLACK);
086                    g.fillOval(barX + leftPadding + 1, barY + topPadding + 7 + i * layerHeight, radioButtonSize - 2, radioButtonSize - 2);
087                }
088            }
089
090            g.drawImage(shrinkImage.getImage(), barX + barWidth, barY, null);
091        } else {
092            barWidth = 0;
093            barX = g.getClipBounds().width  - shrinkImage.getIconWidth();
094            barY = 30;
095            g.drawImage(enlargeImage.getImage(), barX + barWidth, barY, null);
096        }
097    }
098
099    public void toggle() {
100        this.isEnlarged = !this.isEnlarged;
101
102    }
103
104    public int hit(Point point) {
105        if (isEnlarged) {
106            if (barX + barWidth < point.x) {
107                if (barY < point.y && point.y < barY + shrinkImage.getIconHeight())
108                    return HIDE_OR_SHOW;
109            } else if (barX < point.x && point.x < barX + barWidth) {
110                int result = (point.y - barY - 5) / layerHeight;
111                if (result >= 0 && result < sources.length) {
112                    currentMap = result + 2;
113                    return currentMap;
114                }
115            }
116        } else {
117            if (barX + barWidth < point.x) {
118                if (barY < point.y && point.y < barY + shrinkImage.getIconHeight())
119                    return HIDE_OR_SHOW;
120            }
121        }
122
123        return 0;
124    }
125
126    public TileSource hitToTileSource(int hit) {
127        if (hit >= 2 && hit < sources.length + 2)
128            return sources[hit - 2];
129        else
130            return null;
131    }
132
133    public void setCurrentMap(TileSource tileSource) {
134        for (int i=0; i<sources.length; i++) {
135            if (sources[i].equals(tileSource)) {
136                currentMap = i + 2;
137                return;
138            }
139        }
140        currentMap = 2;
141    }
142}