diff --git a/Caching/FileDbCache/Properties/AssemblyInfo.cs b/Caching/FileDbCache/Properties/AssemblyInfo.cs
index 402ea30f..b341c093 100644
--- a/Caching/FileDbCache/Properties/AssemblyInfo.cs
+++ b/Caching/FileDbCache/Properties/AssemblyInfo.cs
@@ -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)]
diff --git a/Caching/ImageFileCache/Properties/AssemblyInfo.cs b/Caching/ImageFileCache/Properties/AssemblyInfo.cs
index ce0663f6..a43f045b 100644
--- a/Caching/ImageFileCache/Properties/AssemblyInfo.cs
+++ b/Caching/ImageFileCache/Properties/AssemblyInfo.cs
@@ -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)]
diff --git a/MapControl.sln b/MapControl.sln
index af9fb9bf..28867e55 100644
--- a/MapControl.sln
+++ b/MapControl.sln
@@ -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
diff --git a/MapControl/MatrixEx.cs b/MapControl/Extensions.Silverlight.WinRT.cs
similarity index 94%
rename from MapControl/MatrixEx.cs
rename to MapControl/Extensions.Silverlight.WinRT.cs
index 6a3ac5a3..5ba06a01 100644
--- a/MapControl/MatrixEx.cs
+++ b/MapControl/Extensions.Silverlight.WinRT.cs
@@ -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,
diff --git a/MapControl/AnimationEx.Silverlight.cs b/MapControl/Extensions.Silverlight.cs
similarity index 93%
rename from MapControl/AnimationEx.Silverlight.cs
rename to MapControl/Extensions.Silverlight.cs
index ed662105..d3475f7b 100644
--- a/MapControl/AnimationEx.Silverlight.cs
+++ b/MapControl/Extensions.Silverlight.cs
@@ -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)
{
diff --git a/MapControl/AnimationEx.WinRT.cs b/MapControl/Extensions.WinRT.cs
similarity index 86%
rename from MapControl/AnimationEx.WinRT.cs
rename to MapControl/Extensions.WinRT.cs
index 25939843..db7cefbf 100644
--- a/MapControl/AnimationEx.WinRT.cs
+++ b/MapControl/Extensions.WinRT.cs
@@ -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;
diff --git a/MapControl/GlyphRunText.cs b/MapControl/GlyphRunText.cs
index 04b9de2b..ec04a8a9 100644
--- a/MapControl/GlyphRunText.cs
+++ b/MapControl/GlyphRunText.cs
@@ -13,7 +13,7 @@ namespace MapControl
///
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();
}
}
}
diff --git a/MapControl/MapImage.WPF.cs b/MapControl/IMapElement.cs
similarity index 62%
rename from MapControl/MapImage.WPF.cs
rename to MapControl/IMapElement.cs
index 28f23574..33faaa3b 100644
--- a/MapControl/MapImage.WPF.cs
+++ b/MapControl/IMapElement.cs
@@ -4,11 +4,8 @@
namespace MapControl
{
- public partial class MapImage
+ public interface IMapElement
{
- static MapImage()
- {
- imageTransform.Freeze();
- }
+ MapBase ParentMap { get; set; }
}
}
diff --git a/MapControl/ImageTileSource.cs b/MapControl/ImageTileSource.Silverlight.WinRT.cs
similarity index 68%
rename from MapControl/ImageTileSource.cs
rename to MapControl/ImageTileSource.Silverlight.WinRT.cs
index e4ff935a..8c7cfcc9 100644
--- a/MapControl/ImageTileSource.cs
+++ b/MapControl/ImageTileSource.Silverlight.WinRT.cs
@@ -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
{
///
- /// 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.
///
- public partial class ImageTileSource : TileSource
+ public class ImageTileSource : TileSource
{
public virtual ImageSource LoadImage(int x, int y, int zoomLevel)
{
diff --git a/MapControl/ImageTileSource.WPF.cs b/MapControl/ImageTileSource.WPF.cs
index f9aafcd9..2af21f5b 100644
--- a/MapControl/ImageTileSource.WPF.cs
+++ b/MapControl/ImageTileSource.WPF.cs
@@ -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
+ ///
+ /// 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.
+ ///
+ 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;
}
}
}
diff --git a/MapControl/Location.cs b/MapControl/Location.cs
index 89286a46..47f38fb9 100644
--- a/MapControl/Location.cs
+++ b/MapControl/Location.cs
@@ -10,9 +10,6 @@ namespace MapControl
///
/// A geographic location with latitude and longitude values in degrees.
///
-#if !SILVERLIGHT && !NETFX_CORE
- [Serializable]
-#endif
public partial class Location
{
private double latitude;
diff --git a/MapControl/LocationConverter.cs b/MapControl/LocationConverter.cs
index 1c9c8bde..e8f48463 100644
--- a/MapControl/LocationConverter.cs
+++ b/MapControl/LocationConverter.cs
@@ -22,6 +22,9 @@ namespace MapControl
}
[TypeConverter(typeof(LocationConverter))]
+#if !SILVERLIGHT
+ [Serializable]
+#endif
public partial class Location
{
}
diff --git a/MapControl/Map.WinRT.cs b/MapControl/Map.WinRT.cs
index e0f93aa5..bf163201 100644
--- a/MapControl/Map.WinRT.cs
+++ b/MapControl/Map.WinRT.cs
@@ -21,7 +21,7 @@ namespace MapControl
public Map()
{
- ManipulationMode = ManipulationModes.Scale | ManipulationModes.ScaleInertia |
+ ManipulationMode = ManipulationModes.Scale |
ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.TranslateInertia;
ManipulationDelta += OnManipulationDelta;
diff --git a/MapControl/MapBase.Silverlight.WinRT.cs b/MapControl/MapBase.Silverlight.WinRT.cs
index 0877bb12..d1b207a0 100644
--- a/MapControl/MapBase.Silverlight.WinRT.cs
+++ b/MapControl/MapBase.Silverlight.WinRT.cs
@@ -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;
}
diff --git a/MapControl/MapBase.WPF.cs b/MapControl/MapBase.WPF.cs
index 20bbc897..8f03fc95 100644
--- a/MapControl/MapBase.WPF.cs
+++ b/MapControl/MapBase.WPF.cs
@@ -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);
diff --git a/MapControl/MapBase.cs b/MapControl/MapBase.cs
index dd65cbe7..de840b01 100644
--- a/MapControl/MapBase.cs
+++ b/MapControl/MapBase.cs
@@ -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;
diff --git a/MapControl/MapControl.Silverlight.csproj b/MapControl/MapControl.Silverlight.csproj
index 23e1528e..864aa374 100644
--- a/MapControl/MapControl.Silverlight.csproj
+++ b/MapControl/MapControl.Silverlight.csproj
@@ -67,8 +67,12 @@
-
-
+
+
+
+ Code
+
+
@@ -84,6 +88,8 @@
+
+
@@ -92,8 +98,8 @@
-
+
@@ -102,7 +108,6 @@
-
diff --git a/MapControl/MapControl.WPF.csproj b/MapControl/MapControl.WPF.csproj
index 0a1165ba..d24d60a8 100644
--- a/MapControl/MapControl.WPF.csproj
+++ b/MapControl/MapControl.WPF.csproj
@@ -52,8 +52,8 @@
-
+
@@ -64,20 +64,20 @@
-
+
+
-
@@ -89,7 +89,6 @@
-
diff --git a/MapControl/MapGraticule.Silverlight.WinRT.cs b/MapControl/MapGraticule.Silverlight.WinRT.cs
index 546c5933..8ae43dd2 100644
--- a/MapControl/MapGraticule.Silverlight.WinRT.cs
+++ b/MapControl/MapGraticule.Silverlight.WinRT.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((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((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();
diff --git a/MapControl/MapGraticule.WPF.cs b/MapControl/MapGraticule.WPF.cs
index 9da38a78..8111b850 100644
--- a/MapControl/MapGraticule.WPF.cs
+++ b/MapControl/MapGraticule.WPF.cs
@@ -10,7 +10,7 @@ using System.Windows.Media;
namespace MapControl
{
- public partial class MapGraticule : MapOverlay
+ public partial class MapGraticule
{
private class Label
{
diff --git a/MapControl/MapGraticule.cs b/MapControl/MapGraticule.cs
index 3a3808f6..c5003d9a 100644
--- a/MapControl/MapGraticule.cs
+++ b/MapControl/MapGraticule.cs
@@ -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
///
/// Draws a graticule overlay.
///
- public partial class MapGraticule
+ public partial class MapGraticule : MapOverlay
{
///
/// Graticule line spacings in degrees.
diff --git a/MapControl/MapImage.cs b/MapControl/MapImage.cs
index 74e9fd6c..b890f429 100644
--- a/MapControl/MapImage.cs
+++ b/MapControl/MapImage.cs
@@ -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
///
/// Fills a rectangular area with an ImageBrush from the Source property.
///
- 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;
}
}
}
diff --git a/MapControl/MapImageLayer.Silverlight.WinRT.cs b/MapControl/MapImageLayer.Silverlight.WinRT.cs
index d697ba6a..3dde5f53 100644
--- a/MapControl/MapImageLayer.Silverlight.WinRT.cs
+++ b/MapControl/MapImageLayer.Silverlight.WinRT.cs
@@ -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
diff --git a/MapControl/MapImageLayer.cs b/MapControl/MapImageLayer.cs
index 9aa5bc97..e17fd437 100644
--- a/MapControl/MapImageLayer.cs
+++ b/MapControl/MapImageLayer.cs
@@ -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
diff --git a/MapControl/MapItem.Silverlight.WinRT.cs b/MapControl/MapItem.Silverlight.WinRT.cs
index c4edc04f..13faa675 100644
--- a/MapControl/MapItem.Silverlight.WinRT.cs
+++ b/MapControl/MapItem.Silverlight.WinRT.cs
@@ -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;
diff --git a/MapControl/MapItemsControl.Silverlight.WinRT.cs b/MapControl/MapItemsControl.Silverlight.WinRT.cs
index 1787444c..f9cade87 100644
--- a/MapControl/MapItemsControl.Silverlight.WinRT.cs
+++ b/MapControl/MapItemsControl.Silverlight.WinRT.cs
@@ -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
diff --git a/MapControl/MapOverlay.Silverlight.WinRT.cs b/MapControl/MapOverlay.Silverlight.WinRT.cs
new file mode 100644
index 00000000..aeed4db4
--- /dev/null
+++ b/MapControl/MapOverlay.Silverlight.WinRT.cs
@@ -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;
+ }
+ }
+ }
+}
diff --git a/MapControl/MapOverlay.WPF.cs b/MapControl/MapOverlay.WPF.cs
new file mode 100644
index 00000000..bce2be5f
--- /dev/null
+++ b/MapControl/MapOverlay.WPF.cs
@@ -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;
+ }
+ }
+ }
+}
diff --git a/MapControl/MapOverlay.cs b/MapControl/MapOverlay.cs
index 88f1ad29..9e853ca6 100644
--- a/MapControl/MapOverlay.cs
+++ b/MapControl/MapOverlay.cs
@@ -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
{
///
/// Base class for map overlays with font, background, foreground and stroke properties.
- /// Rendering is typically done by overriding OnRender in derived classes.
///
- 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;
- }
- }
}
}
diff --git a/MapControl/MapPanel.Silverlight.WinRT.cs b/MapControl/MapPanel.Silverlight.WinRT.cs
index c7bf1e30..3f261587 100644
--- a/MapControl/MapPanel.Silverlight.WinRT.cs
+++ b/MapControl/MapPanel.Silverlight.WinRT.cs
@@ -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; }
- }
-
///
- /// 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.
///
public static void AddParentMapHandlers(FrameworkElement element)
{
diff --git a/MapControl/MapPanel.cs b/MapControl/MapPanel.cs
index 94193a69..e8726f57 100644
--- a/MapControl/MapPanel.cs
+++ b/MapControl/MapPanel.cs
@@ -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; }
- }
-
///
/// 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.
///
- 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);
}
diff --git a/MapControl/MapPath.Silverlight.WinRT.cs b/MapControl/MapPath.Silverlight.WinRT.cs
index 839bd653..37c59a0f 100644
--- a/MapControl/MapPath.Silverlight.WinRT.cs
+++ b/MapControl/MapPath.Silverlight.WinRT.cs
@@ -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;
diff --git a/MapControl/MapPath.cs b/MapControl/MapPath.cs
index 587591fb..665a2101 100644
--- a/MapControl/MapPath.cs
+++ b/MapControl/MapPath.cs
@@ -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.
diff --git a/MapControl/MapPolyline.Silverlight.WinRT.cs b/MapControl/MapPolyline.Silverlight.WinRT.cs
index f6136200..d921ec58 100644
--- a/MapControl/MapPolyline.Silverlight.WinRT.cs
+++ b/MapControl/MapPolyline.Silverlight.WinRT.cs
@@ -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;
diff --git a/MapControl/MapPolyline.cs b/MapControl/MapPolyline.cs
index 4fd940b7..a8fb4dc1 100644
--- a/MapControl/MapPolyline.cs
+++ b/MapControl/MapPolyline.cs
@@ -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
///
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
///
/// Gets or sets the locations that define the polyline points.
///
-#if !NETFX_CORE
+#if !WINDOWS_RUNTIME
[TypeConverter(typeof(LocationCollectionConverter))]
#endif
public IEnumerable Locations
diff --git a/MapControl/MapRectangle.WPF.cs b/MapControl/MapRectangle.WPF.cs
deleted file mode 100644
index 73f2b630..00000000
--- a/MapControl/MapRectangle.WPF.cs
+++ /dev/null
@@ -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();
- }
- }
-}
diff --git a/MapControl/MapRectangle.cs b/MapControl/MapRectangle.cs
index 2440d594..79baf632 100644
--- a/MapControl/MapRectangle.cs
+++ b/MapControl/MapRectangle.cs
@@ -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
///
/// Fills a rectangular area defined by South, North, West and East with a Brush.
///
- 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;
}
diff --git a/MapControl/MapScale.cs b/MapControl/MapScale.cs
index d94f8dca..2b6428e4 100644
--- a/MapControl/MapScale.cs
+++ b/MapControl/MapScale.cs
@@ -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);
}
}
diff --git a/MapControl/MapTransform.cs b/MapControl/MapTransform.cs
index 93077598..03ac5854 100644
--- a/MapControl/MapTransform.cs
+++ b/MapControl/MapTransform.cs
@@ -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
///
public abstract double RelativeScale(Location location);
- ///
- /// Transforms a geographic location to a cartesian coordinate point.
- ///
- public abstract Point Transform(Location location);
-
///
/// Transforms a cartesian coordinate point to a geographic location.
///
public abstract Location Transform(Point point);
+ ///
+ /// Transforms a geographic location to a cartesian coordinate point.
+ ///
+ public abstract Point Transform(Location location);
+
///
/// Transforms a geographic location to a cartesian coordinate point
/// with minumum distance to the specified reference longitude value.
diff --git a/MapControl/MercatorTransform.cs b/MapControl/MercatorTransform.cs
index db2202e5..4c4b558f 100644
--- a/MapControl/MercatorTransform.cs
+++ b/MapControl/MercatorTransform.cs
@@ -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;
diff --git a/MapControl/PanelBase.cs b/MapControl/PanelBase.cs
new file mode 100644
index 00000000..063a9623
--- /dev/null
+++ b/MapControl/PanelBase.cs
@@ -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
+{
+ ///
+ /// Common base class for MapPanel, TileLayer and TileContainer.
+ ///
+ 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;
+ }
+ }
+}
diff --git a/MapControl/Properties/AssemblyInfo.cs b/MapControl/Properties/AssemblyInfo.cs
index ada7175a..1eda3a64 100644
--- a/MapControl/Properties/AssemblyInfo.cs
+++ b/MapControl/Properties/AssemblyInfo.cs
@@ -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)]
diff --git a/MapControl/Pushpin.Silverlight.WinRT.cs b/MapControl/Pushpin.Silverlight.WinRT.cs
index 1325d99c..7f5279bb 100644
--- a/MapControl/Pushpin.Silverlight.WinRT.cs
+++ b/MapControl/Pushpin.Silverlight.WinRT.cs
@@ -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;
diff --git a/MapControl/Tile.Silverlight.WinRT.cs b/MapControl/Tile.Silverlight.WinRT.cs
index 1b10c377..82d1bafc 100644
--- a/MapControl/Tile.Silverlight.WinRT.cs
+++ b/MapControl/Tile.Silverlight.WinRT.cs
@@ -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)
diff --git a/MapControl/Tile.WPF.cs b/MapControl/Tile.WPF.cs
index 2a847361..e3706e85 100644
--- a/MapControl/Tile.WPF.cs
+++ b/MapControl/Tile.WPF.cs
@@ -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;
}
}
}
diff --git a/MapControl/Tile.cs b/MapControl/Tile.cs
index 02042f97..c5ab8a7f 100644
--- a/MapControl/Tile.cs
+++ b/MapControl/Tile.cs
@@ -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)
{
diff --git a/MapControl/TileContainer.Silverlight.WinRT.cs b/MapControl/TileContainer.Silverlight.WinRT.cs
index be95fd74..96372f2c 100644
--- a/MapControl/TileContainer.Silverlight.WinRT.cs
+++ b/MapControl/TileContainer.Silverlight.WinRT.cs
@@ -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);
- }
-
- ///
- /// Gets a transform matrix with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
- ///
- 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)
+ ///
+ /// Sets a RenderTransform with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
+ ///
+ 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);
}
}
}
diff --git a/MapControl/TileContainer.WPF.cs b/MapControl/TileContainer.WPF.cs
index 64eaba80..9dd5a348 100644
--- a/MapControl/TileContainer.WPF.cs
+++ b/MapControl/TileContainer.WPF.cs
@@ -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;
- }
-
- ///
- /// Gets a transform matrix with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
- ///
- 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;
}
+
+ ///
+ /// Sets a RenderTransform with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
+ ///
+ 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;
+ }
}
}
diff --git a/MapControl/TileContainer.cs b/MapControl/TileContainer.cs
index 1c61865e..e4080181 100644
--- a/MapControl/TileContainer.cs
+++ b/MapControl/TileContainer.cs
@@ -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 TileLayers
+ {
+ get { return InternalChildren.Cast(); }
+ }
+
public void AddTileLayers(int index, IEnumerable 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);
}
}
diff --git a/MapControl/TileImageLoader.Silverlight.WinRT.cs b/MapControl/TileImageLoader.Silverlight.WinRT.cs
index b05b8364..9bc58a05 100644
--- a/MapControl/TileImageLoader.Silverlight.WinRT.cs
+++ b/MapControl/TileImageLoader.Silverlight.WinRT.cs
@@ -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()
{
}
}
diff --git a/MapControl/TileImageLoader.WPF.cs b/MapControl/TileImageLoader.WPF.cs
index 71d50119..16621882 100644
--- a/MapControl/TileImageLoader.WPF.cs
+++ b/MapControl/TileImageLoader.WPF.cs
@@ -34,7 +34,7 @@ namespace MapControl
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MapControl");
///
- /// The ObjectCache used to cache tile images. The default is null.
+ /// The ObjectCache used to cache tile images. The default is MemoryCache.Default.
///
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 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(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 tiles, Dispatcher dispatcher, TileSource tileSource,
- string sourceName, int maxDownloads, bool animateOpacity)
+ private void GetTiles(List 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((t, i) => t.SetImageSource(i, animateOpacity));
+ var outdatedTiles = new List(tiles.Count);
+
+ foreach (var tile in tiles)
{
- var setImageAction = new Action((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((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((t, i) => t.SetImageSource(i, animateOpacity));
- var outdatedTiles = new List(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();
+ }
+ }
+ }
}
}
diff --git a/MapControl/TileLayer.Silverlight.WinRT.cs b/MapControl/TileLayer.Silverlight.WinRT.cs
deleted file mode 100644
index 154ee159..00000000
--- a/MapControl/TileLayer.Silverlight.WinRT.cs
+++ /dev/null
@@ -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;
- }
- }
-}
diff --git a/MapControl/TileLayer.WPF.cs b/MapControl/TileLayer.WPF.cs
deleted file mode 100644
index cc27909c..00000000
--- a/MapControl/TileLayer.WPF.cs
+++ /dev/null
@@ -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);
- }
- }
- }
- }
-}
diff --git a/MapControl/TileLayer.cs b/MapControl/TileLayer.cs
index e393a18d..2b623f2c 100644
--- a/MapControl/TileLayer.cs
+++ b/MapControl/TileLayer.cs
@@ -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
///
/// Fills a rectangular area with map tiles from a TileSource.
///
-#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;
+ }
}
}
diff --git a/MapControl/TileSource.cs b/MapControl/TileSource.cs
index 8a790b41..97d0da98 100644
--- a/MapControl/TileSource.cs
+++ b/MapControl/TileSource.cs
@@ -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)).
diff --git a/MapControl/TransformEx.WinRT.cs b/MapControl/TransformEx.WinRT.cs
deleted file mode 100644
index 63e7ff49..00000000
--- a/MapControl/TransformEx.WinRT.cs
+++ /dev/null
@@ -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);
- }
- }
-}
diff --git a/MapControl/WinRT/MapControl.WinRT.csproj b/MapControl/WinRT/MapControl.WinRT.csproj
index af7c1cfd..fc95fecc 100644
--- a/MapControl/WinRT/MapControl.WinRT.csproj
+++ b/MapControl/WinRT/MapControl.WinRT.csproj
@@ -13,17 +13,17 @@
MapControl.WinRT
en-US
512
- {BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
12.0
- Windows
- 8.1
+ Profile32
+ v4.6
true
full
false
..\bin\Debug\
- TRACE;DEBUG;NETFX_CORE
+ TRACE;DEBUG;WINDOWS_RUNTIME
prompt
4
@@ -31,16 +31,22 @@
none
true
..\bin\Release\
- TRACE;NETFX_CORE
+ TRACE;WINDOWS_RUNTIME
prompt
4
-
- AnimationEx.WinRT.cs
+
+ Extensions.Silverlight.WinRT.cs
-
- ImageTileSource.cs
+
+ Extensions.WinRT.cs
+
+
+ ImageTileSource.Silverlight.WinRT.cs
+
+
+ IMapElement.cs
Int32Rect.cs
@@ -81,6 +87,12 @@
MapItemsControl.Silverlight.WinRT.cs
+
+ MapOverlay.cs
+
+
+ MapOverlay.Silverlight.WinRT.cs
+
MapPanel.cs
@@ -105,12 +117,12 @@
MapTransform.cs
-
- MatrixEx.cs
-
MercatorTransform.cs
+
+ PanelBase.cs
+
Pushpin.Silverlight.WinRT.cs
@@ -132,18 +144,12 @@
TileLayer.cs
-
- TileLayer.Silverlight.WinRT.cs
-
TileLayerCollection.cs
TileSource.cs
-
- TransformEx.WinRT.cs
-
@@ -157,6 +163,10 @@
Designer
+
+
+
+
12.0
@@ -169,7 +179,7 @@
..\..\MapControl.snk
-
+
diff --git a/MapControl/WinRT/Properties/AssemblyInfo.cs b/MapControl/WinRT/Properties/AssemblyInfo.cs
index e6822839..b2659bae 100644
--- a/MapControl/WinRT/Properties/AssemblyInfo.cs
+++ b/MapControl/WinRT/Properties/AssemblyInfo.cs
@@ -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)]
diff --git a/SampleApps/Common/ViewModel.cs b/SampleApps/Common/ViewModel.cs
index ea11efd5..0e5648ab 100644
--- a/SampleApps/Common/ViewModel.cs
+++ b/SampleApps/Common/ViewModel.cs
@@ -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");
}
}
diff --git a/SampleApps/PhoneApplication/App.xaml b/SampleApps/PhoneApplication/App.xaml
new file mode 100644
index 00000000..fa95c1b9
--- /dev/null
+++ b/SampleApps/PhoneApplication/App.xaml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/SampleApps/PhoneApplication/App.xaml.cs b/SampleApps/PhoneApplication/App.xaml.cs
new file mode 100644
index 00000000..aec98412
--- /dev/null
+++ b/SampleApps/PhoneApplication/App.xaml.cs
@@ -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
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ public sealed partial class App : Application
+ {
+ private TransitionCollection transitions;
+
+ ///
+ /// 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().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ this.Suspending += this.OnSuspending;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// Details about the launch request and process.
+ 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();
+ }
+
+ ///
+ /// Restores the content transitions after the app has launched.
+ ///
+ /// The object where the handler is attached.
+ /// Details about the navigation event.
+ 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;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The source of the suspend request.
+ /// Details about the suspend request.
+ private void OnSuspending(object sender, SuspendingEventArgs e)
+ {
+ var deferral = e.SuspendingOperation.GetDeferral();
+
+ // TODO: Save application state and stop any background activity
+ deferral.Complete();
+ }
+ }
+}
\ No newline at end of file
diff --git a/SampleApps/PhoneApplication/Assets/Logo.scale-240.png b/SampleApps/PhoneApplication/Assets/Logo.scale-240.png
new file mode 100644
index 00000000..76921ca9
Binary files /dev/null and b/SampleApps/PhoneApplication/Assets/Logo.scale-240.png differ
diff --git a/SampleApps/PhoneApplication/Assets/SmallLogo.scale-240.png b/SampleApps/PhoneApplication/Assets/SmallLogo.scale-240.png
new file mode 100644
index 00000000..31663012
Binary files /dev/null and b/SampleApps/PhoneApplication/Assets/SmallLogo.scale-240.png differ
diff --git a/SampleApps/PhoneApplication/Assets/SplashScreen.scale-240.png b/SampleApps/PhoneApplication/Assets/SplashScreen.scale-240.png
new file mode 100644
index 00000000..33f26b33
Binary files /dev/null and b/SampleApps/PhoneApplication/Assets/SplashScreen.scale-240.png differ
diff --git a/SampleApps/PhoneApplication/Assets/Square71x71Logo.scale-240.png b/SampleApps/PhoneApplication/Assets/Square71x71Logo.scale-240.png
new file mode 100644
index 00000000..cfa54bee
Binary files /dev/null and b/SampleApps/PhoneApplication/Assets/Square71x71Logo.scale-240.png differ
diff --git a/SampleApps/PhoneApplication/Assets/StoreLogo.scale-240.png b/SampleApps/PhoneApplication/Assets/StoreLogo.scale-240.png
new file mode 100644
index 00000000..47e084b5
Binary files /dev/null and b/SampleApps/PhoneApplication/Assets/StoreLogo.scale-240.png differ
diff --git a/SampleApps/PhoneApplication/Assets/WideLogo.scale-240.png b/SampleApps/PhoneApplication/Assets/WideLogo.scale-240.png
new file mode 100644
index 00000000..6249d29d
Binary files /dev/null and b/SampleApps/PhoneApplication/Assets/WideLogo.scale-240.png differ
diff --git a/SampleApps/PhoneApplication/MainPage.xaml b/SampleApps/PhoneApplication/MainPage.xaml
new file mode 100644
index 00000000..e2c9b597
--- /dev/null
+++ b/SampleApps/PhoneApplication/MainPage.xaml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SampleApps/PhoneApplication/MainPage.xaml.cs b/SampleApps/PhoneApplication/MainPage.xaml.cs
new file mode 100644
index 00000000..7493bb85
--- /dev/null
+++ b/SampleApps/PhoneApplication/MainPage.xaml.cs
@@ -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();
+ }
+ }
+}
diff --git a/SampleApps/PhoneApplication/Package.appxmanifest b/SampleApps/PhoneApplication/Package.appxmanifest
new file mode 100644
index 00000000..05637d6c
--- /dev/null
+++ b/SampleApps/PhoneApplication/Package.appxmanifest
@@ -0,0 +1,30 @@
+
+
+
+
+
+ PhoneApplication
+ Clemens
+ Assets\StoreLogo.png
+
+
+ 6.3.1
+ 6.3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SampleApps/PhoneApplication/PhoneApplication.csproj b/SampleApps/PhoneApplication/PhoneApplication.csproj
new file mode 100644
index 00000000..ec1fd6f6
--- /dev/null
+++ b/SampleApps/PhoneApplication/PhoneApplication.csproj
@@ -0,0 +1,135 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {8D0A57DF-FABF-4AEE-8768-9C18B2B43CA9}
+ AppContainerExe
+ Properties
+ PhoneApplication
+ PhoneApplication
+ en-US
+ 8.1
+ 12
+ 512
+ {76F1466A-8B6D-4E39-A767-685A06062A39};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE;NETFX_CORE;WINDOWS_PHONE_APP
+ prompt
+ 4
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_PHONE_APP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_PHONE_APP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+
+
+
+
+ {63cefdf7-5170-43b6-86f8-5c4a383a1615}
+ MapControl.WinRT
+
+
+
+
+ App.xaml
+
+
+ MainPage.xaml
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+ 12.0
+
+
+ WindowsPhoneApp
+
+
+
+
\ No newline at end of file
diff --git a/SampleApps/PhoneApplication/PhoneApplication.csproj.user b/SampleApps/PhoneApplication/PhoneApplication.csproj.user
new file mode 100644
index 00000000..790515dc
--- /dev/null
+++ b/SampleApps/PhoneApplication/PhoneApplication.csproj.user
@@ -0,0 +1,9 @@
+
+
+
+ 30F105C9-681E-420b-A277-7C086EAD8A4E
+
+
+ 30F105C9-681E-420b-A277-7C086EAD8A4E
+
+
\ No newline at end of file
diff --git a/SampleApps/PhoneApplication/Properties/AssemblyInfo.cs b/SampleApps/PhoneApplication/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..59a482cd
--- /dev/null
+++ b/SampleApps/PhoneApplication/Properties/AssemblyInfo.cs
@@ -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)]
\ No newline at end of file
diff --git a/SampleApps/PhoneApplication/ViewModel.cs b/SampleApps/PhoneApplication/ViewModel.cs
new file mode 100644
index 00000000..10857534
--- /dev/null
+++ b/SampleApps/PhoneApplication/ViewModel.cs
@@ -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);
+ });
+ }
+ }
+}
diff --git a/SampleApps/SilverlightApplication.Web/Properties/AssemblyInfo.cs b/SampleApps/SilverlightApplication.Web/Properties/AssemblyInfo.cs
index 585f0146..fa4fde76 100644
--- a/SampleApps/SilverlightApplication.Web/Properties/AssemblyInfo.cs
+++ b/SampleApps/SilverlightApplication.Web/Properties/AssemblyInfo.cs
@@ -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)]
diff --git a/SampleApps/SilverlightApplication/Properties/AssemblyInfo.cs b/SampleApps/SilverlightApplication/Properties/AssemblyInfo.cs
index 041a2e25..a6ef69a5 100644
--- a/SampleApps/SilverlightApplication/Properties/AssemblyInfo.cs
+++ b/SampleApps/SilverlightApplication/Properties/AssemblyInfo.cs
@@ -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)]
diff --git a/SampleApps/StoreApplication/MainPage.xaml b/SampleApps/StoreApplication/MainPage.xaml
index aa5e5070..f6d83196 100644
--- a/SampleApps/StoreApplication/MainPage.xaml
+++ b/SampleApps/StoreApplication/MainPage.xaml
@@ -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">
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -180,7 +183,8 @@
-
+
OpenStreetMap
OpenCycleMap
OCM Transport
diff --git a/SampleApps/StoreApplication/MainPage.xaml.cs b/SampleApps/StoreApplication/MainPage.xaml.cs
index 0b736185..1cd81486 100644
--- a/SampleApps/StoreApplication/MainPage.xaml.cs
+++ b/SampleApps/StoreApplication/MainPage.xaml.cs
@@ -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"]);
}
}
}
diff --git a/SampleApps/StoreApplication/Properties/AssemblyInfo.cs b/SampleApps/StoreApplication/Properties/AssemblyInfo.cs
index 2d4c6ae0..f9feb655 100644
--- a/SampleApps/StoreApplication/Properties/AssemblyInfo.cs
+++ b/SampleApps/StoreApplication/Properties/AssemblyInfo.cs
@@ -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)]
diff --git a/SampleApps/StoreApplication/StoreApplication.csproj b/SampleApps/StoreApplication/StoreApplication.csproj
index 50fce977..ffada2ff 100644
--- a/SampleApps/StoreApplication/StoreApplication.csproj
+++ b/SampleApps/StoreApplication/StoreApplication.csproj
@@ -23,7 +23,7 @@
full
false
bin\Debug\
- DEBUG;TRACE;NETFX_CORE
+ TRACE;DEBUG;WINDOWS_RUNTIME
prompt
4
@@ -32,7 +32,7 @@
pdbonly
true
bin\Release\
- TRACE;NETFX_CORE
+ TRACE;WINDOWS_RUNTIME
prompt
4
diff --git a/SampleApps/SurfaceApplication/Properties/AssemblyInfo.cs b/SampleApps/SurfaceApplication/Properties/AssemblyInfo.cs
index ab01a4d7..be1f7b7c 100644
--- a/SampleApps/SurfaceApplication/Properties/AssemblyInfo.cs
+++ b/SampleApps/SurfaceApplication/Properties/AssemblyInfo.cs
@@ -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)]
diff --git a/SampleApps/WpfApplication/MainWindow.xaml b/SampleApps/WpfApplication/MainWindow.xaml
index bb056196..98a9188d 100644
--- a/SampleApps/WpfApplication/MainWindow.xaml
+++ b/SampleApps/WpfApplication/MainWindow.xaml
@@ -41,7 +41,7 @@
diff --git a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs b/SampleApps/WpfApplication/Properties/AssemblyInfo.cs
index db7ebace..7fc78994 100644
--- a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs
+++ b/SampleApps/WpfApplication/Properties/AssemblyInfo.cs
@@ -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)]