Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [0.3.0] 2023-05-12

### Added
Map Clustering for IOS and Android

## [0.2.0] 2022-12-08

### Added
Source link support

### update
bump uno to 4.4.20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I'm nit-picky but use some capital letters please. Don't do it if you don't want to.


## [0.1.1] 2022-04-10

### Added
Expand Down
7 changes: 7 additions & 0 deletions Samples/Samples/Samples.Shared/DynamicMapMenuPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@
<!-- Show DynamicMap_PushpinsPage button -->
<Button Content="Show overview of DynamicMap features"
Command="{Binding GotoDynamicMap_FeaturesPage}"
Style="{StaticResource BasicButtonStyle}"
HorizontalAlignment="Stretch"
Margin="0,20" />

<!-- Show DynamicMap_PushpinsPage button -->
<Button Content="Show DynamicMap Clustering sample"
Command="{Binding GotoDynamicMap_WithClustering_FeaturesPage}"
Style="{StaticResource BasicButtonStyle}"
HorizontalAlignment="Stretch"
Margin="0,20" />
Expand Down
4 changes: 3 additions & 1 deletion Samples/Samples/Samples.Shared/DynamicMap_FeaturesPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
<converters:FromNullableBoolToVisibilityConverter x:Key="IsTrueToVisible" />

<converters:FromNullableBoolToVisibilityConverter x:Key="IsTrueToCollapsed"
VisibilityIfTrue="Collapsed" />
VisibilityIfTrue="Collapsed" />

</ResourceDictionary>
</Page.Resources>

Expand Down Expand Up @@ -112,6 +113,7 @@
<dynamicMap:MapControl ViewModel="{Binding}"
SelectionMode="Single"
AutolocateButtonVisibility="Collapsed"
IsClusterEnabled="{Binding IsClusterEnabled}"
dynamicMap:MapControlBehavior.DisableRotation="True"
dynamicMap:MapControlBehavior.PushpinImageSelector="{StaticResource PushpinEntityToMapPin}"
dynamicMap:MapControlBehavior.IconWidth="36"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public DynamicMapMenuViewModel()
await _sectionsNavigator.Navigate(ct, () => new DynamicMap_FeaturesPageViewModel());
});

public IDynamicCommand GotoDynamicMap_WithClustering_FeaturesPage => this.GetCommandFromTask(async ct =>
{
await _sectionsNavigator.Navigate(ct, () => new DynamicMap_FeaturesPageViewModel(isClusterEnabled: true));
});

public IDynamicCommand GotoDynamicMap_MoveSearchPage => this.GetCommandFromTask(async ct =>
{
await _sectionsNavigator.Navigate(ct, () => new DynamicMap_MoveSearchPageViewModel());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
using Chinook.DynamicMvvm;
using Uno.Extensions;
using Cartography.DynamicMap;
using Chinook.DynamicMvvm;
using Chinook.SectionsNavigation;
using GeolocatorService;
using Samples.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
using Cartography.DynamicMap;
using GeolocatorService;
using Uno.Extensions;
using Uno.Logging;
using Samples.Entities;
using System.Collections.Generic;
using Uno;
using Windows.Devices.Geolocation;
using Chinook.SectionsNavigation;
using System.Reactive.Concurrency;

namespace Samples.Presentation
{
Expand All @@ -32,8 +29,9 @@ public class DynamicMap_FeaturesPageViewModel : ViewModel, IDynamicMapComponent
private ISectionsNavigator _sectionsNavigator;
private readonly IDispatcherScheduler _dispatcherScheduler;

public DynamicMap_FeaturesPageViewModel()
public DynamicMap_FeaturesPageViewModel(bool isClusterEnabled = false)
{
IsClusterEnabled = isClusterEnabled;
_geolocatorService = this.GetService<IGeolocatorService>();
_sectionsNavigator = this.GetService<ISectionsNavigator>();
_dispatcherScheduler = this.GetService<IDispatcherScheduler>();
Expand Down Expand Up @@ -179,6 +177,12 @@ public bool IsUserDragging
set => this.Set(value);
}

public bool IsClusterEnabled
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be called IsClusteringEnabled? Using "Cluster" suggests that there is only 1 cluster.

{
get => this.Get<bool>(initialValue: false);
set => this.Set(value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this setter be private?

}

public LocationResult UserLocation
{
get => this.Get<LocationResult>();
Expand Down Expand Up @@ -292,17 +296,57 @@ private PushpinEntity[] GetInitialPushpins()
new PushpinEntity
{
Name = "Pushpin 1",
Coordinates = new Geopoint(new BasicGeoposition{Latitude = 46.3938717, Longitude = -72.0921769})
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5040713, Longitude = -73.5587092 })
},
new PushpinEntity
{
Name = "Pushpin 2",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5502838, Longitude = -73.2801901 })
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5041113, Longitude = -73.5584092 })
},
new PushpinEntity
{
Name = "Pushpin 3",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5502838, Longitude = -72.0921769 })
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5035613, Longitude = -73.5587392 })
},
new PushpinEntity
{
Name = "Pushpin 4",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5043413, Longitude = -73.5567092 })
},
new PushpinEntity
{
Name = "Pushpin 5",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5040713, Longitude = -73.5547092 })
},
new PushpinEntity
{
Name = "Pushpin 6",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5042713, Longitude = -73.5583092 })
},
new PushpinEntity
{
Name = "Pushpin 7",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5046513, Longitude = -73.5587492 })
},
new PushpinEntity
{
Name = "Pushpin 8",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5042313, Longitude = -73.5583562 })
},
new PushpinEntity
{
Name = "Pushpin 9",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5040313, Longitude = -73.5584322 })
},
new PushpinEntity
{
Name = "Pushpin 10",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5502338, Longitude = -73.2801901 })
},
new PushpinEntity
{
Name = "Pushpin 11",
Coordinates = new Geopoint(new BasicGeoposition { Latitude = 45.5501838, Longitude = -72.0921769 })
},
};
}
Expand Down Expand Up @@ -387,7 +431,7 @@ private async Task<GeoViewPort> GetUserCoordinates(CancellationToken ct)
var newPushpin = await CreatePushpinAtCenter(ct);

