mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Version 2.0:
- Support for Windows Phone 8.1 by making MapControl.WinRT a portable library - Unified TileContainer and MapOverlay implementations across platforms
This commit is contained in:
parent
ed140c6d01
commit
10527c3f0d
|
|
@ -3,13 +3,12 @@ using System.Runtime.InteropServices;
|
|||
|
||||
[assembly: AssemblyTitle("FileDbCache")]
|
||||
[assembly: AssemblyDescription("ObjectCache implementation based on EzTools FileDb")]
|
||||
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("1.12.1")]
|
||||
[assembly: AssemblyFileVersion("1.12.1")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ using System.Runtime.InteropServices;
|
|||
|
||||
[assembly: AssemblyTitle("ImageFileCache")]
|
||||
[assembly: AssemblyDescription("ObjectCache implementation based on local image files")]
|
||||
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("1.12.1")]
|
||||
[assembly: AssemblyFileVersion("1.12.1")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl.WinRT", "MapCont
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfApplication", "SampleApps\WpfApplication\WpfApplication.csproj", "{9949326E-9261-4F95-89B1-151F60498951}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhoneApplication", "SampleApps\PhoneApplication\PhoneApplication.csproj", "{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -65,6 +67,12 @@ Global
|
|||
{9949326E-9261-4F95-89B1-151F60498951}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9949326E-9261-4F95-89B1-151F60498951}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9949326E-9261-4F95-89B1-151F60498951}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows.Media;
|
||||
|
|
@ -11,12 +11,17 @@ using System.Windows.Media;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
public static class MatrixEx
|
||||
internal static partial class Extensions
|
||||
{
|
||||
public static void Freeze(this object freezable)
|
||||
{
|
||||
}
|
||||
|
||||
public static Matrix Translate(this Matrix matrix, double offsetX, double offsetY)
|
||||
{
|
||||
matrix.OffsetX += offsetX;
|
||||
matrix.OffsetY += offsetY;
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
|
@ -30,6 +35,7 @@ namespace MapControl
|
|||
angle = (angle % 360d) / 180d * Math.PI;
|
||||
var cos = Math.Cos(angle);
|
||||
var sin = Math.Sin(angle);
|
||||
|
||||
return Multiply(matrix, new Matrix(cos, sin, -sin, cos, 0d, 0d));
|
||||
}
|
||||
|
||||
|
|
@ -40,12 +46,14 @@ namespace MapControl
|
|||
var sin = Math.Sin(angle);
|
||||
var offsetX = centerX * (1d - cos) + centerY * sin;
|
||||
var offsetY = centerY * (1d - cos) - centerX * sin;
|
||||
|
||||
return Multiply(matrix, new Matrix(cos, sin, -sin, cos, offsetX, offsetY));
|
||||
}
|
||||
|
||||
public static Matrix Invert(this Matrix matrix)
|
||||
{
|
||||
var determinant = matrix.M11 * matrix.M22 - matrix.M12 * matrix.M21;
|
||||
|
||||
return new Matrix(
|
||||
matrix.M22 / determinant, -matrix.M12 / determinant,
|
||||
-matrix.M21 / determinant, matrix.M11 / determinant,
|
||||
|
|
@ -7,7 +7,7 @@ using System.Windows.Media.Animation;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
public static class AnimationEx
|
||||
internal static partial class Extensions
|
||||
{
|
||||
public static void BeginAnimation(this DependencyObject obj, DependencyProperty property, Timeline animation)
|
||||
{
|
||||
|
|
@ -2,13 +2,20 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public static class AnimationEx
|
||||
internal static partial class Extensions
|
||||
{
|
||||
public static Point Transform(this GeneralTransform transform, Point point)
|
||||
{
|
||||
return transform.TransformPoint(point);
|
||||
}
|
||||
|
||||
public static void BeginAnimation(this DependencyObject obj, DependencyProperty property, DoubleAnimation animation)
|
||||
{
|
||||
animation.EnableDependentAnimation = true;
|
||||
|
|
@ -13,7 +13,7 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public static class GlyphRunText
|
||||
{
|
||||
public static GlyphRun Create(string text, Typeface typeface, double emSize, Point baselineOrigin)
|
||||
public static GlyphRun Create(string text, Typeface typeface, double emSize, Point baselineOrigin = new Point())
|
||||
{
|
||||
GlyphTypeface glyphTypeface;
|
||||
|
||||
|
|
@ -32,36 +32,42 @@ namespace MapControl
|
|||
advanceWidths[i] = glyphTypeface.AdvanceWidths[glyphIndex] * emSize;
|
||||
}
|
||||
|
||||
return new GlyphRun(glyphTypeface, 0, false, emSize, glyphIndices, baselineOrigin, advanceWidths,
|
||||
null, null, null, null, null, null);
|
||||
return new GlyphRun(glyphTypeface, 0, false, emSize, glyphIndices, baselineOrigin, advanceWidths, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static GlyphRun Create(string text, Typeface typeface, double emSize, Vector centerOffset)
|
||||
public static void DrawGlyphRun(this DrawingContext drawingContext, Brush foreground, GlyphRun glyphRun,
|
||||
Point position, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment)
|
||||
{
|
||||
GlyphTypeface glyphTypeface;
|
||||
|
||||
if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
|
||||
{
|
||||
throw new ArgumentException(string.Format("{0}: no GlyphTypeface found", typeface.FontFamily));
|
||||
}
|
||||
|
||||
var glyphIndices = new ushort[text.Length];
|
||||
var advanceWidths = new double[text.Length];
|
||||
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
var glyphIndex = glyphTypeface.CharacterToGlyphMap[text[i]];
|
||||
glyphIndices[i] = glyphIndex;
|
||||
advanceWidths[i] = glyphTypeface.AdvanceWidths[glyphIndex] * emSize;
|
||||
}
|
||||
|
||||
var glyphRun = new GlyphRun(glyphTypeface, 0, false, emSize, glyphIndices, new Point(), advanceWidths,
|
||||
null, null, null, null, null, null);
|
||||
var bbox = glyphRun.ComputeInkBoundingBox();
|
||||
var baselineOrigin = new Point(centerOffset.X - bbox.X - bbox.Width / 2d, centerOffset.Y - bbox.Y - bbox.Height / 2d);
|
||||
var transform = new TranslateTransform(position.X - bbox.X, position.Y - bbox.Y);
|
||||
|
||||
return new GlyphRun(glyphTypeface, 0, false, emSize, glyphIndices, baselineOrigin, advanceWidths,
|
||||
null, null, null, null, null, null);
|
||||
switch (horizontalAlignment)
|
||||
{
|
||||
case HorizontalAlignment.Center:
|
||||
transform.X -= bbox.Width / 2d;
|
||||
break;
|
||||
case HorizontalAlignment.Right:
|
||||
transform.X -= bbox.Width;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (verticalAlignment)
|
||||
{
|
||||
case VerticalAlignment.Center:
|
||||
transform.Y -= bbox.Height / 2d;
|
||||
break;
|
||||
case VerticalAlignment.Bottom:
|
||||
transform.Y -= bbox.Height;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
drawingContext.PushTransform(transform);
|
||||
drawingContext.DrawGlyphRun(foreground, glyphRun);
|
||||
drawingContext.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,8 @@
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapImage
|
||||
public interface IMapElement
|
||||
{
|
||||
static MapImage()
|
||||
{
|
||||
imageTransform.Freeze();
|
||||
}
|
||||
MapBase ParentMap { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
|
|
@ -13,13 +13,11 @@ using System.Windows.Media.Imaging;
|
|||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the image of a map tile. ImageTileSource bypasses downloading and
|
||||
/// optional caching in TileImageLoader. By overriding the LoadImage method,
|
||||
/// Provides the image of a map tile. ImageTileSource bypasses image
|
||||
/// downloading in TileImageLoader. By overriding the LoadImage method,
|
||||
/// an application can provide tile images from an arbitrary source.
|
||||
/// WPF only: If the CanLoadAsync property is true, LoadImage will be called
|
||||
/// from a separate, non-UI thread and must hence return a frozen ImageSource.
|
||||
/// </summary>
|
||||
public partial class ImageTileSource : TileSource
|
||||
public class ImageTileSource : TileSource
|
||||
{
|
||||
public virtual ImageSource LoadImage(int x, int y, int zoomLevel)
|
||||
{
|
||||
|
|
@ -2,13 +2,52 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class ImageTileSource
|
||||
/// <summary>
|
||||
/// Provides the image of a map tile. ImageTileSource bypasses image downloading
|
||||
/// and optional caching in TileImageLoader. By overriding the LoadImage method,
|
||||
/// an application can provide tile images from an arbitrary source.
|
||||
/// If the IsAsync property is true, LoadImage will be called from a separate,
|
||||
/// non-UI thread and must therefore return a frozen ImageSource.
|
||||
/// </summary>
|
||||
public class ImageTileSource : TileSource
|
||||
{
|
||||
public virtual bool CanLoadAsync
|
||||
public bool IsAsync { get; set; }
|
||||
|
||||
public virtual ImageSource LoadImage(int x, int y, int zoomLevel)
|
||||
{
|
||||
get { return false; }
|
||||
ImageSource image = null;
|
||||
|
||||
var uri = GetUri(x, y, zoomLevel);
|
||||
|
||||
if (uri != null)
|
||||
{
|
||||
if (IsAsync)
|
||||
{
|
||||
var buffer = new WebClient().DownloadData(uri);
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
using (var stream = new MemoryStream(buffer))
|
||||
{
|
||||
image = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
image.Freeze();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
image = BitmapFrame.Create(uri);
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,6 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// A geographic location with latitude and longitude values in degrees.
|
||||
/// </summary>
|
||||
#if !SILVERLIGHT && !NETFX_CORE
|
||||
[Serializable]
|
||||
#endif
|
||||
public partial class Location
|
||||
{
|
||||
private double latitude;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ namespace MapControl
|
|||
}
|
||||
|
||||
[TypeConverter(typeof(LocationConverter))]
|
||||
#if !SILVERLIGHT
|
||||
[Serializable]
|
||||
#endif
|
||||
public partial class Location
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace MapControl
|
|||
|
||||
public Map()
|
||||
{
|
||||
ManipulationMode = ManipulationModes.Scale | ManipulationModes.ScaleInertia |
|
||||
ManipulationMode = ManipulationModes.Scale |
|
||||
ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.TranslateInertia;
|
||||
|
||||
ManipulationDelta += OnManipulationDelta;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Xaml;
|
||||
|
|
@ -47,7 +47,6 @@ namespace MapControl
|
|||
{
|
||||
Background = new SolidColorBrush(Colors.Transparent);
|
||||
Clip = new RectangleGeometry();
|
||||
Children.Add(tileContainer);
|
||||
|
||||
SizeChanged += OnRenderSizeChanged;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,31 +52,11 @@ namespace MapControl
|
|||
typeof(MapBase), new FrameworkPropertyMetadata(Brushes.Transparent));
|
||||
}
|
||||
|
||||
partial void Initialize()
|
||||
{
|
||||
AddVisualChild(tileContainer);
|
||||
}
|
||||
|
||||
partial void RemoveAnimation(DependencyProperty property)
|
||||
{
|
||||
BeginAnimation(property, null);
|
||||
}
|
||||
|
||||
protected override int VisualChildrenCount
|
||||
{
|
||||
get { return base.VisualChildrenCount + 1; }
|
||||
}
|
||||
|
||||
protected override Visual GetVisualChild(int index)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
return tileContainer;
|
||||
}
|
||||
|
||||
return base.GetVisualChild(index - 1);
|
||||
}
|
||||
|
||||
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
|
||||
{
|
||||
base.OnRenderSizeChanged(sizeInfo);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
|
@ -74,6 +74,7 @@ namespace MapControl
|
|||
SetParentMap();
|
||||
|
||||
TileLayers = new TileLayerCollection();
|
||||
InternalChildren.Add(tileContainer);
|
||||
Initialize();
|
||||
|
||||
Loaded += OnLoaded;
|
||||
|
|
|
|||
|
|
@ -67,8 +67,12 @@
|
|||
<Reference Include="System.Net" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AnimationEx.Silverlight.cs" />
|
||||
<Compile Include="ImageTileSource.cs" />
|
||||
<Compile Include="Extensions.Silverlight.cs" />
|
||||
<Compile Include="Extensions.Silverlight.WinRT.cs" />
|
||||
<Compile Include="ImageTileSource.Silverlight.WinRT.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="IMapElement.cs" />
|
||||
<Compile Include="Int32Rect.cs" />
|
||||
<Compile Include="Location.cs" />
|
||||
<Compile Include="LocationCollection.cs" />
|
||||
|
|
@ -84,6 +88,8 @@
|
|||
<Compile Include="MapImageLayer.Silverlight.WinRT.cs" />
|
||||
<Compile Include="MapItem.Silverlight.WinRT.cs" />
|
||||
<Compile Include="MapItemsControl.Silverlight.WinRT.cs" />
|
||||
<Compile Include="MapOverlay.cs" />
|
||||
<Compile Include="MapOverlay.Silverlight.WinRT.cs" />
|
||||
<Compile Include="MapPanel.cs" />
|
||||
<Compile Include="MapPanel.Silverlight.WinRT.cs" />
|
||||
<Compile Include="MapPath.cs" />
|
||||
|
|
@ -92,8 +98,8 @@
|
|||
<Compile Include="MapPolyline.Silverlight.WinRT.cs" />
|
||||
<Compile Include="MapRectangle.cs" />
|
||||
<Compile Include="MapTransform.cs" />
|
||||
<Compile Include="MatrixEx.cs" />
|
||||
<Compile Include="MercatorTransform.cs" />
|
||||
<Compile Include="PanelBase.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Pushpin.Silverlight.WinRT.cs" />
|
||||
<Compile Include="Tile.cs" />
|
||||
|
|
@ -102,7 +108,6 @@
|
|||
<Compile Include="TileContainer.Silverlight.WinRT.cs" />
|
||||
<Compile Include="TileImageLoader.Silverlight.WinRT.cs" />
|
||||
<Compile Include="TileLayer.cs" />
|
||||
<Compile Include="TileLayer.Silverlight.WinRT.cs" />
|
||||
<Compile Include="TileLayerCollection.cs" />
|
||||
<Compile Include="TileSource.cs" />
|
||||
<Compile Include="TileSourceConverter.cs" />
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="GlyphRunText.cs" />
|
||||
<Compile Include="ImageTileSource.cs" />
|
||||
<Compile Include="ImageTileSource.WPF.cs" />
|
||||
<Compile Include="IMapElement.cs" />
|
||||
<Compile Include="Location.cs" />
|
||||
<Compile Include="LocationCollection.cs" />
|
||||
<Compile Include="LocationCollectionConverter.cs" />
|
||||
|
|
@ -64,20 +64,20 @@
|
|||
<Compile Include="MapGraticule.cs" />
|
||||
<Compile Include="MapGraticule.WPF.cs" />
|
||||
<Compile Include="MapImage.cs" />
|
||||
<Compile Include="MapImage.WPF.cs" />
|
||||
<Compile Include="MapImageLayer.cs" />
|
||||
<Compile Include="MapImageLayer.WPF.cs" />
|
||||
<Compile Include="MapItem.WPF.cs" />
|
||||
<Compile Include="MapItemsControl.WPF.cs" />
|
||||
<Compile Include="MapOverlay.cs" />
|
||||
<Compile Include="MapOverlay.WPF.cs" />
|
||||
<Compile Include="MapPanel.cs" />
|
||||
<Compile Include="MapPanel.WPF.cs" />
|
||||
<Compile Include="PanelBase.cs" />
|
||||
<Compile Include="MapPath.cs" />
|
||||
<Compile Include="MapPath.WPF.cs" />
|
||||
<Compile Include="MapPolyline.cs" />
|
||||
<Compile Include="MapPolyline.WPF.cs" />
|
||||
<Compile Include="MapRectangle.cs" />
|
||||
<Compile Include="MapRectangle.WPF.cs" />
|
||||
<Compile Include="MapScale.cs" />
|
||||
<Compile Include="MapTransform.cs" />
|
||||
<Compile Include="MercatorTransform.cs" />
|
||||
|
|
@ -89,7 +89,6 @@
|
|||
<Compile Include="TileContainer.WPF.cs" />
|
||||
<Compile Include="TileImageLoader.WPF.cs" />
|
||||
<Compile Include="TileLayer.cs" />
|
||||
<Compile Include="TileLayer.WPF.cs" />
|
||||
<Compile Include="TileLayerCollection.cs" />
|
||||
<Compile Include="TileSource.cs" />
|
||||
<Compile Include="TileSourceConverter.cs" />
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Text;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
|
@ -23,40 +22,8 @@ using System.Windows.Data;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapGraticule : MapPanel
|
||||
public partial class MapGraticule
|
||||
{
|
||||
public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register(
|
||||
"FontFamily", typeof(FontFamily), typeof(MapGraticule),
|
||||
new PropertyMetadata(default(FontFamily), (o, e) => ((MapGraticule)o).OnViewportChanged()));
|
||||
|
||||
public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
|
||||
"FontSize", typeof(double), typeof(MapGraticule),
|
||||
new PropertyMetadata(10d, (o, e) => ((MapGraticule)o).OnViewportChanged()));
|
||||
|
||||
public static readonly DependencyProperty FontStyleProperty = DependencyProperty.Register(
|
||||
"FontStyle", typeof(FontStyle), typeof(MapGraticule),
|
||||
new PropertyMetadata(default(FontStyle), (o, e) => ((MapGraticule)o).OnViewportChanged()));
|
||||
|
||||
public static readonly DependencyProperty FontStretchProperty = DependencyProperty.Register(
|
||||
"FontStretch", typeof(FontStretch), typeof(MapGraticule),
|
||||
new PropertyMetadata(default(FontStretch), (o, e) => ((MapGraticule)o).OnViewportChanged()));
|
||||
|
||||
public static readonly DependencyProperty FontWeightProperty = DependencyProperty.Register(
|
||||
"FontWeight", typeof(FontWeight), typeof(MapGraticule),
|
||||
new PropertyMetadata(FontWeights.Normal, (o, e) => ((MapGraticule)o).OnViewportChanged()));
|
||||
|
||||
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
|
||||
"Foreground", typeof(Brush), typeof(MapGraticule),
|
||||
new PropertyMetadata(null, (o, e) => ((MapGraticule)o).OnViewportChanged()));
|
||||
|
||||
public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
|
||||
"Stroke", typeof(Brush), typeof(MapGraticule),
|
||||
new PropertyMetadata(null, (o, e) => ((MapGraticule)o).path.Stroke = (Brush)e.NewValue));
|
||||
|
||||
public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
|
||||
"StrokeThickness", typeof(double), typeof(MapGraticule),
|
||||
new PropertyMetadata(0.5, (o, e) => ((MapGraticule)o).path.StrokeThickness = (double)e.NewValue));
|
||||
|
||||
private readonly Path path;
|
||||
private Location graticuleStart;
|
||||
private Location graticuleEnd;
|
||||
|
|
@ -64,247 +31,181 @@ namespace MapControl
|
|||
public MapGraticule()
|
||||
{
|
||||
IsHitTestVisible = false;
|
||||
StrokeThickness = 0.5;
|
||||
|
||||
path = new Path
|
||||
{
|
||||
Stroke = Stroke,
|
||||
StrokeThickness = StrokeThickness
|
||||
Data = new PathGeometry()
|
||||
};
|
||||
|
||||
path.SetBinding(Shape.StrokeProperty, new Binding
|
||||
{
|
||||
Source = this,
|
||||
Path = new PropertyPath("Stroke")
|
||||
});
|
||||
|
||||
path.SetBinding(Shape.StrokeThicknessProperty, new Binding
|
||||
{
|
||||
Source = this,
|
||||
Path = new PropertyPath("StrokeThickness")
|
||||
});
|
||||
|
||||
Children.Add(path);
|
||||
}
|
||||
|
||||
public FontFamily FontFamily
|
||||
{
|
||||
get { return (FontFamily)GetValue(FontFamilyProperty); }
|
||||
set { SetValue(FontFamilyProperty, value); }
|
||||
}
|
||||
|
||||
public double FontSize
|
||||
{
|
||||
get { return (double)GetValue(FontSizeProperty); }
|
||||
set { SetValue(FontSizeProperty, value); }
|
||||
}
|
||||
|
||||
public FontStyle FontStyle
|
||||
{
|
||||
get { return (FontStyle)GetValue(FontStyleProperty); }
|
||||
set { SetValue(FontStyleProperty, value); }
|
||||
}
|
||||
|
||||
public FontStretch FontStretch
|
||||
{
|
||||
get { return (FontStretch)GetValue(FontStretchProperty); }
|
||||
set { SetValue(FontStretchProperty, value); }
|
||||
}
|
||||
|
||||
public FontWeight FontWeight
|
||||
{
|
||||
get { return (FontWeight)GetValue(FontWeightProperty); }
|
||||
set { SetValue(FontWeightProperty, value); }
|
||||
}
|
||||
|
||||
public Brush Foreground
|
||||
{
|
||||
get { return (Brush)GetValue(ForegroundProperty); }
|
||||
set { SetValue(ForegroundProperty, value); }
|
||||
}
|
||||
|
||||
public Brush Stroke
|
||||
{
|
||||
get { return (Brush)GetValue(StrokeProperty); }
|
||||
set { SetValue(StrokeProperty, value); }
|
||||
}
|
||||
|
||||
public double StrokeThickness
|
||||
{
|
||||
get { return (double)GetValue(StrokeThicknessProperty); }
|
||||
set { SetValue(StrokeThicknessProperty, value); }
|
||||
}
|
||||
|
||||
protected override void OnViewportChanged()
|
||||
{
|
||||
if (ParentMap != null)
|
||||
var geometry = (PathGeometry)path.Data;
|
||||
var bounds = ParentMap.ViewportTransform.Inverse.TransformBounds(new Rect(new Point(), ParentMap.RenderSize));
|
||||
var start = ParentMap.MapTransform.Transform(new Point(bounds.X, bounds.Y));
|
||||
var end = ParentMap.MapTransform.Transform(new Point(bounds.X + bounds.Width, bounds.Y + bounds.Height));
|
||||
var minSpacing = MinLineSpacing * 360d / (Math.Pow(2d, ParentMap.ZoomLevel) * 256d);
|
||||
var spacing = LineSpacings[LineSpacings.Length - 1];
|
||||
|
||||
if (spacing >= minSpacing)
|
||||
{
|
||||
if (path.Data == null)
|
||||
spacing = LineSpacings.FirstOrDefault(s => s >= minSpacing);
|
||||
}
|
||||
|
||||
var labelStart = new Location(
|
||||
Math.Ceiling(start.Latitude / spacing) * spacing,
|
||||
Math.Ceiling(start.Longitude / spacing) * spacing);
|
||||
|
||||
var labelEnd = new Location(
|
||||
Math.Floor(end.Latitude / spacing) * spacing,
|
||||
Math.Floor(end.Longitude / spacing) * spacing);
|
||||
|
||||
var lineStart = new Location(
|
||||
Math.Min(Math.Max(labelStart.Latitude - spacing, -ParentMap.MapTransform.MaxLatitude), ParentMap.MapTransform.MaxLatitude),
|
||||
labelStart.Longitude - spacing);
|
||||
|
||||
var lineEnd = new Location(
|
||||
Math.Min(Math.Max(labelEnd.Latitude + spacing, -ParentMap.MapTransform.MaxLatitude), ParentMap.MapTransform.MaxLatitude),
|
||||
labelEnd.Longitude + spacing);
|
||||
|
||||
if (!lineStart.Equals(graticuleStart) || !lineEnd.Equals(graticuleEnd))
|
||||
{
|
||||
graticuleStart = lineStart;
|
||||
graticuleEnd = lineEnd;
|
||||
|
||||
geometry.Figures.Clear();
|
||||
geometry.Transform = ParentMap.ViewportTransform;
|
||||
|
||||
var latLocations = new List<Location>((int)((end.Latitude - labelStart.Latitude) / spacing) + 1);
|
||||
|
||||
for (var lat = labelStart.Latitude; lat <= end.Latitude; lat += spacing)
|
||||
{
|
||||
path.Data = new PathGeometry();
|
||||
var location = new Location(lat, lineStart.Longitude);
|
||||
latLocations.Add(location);
|
||||
|
||||
if (Foreground == null)
|
||||
var figure = new PathFigure
|
||||
{
|
||||
SetBinding(ForegroundProperty, new Binding()
|
||||
{
|
||||
Source = ParentMap,
|
||||
Path = new PropertyPath("Foreground")
|
||||
});
|
||||
}
|
||||
StartPoint = ParentMap.MapTransform.Transform(location),
|
||||
IsClosed = false,
|
||||
IsFilled = false
|
||||
};
|
||||
|
||||
if (Stroke == null)
|
||||
location.Longitude = lineEnd.Longitude;
|
||||
|
||||
figure.Segments.Add(new LineSegment
|
||||
{
|
||||
SetBinding(StrokeProperty, new Binding()
|
||||
{
|
||||
Source = ParentMap,
|
||||
Path = new PropertyPath("Foreground")
|
||||
});
|
||||
}
|
||||
Point = ParentMap.MapTransform.Transform(location),
|
||||
});
|
||||
|
||||
geometry.Figures.Add(figure);
|
||||
}
|
||||
|
||||
var geometry = (PathGeometry)path.Data;
|
||||
var bounds = ParentMap.ViewportTransform.Inverse.TransformBounds(new Rect(new Point(), ParentMap.RenderSize));
|
||||
var start = ParentMap.MapTransform.Transform(new Point(bounds.X, bounds.Y));
|
||||
var end = ParentMap.MapTransform.Transform(new Point(bounds.X + bounds.Width, bounds.Y + bounds.Height));
|
||||
var minSpacing = MinLineSpacing * 360d / (Math.Pow(2d, ParentMap.ZoomLevel) * 256d);
|
||||
var spacing = LineSpacings[LineSpacings.Length - 1];
|
||||
|
||||
if (spacing >= minSpacing)
|
||||
for (var lon = labelStart.Longitude; lon <= end.Longitude; lon += spacing)
|
||||
{
|
||||
spacing = LineSpacings.FirstOrDefault(s => s >= minSpacing);
|
||||
var figure = new PathFigure
|
||||
{
|
||||
StartPoint = ParentMap.MapTransform.Transform(new Location(lineStart.Latitude, lon)),
|
||||
IsClosed = false,
|
||||
IsFilled = false
|
||||
};
|
||||
|
||||
figure.Segments.Add(new LineSegment
|
||||
{
|
||||
Point = ParentMap.MapTransform.Transform(new Location(lineEnd.Latitude, lon)),
|
||||
});
|
||||
|
||||
geometry.Figures.Add(figure);
|
||||
}
|
||||
|
||||
var labelStart = new Location(
|
||||
Math.Ceiling(start.Latitude / spacing) * spacing,
|
||||
Math.Ceiling(start.Longitude / spacing) * spacing);
|
||||
var childIndex = 1; // 0 for Path
|
||||
var format = spacing < 1d ? "{0} {1}°{2:00}'" : "{0} {1}°";
|
||||
var measureSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
|
||||
|
||||
var labelEnd = new Location(
|
||||
Math.Floor(end.Latitude / spacing) * spacing,
|
||||
Math.Floor(end.Longitude / spacing) * spacing);
|
||||
|
||||
var lineStart = new Location(
|
||||
Math.Min(Math.Max(labelStart.Latitude - spacing, -ParentMap.MapTransform.MaxLatitude), ParentMap.MapTransform.MaxLatitude),
|
||||
labelStart.Longitude - spacing);
|
||||
|
||||
var lineEnd = new Location(
|
||||
Math.Min(Math.Max(labelEnd.Latitude + spacing, -ParentMap.MapTransform.MaxLatitude), ParentMap.MapTransform.MaxLatitude),
|
||||
labelEnd.Longitude + spacing);
|
||||
|
||||
if (!lineStart.Equals(graticuleStart) || !lineEnd.Equals(graticuleEnd))
|
||||
foreach (var location in latLocations)
|
||||
{
|
||||
graticuleStart = lineStart;
|
||||
graticuleEnd = lineEnd;
|
||||
|
||||
geometry.Figures.Clear();
|
||||
geometry.Transform = ParentMap.ViewportTransform;
|
||||
|
||||
var latLocations = new List<Location>((int)((end.Latitude - labelStart.Latitude) / spacing) + 1);
|
||||
|
||||
for (var lat = labelStart.Latitude; lat <= end.Latitude; lat += spacing)
|
||||
{
|
||||
var location = new Location(lat, lineStart.Longitude);
|
||||
latLocations.Add(location);
|
||||
|
||||
var figure = new PathFigure
|
||||
{
|
||||
StartPoint = ParentMap.MapTransform.Transform(location),
|
||||
IsClosed = false,
|
||||
IsFilled = false
|
||||
};
|
||||
|
||||
location.Longitude = lineEnd.Longitude;
|
||||
|
||||
figure.Segments.Add(new LineSegment
|
||||
{
|
||||
Point = ParentMap.MapTransform.Transform(location),
|
||||
});
|
||||
|
||||
geometry.Figures.Add(figure);
|
||||
}
|
||||
|
||||
for (var lon = labelStart.Longitude; lon <= end.Longitude; lon += spacing)
|
||||
{
|
||||
var figure = new PathFigure
|
||||
location.Longitude = lon;
|
||||
|
||||
TextBlock label;
|
||||
|
||||
if (childIndex < Children.Count)
|
||||
{
|
||||
StartPoint = ParentMap.MapTransform.Transform(new Location(lineStart.Latitude, lon)),
|
||||
IsClosed = false,
|
||||
IsFilled = false
|
||||
};
|
||||
|
||||
figure.Segments.Add(new LineSegment
|
||||
{
|
||||
Point = ParentMap.MapTransform.Transform(new Location(lineEnd.Latitude, lon)),
|
||||
});
|
||||
|
||||
geometry.Figures.Add(figure);
|
||||
}
|
||||
|
||||
var childIndex = 1; // 0 for Path
|
||||
var format = spacing < 1d ? "{0} {1}°{2:00}'" : "{0} {1}°";
|
||||
var measureSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
|
||||
|
||||
foreach (var location in latLocations)
|
||||
{
|
||||
for (var lon = labelStart.Longitude; lon <= end.Longitude; lon += spacing)
|
||||
{
|
||||
location.Longitude = lon;
|
||||
|
||||
TextBlock label;
|
||||
|
||||
if (childIndex < Children.Count)
|
||||
{
|
||||
label = (TextBlock)Children[childIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
label = new TextBlock
|
||||
{
|
||||
RenderTransform = new TransformGroup()
|
||||
};
|
||||
|
||||
label.SetBinding(TextBlock.ForegroundProperty, new Binding
|
||||
{
|
||||
Source = this,
|
||||
Path = new PropertyPath("Foreground")
|
||||
});
|
||||
|
||||
Children.Add(label);
|
||||
}
|
||||
|
||||
childIndex++;
|
||||
|
||||
if (FontFamily != null)
|
||||
{
|
||||
label.FontFamily = FontFamily;
|
||||
}
|
||||
|
||||
label.FontSize = FontSize;
|
||||
label.FontStyle = FontStyle;
|
||||
label.FontStretch = FontStretch;
|
||||
label.FontWeight = FontWeight;
|
||||
|
||||
label.Text = string.Format("{0}\n{1}",
|
||||
CoordinateString(location.Latitude, format, "NS"),
|
||||
CoordinateString(Location.NormalizeLongitude(location.Longitude), format, "EW"));
|
||||
|
||||
label.Measure(measureSize);
|
||||
|
||||
var transformGroup = (TransformGroup)label.RenderTransform;
|
||||
|
||||
if (transformGroup.Children.Count == 0)
|
||||
{
|
||||
transformGroup.Children.Add(new TranslateTransform());
|
||||
transformGroup.Children.Add(ParentMap.RotateTransform);
|
||||
transformGroup.Children.Add(new TranslateTransform());
|
||||
}
|
||||
|
||||
var translateTransform = (TranslateTransform)transformGroup.Children[0];
|
||||
translateTransform.X = StrokeThickness / 2d + 2d;
|
||||
translateTransform.Y = -label.DesiredSize.Height / 2d;
|
||||
|
||||
var viewportPosition = ParentMap.LocationToViewportPoint(location);
|
||||
translateTransform = (TranslateTransform)transformGroup.Children[2];
|
||||
translateTransform.X = viewportPosition.X;
|
||||
translateTransform.Y = viewportPosition.Y;
|
||||
label = (TextBlock)Children[childIndex];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label = new TextBlock
|
||||
{
|
||||
RenderTransform = new TransformGroup()
|
||||
};
|
||||
|
||||
while (Children.Count > childIndex)
|
||||
{
|
||||
Children.RemoveAt(Children.Count - 1);
|
||||
label.SetBinding(TextBlock.ForegroundProperty, new Binding
|
||||
{
|
||||
Source = this,
|
||||
Path = new PropertyPath("Foreground")
|
||||
});
|
||||
|
||||
Children.Add(label);
|
||||
}
|
||||
|
||||
childIndex++;
|
||||
|
||||
if (FontFamily != null)
|
||||
{
|
||||
label.FontFamily = FontFamily;
|
||||
}
|
||||
|
||||
label.FontSize = FontSize;
|
||||
label.FontStyle = FontStyle;
|
||||
label.FontStretch = FontStretch;
|
||||
label.FontWeight = FontWeight;
|
||||
|
||||
label.Text = string.Format("{0}\n{1}",
|
||||
CoordinateString(location.Latitude, format, "NS"),
|
||||
CoordinateString(Location.NormalizeLongitude(location.Longitude), format, "EW"));
|
||||
|
||||
label.Measure(measureSize);
|
||||
|
||||
var transformGroup = (TransformGroup)label.RenderTransform;
|
||||
|
||||
if (transformGroup.Children.Count == 0)
|
||||
{
|
||||
transformGroup.Children.Add(new TranslateTransform());
|
||||
transformGroup.Children.Add(ParentMap.RotateTransform);
|
||||
transformGroup.Children.Add(new TranslateTransform());
|
||||
}
|
||||
|
||||
var translateTransform = (TranslateTransform)transformGroup.Children[0];
|
||||
translateTransform.X = StrokeThickness / 2d + 2d;
|
||||
translateTransform.Y = -label.DesiredSize.Height / 2d;
|
||||
|
||||
var viewportPosition = ParentMap.LocationToViewportPoint(location);
|
||||
translateTransform = (TranslateTransform)transformGroup.Children[2];
|
||||
translateTransform.X = viewportPosition.X;
|
||||
translateTransform.Y = viewportPosition.Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
path.Data = null;
|
||||
|
||||
while (Children.Count > childIndex)
|
||||
{
|
||||
Children.RemoveAt(Children.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
base.OnViewportChanged();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ using System.Windows.Media;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapGraticule : MapOverlay
|
||||
public partial class MapGraticule
|
||||
{
|
||||
private class Label
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml;
|
||||
#else
|
||||
using System.Windows;
|
||||
|
|
@ -13,7 +13,7 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Draws a graticule overlay.
|
||||
/// </summary>
|
||||
public partial class MapGraticule
|
||||
public partial class MapGraticule : MapOverlay
|
||||
{
|
||||
/// <summary>
|
||||
/// Graticule line spacings in degrees.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
|
|
@ -15,13 +15,8 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Fills a rectangular area with an ImageBrush from the Source property.
|
||||
/// </summary>
|
||||
public partial class MapImage : MapRectangle
|
||||
public class MapImage : MapRectangle
|
||||
{
|
||||
private static readonly MatrixTransform imageTransform = new MatrixTransform
|
||||
{
|
||||
Matrix = new Matrix(1d, 0d, 0d, -1d, 0d, 1d)
|
||||
};
|
||||
|
||||
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
|
||||
"Source", typeof(ImageSource), typeof(MapImage),
|
||||
new PropertyMetadata(null, (o, e) => ((MapImage)o).SourceChanged((ImageSource)e.NewValue)));
|
||||
|
|
@ -34,13 +29,17 @@ namespace MapControl
|
|||
|
||||
private void SourceChanged(ImageSource image)
|
||||
{
|
||||
var imageBrush = new ImageBrush
|
||||
var transform = new MatrixTransform
|
||||
{
|
||||
Matrix = new Matrix(1d, 0d, 0d, -1d, 0d, 1d)
|
||||
};
|
||||
transform.Freeze();
|
||||
|
||||
Fill = new ImageBrush
|
||||
{
|
||||
ImageSource = image,
|
||||
RelativeTransform = imageTransform
|
||||
RelativeTransform = transform
|
||||
};
|
||||
|
||||
Fill = imageBrush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
|
|
@ -177,8 +177,8 @@ namespace MapControl
|
|||
|
||||
private void BlendImages()
|
||||
{
|
||||
#if NETFX_CORE
|
||||
var duration = TimeSpan.Zero; // animation not working in WinRT (?)
|
||||
#if WINDOWS_RUNTIME
|
||||
var duration = TimeSpan.Zero; // animation not working in Windows Runtime (?)
|
||||
#else
|
||||
var duration = Tile.AnimationDuration;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#else
|
||||
using System.Windows.Controls;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#else
|
||||
|
|
|
|||
112
MapControl/MapOverlay.Silverlight.WinRT.cs
Normal file
112
MapControl/MapOverlay.Silverlight.WinRT.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Text;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapOverlay
|
||||
{
|
||||
public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
|
||||
"FontSize", typeof(double), typeof(MapOverlay), new PropertyMetadata(10d));
|
||||
|
||||
public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register(
|
||||
"FontFamily", typeof(FontFamily), typeof(MapOverlay), new PropertyMetadata(default(FontFamily)));
|
||||
|
||||
public static readonly DependencyProperty FontStyleProperty = DependencyProperty.Register(
|
||||
"FontStyle", typeof(FontStyle), typeof(MapOverlay), new PropertyMetadata(default(FontStyle)));
|
||||
|
||||
public static readonly DependencyProperty FontStretchProperty = DependencyProperty.Register(
|
||||
"FontStretch", typeof(FontStretch), typeof(MapOverlay), new PropertyMetadata(default(FontStretch)));
|
||||
|
||||
public static readonly DependencyProperty FontWeightProperty = DependencyProperty.Register(
|
||||
"FontWeight", typeof(FontWeight), typeof(MapOverlay), new PropertyMetadata(default(FontWeight)));
|
||||
|
||||
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
|
||||
"Foreground", typeof(Brush), typeof(MapOverlay), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
|
||||
"Stroke", typeof(Brush), typeof(MapOverlay), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
|
||||
"StrokeThickness", typeof(double), typeof(MapOverlay), new PropertyMetadata(1d));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashArrayProperty = DependencyProperty.Register(
|
||||
"StrokeDashArray", typeof(DoubleCollection), typeof(MapOverlay), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashOffsetProperty = DependencyProperty.Register(
|
||||
"StrokeDashOffset", typeof(double), typeof(MapOverlay), new PropertyMetadata(0d));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashCapProperty = DependencyProperty.Register(
|
||||
"StrokeDashCap", typeof(PenLineCap), typeof(MapOverlay), new PropertyMetadata(default(PenLineCap)));
|
||||
|
||||
public static readonly DependencyProperty StrokeStartLineCapProperty = DependencyProperty.Register(
|
||||
"StrokeStartLineCap", typeof(PenLineCap), typeof(MapOverlay), new PropertyMetadata(default(PenLineCap)));
|
||||
|
||||
public static readonly DependencyProperty StrokeEndLineCapProperty = DependencyProperty.Register(
|
||||
"StrokeEndLineCap", typeof(PenLineCap), typeof(MapOverlay), new PropertyMetadata(default(PenLineCap)));
|
||||
|
||||
public static readonly DependencyProperty StrokeLineJoinProperty = DependencyProperty.Register(
|
||||
"StrokeLineJoin", typeof(PenLineJoin), typeof(MapOverlay), new PropertyMetadata(default(PenLineJoin)));
|
||||
|
||||
public static readonly DependencyProperty StrokeMiterLimitProperty = DependencyProperty.Register(
|
||||
"StrokeMiterLimit", typeof(double), typeof(MapOverlay), new PropertyMetadata(1d));
|
||||
|
||||
private Binding foregroundBinding;
|
||||
private Binding strokeBinding;
|
||||
|
||||
public override MapBase ParentMap
|
||||
{
|
||||
get { return base.ParentMap; }
|
||||
set
|
||||
{
|
||||
if (foregroundBinding != null)
|
||||
{
|
||||
foregroundBinding = null;
|
||||
ClearValue(ForegroundProperty);
|
||||
}
|
||||
|
||||
if (strokeBinding != null)
|
||||
{
|
||||
strokeBinding = null;
|
||||
ClearValue(StrokeProperty);
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
if (Foreground == null)
|
||||
{
|
||||
foregroundBinding = new Binding
|
||||
{
|
||||
Source = value,
|
||||
Path = new PropertyPath("Foreground")
|
||||
};
|
||||
SetBinding(ForegroundProperty, foregroundBinding);
|
||||
}
|
||||
|
||||
if (Stroke == null)
|
||||
{
|
||||
strokeBinding = new Binding
|
||||
{
|
||||
Source = value,
|
||||
Path = new PropertyPath("Foreground")
|
||||
};
|
||||
SetBinding(StrokeProperty, strokeBinding);
|
||||
}
|
||||
}
|
||||
|
||||
base.ParentMap = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
100
MapControl/MapOverlay.WPF.cs
Normal file
100
MapControl/MapOverlay.WPF.cs
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapOverlay
|
||||
{
|
||||
public static readonly DependencyProperty FontSizeProperty = Control.FontSizeProperty.AddOwner(
|
||||
typeof(MapOverlay));
|
||||
|
||||
public static readonly DependencyProperty FontFamilyProperty = Control.FontFamilyProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
|
||||
|
||||
public static readonly DependencyProperty FontStyleProperty = Control.FontStyleProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
|
||||
|
||||
public static readonly DependencyProperty FontStretchProperty = Control.FontStretchProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
|
||||
|
||||
public static readonly DependencyProperty FontWeightProperty = Control.FontWeightProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
|
||||
|
||||
public static readonly DependencyProperty ForegroundProperty = Control.ForegroundProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => { if (o.GetValue(StrokeProperty) == null) ((MapOverlay)o).pen = null; }));
|
||||
|
||||
public static readonly DependencyProperty StrokeProperty = Shape.StrokeProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashArrayProperty = Shape.StrokeDashArrayProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashOffsetProperty = Shape.StrokeDashOffsetProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashCapProperty = Shape.StrokeDashCapProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeStartLineCapProperty = Shape.StrokeStartLineCapProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeEndLineCapProperty = Shape.StrokeEndLineCapProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeLineJoinProperty = Shape.StrokeLineJoinProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeMiterLimitProperty = Shape.StrokeMiterLimitProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
private Typeface typeface;
|
||||
private Pen pen;
|
||||
|
||||
protected Typeface Typeface
|
||||
{
|
||||
get
|
||||
{
|
||||
if (typeface == null)
|
||||
{
|
||||
typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
|
||||
}
|
||||
|
||||
return typeface;
|
||||
}
|
||||
}
|
||||
|
||||
protected Pen Pen
|
||||
{
|
||||
get
|
||||
{
|
||||
if (pen == null)
|
||||
{
|
||||
pen = new Pen
|
||||
{
|
||||
Brush = Stroke ?? Foreground,
|
||||
Thickness = StrokeThickness,
|
||||
DashStyle = new DashStyle(StrokeDashArray, StrokeDashOffset),
|
||||
DashCap = StrokeDashCap,
|
||||
StartLineCap = StrokeStartLineCap,
|
||||
EndLineCap = StrokeEndLineCap,
|
||||
LineJoin = StrokeLineJoin,
|
||||
MiterLimit = StrokeMiterLimit
|
||||
};
|
||||
|
||||
pen.Freeze();
|
||||
}
|
||||
|
||||
return pen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,72 +2,21 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Text;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for map overlays with font, background, foreground and stroke properties.
|
||||
/// Rendering is typically done by overriding OnRender in derived classes.
|
||||
/// </summary>
|
||||
public class MapOverlay : FrameworkElement, IMapElement
|
||||
public partial class MapOverlay : MapPanel
|
||||
{
|
||||
public static readonly DependencyProperty FontSizeProperty = Control.FontSizeProperty.AddOwner(
|
||||
typeof(MapOverlay));
|
||||
|
||||
public static readonly DependencyProperty FontFamilyProperty = Control.FontFamilyProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
|
||||
|
||||
public static readonly DependencyProperty FontStyleProperty = Control.FontStyleProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
|
||||
|
||||
public static readonly DependencyProperty FontStretchProperty = Control.FontStretchProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
|
||||
|
||||
public static readonly DependencyProperty FontWeightProperty = Control.FontWeightProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).typeface = null));
|
||||
|
||||
public static readonly DependencyProperty BackgroundProperty = Control.BackgroundProperty.AddOwner(
|
||||
typeof(MapOverlay));
|
||||
|
||||
public static readonly DependencyProperty ForegroundProperty = Control.ForegroundProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata((o, e) => ((MapOverlay)o).ForegroundChanged()));
|
||||
|
||||
public static readonly DependencyProperty StrokeProperty = Shape.StrokeProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashArrayProperty = Shape.StrokeDashArrayProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashOffsetProperty = Shape.StrokeDashOffsetProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashCapProperty = Shape.StrokeDashCapProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata(default(PenLineCap), FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeStartLineCapProperty = Shape.StrokeStartLineCapProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata(default(PenLineCap), FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeEndLineCapProperty = Shape.StrokeEndLineCapProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata(default(PenLineCap), FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeLineJoinProperty = Shape.StrokeLineJoinProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata(default(PenLineJoin), FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
public static readonly DependencyProperty StrokeMiterLimitProperty = Shape.StrokeMiterLimitProperty.AddOwner(
|
||||
typeof(MapOverlay), new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsRender, (o, e) => ((MapOverlay)o).pen = null));
|
||||
|
||||
private MapBase parentMap;
|
||||
private Typeface typeface;
|
||||
private Pen pen;
|
||||
|
||||
public double FontSize
|
||||
{
|
||||
get { return (double)GetValue(FontSizeProperty); }
|
||||
|
|
@ -98,12 +47,6 @@ namespace MapControl
|
|||
set { SetValue(FontWeightProperty, value); }
|
||||
}
|
||||
|
||||
public Brush Background
|
||||
{
|
||||
get { return (Brush)GetValue(BackgroundProperty); }
|
||||
set { SetValue(BackgroundProperty, value); }
|
||||
}
|
||||
|
||||
public Brush Foreground
|
||||
{
|
||||
get { return (Brush)GetValue(ForegroundProperty); }
|
||||
|
|
@ -163,80 +106,5 @@ namespace MapControl
|
|||
get { return (double)GetValue(StrokeMiterLimitProperty); }
|
||||
set { SetValue(StrokeMiterLimitProperty, value); }
|
||||
}
|
||||
|
||||
public MapBase ParentMap
|
||||
{
|
||||
get { return parentMap; }
|
||||
set
|
||||
{
|
||||
if (parentMap != null)
|
||||
{
|
||||
parentMap.ViewportChanged -= OnViewportChanged;
|
||||
}
|
||||
|
||||
parentMap = value;
|
||||
|
||||
if (parentMap != null)
|
||||
{
|
||||
parentMap.ViewportChanged += OnViewportChanged;
|
||||
OnViewportChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Typeface Typeface
|
||||
{
|
||||
get
|
||||
{
|
||||
if (typeface == null)
|
||||
{
|
||||
typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
|
||||
}
|
||||
|
||||
return typeface;
|
||||
}
|
||||
}
|
||||
|
||||
protected Pen Pen
|
||||
{
|
||||
get
|
||||
{
|
||||
if (pen == null)
|
||||
{
|
||||
pen = new Pen
|
||||
{
|
||||
Brush = Stroke ?? Foreground,
|
||||
Thickness = StrokeThickness,
|
||||
DashStyle = new DashStyle(StrokeDashArray, StrokeDashOffset),
|
||||
DashCap = StrokeDashCap,
|
||||
StartLineCap = StrokeStartLineCap,
|
||||
EndLineCap = StrokeEndLineCap,
|
||||
LineJoin = StrokeLineJoin,
|
||||
MiterLimit = StrokeMiterLimit
|
||||
};
|
||||
|
||||
pen.Freeze();
|
||||
}
|
||||
|
||||
return pen;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnViewportChanged()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnViewportChanged(object sender, EventArgs e)
|
||||
{
|
||||
OnViewportChanged();
|
||||
}
|
||||
|
||||
private void ForegroundChanged()
|
||||
{
|
||||
if (Stroke == null)
|
||||
{
|
||||
pen = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
|
@ -27,15 +27,10 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
private UIElementCollection InternalChildren
|
||||
{
|
||||
get { return Children; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to work around missing property value inheritance in Silverlight and WinRT.
|
||||
/// Adds Loaded and Unloaded handlers to the specified FrameworkElement, which set and clear
|
||||
/// the value of the MapPanel.ParentMap attached property.
|
||||
/// Helper method to work around missing property value inheritance in Silverlight and Windows Runtime.
|
||||
/// Adds Loaded and Unloaded handlers to the specified FrameworkElement, which set and clear the value
|
||||
/// of the MapPanel.ParentMap attached property.
|
||||
/// </summary>
|
||||
public static void AddParentMapHandlers(FrameworkElement element)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,30 +3,23 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public interface IMapElement
|
||||
{
|
||||
MapBase ParentMap { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Positions child elements on a Map, at a position specified by the attached property Location.
|
||||
/// The Location is transformed to a viewport position by ParentMap.MapTransform and ParentMap.ViewportTransform
|
||||
/// and applied to a child element's RenderTransform as an appropriate TranslateTransform.
|
||||
/// </summary>
|
||||
public partial class MapPanel : Panel, IMapElement
|
||||
public partial class MapPanel : PanelBase, IMapElement
|
||||
{
|
||||
public static readonly DependencyProperty LocationProperty = DependencyProperty.RegisterAttached(
|
||||
"Location", typeof(Location), typeof(MapPanel), new PropertyMetadata(null, LocationPropertyChanged));
|
||||
|
|
@ -51,7 +44,7 @@ namespace MapControl
|
|||
|
||||
private MapBase parentMap;
|
||||
|
||||
public MapBase ParentMap
|
||||
public virtual MapBase ParentMap
|
||||
{
|
||||
get { return parentMap; }
|
||||
set
|
||||
|
|
@ -71,18 +64,6 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
|
||||
|
||||
foreach (UIElement element in InternalChildren)
|
||||
{
|
||||
element.Measure(availableSize);
|
||||
}
|
||||
|
||||
return new Size();
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
foreach (UIElement element in InternalChildren)
|
||||
|
|
@ -147,8 +128,7 @@ namespace MapControl
|
|||
}
|
||||
else if (e.OldValue == null)
|
||||
{
|
||||
// Arrange element once when Location was null before
|
||||
ArrangeElementWithLocation(element);
|
||||
ArrangeElementWithLocation(element); // arrange element when Location was null before
|
||||
}
|
||||
|
||||
SetViewportPosition(element, parentMap, location);
|
||||
|
|
@ -161,8 +141,7 @@ namespace MapControl
|
|||
|
||||
if (parentMap != null && location != null)
|
||||
{
|
||||
// Keep ViewportPosition near map center
|
||||
var mapPosition = parentMap.MapTransform.Transform(location, parentMap.Center.Longitude);
|
||||
var mapPosition = parentMap.MapTransform.Transform(location, parentMap.Center.Longitude); // nearest to center longitude
|
||||
viewportPosition = parentMap.ViewportTransform.Transform(mapPosition);
|
||||
element.SetValue(ViewportPositionProperty, viewportPosition);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml.Shapes;
|
||||
#else
|
||||
using System.Windows.Shapes;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
#else
|
||||
using System.Windows;
|
||||
|
|
@ -33,7 +33,7 @@ namespace MapControl
|
|||
|
||||
protected override Size MeasureOverride(Size constraint)
|
||||
{
|
||||
// base.MeasureOverride in WPF and WinRT sometimes return a Size with zero
|
||||
// base.MeasureOverride in WPF and Windows Runtime sometimes return a Size with zero
|
||||
// width or height, whereas base.MeasureOverride in Silverlight occasionally
|
||||
// throws an ArgumentException, as it tries to create a Size from a negative
|
||||
// width or height, apparently resulting from a transformed Geometry.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System.Linq;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows.Media;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
#else
|
||||
|
|
@ -20,8 +20,8 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public partial class MapPolyline : MapPath
|
||||
{
|
||||
#if NETFX_CORE
|
||||
// For WinRT, the Locations dependency property type is declared as object
|
||||
#if WINDOWS_RUNTIME
|
||||
// For Windows Runtime, the Locations dependency property type is declared as object
|
||||
// instead of IEnumerable. See http://stackoverflow.com/q/10544084/1136211
|
||||
private static readonly Type LocationsPropertyType = typeof(object);
|
||||
#else
|
||||
|
|
@ -38,7 +38,7 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Gets or sets the locations that define the polyline points.
|
||||
/// </summary>
|
||||
#if !NETFX_CORE
|
||||
#if !WINDOWS_RUNTIME
|
||||
[TypeConverter(typeof(LocationCollectionConverter))]
|
||||
#endif
|
||||
public IEnumerable<Location> Locations
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapRectangle
|
||||
{
|
||||
static MapRectangle()
|
||||
{
|
||||
geometryScaleTransform.Freeze();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
|
@ -16,16 +16,8 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Fills a rectangular area defined by South, North, West and East with a Brush.
|
||||
/// </summary>
|
||||
public partial class MapRectangle : MapPath
|
||||
public class MapRectangle : MapPath
|
||||
{
|
||||
private const double GeometryScale = 1e6;
|
||||
|
||||
private static readonly ScaleTransform geometryScaleTransform = new ScaleTransform
|
||||
{
|
||||
ScaleX = 1d / GeometryScale,
|
||||
ScaleY = 1d / GeometryScale
|
||||
};
|
||||
|
||||
public static readonly DependencyProperty SouthProperty = DependencyProperty.Register(
|
||||
"South", typeof(double), typeof(MapRectangle),
|
||||
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateData()));
|
||||
|
|
@ -81,17 +73,23 @@ namespace MapControl
|
|||
!double.IsNaN(West) && !double.IsNaN(East) &&
|
||||
South < North && West < East)
|
||||
{
|
||||
var p1 = ParentMap.MapTransform.Transform(new Location(South, West));
|
||||
var p2 = ParentMap.MapTransform.Transform(new Location(North, East));
|
||||
|
||||
// Create a scaled RectangleGeometry due to inaccurate hit testing in WPF.
|
||||
// See http://stackoverflow.com/a/19335624/1136211
|
||||
|
||||
geometry.Rect = new Rect(p1.X * GeometryScale, p1.Y * GeometryScale,
|
||||
(p2.X - p1.X) * GeometryScale, (p2.Y - p1.Y) * GeometryScale);
|
||||
const double scale = 1e6;
|
||||
var p1 = ParentMap.MapTransform.Transform(new Location(South, West));
|
||||
var p2 = ParentMap.MapTransform.Transform(new Location(North, East));
|
||||
geometry.Rect = new Rect(p1.X * scale, p1.Y * scale, (p2.X - p1.X) * scale, (p2.Y - p1.Y) * scale);
|
||||
|
||||
var scaleTransform = new ScaleTransform // revert scaling
|
||||
{
|
||||
ScaleX = 1d / scale,
|
||||
ScaleY = 1d / scale
|
||||
};
|
||||
scaleTransform.Freeze();
|
||||
|
||||
var transform = new TransformGroup();
|
||||
transform.Children.Add(geometryScaleTransform); // revert scaling
|
||||
transform.Children.Add(scaleTransform);
|
||||
transform.Children.Add(ParentMap.ViewportTransform);
|
||||
RenderTransform = transform;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,9 @@ namespace MapControl
|
|||
drawingContext.DrawLine(Pen, new Point(x2, y1), new Point(x2, y2));
|
||||
drawingContext.DrawLine(Pen, new Point(x1, y2), new Point(x2, y2));
|
||||
drawingContext.DrawGlyphRun(Foreground,
|
||||
GlyphRunText.Create(text, Typeface, FontSize, new Vector(size.Width / 2d, y1 - StrokeThickness - 1d)));
|
||||
GlyphRunText.Create(text, Typeface, FontSize),
|
||||
new Point(size.Width / 2d, y1 - StrokeThickness - 1d),
|
||||
HorizontalAlignment.Center, VerticalAlignment.Center);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
#else
|
||||
using System.Windows;
|
||||
|
|
@ -30,16 +30,16 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public abstract double RelativeScale(Location location);
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a geographic location to a cartesian coordinate point.
|
||||
/// </summary>
|
||||
public abstract Point Transform(Location location);
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a cartesian coordinate point to a geographic location.
|
||||
/// </summary>
|
||||
public abstract Location Transform(Point point);
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a geographic location to a cartesian coordinate point.
|
||||
/// </summary>
|
||||
public abstract Point Transform(Location location);
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a geographic location to a cartesian coordinate point
|
||||
/// with minumum distance to the specified reference longitude value.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
#else
|
||||
using System.Windows;
|
||||
|
|
|
|||
50
MapControl/PanelBase.cs
Normal file
50
MapControl/PanelBase.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Common base class for MapPanel, TileLayer and TileContainer.
|
||||
/// </summary>
|
||||
public class PanelBase : Panel
|
||||
{
|
||||
#if WINDOWS_RUNTIME || SILVERLIGHT
|
||||
protected internal UIElementCollection InternalChildren
|
||||
{
|
||||
get { return Children; }
|
||||
}
|
||||
#endif
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
|
||||
|
||||
foreach (UIElement element in InternalChildren)
|
||||
{
|
||||
element.Measure(availableSize);
|
||||
}
|
||||
|
||||
return new Size();
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
foreach (UIElement child in InternalChildren)
|
||||
{
|
||||
child.Arrange(new Rect(new Point(), finalSize));
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,13 +10,12 @@ using System.Windows;
|
|||
[assembly: AssemblyDescription("XAML Map Control Library for WPF")]
|
||||
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
|
||||
#endif
|
||||
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("1.12.1")]
|
||||
[assembly: AssemblyFileVersion("1.12.1")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#else
|
||||
using System.Windows.Controls;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
|
@ -20,13 +20,6 @@ namespace MapControl
|
|||
{
|
||||
public partial class Tile
|
||||
{
|
||||
public readonly Image Image = new Image { Opacity = 0d };
|
||||
|
||||
public ImageSource ImageSource
|
||||
{
|
||||
get { return Image.Source; }
|
||||
}
|
||||
|
||||
public void SetImageSource(ImageSource image, bool animateOpacity)
|
||||
{
|
||||
if (image != null && Image.Source == null)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
|
@ -11,16 +12,9 @@ namespace MapControl
|
|||
{
|
||||
public partial class Tile
|
||||
{
|
||||
public readonly ImageBrush Brush = new ImageBrush { Opacity = 0d };
|
||||
|
||||
public ImageSource ImageSource
|
||||
{
|
||||
get { return Brush.ImageSource; }
|
||||
}
|
||||
|
||||
public void SetImageSource(ImageSource image, bool animateOpacity)
|
||||
{
|
||||
if (image != null && Brush.ImageSource == null)
|
||||
if (image != null && Image.Source == null)
|
||||
{
|
||||
if (animateOpacity)
|
||||
{
|
||||
|
|
@ -33,16 +27,16 @@ namespace MapControl
|
|||
}
|
||||
else
|
||||
{
|
||||
Brush.BeginAnimation(ImageBrush.OpacityProperty, new DoubleAnimation(1d, AnimationDuration));
|
||||
Image.BeginAnimation(Image.OpacityProperty, new DoubleAnimation(1d, AnimationDuration));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Brush.Opacity = 1d;
|
||||
Image.Opacity = 1d;
|
||||
}
|
||||
}
|
||||
|
||||
Brush.ImageSource = image;
|
||||
Image.Source = image;
|
||||
HasImageSource = true;
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +47,7 @@ namespace MapControl
|
|||
bitmap.DownloadCompleted -= BitmapDownloadCompleted;
|
||||
bitmap.DownloadFailed -= BitmapDownloadFailed;
|
||||
|
||||
Brush.BeginAnimation(ImageBrush.OpacityProperty, new DoubleAnimation(1d, AnimationDuration));
|
||||
Image.BeginAnimation(Image.OpacityProperty, new DoubleAnimation(1d, AnimationDuration));
|
||||
}
|
||||
|
||||
private void BitmapDownloadFailed(object sender, ExceptionEventArgs e)
|
||||
|
|
@ -63,7 +57,7 @@ namespace MapControl
|
|||
bitmap.DownloadCompleted -= BitmapDownloadCompleted;
|
||||
bitmap.DownloadFailed -= BitmapDownloadFailed;
|
||||
|
||||
Brush.ImageSource = null;
|
||||
Image.Source = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#else
|
||||
using System.Windows.Controls;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
|
|
@ -13,6 +18,7 @@ namespace MapControl
|
|||
public readonly int ZoomLevel;
|
||||
public readonly int X;
|
||||
public readonly int Y;
|
||||
public readonly Image Image = new Image { Opacity = 0d };
|
||||
|
||||
public Tile(int zoomLevel, int x, int y)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,37 +3,19 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if NETFX_CORE
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
internal partial class TileContainer : Panel
|
||||
internal partial class TileContainer
|
||||
{
|
||||
private Matrix GetViewportTransformMatrix(double scale, double offsetX, double offsetY)
|
||||
{
|
||||
var transform = new Matrix(scale, 0d, 0d, -scale, offsetX, offsetY);
|
||||
|
||||
return transform.RotateAt(rotation, viewportOrigin.X, viewportOrigin.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a transform matrix with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
|
||||
/// </summary>
|
||||
private Matrix GetTileLayerTransformMatrix()
|
||||
{
|
||||
var scale = Math.Pow(2d, zoomLevel - tileZoomLevel);
|
||||
|
||||
return new Matrix(1d, 0d, 0d, 1d, tileGrid.X * TileSource.TileSize, tileGrid.Y * TileSource.TileSize)
|
||||
.Scale(scale, scale)
|
||||
.Translate(tileLayerOffset.X, tileLayerOffset.Y)
|
||||
return new Matrix(scale, 0d, 0d, -scale, offsetX, offsetY)
|
||||
.RotateAt(rotation, viewportOrigin.X, viewportOrigin.Y);
|
||||
}
|
||||
|
||||
|
|
@ -47,24 +29,18 @@ namespace MapControl
|
|||
.Scale(scale, -scale); // map coordinates to tile indices
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
/// <summary>
|
||||
/// Sets a RenderTransform with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
|
||||
/// </summary>
|
||||
private void UpdateRenderTransform()
|
||||
{
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
{
|
||||
tileLayer.Measure(availableSize);
|
||||
}
|
||||
var scale = Math.Pow(2d, zoomLevel - tileZoomLevel);
|
||||
|
||||
return new Size();
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
{
|
||||
tileLayer.Arrange(new Rect());
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
((MatrixTransform)RenderTransform).Matrix =
|
||||
new Matrix(1d, 0d, 0d, 1d, tileGrid.X * TileSource.TileSize, tileGrid.Y * TileSource.TileSize)
|
||||
.Scale(scale, scale)
|
||||
.Translate(tileLayerOffset.X, tileLayerOffset.Y)
|
||||
.RotateAt(rotation, viewportOrigin.X, viewportOrigin.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,27 +7,11 @@ using System.Windows.Media;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
internal partial class TileContainer : ContainerVisual
|
||||
internal partial class TileContainer
|
||||
{
|
||||
private Matrix GetViewportTransformMatrix(double scale, double offsetX, double offsetY)
|
||||
{
|
||||
var transform = new Matrix(scale, 0d, 0d, -scale, offsetX, offsetY);
|
||||
|
||||
transform.RotateAt(rotation, viewportOrigin.X, viewportOrigin.Y);
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a transform matrix with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
|
||||
/// </summary>
|
||||
private Matrix GetTileLayerTransformMatrix()
|
||||
{
|
||||
var scale = Math.Pow(2d, zoomLevel - tileZoomLevel);
|
||||
var transform = new Matrix(1d, 0d, 0d, 1d, tileGrid.X * TileSource.TileSize, tileGrid.Y * TileSource.TileSize);
|
||||
|
||||
transform.Scale(scale, scale);
|
||||
transform.Translate(tileLayerOffset.X, tileLayerOffset.Y);
|
||||
transform.RotateAt(rotation, viewportOrigin.X, viewportOrigin.Y);
|
||||
|
||||
return transform;
|
||||
|
|
@ -37,12 +21,25 @@ namespace MapControl
|
|||
{
|
||||
var scale = (double)numTiles / 360d;
|
||||
var transform = ViewportTransform.Matrix;
|
||||
|
||||
transform.Invert(); // view to map coordinates
|
||||
transform.Translate(180d, -180d);
|
||||
transform.Scale(scale, -scale); // map coordinates to tile indices
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a RenderTransform with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
|
||||
/// </summary>
|
||||
private void UpdateRenderTransform()
|
||||
{
|
||||
var scale = Math.Pow(2d, zoomLevel - tileZoomLevel);
|
||||
var transform = new Matrix(1d, 0d, 0d, 1d, tileGrid.X * TileSource.TileSize, tileGrid.Y * TileSource.TileSize);
|
||||
transform.Scale(scale, scale);
|
||||
transform.Translate(tileLayerOffset.X, tileLayerOffset.Y);
|
||||
transform.RotateAt(rotation, viewportOrigin.X, viewportOrigin.Y);
|
||||
|
||||
((MatrixTransform)RenderTransform).Matrix = transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NETFX_CORE
|
||||
using System.Linq;
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
|
@ -16,7 +17,7 @@ using System.Windows.Threading;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
internal partial class TileContainer
|
||||
internal partial class TileContainer : PanelBase
|
||||
{
|
||||
// relative scaled tile size ranges from 0.75 to 1.5 (192 to 384 pixels)
|
||||
private static double zoomLevelSwitchDelta = -Math.Log(0.75, 2d);
|
||||
|
|
@ -36,27 +37,30 @@ namespace MapControl
|
|||
|
||||
public TileContainer()
|
||||
{
|
||||
RenderTransform = new MatrixTransform();
|
||||
updateTimer = new DispatcherTimer { Interval = UpdateInterval };
|
||||
updateTimer.Tick += UpdateTiles;
|
||||
}
|
||||
|
||||
public IEnumerable<TileLayer> TileLayers
|
||||
{
|
||||
get { return InternalChildren.Cast<TileLayer>(); }
|
||||
}
|
||||
|
||||
public void AddTileLayers(int index, IEnumerable<TileLayer> tileLayers)
|
||||
{
|
||||
var tileLayerTransform = GetTileLayerTransformMatrix();
|
||||
|
||||
foreach (var tileLayer in tileLayers)
|
||||
{
|
||||
if (index < Children.Count)
|
||||
if (index < InternalChildren.Count)
|
||||
{
|
||||
Children.Insert(index, tileLayer);
|
||||
InternalChildren.Insert(index, tileLayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Children.Add(tileLayer);
|
||||
InternalChildren.Add(tileLayer);
|
||||
}
|
||||
|
||||
index++;
|
||||
tileLayer.SetTransformMatrix(tileLayerTransform);
|
||||
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
||||
}
|
||||
}
|
||||
|
|
@ -65,19 +69,19 @@ namespace MapControl
|
|||
{
|
||||
while (count-- > 0)
|
||||
{
|
||||
((TileLayer)Children[index]).ClearTiles();
|
||||
Children.RemoveAt(index);
|
||||
((TileLayer)InternalChildren[index]).ClearTiles();
|
||||
InternalChildren.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearTileLayers()
|
||||
{
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
foreach (TileLayer tileLayer in InternalChildren)
|
||||
{
|
||||
tileLayer.ClearTiles();
|
||||
}
|
||||
|
||||
Children.Clear();
|
||||
InternalChildren.Clear();
|
||||
}
|
||||
|
||||
public double SetViewportTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point vpOrigin, Size vpSize)
|
||||
|
|
@ -103,12 +107,7 @@ namespace MapControl
|
|||
tileLayerOffset.X = transformOffsetX - 180d * scale;
|
||||
tileLayerOffset.Y = transformOffsetY - 180d * scale;
|
||||
|
||||
var tileLayerTransform = GetTileLayerTransformMatrix();
|
||||
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
{
|
||||
tileLayer.SetTransformMatrix(tileLayerTransform);
|
||||
}
|
||||
UpdateRenderTransform();
|
||||
|
||||
if (Math.Abs(mapOrigin.X - oldMapOriginX) > 180d)
|
||||
{
|
||||
|
|
@ -147,11 +146,11 @@ namespace MapControl
|
|||
{
|
||||
tileZoomLevel = zoom;
|
||||
tileGrid = grid;
|
||||
var tileLayerTransform = GetTileLayerTransformMatrix();
|
||||
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
UpdateRenderTransform();
|
||||
|
||||
foreach (TileLayer tileLayer in InternalChildren)
|
||||
{
|
||||
tileLayer.SetTransformMatrix(tileLayerTransform);
|
||||
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
|
|
@ -24,33 +24,40 @@ namespace MapControl
|
|||
{
|
||||
var imageTileSource = tileLayer.TileSource as ImageTileSource;
|
||||
|
||||
foreach (var tile in tiles)
|
||||
if (imageTileSource != null)
|
||||
{
|
||||
try
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
ImageSource image;
|
||||
|
||||
if (imageTileSource != null)
|
||||
try
|
||||
{
|
||||
image = imageTileSource.LoadImage(tile.XIndex, tile.Y, tile.ZoomLevel);
|
||||
var image = imageTileSource.LoadImage(tile.XIndex, tile.Y, tile.ZoomLevel);
|
||||
tile.SetImageSource(image, tileLayer.AnimateTileOpacity);
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("Loading tile image failed: {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
var uri = tileLayer.TileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);
|
||||
|
||||
image = uri != null ? new BitmapImage(uri) : null;
|
||||
var image = uri != null ? new BitmapImage(uri) : null;
|
||||
tile.SetImageSource(image, tileLayer.AnimateTileOpacity);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("Creating tile image failed: {0}", ex.Message);
|
||||
}
|
||||
|
||||
tile.SetImageSource(image, tileLayer.AnimateTileOpacity);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("Creating tile image failed: {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void CancelGetTiles()
|
||||
public void CancelGetTiles()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace MapControl
|
|||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MapControl");
|
||||
|
||||
/// <summary>
|
||||
/// The ObjectCache used to cache tile images. The default is null.
|
||||
/// The ObjectCache used to cache tile images. The default is MemoryCache.Default.
|
||||
/// </summary>
|
||||
public static ObjectCache Cache { get; set; }
|
||||
|
||||
|
|
@ -57,6 +57,7 @@ namespace MapControl
|
|||
|
||||
static TileImageLoader()
|
||||
{
|
||||
Cache = MemoryCache.Default;
|
||||
CacheExpiration = TimeSpan.FromDays(7);
|
||||
CacheUpdateAge = TimeSpan.FromDays(1);
|
||||
}
|
||||
|
|
@ -66,19 +67,32 @@ namespace MapControl
|
|||
|
||||
internal void BeginGetTiles(TileLayer tileLayer, IEnumerable<Tile> tiles)
|
||||
{
|
||||
var tileList = tiles.ToList();
|
||||
|
||||
if (tileList.Count > 0)
|
||||
if (tiles.Any())
|
||||
{
|
||||
// get current TileLayer property values in UI thread
|
||||
var dispatcher = tileLayer.Dispatcher;
|
||||
var tileSource = tileLayer.TileSource;
|
||||
var sourceName = tileLayer.SourceName;
|
||||
var maxDownloads = tileLayer.MaxParallelDownloads;
|
||||
var imageTileSource = tileSource as ImageTileSource;
|
||||
var animateOpacity = tileLayer.AnimateTileOpacity;
|
||||
var dispatcher = tileLayer.Dispatcher;
|
||||
|
||||
ThreadPool.QueueUserWorkItem(o =>
|
||||
GetTiles(tileList, dispatcher, tileSource, sourceName, maxDownloads, animateOpacity));
|
||||
if (imageTileSource != null && !imageTileSource.IsAsync) // call LoadImage in UI thread
|
||||
{
|
||||
var setImageAction = new Action<Tile>(t => t.SetImageSource(LoadImage(imageTileSource, t), animateOpacity));
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
dispatcher.BeginInvoke(setImageAction, DispatcherPriority.Background, tile); // with low priority
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var tileList = tiles.ToList();
|
||||
var sourceName = tileLayer.SourceName;
|
||||
var maxDownloads = tileLayer.MaxParallelDownloads;
|
||||
|
||||
ThreadPool.QueueUserWorkItem(o =>
|
||||
GetTiles(tileList, dispatcher, tileSource, sourceName, animateOpacity, maxDownloads));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,69 +102,35 @@ namespace MapControl
|
|||
while (pendingTiles.TryDequeue(out tile)) ; // no Clear method
|
||||
}
|
||||
|
||||
private void GetTiles(List<Tile> tiles, Dispatcher dispatcher, TileSource tileSource,
|
||||
string sourceName, int maxDownloads, bool animateOpacity)
|
||||
private void GetTiles(List<Tile> tiles, Dispatcher dispatcher, TileSource tileSource, string sourceName, bool animateOpacity, int maxDownloads)
|
||||
{
|
||||
var imageTileSource = tileSource as ImageTileSource;
|
||||
|
||||
if (imageTileSource != null)
|
||||
if (Cache != null && !string.IsNullOrWhiteSpace(sourceName) &&
|
||||
!(tileSource is ImageTileSource) && !tileSource.UriFormat.StartsWith("file:"))
|
||||
{
|
||||
if (!imageTileSource.CanLoadAsync) // call LoadImage in UI thread
|
||||
var setImageAction = new Action<Tile, ImageSource>((t, i) => t.SetImageSource(i, animateOpacity));
|
||||
var outdatedTiles = new List<Tile>(tiles.Count);
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
var setImageAction = new Action<Tile, ImageTileSource>((t, ts) => t.SetImageSource(LoadImage(ts, t), animateOpacity));
|
||||
var buffer = Cache.Get(TileCache.Key(sourceName, tile)) as byte[];
|
||||
var image = CreateImage(buffer);
|
||||
|
||||
foreach (var tile in tiles)
|
||||
if (image == null)
|
||||
{
|
||||
dispatcher.BeginInvoke(setImageAction, tile, imageTileSource);
|
||||
pendingTiles.Enqueue(tile); // not yet cached
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!tileSource.UriFormat.StartsWith("file:")) // load local image files asynchronously, without caching
|
||||
{
|
||||
if (Cache == null || string.IsNullOrWhiteSpace(sourceName))
|
||||
{
|
||||
// no caching here: use default asynchronous downloading and caching done by WPF
|
||||
|
||||
var setImageAction = new Action<Tile, TileSource>((t, ts) => t.SetImageSource(CreateImage(ts, t), animateOpacity));
|
||||
|
||||
foreach (var tile in tiles)
|
||||
else if (CacheUpdateAge > TimeSpan.Zero && TileCache.CreationTime(buffer) + CacheUpdateAge < DateTime.UtcNow)
|
||||
{
|
||||
dispatcher.BeginInvoke(setImageAction, tile, tileSource);
|
||||
dispatcher.Invoke(setImageAction, tile, image); // synchronously before enqueuing
|
||||
outdatedTiles.Add(tile); // update outdated cache
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var setImageAction = new Action<Tile, ImageSource>((t, i) => t.SetImageSource(i, animateOpacity));
|
||||
var outdatedTiles = new List<Tile>(tiles.Count);
|
||||
|
||||
foreach (var tile in tiles)
|
||||
else
|
||||
{
|
||||
var key = GetCacheKey(sourceName, tile);
|
||||
var buffer = Cache.Get(key) as byte[];
|
||||
var image = CreateImage(buffer);
|
||||
|
||||
if (image == null)
|
||||
{
|
||||
pendingTiles.Enqueue(tile); // not yet cached
|
||||
}
|
||||
else if (CacheUpdateAge > TimeSpan.Zero &&
|
||||
DateTime.FromBinary(BitConverter.ToInt64(buffer, 0)) + CacheUpdateAge < DateTime.UtcNow)
|
||||
{
|
||||
dispatcher.Invoke(setImageAction, tile, image); // synchronously before enqueuing
|
||||
outdatedTiles.Add(tile); // update outdated cache
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatcher.BeginInvoke(setImageAction, tile, image);
|
||||
}
|
||||
dispatcher.BeginInvoke(setImageAction, tile, image);
|
||||
}
|
||||
|
||||
tiles = outdatedTiles; // enqueue outdated tiles at last
|
||||
}
|
||||
|
||||
tiles = outdatedTiles; // enqueue outdated tiles after current tiles
|
||||
}
|
||||
|
||||
foreach (var tile in tiles)
|
||||
|
|
@ -187,7 +167,7 @@ namespace MapControl
|
|||
|
||||
if (uri != null)
|
||||
{
|
||||
if (uri.Scheme == "file") // create from FileStream as creating from URI leaves the file open
|
||||
if (uri.Scheme == "file") // create from FileStream because creating from URI leaves the file open
|
||||
{
|
||||
image = CreateImage(uri.LocalPath);
|
||||
}
|
||||
|
|
@ -199,25 +179,20 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
if (image != null || !tile.HasImageSource) // do not set null if tile already has an image (from cache)
|
||||
if (image != null || !tile.HasImageSource) // set null image if tile does not yet have an ImageSource
|
||||
{
|
||||
dispatcher.BeginInvoke(setImageAction, tile, image);
|
||||
}
|
||||
|
||||
if (buffer != null && image != null)
|
||||
if (image != null && buffer != null && Cache != null && !string.IsNullOrWhiteSpace(sourceName))
|
||||
{
|
||||
Cache.Set(GetCacheKey(sourceName, tile), buffer, new CacheItemPolicy { SlidingExpiration = CacheExpiration });
|
||||
Cache.Set(TileCache.Key(sourceName, tile), buffer, new CacheItemPolicy { SlidingExpiration = CacheExpiration });
|
||||
}
|
||||
}
|
||||
|
||||
Interlocked.Decrement(ref threadCount);
|
||||
}
|
||||
|
||||
private static string GetCacheKey(string sourceName, Tile tile)
|
||||
{
|
||||
return string.Format("{0}/{1}/{2}/{3}", sourceName, tile.ZoomLevel, tile.XIndex, tile.Y);
|
||||
}
|
||||
|
||||
private static ImageSource LoadImage(ImageTileSource tileSource, Tile tile)
|
||||
{
|
||||
ImageSource image = null;
|
||||
|
|
@ -234,27 +209,6 @@ namespace MapControl
|
|||
return image;
|
||||
}
|
||||
|
||||
private static ImageSource CreateImage(TileSource tileSource, Tile tile)
|
||||
{
|
||||
ImageSource image = null;
|
||||
|
||||
try
|
||||
{
|
||||
var uri = tileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);
|
||||
|
||||
if (uri != null)
|
||||
{
|
||||
image = BitmapFrame.Create(uri);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.TraceWarning("Creating tile image failed: {0}", ex.Message);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private static ImageSource CreateImage(string path)
|
||||
{
|
||||
ImageSource image = null;
|
||||
|
|
@ -281,11 +235,11 @@ namespace MapControl
|
|||
{
|
||||
ImageSource image = null;
|
||||
|
||||
if (buffer != null && buffer.Length > sizeof(long))
|
||||
if (buffer != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var stream = new MemoryStream(buffer, sizeof(long), buffer.Length - sizeof(long), false))
|
||||
using (var stream = TileCache.ImageStream(buffer))
|
||||
{
|
||||
image = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
}
|
||||
|
|
@ -311,17 +265,7 @@ namespace MapControl
|
|||
using (var response = (HttpWebResponse)request.GetResponse())
|
||||
using (var responseStream = response.GetResponseStream())
|
||||
{
|
||||
var length = (int)response.ContentLength;
|
||||
|
||||
using (var memoryStream = length > 0 ? new MemoryStream(length + sizeof(long)) : new MemoryStream())
|
||||
{
|
||||
var creationTime = DateTime.UtcNow.ToBinary();
|
||||
|
||||
memoryStream.Write(BitConverter.GetBytes(creationTime), 0, sizeof(long));
|
||||
responseStream.CopyTo(memoryStream);
|
||||
|
||||
buffer = length > 0 ? memoryStream.GetBuffer() : memoryStream.ToArray();
|
||||
}
|
||||
buffer = TileCache.CreateBuffer(responseStream, (int)response.ContentLength);
|
||||
}
|
||||
}
|
||||
catch (WebException ex)
|
||||
|
|
@ -346,5 +290,38 @@ namespace MapControl
|
|||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static class TileCache
|
||||
{
|
||||
private const int imageBufferOffset = sizeof(Int64);
|
||||
|
||||
public static string Key(string sourceName, Tile tile)
|
||||
{
|
||||
return string.Format("{0}/{1}/{2}/{3}", sourceName, tile.ZoomLevel, tile.XIndex, tile.Y);
|
||||
}
|
||||
|
||||
public static MemoryStream ImageStream(byte[] cacheBuffer)
|
||||
{
|
||||
return new MemoryStream(cacheBuffer, imageBufferOffset, cacheBuffer.Length - imageBufferOffset, false);
|
||||
}
|
||||
|
||||
public static DateTime CreationTime(byte[] cacheBuffer)
|
||||
{
|
||||
return DateTime.FromBinary(BitConverter.ToInt64(cacheBuffer, 0));
|
||||
}
|
||||
|
||||
public static byte[] CreateBuffer(Stream imageStream, int length)
|
||||
{
|
||||
var creationTime = BitConverter.GetBytes(DateTime.UtcNow.ToBinary());
|
||||
|
||||
using (var memoryStream = length > 0 ? new MemoryStream(length + imageBufferOffset) : new MemoryStream())
|
||||
{
|
||||
memoryStream.Write(creationTime, 0, imageBufferOffset);
|
||||
imageStream.CopyTo(memoryStream);
|
||||
|
||||
return length > 0 ? memoryStream.GetBuffer() : memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if NETFX_CORE
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class TileLayer : Panel
|
||||
{
|
||||
partial void Initialize()
|
||||
{
|
||||
RenderTransform = transform;
|
||||
}
|
||||
|
||||
private Panel TileContainer
|
||||
{
|
||||
get { return Parent as Panel; }
|
||||
}
|
||||
|
||||
private void RenderTiles()
|
||||
{
|
||||
Children.Clear();
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
Children.Add(tile.Image);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
tile.Image.Measure(availableSize);
|
||||
}
|
||||
|
||||
return new Size();
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
var tileSize = (double)(256 << (zoomLevel - tile.ZoomLevel));
|
||||
tile.Image.Width = tileSize;
|
||||
tile.Image.Height = tileSize;
|
||||
tile.Image.Arrange(new Rect(tileSize * tile.X - 256 * grid.X, tileSize * tile.Y - 256 * grid.Y, tileSize, tileSize));
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class TileLayer : DrawingVisual
|
||||
{
|
||||
partial void Initialize()
|
||||
{
|
||||
VisualTransform = transform;
|
||||
VisualEdgeMode = EdgeMode.Aliased;
|
||||
}
|
||||
|
||||
public Brush Background { get; set; }
|
||||
|
||||
private ContainerVisual TileContainer
|
||||
{
|
||||
get { return Parent as ContainerVisual; }
|
||||
}
|
||||
|
||||
private void RenderTiles()
|
||||
{
|
||||
using (var drawingContext = RenderOpen())
|
||||
{
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
var tileSize = TileSource.TileSize << (zoomLevel - tile.ZoomLevel);
|
||||
var tileRect = new Rect(
|
||||
tileSize * tile.X - TileSource.TileSize * grid.X,
|
||||
tileSize * tile.Y - TileSource.TileSize * grid.Y,
|
||||
tileSize, tileSize);
|
||||
|
||||
drawingContext.DrawRectangle(tile.Brush, null, tileRect);
|
||||
|
||||
//if (tile.ZoomLevel == zoomLevel)
|
||||
// drawingContext.DrawText(new FormattedText(string.Format("{0}-{1}-{2}", tile.ZoomLevel, tile.X, tile.Y),
|
||||
// System.Globalization.CultureInfo.InvariantCulture, FlowDirection.LeftToRight, new Typeface("Segoe UI"), 14, Brushes.Black), tileRect.TopLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml.Markup;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
|
|
@ -19,12 +20,12 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Fills a rectangular area with map tiles from a TileSource.
|
||||
/// </summary>
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
[ContentProperty(Name = "TileSource")]
|
||||
#else
|
||||
[ContentProperty("TileSource")]
|
||||
#endif
|
||||
public partial class TileLayer
|
||||
public class TileLayer : PanelBase
|
||||
{
|
||||
public static TileLayer Default
|
||||
{
|
||||
|
|
@ -39,7 +40,6 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
private readonly MatrixTransform transform = new MatrixTransform();
|
||||
private readonly TileImageLoader tileImageLoader = new TileImageLoader();
|
||||
private string description = string.Empty;
|
||||
private TileSource tileSource;
|
||||
|
|
@ -54,11 +54,8 @@ namespace MapControl
|
|||
MaxParallelDownloads = 8;
|
||||
LoadLowerZoomLevels = true;
|
||||
AnimateTileOpacity = true;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
partial void Initialize();
|
||||
|
||||
public string SourceName { get; set; }
|
||||
public int MinZoomLevel { get; set; }
|
||||
public int MaxZoomLevel { get; set; }
|
||||
|
|
@ -99,26 +96,14 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
public string TileSourceUriFormat
|
||||
{
|
||||
get { return tileSource != null ? tileSource.UriFormat : string.Empty; }
|
||||
set { TileSource = !string.IsNullOrWhiteSpace(value) ? new TileSource(value) : null; }
|
||||
}
|
||||
|
||||
internal void SetTransformMatrix(Matrix transformMatrix)
|
||||
{
|
||||
transform.Matrix = transformMatrix;
|
||||
}
|
||||
|
||||
internal void UpdateTiles(int zoomLevel, Int32Rect grid)
|
||||
{
|
||||
this.grid = grid;
|
||||
this.zoomLevel = zoomLevel;
|
||||
|
||||
tileImageLoader.CancelGetTiles();
|
||||
|
||||
if (tileSource != null)
|
||||
{
|
||||
tileImageLoader.CancelGetTiles();
|
||||
SelectTiles();
|
||||
RenderTiles();
|
||||
tileImageLoader.BeginGetTiles(this, tiles.Where(t => !t.HasImageSource));
|
||||
|
|
@ -136,9 +121,8 @@ namespace MapControl
|
|||
{
|
||||
var maxZoomLevel = Math.Min(zoomLevel, MaxZoomLevel);
|
||||
var minZoomLevel = maxZoomLevel;
|
||||
var container = TileContainer;
|
||||
|
||||
if (LoadLowerZoomLevels && container != null && container.Children.IndexOf(this) == 0)
|
||||
if (LoadLowerZoomLevels && Parent is TileContainer && ((TileContainer)Parent).TileLayers.FirstOrDefault() == this)
|
||||
{
|
||||
minZoomLevel = MinZoomLevel;
|
||||
}
|
||||
|
|
@ -164,12 +148,12 @@ namespace MapControl
|
|||
tile = new Tile(z, x, y);
|
||||
|
||||
var equivalentTile = tiles.FirstOrDefault(
|
||||
t => t.ImageSource != null && t.ZoomLevel == z && t.XIndex == tile.XIndex && t.Y == y);
|
||||
t => t.Image.Source != null && t.ZoomLevel == z && t.XIndex == tile.XIndex && t.Y == y);
|
||||
|
||||
if (equivalentTile != null)
|
||||
{
|
||||
// do not animate to avoid flicker when crossing date line
|
||||
tile.SetImageSource(equivalentTile.ImageSource, false);
|
||||
tile.SetImageSource(equivalentTile.Image.Source, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -180,5 +164,28 @@ namespace MapControl
|
|||
|
||||
tiles = newTiles;
|
||||
}
|
||||
|
||||
private void RenderTiles()
|
||||
{
|
||||
InternalChildren.Clear();
|
||||
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
InternalChildren.Add(tile.Image);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
var tileSize = (double)(256 << (zoomLevel - tile.ZoomLevel));
|
||||
tile.Image.Width = tileSize;
|
||||
tile.Image.Height = tileSize;
|
||||
tile.Image.Arrange(new Rect(tileSize * tile.X - 256 * grid.X, tileSize * tile.Y - 256 * grid.Y, tileSize, tileSize));
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.Foundation;
|
||||
#else
|
||||
using System.Windows;
|
||||
|
|
@ -94,7 +94,7 @@ namespace MapControl
|
|||
|
||||
private Uri GetBasicUri(int x, int y, int zoomLevel)
|
||||
{
|
||||
return new Uri(UriFormat.
|
||||
return new Uri(uriFormat.
|
||||
Replace("{x}", x.ToString()).
|
||||
Replace("{y}", y.ToString()).
|
||||
Replace("{z}", zoomLevel.ToString()));
|
||||
|
|
@ -104,7 +104,7 @@ namespace MapControl
|
|||
{
|
||||
var hostIndex = (x + y) % 3;
|
||||
|
||||
return new Uri(UriFormat.
|
||||
return new Uri(uriFormat.
|
||||
Replace("{c}", "abc".Substring(hostIndex, 1)).
|
||||
Replace("{x}", x.ToString()).
|
||||
Replace("{y}", y.ToString()).
|
||||
|
|
@ -115,7 +115,7 @@ namespace MapControl
|
|||
{
|
||||
var hostIndex = (x + y) % 4;
|
||||
|
||||
return new Uri(UriFormat.
|
||||
return new Uri(uriFormat.
|
||||
Replace("{i}", hostIndex.ToString()).
|
||||
Replace("{x}", x.ToString()).
|
||||
Replace("{y}", y.ToString()).
|
||||
|
|
@ -126,7 +126,7 @@ namespace MapControl
|
|||
{
|
||||
var hostIndex = (x + y) % 4 + 1;
|
||||
|
||||
return new Uri(UriFormat.
|
||||
return new Uri(uriFormat.
|
||||
Replace("{n}", hostIndex.ToString()).
|
||||
Replace("{x}", x.ToString()).
|
||||
Replace("{y}", y.ToString()).
|
||||
|
|
@ -137,7 +137,7 @@ namespace MapControl
|
|||
{
|
||||
y = (1 << zoomLevel) - 1 - y;
|
||||
|
||||
return new Uri(UriFormat.
|
||||
return new Uri(uriFormat.
|
||||
Replace("{x}", x.ToString()).
|
||||
Replace("{v}", y.ToString()).
|
||||
Replace("{z}", zoomLevel.ToString()));
|
||||
|
|
@ -157,7 +157,7 @@ namespace MapControl
|
|||
key[z] = (char)('0' + 2 * (y % 2) + (x % 2));
|
||||
}
|
||||
|
||||
return new Uri(UriFormat.
|
||||
return new Uri(uriFormat.
|
||||
Replace("{i}", key.ToString(key.Length - 1, 1)).
|
||||
Replace("{q}", key.ToString()));
|
||||
}
|
||||
|
|
@ -171,7 +171,7 @@ namespace MapControl
|
|||
var y1 = m * (180d - (double)(y + 1) * 360d / n);
|
||||
var y2 = m * (180d - (double)y * 360d / n);
|
||||
|
||||
return new Uri(UriFormat.
|
||||
return new Uri(uriFormat.
|
||||
Replace("{W}", x1.ToString(CultureInfo.InvariantCulture)).
|
||||
Replace("{S}", y1.ToString(CultureInfo.InvariantCulture)).
|
||||
Replace("{E}", x2.ToString(CultureInfo.InvariantCulture)).
|
||||
|
|
@ -189,7 +189,7 @@ namespace MapControl
|
|||
var p1 = t.Transform(new Point(x1, y1));
|
||||
var p2 = t.Transform(new Point(x2, y2));
|
||||
|
||||
return new Uri(UriFormat.
|
||||
return new Uri(uriFormat.
|
||||
Replace("{w}", p1.Longitude.ToString(CultureInfo.InvariantCulture)).
|
||||
Replace("{s}", p1.Latitude.ToString(CultureInfo.InvariantCulture)).
|
||||
Replace("{e}", p2.Longitude.ToString(CultureInfo.InvariantCulture)).
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
||||
// Copyright © 2014 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public static class TransformEx
|
||||
{
|
||||
public static Point Transform(this GeneralTransform transform, Point point)
|
||||
{
|
||||
return transform.TransformPoint(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,17 +13,17 @@
|
|||
<AssemblyName>MapControl.WinRT</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||
<TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
|
||||
<TargetPlatformVersion>8.1</TargetPlatformVersion>
|
||||
<TargetFrameworkProfile>Profile32</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;NETFX_CORE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;WINDOWS_RUNTIME</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
|
@ -31,16 +31,22 @@
|
|||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE</DefineConstants>
|
||||
<DefineConstants>TRACE;WINDOWS_RUNTIME</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\AnimationEx.WinRT.cs">
|
||||
<Link>AnimationEx.WinRT.cs</Link>
|
||||
<Compile Include="..\Extensions.Silverlight.WinRT.cs">
|
||||
<Link>Extensions.Silverlight.WinRT.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\ImageTileSource.cs">
|
||||
<Link>ImageTileSource.cs</Link>
|
||||
<Compile Include="..\Extensions.WinRT.cs">
|
||||
<Link>Extensions.WinRT.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\ImageTileSource.Silverlight.WinRT.cs">
|
||||
<Link>ImageTileSource.Silverlight.WinRT.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\IMapElement.cs">
|
||||
<Link>IMapElement.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Int32Rect.cs">
|
||||
<Link>Int32Rect.cs</Link>
|
||||
|
|
@ -81,6 +87,12 @@
|
|||
<Compile Include="..\MapItemsControl.Silverlight.WinRT.cs">
|
||||
<Link>MapItemsControl.Silverlight.WinRT.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MapOverlay.cs">
|
||||
<Link>MapOverlay.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MapOverlay.Silverlight.WinRT.cs">
|
||||
<Link>MapOverlay.Silverlight.WinRT.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MapPanel.cs">
|
||||
<Link>MapPanel.cs</Link>
|
||||
</Compile>
|
||||
|
|
@ -105,12 +117,12 @@
|
|||
<Compile Include="..\MapTransform.cs">
|
||||
<Link>MapTransform.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MatrixEx.cs">
|
||||
<Link>MatrixEx.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MercatorTransform.cs">
|
||||
<Link>MercatorTransform.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\PanelBase.cs">
|
||||
<Link>PanelBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Pushpin.Silverlight.WinRT.cs">
|
||||
<Link>Pushpin.Silverlight.WinRT.cs</Link>
|
||||
</Compile>
|
||||
|
|
@ -132,18 +144,12 @@
|
|||
<Compile Include="..\TileLayer.cs">
|
||||
<Link>TileLayer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\TileLayer.Silverlight.WinRT.cs">
|
||||
<Link>TileLayer.Silverlight.WinRT.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\TileLayerCollection.cs">
|
||||
<Link>TileLayerCollection.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\TileSource.cs">
|
||||
<Link>TileSource.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\TransformEx.WinRT.cs">
|
||||
<Link>TransformEx.WinRT.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
@ -157,6 +163,10 @@
|
|||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<TargetPlatform Include="Windows, Version=8.1" />
|
||||
<TargetPlatform Include="WindowsPhoneApp, Version=8.1" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
|
||||
<VisualStudioVersion>12.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
|
|
@ -169,7 +179,7 @@
|
|||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>..\..\MapControl.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ using System.Runtime.InteropServices;
|
|||
|
||||
[assembly: AssemblyTitle("XAML Map Control (WinRT)")]
|
||||
[assembly: AssemblyDescription("XAML Map Control Library for Windows Runtime")]
|
||||
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("1.12.1")]
|
||||
[assembly: AssemblyFileVersion("1.12.1")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
#if NETFX_CORE
|
||||
#if WINDOWS_RUNTIME
|
||||
using Windows.UI.Xaml;
|
||||
#else
|
||||
using System.Windows.Threading;
|
||||
|
|
@ -15,11 +15,12 @@ namespace ViewModel
|
|||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected void OnPropertyChanged(string propertyName)
|
||||
protected void RaisePropertyChanged(string propertyName)
|
||||
{
|
||||
if (PropertyChanged != null)
|
||||
var propertyChanged = PropertyChanged;
|
||||
if (propertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
||||
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +34,7 @@ namespace ViewModel
|
|||
set
|
||||
{
|
||||
name = value;
|
||||
OnPropertyChanged("Name");
|
||||
RaisePropertyChanged("Name");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +45,7 @@ namespace ViewModel
|
|||
set
|
||||
{
|
||||
location = value;
|
||||
OnPropertyChanged("Location");
|
||||
RaisePropertyChanged("Location");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -67,7 +68,7 @@ namespace ViewModel
|
|||
set
|
||||
{
|
||||
mapCenter = value;
|
||||
OnPropertyChanged("MapCenter");
|
||||
RaisePropertyChanged("MapCenter");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
7
SampleApps/PhoneApplication/App.xaml
Normal file
7
SampleApps/PhoneApplication/App.xaml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<Application
|
||||
x:Class="PhoneApplication.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:PhoneApplication">
|
||||
|
||||
</Application>
|
||||
131
SampleApps/PhoneApplication/App.xaml.cs
Normal file
131
SampleApps/PhoneApplication/App.xaml.cs
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=391641
|
||||
|
||||
namespace PhoneApplication
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
public sealed partial class App : Application
|
||||
{
|
||||
private TransitionCollection transitions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.Suspending += this.OnSuspending;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the application is launched normally by the end user. Other entry points
|
||||
/// will be used when the application is launched to open a specific file, to display
|
||||
/// search results, and so forth.
|
||||
/// </summary>
|
||||
/// <param name="e">Details about the launch request and process.</param>
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs e)
|
||||
{
|
||||
#if DEBUG
|
||||
if (System.Diagnostics.Debugger.IsAttached)
|
||||
{
|
||||
this.DebugSettings.EnableFrameRateCounter = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
Frame rootFrame = Window.Current.Content as Frame;
|
||||
|
||||
// Do not repeat app initialization when the Window already has content,
|
||||
// just ensure that the window is active
|
||||
if (rootFrame == null)
|
||||
{
|
||||
// Create a Frame to act as the navigation context and navigate to the first page
|
||||
rootFrame = new Frame();
|
||||
|
||||
// TODO: change this value to a cache size that is appropriate for your application
|
||||
rootFrame.CacheSize = 1;
|
||||
|
||||
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
|
||||
{
|
||||
// TODO: Load state from previously suspended application
|
||||
}
|
||||
|
||||
// Place the frame in the current Window
|
||||
Window.Current.Content = rootFrame;
|
||||
}
|
||||
|
||||
if (rootFrame.Content == null)
|
||||
{
|
||||
// Removes the turnstile navigation for startup.
|
||||
if (rootFrame.ContentTransitions != null)
|
||||
{
|
||||
this.transitions = new TransitionCollection();
|
||||
foreach (var c in rootFrame.ContentTransitions)
|
||||
{
|
||||
this.transitions.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
rootFrame.ContentTransitions = null;
|
||||
rootFrame.Navigated += this.RootFrame_FirstNavigated;
|
||||
|
||||
// When the navigation stack isn't restored navigate to the first page,
|
||||
// configuring the new page by passing required information as a navigation
|
||||
// parameter
|
||||
if (!rootFrame.Navigate(typeof(MainPage), e.Arguments))
|
||||
{
|
||||
throw new Exception("Failed to create initial page");
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the current window is active
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores the content transitions after the app has launched.
|
||||
/// </summary>
|
||||
/// <param name="sender">The object where the handler is attached.</param>
|
||||
/// <param name="e">Details about the navigation event.</param>
|
||||
private void RootFrame_FirstNavigated(object sender, NavigationEventArgs e)
|
||||
{
|
||||
var rootFrame = sender as Frame;
|
||||
rootFrame.ContentTransitions = this.transitions ?? new TransitionCollection() { new NavigationThemeTransition() };
|
||||
rootFrame.Navigated -= this.RootFrame_FirstNavigated;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when application execution is being suspended. Application state is saved
|
||||
/// without knowing whether the application will be terminated or resumed with the contents
|
||||
/// of memory still intact.
|
||||
/// </summary>
|
||||
/// <param name="sender">The source of the suspend request.</param>
|
||||
/// <param name="e">Details about the suspend request.</param>
|
||||
private void OnSuspending(object sender, SuspendingEventArgs e)
|
||||
{
|
||||
var deferral = e.SuspendingOperation.GetDeferral();
|
||||
|
||||
// TODO: Save application state and stop any background activity
|
||||
deferral.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
SampleApps/PhoneApplication/Assets/Logo.scale-240.png
Normal file
BIN
SampleApps/PhoneApplication/Assets/Logo.scale-240.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
BIN
SampleApps/PhoneApplication/Assets/SmallLogo.scale-240.png
Normal file
BIN
SampleApps/PhoneApplication/Assets/SmallLogo.scale-240.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 753 B |
BIN
SampleApps/PhoneApplication/Assets/SplashScreen.scale-240.png
Normal file
BIN
SampleApps/PhoneApplication/Assets/SplashScreen.scale-240.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
SampleApps/PhoneApplication/Assets/Square71x71Logo.scale-240.png
Normal file
BIN
SampleApps/PhoneApplication/Assets/Square71x71Logo.scale-240.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
SampleApps/PhoneApplication/Assets/StoreLogo.scale-240.png
Normal file
BIN
SampleApps/PhoneApplication/Assets/StoreLogo.scale-240.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
SampleApps/PhoneApplication/Assets/WideLogo.scale-240.png
Normal file
BIN
SampleApps/PhoneApplication/Assets/WideLogo.scale-240.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
116
SampleApps/PhoneApplication/MainPage.xaml
Normal file
116
SampleApps/PhoneApplication/MainPage.xaml
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
<Page
|
||||
x:Class="PhoneApplication.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:map="using:MapControl"
|
||||
xmlns:local="using:PhoneApplication"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Page.Resources>
|
||||
<map:TileLayerCollection x:Key="TileLayers">
|
||||
<map:TileLayer SourceName="OpenStreetMap" Description="© {y} OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:TileSource UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="OpenCycleMap" Description="OpenCycleMap - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:TileSource UriFormat="http://{c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="OCM Transport" Description="OpenCycleMap Transport - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:TileSource UriFormat="http://{c}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="OCM Landscape" Description="OpenCycleMap Landscape - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:TileSource UriFormat="http://{c}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="MapQuest OSM" Description="MapQuest OSM - © {y} MapQuest & OpenStreetMap Contributors">
|
||||
<map:TileSource UriFormat="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="Google Maps" Description="Google Maps - © {y} Google" MaxZoomLevel="20">
|
||||
<map:TileSource UriFormat="http://mt{i}.google.com/vt/x={x}&y={y}&z={z}"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="Bing Maps" Description="Bing Maps - © {y} Microsoft Corporation" MinZoomLevel="1" MaxZoomLevel="19">
|
||||
<map:TileSource UriFormat="http://ecn.t{i}.tiles.virtualearth.net/tiles/r{q}.png?g=0&stl=h"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="Seamarks" Description="© {y} OpenSeaMap Contributors, CC-BY-SA" MinZoomLevel="10" MaxZoomLevel="18">
|
||||
<map:TileSource UriFormat="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
</map:TileLayerCollection>
|
||||
<local:ObjectReferenceConverter x:Key="ObjectReferenceConverter"/>
|
||||
</Page.Resources>
|
||||
<Grid>
|
||||
<map:MapBase x:Name="map" ZoomLevel="11"
|
||||
ManipulationMode="Scale,TranslateX,TranslateY,TranslateInertia"
|
||||
ManipulationStarted="MapManipulationStarted"
|
||||
ManipulationCompleted="MapManipulationCompleted"
|
||||
ManipulationDelta="MapManipulationDelta">
|
||||
<map:MapBase.Center>
|
||||
<map:Location Latitude="53.5" Longitude="8.2"/>
|
||||
</map:MapBase.Center>
|
||||
<map:MapGraticule Opacity="0.6"/>
|
||||
|
||||
<Canvas map:MapPanel.Location="{Binding Location}"
|
||||
Visibility="{Binding Location, Converter={StaticResource ObjectReferenceConverter}}">
|
||||
<Path Fill="{StaticResource PhoneAccentBrush}" Opacity="0.2">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="{Binding Accuracy}" RadiusY="{Binding Accuracy}"
|
||||
Transform="{Binding ScaleTransform, ElementName=map}"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path Fill="{StaticResource PhoneAccentBrush}">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="10" RadiusY="10"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path Stroke="White" StrokeThickness="3">
|
||||
<Path.Data>
|
||||
<EllipseGeometry RadiusX="6" RadiusY="6"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
</Canvas>
|
||||
</map:MapBase>
|
||||
</Grid>
|
||||
<Page.BottomAppBar>
|
||||
<CommandBar>
|
||||
<AppBarButton Label="Map">
|
||||
<AppBarButton.Icon>
|
||||
<PathIcon Width="40" Height="40">
|
||||
<PathIcon.Data>
|
||||
<GeometryGroup>
|
||||
<RectangleGeometry Rect="10,10,9,9"/>
|
||||
<RectangleGeometry Rect="21,10,9,9"/>
|
||||
<RectangleGeometry Rect="10,21,9,9"/>
|
||||
<RectangleGeometry Rect="21,21,9,9"/>
|
||||
</GeometryGroup>
|
||||
</PathIcon.Data>
|
||||
</PathIcon>
|
||||
</AppBarButton.Icon>
|
||||
<AppBarButton.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem Text="OpenStreetMap" Click="MapMenuItemClick"/>
|
||||
<MenuFlyoutItem Text="OpenCycleMap" Click="MapMenuItemClick"/>
|
||||
<MenuFlyoutItem Text="OCM Transport" Click="MapMenuItemClick"/>
|
||||
<MenuFlyoutItem Text="OCM Landscape" Click="MapMenuItemClick"/>
|
||||
<MenuFlyoutItem Text="MapQuest OSM" Click="MapMenuItemClick"/>
|
||||
<!--<MenuFlyoutItem Text="Google Maps" Click="MapMenuItemClick"/>
|
||||
<MenuFlyoutItem Text="Bing Maps" Click="MapMenuItemClick"/>-->
|
||||
</MenuFlyout>
|
||||
</AppBarButton.Flyout>
|
||||
</AppBarButton>
|
||||
<AppBarToggleButton Label="Seamarks" Checked="SeamarksChecked" Unchecked="SeamarksUnchecked">
|
||||
<AppBarToggleButton.Icon>
|
||||
<PathIcon Width="40" Height="40" Data="M20,15 l5,-6 -10,0Z M20,15 l5,6 -10,0Z M21.5,23 l0,10 -3,0 0,-10Z"/>
|
||||
</AppBarToggleButton.Icon>
|
||||
</AppBarToggleButton>
|
||||
<AppBarButton Label="Center" Click="CenterButtonClick"
|
||||
IsEnabled="{Binding Location, Converter={StaticResource ObjectReferenceConverter}}">
|
||||
<AppBarButton.Icon>
|
||||
<PathIcon Width="40" Height="40">
|
||||
<PathIcon.Data>
|
||||
<GeometryGroup>
|
||||
<EllipseGeometry Center="20,20" RadiusX="10" RadiusY="10"/>
|
||||
<EllipseGeometry Center="20,20" RadiusX="6" RadiusY="6"/>
|
||||
</GeometryGroup>
|
||||
</PathIcon.Data>
|
||||
</PathIcon>
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
</CommandBar>
|
||||
</Page.BottomAppBar>
|
||||
</Page>
|
||||
87
SampleApps/PhoneApplication/MainPage.xaml.cs
Normal file
87
SampleApps/PhoneApplication/MainPage.xaml.cs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
using System;
|
||||
using MapControl;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace PhoneApplication
|
||||
{
|
||||
public sealed partial class MainPage : Page
|
||||
{
|
||||
private bool manipulationActive;
|
||||
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new ViewModel(Dispatcher);
|
||||
NavigationCacheMode = NavigationCacheMode.Required;
|
||||
}
|
||||
|
||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||
map.TileLayers.Add((TileLayer)tileLayers["Seamarks"]);
|
||||
}
|
||||
|
||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||
map.TileLayers.Remove((TileLayer)tileLayers["Seamarks"]);
|
||||
}
|
||||
|
||||
private void MapMenuItemClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var selectedValue = ((MenuFlyoutItem)sender).Text;
|
||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||
map.TileLayer = tileLayers[selectedValue];
|
||||
}
|
||||
|
||||
private void CenterButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
manipulationActive = false;
|
||||
map.TargetCenter = ((ViewModel)DataContext).Location;
|
||||
}
|
||||
|
||||
private void MapManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
|
||||
{
|
||||
manipulationActive = true;
|
||||
}
|
||||
|
||||
private void MapManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
|
||||
{
|
||||
manipulationActive = false;
|
||||
}
|
||||
|
||||
private void MapManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
|
||||
{
|
||||
if (manipulationActive)
|
||||
{
|
||||
map.TransformMap(e.Position, e.Delta.Translation, e.Delta.Rotation, e.Delta.Scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ObjectReferenceConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (targetType == typeof(Visibility))
|
||||
{
|
||||
return value != null ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
return value != null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
30
SampleApps/PhoneApplication/Package.appxmanifest
Normal file
30
SampleApps/PhoneApplication/Package.appxmanifest
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest" xmlns:m3="http://schemas.microsoft.com/appx/2014/manifest" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
|
||||
<Identity Name="45fd5832-8021-45d0-909e-dd7af206f388" Publisher="CN=Clemens" Version="1.0.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="45fd5832-8021-45d0-909e-dd7af206f388" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>PhoneApplication</DisplayName>
|
||||
<PublisherDisplayName>Clemens</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
<Prerequisites>
|
||||
<OSMinVersion>6.3.1</OSMinVersion>
|
||||
<OSMaxVersionTested>6.3.1</OSMaxVersionTested>
|
||||
</Prerequisites>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="PhoneApplication.App">
|
||||
<m3:VisualElements DisplayName="PhoneApplication" Square150x150Logo="Assets\Logo.png" Square44x44Logo="Assets\SmallLogo.png" Description="PhoneApplication" ForegroundText="light" BackgroundColor="transparent">
|
||||
<m3:DefaultTile Wide310x150Logo="Assets\WideLogo.png" Square71x71Logo="Assets\Square71x71Logo.png">
|
||||
</m3:DefaultTile>
|
||||
<m3:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
</m3:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
<Capabilities>
|
||||
<Capability Name="internetClientServer" />
|
||||
<DeviceCapability Name="location" />
|
||||
</Capabilities>
|
||||
</Package>
|
||||
135
SampleApps/PhoneApplication/PhoneApplication.csproj
Normal file
135
SampleApps/PhoneApplication/PhoneApplication.csproj
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}</ProjectGuid>
|
||||
<OutputType>AppContainerExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PhoneApplication</RootNamespace>
|
||||
<AssemblyName>PhoneApplication</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<TargetPlatformVersion>8.1</TargetPlatformVersion>
|
||||
<MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{76F1466A-8B6D-4E39-A767-685A06062A39};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\ARM\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>ARM</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
|
||||
<OutputPath>bin\ARM\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>ARM</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_PHONE_APP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
|
||||
<ProjectReference Include="..\..\MapControl\WinRT\MapControl.WinRT.csproj">
|
||||
<Project>{63cefdf7-5170-43b6-86f8-5c4a383a1615}</Project>
|
||||
<Name>MapControl.WinRT</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MainPage.xaml.cs">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ViewModel.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Package.appxmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</AppxManifest>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\Logo.scale-240.png" />
|
||||
<Content Include="Assets\SmallLogo.scale-240.png" />
|
||||
<Content Include="Assets\SplashScreen.scale-240.png" />
|
||||
<Content Include="Assets\Square71x71Logo.scale-240.png" />
|
||||
<Content Include="Assets\StoreLogo.scale-240.png" />
|
||||
<Content Include="Assets\WideLogo.scale-240.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="MainPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
|
||||
<VisualStudioVersion>12.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetPlatformIdentifier)' == '' ">
|
||||
<TargetPlatformIdentifier>WindowsPhoneApp</TargetPlatformIdentifier>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
9
SampleApps/PhoneApplication/PhoneApplication.csproj.user
Normal file
9
SampleApps/PhoneApplication/PhoneApplication.csproj.user
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<DeviceId>30F105C9-681E-420b-A277-7C086EAD8A4E</DeviceId>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<DeviceId>30F105C9-681E-420b-A277-7C086EAD8A4E</DeviceId>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
14
SampleApps/PhoneApplication/Properties/AssemblyInfo.cs
Normal file
14
SampleApps/PhoneApplication/Properties/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("Windows Phone Sample Application")]
|
||||
[assembly: AssemblyDescription("XAML Map Control Windows Phone Sample Application")]
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
84
SampleApps/PhoneApplication/ViewModel.cs
Normal file
84
SampleApps/PhoneApplication/ViewModel.cs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using MapControl;
|
||||
using Windows.Devices.Geolocation;
|
||||
using Windows.UI.Core;
|
||||
|
||||
namespace PhoneApplication
|
||||
{
|
||||
public class ViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private readonly CoreDispatcher dispatcher;
|
||||
private readonly Geolocator geoLocator;
|
||||
private double accuracy;
|
||||
private Location location;
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public ViewModel(CoreDispatcher dispatcher)
|
||||
{
|
||||
this.dispatcher = dispatcher;
|
||||
|
||||
geoLocator = new Geolocator
|
||||
{
|
||||
DesiredAccuracy = PositionAccuracy.High,
|
||||
MovementThreshold = 1d
|
||||
};
|
||||
|
||||
geoLocator.StatusChanged += GeoLocatorStatusChanged;
|
||||
geoLocator.PositionChanged += GeoLocatorPositionChanged;
|
||||
}
|
||||
|
||||
public double Accuracy
|
||||
{
|
||||
get { return accuracy; }
|
||||
private set
|
||||
{
|
||||
accuracy = value;
|
||||
RaisePropertyChanged("Accuracy");
|
||||
}
|
||||
}
|
||||
|
||||
public Location Location
|
||||
{
|
||||
get { return location; }
|
||||
private set
|
||||
{
|
||||
location = value;
|
||||
RaisePropertyChanged("Location");
|
||||
}
|
||||
}
|
||||
|
||||
private void RaisePropertyChanged(string propertyName)
|
||||
{
|
||||
var propertyChanged = PropertyChanged;
|
||||
if (propertyChanged != null)
|
||||
{
|
||||
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
private async void GeoLocatorStatusChanged(Geolocator sender, StatusChangedEventArgs args)
|
||||
{
|
||||
if (args.Status != PositionStatus.Initializing &&
|
||||
args.Status != PositionStatus.Ready)
|
||||
{
|
||||
await dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
|
||||
{
|
||||
Location = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async void GeoLocatorPositionChanged(Geolocator sender, PositionChangedEventArgs args)
|
||||
{
|
||||
await dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
|
||||
{
|
||||
Accuracy = args.Position.Coordinate.Accuracy;
|
||||
Location = new Location(
|
||||
args.Position.Coordinate.Point.Position.Latitude,
|
||||
args.Position.Coordinate.Point.Position.Longitude);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,13 +3,12 @@ using System.Runtime.InteropServices;
|
|||
|
||||
[assembly: AssemblyTitle("Silverlight/Web Sample Application")]
|
||||
[assembly: AssemblyDescription("XAML Map Control Silverlight/Web Sample Application")]
|
||||
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("1.12.1")]
|
||||
[assembly: AssemblyFileVersion("1.12.1")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ using System.Runtime.InteropServices;
|
|||
|
||||
[assembly: AssemblyTitle("Silverlight Sample Application")]
|
||||
[assembly: AssemblyDescription("XAML Map Control Silverlight Sample Application")]
|
||||
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("1.12.1")]
|
||||
[assembly: AssemblyFileVersion("1.12.1")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -2,26 +2,29 @@
|
|||
x:Class="StoreApplication.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:map="using:MapControl"
|
||||
xmlns:vm="using:ViewModel"
|
||||
xmlns:local="using:StoreApplication"
|
||||
mc:Ignorable="d">
|
||||
xmlns:local="using:StoreApplication">
|
||||
<Page.Resources>
|
||||
<map:TileLayerCollection x:Key="TileLayers">
|
||||
<map:TileLayer SourceName="OpenStreetMap" Description="© {y} OpenStreetMap Contributors, CC-BY-SA"
|
||||
TileSourceUriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
||||
<map:TileLayer SourceName="OpenCycleMap" Description="OpenCycleMap - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA"
|
||||
TileSourceUriFormat="http://{c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png"/>
|
||||
<map:TileLayer SourceName="OCM Transport" Description="OpenCycleMap Transport - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA"
|
||||
TileSourceUriFormat="http://{c}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png"/>
|
||||
<map:TileLayer SourceName="OCM Landscape" Description="OpenCycleMap Landscape - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA"
|
||||
TileSourceUriFormat="http://{c}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png"/>
|
||||
<map:TileLayer SourceName="MapQuest OSM" Description="MapQuest OSM - © {y} MapQuest & OpenStreetMap Contributors"
|
||||
TileSourceUriFormat="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
||||
<map:TileLayer SourceName="Seamarks" Description="© {y} OpenSeaMap Contributors, CC-BY-SA"
|
||||
TileSourceUriFormat="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png" MinZoomLevel="10" MaxZoomLevel="18"/>
|
||||
<map:TileLayer SourceName="OpenStreetMap" Description="© {y} OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:TileSource UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="OpenCycleMap" Description="OpenCycleMap - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:TileSource UriFormat="http://{c}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="OCM Transport" Description="OpenCycleMap Transport - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:TileSource UriFormat="http://{c}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="OCM Landscape" Description="OpenCycleMap Landscape - © {y} Andy Allen & OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:TileSource UriFormat="http://{c}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="MapQuest OSM" Description="MapQuest OSM - © {y} MapQuest & OpenStreetMap Contributors">
|
||||
<map:TileSource UriFormat="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
<map:TileLayer SourceName="Seamarks" Description="© {y} OpenSeaMap Contributors, CC-BY-SA" MinZoomLevel="10" MaxZoomLevel="18">
|
||||
<map:TileSource UriFormat="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>
|
||||
</map:TileLayerCollection>
|
||||
<DataTemplate x:Key="PolylineItemTemplate">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
|
|
@ -180,7 +183,8 @@
|
|||
<Slider Margin="10,-10,10,-10" Width="200" Value="50" ValueChanged="ImageOpacitySliderValueChanged"/>
|
||||
</StackPanel>
|
||||
<CheckBox Margin="10" VerticalAlignment="Center" Content="Seamarks" Checked="SeamarksChecked" Unchecked="SeamarksUnchecked"/>
|
||||
<ComboBox x:Name="tileLayerComboBox" Margin="10" Width="200" VerticalAlignment="Center" SelectionChanged="TileLayerSelectionChanged">
|
||||
<ComboBox Margin="10" Width="200" VerticalAlignment="Center" SelectedValuePath="Content"
|
||||
Loaded="TileLayerComboBoxLoaded" SelectionChanged="TileLayerSelectionChanged">
|
||||
<ComboBoxItem>OpenStreetMap</ComboBoxItem>
|
||||
<ComboBoxItem>OpenCycleMap</ComboBoxItem>
|
||||
<ComboBoxItem>OCM Transport</ComboBoxItem>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ namespace StoreApplication
|
|||
public MainPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
tileLayerComboBox.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
private void ImageOpacitySliderValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
||||
|
|
@ -21,21 +20,28 @@ namespace StoreApplication
|
|||
}
|
||||
}
|
||||
|
||||
private void TileLayerComboBoxLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
((ComboBox)sender).SelectedIndex = 0;
|
||||
}
|
||||
|
||||
private void TileLayerSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
var comboBox = (ComboBox)sender;
|
||||
var selectedValue = (string)((ComboBox)sender).SelectedValue;
|
||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||
map.TileLayer = tileLayers[(string)((ComboBoxItem)comboBox.SelectedItem).Content];
|
||||
map.TileLayer = tileLayers[selectedValue];
|
||||
}
|
||||
|
||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
map.TileLayers.Add((TileLayer)((TileLayerCollection)Resources["TileLayers"])["Seamarks"]);
|
||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||
map.TileLayers.Add((TileLayer)tileLayers["Seamarks"]);
|
||||
}
|
||||
|
||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
map.TileLayers.Remove((TileLayer)((TileLayerCollection)Resources["TileLayers"])["Seamarks"]);
|
||||
var tileLayers = (TileLayerCollection)Resources["TileLayers"];
|
||||
map.TileLayers.Remove((TileLayer)tileLayers["Seamarks"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ using System.Runtime.InteropServices;
|
|||
|
||||
[assembly: AssemblyTitle("Windows Runtime Sample Application")]
|
||||
[assembly: AssemblyDescription("XAML Map Control Windows Runtime Sample Application")]
|
||||
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("1.12.1")]
|
||||
[assembly: AssemblyFileVersion("1.12.1")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;WINDOWS_RUNTIME</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE</DefineConstants>
|
||||
<DefineConstants>TRACE;WINDOWS_RUNTIME</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("1.12.1")]
|
||||
[assembly: AssemblyFileVersion("1.12.1")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
<!-- The following TileLayer uses an ImageTileSource, which bypasses caching of map tile images -->
|
||||
<!--<map:TileLayer SourceName="OSM Uncached" Description="© {y} OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:ImageTileSource UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
||||
<map:ImageTileSource IsAsync="True" UriFormat="http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
|
||||
</map:TileLayer>-->
|
||||
|
||||
<!-- The following TileLayer demonstrates how to access local tile image files (from ImageFileCache here) -->
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ using System.Runtime.InteropServices;
|
|||
|
||||
[assembly: AssemblyTitle("WPF Sample Application")]
|
||||
[assembly: AssemblyDescription("XAML Map Control WPF Sample Application")]
|
||||
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("1.12.1")]
|
||||
[assembly: AssemblyFileVersion("1.12.1")]
|
||||
[assembly: AssemblyVersion("2.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
Loading…
Reference in a new issue