| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- using System;
- using System.Collections.Specialized;
- using System.IO;
- using System.Linq;
- using System.Runtime.InteropServices;
- using Avalonia.Collections;
- using Avalonia.Controls;
- using Avalonia.Threading;
- namespace Avalonia.Dialogs
- {
- internal class ManagedFileChooserViewModel : InternalViewModelBase
- {
- public event Action CancelRequested;
- public event Action<string[]> CompleteRequested;
- public AvaloniaList<ManagedFileChooserItemViewModel> QuickLinks { get; } =
- new AvaloniaList<ManagedFileChooserItemViewModel>();
- public AvaloniaList<ManagedFileChooserItemViewModel> Items { get; } =
- new AvaloniaList<ManagedFileChooserItemViewModel>();
- public AvaloniaList<ManagedFileChooserFilterViewModel> Filters { get; } =
- new AvaloniaList<ManagedFileChooserFilterViewModel>();
- public AvaloniaList<ManagedFileChooserItemViewModel> SelectedItems { get; } =
- new AvaloniaList<ManagedFileChooserItemViewModel>();
- string _location;
- string _fileName;
- private bool _showHiddenFiles;
- private ManagedFileChooserFilterViewModel _selectedFilter;
- private bool _selectingDirectory;
- private bool _savingFile;
- private bool _scheduledSelectionValidation;
- private string _defaultExtension;
- public string Location
- {
- get => _location;
- private set => this.RaiseAndSetIfChanged(ref _location, value);
- }
- public string FileName
- {
- get => _fileName;
- private set => this.RaiseAndSetIfChanged(ref _fileName, value);
- }
- public bool SelectingFolder => _selectingDirectory;
- public bool ShowFilters { get; }
- public SelectionMode SelectionMode { get; }
- public string Title { get; }
- public int QuickLinksSelectedIndex
- {
- get
- {
- for (var index = 0; index < QuickLinks.Count; index++)
- {
- var i = QuickLinks[index];
- if (i.Path == Location)
- {
- return index;
- }
- }
- return -1;
- }
- set => this.RaisePropertyChanged(nameof(QuickLinksSelectedIndex));
- }
- public ManagedFileChooserFilterViewModel SelectedFilter
- {
- get => _selectedFilter;
- set
- {
- this.RaiseAndSetIfChanged(ref _selectedFilter, value);
- Refresh();
- }
- }
- public bool ShowHiddenFiles
- {
- get => _showHiddenFiles;
- set
- {
- this.RaiseAndSetIfChanged(ref _showHiddenFiles, value);
- Refresh();
- }
- }
- public ManagedFileChooserViewModel(FileSystemDialog dialog)
- {
- var quickSources = AvaloniaLocator.Current.GetService<ManagedFileChooserSources>()
- ?? new ManagedFileChooserSources();
- QuickLinks.Clear();
- QuickLinks.AddRange(quickSources.GetAllItems().Select(i => new ManagedFileChooserItemViewModel(i)));
- Title = dialog.Title ?? (
- dialog is OpenFileDialog ? "Open file"
- : dialog is SaveFileDialog ? "Save file"
- : dialog is OpenFolderDialog ? "Select directory"
- : throw new ArgumentException(nameof(dialog)));
- var directory = dialog.InitialDirectory;
- if (directory == null || !Directory.Exists(directory))
- {
- directory = Directory.GetCurrentDirectory();
- }
- if (dialog is FileDialog fd)
- {
- if (fd.Filters?.Count > 0)
- {
- Filters.AddRange(fd.Filters.Select(f => new ManagedFileChooserFilterViewModel(f)));
- _selectedFilter = Filters[0];
- ShowFilters = true;
- }
- if (dialog is OpenFileDialog ofd)
- {
- if (ofd.AllowMultiple)
- {
- SelectionMode = SelectionMode.Multiple;
- }
- }
- }
- _selectingDirectory = dialog is OpenFolderDialog;
- if(dialog is SaveFileDialog sfd)
- {
- _savingFile = true;
- _defaultExtension = sfd.DefaultExtension;
- FileName = sfd.InitialFileName;
- }
- Navigate(directory, (dialog as FileDialog)?.InitialFileName);
- SelectedItems.CollectionChanged += OnSelectionChangedAsync;
- }
- public void EnterPressed ()
- {
- if (Directory.Exists(Location))
- {
- Navigate(Location);
- }
- else if (File.Exists(Location))
- {
- CompleteRequested?.Invoke(new[] { Location });
- }
- }
- private async void OnSelectionChangedAsync(object sender, NotifyCollectionChangedEventArgs e)
- {
- if (_scheduledSelectionValidation)
- {
- return;
- }
- _scheduledSelectionValidation = true;
- await Dispatcher.UIThread.InvokeAsync(() =>
- {
- try
- {
- if (_selectingDirectory)
- {
- SelectedItems.Clear();
- }
- else
- {
- var invalidItems = SelectedItems.Where(i => i.IsDirectory).ToList();
- foreach (var item in invalidItems)
- {
- SelectedItems.Remove(item);
- }
- if(!_selectingDirectory)
- {
- FileName = SelectedItems.FirstOrDefault()?.DisplayName;
- }
- }
- }
- finally
- {
- _scheduledSelectionValidation = false;
- }
- });
- }
- void NavigateRoot(string initialSelectionName)
- {
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- Navigate(Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)), initialSelectionName);
- }
- else
- {
- Navigate("/", initialSelectionName);
- }
- }
- public void Refresh() => Navigate(Location);
- public void Navigate(string path, string initialSelectionName = null)
- {
- if (!Directory.Exists(path))
- {
- NavigateRoot(initialSelectionName);
- }
- else
- {
- Location = path;
- Items.Clear();
- SelectedItems.Clear();
- try
- {
- var infos = new DirectoryInfo(path).EnumerateFileSystemInfos();
- if (!ShowHiddenFiles)
- {
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- infos = infos.Where(i => (i.Attributes & (FileAttributes.Hidden | FileAttributes.System)) != 0);
- }
- else
- {
- infos = infos.Where(i => !i.Name.StartsWith("."));
- }
- }
- if (SelectedFilter != null)
- {
- infos = infos.Where(i => i is DirectoryInfo || SelectedFilter.Match(i.Name));
- }
- Items.AddRange(infos.Where(x =>
- {
- if (_selectingDirectory)
- {
- if (!(x is DirectoryInfo))
- {
- return false;
- }
- }
- return true;
- })
- .Where(x => x.Exists)
- .Select(info => new ManagedFileChooserItemViewModel
- {
- DisplayName = info.Name,
- Path = info.FullName,
- IsDirectory = info is DirectoryInfo,
- Type = info is FileInfo ? info.Extension : "File Folder",
- Size = info is FileInfo f ? f.Length : 0,
- Modified = info.LastWriteTime
- })
- .OrderByDescending(x => x.IsDirectory)
- .ThenBy(x => x.DisplayName, StringComparer.InvariantCultureIgnoreCase));
- if (initialSelectionName != null)
- {
- var sel = Items.FirstOrDefault(i => !i.IsDirectory && i.DisplayName == initialSelectionName);
- if (sel != null)
- {
- SelectedItems.Add(sel);
- }
- }
- this.RaisePropertyChanged(nameof(QuickLinksSelectedIndex));
- }
- catch (System.UnauthorizedAccessException)
- {
- }
- }
- }
- public void GoUp()
- {
- var parent = Path.GetDirectoryName(Location);
- if (string.IsNullOrWhiteSpace(parent))
- {
- return;
- }
- Navigate(parent);
- }
- public void Cancel()
- {
- CancelRequested?.Invoke();
- }
- public void Ok()
- {
- if (_selectingDirectory)
- {
- CompleteRequested?.Invoke(new[] { Location });
- }
- else if(_savingFile)
- {
- if (!string.IsNullOrWhiteSpace(FileName))
- {
- if (!Path.HasExtension(FileName) && !string.IsNullOrWhiteSpace(_defaultExtension))
- {
- FileName = Path.ChangeExtension(FileName, _defaultExtension);
- }
- CompleteRequested?.Invoke(new[] { Path.Combine(Location, FileName) });
- }
- }
- else
- {
- CompleteRequested?.Invoke(SelectedItems.Select(i => i.Path).ToArray());
- }
- }
- public void SelectSingleFile(ManagedFileChooserItemViewModel item)
- {
- CompleteRequested?.Invoke(new[] { item.Path });
- }
- }
- }
|