1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.gui.bbox;
|
---|
3 |
|
---|
4 | import java.awt.Color;
|
---|
5 | import 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;
|
---|
15 | import java.util.Collection;
|
---|
16 |
|
---|
17 | import javax.swing.ImageIcon;
|
---|
18 | import javax.swing.JComponent;
|
---|
19 |
|
---|
20 | import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
|
---|
21 | import org.openstreetmap.josm.tools.CheckParameterUtil;
|
---|
22 | import org.openstreetmap.josm.tools.ImageProvider;
|
---|
23 |
|
---|
24 | /**
|
---|
25 | * Button that allows to choose the imagery source used for slippy map background.
|
---|
26 | * @since 1390
|
---|
27 | */
|
---|
28 | public class SourceButton extends JComponent {
|
---|
29 |
|
---|
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;
|
---|
34 |
|
---|
35 | private transient TileSource[] sources;
|
---|
36 |
|
---|
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 |
|
---|
51 | /**
|
---|
52 | * Constructs a new {@code SourceButton}.
|
---|
53 | * @param slippyMapBBoxChooser parent slippy map
|
---|
54 | * @param sources list of imagery sources to display
|
---|
55 | */
|
---|
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);
|
---|
66 | }
|
---|
67 |
|
---|
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 | }
|
---|
88 | }
|
---|
89 | };
|
---|
90 |
|
---|
91 | /**
|
---|
92 | * Set the tile sources.
|
---|
93 | * @param sources The tile sources to display
|
---|
94 | * @since 6364
|
---|
95 | */
|
---|
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();
|
---|
132 | }
|
---|
133 | }
|
---|
134 |
|
---|
135 | /**
|
---|
136 | * Toggle the visibility of imagery source list.
|
---|
137 | */
|
---|
138 | public void toggle() {
|
---|
139 | this.isEnlarged = !this.isEnlarged;
|
---|
140 | calculateShownDimension();
|
---|
141 | setPreferredSize(isEnlarged ? shownDimension : hiddenDimension);
|
---|
142 | revalidate();
|
---|
143 | }
|
---|
144 |
|
---|
145 | /**
|
---|
146 | * Changes the current imagery source used for slippy map background.
|
---|
147 | * @param tileSource the new imagery source to use
|
---|
148 | */
|
---|
149 | public void setCurrentMap(TileSource tileSource) {
|
---|
150 | for (int i = 0; i < sources.length; i++) {
|
---|
151 | if (sources[i].equals(tileSource)) {
|
---|
152 | currentMap = i;
|
---|
153 | return;
|
---|
154 | }
|
---|
155 | }
|
---|
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 | }
|
---|
173 | }
|
---|
174 | }
|
---|