Changeset 15054 in josm


Ignore:
Timestamp:
2019-05-06T01:08:10+02:00 (2 weeks ago)
Author:
Don-vip
Message:

fix #17676 - display dynamic imagery entries in sub menus when they have category not equal to photo

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

Legend:

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

    r14548 r15054  
    1212import java.util.Collection;
    1313import java.util.Comparator;
    14 import java.util.Iterator;
     14import java.util.EnumMap;
    1515import java.util.List;
    1616import java.util.Locale;
     17import java.util.Map;
     18import java.util.Map.Entry;
    1719import java.util.Optional;
     20import java.util.stream.Collectors;
    1821
    1922import javax.swing.Action;
     
    3033import org.openstreetmap.josm.data.coor.LatLon;
    3134import org.openstreetmap.josm.data.imagery.ImageryInfo;
     35import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryCategory;
    3236import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
    3337import org.openstreetmap.josm.data.imagery.Shape;
     
    3943import org.openstreetmap.josm.gui.preferences.imagery.ImageryPreference;
    4044import org.openstreetmap.josm.tools.ImageProvider;
     45import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
     46import org.openstreetmap.josm.tools.Logging;
    4147
    4248/**
     
    139145
    140146    /**
     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    /**
    141158     * Refresh imagery menu.
    142159     *
     
    147164        removeDynamicItems();
    148165
    149         addDynamic(offsetMenuItem);
     166        addDynamic(offsetMenuItem, null);
    150167        addDynamicSeparator();
    151168
     
    154171        savedLayers.sort(alphabeticImageryComparator);
    155172        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
    161177        if (MainApplication.isDisplayingMapView()) {
    162178            MapView mv = MainApplication.getMap().mapView;
    163179            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());
    187186            if (!inViewLayers.isEmpty()) {
    188                 inViewLayers.sort(alphabeticImageryComparator);
    189187                addDynamicSeparator();
    190188                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));
    192202                }
    193203            }
     
    201211            int n = subMenu.getItemCount();
    202212            for (int i = 0; i < n; i++) {
    203                 addDynamic(subMenu.getItem(i).getAction());
     213                addDynamic(subMenu.getItem(i).getAction(), null);
    204214            }
    205215        } else {
    206216            // or add the submenu itself
    207             addDynamic(subMenu);
     217            addDynamic(subMenu, null);
    208218        }
    209219    }
     
    257267
    258268    /**
    259      * Collection to store temporary menu items. They will be deleted
     269     * List to store temporary "photo" menu items. They will be deleted
    260270     * (and possibly recreated) when refreshImageryMenu() is called.
    261      * @since 5803
    262271     */
    263272    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);
    264283    private final List<JosmAction> dynJosmActions = new ArrayList<>(20);
    265284
     
    271290        dynJosmActions.forEach(JosmAction::destroy);
    272291        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);
    283293        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        }
    284310    }
    285311
     
    290316    }
    291317
    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        }
    298334    }
    299335
  • trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java

    r14695 r15054  
    190190    /**
    191191     * 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.
    193194     * @param task The runnable to execute
    194195     * @see SwingUtilities#invokeLater
Note: See TracChangeset for help on using the changeset viewer.