001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.layer; 003 004import java.util.List; 005import java.util.Objects; 006import java.util.function.Predicate; 007 008/** 009 * This class defines a position to insert a given layer in the list of layers. 010 * @author Michael Zangl 011 * @since 10008 012 * @since 10592 functional interface 013 */ 014@FunctionalInterface 015public interface LayerPositionStrategy { 016 017 /** 018 * always inserts at the front of the stack. 019 */ 020 LayerPositionStrategy IN_FRONT = manager -> 0; 021 022 /** 023 * A GPX layer is added below the lowest data layer. 024 */ 025 LayerPositionStrategy AFTER_LAST_DATA_LAYER = afterLast( 026 layer -> layer instanceof OsmDataLayer || layer instanceof ValidatorLayer); 027 028 /** 029 * A normal layer is added after all validation layers. 030 */ 031 LayerPositionStrategy AFTER_LAST_VALIDATION_LAYER = afterLast( 032 layer -> layer instanceof ValidatorLayer); 033 034 /** 035 * The default for background layers: They are added before the first background layer in the list. 036 * If there is none, they are added at the end of the list. 037 */ 038 LayerPositionStrategy BEFORE_FIRST_BACKGROUND_LAYER = inFrontOfFirst( 039 Layer::isBackgroundLayer); 040 041 /** 042 * Gets a {@link LayerPositionStrategy} that inserts this layer in front of a given layer 043 * @param other The layer before which to insert this layer 044 * @return The strategy 045 */ 046 static LayerPositionStrategy inFrontOf(Layer other) { 047 return inFrontOfFirst(obj -> Objects.equals(obj, other)); 048 } 049 050 /** 051 * Gets a {@link LayerPositionStrategy} that inserts the layer in front of the first layer that matches a condition. 052 * @param what The condition to match. 053 * @return The strategy. 054 */ 055 static LayerPositionStrategy inFrontOfFirst(final Predicate<Layer> what) { 056 return manager -> { 057 if (manager != null) { 058 List<Layer> layers = manager.getLayers(); 059 for (int i = 0; i < layers.size(); i++) { 060 if (what.test(layers.get(i))) { 061 return i; 062 } 063 } 064 return layers.size(); 065 } 066 return 0; 067 }; 068 } 069 070 /** 071 * Creates a strategy that places the layer after the last layer of a given kind or at the beginning of the list if no such layer exists. 072 * @param what what to search for 073 * @return The strategy. 074 */ 075 static LayerPositionStrategy afterLast(final Predicate<Layer> what) { 076 return manager -> { 077 if (manager != null) { 078 List<Layer> layers = manager.getLayers(); 079 for (int i = layers.size() - 1; i >= 0; i--) { 080 if (what.test(layers.get(i))) { 081 return i + 1; 082 } 083 } 084 } 085 return 0; 086 }; 087 } 088 089 /** 090 * Gets the position where the layer should be inserted 091 * @param manager The layer manager to insert the layer in. 092 * @return The position in the range 0...layers.size 093 */ 094 int getPosition(LayerManager manager); 095}