Changeset 15054 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2019-05-06T01:08:10+02:00 (6 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/ImageryMenu.java
r14548 r15054 12 12 import java.util.Collection; 13 13 import java.util.Comparator; 14 import java.util. Iterator;14 import java.util.EnumMap; 15 15 import java.util.List; 16 16 import java.util.Locale; 17 import java.util.Map; 18 import java.util.Map.Entry; 17 19 import java.util.Optional; 20 import java.util.stream.Collectors; 18 21 19 22 import javax.swing.Action; … … 30 33 import org.openstreetmap.josm.data.coor.LatLon; 31 34 import org.openstreetmap.josm.data.imagery.ImageryInfo; 35 import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryCategory; 32 36 import org.openstreetmap.josm.data.imagery.ImageryLayerInfo; 33 37 import org.openstreetmap.josm.data.imagery.Shape; … … 39 43 import org.openstreetmap.josm.gui.preferences.imagery.ImageryPreference; 40 44 import org.openstreetmap.josm.tools.ImageProvider; 45 import org.openstreetmap.josm.tools.ImageProvider.ImageSizes; 46 import org.openstreetmap.josm.tools.Logging; 41 47 42 48 /** … … 139 145 140 146 /** 147 * For layers containing complex shapes, check that center is in one of its shapes (fix #7910) 148 * @param info layer info 149 * @param pos center 150 * @return {@code true} if center is in one of info shapes 151 */ 152 private static boolean isPosInOneShapeIfAny(ImageryInfo info, LatLon pos) { 153 List<Shape> shapes = info.getBounds().getShapes(); 154 return shapes == null || shapes.stream().anyMatch(s -> s.contains(pos)); 155 } 156 157 /** 141 158 * Refresh imagery menu. 142 159 * … … 147 164 removeDynamicItems(); 148 165 149 addDynamic(offsetMenuItem );166 addDynamic(offsetMenuItem, null); 150 167 addDynamicSeparator(); 151 168 … … 154 171 savedLayers.sort(alphabeticImageryComparator); 155 172 for (final ImageryInfo u : savedLayers) { 156 addDynamic(trackJosmAction(new AddImageryLayerAction(u))); 157 } 158 159 // list all imagery entries where the current map location 160 // is within the imagery bounds 173 addDynamic(trackJosmAction(new AddImageryLayerAction(u)), null); 174 } 175 176 // list all imagery entries where the current map location is within the imagery bounds 161 177 if (MainApplication.isDisplayingMapView()) { 162 178 MapView mv = MainApplication.getMap().mapView; 163 179 LatLon pos = mv.getProjection().eastNorth2latlon(mv.getCenter()); 164 final List<ImageryInfo> inViewLayers = new ArrayList<>(); 165 166 for (ImageryInfo i : ImageryLayerInfo.instance.getDefaultLayers()) { 167 if (i.getBounds() != null && i.getBounds().contains(pos)) { 168 inViewLayers.add(i); 169 } 170 } 171 // Do not suggest layers already in use 172 inViewLayers.removeAll(ImageryLayerInfo.instance.getLayers()); 173 // For layers containing complex shapes, check that center is in one 174 // of its shapes (fix #7910) 175 for (Iterator<ImageryInfo> iti = inViewLayers.iterator(); iti.hasNext();) { 176 List<Shape> shapes = iti.next().getBounds().getShapes(); 177 if (shapes != null && !shapes.isEmpty()) { 178 boolean found = false; 179 for (Iterator<Shape> its = shapes.iterator(); its.hasNext() && !found;) { 180 found = its.next().contains(pos); 181 } 182 if (!found) { 183 iti.remove(); 184 } 185 } 186 } 180 final List<ImageryInfo> alreadyInUse = ImageryLayerInfo.instance.getLayers(); 181 final List<ImageryInfo> inViewLayers = ImageryLayerInfo.instance.getDefaultLayers() 182 .stream().filter(i -> i.getBounds() != null && i.getBounds().contains(pos) 183 && !alreadyInUse.contains(i) && isPosInOneShapeIfAny(i, pos)) 184 .sorted(alphabeticImageryComparator) 185 .collect(Collectors.toList()); 187 186 if (!inViewLayers.isEmpty()) { 188 inViewLayers.sort(alphabeticImageryComparator);189 187 addDynamicSeparator(); 190 188 for (ImageryInfo i : inViewLayers) { 191 addDynamic(trackJosmAction(new AddImageryLayerAction(i))); 189 addDynamic(trackJosmAction(new AddImageryLayerAction(i)), i.getImageryCategory()); 190 } 191 } 192 if (!dynamicNonPhotoItems.isEmpty()) { 193 addDynamicSeparator(); 194 for (Entry<ImageryCategory, List<JMenuItem>> e : dynamicNonPhotoItems.entrySet()) { 195 ImageryCategory cat = e.getKey(); 196 JMenuItem categoryMenu = new JMenu(cat.getDescription()); 197 categoryMenu.setIcon(cat.getIcon(ImageSizes.MENU)); 198 for (JMenuItem it : e.getValue()) { 199 categoryMenu.add(it); 200 } 201 dynamicNonPhotoMenus.add(add(categoryMenu)); 192 202 } 193 203 } … … 201 211 int n = subMenu.getItemCount(); 202 212 for (int i = 0; i < n; i++) { 203 addDynamic(subMenu.getItem(i).getAction() );213 addDynamic(subMenu.getItem(i).getAction(), null); 204 214 } 205 215 } else { 206 216 // or add the submenu itself 207 addDynamic(subMenu );217 addDynamic(subMenu, null); 208 218 } 209 219 } … … 257 267 258 268 /** 259 * Collection to store temporarymenu items. They will be deleted269 * List to store temporary "photo" menu items. They will be deleted 260 270 * (and possibly recreated) when refreshImageryMenu() is called. 261 * @since 5803262 271 */ 263 272 private final List<Object> dynamicItems = new ArrayList<>(20); 273 /** 274 * Map to store temporary "not photo" menu items. They will be deleted 275 * (and possibly recreated) when refreshImageryMenu() is called. 276 */ 277 private final Map<ImageryCategory, List<JMenuItem>> dynamicNonPhotoItems = new EnumMap<>(ImageryCategory.class); 278 /** 279 * List to store temporary "not photo" submenus. They will be deleted 280 * (and possibly recreated) when refreshImageryMenu() is called. 281 */ 282 private final List<JMenuItem> dynamicNonPhotoMenus = new ArrayList<>(20); 264 283 private final List<JosmAction> dynJosmActions = new ArrayList<>(20); 265 284 … … 271 290 dynJosmActions.forEach(JosmAction::destroy); 272 291 dynJosmActions.clear(); 273 for (Object item : dynamicItems) { 274 if (item instanceof JMenuItem) { 275 Optional.ofNullable(((JMenuItem) item).getAction()).ifPresent(MainApplication.getToolbar()::unregister); 276 remove((JMenuItem) item); 277 } else if (item instanceof MenuComponent) { 278 remove((MenuComponent) item); 279 } else if (item instanceof Component) { 280 remove((Component) item); 281 } 282 } 292 dynamicItems.forEach(this::removeDynamicItem); 283 293 dynamicItems.clear(); 294 dynamicNonPhotoMenus.forEach(this::removeDynamicItem); 295 dynamicItems.clear(); 296 dynamicNonPhotoItems.clear(); 297 } 298 299 private void removeDynamicItem(Object item) { 300 if (item instanceof JMenuItem) { 301 Optional.ofNullable(((JMenuItem) item).getAction()).ifPresent(MainApplication.getToolbar()::unregister); 302 remove((JMenuItem) item); 303 } else if (item instanceof MenuComponent) { 304 remove((MenuComponent) item); 305 } else if (item instanceof Component) { 306 remove((Component) item); 307 } else { 308 Logging.error("Unknown imagery menu item type: {0}", item); 309 } 284 310 } 285 311 … … 290 316 } 291 317 292 private void addDynamic(Action a) { 293 dynamicItems.add(this.add(a)); 294 } 295 296 private void addDynamic(JMenuItem it) { 297 dynamicItems.add(this.add(it)); 318 private void addDynamic(Action a, ImageryCategory category) { 319 JMenuItem item = createActionComponent(a); 320 item.setAction(a); 321 doAddDynamic(item, category); 322 } 323 324 private void addDynamic(JMenuItem it, ImageryCategory category) { 325 doAddDynamic(it, category); 326 } 327 328 private void doAddDynamic(JMenuItem item, ImageryCategory category) { 329 if (category == null || category == ImageryCategory.PHOTO) { 330 dynamicItems.add(this.add(item)); 331 } else { 332 dynamicNonPhotoItems.computeIfAbsent(category, x -> new ArrayList<>()).add(item); 333 } 298 334 } 299 335 -
trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java
r14695 r15054 190 190 /** 191 191 * Executes asynchronously a runnable in 192 * <a href="https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>. 192 * <a href="https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>, 193 * except if we're already in the EDT: in this case the runnable is executed synchronously. 193 194 * @param task The runnable to execute 194 195 * @see SwingUtilities#invokeLater
Note:
See TracChangeset
for help on using the changeset viewer.