mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Version 4.1.0
This commit is contained in:
parent
078f3173da
commit
6efad6df0f
|
|
@ -1,7 +1,7 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("XAML Map Control FileDbCache for UWP")]
|
||||
[assembly: AssemblyTitle("XAML Map Control FileDbCache (UWP)")]
|
||||
[assembly: AssemblyDescription("IImageCache implementation based on EzTools FileDb")]
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("XAML Map Control FileDbCache for WPF")]
|
||||
[assembly: AssemblyTitle("XAML Map Control FileDbCache (WPF)")]
|
||||
[assembly: AssemblyDescription("ObjectCache implementation based on EzTools FileDb")]
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
|
|
|
|||
95
MBTiles/Shared/MBTileLayer.cs
Normal file
95
MBTiles/Shared/MBTileLayer.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#if WINDOWS_UWP
|
||||
using Windows.UI.Xaml;
|
||||
#else
|
||||
using System.Windows;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class MBTileLayer : MapTileLayer
|
||||
{
|
||||
public static readonly DependencyProperty FileProperty = DependencyProperty.Register(
|
||||
nameof(File), typeof(string), typeof(MBTileLayer),
|
||||
new PropertyMetadata(null, (o, e) => ((MBTileLayer)o).FilePropertyChanged((string)e.NewValue)));
|
||||
|
||||
public MBTileLayer()
|
||||
: this(new TileImageLoader())
|
||||
{
|
||||
}
|
||||
|
||||
public MBTileLayer(ITileImageLoader tileImageLoader)
|
||||
: base(tileImageLoader)
|
||||
{
|
||||
}
|
||||
|
||||
public string File
|
||||
{
|
||||
get { return (string)GetValue(FileProperty); }
|
||||
set { SetValue(FileProperty, value); }
|
||||
}
|
||||
|
||||
private void FilePropertyChanged(string file)
|
||||
{
|
||||
MBTileSource ts;
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
ts = new MBTileSource(file);
|
||||
|
||||
if (ts.Metadata.ContainsKey("name"))
|
||||
{
|
||||
SourceName = ts.Metadata["name"];
|
||||
}
|
||||
|
||||
if (ts.Metadata.ContainsKey("description"))
|
||||
{
|
||||
Description = ts.Metadata["description"];
|
||||
}
|
||||
|
||||
if (ts.Metadata.ContainsKey("minzoom"))
|
||||
{
|
||||
int minZoom;
|
||||
if (int.TryParse(ts.Metadata["minzoom"], out minZoom))
|
||||
{
|
||||
MinZoomLevel = minZoom;
|
||||
}
|
||||
}
|
||||
|
||||
if (ts.Metadata.ContainsKey("maxzoom"))
|
||||
{
|
||||
int maxZoom;
|
||||
if (int.TryParse(ts.Metadata["maxzoom"], out maxZoom))
|
||||
{
|
||||
MaxZoomLevel = maxZoom;
|
||||
}
|
||||
}
|
||||
|
||||
TileSource = ts;
|
||||
}
|
||||
else if ((ts = TileSource as MBTileSource) != null)
|
||||
{
|
||||
ClearValue(TileSourceProperty);
|
||||
|
||||
if (ts.Metadata.ContainsKey("name"))
|
||||
{
|
||||
ClearValue(SourceNameProperty);
|
||||
}
|
||||
|
||||
if (ts.Metadata.ContainsKey("description"))
|
||||
{
|
||||
ClearValue(DescriptionProperty);
|
||||
}
|
||||
|
||||
if (ts.Metadata.ContainsKey("minzoom"))
|
||||
{
|
||||
ClearValue(MinZoomLevelProperty);
|
||||
}
|
||||
|
||||
if (ts.Metadata.ContainsKey("maxzoom"))
|
||||
{
|
||||
ClearValue(MaxZoomLevelProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
85
MBTiles/UWP/MBTileSource.UWP.cs
Normal file
85
MBTiles/UWP/MBTileSource.UWP.cs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class MBTileSource : TileSource, IDisposable
|
||||
{
|
||||
private readonly SqliteConnection connection;
|
||||
|
||||
public IDictionary<string, string> Metadata { get; } = new Dictionary<string, string>();
|
||||
|
||||
public MBTileSource(string file)
|
||||
{
|
||||
connection = new SqliteConnection("Data Source=" + file);
|
||||
connection.Open();
|
||||
|
||||
using (var command = new SqliteCommand("select * from metadata", connection))
|
||||
{
|
||||
var reader = command.ExecuteReader();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
Metadata[(string)reader["name"]] = (string)reader["value"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<ImageSource> LoadImageAsync(int x, int y, int zoomLevel)
|
||||
{
|
||||
ImageSource imageSource = null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var command = new SqliteCommand("select tile_data from tiles where zoom_level=@z and tile_column=@x and tile_row=@y", connection))
|
||||
{
|
||||
command.Parameters.AddWithValue("@z", zoomLevel);
|
||||
command.Parameters.AddWithValue("@x", x);
|
||||
command.Parameters.AddWithValue("@y", (1 << zoomLevel) - y - 1);
|
||||
|
||||
var buffer = await command.ExecuteScalarAsync() as byte[];
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
using (var stream = new InMemoryRandomAccessStream())
|
||||
{
|
||||
await stream.WriteAsync(buffer.AsBuffer());
|
||||
stream.Seek(0);
|
||||
|
||||
var bitmapImage = new BitmapImage();
|
||||
await bitmapImage.SetSourceAsync(stream);
|
||||
|
||||
imageSource = bitmapImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("MBTileSource: {0}/{1}/{2}: {3}", zoomLevel, x, y, ex.Message);
|
||||
}
|
||||
|
||||
return imageSource;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && connection != null)
|
||||
{
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
68
MBTiles/UWP/MBTiles.UWP.csproj
Normal file
68
MBTiles/UWP/MBTiles.UWP.csproj
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{46D812C6-5354-46A6-8604-D4497E17E2A2}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>MBTiles</RootNamespace>
|
||||
<AssemblyName>MBTiles.UWP</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.14393.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.14393.0</TargetPlatformMinVersion>
|
||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
|
||||
<None Include="project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Shared\MBTileLayer.cs">
|
||||
<Link>MBTileLayer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="MBTileSource.UWP.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Properties\MBTiles.UWP.rd.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\MapControl\UWP\MapControl.UWP.csproj">
|
||||
<Project>{951bc5d2-d653-42d9-9a91-21dc50de0182}</Project>
|
||||
<Name>MapControl.UWP</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
14
MBTiles/UWP/Properties/AssemblyInfo.cs
Normal file
14
MBTiles/UWP/Properties/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("XAML Map Control MBTiles Support (UWP)")]
|
||||
[assembly: AssemblyDescription("MBTiles Support Library for XAML Map Control")]
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.1.0")]
|
||||
[assembly: AssemblyFileVersion("4.1.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
5
MBTiles/UWP/Properties/MBTiles.UWP.rd.xml
Normal file
5
MBTiles/UWP/Properties/MBTiles.UWP.rd.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
|
||||
<Library Name="MBTiles.UWP">
|
||||
</Library>
|
||||
</Directives>
|
||||
17
MBTiles/UWP/project.json
Normal file
17
MBTiles/UWP/project.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.Data.Sqlite": "1.1.1",
|
||||
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2"
|
||||
},
|
||||
"frameworks": {
|
||||
"uap10.0.14393": {}
|
||||
},
|
||||
"runtimes": {
|
||||
"win10-arm": {},
|
||||
"win10-arm-aot": {},
|
||||
"win10-x86": {},
|
||||
"win10-x86-aot": {},
|
||||
"win10-x64": {},
|
||||
"win10-x64-aot": {}
|
||||
}
|
||||
}
|
||||
81
MBTiles/WPF/MBTileSource.WPF.cs
Normal file
81
MBTiles/WPF/MBTileSource.WPF.cs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Data.SQLite;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class MBTileSource : TileSource, IDisposable
|
||||
{
|
||||
private readonly SQLiteConnection connection;
|
||||
|
||||
public IDictionary<string, string> Metadata { get; } = new Dictionary<string, string>();
|
||||
|
||||
public MBTileSource(string file)
|
||||
{
|
||||
connection = new SQLiteConnection("Data Source=" + file + ";Version=3;");
|
||||
connection.Open();
|
||||
|
||||
using (var command = new SQLiteCommand("select * from metadata", connection))
|
||||
{
|
||||
var reader = command.ExecuteReader();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
Metadata[(string)reader["name"]] = (string)reader["value"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<ImageSource> LoadImageAsync(int x, int y, int zoomLevel)
|
||||
{
|
||||
ImageSource imageSource = null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var command = new SQLiteCommand("select tile_data from tiles where zoom_level=@z and tile_column=@x and tile_row=@y", connection))
|
||||
{
|
||||
command.Parameters.AddWithValue("@z", zoomLevel);
|
||||
command.Parameters.AddWithValue("@x", x);
|
||||
command.Parameters.AddWithValue("@y", (1 << zoomLevel) - y - 1);
|
||||
|
||||
var buffer = await command.ExecuteScalarAsync() as byte[];
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
imageSource = await Task.Run(() =>
|
||||
{
|
||||
using (var stream = new MemoryStream(buffer))
|
||||
{
|
||||
return BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("MBTileSource: {0}/{1}/{2}: {3}", zoomLevel, x, y, ex.Message);
|
||||
}
|
||||
|
||||
return imageSource;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && connection != null)
|
||||
{
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
71
MBTiles/WPF/MBTiles.WPF.csproj
Normal file
71
MBTiles/WPF/MBTiles.WPF.csproj
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>MapControl</RootNamespace>
|
||||
<AssemblyName>MBTiles.WPF</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Data.SQLite, Version=1.0.105.2, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Data.SQLite.Core.1.0.105.2\lib\net45\System.Data.SQLite.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Shared\MBTileLayer.cs">
|
||||
<Link>MBTileLayer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="MBTileSource.WPF.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\MapControl\WPF\MapControl.WPF.csproj">
|
||||
<Project>{a204a102-c745-4d65-aec8-7b96faedef2d}</Project>
|
||||
<Name>MapControl.WPF</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\..\packages\System.Data.SQLite.Core.1.0.105.2\build\net45\System.Data.SQLite.Core.targets" Condition="Exists('..\..\packages\System.Data.SQLite.Core.1.0.105.2\build\net45\System.Data.SQLite.Core.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\System.Data.SQLite.Core.1.0.105.2\build\net45\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\System.Data.SQLite.Core.1.0.105.2\build\net45\System.Data.SQLite.Core.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
14
MBTiles/WPF/Properties/AssemblyInfo.cs
Normal file
14
MBTiles/WPF/Properties/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("XAML Map Control MBTiles Support (WPF)")]
|
||||
[assembly: AssemblyDescription("MBTiles Support Library for XAML Map Control")]
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.1.0")]
|
||||
[assembly: AssemblyFileVersion("4.1.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
4
MBTiles/WPF/packages.config
Normal file
4
MBTiles/WPF/packages.config
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="System.Data.SQLite.Core" version="1.0.105.2" targetFramework="net45" />
|
||||
</packages>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26730.16
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MapControl", "MapControl", "{52AECE49-F314-4F76-98F2-FA800F07824B}"
|
||||
EndProject
|
||||
|
|
@ -21,6 +21,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileDbCache.WPF", "Caching\
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileDbCache.UWP", "Caching\FileDbCache.UWP\FileDbCache.UWP.csproj", "{3FF37D40-F770-45B2-95DD-7A84093E1425}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MBTiles", "MBTiles", "{CEAD0EA1-A971-4F5F-9EAE-C72F75D1F737}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBTiles.WPF", "MBTiles\WPF\MBTiles.WPF.csproj", "{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBTiles.UWP", "MBTiles\UWP\MBTiles.UWP.csproj", "{46D812C6-5354-46A6-8604-D4497E17E2A2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -135,6 +141,38 @@ Global
|
|||
{3FF37D40-F770-45B2-95DD-7A84093E1425}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3FF37D40-F770-45B2-95DD-7A84093E1425}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3FF37D40-F770-45B2-95DD-7A84093E1425}.Release|x86.Build.0 = Release|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -146,5 +184,10 @@ Global
|
|||
{AA62B4AA-1CA3-4C20-BEB7-B824D0FC4BD1} = {8F2103C2-78AF-4810-8FB9-67572F50C8FC}
|
||||
{AD1CB53E-7AA4-4EC0-B901-B4E0E2665133} = {6A596588-F93F-47CC-BE5D-58C3B34ADDEB}
|
||||
{3FF37D40-F770-45B2-95DD-7A84093E1425} = {6A596588-F93F-47CC-BE5D-58C3B34ADDEB}
|
||||
{38B18AB6-6E70-4696-8FB4-E8C8E12BF50C} = {CEAD0EA1-A971-4F5F-9EAE-C72F75D1F737}
|
||||
{46D812C6-5354-46A6-8604-D4497E17E2A2} = {CEAD0EA1-A971-4F5F-9EAE-C72F75D1F737}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {458346DD-B23F-4FDC-8F9D-A10F1882A4DB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace MapControl
|
|||
|
||||
public MapMode Mode { get; set; }
|
||||
public string Culture { get; set; }
|
||||
public Uri LogoImageUri { get; set; }
|
||||
public Uri LogoImageUri { get; private set; }
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -344,7 +344,12 @@ namespace MapControl
|
|||
if (parentMap != null && TileGrid != null && TileSource != null)
|
||||
{
|
||||
var maxZoomLevel = Math.Min(TileGrid.ZoomLevel, MaxZoomLevel);
|
||||
var minZoomLevel = parentMap.MapLayer == this ? MinZoomLevel : maxZoomLevel; // load background tiles only if this is the base layer
|
||||
var minZoomLevel = MinZoomLevel;
|
||||
|
||||
if (minZoomLevel < maxZoomLevel && parentMap.MapLayer != this) // load lower tiles only in a base layer
|
||||
{
|
||||
minZoomLevel = maxZoomLevel;
|
||||
}
|
||||
|
||||
for (var z = minZoomLevel; z <= maxZoomLevel; z++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,11 +53,13 @@ namespace MapControl
|
|||
style.Setters.Add(new Setter(BackgroundProperty, new SolidColorBrush(Colors.Transparent)));
|
||||
Style = style;
|
||||
|
||||
Clip = new RectangleGeometry();
|
||||
|
||||
SizeChanged += (s, e) =>
|
||||
{
|
||||
Clip.Rect = new Rect(0d, 0d, e.NewSize.Width, e.NewSize.Height);
|
||||
Clip = new RectangleGeometry
|
||||
{
|
||||
Rect = new Rect(0d, 0d, e.NewSize.Width, e.NewSize.Height)
|
||||
};
|
||||
|
||||
ResetTransformCenter();
|
||||
UpdateTransform();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("XAML Map Control for UWP")]
|
||||
[assembly: AssemblyDescription("XAML Map Control Library for UWP")]
|
||||
[assembly: AssemblyTitle("XAML Map Control (UWP)")]
|
||||
[assembly: AssemblyDescription("XAML Map Control Library")]
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
|
|
|
|||
|
|
@ -53,17 +53,16 @@ namespace MapControl
|
|||
}
|
||||
else if (TileAvailable(response.Headers))
|
||||
{
|
||||
var bitmapImage = new BitmapImage();
|
||||
|
||||
using (var stream = new InMemoryRandomAccessStream())
|
||||
{
|
||||
await response.Content.WriteToStreamAsync(stream);
|
||||
stream.Seek(0);
|
||||
|
||||
var bitmapImage = new BitmapImage();
|
||||
await bitmapImage.SetSourceAsync(stream);
|
||||
}
|
||||
|
||||
imageSource = bitmapImage;
|
||||
imageSource = bitmapImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
[assembly: AssemblyTitle("XAML Map Control for WPF")]
|
||||
[assembly: AssemblyDescription("XAML Map Control Library for WPF")]
|
||||
[assembly: AssemblyTitle("XAML Map Control (WPF)")]
|
||||
[assembly: AssemblyDescription("XAML Map Control Library")]
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
|
|
|
|||
|
|
@ -24,60 +24,33 @@ namespace ViewModel
|
|||
MapTileLayer.OpenStreetMapTileLayer
|
||||
},
|
||||
{
|
||||
"OpenStreetMap German Style",
|
||||
"OpenStreetMap German",
|
||||
new MapTileLayer
|
||||
{
|
||||
SourceName = "OpenStreetMap German",
|
||||
Description = "© [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)",
|
||||
Description = "© [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)",
|
||||
TileSource = new TileSource { UriFormat = "http://{c}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png" },
|
||||
MaxZoomLevel = 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"Thunderforest OpenCycleMap",
|
||||
"Stamen Terrain",
|
||||
new MapTileLayer
|
||||
{
|
||||
SourceName = "Thunderforest OpenCycleMap",
|
||||
Description = "Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)",
|
||||
TileSource = new TileSource { UriFormat = "http://{c}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png" }
|
||||
SourceName = "Stamen Terrain",
|
||||
Description = "Map tiles by [Stamen Design](http://stamen.com/), under [CC BY 3.0](http://creativecommons.org/licenses/by/3.0). Data by OpenStreetMap, under [ODbL](http://www.openstreetmap.org/copyright)",
|
||||
TileSource = new TileSource { UriFormat = "http://tile.stamen.com/terrain/{z}/{x}/{y}.png" },
|
||||
MaxZoomLevel = 17
|
||||
}
|
||||
},
|
||||
{
|
||||
"Thunderforest Landscape",
|
||||
"Stamen Toner Light",
|
||||
new MapTileLayer
|
||||
{
|
||||
SourceName = "Thunderforest Landscape",
|
||||
Description = "Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)",
|
||||
TileSource = new TileSource { UriFormat = "http://{c}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"Thunderforest Outdoors",
|
||||
new MapTileLayer
|
||||
{
|
||||
SourceName = "Thunderforest Outdoors",
|
||||
Description = "Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)",
|
||||
TileSource = new TileSource { UriFormat = "http://{c}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"Thunderforest Transport",
|
||||
new MapTileLayer
|
||||
{
|
||||
SourceName = "Thunderforest Transport",
|
||||
Description = "Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)",
|
||||
TileSource = new TileSource { UriFormat = "http://{c}.tile.thunderforest.com/transport/{z}/{x}/{y}.png" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"Thunderforest Transport Dark",
|
||||
new MapTileLayer
|
||||
{
|
||||
SourceName = "Thunderforest Transport Dark",
|
||||
Description = "Maps © [Thunderforest](http://www.thunderforest.com/), Data © [OpenStreetMap Contributors](http://www.openstreetmap.org/copyright)",
|
||||
TileSource = new TileSource { UriFormat = "http://{c}.tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png" },
|
||||
MapForeground = new SolidColorBrush(Colors.White),
|
||||
MapBackground = new SolidColorBrush(Colors.Black)
|
||||
SourceName = "Stamen Toner Light",
|
||||
Description = "Map tiles by [Stamen Design](http://stamen.com/), under [CC BY 3.0](http://creativecommons.org/licenses/by/3.0). Data by OpenStreetMap, under [ODbL](http://www.openstreetmap.org/copyright)",
|
||||
TileSource = new TileSource { UriFormat = "http://tile.stamen.com/toner-lite/{z}/{x}/{y}.png" },
|
||||
MaxZoomLevel = 18
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -172,12 +145,9 @@ namespace ViewModel
|
|||
public List<string> MapLayerNames { get; } = new List<string>
|
||||
{
|
||||
"OpenStreetMap",
|
||||
"OpenStreetMap German Style",
|
||||
"Thunderforest OpenCycleMap",
|
||||
//"Thunderforest Landscape",
|
||||
//"Thunderforest Outdoors",
|
||||
//"Thunderforest Transport",
|
||||
//"Thunderforest Transport Dark",
|
||||
"OpenStreetMap German",
|
||||
"Stamen Terrain",
|
||||
"Stamen Toner Light",
|
||||
"OpenStreetMap WMS",
|
||||
"OpenStreetMap TOPO WMS"
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ namespace UniversalApp
|
|||
{
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.Suspending += OnSuspending;
|
||||
InitializeComponent();
|
||||
Suspending += OnSuspending;
|
||||
}
|
||||
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs e)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<Style x:Key="PointItemStyle" TargetType="map:MapItem">
|
||||
<EventSetter Event="TouchDown" Handler="MapItemTouchDown"/>
|
||||
<Setter Property="Location" Value="{Binding Location}"/>
|
||||
<Setter Property="map:MapPanel.Location" Value="{Binding Location}"/>
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
|
||||
<Style x:Key="PushpinItemStyle" TargetType="map:MapItem">
|
||||
<EventSetter Event="TouchDown" Handler="MapItemTouchDown"/>
|
||||
<Setter Property="Location" Value="{Binding Location}"/>
|
||||
<Setter Property="map:MapPanel.Location" Value="{Binding Location}"/>
|
||||
<Setter Property="VerticalAlignment" Value="Bottom"/>
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="Visibility">
|
||||
|
|
@ -155,10 +155,10 @@
|
|||
ItemContainerStyle="{StaticResource PushpinItemStyle}"
|
||||
IsSynchronizedWithCurrentItem="True"/>
|
||||
|
||||
<map:Pushpin Location="65,-18" Content="Iceland"/>
|
||||
<map:Pushpin Location="71,25" Content="Norway"/>
|
||||
<map:Pushpin Location="35,33" Content="Cyprus"/>
|
||||
<map:Pushpin Location="28.25,-16.5" Content="Tenerife"/>
|
||||
<map:Pushpin map:MapPanel.Location="65,-18" Content="Iceland"/>
|
||||
<map:Pushpin map:MapPanel.Location="71,25" Content="Norway"/>
|
||||
<map:Pushpin map:MapPanel.Location="35,33" Content="Cyprus"/>
|
||||
<map:Pushpin map:MapPanel.Location="28.25,-16.5" Content="Tenerife"/>
|
||||
|
||||
<Path map:MapPanel.Location="53.5,8.2" Stroke="Blue" StrokeThickness="3" Fill="#1F007F00">
|
||||
<Path.Data>
|
||||
|
|
@ -166,7 +166,7 @@
|
|||
</Path.Data>
|
||||
</Path>
|
||||
|
||||
<map:Pushpin Location="53.5,8.2" Background="Yellow" Foreground="Blue" Content="N 53°30' E 8°12'">
|
||||
<map:Pushpin map:MapPanel.Location="53.5,8.2" Background="Yellow" Foreground="Blue" Content="N 53°30' E 8°12'">
|
||||
<map:Pushpin.Visibility>
|
||||
<MultiBinding Converter="{StaticResource LocationToVisibilityConverter}">
|
||||
<Binding Path="(map:MapPanel.ParentMap)" RelativeSource="{RelativeSource Self}"/>
|
||||
|
|
@ -177,7 +177,7 @@
|
|||
</map:Map>
|
||||
|
||||
<Border HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#7FFFFFFF">
|
||||
<TextBlock Margin="2" FontSize="10" map:HyperlinkText.InlinesSource="{Binding MapLayers.CurrentMapLayer.Description}"/>
|
||||
<TextBlock Margin="2" FontSize="10" map:HyperlinkText.InlinesSource="{Binding MapLayer.Description, ElementName=map}"/>
|
||||
</Border>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ namespace WpfApplication
|
|||
{
|
||||
if (e.ClickCount == 2)
|
||||
{
|
||||
map.TargetCenter = map.ViewportPointToLocation(e.GetPosition(map));
|
||||
//map.ZoomMap(e.GetPosition(map), Math.Floor(map.ZoomLevel + 1.5));
|
||||
//map.ZoomToBounds(new BoundingBox(53, 7, 54, 9));
|
||||
map.TargetCenter = map.ViewportPointToLocation(e.GetPosition(map));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ namespace WpfApplication
|
|||
{
|
||||
if (e.ClickCount == 2)
|
||||
{
|
||||
map.ZoomMap(e.GetPosition(map), Math.Ceiling(map.ZoomLevel - 1.5));
|
||||
//map.ZoomMap(e.GetPosition(map), Math.Ceiling(map.ZoomLevel - 1.5));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,12 +80,12 @@ namespace WpfApplication
|
|||
|
||||
private void SeamarksChecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
map.Children.Insert(map.Children.IndexOf(mapGraticule), ((MapViewModel)DataContext).MapLayers.SeamarksLayer);
|
||||
map.Children.Insert(map.Children.IndexOf(mapGraticule), (UIElement)Application.Current.Resources["Seamarks"]);
|
||||
}
|
||||
|
||||
private void SeamarksUnchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
map.Children.Remove(((MapViewModel)DataContext).MapLayers.SeamarksLayer);
|
||||
map.Children.Remove((UIElement)Application.Current.Resources["Seamarks"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue