This commit is contained in:
Wiesław Šoltés 2022-08-07 10:58:03 +02:00
Родитель aefee86940
Коммит e0bb800877
4 изменённых файлов: 143 добавлений и 43 удалений

Просмотреть файл

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Media;
namespace TraceGui.Model;
@ -24,9 +25,10 @@ static class SvgWriter
return sb.ToString();
}
public static void Save(int width, int height, IEnumerable<PathGeometry> paths, string filename, string fillColor = "#000000")
public static async Task Save(int width, int height, IEnumerable<PathGeometry> paths, Stream stream, string fillColor = "#000000")
{
var svg = ToSvg(width, height, paths, fillColor);
File.WriteAllText(filename, svg);
await using var writer = new StreamWriter(stream);
await writer.WriteAsync(svg);
}
}
}

Просмотреть файл

@ -5,10 +5,8 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Media;
using Avalonia.Platform.Storage;
using BitmapToVector;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
@ -136,69 +134,109 @@ public class MainWindowViewModel : ViewModelBase
set => this.RaiseAndSetIfChanged(ref _fillColor, value);
}
private List<FilePickerFileType> GetOpenFileTypes()
{
return new List<FilePickerFileType>
{
StorageService.ImageAll,
StorageService.All
};
}
private static List<FilePickerFileType> GetSaveFileTypes()
{
return new List<FilePickerFileType>
{
StorageService.ImageSvg,
StorageService.All
};
}
private async Task OnOpen()
{
var dlg = new OpenFileDialog();
dlg.Filters.Add(new FileDialogFilter()
var storageProvider = StorageService.GetStorageProvider();
if (storageProvider is null)
{
Name = "Supported Files (*.png;*.jpg;*.jpeg;*.bmp)",
Extensions = new List<string> {"png", "jpg", "jpeg", "bmp"}
return;
}
var result = await storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
Title = "Open image",
FileTypeFilter = GetOpenFileTypes(),
AllowMultiple = false
});
dlg.Filters.Add(new FileDialogFilter()
{
Name = "All Files",
Extensions = new List<string> {"*"}
});
var file = result.FirstOrDefault();
var result = await dlg.ShowAsync(GetMainWindow());
if (result is not null && result.Length == 1)
if (file is not null && file.CanOpenRead)
{
Load(result[0]);
try
{
await using var stream = await file.OpenReadAsync();
Load(stream, file.Name);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
}
}
}
private async Task OnSave()
{
var dlg = new SaveFileDialog();
dlg.Filters.Add(new FileDialogFilter()
var storageProvider = StorageService.GetStorageProvider();
if (storageProvider is null)
{
Name = "Svg Files (*.svg)",
Extensions = new List<string> {"svg"}
return;
}
var file = await storageProvider.SaveFilePickerAsync(new FilePickerSaveOptions
{
Title = "Save drawing",
FileTypeChoices = GetSaveFileTypes(),
SuggestedFileName = Path.GetFileNameWithoutExtension(_fileName),
DefaultExtension = "svg",
ShowOverwritePrompt = true
});
dlg.InitialFileName = Path.GetFileNameWithoutExtension(_fileName);
var result = await dlg.ShowAsync(GetMainWindow());
if (result is not null)
if (file is not null && file.CanOpenWrite)
{
Save(result);
try
{
await using var stream = await file.OpenWriteAsync();
await Save(stream);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
}
}
}
private void Save(string filename)
private async Task Save(Stream stream)
{
if (_paths is not null)
{
SvgWriter.Save(Width, _height, _paths, filename, FillColor);
await SvgWriter.Save(Width, _height, _paths, stream, FillColor);
}
}
public void Load(string filename)
public void Load(Stream stream, string filename)
{
Decode(filename);
Decode(stream);
Trace();
FileName = filename;
}
private void Decode(string filename)
private void Decode(Stream stream)
{
_source?.Dispose();
_source = SixLabors.ImageSharp.Image.Load<Rgba32>(filename);
_source = SixLabors.ImageSharp.Image.Load<Rgba32>(stream);
}
private async void Trace()
@ -219,7 +257,7 @@ public class MainWindowViewModel : ViewModelBase
};
static bool DefaultFilter(Rgba32 c) => c.R < 128;
Func<Rgba32, bool> filter = DefaultFilter;
var filter = DefaultFilter;
try
{
@ -245,9 +283,4 @@ public class MainWindowViewModel : ViewModelBase
var compiledFilter = await CSharpScript.EvaluateAsync<Func<Rgba32, bool>>(code, options);
return compiledFilter;
}
private Window? GetMainWindow()
{
return (Application.Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow;
}
}

Просмотреть файл

@ -0,0 +1,63 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage;
using Avalonia.VisualTree;
namespace TraceGui.ViewModels;
internal static class StorageService
{
public static FilePickerFileType All { get; } = new("All")
{
Patterns = new[] { "*.*" },
MimeTypes = new[] { "*/*" }
};
public static FilePickerFileType ImageSvg { get; } = new("Svg")
{
Patterns = new[] { "*.svg" },
AppleUniformTypeIdentifiers = new[] { "public.svg-image" },
MimeTypes = new[] { "image/svg+xml" }
};
public static FilePickerFileType ImagePng { get; } = new("PNG image")
{
Patterns = new[] { "*.png" },
AppleUniformTypeIdentifiers = new[] { "public.png" },
MimeTypes = new[] { "image/png" }
};
public static FilePickerFileType ImageJpg { get; } = new("JPEG image")
{
Patterns = new[] { "*.jpg", "*.jpeg" },
AppleUniformTypeIdentifiers = new[] { "public.jpeg" },
MimeTypes = new[] { "image/jpeg" }
};
public static FilePickerFileType ImageAll { get; } = new("All Images")
{
Patterns = new[] { "*.png", "*.jpg", "*.jpeg", "*.bmp" },
AppleUniformTypeIdentifiers = new[] { "public.image" },
MimeTypes = new[] { "image/*" }
};
public static IStorageProvider? GetStorageProvider()
{
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } window })
{
return window.StorageProvider;
}
if (Application.Current?.ApplicationLifetime is ISingleViewApplicationLifetime { MainView: { } mainView })
{
var visualRoot = mainView.GetVisualRoot();
if (visualRoot is TopLevel topLevel)
{
return topLevel.StorageProvider;
}
}
return null;
}
}

Просмотреть файл

@ -1,4 +1,5 @@
using System.Linq;
using System.IO;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
@ -39,7 +40,8 @@ public class MainView : UserControl
{
if (DataContext is MainWindowViewModel vm)
{
vm.Load(fileName);
using var stream = File.OpenRead(fileName);
vm.Load(stream, fileName);
}
}
}