File scoped namespaces

This commit is contained in:
ClemensFischer 2026-04-13 17:14:49 +02:00
parent c14377f976
commit 65aba44af6
152 changed files with 11962 additions and 12115 deletions

View file

@ -11,86 +11,85 @@ using Microsoft.UI.Xaml;
using DependencyProperty = Avalonia.AvaloniaProperty;
#endif
namespace MapControl.MBTiles
namespace MapControl.MBTiles;
/// <summary>
/// MapTileLayer that uses an MBTiles SQLite Database. See https://wiki.openstreetmap.org/wiki/MBTiles.
/// </summary>
public class MBTileLayer : MapTileLayer
{
/// <summary>
/// MapTileLayer that uses an MBTiles SQLite Database. See https://wiki.openstreetmap.org/wiki/MBTiles.
/// </summary>
public class MBTileLayer : MapTileLayer
private static ILogger Logger => field ??= ImageLoader.LoggerFactory?.CreateLogger<MBTileLayer>();
public static readonly DependencyProperty FileProperty =
DependencyPropertyHelper.Register<MBTileLayer, string>(nameof(File), null,
async (layer, oldValue, newValue) => await layer.FilePropertyChanged(newValue));
public string File
{
private static ILogger Logger => field ??= ImageLoader.LoggerFactory?.CreateLogger<MBTileLayer>();
get => (string)GetValue(FileProperty);
set => SetValue(FileProperty, value);
}
public static readonly DependencyProperty FileProperty =
DependencyPropertyHelper.Register<MBTileLayer, string>(nameof(File), null,
async (layer, oldValue, newValue) => await layer.FilePropertyChanged(newValue));
/// <summary>
/// May be overridden to create a derived MBTileSource that handles other tile formats than png and jpg.
/// </summary>
protected virtual async Task<MBTileSource> CreateTileSourceAsync(string file)
{
var tileSource = new MBTileSource();
public string File
await tileSource.OpenAsync(file);
if (tileSource.Metadata.TryGetValue("format", out string format) && format != "png" && format != "jpg")
{
get => (string)GetValue(FileProperty);
set => SetValue(FileProperty, value);
tileSource.Dispose();
throw new NotSupportedException($"Tile image format {format} is not supported.");
}
/// <summary>
/// May be overridden to create a derived MBTileSource that handles other tile formats than png and jpg.
/// </summary>
protected virtual async Task<MBTileSource> CreateTileSourceAsync(string file)
return tileSource;
}
private async Task FilePropertyChanged(string file)
{
(TileSource as MBTileSource)?.Close();
ClearValue(TileSourceProperty);
ClearValue(SourceNameProperty);
ClearValue(DescriptionProperty);
ClearValue(MinZoomLevelProperty);
ClearValue(MaxZoomLevelProperty);
if (!string.IsNullOrEmpty(file))
{
var tileSource = new MBTileSource();
await tileSource.OpenAsync(file);
if (tileSource.Metadata.TryGetValue("format", out string format) && format != "png" && format != "jpg")
try
{
tileSource.Dispose();
var tileSource = await CreateTileSourceAsync(file);
throw new NotSupportedException($"Tile image format {format} is not supported.");
TileSource = tileSource;
if (tileSource.Metadata.TryGetValue("name", out string value))
{
SourceName = value;
}
if (tileSource.Metadata.TryGetValue("description", out value))
{
Description = value;
}
if (tileSource.Metadata.TryGetValue("minzoom", out value) && int.TryParse(value, out int zoomLevel))
{
MinZoomLevel = zoomLevel;
}
if (tileSource.Metadata.TryGetValue("maxzoom", out value) && int.TryParse(value, out zoomLevel))
{
MaxZoomLevel = zoomLevel;
}
}
return tileSource;
}
private async Task FilePropertyChanged(string file)
{
(TileSource as MBTileSource)?.Close();
ClearValue(TileSourceProperty);
ClearValue(SourceNameProperty);
ClearValue(DescriptionProperty);
ClearValue(MinZoomLevelProperty);
ClearValue(MaxZoomLevelProperty);
if (!string.IsNullOrEmpty(file))
catch (Exception ex)
{
try
{
var tileSource = await CreateTileSourceAsync(file);
TileSource = tileSource;
if (tileSource.Metadata.TryGetValue("name", out string value))
{
SourceName = value;
}
if (tileSource.Metadata.TryGetValue("description", out value))
{
Description = value;
}
if (tileSource.Metadata.TryGetValue("minzoom", out value) && int.TryParse(value, out int zoomLevel))
{
MinZoomLevel = zoomLevel;
}
if (tileSource.Metadata.TryGetValue("maxzoom", out value) && int.TryParse(value, out zoomLevel))
{
MaxZoomLevel = zoomLevel;
}
}
catch (Exception ex)
{
Logger?.LogError(ex, "Invalid file: {file}", file);
}
Logger?.LogError(ex, "Invalid file: {file}", file);
}
}
}

View file

@ -13,74 +13,73 @@ using Microsoft.UI.Xaml.Media;
using ImageSource = Avalonia.Media.IImage;
#endif
namespace MapControl.MBTiles
namespace MapControl.MBTiles;
public sealed partial class MBTileSource : TileSource, IDisposable
{
public sealed partial class MBTileSource : TileSource, IDisposable
private static ILogger Logger => field ??= ImageLoader.LoggerFactory?.CreateLogger<MBTileSource>();
private SQLiteConnection connection;
public IDictionary<string, string> Metadata { get; } = new Dictionary<string, string>();
public async Task OpenAsync(string file)
{
private static ILogger Logger => field ??= ImageLoader.LoggerFactory?.CreateLogger<MBTileSource>();
Close();
private SQLiteConnection connection;
connection = new SQLiteConnection("Data Source=" + FilePath.GetFullPath(file) + ";Read Only=True");
public IDictionary<string, string> Metadata { get; } = new Dictionary<string, string>();
await connection.OpenAsync();
public async Task OpenAsync(string file)
using var command = new SQLiteCommand("select * from metadata", connection);
var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
Close();
connection = new SQLiteConnection("Data Source=" + FilePath.GetFullPath(file) + ";Read Only=True");
await connection.OpenAsync();
using var command = new SQLiteCommand("select * from metadata", connection);
var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
Metadata[(string)reader["name"]] = (string)reader["value"];
}
}
public void Close()
{
if (connection != null)
{
Metadata.Clear();
connection.Dispose();
connection = null;
}
}
public void Dispose()
{
Close();
}
public override async Task<ImageSource> LoadImageAsync(int zoomLevel, int column, int row)
{
ImageSource image = 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", column);
command.Parameters.AddWithValue("@y", (1 << zoomLevel) - row - 1);
var buffer = (byte[])await command.ExecuteScalarAsync();
if (buffer?.Length > 0)
{
image = await ImageLoader.LoadImageAsync(buffer);
}
}
catch (Exception ex)
{
Logger?.LogError(ex, "LoadImageAsync");
}
return image;
Metadata[(string)reader["name"]] = (string)reader["value"];
}
}
public void Close()
{
if (connection != null)
{
Metadata.Clear();
connection.Dispose();
connection = null;
}
}
public void Dispose()
{
Close();
}
public override async Task<ImageSource> LoadImageAsync(int zoomLevel, int column, int row)
{
ImageSource image = 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", column);
command.Parameters.AddWithValue("@y", (1 << zoomLevel) - row - 1);
var buffer = (byte[])await command.ExecuteScalarAsync();
if (buffer?.Length > 0)
{
image = await ImageLoader.LoadImageAsync(buffer);
}
}
catch (Exception ex)
{
Logger?.LogError(ex, "LoadImageAsync");
}
return image;
}
}