Skip to content

Commit 8c22fa1

Browse files
committed
Handle conflicts between Bounds and Center on SetCameraOptions
1 parent 2ce0182 commit 8c22fa1

3 files changed

Lines changed: 97 additions & 4 deletions

File tree

src/AzureMapsControl.Components/Map/CameraOptions.cs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@
77
[ExcludeFromCodeCoverage]
88
public sealed class CameraOptions
99
{
10+
private BoundingBox _bounds;
11+
private Position _center;
12+
13+
/// <summary>
14+
/// Flag indicating if the bounds have been updated.
15+
/// If true, the bounds will be used while setting the camera options in favor of the center
16+
/// </summary>
17+
internal bool UpdatedBounds { get; set; }
18+
19+
/// <summary>
20+
/// Flag indicating if the center has been updated.
21+
/// If true and if the bounds have not been updated, the center will be used to set the camera options
22+
/// </summary>
23+
internal bool UpdatedCenter { get; set; }
24+
1025
/// <summary>
1126
/// The bearing of the map (rotation).
1227
/// default: North
@@ -16,12 +31,26 @@ public sealed class CameraOptions
1631
/// <summary>
1732
/// The bounds of the map control's camera
1833
/// </summary>
19-
public BoundingBox Bounds { get; set; }
34+
public BoundingBox Bounds
35+
{
36+
get => _bounds;
37+
set {
38+
_bounds = value;
39+
UpdatedBounds = true;
40+
}
41+
}
2042

2143
/// <summary>
2244
/// The position to align the center of the map view with
2345
/// </summary>
24-
public Position Center { get; set; }
46+
public Position Center
47+
{
48+
get => _center;
49+
set {
50+
_center = value;
51+
UpdatedCenter = true;
52+
}
53+
}
2554

2655
/// <summary>
2756
/// A pixel offset to apply to the center of the map.

src/AzureMapsControl.Components/Map/Map.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,17 +693,37 @@ public async ValueTask ClearMapAsync()
693693
}
694694

695695
/// <summary>
696-
/// Update the camera options of the map
696+
/// Update the camera options of the map.
697+
/// If this method updates the Bounds and the Center properties, the Bounds will be used to move the map and the Center and ZoomLevel will be ignored.
697698
/// </summary>
698-
/// <param name="configure">Action setting the camera options</param>
699+
/// <param name="configure">Action setting the camera options.</param>
699700
/// <returns></returns>
700701
public async ValueTask SetCameraOptionsAsync(Action<CameraOptions> configure)
701702
{
702703
if (CameraOptions == null)
703704
{
704705
CameraOptions = new CameraOptions();
705706
}
707+
708+
//Before calling the configure action, UpdatedBounds and UpdatedCenter should be set to false.
709+
//This allows us to identify if there was any change on one of this properties.
710+
CameraOptions.UpdatedBounds = false;
711+
CameraOptions.UpdatedCenter = false;
712+
706713
configure.Invoke(CameraOptions);
714+
715+
//If the bounds were updated, we set the center to null, so the bounds are used to move the map.
716+
//If the center has been updated and if the bounds did not change, the center will be used to move the map.s
717+
718+
if (CameraOptions.UpdatedBounds)
719+
{
720+
CameraOptions.Center = null;
721+
}
722+
else if (CameraOptions.UpdatedCenter)
723+
{
724+
CameraOptions.Bounds = null;
725+
}
726+
707727
_logger?.LogAzureMapsControlInfo(AzureMapLogEvent.Map_SetCameraOptionsAsync, "Setting camera options");
708728
await _jsRuntime.InvokeVoidAsync(Constants.JsConstants.Methods.Core.SetCameraOptions.ToCoreNamespace(), CameraOptions);
709729
}

tests/AzureMapsControl.Components.Tests/Map/Map.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,50 @@ public async void Should_UpdateCameraOptions_Async()
10101010
_jsRuntimeMock.VerifyNoOtherCalls();
10111011
}
10121012

1013+
[Fact]
1014+
public async void Should_UpdateCameraOptions_WithCenter_Async()
1015+
{
1016+
var center = new Position(10, 10);
1017+
var initialCameraOptions = new CameraOptions {
1018+
Duration = 10
1019+
};
1020+
var map = new Map("id", _jsRuntimeMock.Object, _loggerMock.Object) {
1021+
CameraOptions = initialCameraOptions
1022+
};
1023+
1024+
await map.SetCameraOptionsAsync(options => options.Center = center);
1025+
1026+
_jsRuntimeMock.Verify(runtime => runtime.InvokeVoidAsync(Constants.JsConstants.Methods.Core.SetCameraOptions.ToCoreNamespace(), It.Is<object[]>(parameters =>
1027+
(parameters[0] as CameraOptions).Duration == 10 && (parameters[0] as CameraOptions).Center.Longitude == 10 && (parameters[0] as CameraOptions).Center.Latitude == 10
1028+
)), Times.Once);
1029+
_jsRuntimeMock.VerifyNoOtherCalls();
1030+
}
1031+
1032+
[Fact]
1033+
public async void Should_UpdateCameraOptions_WithBounds_Async()
1034+
{
1035+
var bounds = new BoundingBox(-10, 10, 10, -10);
1036+
var initialCameraOptions = new CameraOptions {
1037+
Duration = 10
1038+
};
1039+
var map = new Map("id", _jsRuntimeMock.Object, _loggerMock.Object) {
1040+
CameraOptions = initialCameraOptions
1041+
};
1042+
1043+
await map.SetCameraOptionsAsync(options => {
1044+
options.Bounds = bounds;
1045+
options.Center = new Position(0, 0);
1046+
});
1047+
1048+
_jsRuntimeMock.Verify(runtime => runtime.InvokeVoidAsync(Constants.JsConstants.Methods.Core.SetCameraOptions.ToCoreNamespace(), It.Is<object[]>(parameters =>
1049+
(parameters[0] as CameraOptions).Duration == 10 && (parameters[0] as CameraOptions).Center == null && (parameters[0] as CameraOptions).Bounds.West == -10
1050+
&& (parameters[0] as CameraOptions).Bounds.South == 10
1051+
&& (parameters[0] as CameraOptions).Bounds.East == 10
1052+
&& (parameters[0] as CameraOptions).Bounds.North == -10
1053+
)), Times.Once);
1054+
_jsRuntimeMock.VerifyNoOtherCalls();
1055+
}
1056+
10131057
[Fact]
10141058
public async void Should_UpdateCameraOptions_NoCameraOptionsDefined_Async()
10151059
{

0 commit comments

Comments
 (0)