Skip to content

Commit ac5f240

Browse files
authored
Enable layer insertion below symbols (#70)
1 parent 61cffb6 commit ac5f240

File tree

11 files changed

+60
-41
lines changed

11 files changed

+60
-41
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## Version 0.7.0 - 2025-02-02
9+
10+
### Added
11+
12+
- Adds support for a `belowSymbols` layer order. The `renderBelowSymbols` modifier on layers will insert the new layer below the first symbol layer in the style. This allows for rendering below labels and icons.
13+
- BREAKING: Refactored the layer position modifiers to accept enum variants to enable better extensibility.
14+
15+
### Fixed
16+
17+
- Moved modifiers on `StyleLayer` to `StyleLayerDefinition`. The previous extension of `StyleLayer` was a mistake, since `StyleLayerDefinition` is the supertype, and none of the behavior was specific to `StyleLayer`.
18+
819
## Version 0.6.0 - 2025-01-14
920

1021
- Potentially BREAKING: Upgrades Mockable to 0.2.0. If you're using mockable in your project, this may require you to upgrade there as well.

Sources/MapLibreSwiftDSL/Style Layers/Background.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import MapLibreSwiftMacros
77
@MLNStyleProperty<Float>("backgroundOpacity", supportsInterpolation: true)
88
public struct BackgroundLayer: StyleLayer {
99
public let identifier: String
10-
public var insertionPosition: LayerInsertionPosition = .belowOthers
10+
public var insertionPosition: LayerInsertionPosition = .below(.all)
1111
public var isVisible: Bool = true
1212
public var maximumZoomLevel: Float? = nil
1313
public var minimumZoomLevel: Float? = nil

Sources/MapLibreSwiftDSL/Style Layers/Circle.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import MapLibreSwiftMacros
1010
public struct CircleStyleLayer: SourceBoundVectorStyleLayerDefinition {
1111
public let identifier: String
1212
public let sourceLayerIdentifier: String?
13-
public var insertionPosition: LayerInsertionPosition = .aboveOthers
13+
public var insertionPosition: LayerInsertionPosition = .above(.all)
1414
public var isVisible: Bool = true
1515
public var maximumZoomLevel: Float? = nil
1616
public var minimumZoomLevel: Float? = nil

Sources/MapLibreSwiftDSL/Style Layers/FillStyleLayer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import MapLibreSwiftMacros
1010
public struct FillStyleLayer: SourceBoundVectorStyleLayerDefinition {
1111
public let identifier: String
1212
public let sourceLayerIdentifier: String?
13-
public var insertionPosition: LayerInsertionPosition = .aboveOthers
13+
public var insertionPosition: LayerInsertionPosition = .above(.all)
1414
public var isVisible: Bool = true
1515
public var maximumZoomLevel: Float? = nil
1616
public var minimumZoomLevel: Float? = nil

Sources/MapLibreSwiftDSL/Style Layers/Line.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import MapLibreSwiftMacros
1111
public struct LineStyleLayer: SourceBoundVectorStyleLayerDefinition {
1212
public let identifier: String
1313
public let sourceLayerIdentifier: String?
14-
public var insertionPosition: LayerInsertionPosition = .aboveOthers
14+
public var insertionPosition: LayerInsertionPosition = .above(.all)
1515
public var isVisible: Bool = true
1616
public var maximumZoomLevel: Float? = nil
1717
public var minimumZoomLevel: Float? = nil

Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,34 @@
11
import InternalUtils
22
import MapLibre
33

4+
/// A layer reference specifying which layer we should insert a new layer above.
5+
public enum LayerReferenceAbove: Equatable {
6+
/// A specific layer, referenced by ID.
7+
case layer(layerId: String)
8+
/// The group of all layers currently in the style.
9+
case all
10+
}
11+
12+
/// A layer reference specifying which layer we should insert a new layer below.
13+
public enum LayerReferenceBelow: Equatable {
14+
/// A specific layer, referenced by ID.
15+
case layer(layerId: String)
16+
/// The group of all layers currently in the style.
17+
case all
18+
/// The group of symbol layers currently in the style.
19+
case symbols
20+
}
21+
422
/// Specifies a preference for where the layer should be inserted in the hierarchy.
523
public enum LayerInsertionPosition: Equatable {
624
/// The layer should be inserted above the layer with ID ``layerID``.
725
///
826
/// If no such layer exists, the layer will be added above others and an error will be logged.
9-
case above(layerID: String)
27+
case above(LayerReferenceAbove)
1028
/// The layer should be inserted below the layer with ID ``layerID``.
1129
///
1230
/// If no such layer exists, the layer will be added above others and an error will be logged.
13-
case below(layerID: String)
14-
/// The layer should be inserted above other existing layers.
15-
case aboveOthers
16-
/// The layer should be inserted below other existing layers.
17-
case belowOthers
31+
case below(LayerReferenceBelow)
1832
}
1933

2034
/// Internal style enum that wraps a source reference.
@@ -132,7 +146,7 @@ public extension StyleLayer {
132146
}
133147
}
134148

135-
public extension StyleLayer {
149+
public extension StyleLayerDefinition {
136150
// MARK: - Common modifiers
137151

138152
func visible(_ value: Bool) -> Self {
@@ -147,29 +161,11 @@ public extension StyleLayer {
147161
modified(self) { $0.maximumZoomLevel = value }
148162
}
149163

150-
func renderAbove(_ layerID: String) -> Self {
151-
modified(self) { $0.insertionPosition = .above(layerID: layerID) }
152-
}
153-
154-
func renderBelow(_ layerID: String) -> Self {
155-
modified(self) { $0.insertionPosition = .below(layerID: layerID) }
156-
}
157-
158-
func renderAboveOthers() -> Self {
159-
modified(self) { $0.insertionPosition = .aboveOthers }
164+
func renderAbove(_ layerReference: LayerReferenceAbove) -> Self {
165+
modified(self) { $0.insertionPosition = .above(layerReference) }
160166
}
161167

162-
func renderBelowOthers() -> Self {
163-
modified(self) { $0.insertionPosition = .belowOthers }
164-
}
165-
}
166-
167-
public extension StyleLayerDefinition {
168-
func minimumZoomLevel(_ value: Float) -> Self {
169-
modified(self) { $0.minimumZoomLevel = value }
170-
}
171-
172-
func maximumZoomLevel(_ value: Float) -> Self {
173-
modified(self) { $0.maximumZoomLevel = value }
168+
func renderBelow(_ layerReference: LayerReferenceBelow) -> Self {
169+
modified(self) { $0.insertionPosition = .below(layerReference) }
174170
}
175171
}

Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import MapLibreSwiftMacros
2323
public struct SymbolStyleLayer: SourceBoundVectorStyleLayerDefinition {
2424
public let identifier: String
2525
public let sourceLayerIdentifier: String?
26-
public var insertionPosition: LayerInsertionPosition = .aboveOthers
26+
public var insertionPosition: LayerInsertionPosition = .above(.all)
2727
public var isVisible: Bool = true
2828
public var maximumZoomLevel: Float? = nil
2929
public var minimumZoomLevel: Float? = nil

Sources/MapLibreSwiftUI/Examples/Layers.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ let clustered = ShapeSource(identifier: "points", options: [.clustered: true, .c
3838
// Silly example: a background layer on top of everything to create a tint effect
3939
BackgroundLayer(identifier: "rose-colored-glasses")
4040
.backgroundColor(.systemPink.withAlphaComponent(0.3))
41-
.renderAboveOthers()
41+
.renderAbove(.all)
4242
}
4343
.ignoresSafeArea(.all)
4444
}

Sources/MapLibreSwiftUI/Examples/Polyline.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct PolylineMapView: View {
2626
curveType: .exponential,
2727
parameters: NSExpression(forConstantValue: 1.5),
2828
stops: NSExpression(forConstantValue: [14: 6, 18: 24]))
29+
.renderBelow(.symbols)
2930

3031
// Add an inner (blue) polyline
3132
LineStyleLayer(identifier: "polyline-inner", source: polylineSource)
@@ -36,6 +37,7 @@ struct PolylineMapView: View {
3637
curveType: .exponential,
3738
parameters: NSExpression(forConstantValue: 1.5),
3839
stops: NSExpression(forConstantValue: [14: 3, 18: 16]))
40+
.renderBelow(.symbols)
3941
}
4042
}
4143
}

Sources/MapLibreSwiftUI/MapViewCoordinator.swift

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,10 @@ public class MapViewCoordinator<T: MapViewHostViewController>: NSObject, MLNMapV
268268
}
269269

270270
func addLayers(to mglStyle: MLNStyle) {
271+
let firstSymbolLayer = mglStyle.layers.first { layer in
272+
layer is MLNSymbolStyleLayer
273+
}
274+
271275
for layerSpec in parent.userLayers {
272276
// DISCUSS: What preventions should we try to put in place against the user accidentally adding the same layer twice?
273277
let newLayer = layerSpec.makeStyleLayer(style: mglStyle).makeMLNStyleLayer()
@@ -284,24 +288,30 @@ public class MapViewCoordinator<T: MapViewHostViewController>: NSObject, MLNMapV
284288
}
285289

286290
switch layerSpec.insertionPosition {
287-
case let .above(layerID: id):
291+
case let .above(.layer(layerId: id)):
288292
if let layer = mglStyle.layer(withIdentifier: id) {
289293
mglStyle.insertLayer(newLayer, above: layer)
290294
} else {
291295
NSLog("Failed to find layer with ID \(id). Adding layer on top.")
292296
mglStyle.addLayer(newLayer)
293297
}
294-
case let .below(layerID: id):
298+
case .above(.all):
299+
mglStyle.addLayer(newLayer)
300+
case let .below(.layer(layerId: id)):
295301
if let layer = mglStyle.layer(withIdentifier: id) {
296302
mglStyle.insertLayer(newLayer, below: layer)
297303
} else {
298304
NSLog("Failed to find layer with ID \(id). Adding layer on top.")
299305
mglStyle.addLayer(newLayer)
300306
}
301-
case .aboveOthers:
302-
mglStyle.addLayer(newLayer)
303-
case .belowOthers:
307+
case .below(.all):
304308
mglStyle.insertLayer(newLayer, at: 0)
309+
case .below(.symbols):
310+
if let firstSymbolLayer {
311+
mglStyle.insertLayer(newLayer, below: firstSymbolLayer)
312+
} else {
313+
mglStyle.addLayer(newLayer)
314+
}
305315
}
306316
}
307317
}

Tests/MapLibreSwiftUITests/Examples/LayerPreviewTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class LayerPreviewTests: XCTestCase {
3030
// Silly example: a background layer on top of everything to create a tint effect
3131
BackgroundLayer(identifier: "rose-colored-glasses")
3232
.backgroundColor(.systemPink.withAlphaComponent(0.3))
33-
.renderAboveOthers()
33+
.renderAbove(.all)
3434
}
3535
}
3636
}

0 commit comments

Comments
 (0)