Refactor path handling in UI components
- Removed redundant folder and file opening methods from AiTabView and FaceAiTabView. - Introduced PathPickerField control to streamline path selection and opening functionality across multiple views. - Updated FaceAiTabView and GeneralTabView to utilize PathPickerField for source and destination path selection. - Created PathShellService to encapsulate logic for opening paths in the file explorer. - Simplified XAML structure by replacing manual grid definitions with PathPickerField components. - Removed unused namespaces and cleaned up code for better readability and maintainability.
This commit is contained in:
parent
f3ac1ea920
commit
398cfa310e
10 changed files with 484 additions and 562 deletions
285
imagecatalog/Controls/PathPickerField.axaml.cs
Normal file
285
imagecatalog/Controls/PathPickerField.axaml.cs
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
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<string> LabelProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, string>(nameof(Label), string.Empty);
|
||||
|
||||
public static readonly StyledProperty<string> TextProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, string>(nameof(Text), string.Empty, defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
public static readonly StyledProperty<string> WatermarkProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, string>(nameof(Watermark), string.Empty);
|
||||
|
||||
public static readonly StyledProperty<string> PreferenceKeyProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, string>(nameof(PreferenceKey), string.Empty);
|
||||
|
||||
public static readonly StyledProperty<string> PickerTitleProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, string>(nameof(PickerTitle), string.Empty);
|
||||
|
||||
public static readonly StyledProperty<string> FileTypeNameProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, string>(nameof(FileTypeName), string.Empty);
|
||||
|
||||
public static readonly StyledProperty<string> FilePatternsProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, string>(nameof(FilePatterns), string.Empty);
|
||||
|
||||
public static readonly StyledProperty<string> DefaultExtensionProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, string>(nameof(DefaultExtension), string.Empty);
|
||||
|
||||
public static readonly StyledProperty<PathPickerSelectionMode> PickerModeProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, PathPickerSelectionMode>(nameof(PickerMode), PathPickerSelectionMode.Folder);
|
||||
|
||||
public static readonly StyledProperty<bool> IsTextReadOnlyProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, bool>(nameof(IsTextReadOnly), false);
|
||||
|
||||
public static readonly StyledProperty<bool> ShowPickerButtonProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, bool>(nameof(ShowPickerButton), true);
|
||||
|
||||
public static readonly StyledProperty<bool> AppendDirectorySeparatorProperty =
|
||||
AvaloniaProperty.Register<PathPickerField, bool>(nameof(AppendDirectorySeparator), false);
|
||||
|
||||
public PathPickerField()
|
||||
{
|
||||
_pickerPreferenceService = Program.ServiceProvider.GetRequiredService<PickerPreferenceService>();
|
||||
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<string?> 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<IStorageFolder?> TryGetSuggestedStartLocationAsync(IStorageProvider storageProvider)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(PreferenceKey))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return await _pickerPreferenceService.TryGetStartFolderAsync(storageProvider, PreferenceKey, Text);
|
||||
}
|
||||
|
||||
private IReadOnlyList<FilePickerFileType> BuildFileTypes()
|
||||
{
|
||||
var patterns = (FilePatterns ?? string.Empty)
|
||||
.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
|
||||
if (patterns.Length == 0)
|
||||
{
|
||||
return Array.Empty<FilePickerFileType>();
|
||||
}
|
||||
|
||||
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('.');
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue