Skip to content

Commit

Permalink
Break out map controls
Browse files Browse the repository at this point in the history
  • Loading branch information
ianthetechie committed Mar 17, 2024
1 parent 3c084b3 commit 05c7af3
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 29 deletions.
137 changes: 137 additions & 0 deletions Sources/MapLibreSwiftDSL/MapControls.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import Foundation
import MapLibre

public protocol MapControl {
/// Overrides the position of the control. Default values are control-specfiic.
var position: MLNOrnamentPosition? { get set }
/// Overrides the offset of the control.
var margins: CGPoint? { get set }
/// Overrides whether the control is hidden.
var isHidden: Bool { get set }

@MainActor func configureMapView(_ mapView: MLNMapView)
}

public extension MapControl {
/// Sets position of the control.
func position(_ position: MLNOrnamentPosition) -> Self {
var result = self

result.position = position

return result
}

/// Sets the position offset of the control.
func margins(_ margins: CGPoint) -> Self {
var result = self

result.margins = margins

return result
}

/// Hides the control.
func hidden(_: Bool) -> Self {
var result = self

result.isHidden = true

return result
}
}

public struct CompassView: MapControl {
public var position: MLNOrnamentPosition?
public var margins: CGPoint?
public var isHidden: Bool = false

public func configureMapView(_ mapView: MLNMapView) {
if let position {
mapView.compassViewPosition = position
}

if let margins {
mapView.compassViewMargins = margins
}

mapView.compassView.isHidden = isHidden
}

public init() {}
}

public struct LogoView: MapControl {
public var position: MLNOrnamentPosition?
public var margins: CGPoint?
public var isHidden: Bool = false
public var image: UIImage?

public init() {}

public func configureMapView(_ mapView: MLNMapView) {
if let position {
mapView.logoViewPosition = position
}

if let margins {
mapView.logoViewMargins = margins
}

mapView.logoView.isHidden = isHidden

if let image {
mapView.logoView.image = image
}
}
}

public extension LogoView {
/// Sets the logo image (defaults to the MapLibre logo).
func image(_ image: UIImage?) -> Self {
var result = self

result.image = image

return result
}
}

@resultBuilder
public enum MapControlsBuilder: DefaultResultBuilder {
public static func buildExpression(_ expression: MapControl) -> [MapControl] {
[expression]
}

public static func buildExpression(_ expression: [MapControl]) -> [MapControl] {
expression
}

public static func buildExpression(_: Void) -> [MapControl] {
[]
}

public static func buildBlock(_ components: [MapControl]...) -> [MapControl] {
components.flatMap { $0 }
}

public static func buildArray(_ components: [MapControl]) -> [MapControl] {
components
}

public static func buildArray(_ components: [[MapControl]]) -> [MapControl] {
components.flatMap { $0 }
}

public static func buildEither(first components: [MapControl]) -> [MapControl] {
components
}

public static func buildEither(second components: [MapControl]) -> [MapControl] {
components
}

public static func buildOptional(_ components: [MapControl]?) -> [MapControl] {
components ?? []
}
}
5 changes: 4 additions & 1 deletion Sources/MapLibreSwiftUI/Examples/User Location.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import CoreLocation
import MapLibreSwiftDSL
import SwiftUI

@MainActor
Expand Down Expand Up @@ -29,6 +30,8 @@ private let locationManager = StaticLocationManager(initialLocation: CLLocation(
locationManager: locationManager
)
.mapViewContentInset(.init(top: 450, left: 0, bottom: 0, right: 0))
.hideCompassView()
.mapControls {
LogoView()
}
.ignoresSafeArea(.all)
}
41 changes: 13 additions & 28 deletions Sources/MapLibreSwiftUI/MapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ public struct MapView: UIViewRepresentable {
/// See ``unsafeMapViewModifier(_:)``
var unsafeMapViewModifier: ((MLNMapView) -> Void)?

var controls: [MapControl] = [
CompassView(),
LogoView(),
]

private var locationManager: MLNLocationManager?

public init(
Expand Down Expand Up @@ -92,41 +97,21 @@ public struct MapView: UIViewRepresentable {
@MainActor private func applyModifiers(_ mapView: MLNMapView, runUnsafe: Bool) {
mapView.contentInset = mapViewContentInset

mapView.logoView.isHidden = isLogoViewHidden
mapView.compassView.isHidden = isCompassViewHidden
// Assume all controls are hidden by default (so that an empty list returns a map with no controls)
mapView.logoView.isHidden = true
mapView.compassView.isHidden = true

// Apply each control configuration
for control in controls {
control.configureMapView(mapView)
}

if runUnsafe {
unsafeMapViewModifier?(mapView)
}
}
}

public extension MapView {
func mapViewContentInset(_ inset: UIEdgeInsets) -> Self {
var result = self

result.mapViewContentInset = inset

return result
}

func hideLogoView() -> Self {
var result = self

result.isLogoViewHidden = true

return result
}

func hideCompassView() -> Self {
var result = self

result.isCompassViewHidden = true

return result
}
}

#Preview {
MapView(styleURL: demoTilesURL)
.ignoresSafeArea(.all)
Expand Down
17 changes: 17 additions & 0 deletions Sources/MapLibreSwiftUI/MapViewModifiers.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation
import MapLibre
import MapLibreSwiftDSL
import SwiftUI

public extension MapView {
Expand Down Expand Up @@ -82,4 +83,20 @@ public extension MapView {

return newMapView
}

func mapViewContentInset(_ inset: UIEdgeInsets) -> Self {
var result = self

result.mapViewContentInset = inset

return result
}

func mapControls(@MapControlsBuilder _ buildControls: () -> [MapControl]) -> Self {
var result = self

result.controls = buildControls()

return result
}
}
8 changes: 8 additions & 0 deletions Tests/MapLibreSwiftUITests/Examples/MapControlsTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//
// File.swift
//
//
// Created by Ian Wagner on 2024-03-18.
//

import Foundation

0 comments on commit 05c7af3

Please sign in to comment.