source: josm/trunk/src/org/openstreetmap/josm/gui/ImageryMenu.java@ 8443

Last change on this file since 8443 was 8443, checked in by Don-vip, 9 years ago

remove extra whitespaces

  • Property svn:eol-style set to native
File size: 10.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trc;
6
7import java.awt.Component;
8import java.awt.GraphicsEnvironment;
9import java.awt.MenuComponent;
10import java.awt.event.ActionEvent;
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.Collections;
14import java.util.Comparator;
15import java.util.Iterator;
16import java.util.List;
17import java.util.Locale;
18
19import javax.swing.Action;
20import javax.swing.JComponent;
21import javax.swing.JMenu;
22import javax.swing.JMenuItem;
23import javax.swing.JPopupMenu;
24import javax.swing.event.MenuEvent;
25import javax.swing.event.MenuListener;
26
27import org.openstreetmap.josm.Main;
28import org.openstreetmap.josm.actions.AddImageryLayerAction;
29import org.openstreetmap.josm.actions.JosmAction;
30import org.openstreetmap.josm.actions.MapRectifierWMSmenuAction;
31import org.openstreetmap.josm.data.coor.LatLon;
32import org.openstreetmap.josm.data.imagery.ImageryInfo;
33import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
34import org.openstreetmap.josm.data.imagery.Shape;
35import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
36import org.openstreetmap.josm.gui.layer.ImageryLayer;
37import org.openstreetmap.josm.gui.layer.Layer;
38import org.openstreetmap.josm.gui.preferences.imagery.ImageryPreference;
39import org.openstreetmap.josm.tools.ImageProvider;
40
41/**
42 * Imagery menu, holding entries for imagery preferences, offset actions and dynamic imagery entries
43 * depending on current maview coordinates.
44 * @since 3737
45 */
46public class ImageryMenu extends JMenu implements LayerChangeListener {
47
48 /**
49 * Compare ImageryInfo objects alphabetically by name.
50 *
51 * ImageryInfo objects are normally sorted by country code first
52 * (for the preferences). We don't want this in the imagery menu.
53 */
54 public static final Comparator<ImageryInfo> alphabeticImageryComparator = new Comparator<ImageryInfo>() {
55 @Override
56 public int compare(ImageryInfo ii1, ImageryInfo ii2) {
57 return ii1.getName().toLowerCase(Locale.ENGLISH).compareTo(ii2.getName().toLowerCase(Locale.ENGLISH));
58 }
59 };
60
61 private transient Action offsetAction = new JosmAction(
62 tr("Imagery offset"), "mapmode/adjustimg", tr("Adjust imagery offset"), null, false, false) {
63 {
64 putValue("toolbar", "imagery-offset");
65 Main.toolbar.register(this);
66 }
67 @Override
68 public void actionPerformed(ActionEvent e) {
69 Collection<ImageryLayer> layers = Main.map.mapView.getLayersOfType(ImageryLayer.class);
70 if (layers.isEmpty()) {
71 setEnabled(false);
72 return;
73 }
74 Component source = null;
75 if (e.getSource() instanceof Component) {
76 source = (Component)e.getSource();
77 }
78 JPopupMenu popup = new JPopupMenu();
79 if (layers.size() == 1) {
80 JComponent c = layers.iterator().next().getOffsetMenuItem(popup);
81 if (c instanceof JMenuItem) {
82 ((JMenuItem) c).getAction().actionPerformed(e);
83 } else {
84 if (source == null) return;
85 popup.show(source, source.getWidth()/2, source.getHeight()/2);
86 }
87 return;
88 }
89 if (source == null) return;
90 for (ImageryLayer layer : layers) {
91 JMenuItem layerMenu = layer.getOffsetMenuItem();
92 layerMenu.setText(layer.getName());
93 layerMenu.setIcon(layer.getIcon());
94 popup.add(layerMenu);
95 }
96 popup.show(source, source.getWidth()/2, source.getHeight()/2);
97 }
98 };
99
100 private final JMenuItem singleOffset = new JMenuItem(offsetAction);
101 private JMenuItem offsetMenuItem = singleOffset;
102 private final MapRectifierWMSmenuAction rectaction = new MapRectifierWMSmenuAction();
103
104 /**
105 * Constructs a new {@code ImageryMenu}.
106 * @param subMenu submenu in that contains plugin-managed additional imagery layers
107 */
108 public ImageryMenu(JMenu subMenu) {
109 super(tr("Imagery"));
110 setupMenuScroller();
111 MapView.addLayerChangeListener(this);
112 // build dynamically
113 addMenuListener(new MenuListener() {
114 @Override
115 public void menuSelected(MenuEvent e) {
116 refreshImageryMenu();
117 }
118
119 @Override
120 public void menuDeselected(MenuEvent e) {
121 }
122
123 @Override
124 public void menuCanceled(MenuEvent e) {
125 }
126 });
127 MainMenu.add(subMenu, rectaction);
128 }
129
130 private void setupMenuScroller() {
131 if (!GraphicsEnvironment.isHeadless()) {
132 MenuScroller.setScrollerFor(this, 150, 2);
133 }
134 }
135
136 /**
137 * Refresh imagery menu.
138 *
139 * Outside this class only called in {@link ImageryPreference#initialize()}.
140 * (In order to have actions ready for the toolbar, see #8446.)
141 */
142 public void refreshImageryMenu() {
143 removeDynamicItems();
144
145 addDynamic(offsetMenuItem);
146 addDynamicSeparator();
147
148 // for each configured ImageryInfo, add a menu entry.
149 final List<ImageryInfo> savedLayers = new ArrayList<>(ImageryLayerInfo.instance.getLayers());
150 Collections.sort(savedLayers, alphabeticImageryComparator);
151 for (final ImageryInfo u : savedLayers) {
152 addDynamic(new AddImageryLayerAction(u));
153 }
154
155 // list all imagery entries where the current map location
156 // is within the imagery bounds
157 if (Main.isDisplayingMapView()) {
158 MapView mv = Main.map.mapView;
159 LatLon pos = mv.getProjection().eastNorth2latlon(mv.getCenter());
160 final List<ImageryInfo> inViewLayers = new ArrayList<>();
161
162 for (ImageryInfo i : ImageryLayerInfo.instance.getDefaultLayers()) {
163 if (i.getBounds() != null && i.getBounds().contains(pos)) {
164 inViewLayers.add(i);
165 }
166 }
167 // Do not suggest layers already in use
168 inViewLayers.removeAll(ImageryLayerInfo.instance.getLayers());
169 // For layers containing complex shapes, check that center is in one
170 // of its shapes (fix #7910)
171 for (Iterator<ImageryInfo> iti = inViewLayers.iterator(); iti.hasNext(); ) {
172 List<Shape> shapes = iti.next().getBounds().getShapes();
173 if (shapes != null && !shapes.isEmpty()) {
174 boolean found = false;
175 for (Iterator<Shape> its = shapes.iterator(); its.hasNext() && !found; ) {
176 found = its.next().contains(pos);
177 }
178 if (!found) {
179 iti.remove();
180 }
181 }
182 }
183 if (!inViewLayers.isEmpty()) {
184 Collections.sort(inViewLayers, alphabeticImageryComparator);
185 addDynamicSeparator();
186 for (ImageryInfo i : inViewLayers) {
187 addDynamic(new AddImageryLayerAction(i));
188 }
189 }
190 }
191
192 addDynamicSeparator();
193 JMenu subMenu = Main.main.menu.imagerySubMenu;
194 int heightUnrolled = 30*(getItemCount()+subMenu.getItemCount());
195 if (heightUnrolled < Main.panel.getHeight()) {
196 // add all items of submenu if they will fit on screen
197 int n = subMenu.getItemCount();
198 for (int i=0; i<n; i++) {
199 addDynamic(subMenu.getItem(i).getAction());
200 }
201 } else {
202 // or add the submenu itself
203 addDynamic(subMenu);
204 }
205 }
206
207 private JMenuItem getNewOffsetMenu(){
208 if (!Main.isDisplayingMapView()) {
209 offsetAction.setEnabled(false);
210 return singleOffset;
211 }
212 Collection<ImageryLayer> layers = Main.map.mapView.getLayersOfType(ImageryLayer.class);
213 if (layers.isEmpty()) {
214 offsetAction.setEnabled(false);
215 return singleOffset;
216 }
217 offsetAction.setEnabled(true);
218 JMenu newMenu = new JMenu(trc("layer","Offset"));
219 newMenu.setIcon(ImageProvider.get("mapmode", "adjustimg"));
220 newMenu.setAction(offsetAction);
221 if (layers.size() == 1)
222 return (JMenuItem)layers.iterator().next().getOffsetMenuItem(newMenu);
223 for (ImageryLayer layer : layers) {
224 JMenuItem layerMenu = layer.getOffsetMenuItem();
225 layerMenu.setText(layer.getName());
226 layerMenu.setIcon(layer.getIcon());
227 newMenu.add(layerMenu);
228 }
229 return newMenu;
230 }
231
232 public void refreshOffsetMenu() {
233 offsetMenuItem = getNewOffsetMenu();
234 }
235
236 @Override
237 public void activeLayerChange(Layer oldLayer, Layer newLayer) {
238 }
239
240 @Override
241 public void layerAdded(Layer newLayer) {
242 if (newLayer instanceof ImageryLayer) {
243 refreshOffsetMenu();
244 }
245 }
246
247 @Override
248 public void layerRemoved(Layer oldLayer) {
249 if (oldLayer instanceof ImageryLayer) {
250 refreshOffsetMenu();
251 }
252 }
253
254 /**
255 * Collection to store temporary menu items. They will be deleted
256 * (and possibly recreated) when refreshImageryMenu() is called.
257 * @since 5803
258 */
259 private List<Object> dynamicItems = new ArrayList<>(20);
260
261 /**
262 * Remove all the items in @field dynamicItems collection
263 * @since 5803
264 */
265 private void removeDynamicItems() {
266 for (Object item : dynamicItems) {
267 if (item instanceof JMenuItem) {
268 remove((JMenuItem)item);
269 }
270 if (item instanceof MenuComponent) {
271 remove((MenuComponent)item);
272 }
273 if (item instanceof Component) {
274 remove((Component)item);
275 }
276 }
277 dynamicItems.clear();
278 }
279
280 private void addDynamicSeparator() {
281 JPopupMenu.Separator s = new JPopupMenu.Separator();
282 dynamicItems.add(s);
283 add(s);
284 }
285
286 private void addDynamic(Action a) {
287 dynamicItems.add(this.add(a));
288 }
289
290 private void addDynamic(JMenuItem it) {
291 dynamicItems.add(this.add(it));
292 }
293}
Note: See TracBrowser for help on using the repository browser.