From daad648c9711397ee84002c4af196e5e86af33ce Mon Sep 17 00:00:00 2001 From: Arnaud Leclerc Date: Mon, 23 Nov 2020 22:11:00 +0100 Subject: [PATCH] Reworking way of setting the options on the map * Adding SetStyleOptionsAsync on map * Adding SetUserInteractionAsync on Map * Adding SetTrafficAsync on Map * Reworking CameraOptions binding on map * Reworking StyleOptions bindings on map * Reworking UserInteractionOptions bindings on map * Reworking ServiceOptions * Updating docs --- docs/layers/README.md | 6 +- docs/layers/bubblelayer/README.md | 2 +- docs/layers/heatmaplayer/README.md | 10 +- docs/layers/imagelayer/README.md | 3 +- docs/layers/linelayer/README.md | 11 +- docs/layers/polygonextrusionlayer/README.md | 6 +- docs/layers/polygonlayer/README.md | 2 +- docs/layers/symbollayer/README.md | 4 +- docs/layers/tilelayer/README.md | 5 +- docs/map/README.md | 48 ++- docs/popups/README.md | 42 ++- docs/sources/datasources/README.md | 12 +- docs/sources/vectortilesources/README.md | 11 +- docs/traffic/README.md | 26 +- .../Pages/BubbleLayerOnReady.razor | 2 +- .../Pages/HeatmapLayerOnReady.razor | 10 +- .../Pages/ImageLayerOnReady.razor | 3 +- .../AzureMapsControl.Sample/Pages/Index.razor | 16 +- .../Pages/LayerRemove.razor | 3 +- .../Pages/LineLayerOnReady.razor | 11 +- .../Pages/PolygonExtrusionLayerOnReady.razor | 6 +- .../Pages/PolygonLayerOnReady.razor | 2 +- .../Pages/PopupOnReady.razor | 7 +- .../Pages/StyleOptionsUpdate.razor | 24 ++ .../Pages/SymbolLayerOnReady.razor | 2 +- .../Pages/TileLayerOnReady.razor | 3 +- .../Pages/Traffic.razor | 4 +- .../Pages/TrafficOptionsUpdate.razor | 23 ++ .../Pages/UserInteractionUpdate.razor | 25 ++ .../Pages/VectorTileSource.razor | 11 +- .../Configuration/AzureMapsConfiguration.cs | 26 ++ .../Constants/Constants.cs | 3 + .../Map/AzureMap.razor | 300 ++---------------- .../Map/Bearing.cs | 47 ++- .../Map/CameraOptions.cs | 60 +++- .../Map/CameraType.cs | 23 ++ src/AzureMapsControl.Components/Map/Map.cs | 73 ++++- .../Map/ServiceOptions.cs | 9 +- .../Map/StyleOptions.cs | 54 +++- .../Map/UserInteractionOptions.cs | 55 +++- .../Traffic/TrafficFlow.cs | 16 + .../Traffic/TrafficJsOptions.cs | 18 -- .../Traffic/TrafficOptions.cs | 34 ++ .../wwwroot/azure-maps-control.js | 40 +-- .../Map/Map.cs | 93 ++++++ 45 files changed, 770 insertions(+), 421 deletions(-) create mode 100644 samples/AzureMapsControl.Sample/Pages/StyleOptionsUpdate.razor create mode 100644 samples/AzureMapsControl.Sample/Pages/TrafficOptionsUpdate.razor create mode 100644 samples/AzureMapsControl.Sample/Pages/UserInteractionUpdate.razor delete mode 100644 src/AzureMapsControl.Components/Traffic/TrafficJsOptions.cs diff --git a/docs/layers/README.md b/docs/layers/README.md index 9af83fd..2453245 100644 --- a/docs/layers/README.md +++ b/docs/layers/README.md @@ -17,8 +17,7 @@ Layers can be added to the map after the `MapReady` event has been triggered by @using AzureMapsControl.Components.Map @code { + + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark" + }; + public async Task OnMapReady(MapEventArgs events) { const string dataSourceId = "heatmapDataSource"; diff --git a/docs/layers/imagelayer/README.md b/docs/layers/imagelayer/README.md index 81ee7a4..2af5765 100644 --- a/docs/layers/imagelayer/README.md +++ b/docs/layers/imagelayer/README.md @@ -14,8 +14,7 @@ The image layer supports the following image formats @using AzureMapsControl.Components.Map @code { + + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark" + }; + public async Task OnMapReady(MapEventArgs events) { const string dataSourceId = "dataSource"; diff --git a/docs/layers/polygonextrusionlayer/README.md b/docs/layers/polygonextrusionlayer/README.md index 35f38dd..1d4c47c 100644 --- a/docs/layers/polygonextrusionlayer/README.md +++ b/docs/layers/polygonextrusionlayer/README.md @@ -9,9 +9,7 @@ The polygon extrusion layer renders areas of `Polygon` and `MultiPolygon` featur @using AzureMapsControl.Components.Map + CameraOptions="new CameraOptions { Center= new AzureMapsControl.Components.Atlas.Position(11.581990, 48.143534), Zoom= 10 }" + StyleOptions="StyleOptions"/> + +@code { + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark", + ShowLogo = false, + ShowFeedbackLink = false + }; +} ``` Different inputs can be specified to customize the map. Please refer to the [Azure Maps Web SDK Documentation](https://docs.microsoft.com/en-us/azure/azure-maps/map-create) for more information. @@ -85,11 +91,8 @@ The following example activates all the events except `Drag`, `Idle`, `MouseMove @using AzureMapsControl.Components.Map + +@code { + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark", + ShowLogo = false, + ShowFeedbackLink = false + }; +} ``` The following example deactivates all the events except `Ready`. @@ -106,13 +118,19 @@ The following example deactivates all the events except `Ready`. @using AzureMapsControl.Components.Map + +@code { + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark", + ShowLogo = false, + ShowFeedbackLink = false + }; +} ``` \ No newline at end of file diff --git a/docs/popups/README.md b/docs/popups/README.md index fcbd9d0..1a668e3 100644 --- a/docs/popups/README.md +++ b/docs/popups/README.md @@ -9,7 +9,7 @@ Popups can be added to the map using the `AddPopupAsync` method on the map. If t @using AzureMapsControl.Components.Map @code { + + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark" + }; + public async Task OnMapReady(MapEventArgs events) { const string dataSourceId = "heatmapDataSource"; diff --git a/docs/sources/vectortilesources/README.md b/docs/sources/vectortilesources/README.md index 18d784d..2abdd69 100644 --- a/docs/sources/vectortilesources/README.md +++ b/docs/sources/vectortilesources/README.md @@ -5,15 +5,20 @@ A vector tile source loads data formatted as vector tiles for the current map vi @using AzureMapsControl.Components.Map @code { + + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark" + }; + public async Task OnMapReady(MapEventArgs events) { var sourceId = "dataSourceId"; diff --git a/docs/traffic/README.md b/docs/traffic/README.md index 7dcc90a..b6a8c29 100644 --- a/docs/traffic/README.md +++ b/docs/traffic/README.md @@ -1,15 +1,31 @@ ## Traffic -![Traffic](./assets/traffic.png) +![Traffic](../assets/traffic.png) Traffic information can be added to the map by providing the `TrafficOptions` parameter on the `AzureMap` component. ``` -@page "/Traffic" +@page "/TrafficOptionsUpdate" @using AzureMapsControl.Components.Map + CameraOptions="new CameraOptions { Center = new AzureMapsControl.Components.Atlas.Position(11.581990, 48.143534), Zoom = 10}" + StyleOptions="StyleOptions" + EventActivationFlags="MapEventActivationFlags.None().Enable(MapEventType.Ready)" + TrafficOptions="new Components.Traffic.TrafficOptions { Incidents = false, Flow = AzureMapsControl.Components.Traffic.TrafficFlow.Relative }" + OnReady="OnMapReadyAsync" /> + +@code { + + public StyleOptions StyleOptions = new StyleOptions + { + ShowLogo = false + }; + + public async Task OnMapReadyAsync(MapEventArgs eventArgs) + { + System.Threading.Thread.Sleep(5000); + await eventArgs.Map.SetTrafficOptionsAsync(options => options.Incidents = true); + } +} ``` \ No newline at end of file diff --git a/samples/AzureMapsControl.Sample/Pages/BubbleLayerOnReady.razor b/samples/AzureMapsControl.Sample/Pages/BubbleLayerOnReady.razor index 2cacd76..b8bc784 100644 --- a/samples/AzureMapsControl.Sample/Pages/BubbleLayerOnReady.razor +++ b/samples/AzureMapsControl.Sample/Pages/BubbleLayerOnReady.razor @@ -2,7 +2,7 @@ @using AzureMapsControl.Components.Map @code { + + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark" + }; + public async Task OnMapReady(MapEventArgs events) { const string dataSourceId = "heatmapDataSource"; diff --git a/samples/AzureMapsControl.Sample/Pages/ImageLayerOnReady.razor b/samples/AzureMapsControl.Sample/Pages/ImageLayerOnReady.razor index 949542a..39e53d8 100644 --- a/samples/AzureMapsControl.Sample/Pages/ImageLayerOnReady.razor +++ b/samples/AzureMapsControl.Sample/Pages/ImageLayerOnReady.razor @@ -2,8 +2,7 @@ @using AzureMapsControl.Components.Map \ No newline at end of file + CameraOptions="new CameraOptions { Center= new AzureMapsControl.Components.Atlas.Position(11.581990, 48.143534), Zoom= 10 }" + StyleOptions="StyleOptions"/> + +@code { + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark", + ShowLogo = false, + ShowFeedbackLink = false + }; +} \ No newline at end of file diff --git a/samples/AzureMapsControl.Sample/Pages/LayerRemove.razor b/samples/AzureMapsControl.Sample/Pages/LayerRemove.razor index fc882d5..afe08e8 100644 --- a/samples/AzureMapsControl.Sample/Pages/LayerRemove.razor +++ b/samples/AzureMapsControl.Sample/Pages/LayerRemove.razor @@ -2,8 +2,7 @@ @using AzureMapsControl.Components.Map @code { + + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark" + }; + public async Task OnMapReady(MapEventArgs events) { const string dataSourceId = "dataSource"; diff --git a/samples/AzureMapsControl.Sample/Pages/PolygonExtrusionLayerOnReady.razor b/samples/AzureMapsControl.Sample/Pages/PolygonExtrusionLayerOnReady.razor index efd3943..7ae8461 100644 --- a/samples/AzureMapsControl.Sample/Pages/PolygonExtrusionLayerOnReady.razor +++ b/samples/AzureMapsControl.Sample/Pages/PolygonExtrusionLayerOnReady.razor @@ -2,9 +2,7 @@ @using AzureMapsControl.Components.Map + +@code { + + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark", + ShowLogo = false, + ShowFeedbackLink = false + }; + + public async Task OnMapReadyAsync(MapEventArgs eventArgs) + { + System.Threading.Thread.Sleep(5000); + await eventArgs.Map.SetStyleOptionsAsync(options => options.ShowTileBoundaries = true); + } +} \ No newline at end of file diff --git a/samples/AzureMapsControl.Sample/Pages/SymbolLayerOnReady.razor b/samples/AzureMapsControl.Sample/Pages/SymbolLayerOnReady.razor index aec8e65..a59075c 100644 --- a/samples/AzureMapsControl.Sample/Pages/SymbolLayerOnReady.razor +++ b/samples/AzureMapsControl.Sample/Pages/SymbolLayerOnReady.razor @@ -2,7 +2,7 @@ @using AzureMapsControl.Components.Map \ No newline at end of file + CameraOptions="new CameraOptions { Center = new AzureMapsControl.Components.Atlas.Position(11.581990, 48.143534), Zoom = 10}" + /> \ No newline at end of file diff --git a/samples/AzureMapsControl.Sample/Pages/TrafficOptionsUpdate.razor b/samples/AzureMapsControl.Sample/Pages/TrafficOptionsUpdate.razor new file mode 100644 index 0000000..c0a3264 --- /dev/null +++ b/samples/AzureMapsControl.Sample/Pages/TrafficOptionsUpdate.razor @@ -0,0 +1,23 @@ +@page "/TrafficOptionsUpdate" + +@using AzureMapsControl.Components.Map + + +@code { + + public StyleOptions StyleOptions = new StyleOptions + { + ShowLogo = false + }; + + public async Task OnMapReadyAsync(MapEventArgs eventArgs) + { + System.Threading.Thread.Sleep(5000); + await eventArgs.Map.SetTrafficOptionsAsync(options => options.Incidents = true); + } +} \ No newline at end of file diff --git a/samples/AzureMapsControl.Sample/Pages/UserInteractionUpdate.razor b/samples/AzureMapsControl.Sample/Pages/UserInteractionUpdate.razor new file mode 100644 index 0000000..88c2b31 --- /dev/null +++ b/samples/AzureMapsControl.Sample/Pages/UserInteractionUpdate.razor @@ -0,0 +1,25 @@ +@page "/UserInteractionUpdate" + +@using AzureMapsControl.Components.Map + + +@code { + + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark", + ShowLogo = false, + ShowFeedbackLink = false + }; + + public async Task OnMapReadyAsync(MapEventArgs eventArgs) + { + System.Threading.Thread.Sleep(5000); + await eventArgs.Map.SetUserInteractionAsync(options => options.Interactive = true); + } +} \ No newline at end of file diff --git a/samples/AzureMapsControl.Sample/Pages/VectorTileSource.razor b/samples/AzureMapsControl.Sample/Pages/VectorTileSource.razor index 2719633..ce174d4 100644 --- a/samples/AzureMapsControl.Sample/Pages/VectorTileSource.razor +++ b/samples/AzureMapsControl.Sample/Pages/VectorTileSource.razor @@ -2,15 +2,20 @@ @using AzureMapsControl.Components.Map @code { + + public StyleOptions StyleOptions = new StyleOptions + { + Style = "grayscale_dark" + }; + public async Task OnMapReady(MapEventArgs events) { var sourceId = "dataSourceId"; diff --git a/src/AzureMapsControl.Components/Configuration/AzureMapsConfiguration.cs b/src/AzureMapsControl.Components/Configuration/AzureMapsConfiguration.cs index df84659..2fd70ce 100644 --- a/src/AzureMapsControl.Components/Configuration/AzureMapsConfiguration.cs +++ b/src/AzureMapsControl.Components/Configuration/AzureMapsConfiguration.cs @@ -1,8 +1,13 @@ namespace AzureMapsControl.Components.Configuration { + using System; + using System.Text.Json; + using System.Text.Json.Serialization; + /// /// Options for specifying how the map control should authenticate with the Azure Maps services. /// + [JsonConverter(typeof(AzureMapsConfigurationJsonConverter))] public sealed class AzureMapsConfiguration { /// @@ -43,4 +48,25 @@ internal string AuthType } } } + + internal sealed class AzureMapsConfigurationJsonConverter : JsonConverter + { + public override AzureMapsConfiguration Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException(); + public override void Write(Utf8JsonWriter writer, AzureMapsConfiguration value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteString("authType", value.AuthType); + if (value.AuthType == "subscriptionKey") + { + writer.WriteString("subscriptionKey", value.SubscriptionKey); + } + else if (value.AuthType == "aad") + { + writer.WriteString("aadAppId", value.AadAppId); + writer.WriteString("aadTenant", value.AadTenant); + writer.WriteString("clientId", value.ClientId); + } + writer.WriteEndObject(); + } + } } diff --git a/src/AzureMapsControl.Components/Constants/Constants.cs b/src/AzureMapsControl.Components/Constants/Constants.cs index 5afeb5d..bc41133 100644 --- a/src/AzureMapsControl.Components/Constants/Constants.cs +++ b/src/AzureMapsControl.Components/Constants/Constants.cs @@ -14,6 +14,9 @@ internal static class JsConstants internal const string MethodClearMap = "clearMap"; internal const string MethodSetOptions = "setOptions"; internal const string MethodSetCameraOptions = "setCameraOptions"; + internal const string MethodSetStyleOptions = "setStyleOptions"; + internal const string MethodSetUserInteraction = "setUserInteraction"; + internal const string MethodSetTraffic = "setTraffic"; internal const string MethodAddControl = "addControls"; diff --git a/src/AzureMapsControl.Components/Map/AzureMap.razor b/src/AzureMapsControl.Components/Map/AzureMap.razor index d3ca387..ebda2f9 100644 --- a/src/AzureMapsControl.Components/Map/AzureMap.razor +++ b/src/AzureMapsControl.Components/Map/AzureMap.razor @@ -28,115 +28,28 @@ #region Parameters /// - /// If true the map will automatically resize whenever the window's size changes. Otherwise map.resize() must be called. - /// Default true. + /// The options for setting the map control's camera. /// [Parameter] - public bool AutoResize { get; set; } = true; + public CameraOptions CameraOptions { get; set; } = new CameraOptions(); /// - /// The bearing of the map (rotation). - /// default: North + /// Options for the map's style. /// [Parameter] - public Bearing Bearing { get; set; } = Bearing.North; + public StyleOptions StyleOptions { get; set; } = new StyleOptions(); /// - /// The bounds of the map control's camera + /// Options for enabling/disabling user interaction with the map. /// [Parameter] - public BoundingBox Bounds { get; set; } + public UserInteractionOptions UserInteractionOptions { get; set; } = new UserInteractionOptions(); /// - /// Whether the Shift + left click and drag will draw a zoom box. default true + /// Global properties used in all atlas service requests. /// [Parameter] - public bool BoxZoomInteraction { get; set; } = true; - - /// - /// The type of animation. - /// "jump" is an immediate change. - /// "ease" is a gradual change of the camera's settings. - /// "fly" is a gradual change of the camera's settings following an arc resembling flight. - /// - [Parameter] - public CameraType CameryType { get; set; } - - /// - /// The position to align the center of the map view with - /// - [Parameter] - public Position Center { get; set; } - - /// - /// A pixel offset to apply to the center of the map. - /// This is useful if you want to programmatically pan the map to another location or if you want to center the map over a shape, then offset the maps view to make room for a popup. - /// - [Parameter] - public Pixel CenterOffset { get; set; } - - /// - /// Whether double left click will zoom the map inwards. Default true - /// - [Parameter] - public bool DblclickZoomInteraction { get; set; } = true; - - /// - /// Disable telemetry collection - /// This option may only be set when initializing the map. - /// default: false - /// - [Parameter] - public bool DisableTelemetry { get; set; } - - /// - /// Whether left click and drag will pan the map. default true - /// - [Parameter] - public bool DragPanInteraction { get; set; } = true; - - /// - /// Whether right click and drag will rotate and pitch the map. default true - /// - [Parameter] - public bool DragRotateInteraction { get; set; } = true; - - /// - /// The duration of the animation in milliseconds. - /// - [Parameter] - public int? Duration { get; set; } - - /// - /// Enable accessibility - /// default: true - /// - [Parameter] - public bool EnableAccessibility { get; set; } = true; - - /// - /// Whether the map is interactive or static. If false, all user interaction is disabled. If true, only selected user interactions will enabled. default true - /// - [Parameter] - public bool Interactive { get; set; } = true; - - /// - /// Whether the keyboard interactions are enabled. Default true - /// - [Parameter] - public bool KeyboardInteraction { get; set; } = true; - - /// - /// The language of the map labels. - /// - [Parameter] - public string Language { get; set; } - - /// - /// Sets the lighting options of the map. - /// - [Parameter] - public LightOptions Light { get; set; } + public ServiceOptions ServiceOptions { get; set; } = new ServiceOptions(); /// /// Id affected to the div hosting the map @@ -148,122 +61,6 @@ set { if (string.IsNullOrWhiteSpace(value)) { throw new ArgumentException("ID on the map is mandatory"); } _id = value; } } - /// - /// A bounding box in which to constrain the viewable map area to. Users won't be able to pan the center of the map outside of this bounding box. Set maxBounds to null or undefined to remove maxBounds - /// - [Parameter] - public BoundingBox MaxBounds { get; set; } - - /// - /// The maximum zoom level that the map can be zoomed into during the animation. Must be between 0 and 24, and greater than or equal to `minZoom`. - /// - [Parameter] - public int? MaxZoom { get; set; } - - /// - /// The minimum zoom level that the map can be zoomed out to during the animation. Must be between 0 and 24, and less than or equal to `maxZoom`. - /// - [Parameter] - public int? MinZoom { get; set; } - - /// - /// An offset of the center of the given bounds relative to the map's center, measured in pixels - /// - [Parameter] - public Pixel Offset { get; set; } - - /// - /// The amount of padding in pixels to add to the given bounds - /// - [Parameter] - public Padding Padding { get; set; } - - /// - /// The pitch (tilt) of the map in degrees between 0 and 60, where 0 is looking straight down on the map. - /// - [Parameter] - public int? Pitch { get; set; } - - /// - /// If true, the map's canvas can be exported to a PNG using map.getCanvas().toDataURL(). - /// - [Parameter] - public bool PreserveDrawingBuffer { get; set; } - - /// - /// A boolean that specifies if vector and raster tiles should be reloaded when they expire (based on expires header). - /// This is useful for data sets that update frequently. When set to false, each tile will be loaded once, when needed, and not reloaded when they expire. - /// default: true - /// - [Parameter] - public bool RefreshExpiredTiles { get; set; } = true; - - /// - /// Specifies if multiple copies of the world should be rendered when zoomed out. Default true - /// - [Parameter] - public bool RenderWorldCopies { get; set; } = true; - - /// - /// Whether the map should zoom on scroll input. default true - /// - [Parameter] - public bool ScrollZoomInteraction { get; set; } = true; - - /// - /// Specifies if buildings will be rendered with their models. If false all buildings will be rendered as just their footprints - /// - [Parameter] - public bool ShowBuildingModels { get; set; } - - /// - /// Specifies if the feedback link should be displayed on the map or not. Default true - /// - [Parameter] - public bool ShowFeedbackLink { get; set; } = true; - - /// - /// Specifies if the Microsoft logo should be hidden or not. If set to true a Microsoft copyright string will be added to the map. Default true - /// - [Parameter] - public bool ShowLogo { get; set; } = true; - - /// - /// Specifies if the map should render an outline around each tile and the tile ID. These tile boundaries are useful for debugging. The uncompressed file size of the first vector source is drawn in the top left corner of each tile, next to the tile ID - /// - [Parameter] - public bool ShowTilesBoundaries { get; set; } - - /// - /// The name of the style to use when rendering the map - /// - [Parameter] - public string Style { get; set; } - - /// - /// Whether touch interactions are enabled for touch devices. default true - /// - [Parameter] - public bool TouchInteraction { get; set; } - - /// - /// Specifies which set of geopolitically disputed borders and labels are displayed on the map. The View parameter (also referred to as user region parameter) is a 2-letter ISO-3166 Country Code that will show the correct maps for that country/region. Country/Regions that are not on the View list or if unspecified will default to the Unified View - /// - [Parameter] - public string View { get; set; } - - /// - /// Sets the zoom rate of the mouse wheel default 1/450 - /// - [Parameter] - public double WheelZoomRate { get; set; } - - /// - /// The zoom level of the map view - /// - [Parameter] - public int? Zoom { get; set; } - /// /// Defines the events which needs to be activated /// @@ -620,17 +417,8 @@ { await JSRuntime.InvokeVoidAsync(Constants.JsConstants.MethodAddMap.ToAzureMapsControlNamespace(), Id, - Configuration.Value.AuthType, - Configuration.Value.AadAppId, - Configuration.Value.AadTenant, - Configuration.Value.ClientId, - Configuration.Value.SubscriptionKey, - new ServiceOptions - { - DisableTelemetry = DisableTelemetry, - EnableAccessibility = EnableAccessibility, - RefreshExpiredTiles = RefreshExpiredTiles - }, + Configuration.Value, + ServiceOptions, (EventActivationFlags ?? MapEventActivationFlags.None().Enable(MapEventType.Ready)).EnabledEvents, DotNetObjectReference.Create(_mapEventInvokeHelper)); } @@ -888,55 +676,11 @@ { if (mapEvent.Type == "ready") { - var cameraOptions = new CameraOptions - { - Bearing = (int?)Bearing, - CenterOffset = CenterOffset, - Duration = Duration, - MaxZoom = MaxZoom, - MinZoom = MinZoom, - Pitch = Pitch, - Type = CameryType?.ToString(), - Bounds = Bounds, - MaxBounds = Bounds != null ? MaxBounds : null, - Offset = Bounds != null ? Offset : null, - Padding = Bounds != null ? Padding : null, - Center = Bounds == null ? Center : null, - Zoom = Bounds == null ? Zoom : null - }; await JSRuntime.InvokeVoidAsync(Constants.JsConstants.MethodSetOptions.ToAzureMapsControlNamespace(), - cameraOptions, - new StyleOptions - { - AutoResize = AutoResize, - Language = Language, - Light = Light, - PreserveDrawingBuffer = PreserveDrawingBuffer, - RenderWorldCopies = RenderWorldCopies, - ShowBuildingModels = ShowBuildingModels, - ShowFeedbackLink = ShowFeedbackLink, - ShowLogo = ShowLogo, - ShowTileBoundaries = ShowTilesBoundaries, - Style = Style, - View = View - }, - new UserInteractionOptions - { - BoxZoomInteraction = BoxZoomInteraction, - DblclickZoomInteraction = DblclickZoomInteraction, - DragPanInteraction = DragPanInteraction, - DragRotateInteraction = DragRotateInteraction, - Interactive = Interactive, - KeyboardInteraction = KeyboardInteraction, - ScrollZoomInteraction = ScrollZoomInteraction, - TouchInteraction = TouchInteraction, - WheelZoomRate = WheelZoomRate - }, - TrafficOptions != null ? new AzureMapsControl.Components.Traffic.TrafficJsOptions - { - Flow = (TrafficOptions.Flow ?? AzureMapsControl.Components.Traffic.TrafficFlow.None).ToString(), - Incidents = TrafficOptions.Incidents - } : null); + CameraOptions, + StyleOptions, + UserInteractionOptions, + TrafficOptions); await MapService.AddMapAsync(new Map(Id, AddControlsAsync, @@ -958,12 +702,18 @@ AddPopupAsync, Popup_RemoveAsync, ClearPopupsAsync, - SetCameraOptionsAsync) + SetCameraOptionsAsync, + SetStyleOptionsAsync, + SetUserInteractionAsync, + SetTrafficAsync) { Controls = Controls, HtmlMarkers = HtmlMarkers, DrawingToolbarOptions = DrawingToolbarOptions, - CameraOptions = cameraOptions + CameraOptions = CameraOptions, + StyleOptions = StyleOptions, + UserInteractionOptions = UserInteractionOptions, + TrafficOptions = TrafficOptions }); await AddControlsAsync(Controls); @@ -975,6 +725,12 @@ private async Task SetCameraOptionsAsync(CameraOptions options) => await JSRuntime.InvokeVoidAsync(Constants.JsConstants.MethodSetCameraOptions.ToAzureMapsControlNamespace(), options); + private async Task SetStyleOptionsAsync(StyleOptions options) => await JSRuntime.InvokeVoidAsync(Constants.JsConstants.MethodSetStyleOptions.ToAzureMapsControlNamespace(), options); + + private async Task SetUserInteractionAsync(UserInteractionOptions options) => await JSRuntime.InvokeVoidAsync(Constants.JsConstants.MethodSetUserInteraction.ToAzureMapsControlNamespace(), options); + + private async Task SetTrafficAsync(AzureMapsControl.Components.Traffic.TrafficOptions options) => await JSRuntime.InvokeVoidAsync(Constants.JsConstants.MethodSetTraffic.ToAzureMapsControlNamespace(), options); + private async Task ClearMapAsync() => await JSRuntime.InvokeVoidAsync(Constants.JsConstants.MethodClearMap.ToAzureMapsControlNamespace()); private async Task DispatchMapEventAsync(MapJsEventArgs mapEvent) diff --git a/src/AzureMapsControl.Components/Map/Bearing.cs b/src/AzureMapsControl.Components/Map/Bearing.cs index e075509..7133e65 100644 --- a/src/AzureMapsControl.Components/Map/Bearing.cs +++ b/src/AzureMapsControl.Components/Map/Bearing.cs @@ -1,13 +1,50 @@ namespace AzureMapsControl.Components.Map { + using System; + using System.Text.Json; + using System.Text.Json.Serialization; + /// /// Bearing of the map (rotation) /// - public enum Bearing + [JsonConverter(typeof(BearingJsonConverter))] + public sealed class Bearing { - North = 0, - East = 90, - South = 180, - West = 270 + internal int Degrees { get; } + + public static Bearing North = new Bearing(0); + public static Bearing East = new Bearing(90); + public static Bearing South = new Bearing(180); + public static Bearing West = new Bearing(270); + + private Bearing(int degrees) => Degrees = degrees; + + public static Bearing FromDegrees(int degrees) + { + switch (degrees) + { + + case 0: + return North; + + case 90: + return East; + + case 180: + return South; + + case 270: + return West; + + default: + return null; + } + } + } + + internal sealed class BearingJsonConverter : JsonConverter + { + public override Bearing Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => Bearing.FromDegrees(reader.GetInt32()); + public override void Write(Utf8JsonWriter writer, Bearing value, JsonSerializerOptions options) => writer.WriteNumberValue(value.Degrees); } } diff --git a/src/AzureMapsControl.Components/Map/CameraOptions.cs b/src/AzureMapsControl.Components/Map/CameraOptions.cs index 469f9d7..7b4651e 100644 --- a/src/AzureMapsControl.Components/Map/CameraOptions.cs +++ b/src/AzureMapsControl.Components/Map/CameraOptions.cs @@ -7,18 +7,74 @@ [ExcludeFromCodeCoverage] public sealed class CameraOptions { - public int? Bearing { get; set; } + /// + /// The bearing of the map (rotation). + /// default: North + /// + public Bearing Bearing { get; set; } = Bearing.North; + + /// + /// The bounds of the map control's camera + /// public BoundingBox Bounds { get; set; } + + /// + /// The position to align the center of the map view with + /// public Position Center { get; set; } + + /// + /// A pixel offset to apply to the center of the map. + /// This is useful if you want to programmatically pan the map to another location or if you want to center the map over a shape, then offset the maps view to make room for a popup. + /// public Pixel CenterOffset { get; set; } + + /// + /// The duration of the animation in milliseconds. + /// public int? Duration { get; set; } + + /// + /// A bounding box in which to constrain the viewable map area to. Users won't be able to pan the center of the map outside of this bounding box. Set maxBounds to null or undefined to remove maxBounds + /// public BoundingBox MaxBounds { get; set; } + + /// + /// The maximum zoom level that the map can be zoomed into during the animation. Must be between 0 and 24, and greater than or equal to `minZoom`. + /// public int? MaxZoom { get; set; } + + /// + /// The minimum zoom level that the map can be zoomed out to during the animation. Must be between 0 and 24, and less than or equal to `maxZoom`. + /// public int? MinZoom { get; set; } + + /// + /// An offset of the center of the given bounds relative to the map's center, measured in pixels + /// public Pixel Offset { get; set; } + + /// + /// The amount of padding in pixels to add to the given bounds + /// public Padding Padding { get; set; } + + /// + /// The pitch (tilt) of the map in degrees between 0 and 60, where 0 is looking straight down on the map. + /// public int? Pitch { get; set; } - public string Type { get; set; } + + /// + /// The type of animation. + /// "jump" is an immediate change. + /// "ease" is a gradual change of the camera's settings. + /// "fly" is a gradual change of the camera's settings following an arc resembling flight. + /// + public CameraType Type { get; set; } + + /// + /// The zoom level of the map view + /// public int? Zoom { get; set; } } } diff --git a/src/AzureMapsControl.Components/Map/CameraType.cs b/src/AzureMapsControl.Components/Map/CameraType.cs index 862fa89..e695cba 100644 --- a/src/AzureMapsControl.Components/Map/CameraType.cs +++ b/src/AzureMapsControl.Components/Map/CameraType.cs @@ -1,8 +1,12 @@ namespace AzureMapsControl.Components.Map { + using System; using System.Diagnostics.CodeAnalysis; + using System.Text.Json; + using System.Text.Json.Serialization; [ExcludeFromCodeCoverage] + [JsonConverter(typeof(CameraTypeJsonConverter))] public sealed class CameraType { private readonly string _type; @@ -14,5 +18,24 @@ public sealed class CameraType private CameraType(string type) => _type = type; public override string ToString() => _type; + + internal static CameraType FromString(string type) + { + switch (type) + { + case "ease": + return Ease; + case "fly": + return Fly; + default: + return Jump; + } + } + } + + internal sealed class CameraTypeJsonConverter : JsonConverter + { + public override CameraType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => CameraType.FromString(reader.GetString()); + public override void Write(Utf8JsonWriter writer, CameraType value, JsonSerializerOptions options) => writer.WriteStringValue(value.ToString()); } } diff --git a/src/AzureMapsControl.Components/Map/Map.cs b/src/AzureMapsControl.Components/Map/Map.cs index 1fa7911..26ab74b 100644 --- a/src/AzureMapsControl.Components/Map/Map.cs +++ b/src/AzureMapsControl.Components/Map/Map.cs @@ -12,6 +12,7 @@ using AzureMapsControl.Components.Layers; using AzureMapsControl.Components.Markers; using AzureMapsControl.Components.Popups; + using AzureMapsControl.Components.Traffic; /// /// Representation of a map @@ -38,6 +39,9 @@ public sealed class Map private readonly Func _removePopupCallback; private readonly Func _clearPopupsCallback; private readonly Func _setCameraCallback; + private readonly Func _setStyleCallback; + private readonly Func _setUserInteractionCallback; + private readonly Func _setTrafficOptions; private List _layers; private List _sources; @@ -61,6 +65,9 @@ public sealed class Map public IEnumerable Popups => _popups; internal CameraOptions CameraOptions { get; set; } + internal StyleOptions StyleOptions { get; set; } + internal UserInteractionOptions UserInteractionOptions { get; set; } + internal TrafficOptions TrafficOptions { get; set; } internal Map(string id, Func, Task> addControlsCallback = null, @@ -82,7 +89,10 @@ internal Map(string id, Func addPopupCallback = null, Func removePopupCallback = null, Func clearPopupsCallback = null, - Func setCameraCallback = null) + Func setCameraCallback = null, + Func setStyleCallback = null, + Func setUserInteractionCallback = null, + Func setTrafficOptions = null) { Id = id; _addControlsCallback = addControlsCallback; @@ -105,6 +115,9 @@ internal Map(string id, _removePopupCallback = removePopupCallback; _clearPopupsCallback = clearPopupsCallback; _setCameraCallback = setCameraCallback; + _setStyleCallback = setStyleCallback; + _setUserInteractionCallback = setUserInteractionCallback; + _setTrafficOptions = setTrafficOptions; } # region Controls @@ -396,12 +409,66 @@ public async Task ClearMapAsync() await _clearMapCallback.Invoke(); } - public async Task SetCameraOptionsAsync(Action optionsCallback) + /// + /// Update the camera options of the map + /// + /// Action setting the camera options + /// + public async Task SetCameraOptionsAsync(Action configure) { - optionsCallback.Invoke(CameraOptions); + if (CameraOptions == null) + { + CameraOptions = new CameraOptions(); + } + configure.Invoke(CameraOptions); await _setCameraCallback.Invoke(CameraOptions); } + /// + /// Update the style options of the map + /// + /// Action setting the style options + /// + public async Task SetStyleOptionsAsync(Action configure) + { + if (StyleOptions == null) + { + StyleOptions = new StyleOptions(); + } + configure.Invoke(StyleOptions); + await _setStyleCallback.Invoke(StyleOptions); + } + + /// + /// Update the user interaction options of the map + /// + /// Action setting the user interaction options + /// + public async Task SetUserInteractionAsync(Action configure) + { + if (UserInteractionOptions == null) + { + UserInteractionOptions = new UserInteractionOptions(); + } + configure.Invoke(UserInteractionOptions); + await _setUserInteractionCallback.Invoke(UserInteractionOptions); + } + + /// + /// Update the traffic options on the map + /// + /// Action setting the traffic options + /// + public async Task SetTrafficOptionsAsync(Action configure) + { + if (TrafficOptions == null) + { + TrafficOptions = new TrafficOptions(); + } + configure.Invoke(TrafficOptions); + await _setTrafficOptions.Invoke(TrafficOptions); + } + #endregion #region Popups diff --git a/src/AzureMapsControl.Components/Map/ServiceOptions.cs b/src/AzureMapsControl.Components/Map/ServiceOptions.cs index 77b1632..22d4bbf 100644 --- a/src/AzureMapsControl.Components/Map/ServiceOptions.cs +++ b/src/AzureMapsControl.Components/Map/ServiceOptions.cs @@ -6,7 +6,7 @@ /// Global properties used in all atlas service requests. /// [ExcludeFromCodeCoverage] - internal class ServiceOptions + public sealed class ServiceOptions { /// /// Disable telemetry collection @@ -15,14 +15,15 @@ internal class ServiceOptions public bool DisableTelemetry { get; set; } /// - /// Enable accessibility + /// Enable accessibility. Default: true /// - public bool EnableAccessibility { get; set; } + public bool EnableAccessibility { get; set; } = true; /// /// A boolean that specifies if vector and raster tiles should be reloaded when they expire (based on expires header). /// This is useful for data sets that update frequently. When set to false, each tile will be loaded once, when needed, and not reloaded when they expire. + /// Default: true /// - public bool RefreshExpiredTiles { get; set; } + public bool RefreshExpiredTiles { get; set; } = true; } } diff --git a/src/AzureMapsControl.Components/Map/StyleOptions.cs b/src/AzureMapsControl.Components/Map/StyleOptions.cs index 31c7d1e..3cea604 100644 --- a/src/AzureMapsControl.Components/Map/StyleOptions.cs +++ b/src/AzureMapsControl.Components/Map/StyleOptions.cs @@ -3,18 +3,62 @@ using System.Diagnostics.CodeAnalysis; [ExcludeFromCodeCoverage] - internal class StyleOptions + public sealed class StyleOptions { - public bool AutoResize { get; set; } + /// + /// If true the map will automatically resize whenever the window's size changes. Otherwise map.resize() must be called. + /// Default true. + /// + public bool AutoResize { get; set; } = true; + + /// + /// The language of the map labels. + /// public string Language { get; set; } + + /// + /// Sets the lighting options of the map. + /// public LightOptions Light { get; set; } + + /// + /// If true, the map's canvas can be exported to a PNG using map.getCanvas().toDataURL(). + /// public bool PreserveDrawingBuffer { get; set; } - public bool RenderWorldCopies { get; set; } + + /// + /// Specifies if multiple copies of the world should be rendered when zoomed out. Default true + /// + public bool RenderWorldCopies { get; set; } = true; + + /// + /// Specifies if buildings will be rendered with their models. If false all buildings will be rendered as just their footprints + /// public bool ShowBuildingModels { get; set; } - public bool ShowFeedbackLink { get; set; } - public bool ShowLogo { get; set; } + + /// + /// Specifies if the feedback link should be displayed on the map or not. Default true + /// + public bool ShowFeedbackLink { get; set; } = true; + + /// + /// Specifies if the Microsoft logo should be hidden or not. If set to true a Microsoft copyright string will be added to the map. Default true + /// + public bool ShowLogo { get; set; } = true; + + /// + /// Specifies if the map should render an outline around each tile and the tile ID. These tile boundaries are useful for debugging. The uncompressed file size of the first vector source is drawn in the top left corner of each tile, next to the tile ID + /// public bool ShowTileBoundaries { get; set; } + + /// + /// The name of the style to use when rendering the map + /// public string Style { get; set; } + + /// + /// Specifies which set of geopolitically disputed borders and labels are displayed on the map. The View parameter (also referred to as “user region parameter”) is a 2-letter ISO-3166 Country Code that will show the correct maps for that country/region. Country/Regions that are not on the View list or if unspecified will default to the “Unified” View + /// public string View { get; set; } } } diff --git a/src/AzureMapsControl.Components/Map/UserInteractionOptions.cs b/src/AzureMapsControl.Components/Map/UserInteractionOptions.cs index b38b7dd..b58be09 100644 --- a/src/AzureMapsControl.Components/Map/UserInteractionOptions.cs +++ b/src/AzureMapsControl.Components/Map/UserInteractionOptions.cs @@ -1,18 +1,53 @@ namespace AzureMapsControl.Components.Map { using System.Diagnostics.CodeAnalysis; - + [ExcludeFromCodeCoverage] - internal class UserInteractionOptions + public sealed class UserInteractionOptions { - public bool BoxZoomInteraction { get; set; } - public bool DblclickZoomInteraction { get; set; } - public bool DragPanInteraction { get; set; } - public bool DragRotateInteraction { get; set; } - public bool Interactive { get; set; } - public bool KeyboardInteraction { get; set; } - public bool ScrollZoomInteraction { get; set; } - public bool TouchInteraction { get; set; } + /// + /// Whether the Shift + left click and drag will draw a zoom box. default true + /// + public bool BoxZoomInteraction { get; set; } = true; + + /// + /// Whether double left click will zoom the map inwards. Default true + /// + public bool DblclickZoomInteraction { get; set; } = true; + + /// + /// Whether left click and drag will pan the map. default true + /// + public bool DragPanInteraction { get; set; } = true; + + /// + /// Whether right click and drag will rotate and pitch the map. default true + /// + public bool DragRotateInteraction { get; set; } = true; + + /// + /// Whether the map is interactive or static. If false, all user interaction is disabled. If true, only selected user interactions will enabled. default true + /// + public bool Interactive { get; set; } = true; + + /// + /// Whether the keyboard interactions are enabled. Default true + /// + public bool KeyboardInteraction { get; set; } = true; + + /// + /// Whether the map should zoom on scroll input. default true + /// + public bool ScrollZoomInteraction { get; set; } = true; + + /// + /// Whether touch interactions are enabled for touch devices. default true + /// + public bool TouchInteraction { get; set; } = true; + + /// + /// Sets the zoom rate of the mouse wheel default 1/450 + /// public double WheelZoomRate { get; set; } } } diff --git a/src/AzureMapsControl.Components/Traffic/TrafficFlow.cs b/src/AzureMapsControl.Components/Traffic/TrafficFlow.cs index 0827bad..0f01931 100644 --- a/src/AzureMapsControl.Components/Traffic/TrafficFlow.cs +++ b/src/AzureMapsControl.Components/Traffic/TrafficFlow.cs @@ -1,5 +1,6 @@ namespace AzureMapsControl.Components.Traffic { + using System; using System.Diagnostics.CodeAnalysis; /// @@ -30,6 +31,21 @@ public sealed class TrafficFlow private TrafficFlow(string flow) => _flow = flow; + internal static TrafficFlow FromString(string type) + { + switch (type) + { + case "absolute": + return Absolute; + case "relative": + return Relative; + case "relative-delay": + return RelativeDelay; + default: + return None; + } + } + public override string ToString() => _flow; } } diff --git a/src/AzureMapsControl.Components/Traffic/TrafficJsOptions.cs b/src/AzureMapsControl.Components/Traffic/TrafficJsOptions.cs deleted file mode 100644 index 79e277f..0000000 --- a/src/AzureMapsControl.Components/Traffic/TrafficJsOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace AzureMapsControl.Components.Traffic -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - internal class TrafficJsOptions - { - /// - /// The type of traffic flow to display - /// - public string Flow { get; set; } - - /// - /// Whether to display incidents on the map. - /// - public bool? Incidents { get; set; } - } -} diff --git a/src/AzureMapsControl.Components/Traffic/TrafficOptions.cs b/src/AzureMapsControl.Components/Traffic/TrafficOptions.cs index ca50a37..b255d60 100644 --- a/src/AzureMapsControl.Components/Traffic/TrafficOptions.cs +++ b/src/AzureMapsControl.Components/Traffic/TrafficOptions.cs @@ -1,12 +1,16 @@ namespace AzureMapsControl.Components.Traffic { + using System; using System.Diagnostics.CodeAnalysis; + using System.Text.Json; + using System.Text.Json.Serialization; /// /// Contains the configuration to display traffic on the map /// [ExcludeFromCodeCoverage] + [JsonConverter(typeof(TrafficOptionsJsonConverter))] public sealed class TrafficOptions { /// @@ -19,4 +23,34 @@ public sealed class TrafficOptions /// public bool? Incidents { get; set; } } + + internal sealed class TrafficOptionsJsonConverter : JsonConverter + { + public override TrafficOptions Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var trafficOptions = new TrafficOptions(); + while (reader.Read()) + { + if (reader.TokenType == JsonTokenType.String) + { + trafficOptions.Flow = TrafficFlow.FromString(reader.GetString()); + } + else if (reader.TokenType == JsonTokenType.True) + { + trafficOptions.Incidents = true; + } + } + return trafficOptions; + } + public override void Write(Utf8JsonWriter writer, TrafficOptions value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteString("flow", value.Flow.ToString()); + if(value.Incidents.HasValue) + { + writer.WriteBoolean("incidents", value.Incidents.Value); + } + writer.WriteEndObject(); + } + } } diff --git a/src/AzureMapsControl.Components/wwwroot/azure-maps-control.js b/src/AzureMapsControl.Components/wwwroot/azure-maps-control.js index 50a819e..ebab208 100644 --- a/src/AzureMapsControl.Components/wwwroot/azure-maps-control.js +++ b/src/AzureMapsControl.Components/wwwroot/azure-maps-control.js @@ -200,30 +200,26 @@ window.azureMapsControl = { }); }, addMap: function (mapId, - authType, - aadAppId, - aadTenant, - clientId, - subscriptionKey, + configuration, serviceOptions, enabledEvents, eventHelper) { - if (authType === 'aad') { + if (configuration.authType === 'aad') { atlas.setAuthenticationOptions({ - authType: authType, - aadAppId: aadAppId, - aadTenant: aadTenant, - clientId: clientId + authType: configuration.authType, + aadAppId: configuration.aadAppId, + aadTenant: configuration.aadTenant, + clientId: configuration.clientId }); - } else if (authType === 'subscriptionKey') { + } else if (configuration.authType === 'subscriptionKey') { atlas.setAuthenticationOptions({ - authType: authType, - subscriptionKey: subscriptionKey + authType: configuration.authType, + subscriptionKey: configuration.subscriptionKey }); } else { atlas.setAuthenticationOptions({ - authType: authType + authType: configuration.authType }); } @@ -362,12 +358,18 @@ window.azureMapsControl = { trafficOptions) { this.setCameraOptions(cameraOptions); - this._map.setStyle(styleOptions); + this.setStyleOptions(styleOptions); + this.setUserInteraction(userInteractionOptions); + this.setTraffic(trafficOptions); + }, + setTraffic: function (trafficOptions) { + this._map.setTraffic(trafficOptions); + }, + setUserInteraction: function (userInteractionOptions) { this._map.setUserInteraction(userInteractionOptions); - - if (trafficOptions) { - this._map.setTraffic(trafficOptions); - } + }, + setStyleOptions: function (styleOptions) { + this._map.setStyle(styleOptions); }, setCameraOptions: function (cameraOptions) { const options = { diff --git a/tests/AzureMapsControl.Components.Tests/Map/Map.cs b/tests/AzureMapsControl.Components.Tests/Map/Map.cs index d6c4d9b..f6c50a0 100644 --- a/tests/AzureMapsControl.Components.Tests/Map/Map.cs +++ b/tests/AzureMapsControl.Components.Tests/Map/Map.cs @@ -12,6 +12,7 @@ using AzureMapsControl.Components.Map; using AzureMapsControl.Components.Markers; using AzureMapsControl.Components.Popups; + using AzureMapsControl.Components.Traffic; using Xunit; @@ -607,5 +608,97 @@ public async void Should_UpdateCameraOptions_Async() await map.SetCameraOptionsAsync(options => options.Center = center); Assert.True(assertOptionsCallback); } + + [Fact] + public async void Should_UpdateCameraOptions_NoCameraOptionsDefined_Async() + { + var assertOptionsCallback = false; + var center = new Position(10, 10); + var map = new Map("id", setCameraCallback: async options => assertOptionsCallback = options.Center == center); + + await map.SetCameraOptionsAsync(options => options.Center = center); + Assert.True(assertOptionsCallback); + } + + [Fact] + public async void Should_UpdateStyleOptions_Async() + { + var assertOptionsCallback = false; + var language = "fr"; + var initialStyleOptions = new StyleOptions { + AutoResize = true + }; + var map = new Map("id", setStyleCallback: async options => assertOptionsCallback = options.AutoResize == initialStyleOptions.AutoResize && options.Language == language) { + StyleOptions = initialStyleOptions + }; + + await map.SetStyleOptionsAsync(options => options.Language = language); + Assert.True(assertOptionsCallback); + } + + [Fact] + public async void Should_UpdateStyleOptions_NoStyleOptionsDefined_Async() + { + var assertOptionsCallback = false; + var language = "fr"; + var map = new Map("id", setStyleCallback: async options => assertOptionsCallback = options.Language == language); + + await map.SetStyleOptionsAsync(options => options.Language = language); + Assert.True(assertOptionsCallback); + } + + [Fact] + public async void Should_UpdateUserInteraction_Async() + { + var assertOptionsCallback = false; + var initialUserInteractionOptions = new UserInteractionOptions { + BoxZoomInteraction = true + }; + var dblClickZoomInteraction = true; + var map = new Map("id", setUserInteractionCallback: async options => assertOptionsCallback = options.BoxZoomInteraction == initialUserInteractionOptions.BoxZoomInteraction && options.DblclickZoomInteraction == dblClickZoomInteraction) { + UserInteractionOptions = initialUserInteractionOptions + }; + + await map.SetUserInteractionAsync(options => options.DblclickZoomInteraction = dblClickZoomInteraction); + Assert.True(assertOptionsCallback); + } + + [Fact] + public async void Should_UpdateUserInteraction_NoUserInteractionDefined_Async() + { + var assertOptionsCallback = false; + var dblClickZoomInteraction = true; + var map = new Map("id", setUserInteractionCallback: async options => assertOptionsCallback = options.DblclickZoomInteraction == dblClickZoomInteraction); + + await map.SetUserInteractionAsync(options => options.DblclickZoomInteraction = dblClickZoomInteraction); + Assert.True(assertOptionsCallback); + } + + [Fact] + public async void Should_UpdateTrafficInteraction_Async() + { + var assertOptionsCallback = false; + var initialTrafficOptions = new TrafficOptions { + Flow = TrafficFlow.Absolute + }; + var incidents = true; + var map = new Map("id", setTrafficOptions: async options => assertOptionsCallback = options.Flow == initialTrafficOptions.Flow && options.Incidents == incidents) { + TrafficOptions = initialTrafficOptions + }; + + await map.SetTrafficOptionsAsync(options => options.Incidents = incidents); + Assert.True(assertOptionsCallback); + } + + [Fact] + public async void Should_UpdateTrafficInteraction_NoTrafficOptionsDefined_Async() + { + var assertOptionsCallback = false; + var incidents = true; + var map = new Map("id", setTrafficOptions: async options => assertOptionsCallback = options.Incidents == incidents); + + await map.SetTrafficOptionsAsync(options => options.Incidents = incidents); + Assert.True(assertOptionsCallback); + } } }