2023-01-14 18:41:10 +01:00
|
|
|
|
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
2024-02-03 21:01:53 +01:00
|
|
|
|
// Copyright © 2024 Clemens Fischer
|
2023-01-14 18:41:10 +01:00
|
|
|
|
// Licensed under the Microsoft Public License (Ms-PL)
|
|
|
|
|
|
|
2024-05-22 11:25:32 +02:00
|
|
|
|
#if WPF
|
|
|
|
|
|
using System.Windows;
|
2023-01-14 18:41:10 +01:00
|
|
|
|
#elif UWP
|
|
|
|
|
|
using Windows.UI.Xaml;
|
2024-05-22 11:25:32 +02:00
|
|
|
|
#elif WINUI
|
|
|
|
|
|
using Microsoft.UI.Xaml;
|
2023-01-14 18:41:10 +01:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
namespace MapControl
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A MapPanel that adjusts the ViewPosition property of its child elements so that
|
|
|
|
|
|
/// elements that would be outside the current viewport are arranged on a border area.
|
|
|
|
|
|
/// Such elements are arranged at a distance of BorderWidth/2 from the edges of the
|
|
|
|
|
|
/// MapBorderPanel in direction of their original azimuth from the map center.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class MapBorderPanel : MapPanel
|
|
|
|
|
|
{
|
2024-05-22 22:08:07 +02:00
|
|
|
|
public static readonly DependencyProperty BorderWidthProperty =
|
|
|
|
|
|
DependencyPropertyHelper.Register<MapBorderPanel, double>(nameof(BorderWidth));
|
2023-01-14 18:41:10 +01:00
|
|
|
|
|
2024-05-22 22:08:07 +02:00
|
|
|
|
public static readonly DependencyProperty OnBorderProperty =
|
|
|
|
|
|
DependencyPropertyHelper.RegisterAttached<MapBorderPanel, bool>("OnBorder");
|
2023-01-14 18:41:10 +01:00
|
|
|
|
|
|
|
|
|
|
public double BorderWidth
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (double)GetValue(BorderWidthProperty);
|
|
|
|
|
|
set => SetValue(BorderWidthProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static bool GetOnBorder(FrameworkElement element)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (bool)element.GetValue(OnBorderProperty);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void SetViewPosition(FrameworkElement element, ref Point? position)
|
|
|
|
|
|
{
|
|
|
|
|
|
var onBorder = false;
|
|
|
|
|
|
var w = ParentMap.RenderSize.Width;
|
|
|
|
|
|
var h = ParentMap.RenderSize.Height;
|
|
|
|
|
|
var minX = BorderWidth / 2d;
|
|
|
|
|
|
var minY = BorderWidth / 2d;
|
|
|
|
|
|
var maxX = w - BorderWidth / 2d;
|
|
|
|
|
|
var maxY = h - BorderWidth / 2d;
|
|
|
|
|
|
|
|
|
|
|
|
if (position.HasValue &&
|
|
|
|
|
|
(position.Value.X < minX || position.Value.X > maxX ||
|
|
|
|
|
|
position.Value.Y < minY || position.Value.Y > maxY))
|
|
|
|
|
|
{
|
|
|
|
|
|
var dx = position.Value.X - w / 2d;
|
|
|
|
|
|
var dy = position.Value.Y - h / 2d;
|
|
|
|
|
|
var cx = (maxX - minX) / 2d;
|
|
|
|
|
|
var cy = (maxY - minY) / 2d;
|
|
|
|
|
|
double x, y;
|
|
|
|
|
|
|
|
|
|
|
|
if (dx < 0d)
|
|
|
|
|
|
{
|
|
|
|
|
|
x = minX;
|
|
|
|
|
|
y = minY + cy - cx * dy / dx;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
x = maxX;
|
|
|
|
|
|
y = minY + cy + cx * dy / dx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (y < minY || y > maxY)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dy < 0d)
|
|
|
|
|
|
{
|
|
|
|
|
|
x = minX + cx - cy * dx / dy;
|
|
|
|
|
|
y = minY;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
x = minX + cx + cy * dx / dy;
|
|
|
|
|
|
y = maxY;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
position = new Point(x, y);
|
|
|
|
|
|
onBorder = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
element.SetValue(OnBorderProperty, onBorder);
|
|
|
|
|
|
|
|
|
|
|
|
base.SetViewPosition(element, ref position);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|