mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2026-04-05 06:26:41 +00:00
MapBase dependency properties
This commit is contained in:
parent
abe3bb75f9
commit
74f4e0176b
14 changed files with 1262 additions and 1037 deletions
|
|
@ -7,41 +7,49 @@ namespace MapControl
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1001")]
|
||||
public static class DependencyPropertyHelper
|
||||
{
|
||||
public static AvaloniaProperty Register<TOwner, TValue>(
|
||||
public static StyledProperty<TValue> Register<TOwner, TValue>(
|
||||
string name,
|
||||
TValue defaultValue = default,
|
||||
bool bindTwoWayByDefault = false,
|
||||
Action<TOwner, TValue, TValue> propertyChanged = null)
|
||||
Action<TOwner, TValue, TValue> changed = null,
|
||||
Func<TOwner, TValue, TValue> coerce = null)
|
||||
where TOwner : AvaloniaObject
|
||||
{
|
||||
StyledProperty<TValue> property = AvaloniaProperty.Register<TOwner, TValue>(name, defaultValue, false,
|
||||
bindTwoWayByDefault ? Avalonia.Data.BindingMode.TwoWay : Avalonia.Data.BindingMode.OneWay);
|
||||
var property = AvaloniaProperty.Register<TOwner, TValue>(name, defaultValue, false,
|
||||
bindTwoWayByDefault ? Avalonia.Data.BindingMode.TwoWay : Avalonia.Data.BindingMode.OneWay, null,
|
||||
coerce != null ? ((obj, value) => coerce((TOwner)obj, value)) : null);
|
||||
|
||||
if (propertyChanged != null)
|
||||
if (changed != null)
|
||||
{
|
||||
property.Changed.AddClassHandler<TOwner, TValue>(
|
||||
(o, e) => propertyChanged(o, e.OldValue.Value, e.NewValue.Value));
|
||||
property.Changed.AddClassHandler<TOwner, TValue>((o, e) => changed(o, e.OldValue.Value, e.NewValue.Value));
|
||||
}
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
public static AvaloniaProperty RegisterAttached<TOwner, TValue>(
|
||||
public static AttachedProperty<TValue> RegisterAttached<TOwner, TValue>(
|
||||
string name,
|
||||
TValue defaultValue = default,
|
||||
bool inherits = false,
|
||||
Action<Control, TValue, TValue> propertyChanged = null)
|
||||
Action<Control, TValue, TValue> changed = null)
|
||||
where TOwner : AvaloniaObject
|
||||
{
|
||||
AttachedProperty<TValue> property = AvaloniaProperty.RegisterAttached<TOwner, Control, TValue>(name, defaultValue, inherits);
|
||||
var property = AvaloniaProperty.RegisterAttached<TOwner, Control, TValue>(name, defaultValue, inherits);
|
||||
|
||||
if (propertyChanged != null)
|
||||
if (changed != null)
|
||||
{
|
||||
property.Changed.AddClassHandler<Control, TValue>(
|
||||
(o, e) => propertyChanged(o, e.OldValue.Value, e.NewValue.Value));
|
||||
property.Changed.AddClassHandler<Control, TValue>((o, e) => changed(o, e.OldValue.Value, e.NewValue.Value));
|
||||
}
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
public static DirectProperty<TOwner, TValue> RegisterReadOnly<TOwner, TValue>(
|
||||
string name,
|
||||
Func<TOwner, TValue> getter)
|
||||
where TOwner : AvaloniaObject
|
||||
{
|
||||
return AvaloniaProperty.RegisterDirect(name, getter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ namespace MapControl
|
|||
{
|
||||
public override Location Interpolate(double progress, Location oldValue, Location newValue)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(progress);
|
||||
return new Location(
|
||||
(1d - progress) * oldValue.Latitude + progress * newValue.Latitude,
|
||||
(1d - progress) * oldValue.Longitude + progress * newValue.Longitude);
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public class Map : MapBase
|
||||
{
|
||||
public static readonly StyledProperty<double> MouseWheelZoomDeltaProperty
|
||||
= AvaloniaProperty.Register<Map, double>(nameof(MouseWheelZoomDelta), 0.25);
|
||||
public static readonly StyledProperty<double> MouseWheelZoomDeltaProperty =
|
||||
DependencyPropertyHelper.Register<Map, double>(nameof(MouseWheelZoomDelta), 0.25);
|
||||
|
||||
private Point? mousePosition;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@
|
|||
global using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Styling;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
@ -15,40 +13,48 @@ namespace MapControl
|
|||
{
|
||||
public partial class MapBase
|
||||
{
|
||||
public static readonly StyledProperty<Location> CenterProperty
|
||||
= AvaloniaProperty.Register<MapBase, Location>(nameof(Center), new Location(), false,
|
||||
BindingMode.TwoWay, null, (map, center) => ((MapBase)map).CoerceCenterProperty(center));
|
||||
public static readonly StyledProperty<Location> CenterProperty =
|
||||
DependencyPropertyHelper.Register<MapBase, Location>(nameof(Center), new Location(), true,
|
||||
(map, oldValue, newValue) => map.CenterPropertyChanged(newValue),
|
||||
(map, value) => map.CoerceCenterProperty(value));
|
||||
|
||||
public static readonly StyledProperty<Location> TargetCenterProperty
|
||||
= AvaloniaProperty.Register<MapBase, Location>(nameof(TargetCenter), new Location(), false,
|
||||
BindingMode.TwoWay, null, (map, center) => ((MapBase)map).CoerceCenterProperty(center));
|
||||
public static readonly StyledProperty<Location> TargetCenterProperty =
|
||||
DependencyPropertyHelper.Register<MapBase, Location>(nameof(TargetCenter), new Location(), true,
|
||||
async (map, oldValue, newValue) => await map.TargetCenterPropertyChanged(newValue),
|
||||
(map, value) => map.CoerceCenterProperty(value));
|
||||
|
||||
public static readonly StyledProperty<double> MinZoomLevelProperty
|
||||
= AvaloniaProperty.Register<MapBase, double>(nameof(MinZoomLevel), 1d, false,
|
||||
BindingMode.OneWay, null, (map, minZoomLevel) => ((MapBase)map).CoerceMinZoomLevelProperty(minZoomLevel));
|
||||
public static readonly StyledProperty<double> MinZoomLevelProperty =
|
||||
DependencyPropertyHelper.Register<MapBase, double>(nameof(MinZoomLevel), 1d, false,
|
||||
(map, oldValue, newValue) => map.MinZoomLevelPropertyChanged(newValue),
|
||||
(map, value) => map.CoerceMinZoomLevelProperty(value));
|
||||
|
||||
public static readonly StyledProperty<double> MaxZoomLevelProperty
|
||||
= AvaloniaProperty.Register<MapBase, double>(nameof(MaxZoomLevel), 20d, false,
|
||||
BindingMode.OneWay, null, (map, maxZoomLevel) => ((MapBase)map).CoerceMaxZoomLevelProperty(maxZoomLevel));
|
||||
public static readonly StyledProperty<double> MaxZoomLevelProperty =
|
||||
DependencyPropertyHelper.Register<MapBase, double>(nameof(MaxZoomLevel), 20d, false,
|
||||
(map, oldValue, newValue) => map.MaxZoomLevelPropertyChanged(newValue),
|
||||
(map, value) => map.CoerceMinZoomLevelProperty(value));
|
||||
|
||||
public static readonly StyledProperty<double> ZoomLevelProperty
|
||||
= AvaloniaProperty.Register<MapBase, double>(nameof(ZoomLevel), 1d, false,
|
||||
BindingMode.TwoWay, null, (map, zoomLevel) => ((MapBase)map).CoerceZoomLevelProperty(zoomLevel));
|
||||
public static readonly StyledProperty<double> ZoomLevelProperty =
|
||||
DependencyPropertyHelper.Register<MapBase, double>(nameof(ZoomLevel), 1d, true,
|
||||
(map, oldValue, newValue) => map.ZoomLevelPropertyChanged(newValue),
|
||||
(map, value) => map.CoerceZoomLevelProperty(value));
|
||||
|
||||
public static readonly StyledProperty<double> TargetZoomLevelProperty
|
||||
= AvaloniaProperty.Register<MapBase, double>(nameof(TargetZoomLevel), 1d, false,
|
||||
BindingMode.TwoWay, null, (map, zoomLevel) => ((MapBase)map).CoerceZoomLevelProperty(zoomLevel));
|
||||
public static readonly StyledProperty<double> TargetZoomLevelProperty =
|
||||
DependencyPropertyHelper.Register<MapBase, double>(nameof(TargetZoomLevel), 1d, true,
|
||||
async (map, oldValue, newValue) => await map.TargetZoomLevelPropertyChanged(newValue),
|
||||
(map, value) => map.CoerceZoomLevelProperty(value));
|
||||
|
||||
public static readonly StyledProperty<double> HeadingProperty
|
||||
= AvaloniaProperty.Register<MapBase, double>(nameof(Heading), 0d, false,
|
||||
BindingMode.TwoWay, null, (map, heading) => CoerceHeadingProperty(heading));
|
||||
public static readonly StyledProperty<double> HeadingProperty =
|
||||
DependencyPropertyHelper.Register<MapBase, double>(nameof(Heading), 0d, true,
|
||||
(map, oldValue, newValue) => map.HeadingPropertyChanged(newValue),
|
||||
(map, value) => map.CoerceHeadingProperty(value));
|
||||
|
||||
public static readonly StyledProperty<double> TargetHeadingProperty
|
||||
= AvaloniaProperty.Register<MapBase, double>(nameof(TargetHeading), 0d, false,
|
||||
BindingMode.TwoWay, null, (map, heading) => CoerceHeadingProperty(heading));
|
||||
public static readonly StyledProperty<double> TargetHeadingProperty =
|
||||
DependencyPropertyHelper.Register<MapBase, double>(nameof(TargetHeading), 0d, true,
|
||||
async (map, oldValue, newValue) => await map.TargetHeadingPropertyChanged(newValue),
|
||||
(map, value) => map.CoerceHeadingProperty(value));
|
||||
|
||||
public static readonly DirectProperty<MapBase, double> ViewScaleProperty
|
||||
= AvaloniaProperty.RegisterDirect<MapBase, double>(nameof(ViewScale), map => map.ViewScale);
|
||||
public static readonly DirectProperty<MapBase, double> ViewScaleProperty =
|
||||
DependencyPropertyHelper.RegisterReadOnly<MapBase, double>(nameof(ViewScale), map => map.ViewScale);
|
||||
|
||||
private CancellationTokenSource centerCts;
|
||||
private CancellationTokenSource zoomLevelCts;
|
||||
|
|
@ -59,27 +65,9 @@ namespace MapControl
|
|||
|
||||
static MapBase()
|
||||
{
|
||||
Animation.RegisterCustomAnimator<Location, LocationAnimator>();
|
||||
|
||||
ClipToBoundsProperty.OverrideDefaultValue(typeof(MapBase), true);
|
||||
|
||||
CenterProperty.Changed.AddClassHandler<MapBase, Location>(
|
||||
(map, args) => map.CenterPropertyChanged(args.NewValue.Value));
|
||||
|
||||
TargetCenterProperty.Changed.AddClassHandler<MapBase, Location>(
|
||||
async (map, args) => await map.TargetCenterPropertyChanged(args.NewValue.Value));
|
||||
|
||||
ZoomLevelProperty.Changed.AddClassHandler<MapBase, double>(
|
||||
(map, args) => map.ZoomLevelPropertyChanged(args.NewValue.Value));
|
||||
|
||||
TargetZoomLevelProperty.Changed.AddClassHandler<MapBase, double>(
|
||||
async (map, args) => await map.TargetZoomLevelPropertyChanged(args.NewValue.Value));
|
||||
|
||||
HeadingProperty.Changed.AddClassHandler<MapBase, double>(
|
||||
(map, args) => map.HeadingPropertyChanged(args.NewValue.Value));
|
||||
|
||||
TargetHeadingProperty.Changed.AddClassHandler<MapBase, double>(
|
||||
async (map, args) => await map.TargetHeadingPropertyChanged(args.NewValue.Value));
|
||||
Animation.RegisterCustomAnimator<Location, LocationAnimator>();
|
||||
}
|
||||
|
||||
public MapBase()
|
||||
|
|
@ -123,44 +111,6 @@ namespace MapControl
|
|||
.Append(Matrix.CreateRotation(ViewTransform.Rotation));
|
||||
}
|
||||
|
||||
private void MapProjectionPropertyChanged(MapProjection projection)
|
||||
{
|
||||
maxLatitude = 90d;
|
||||
|
||||
if (projection.Type <= MapProjectionType.NormalCylindrical)
|
||||
{
|
||||
var maxLocation = projection.MapToLocation(new Point(0d, 180d * MapProjection.Wgs84MeterPerDegree));
|
||||
|
||||
if (maxLocation != null && maxLocation.Latitude < 90d)
|
||||
{
|
||||
maxLatitude = maxLocation.Latitude;
|
||||
|
||||
Center = CoerceCenterProperty(Center);
|
||||
}
|
||||
}
|
||||
|
||||
ResetTransformCenter();
|
||||
UpdateTransform(false, true);
|
||||
}
|
||||
|
||||
private Location CoerceCenterProperty(Location center)
|
||||
{
|
||||
if (center == null)
|
||||
{
|
||||
center = new Location();
|
||||
}
|
||||
else if (
|
||||
center.Latitude < -maxLatitude || center.Latitude > maxLatitude ||
|
||||
center.Longitude < -180d || center.Longitude > 180d)
|
||||
{
|
||||
center = new Location(
|
||||
Math.Min(Math.Max(center.Latitude, -maxLatitude), maxLatitude),
|
||||
Location.NormalizeLongitude(center.Longitude));
|
||||
}
|
||||
|
||||
return center;
|
||||
}
|
||||
|
||||
private void CenterPropertyChanged(Location center)
|
||||
{
|
||||
if (!internalPropertyChange)
|
||||
|
|
@ -204,19 +154,20 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
private double CoerceMinZoomLevelProperty(double minZoomLevel)
|
||||
private void MinZoomLevelPropertyChanged(double minZoomLevel)
|
||||
{
|
||||
return Math.Min(Math.Max(minZoomLevel, 0d), MaxZoomLevel);
|
||||
if (ZoomLevel < minZoomLevel)
|
||||
{
|
||||
ZoomLevel = minZoomLevel;
|
||||
}
|
||||
}
|
||||
|
||||
private double CoerceMaxZoomLevelProperty(double maxZoomLevel)
|
||||
private void MaxZoomLevelPropertyChanged(double maxZoomLevel)
|
||||
{
|
||||
return Math.Max(maxZoomLevel, MinZoomLevel);
|
||||
}
|
||||
|
||||
private double CoerceZoomLevelProperty(double zoomLevel)
|
||||
{
|
||||
return Math.Min(Math.Max(zoomLevel, MinZoomLevel), MaxZoomLevel);
|
||||
if (ZoomLevel > maxZoomLevel)
|
||||
{
|
||||
ZoomLevel = maxZoomLevel;
|
||||
}
|
||||
}
|
||||
|
||||
private void ZoomLevelPropertyChanged(double zoomLevel)
|
||||
|
|
@ -256,17 +207,17 @@ namespace MapControl
|
|||
|
||||
await zoomLevelAnimation.RunAsync(this, zoomLevelCts.Token);
|
||||
|
||||
if (!zoomLevelCts.IsCancellationRequested)
|
||||
{
|
||||
UpdateTransform(true);
|
||||
}
|
||||
|
||||
zoomLevelCts.Dispose();
|
||||
zoomLevelCts = null;
|
||||
zoomLevelAnimation = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static double CoerceHeadingProperty(double heading)
|
||||
{
|
||||
return ((heading % 360d) + 360d) % 360d;
|
||||
}
|
||||
|
||||
private void HeadingPropertyChanged(double heading)
|
||||
{
|
||||
if (!internalPropertyChange)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
<Compile Include="..\Shared\ImageLoader.cs" Link="ImageLoader.cs" />
|
||||
<Compile Include="..\Shared\Location.cs" Link="Location.cs" />
|
||||
<Compile Include="..\Shared\LocationCollection.cs" Link="LocationCollection.cs" />
|
||||
<Compile Include="..\Shared\MapBaseCommon.cs" Link="MapBaseCommon.cs" />
|
||||
<Compile Include="..\Shared\MapBase.cs" Link="MapBase.cs" />
|
||||
<Compile Include="..\Shared\MapPanel.cs" Link="MapPanel.cs" />
|
||||
<Compile Include="..\Shared\MapProjection.cs" Link="MapProjection.cs" />
|
||||
<Compile Include="..\Shared\MapTileLayer.cs" Link="MapTileLayer.cs" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue