Version 2.4.2.:

- added HyperlinkText.InlinesSource attached property
- simplified TileLayerCollection, removed it from MapBase
- simplified MapRectangle and MapImage
This commit is contained in:
ClemensF 2014-12-17 21:38:28 +01:00
parent 1583b10ff3
commit f6a881c674
36 changed files with 456 additions and 372 deletions

View file

@ -6,8 +6,12 @@ using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
#if WINDOWS_RUNTIME
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Documents;
#else
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
#endif
@ -21,7 +25,7 @@ namespace MapControl
/// Converts text containing hyperlinks in markdown syntax [text](url)
/// to a collection of Run and Hyperlink inlines.
/// </summary>
public static List<Inline> ToInlines(this string text)
public static IEnumerable<Inline> TextToInlines(this string text)
{
var inlines = new List<Inline>();
@ -56,5 +60,51 @@ namespace MapControl
return inlines;
}
public static readonly DependencyProperty InlinesSourceProperty = DependencyProperty.RegisterAttached(
"InlinesSource", typeof(string), typeof(HyperlinkText), new PropertyMetadata(null, InlinesSourcePropertyChanged));
public static string GetInlinesSource(UIElement element)
{
return (string)element.GetValue(InlinesSourceProperty);
}
public static void SetInlinesSource(UIElement element, string value)
{
element.SetValue(InlinesSourceProperty, value);
}
private static void InlinesSourcePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
InlineCollection inlines = null;
if (obj is TextBlock)
{
inlines = ((TextBlock)obj).Inlines;
}
else if (obj is Paragraph)
{
inlines = ((Paragraph)obj).Inlines;
}
#if WINDOWS_RUNTIME || SILVERLIGHT
else if (obj is RichTextBlock)
{
var paragraph = new Paragraph();
inlines = paragraph.Inlines;
var richTextBlock = (RichTextBlock)obj;
richTextBlock.Blocks.Clear();
richTextBlock.Blocks.Add(paragraph);
}
#endif
if (inlines != null)
{
inlines.Clear();
foreach (var inline in TextToInlines((string)e.NewValue))
{
inlines.Add(inline);
}
}
}
}
}

View file

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
#if WINDOWS_RUNTIME
@ -39,8 +40,8 @@ namespace MapControl
(o, e) => ((MapBase)o).TileLayerPropertyChanged((TileLayer)e.NewValue)));
public static readonly DependencyProperty TileLayersProperty = DependencyProperty.Register(
"TileLayers", typeof(TileLayerCollection), typeof(MapBase), new PropertyMetadata(null,
(o, e) => ((MapBase)o).TileLayersPropertyChanged((TileLayerCollection)e.OldValue, (TileLayerCollection)e.NewValue)));
"TileLayers", typeof(IList<TileLayer>), typeof(MapBase), new PropertyMetadata(null,
(o, e) => ((MapBase)o).TileLayersPropertyChanged((IList<TileLayer>)e.OldValue, (IList<TileLayer>)e.NewValue)));
public static readonly DependencyProperty MinZoomLevelProperty = DependencyProperty.Register(
"MinZoomLevel", typeof(double), typeof(MapBase), new PropertyMetadata(1d,
@ -74,7 +75,7 @@ namespace MapControl
public MapBase()
{
Children.Add(tileLayerPanel);
TileLayers = new TileLayerCollection();
TileLayers = new ObservableCollection<TileLayer>();
tileUpdateTimer.Tick += UpdateTiles;
Loaded += OnLoaded;
@ -119,9 +120,9 @@ namespace MapControl
/// The additional TileLayers usually have transparent backgrounds and their IsOverlay
/// property is set to true.
/// </summary>
public TileLayerCollection TileLayers
public IList<TileLayer> TileLayers
{
get { return (TileLayerCollection)GetValue(TileLayersProperty); }
get { return (IList<TileLayer>)GetValue(TileLayersProperty); }
set { SetValue(TileLayersProperty, value); }
}
@ -416,7 +417,7 @@ namespace MapControl
{
if (TileLayers == null)
{
TileLayers = new TileLayerCollection(tileLayer);
TileLayers = new ObservableCollection<TileLayer>(new TileLayer[] { tileLayer });
}
else if (TileLayers.Count == 0)
{
@ -429,11 +430,15 @@ namespace MapControl
}
}
private void TileLayersPropertyChanged(TileLayerCollection oldTileLayers, TileLayerCollection newTileLayers)
private void TileLayersPropertyChanged(IList<TileLayer> oldTileLayers, IList<TileLayer> newTileLayers)
{
if (oldTileLayers != null)
{
oldTileLayers.CollectionChanged -= TileLayerCollectionChanged;
var oldCollection = oldTileLayers as INotifyCollectionChanged;
if (oldCollection != null)
{
oldCollection.CollectionChanged -= TileLayerCollectionChanged;
}
TileLayer = null;
RemoveTileLayers(0, oldTileLayers.Count);
@ -444,7 +449,11 @@ namespace MapControl
TileLayer = newTileLayers.FirstOrDefault();
AddTileLayers(0, newTileLayers);
newTileLayers.CollectionChanged += TileLayerCollectionChanged;
var newCollection = newTileLayers as INotifyCollectionChanged;
if (newCollection != null)
{
newCollection.CollectionChanged += TileLayerCollectionChanged;
}
}
}

View file

@ -72,7 +72,6 @@
<Compile Include="MapPolyline.cs" />
<Compile Include="MapPolyline.Silverlight.WinRT.cs" />
<Compile Include="MapRectangle.cs" />
<Compile Include="MapRectangle.Silverlight.WinRT.cs" />
<Compile Include="MapTransform.cs" />
<Compile Include="MatrixEx.cs" />
<Compile Include="MercatorTransform.cs" />

View file

@ -99,7 +99,6 @@
<Compile Include="MapPolyline.cs" />
<Compile Include="MapPolyline.Silverlight.WinRT.cs" />
<Compile Include="MapRectangle.cs" />
<Compile Include="MapRectangle.Silverlight.WinRT.cs" />
<Compile Include="MapTransform.cs" />
<Compile Include="MatrixEx.cs" />
<Compile Include="MercatorTransform.cs" />

View file

@ -19,21 +19,23 @@ namespace MapControl
{
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
"Source", typeof(ImageSource), typeof(MapImage),
new PropertyMetadata(null, (o, e) => ((MapImage)o).SourcePropertyChanged((ImageSource)e.NewValue)));
new PropertyMetadata(null, (o, e) => ((ImageBrush)((MapImage)o).Fill).ImageSource = (ImageSource)e.NewValue));
public MapImage()
{
Fill = new ImageBrush
{
RelativeTransform = new MatrixTransform
{
Matrix = new Matrix(1d, 0d, 0d, -1d, 0d, 1d)
}
};
}
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
private void SourcePropertyChanged(ImageSource image)
{
Fill = new ImageBrush
{
ImageSource = image,
RelativeTransform = FillTransform
};
}
}
}

View file

@ -2,11 +2,9 @@
// Copyright © 2014 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
#if WINDOWS_RUNTIME
using Windows.Foundation;
using Windows.UI.Xaml;
#else
using System.Windows;
@ -20,15 +18,8 @@ namespace MapControl
/// </summary>
public partial class MapPolyline : MapPath
{
#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
private static readonly Type LocationsPropertyType = typeof(IEnumerable<Location>);
#endif
public static readonly DependencyProperty LocationsProperty = DependencyProperty.Register(
"Locations", LocationsPropertyType, typeof(MapPolyline),
"Locations", typeof(IEnumerable<Location>), typeof(MapPolyline),
new PropertyMetadata(null, LocationsPropertyChanged));
public static readonly DependencyProperty IsClosedProperty = DependencyProperty.Register(

View file

@ -1,24 +0,0 @@
// 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.Media;
#else
using System.Windows;
using System.Windows.Media;
#endif
namespace MapControl
{
public partial class MapRectangle
{
private void SetRect(Rect rect)
{
((RectangleGeometry)Data).Rect = rect;
RenderTransform = ParentMap.ViewportTransform;
}
}
}

View file

@ -2,7 +2,6 @@
// Copyright © 2014 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Windows;
using System.Windows.Media;
@ -10,31 +9,21 @@ namespace MapControl
{
public partial class MapRectangle
{
static MapRectangle()
static partial void ScaleRect(ref Rect rect, ref Transform transform)
{
FillTransform.Freeze();
}
private void SetRect(Rect rect)
{
// Apply scaling to the RectangleGeometry to compensate for inaccurate hit testing in WPF.
// Scales the RectangleGeometry to compensate inaccurate hit testing in WPF.
// See http://stackoverflow.com/a/19335624/1136211
var scale = 1e6 / Math.Min(rect.Width, rect.Height);
rect.X *= scale;
rect.Y *= scale;
rect.Width *= scale;
rect.Height *= scale;
rect.Scale(1e6, 1e6);
var scaleTransform = new ScaleTransform(1d / scale, 1d / scale);
var scaleTransform = new ScaleTransform(1e-6, 1e-6); // reverts rect scaling
scaleTransform.Freeze();
var transform = new TransformGroup();
transform.Children.Add(scaleTransform); // revert scaling
transform.Children.Add(ParentMap.ViewportTransform);
var transformGroup = new TransformGroup();
transformGroup.Children.Add(scaleTransform);
transformGroup.Children.Add(transform);
((RectangleGeometry)Data).Rect = rect;
RenderTransform = transform;
transform = transformGroup;
}
}
}

View file

@ -18,14 +18,6 @@ namespace MapControl
/// </summary>
public partial class MapRectangle : MapPath
{
/// <summary>
/// Used in derived classes like MapImage.
/// </summary>
protected static readonly MatrixTransform FillTransform = new MatrixTransform
{
Matrix = new Matrix(1d, 0d, 0d, -1d, 0d, 1d)
};
public static readonly DependencyProperty WestProperty = DependencyProperty.Register(
"West", typeof(double), typeof(MapRectangle),
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateData()));
@ -81,9 +73,14 @@ namespace MapControl
!double.IsNaN(West) && !double.IsNaN(East) &&
South < North && West < East)
{
SetRect(new Rect(
ParentMap.MapTransform.Transform(new Location(South, West)),
ParentMap.MapTransform.Transform(new Location(North, East))));
var rect = new Rect(ParentMap.MapTransform.Transform(new Location(South, West)),
ParentMap.MapTransform.Transform(new Location(North, East)));
var transform = ParentMap.ViewportTransform;
ScaleRect(ref rect, ref transform);
geometry.Rect = rect;
RenderTransform = transform;
}
else
{
@ -91,5 +88,7 @@ namespace MapControl
ClearValue(RenderTransformProperty);
}
}
static partial void ScaleRect(ref Rect rect, ref Transform transform);
}
}

View file

@ -17,8 +17,8 @@ using System.Windows;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.4.1")]
[assembly: AssemblyFileVersion("2.4.1")]
[assembly: AssemblyVersion("2.4.2")]
[assembly: AssemblyFileVersion("2.4.2")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View file

@ -85,7 +85,7 @@ namespace MapControl
}
else
{
var tileList = tiles.ToList();
var tileList = tiles.ToList(); // force immediate evaluation
var sourceName = tileLayer.SourceName;
var maxDownloads = tileLayer.MaxParallelDownloads;
@ -101,7 +101,7 @@ namespace MapControl
while (pendingTiles.TryDequeue(out pendingTile)) ; // no Clear method
}
private void GetTiles(List<Tile> tiles, Dispatcher dispatcher, TileSource tileSource, string sourceName, int maxDownloads)
private void GetTiles(IEnumerable<Tile> tiles, Dispatcher dispatcher, TileSource tileSource, string sourceName, int maxDownloads)
{
if (Cache != null &&
!string.IsNullOrWhiteSpace(sourceName) &&

View file

@ -8,12 +8,10 @@ using System.Linq;
#if WINDOWS_RUNTIME
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Documents;
using Windows.UI.Xaml.Markup;
using Windows.UI.Xaml.Media;
#else
using System.Windows;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;
#endif
@ -158,16 +156,6 @@ namespace MapControl
set { SetValue(BackgroundProperty, value); }
}
/// <summary>
/// In case the Description text contains copyright links in markdown syntax [text](url),
/// the DescriptionInlines property may be used to create a collection of Run and Hyperlink
/// inlines to be displayed in e.g. a TextBlock or a Silverlight RichTextBlock.
/// </summary>
public List<Inline> DescriptionInlines
{
get { return Description.ToInlines(); }
}
public MapBase ParentMap
{
get { return parentMap; }

View file

@ -7,17 +7,12 @@ using System.Linq;
namespace MapControl
{
public class TileLayerCollection : ObservableCollection<TileLayer>
/// <summary>
/// A collection of TileLayers with a string indexer that allows
/// to retrieve individual TileLayers by their SourceName property.
/// </summary>
public class TileLayerCollection : Collection<TileLayer>
{
internal TileLayerCollection(TileLayer tileLayer)
{
Add(tileLayer);
}
public TileLayerCollection()
{
}
public TileLayer this[string sourceName]
{
get { return this.FirstOrDefault(t => t.SourceName == sourceName); }

View file

@ -126,9 +126,6 @@
<Compile Include="..\MapRectangle.cs">
<Link>MapRectangle.cs</Link>
</Compile>
<Compile Include="..\MapRectangle.Silverlight.WinRT.cs">
<Link>MapRectangle.Silverlight.WinRT.cs</Link>
</Compile>
<Compile Include="..\MapTransform.cs">
<Link>MapTransform.cs</Link>
</Compile>

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © 2014 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.4.1")]
[assembly: AssemblyFileVersion("2.4.1")]
[assembly: AssemblyVersion("2.4.2")]
[assembly: AssemblyFileVersion("2.4.2")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]