diff --git a/CHANGELOG.md b/CHANGELOG.md index b27b024..dac2a56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### Added + +- Added FillStyleLayer and example. + ## Version 0.4.2 - 2024-12-03 ### Fixed diff --git a/Sources/MapLibreSwiftDSL/Style Layers/FillStyleLayer.swift b/Sources/MapLibreSwiftDSL/Style Layers/FillStyleLayer.swift new file mode 100644 index 0000000..018723f --- /dev/null +++ b/Sources/MapLibreSwiftDSL/Style Layers/FillStyleLayer.swift @@ -0,0 +1,81 @@ +import Foundation +import InternalUtils +import MapLibre +import MapLibreSwiftMacros + +// TODO: Other properties and their modifiers +@MLNStyleProperty("fillColor", supportsInterpolation: true) +@MLNStyleProperty("fillOutlineColor", supportsInterpolation: true) +@MLNStyleProperty("fillOpacity", supportsInterpolation: true) +public struct FillStyleLayer: SourceBoundVectorStyleLayerDefinition { + public let identifier: String + public let sourceLayerIdentifier: String? + public var insertionPosition: LayerInsertionPosition = .aboveOthers + public var isVisible: Bool = true + public var maximumZoomLevel: Float? = nil + public var minimumZoomLevel: Float? = nil + + public var source: StyleLayerSource + public var predicate: NSPredicate? + + public init(identifier: String, source: Source) { + self.identifier = identifier + self.source = .source(source) + sourceLayerIdentifier = nil + } + + public init(identifier: String, source: MLNSource, sourceLayerIdentifier: String? = nil) { + self.identifier = identifier + self.source = .mglSource(source) + self.sourceLayerIdentifier = sourceLayerIdentifier + } + + public func makeStyleLayer(style: MLNStyle) -> StyleLayer { + let styleSource = addSource(to: style) + + return FillStyleLayerInternal(definition: self, mglSource: styleSource) + } +} + +private struct FillStyleLayerInternal: StyleLayer { + private var definition: FillStyleLayer + private let mglSource: MLNSource + + public var identifier: String { definition.identifier } + public var insertionPosition: LayerInsertionPosition { + get { definition.insertionPosition } + set { definition.insertionPosition = newValue } + } + + public var isVisible: Bool { + get { definition.isVisible } + set { definition.isVisible = newValue } + } + + public var maximumZoomLevel: Float? { + get { definition.maximumZoomLevel } + set { definition.maximumZoomLevel = newValue } + } + + public var minimumZoomLevel: Float? { + get { definition.minimumZoomLevel } + set { definition.minimumZoomLevel = newValue } + } + + init(definition: FillStyleLayer, mglSource: MLNSource) { + self.definition = definition + self.mglSource = mglSource + } + + public func makeMLNStyleLayer() -> MLNStyleLayer { + let result = MLNFillStyleLayer(identifier: identifier, source: mglSource) + + result.fillColor = definition.fillColor + result.fillOutlineColor = definition.fillOutlineColor + result.fillOpacity = definition.fillOpacity + + result.predicate = definition.predicate + + return result + } +} diff --git a/Sources/MapLibreSwiftUI/Examples/FillStyleLayerPreviews.swift b/Sources/MapLibreSwiftUI/Examples/FillStyleLayerPreviews.swift new file mode 100644 index 0000000..369c8d3 --- /dev/null +++ b/Sources/MapLibreSwiftUI/Examples/FillStyleLayerPreviews.swift @@ -0,0 +1,18 @@ +import MapLibre +import MapLibreSwiftDSL +import SwiftUI + +@available(iOS 17.0, *) +#Preview { + @Previewable let source = ShapeSource(identifier: "fillSource") { + MLNPolygonFeature(coordinates: austriaPolygon, count: UInt(austriaPolygon.count)) + } + MapView(styleURL: demoTilesURL, camera: .constant(.center(austriaPolygon.first!, zoom: 4))) { + FillStyleLayer(identifier: "fillLayer", source: source) + .fillColor(.red) + .fillOpacity(0.5) + .fillOutlineColor(.blue) + } + + .ignoresSafeArea(.all) +} diff --git a/Sources/MapLibreSwiftUI/Examples/Preview Helpers.swift b/Sources/MapLibreSwiftUI/Examples/Preview Helpers.swift index 918fb47..718a91d 100644 --- a/Sources/MapLibreSwiftUI/Examples/Preview Helpers.swift +++ b/Sources/MapLibreSwiftUI/Examples/Preview Helpers.swift @@ -3,3 +3,14 @@ import CoreLocation let switzerland = CLLocationCoordinate2D(latitude: 47.03041, longitude: 8.29470) public let demoTilesURL = URL(string: "https://demotiles.maplibre.org/style.json")! + +let austriaPolygon: [CLLocationCoordinate2D] = [ + CLLocationCoordinate2D(latitude: 49.0200, longitude: 16.9600), + CLLocationCoordinate2D(latitude: 48.9000, longitude: 15.0160), + CLLocationCoordinate2D(latitude: 48.2890, longitude: 13.0310), + CLLocationCoordinate2D(latitude: 47.5237, longitude: 10.4350), + CLLocationCoordinate2D(latitude: 46.4000, longitude: 12.1500), + CLLocationCoordinate2D(latitude: 46.8700, longitude: 16.5900), + CLLocationCoordinate2D(latitude: 48.1234, longitude: 16.9600), + CLLocationCoordinate2D(latitude: 49.0200, longitude: 16.9600), // Closing point (same as start) +]