diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift b/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift index 1094953..040065e 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Circle.swift @@ -21,7 +21,7 @@ public struct CircleStyleLayer: SourceBoundVectorStyleLayerDefinition { public init(identifier: String, source: Source) { self.identifier = identifier self.source = .source(source) - self.sourceLayerIdentifier = nil + sourceLayerIdentifier = nil } public init(identifier: String, source: MLNSource, sourceLayerIdentifier: String? = nil) { diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Line.swift b/Sources/MapLibreSwiftDSL/Style Layers/Line.swift index 68e362d..1c10508 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Line.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Line.swift @@ -9,7 +9,6 @@ import MapLibreSwiftMacros @MLNRawRepresentableStyleProperty("lineJoin") @MLNStyleProperty("lineWidth", supportsInterpolation: true) public struct LineStyleLayer: SourceBoundVectorStyleLayerDefinition { - public let identifier: String public let sourceLayerIdentifier: String? public var insertionPosition: LayerInsertionPosition = .aboveOthers @@ -23,7 +22,7 @@ public struct LineStyleLayer: SourceBoundVectorStyleLayerDefinition { public init(identifier: String, source: Source) { self.identifier = identifier self.source = .source(source) - self.sourceLayerIdentifier = nil + sourceLayerIdentifier = nil } public init(identifier: String, source: MLNSource, sourceLayerIdentifier: String? = nil) { diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift b/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift index 3bb30f4..435d562 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Style Layer.swift @@ -75,7 +75,7 @@ public protocol StyleLayerDefinition { public protocol SourceBoundStyleLayerDefinition: StyleLayerDefinition { var source: StyleLayerSource { get set } - + var sourceLayerIdentifier: String? { get } } @@ -168,7 +168,7 @@ public extension StyleLayerDefinition { func minimumZoomLevel(_ value: Float) -> Self { modified(self) { $0.minimumZoomLevel = value } } - + func maximumZoomLevel(_ value: Float) -> Self { modified(self) { $0.maximumZoomLevel = value } } diff --git a/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift b/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift index 5d6c3b6..3f7ce1d 100644 --- a/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift +++ b/Sources/MapLibreSwiftDSL/Style Layers/Symbol.swift @@ -32,7 +32,7 @@ public struct SymbolStyleLayer: SourceBoundVectorStyleLayerDefinition { public init(identifier: String, source: Source) { self.identifier = identifier - self.sourceLayerIdentifier = nil + sourceLayerIdentifier = nil self.source = .source(source) } @@ -40,7 +40,6 @@ public struct SymbolStyleLayer: SourceBoundVectorStyleLayerDefinition { self.identifier = identifier self.sourceLayerIdentifier = sourceLayerIdentifier self.source = .mglSource(source) - } public func makeStyleLayer(style: MLNStyle) -> StyleLayer { @@ -65,7 +64,7 @@ public struct SymbolStyleLayer: SourceBoundVectorStyleLayerDefinition { it.iconImages = [image] } } - + public func iconImage(featurePropertyNamed keyPath: String) -> Self { var copy = self copy.iconImageName = NSExpression(forKeyPath: keyPath) @@ -84,21 +83,29 @@ public struct SymbolStyleLayer: SourceBoundVectorStyleLayerDefinition { // it.iconImages = mappings.values + [defaultImage] // } // } - - /// Add an icon image that can be dynamic and use UIImages in your app, based on a feature property of the source. For example, your feature could have a property called "icon-name". This name is then resolved against the key in the mappings dictionary and used to find a UIImage to display on the map for that feature. + + /// Add an icon image that can be dynamic and use UIImages in your app, based on a feature property of the source. + /// For example, your feature could have a property called "icon-name". This name is then resolved against the key + /// in the mappings dictionary and used to find a UIImage to display on the map for that feature. /// - Parameters: /// - keyPath: The keypath to the feature property containing the icon to use, for example "icon-name". - /// - mappings: A lookup dictionary containing the keys found in "keyPath" and a UIImage for each keyPath. The key of the mappings dictionary needs to match the value type stored at keyPath, for example `String`. - /// - defaultImage: A UIImage that MapLibre should fall back to if the key in your feature is not found in the mappings table - public func iconImage(featurePropertyNamed keyPath: String, mappings: [AnyHashable: UIImage], default defaultImage: UIImage) -> Self { - return modified(self) { it in + /// - mappings: A lookup dictionary containing the keys found in "keyPath" and a UIImage for each keyPath. The key + /// of the mappings dictionary needs to match the value type stored at keyPath, for example `String`. + /// - defaultImage: A UIImage that MapLibre should fall back to if the key in your feature is not found in the + /// mappings table + public func iconImage( + featurePropertyNamed keyPath: String, + mappings: [AnyHashable: UIImage], + default defaultImage: UIImage + ) -> Self { + modified(self) { it in let attributeExpression = NSExpression(forKeyPath: keyPath) let mappingExpressions = mappings.mapValues { image in NSExpression(forConstantValue: image.sha256()) } let mappingDictionary = NSDictionary(dictionary: mappingExpressions) let defaultExpression = NSExpression(forConstantValue: defaultImage.sha256()) - + it.iconImageName = NSExpression( forMLNMatchingKey: attributeExpression, in: mappingDictionary as! [NSExpression: NSExpression], @@ -142,29 +149,29 @@ private struct SymbolStyleLayerInternal: StyleLayer { public func makeMLNStyleLayer() -> MLNStyleLayer { let result = MLNSymbolStyleLayer(identifier: identifier, source: mglSource) result.sourceLayerIdentifier = definition.sourceLayerIdentifier - + result.iconImageName = definition.iconImageName result.iconRotation = definition.iconRotation result.iconAllowsOverlap = definition.iconAllowsOverlap result.iconColor = definition.iconColor - + result.text = definition.text result.textColor = definition.textColor result.textFontSize = definition.textFontSize result.maximumTextWidth = definition.maximumTextWidth result.textAnchor = definition.textAnchor result.textOffset = definition.textOffset - + result.textHaloColor = definition.textHaloColor result.textHaloWidth = definition.textHaloWidth result.textHaloBlur = definition.textHaloBlur - + result.predicate = definition.predicate - + if let minimumZoomLevel = definition.minimumZoomLevel { result.minimumZoomLevel = minimumZoomLevel } - + if let maximumZoomLevel = definition.maximumZoomLevel { result.maximumZoomLevel = maximumZoomLevel } diff --git a/Sources/MapLibreSwiftUI/Examples/Layers.swift b/Sources/MapLibreSwiftUI/Examples/Layers.swift index bbd40fd..dac3096 100644 --- a/Sources/MapLibreSwiftUI/Examples/Layers.swift +++ b/Sources/MapLibreSwiftUI/Examples/Layers.swift @@ -133,17 +133,18 @@ let clustered = ShapeSource(identifier: "points", options: [.clustered: true, .c .ignoresSafeArea(.all) } -// TODO: Fixme +// This example does not work within a package? But it does work when in a real app // #Preview("Multiple Symbol Icons") { // MapView(styleURL: demoTilesURL) { // // Simple symbol layer demonstration with an icon // SymbolStyleLayer(identifier: "simple-symbols", source: pointSource) -// .iconImage(attribute: "icon", +// .iconImage(featurePropertyNamed: "icon", // mappings: [ -// "missing": UIImage(systemName: "mappin.slash")!, -// "club": UIImage(systemName: "figure.dance")! +// "missing": UIImage(systemName: "mappin.slash")!, +// "club": UIImage(systemName: "figure.dance")!, // ], // default: UIImage(systemName: "mappin")!) +// .iconColor(.red) // } -// .edgesIgnoringSafeArea(.all) +// .ignoresSafeArea(.all) // }