diff --git a/src/SmartCommander/Models/OptionsModel.cs b/src/SmartCommander/Models/OptionsModel.cs index 78b346a..379a808 100644 --- a/src/SmartCommander/Models/OptionsModel.cs +++ b/src/SmartCommander/Models/OptionsModel.cs @@ -1,4 +1,6 @@ using Newtonsoft.Json; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using static System.Environment; @@ -56,5 +58,6 @@ static OptionsModel() public bool AllowOnlyOneInstance { get; set; } = true; public string Language { get; set; } = "en-US"; + public List ListerPlugins { get; set; }= new List(); } } diff --git a/src/SmartCommander/Plugins/PluginManager.cs b/src/SmartCommander/Plugins/PluginManager.cs index 18313a1..f884a1f 100644 --- a/src/SmartCommander/Plugins/PluginManager.cs +++ b/src/SmartCommander/Plugins/PluginManager.cs @@ -4,11 +4,9 @@ namespace SmartCommander.Plugins; public static class PluginManager { - public static ListerPluginWrapper CreateListerWrapper() + public static ListerPluginWrapper CreateListerWrapper(string Filename) { - //string pluginPath = "C:\\totalcmd\\plugins\\CodeViewer\\CodeViewer.wlx64"; - string pluginPath = "C:\\totalcmd\\plugins\\wlx\\CodeViewer\\CodeViewer.wlx64"; - return new ListerPluginWrapper(pluginPath); + return new ListerPluginWrapper(Filename); } public static IntPtr CreateListerWindow(this ListerPluginWrapper listerWrapper, IntPtr parentWindowHandle, string fileToLoad) diff --git a/src/SmartCommander/ViewModels/OptionsViewModel.cs b/src/SmartCommander/ViewModels/OptionsViewModel.cs index 890e9b6..84aebf0 100644 --- a/src/SmartCommander/ViewModels/OptionsViewModel.cs +++ b/src/SmartCommander/ViewModels/OptionsViewModel.cs @@ -1,4 +1,8 @@ -using Avalonia.Controls; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Platform.Storage; +using AvaloniaEdit.Utils; using ReactiveUI; using SmartCommander.Assets; using SmartCommander.Models; @@ -18,6 +22,15 @@ public class OptionsViewModel : ViewModelBase public CultureInfo SelectedCulture { get; set; } + + public ObservableCollection ListerPlugins { get; set; } = new(); + private string _selectedPlugin = string.Empty; + public string SelectedPlugin + { + get => _selectedPlugin; + set => this.RaiseAndSetIfChanged(ref _selectedPlugin, value); + } + private static IEnumerable GetAvailableCultures() { List result = new List(); @@ -26,14 +39,15 @@ private static IEnumerable GetAvailableCultures() foreach (CultureInfo culture in cultures) { - if (culture.Equals(CultureInfo.InvariantCulture)) { - result.Add(new CultureInfo("en-US")); - continue; - } - - ResourceSet? rs = rm?.GetResourceSet(culture, true, false); - if (rs != null) - result.Add(culture); + if (culture.Equals(CultureInfo.InvariantCulture)) + { + result.Add(new CultureInfo("en-US")); + continue; + } + + ResourceSet? rs = rm?.GetResourceSet(culture, true, false); + if (rs != null) + result.Add(culture); } return result; } @@ -42,7 +56,7 @@ public OptionsViewModel() { OKCommand = ReactiveCommand.Create(SaveClose); CancelCommand = ReactiveCommand.Create(Close); - + IsCurrentDirectoryDisplayed = Model.IsCurrentDirectoryDisplayed; IsFunctionKeysDisplayed = Model.IsFunctionKeysDisplayed; IsCommandLineDisplayed = Model.IsCommandLineDisplayed; @@ -56,9 +70,13 @@ public OptionsViewModel() AvailableCultures = new ObservableCollection(GetAvailableCultures()); var lang = AvailableCultures.First(x => x.Name == Model.Language); SelectedCulture = lang ?? AvailableCultures.First(); + + ListerPlugins.AddRange(Model.ListerPlugins); + AddFileCommand = ReactiveCommand.Create(AddFileAsync); + RemoveFileCommand = ReactiveCommand.Create(RemoveFile); } - public bool IsCurrentDirectoryDisplayed { get; set; } + public bool IsCurrentDirectoryDisplayed { get; set; } public bool IsFunctionKeysDisplayed { get; set; } @@ -72,11 +90,44 @@ public OptionsViewModel() public bool SaveWindowPositionSize { get; set; } - public bool IsDarkThemeEnabled { get; set; } - public bool AllowOnlyOneInstance { get; set; } + public bool IsDarkThemeEnabled { get; set; } + public bool AllowOnlyOneInstance { get; set; } public ReactiveCommand OKCommand { get; } public ReactiveCommand CancelCommand { get; } + public ReactiveCommand AddFileCommand { get; } + public ReactiveCommand RemoveFileCommand { get; } + private void RemoveFile(Window window) + { + if (!string.IsNullOrWhiteSpace(SelectedPlugin)) + { + ListerPlugins?.Remove(SelectedPlugin); + } + } + + public static FilePickerFileType ListerPluginsFilter { get; } = new("Lister Plugins (64bit)") + { + Patterns = new[] { /*"*.wlx",*/ "*.wlx64" } + }; + private void AddFileAsync(Window window) + { + var desktop = (IClassicDesktopStyleApplicationLifetime?)Application.Current?.ApplicationLifetime; + var topLevel = TopLevel.GetTopLevel(desktop?.MainWindow); + var files = topLevel?.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + { + Title = "Choose plugin", + AllowMultiple = false, + FileTypeFilter = new[] { ListerPluginsFilter } + }).Result; + + if (files?.Count >= 1) + { + var filename = files.First().Path.LocalPath; + + if (ListerPlugins.IndexOf(filename)==-1) + ListerPlugins.Add(filename); + } + } public void SaveClose(Window window) { @@ -90,10 +141,11 @@ public void SaveClose(Window window) Model.IsDarkThemeEnabled = IsDarkThemeEnabled; Model.Language = SelectedCulture.Name; Model.AllowOnlyOneInstance = AllowOnlyOneInstance; + Model.ListerPlugins = ListerPlugins.ToList(); Model.Save(); window?.Close(this); - + } public void Close(Window window) diff --git a/src/SmartCommander/Views/FileSearchWindow.axaml b/src/SmartCommander/Views/FileSearchWindow.axaml index 133bfad..81504e8 100644 --- a/src/SmartCommander/Views/FileSearchWindow.axaml +++ b/src/SmartCommander/Views/FileSearchWindow.axaml @@ -49,7 +49,7 @@ - + diff --git a/src/SmartCommander/Views/OptionsWindow.axaml b/src/SmartCommander/Views/OptionsWindow.axaml index d267cdc..d264c03 100644 --- a/src/SmartCommander/Views/OptionsWindow.axaml +++ b/src/SmartCommander/Views/OptionsWindow.axaml @@ -2,70 +2,85 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="350" - Width="600" Height="350" + mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="400" + Width="600" Height="400" x:Class="SmartCommander.Views.OptionsWindow" ShowInTaskbar="False" Icon="/Assets/main.ico" - WindowStartupLocation="CenterOwner" + WindowStartupLocation="CenterOwner" xmlns:assets="clr-namespace:SmartCommander.Assets" Title="{x:Static assets:Resources.Options}"> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + diff --git a/src/SmartCommander/Views/ViewerWindow.axaml.cs b/src/SmartCommander/Views/ViewerWindow.axaml.cs index 4fbddb3..45b88c1 100644 --- a/src/SmartCommander/Views/ViewerWindow.axaml.cs +++ b/src/SmartCommander/Views/ViewerWindow.axaml.cs @@ -1,6 +1,7 @@ using Avalonia.Controls; using Avalonia.Controls.Platform; using Avalonia.Platform; +using SmartCommander.Models; using SmartCommander.Plugins; using SmartCommander.ViewModels; using System; @@ -13,8 +14,9 @@ public partial class ViewerWindow : Window public ViewerWindow() { InitializeComponent(); - this.Opened += OnWindowOpened; + this.Opened+= OnWindowOpened; } + private void OnWindowOpened(object? sender, EventArgs e) { var grid = this.FindControl("GridPanel"); @@ -22,7 +24,7 @@ private void OnWindowOpened(object? sender, EventArgs e) { var viewModel = this.DataContext as ViewerViewModel; - if (OperatingSystem.IsWindows()) + if (OperatingSystem.IsWindows() && OptionsModel.Instance.ListerPlugins.Count > 0) { var embed = new EmbedSample(viewModel!.Filename); if (embed.CanShowByPlugin) @@ -31,7 +33,6 @@ private void OnWindowOpened(object? sender, EventArgs e) } } } - } } @@ -48,7 +49,7 @@ public void Destroy() public class EmbedSample : NativeControlHost { - ListerPluginWrapper listerPluginWrapper { get; set; } + ListerPluginWrapper? listerPluginWrapper { get; set; } IntPtr listerWindowHandle { get; set; } public bool CanShowByPlugin @@ -63,8 +64,25 @@ public EmbedSample(string Filename) { HorizontalAlignment = 0; VerticalAlignment = 0; - listerPluginWrapper = PluginManager.CreateListerWrapper(); - listerWindowHandle = listerPluginWrapper.CreateListerWindow(IntPtr.Zero, Filename); + + foreach (var ListerFileName in OptionsModel.Instance.ListerPlugins) + { + listerPluginWrapper?.Dispose(); + + try + { + listerPluginWrapper = PluginManager.CreateListerWrapper(ListerFileName); + listerWindowHandle = listerPluginWrapper.CreateListerWindow(IntPtr.Zero, Filename); + + if (listerWindowHandle != IntPtr.Zero) + return; + } + catch (BadImageFormatException ex) + { + Console.WriteLine($"we cannot load 32bit libraries: {ex.Message}"); + } + + } } protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent) @@ -75,7 +93,7 @@ protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle paren protected override void DestroyNativeControlCore(IPlatformHandle control) { - listerPluginWrapper.CloseWindow(listerWindowHandle); + listerPluginWrapper?.CloseWindow(listerWindowHandle); base.DestroyNativeControlCore(control); } }