// // Copyright Amazon.com Inc. or its affiliates. // All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // import Foundation import CoreLocation import Mapbox import SwiftUI public extension AMLMapCompositeView { /// View modifier to enable showing the user's location on the map. /// /// To access the user's locaiton, location access must be enabled in the app, and /// the user must choose to allow access. /// - Parameter showLocation: Enables showing the user's location on the map. /// - Returns: An instance of `AMLMapCompositeView`. func showUserLocation(_ showLocation: Bool) -> AMLMapCompositeView { viewModel.mapSettings.showUserLocation = showLocation return self } /// View modifier to set the map's maximum and minimum zoom levels. /// /// Zoom Level Approximation Reference: /// - 0 -> The Earth /// - 3 -> A continent /// - 4 -> Large islands /// - 6 -> Large rivers /// - 10 -> Large roads /// - 15 -> Buildings /// /// - Parameter zoomLevels: A closed range of `Double` where the lower bound is the min and /// the upper bound the max zoom level. /// - Important: /// The minimum allowable zoom level is 0 and the maximum allowable zoom level is 22. /// Any value set below 0 or above 22 will revert to 0 or 22 accordingly. /// - Returns: An instance of `AMLMapCompositeView`. func allowedZoomLevels(_ zoomLevels: ClosedRange<Double>) -> AMLMapCompositeView { viewModel.mapSettings.minZoomLevel = max(zoomLevels.lowerBound, 0) viewModel.mapSettings.maxZoomLevel = min(zoomLevels.upperBound, 22) return self } /// View modifier to set the map's maximum zoom level. /// /// Zoom Level Approximation Reference: /// - 0 -> The Earth /// - 3 -> A continent /// - 4 -> Large islands /// - 6 -> Large rivers /// - 10 -> Large roads /// - 15 -> Buildings /// /// - Parameter maxZoomLevel: The maximum zoom level allowed by the map. /// - Important: /// The maximum zoom level is 22. Any value set above 22 will revert to 22. /// - Returns: An instance of `AMLMapCompositeView`. func maxZoomLevel(_ maxZoomLevel: Double) -> AMLMapCompositeView { viewModel.mapSettings.maxZoomLevel = min(maxZoomLevel, 22) return self } /// View modifier to set the map's minimum zoom level. /// /// Zoom Level Approximation Reference: /// - 0 -> The Earth /// - 3 -> A continent /// - 4 -> Large islands /// - 6 -> Large rivers /// - 10 -> Large roads /// - 15 -> Buildings /// /// - Parameter minZoomLevel: The minimum zoom level allowed by the map. /// - Important: /// The minimum allowable zoom level is 0. Any value set below 0 revert to 0. /// - Returns: An instance of `AMLMapCompositeView`. func minZoomLevel(_ minZoomLevel: Double) -> AMLMapCompositeView { viewModel.mapSettings.minZoomLevel = max(minZoomLevel, 0) return self } /// Provide an SwiftUI view that represents a point on a map. /// /// - Important: Because the underlying `MGLMapView` consumes `UIImage`s, /// this method turns a `SwiftUI` view into a `UIImage`. /// There may be hidden cost to using this. If you experience performance and / or /// rendering issues, please use the `featureImage(_:)` view modifier instead. /// - Parameter view: The view to be displayed. /// - Returns: An instance of `AMLMapCompositeView`. func featureView<T: View>(_ view: () -> T) -> AMLMapCompositeView { viewModel.mapSettings.featureImage = view().snapshot() return self } /// Provide an UIImage that represents a point on a map. /// - Parameter image: The image to be displayed. /// - Returns: An instance of `AMLMapCompositeView`. func featureImage(_ image: () -> UIImage) -> AMLMapCompositeView { viewModel.mapSettings.featureImage = image() return self } /// Define the behavior when a feature is tapped. /// /// The default implementation pans the feature to the center of the screen and presents an `AMLCalloutView`. /// Defining an implementation here will override this behavior. /// /// - Parameter implementation: Closure provided a `MGLMapView` and `MGLPointFeature`. /// Define your desired behavior on the `mapView` using information from the `pointFeature` as needed. /// - Returns: An instance of `AMLMapCompositeView`. func featureTapped( _ implementation: @escaping ( _ mapView: MGLMapView, _ pointFeature: MGLPointFeature ) -> Void ) -> AMLMapCompositeView { viewModel.mapSettings.proxyDelegate.featureTapped = implementation return self } /// Define the behavior when a feature cluster is tapped. /// /// The default implementation zooms in on the map. /// Defining an implementation here will override this behavior. /// /// - Parameter implementation: Closure provided a `MGLMapView` and `MGLPointFeatureCluster`. /// Define your desired behavior on the `mapView` using information from the `pointFeatureCluster` as needed. /// - Returns: An instance of `AMLMapCompositeView`. func featureClusterTapped( _ implementation: @escaping ( _ mapView: MGLMapView, _ pointFeatureCluster: MGLPointFeatureCluster ) -> Void ) -> AMLMapCompositeView { viewModel.mapSettings.proxyDelegate.clusterTapped = implementation return self } /// Set the position of the compass on the `MGLMapView`. /// - Parameter position: `MGLOrnamentPosition` defining the location. /// - Returns: An instance of `AMLMapCompositeView`. func compassPosition(_ position: MGLOrnamentPosition) -> AMLMapCompositeView { viewModel.mapSettings.compassPosition = position return self } /// Set whether the map features should cluster. /// - Parameter shouldCluster: Features displayed on the map should cluster. /// Corresponds to the `MGLShapeSourceOption` `.clustered`. /// - Returns: An instance of `AMLMapCompositeView`. func shouldCluster(_ shouldCluster: Bool) -> AMLMapCompositeView { viewModel.mapSettings.clusteringBehavior.shouldCluster = shouldCluster return self } /// Specifies the maximum zoom level at which to cluster points if clustering is enabled. /// - Parameter maxZoom: The maximum zoom level of clustering. /// Corresponds to `MGLShapeSourceOption` `.maximumZoomLevelForClustering`. /// - Returns: An instance of `AMLMapCompositeView`. func maximumClusterZoomLevel(_ maxZoom: Int) -> AMLMapCompositeView { viewModel.mapSettings.clusteringBehavior.maximumZoomLevel = maxZoom return self } /// Set the fill color of the circle cluster. /// - Parameter color: The fill color of the circle cluster. /// Sets the `MGLCircleStyleLayer` `circleColor` property. /// - Returns: An instance of `AMLMapCompositeView`. func clusterColor(_ color: UIColor) -> AMLMapCompositeView { viewModel.mapSettings.clusteringBehavior.clusterColor = color return self } /// The text color of the number displayed in the circle cluster. /// - Parameter color: The color of text displaying the number within a cluster. /// Sets the `MGLSymbolStyleLayer` `textColor` property. /// - Returns: An instance of `AMLMapCompositeView`. func clusterNumberColor(_ color: UIColor) -> AMLMapCompositeView { viewModel.mapSettings.clusteringBehavior.clusterNumberColor = color return self } /// Set colors for different cluster steps. /// - Parameter steps: Dictionary representation of cluster color steps where the /// `key` is the number of features in a cluster and the /// `value` is the color for that corresponding number /// - Returns: An instance of `AMLMapCompositeView`. func clusterColorSteps(_ steps: [Int: UIColor]) -> AMLMapCompositeView { viewModel.mapSettings.clusteringBehavior.clusterColorSteps = steps return self } /// Set the radius of each cluster if clustering is enabled. /// - Parameter radius: The cluster radius. /// Corresponds to the `MGLShapeSourceOption` `.clusterRadius`. /// - Returns: An instance of `AMLMapCompositeView`. func clusterRadius(_ radius: Int) -> AMLMapCompositeView { viewModel.mapSettings.clusteringBehavior.clusterRadius = radius return self } }