@@ -2,6 +2,7 @@ package com.mapbox.maps.extension.compose.internal
22
33import com.mapbox.maps.LayerPosition
44import com.mapbox.maps.MapboxStyleManager
5+ import com.mapbox.maps.extension.compose.style.LayerPositionedContent
56import com.mapbox.maps.extension.compose.style.internal.StyleLayerPositionNode
67import com.mapbox.maps.logW
78
@@ -18,7 +19,8 @@ internal interface LayerPositionAwareNode {
1819 * Reposition all the layers within the current node according to [getRelativePositionInfo].
1920 */
2021 fun MapboxStyleManager.repositionCurrentNode (parent : MapNode ) {
21- repositionLayersForCurrentNode(getRelativePositionInfo(parent))
22+ val layerPosition = (parent as ? StyleLayerPositionNode )?.layerPosition
23+ repositionLayersForCurrentNode(getRelativePositionInfo(parent, layerPosition))
2224 }
2325
2426 /* *
@@ -52,27 +54,61 @@ internal interface LayerPositionAwareNode {
5254
5355 /* *
5456 * Search the children of the parent node, and see if there's any other [LayerPositionAwareNode]
55- * which is on top of the current node, construct the [LayerPosition] with below layer id, so the
57+ * which is rendered on top of this one (for [LayerPositionedContent.belowLayer]) or below (for [LayerPositionedContent.aboveLayer])
58+ * of the current node, construct the [LayerPosition] with the found layer id, so the
5659 * current layer is inserted at the correct position and consistent with the node tree.
5760 *
58- * If there's nothing above current node, take the [targetLayerPosition] as it's position.
61+ * If there's nothing above/below current node, take the [targetLayerPosition] as its insertion position.
62+ *
63+ * For example, the following compose block:
64+ * ```
65+ * aboveLayer("buildings") {
66+ * layerPositionAwareNode_1
67+ * layerPositionAwareNode_2
68+ * layerPositionAwareNode_3
69+ * }
70+ * ```
71+ * Should be rendered in the map in the following order (top visible layer to bottom layer):
72+ * ```
73+ * layerPositionAwareNode_3
74+ * layerPositionAwareNode_2
75+ * layerPositionAwareNode_1
76+ * "buildings"
77+ * ```
78+ *
79+ * Meaning that the relative position of the layers should be:
80+ * ```
81+ * layerPositionAwareNode_3 above layerPositionAwareNode_2
82+ * layerPositionAwareNode_2 above layerPositionAwareNode_1
83+ * layerPositionAwareNode_1 above "buildings"
84+ * ```
85+ *
5986 *
6087 * @param parent the parent node of the node to be positioned.
6188 * @param targetLayerPosition the optional target layer position, useful in case of [StyleLayerPositionNode].
6289 */
6390 fun getRelativePositionInfo (
6491 parent : MapNode ,
6592 targetLayerPosition : LayerPosition ? = null
66- ): LayerPosition ? {
67- return with (parent.children.filterIsInstance<LayerPositionAwareNode >()) {
68- elementAtOrNull(indexOf(this @LayerPositionAwareNode) + 1 )?.getLayerIds()?.firstOrNull()
69- ?.let { belowLayerId ->
70- LayerPosition (
71- /* above = */ null ,
72- /* below = */ belowLayerId,
73- /* at = */ null
74- )
75- } ? : targetLayerPosition
93+ ): LayerPosition ? =
94+ parent.children.filterIsInstance<LayerPositionAwareNode >().let { children ->
95+ val me = this @LayerPositionAwareNode
96+ val isAbove = targetLayerPosition?.above != null
97+ val anchorLayerIdx = children.indexOf(me) + if (isAbove) {
98+ - 1
99+ } else {
100+ 1
101+ }
102+ val anchorLayerNode = children.elementAtOrNull(anchorLayerIdx)
103+ return if (anchorLayerNode == null ) {
104+ targetLayerPosition
105+ } else {
106+ val anchorLayerId = anchorLayerNode.getLayerIds().first()
107+ LayerPosition (
108+ /* above = */ if (isAbove) anchorLayerId else null ,
109+ /* below = */ if (isAbove) null else anchorLayerId,
110+ /* at = */ null
111+ )
112+ }
76113 }
77- }
78114}
0 commit comments