var list = pushpins.ToList();
list.Add((IGeoLocated)newPushpin);
list.Add(newPushpin);

Pushpins = list.ToArray();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ public int? AnimationDurationSeconds
await _sectionsNavigator.Navigate(ct, () => new DynamicMapMenuViewModel());
});

public bool IsClusterEnabled
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed? It seems like the xaml associated with this VM wasn't modified?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the same comments from the DynamicMap_FeaturesPageViewModel apply here too.

{
get => this.Get(initialValue: false);
set => this.Set(value);
}

private MapViewPort GetStartingCoordinates()
{
var mapViewPort = new MapViewPort(new Geopoint(new BasicGeoposition { Latitude = 45.503343, Longitude = -73.571695 }));
Expand Down
4 changes: 2 additions & 2 deletions build/gitversion.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
assembly-versioning-scheme: MajorMinorPatch
mode: ContinuousDeployment
next-version: 0.2.0
next-version: 0.3.0
continuous-delivery-fallback-tag: ""
increment: none # Disabled as it is not used. Saves time on the GitVersion step
branches:
Expand Down Expand Up @@ -32,4 +32,4 @@ branches:
source-branches: ['master']
increment: none
ignore:
sha: []
sha: []
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

<ItemGroup Condition="'$(TargetFramework)' == 'xamarinios10'">
<PackageReference Include="Xamarin.Google.iOS.Maps" Version="3.9.0" />
<PackageReference Include="Xamarin.Google.Maps.Utils" Version="1.3.4" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this comes from a previous PR, but why is the DynamicMap package referencing Google maps on iOS? Shouldn't there be a package specific for GoogleMaps on iOS? GoogleMaps is not the default maps provider on iOS.

</ItemGroup>

<ItemGroup>
Expand All @@ -55,12 +56,9 @@
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'monoandroid12.0'">
<PackageReference Include="Xamarin.GooglePlayServices.Base">
<Version>117.6.0.5</Version>
</PackageReference>
<PackageReference Include="Xamarin.GooglePlayServices.Maps">
<Version>117.0.1.5</Version>
</PackageReference>
<PackageReference Include="Xamarin.Google.Maps.Utils" Version="1.3.4" />
<PackageReference Include="Xamarin.GooglePlayServices.Base" Version="117.6.0.5" />
<PackageReference Include="Xamarin.GooglePlayServices.Maps" Version="117.0.1.5" />
</ItemGroup>

</Project>
39 changes: 22 additions & 17 deletions src/Cartography/Cartography.DynamicMap/IDynamicMapComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ namespace Cartography.DynamicMap
public interface IDynamicMapComponent
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The xml doc on the interface itself should be updated too.
And you could fix the grammar at the same time instead of just adding the period.

{
/// <summary>
/// Pushpins to display on map
/// Pushpins to display on map.
/// </summary>
IGeoLocated[] Pushpins { get; set; }

/// <summary>
/// Selected pushpin
/// Selected pushpin.
/// </summary>
IGeoLocated[] SelectedPushpins { get; set; }

/// <summary>
/// Groups to display on map
/// Groups to display on map.
/// </summary>
IGeoLocatedGrouping<IGeoLocated[]> Groups { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are groups? Is it explained somewhere? How is it different from clusters?


/// <summary>
/// Min delay to wait between two map viewport update
/// Min delay to wait between two map viewport update.
/// </summary>
TimeSpan ViewPortUpdateMinDelay { get; set; }

/// <summary>
/// Equality comparer to use to filter the map viewport updates
/// Equality comparer to use to filter the map viewport updates.
/// </summary>
IEqualityComparer<MapViewPort> ViewPortUpdateFilter { get; set; }

Expand All @@ -41,48 +41,53 @@ public interface IDynamicMapComponent
Action<Geocoordinate> OnMapTapped { get; set; }

/// <summary>
/// Defines whether user tracking is enabled - READ / WRITE
/// Defines whether user tracking is enabled - READ / WRITE.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with the "- READ / WRITE"?

/// </summary>
bool IsUserTrackingCurrentlyEnabled { get; set; }

/// <summary>
/// Whether or not the user is currently dragging the map
/// Whether or not the user is currently dragging the map.
/// </summary>
bool IsUserDragging { get; set; }

/// <summary>
/// User location if any and if display requested, else empty value
/// </summary>
LocationResult UserLocation { get; set; }
/// <summary>
/// Whether or not the pushpin clustering is enabled.
/// </summary>
bool IsClusterEnabled { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this should probably be named IsClusteringEnable.


/// <summary>
/// User location if any and if display requested, else empty value.
/// </summary>
LocationResult UserLocation { get; set; }

/// <summary>
/// VisibleRegion of the map - READ ONLY
/// VisibleRegion of the map - READ ONLY.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there a setter if this should be readonly?

/// </summary>
MapViewPortCoordinates ViewPortCoordinates { get; set; }

/// <summary>
/// ViewPort of the map - READ / WRITE - First viewport MUST be provided by VM
/// ViewPort of the map - READ / WRITE - First viewport MUST be provided by VM.
/// </summary>
MapViewPort ViewPort { get; set; }

/// <summary>
/// Sets the desired animation duration
/// Sets the desired animation duration.
/// </summary>
int? AnimationDurationSeconds { get; set; }
}

/// <summary>
/// The MapComponent default value for some field
/// The MapComponent default value for some field.
/// </summary>
public static class MapComponentDefaultValue
{
/// <summary>
/// Get the Default ViewPortUpdateMinDelay
/// Get the Default ViewPortUpdateMinDelay.
/// </summary>
public static TimeSpan DefaultViewPortUpdateMinDelay = TimeSpan.FromMilliseconds(250);

/// <summary>
/// Get the Default ViewPortUpdateFilter
/// Get the Default ViewPortUpdateFilter.
/// </summary>
public static IEqualityComparer<MapViewPort> DefaultViewPortUpdateFilter =
new PrettyMapViewPortEqualityComparer();
Expand Down
17 changes: 14 additions & 3 deletions src/Cartography/Cartography.DynamicMap/MapControlBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,20 @@ public Point PushpinIconsPositionOrigin
get { return (Point)this.GetValue(PushpinsIconsPositionOriginProperty); }
set { this.SetValue(PushpinsIconsPositionOriginProperty, value); }
}
#endregion

#region IsClusterEnabled (dp)
public static readonly DependencyProperty IsClusterEnabledProperty = DependencyProperty.Register(
"IsClusterEnabled", typeof(bool), typeof(MapControlBase), new PropertyMetadata(false));

public bool IsClusterEnabled
{
get { return (bool)this.GetValue(IsClusterEnabledProperty); }
set { this.SetValue(IsClusterEnabledProperty, value); }
}
#endregion

private readonly SerialDisposable _configuredSourceSubscriptions = new SerialDisposable();
private readonly SerialDisposable _configuredSourceSubscriptions = new SerialDisposable();
private ViewModelBase _configuredViewModel;

private Action<Geocoordinate> _onMapTapped;
Expand Down Expand Up @@ -511,7 +522,7 @@ private IDisposable SyncPushpinsFrom(ViewModelBase vm)
vm.GetAndObservePushpins(filterOutChangesFromSource: this),
vm.GetAndObserveGroups(filterOutChangesFromSource: this),
vm.GetAndObserveSelectedPushpins(filterOutChangesFromSource: null),
(pushpins, groups, selected) => new
(pushpins, groups, selected) => new
{
items = pushpins
.Concat(groups)
Expand All @@ -524,7 +535,7 @@ private IDisposable SyncPushpinsFrom(ViewModelBase vm)
.Do(x =>
{
UpdateMapPushpins(x.items, x.selected);
})
})
.ObserveOn(GetBackgroundScheduler())
.CombineLatest(
// In order to prevent the pushpins being updated when the source changes, but still making sure the pins are updated before the selection
Expand Down
Loading