using Avalonia; using Avalonia.Controls; using Avalonia.Data; using Avalonia.Platform.Storage; using ImageCatalog_2.Services; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace ImageCatalog_2.Controls; public partial class PathPickerField : UserControl { private readonly PickerPreferenceService _pickerPreferenceService; public static readonly StyledProperty LabelProperty = AvaloniaProperty.Register(nameof(Label), string.Empty); public static readonly StyledProperty TextProperty = AvaloniaProperty.Register(nameof(Text), string.Empty, defaultBindingMode: BindingMode.TwoWay); public static readonly StyledProperty WatermarkProperty = AvaloniaProperty.Register(nameof(Watermark), string.Empty); public static readonly StyledProperty PreferenceKeyProperty = AvaloniaProperty.Register(nameof(PreferenceKey), string.Empty); public static readonly StyledProperty PickerTitleProperty = AvaloniaProperty.Register(nameof(PickerTitle), string.Empty); public static readonly StyledProperty FileTypeNameProperty = AvaloniaProperty.Register(nameof(FileTypeName), string.Empty); public static readonly StyledProperty FilePatternsProperty = AvaloniaProperty.Register(nameof(FilePatterns), string.Empty); public static readonly StyledProperty DefaultExtensionProperty = AvaloniaProperty.Register(nameof(DefaultExtension), string.Empty); public static readonly StyledProperty PickerModeProperty = AvaloniaProperty.Register(nameof(PickerMode), PathPickerSelectionMode.Folder); public static readonly StyledProperty IsTextReadOnlyProperty = AvaloniaProperty.Register(nameof(IsTextReadOnly), false); public static readonly StyledProperty ShowPickerButtonProperty = AvaloniaProperty.Register(nameof(ShowPickerButton), true); public static readonly StyledProperty AppendDirectorySeparatorProperty = AvaloniaProperty.Register(nameof(AppendDirectorySeparator), false); public PathPickerField() { _pickerPreferenceService = Program.ServiceProvider.GetRequiredService(); InitializeComponent(); } public string Label { get => GetValue(LabelProperty); set => SetValue(LabelProperty, value); } public string Text { get => GetValue(TextProperty); set => SetValue(TextProperty, value); } public string Watermark { get => GetValue(WatermarkProperty); set => SetValue(WatermarkProperty, value); } public string PreferenceKey { get => GetValue(PreferenceKeyProperty); set => SetValue(PreferenceKeyProperty, value); } public string PickerTitle { get => GetValue(PickerTitleProperty); set => SetValue(PickerTitleProperty, value); } public string FileTypeName { get => GetValue(FileTypeNameProperty); set => SetValue(FileTypeNameProperty, value); } public string FilePatterns { get => GetValue(FilePatternsProperty); set => SetValue(FilePatternsProperty, value); } public string DefaultExtension { get => GetValue(DefaultExtensionProperty); set => SetValue(DefaultExtensionProperty, value); } public PathPickerSelectionMode PickerMode { get => GetValue(PickerModeProperty); set => SetValue(PickerModeProperty, value); } public bool IsTextReadOnly { get => GetValue(IsTextReadOnlyProperty); set => SetValue(IsTextReadOnlyProperty, value); } public bool ShowPickerButton { get => GetValue(ShowPickerButtonProperty); set => SetValue(ShowPickerButtonProperty, value); } public bool AppendDirectorySeparator { get => GetValue(AppendDirectorySeparatorProperty); set => SetValue(AppendDirectorySeparatorProperty, value); } private async void PickPath_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) { var topLevel = TopLevel.GetTopLevel(this); var storageProvider = topLevel?.StorageProvider; if (storageProvider is null) { return; } var selectedPath = await PickPathAsync(storageProvider); if (string.IsNullOrWhiteSpace(selectedPath)) { return; } Text = selectedPath; if (!string.IsNullOrWhiteSpace(PreferenceKey)) { _pickerPreferenceService.RememberPath(PreferenceKey, selectedPath); } } private void OpenPath_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) { PathShellService.OpenInExplorer(Text); } private async Task PickPathAsync(IStorageProvider storageProvider) { var suggestedStartLocation = await TryGetSuggestedStartLocationAsync(storageProvider); var pickerTitle = ResolvePickerTitle(); switch (PickerMode) { case PathPickerSelectionMode.Folder: { var folders = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions { Title = pickerTitle, SuggestedStartLocation = suggestedStartLocation }); return folders.Count == 0 ? null : NormalizeSelectedPath(folders[0].Path.LocalPath); } case PathPickerSelectionMode.OpenFile: { var files = await storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { Title = pickerTitle, SuggestedStartLocation = suggestedStartLocation, FileTypeFilter = BuildFileTypes() }); return files.Count == 0 ? null : files[0].Path.LocalPath; } case PathPickerSelectionMode.SaveFile: { var file = await storageProvider.SaveFilePickerAsync(new FilePickerSaveOptions { Title = pickerTitle, SuggestedStartLocation = suggestedStartLocation, DefaultExtension = NormalizeDefaultExtension(DefaultExtension), FileTypeChoices = BuildFileTypes() }); return file?.Path.LocalPath; } default: return null; } } private async Task TryGetSuggestedStartLocationAsync(IStorageProvider storageProvider) { if (string.IsNullOrWhiteSpace(PreferenceKey)) { return null; } return await _pickerPreferenceService.TryGetStartFolderAsync(storageProvider, PreferenceKey, Text); } private IReadOnlyList BuildFileTypes() { var patterns = (FilePatterns ?? string.Empty) .Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); if (patterns.Length == 0) { return Array.Empty(); } var fileTypeName = string.IsNullOrWhiteSpace(FileTypeName) ? "File" : FileTypeName.Trim(); return [ new FilePickerFileType(fileTypeName) { Patterns = patterns.ToList() } ]; } private string ResolvePickerTitle() { if (!string.IsNullOrWhiteSpace(PickerTitle)) { return PickerTitle; } var cleanedLabel = string.IsNullOrWhiteSpace(Label) ? "percorso" : Label.Trim().TrimEnd(':'); return PickerMode == PathPickerSelectionMode.SaveFile ? $"Salva {cleanedLabel.ToLowerInvariant()}" : $"Seleziona {cleanedLabel.ToLowerInvariant()}"; } private string NormalizeSelectedPath(string selectedPath) { if (PickerMode != PathPickerSelectionMode.Folder || !AppendDirectorySeparator) { return selectedPath; } if (string.IsNullOrWhiteSpace(selectedPath)) { return string.Empty; } return selectedPath.EndsWith(Path.DirectorySeparatorChar) || selectedPath.EndsWith(Path.AltDirectorySeparatorChar) ? selectedPath : selectedPath + Path.DirectorySeparatorChar; } private static string NormalizeDefaultExtension(string extension) { if (string.IsNullOrWhiteSpace(extension)) { return string.Empty; } return extension.Trim().TrimStart('.'); } }