2025-02-27 18:46:32 +01:00
|
|
|
|
using System;
|
2021-07-05 00:04:07 +02:00
|
|
|
|
using System.Globalization;
|
2024-05-22 11:25:32 +02:00
|
|
|
|
#if WPF
|
|
|
|
|
|
using System.Windows;
|
|
|
|
|
|
using System.Windows.Controls;
|
2024-05-26 21:25:36 +02:00
|
|
|
|
using System.Windows.Data;
|
2024-05-22 11:25:32 +02:00
|
|
|
|
using System.Windows.Media;
|
|
|
|
|
|
using System.Windows.Shapes;
|
2021-11-17 23:17:11 +01:00
|
|
|
|
#elif UWP
|
2017-08-23 23:33:27 +02:00
|
|
|
|
using Windows.Foundation;
|
|
|
|
|
|
using Windows.UI.Xaml;
|
2024-05-26 21:25:36 +02:00
|
|
|
|
using Windows.UI.Xaml.Data;
|
2017-08-23 23:33:27 +02:00
|
|
|
|
using Windows.UI.Xaml.Controls;
|
|
|
|
|
|
using Windows.UI.Xaml.Media;
|
|
|
|
|
|
using Windows.UI.Xaml.Shapes;
|
2024-05-22 11:25:32 +02:00
|
|
|
|
#elif WINUI
|
|
|
|
|
|
using Windows.Foundation;
|
|
|
|
|
|
using Microsoft.UI.Xaml;
|
|
|
|
|
|
using Microsoft.UI.Xaml.Controls;
|
2024-05-26 21:25:36 +02:00
|
|
|
|
using Microsoft.UI.Xaml.Data;
|
2024-05-22 11:25:32 +02:00
|
|
|
|
using Microsoft.UI.Xaml.Media;
|
|
|
|
|
|
using Microsoft.UI.Xaml.Shapes;
|
2024-08-30 16:37:40 +02:00
|
|
|
|
#elif AVALONIA
|
2025-08-19 19:43:02 +02:00
|
|
|
|
using Avalonia;
|
|
|
|
|
|
using Avalonia.Controls;
|
2024-08-30 16:37:40 +02:00
|
|
|
|
using Avalonia.Controls.Shapes;
|
2025-08-19 19:43:02 +02:00
|
|
|
|
using Avalonia.Data;
|
|
|
|
|
|
using Avalonia.Layout;
|
|
|
|
|
|
using PointCollection = System.Collections.Generic.List<Avalonia.Point>;
|
2017-08-23 23:33:27 +02:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
namespace MapControl
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Draws a map scale overlay.
|
|
|
|
|
|
/// </summary>
|
2025-09-15 17:46:31 +02:00
|
|
|
|
public partial class MapScale : MapPanel
|
2017-08-23 23:33:27 +02:00
|
|
|
|
{
|
2024-05-23 18:08:14 +02:00
|
|
|
|
public static readonly DependencyProperty PaddingProperty =
|
|
|
|
|
|
DependencyPropertyHelper.Register<MapScale, Thickness>(nameof(Padding), new Thickness(4));
|
2017-08-23 23:33:27 +02:00
|
|
|
|
|
2024-05-26 15:55:36 +02:00
|
|
|
|
public static readonly DependencyProperty StrokeThicknessProperty =
|
|
|
|
|
|
DependencyPropertyHelper.Register<MapScale, double>(nameof(StrokeThickness), 1d);
|
|
|
|
|
|
|
|
|
|
|
|
public Thickness Padding
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (Thickness)GetValue(PaddingProperty);
|
|
|
|
|
|
set => SetValue(PaddingProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public double StrokeThickness
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (double)GetValue(StrokeThicknessProperty);
|
|
|
|
|
|
set => SetValue(StrokeThicknessProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-01 12:45:19 +02:00
|
|
|
|
private readonly Polyline line = new Polyline();
|
|
|
|
|
|
|
|
|
|
|
|
private readonly TextBlock label = new TextBlock
|
|
|
|
|
|
{
|
2024-05-26 15:55:36 +02:00
|
|
|
|
HorizontalAlignment = HorizontalAlignment.Center,
|
|
|
|
|
|
VerticalAlignment = VerticalAlignment.Center
|
2018-05-01 12:45:19 +02:00
|
|
|
|
};
|
2017-08-23 23:33:27 +02:00
|
|
|
|
|
|
|
|
|
|
public MapScale()
|
|
|
|
|
|
{
|
|
|
|
|
|
MinWidth = 100d;
|
2021-12-01 20:39:42 +01:00
|
|
|
|
Children.Add(line);
|
|
|
|
|
|
Children.Add(label);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void SetParentMap(MapBase map)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.SetParentMap(map);
|
2018-05-01 02:06:22 +02:00
|
|
|
|
|
2024-05-26 21:25:36 +02:00
|
|
|
|
line.SetBinding(Shape.StrokeThicknessProperty,
|
|
|
|
|
|
new Binding { Source = this, Path = new PropertyPath(nameof(StrokeThickness)) });
|
2024-05-27 11:05:22 +02:00
|
|
|
|
|
2025-06-06 11:39:26 +02:00
|
|
|
|
line.SetBinding(Shape.StrokeProperty,
|
|
|
|
|
|
new Binding { Source = map, Path = new PropertyPath(nameof(MapBase.Foreground)) });
|
|
|
|
|
|
|
2024-05-22 11:25:32 +02:00
|
|
|
|
#if UWP || WINUI
|
2024-05-26 21:25:36 +02:00
|
|
|
|
label.SetBinding(TextBlock.ForegroundProperty,
|
|
|
|
|
|
new Binding { Source = map, Path = new PropertyPath(nameof(MapBase.Foreground)) });
|
2018-08-14 23:56:15 +02:00
|
|
|
|
#endif
|
2017-08-23 23:33:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override Size MeasureOverride(Size availableSize)
|
|
|
|
|
|
{
|
2022-11-19 17:54:37 +01:00
|
|
|
|
double scale;
|
2017-08-23 23:33:27 +02:00
|
|
|
|
|
2024-05-24 18:24:44 +02:00
|
|
|
|
if (ParentMap == null || (scale = ParentMap.GetScale(ParentMap.Center).X) <= 0d)
|
2017-08-23 23:33:27 +02:00
|
|
|
|
{
|
2024-05-24 18:24:44 +02:00
|
|
|
|
return new Size();
|
|
|
|
|
|
}
|
2017-08-23 23:33:27 +02:00
|
|
|
|
|
2024-05-24 18:24:44 +02:00
|
|
|
|
var length = MinWidth / scale;
|
|
|
|
|
|
var magnitude = Math.Pow(10d, Math.Floor(Math.Log10(length)));
|
2017-08-23 23:33:27 +02:00
|
|
|
|
|
2024-05-24 18:24:44 +02:00
|
|
|
|
length = length / magnitude < 2d ? 2d * magnitude
|
|
|
|
|
|
: length / magnitude < 5d ? 5d * magnitude
|
|
|
|
|
|
: 10d * magnitude;
|
2017-08-23 23:33:27 +02:00
|
|
|
|
|
2024-05-24 18:24:44 +02:00
|
|
|
|
var size = new Size(
|
|
|
|
|
|
length * scale + StrokeThickness + Padding.Left + Padding.Right,
|
2024-05-26 15:55:36 +02:00
|
|
|
|
1.5 * label.FontSize + 2 * StrokeThickness + Padding.Top + Padding.Bottom);
|
2017-08-23 23:33:27 +02:00
|
|
|
|
|
2024-05-24 18:24:44 +02:00
|
|
|
|
var x1 = Padding.Left + StrokeThickness / 2d;
|
|
|
|
|
|
var x2 = size.Width - Padding.Right - StrokeThickness / 2d;
|
|
|
|
|
|
var y1 = size.Height / 2d;
|
|
|
|
|
|
var y2 = size.Height - Padding.Bottom - StrokeThickness / 2d;
|
|
|
|
|
|
|
|
|
|
|
|
line.Points = new PointCollection
|
2024-05-26 15:55:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
new Point(x1, y1),
|
|
|
|
|
|
new Point(x1, y2),
|
|
|
|
|
|
new Point(x2, y2),
|
|
|
|
|
|
new Point(x2, y1)
|
|
|
|
|
|
};
|
2024-05-24 18:24:44 +02:00
|
|
|
|
|
|
|
|
|
|
label.Text = length >= 1000d
|
|
|
|
|
|
? string.Format(CultureInfo.InvariantCulture, "{0:F0} km", length / 1000d)
|
|
|
|
|
|
: string.Format(CultureInfo.InvariantCulture, "{0:F0} m", length);
|
2024-05-26 15:55:36 +02:00
|
|
|
|
|
|
|
|
|
|
line.Measure(size);
|
2024-05-24 18:24:44 +02:00
|
|
|
|
label.Measure(size);
|
2017-08-23 23:33:27 +02:00
|
|
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnViewportChanged(ViewportChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
InvalidateMeasure();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|