Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev/lister part2 #101

Merged
merged 12 commits into from
Oct 3, 2024
3 changes: 3 additions & 0 deletions src/SmartCommander/Models/OptionsModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using static System.Environment;

Expand Down Expand Up @@ -56,5 +58,6 @@ static OptionsModel()
public bool AllowOnlyOneInstance { get; set; } = true;
public string Language { get; set; } = "en-US";

public List<string> ListerPlugins { get; set; }= new List<string>();
}
}
6 changes: 2 additions & 4 deletions src/SmartCommander/Plugins/PluginManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
80 changes: 66 additions & 14 deletions src/SmartCommander/ViewModels/OptionsViewModel.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -18,6 +22,15 @@ public class OptionsViewModel : ViewModelBase

public CultureInfo SelectedCulture { get; set; }


public ObservableCollection<string> ListerPlugins { get; set; } = new();
private string _selectedPlugin = string.Empty;
public string SelectedPlugin
{
get => _selectedPlugin;
set => this.RaiseAndSetIfChanged(ref _selectedPlugin, value);
}

private static IEnumerable<CultureInfo> GetAvailableCultures()
{
List<CultureInfo> result = new List<CultureInfo>();
Expand All @@ -26,14 +39,15 @@ private static IEnumerable<CultureInfo> 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;
}
Expand All @@ -42,7 +56,7 @@ public OptionsViewModel()
{
OKCommand = ReactiveCommand.Create<Window>(SaveClose);
CancelCommand = ReactiveCommand.Create<Window>(Close);

IsCurrentDirectoryDisplayed = Model.IsCurrentDirectoryDisplayed;
IsFunctionKeysDisplayed = Model.IsFunctionKeysDisplayed;
IsCommandLineDisplayed = Model.IsCommandLineDisplayed;
Expand All @@ -56,9 +70,13 @@ public OptionsViewModel()
AvailableCultures = new ObservableCollection<CultureInfo>(GetAvailableCultures());
var lang = AvailableCultures.First(x => x.Name == Model.Language);
SelectedCulture = lang ?? AvailableCultures.First();

ListerPlugins.AddRange(Model.ListerPlugins);
AddFileCommand = ReactiveCommand.Create<Window>(AddFileAsync);
RemoveFileCommand = ReactiveCommand.Create<Window>(RemoveFile);
}

public bool IsCurrentDirectoryDisplayed { get; set; }
public bool IsCurrentDirectoryDisplayed { get; set; }

public bool IsFunctionKeysDisplayed { get; set; }

Expand All @@ -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<Window, Unit> OKCommand { get; }
public ReactiveCommand<Window, Unit> CancelCommand { get; }
public ReactiveCommand<Window, Unit> AddFileCommand { get; }
public ReactiveCommand<Window, Unit> 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)
{
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/SmartCommander/Views/FileSearchWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
</ListBox>
</ScrollViewer>

<Border Grid.Row="2" Background="Azure" Padding="0" HorizontalAlignment="Stretch">
<Border Grid.Row="2" Padding="0" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding StatusFolder, Mode=OneWay}" VerticalAlignment="Center"/>
</Border>
</Grid>
Expand Down
125 changes: 70 additions & 55 deletions src/SmartCommander/Views/OptionsWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -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}">

<Window.Resources>
<DataTemplate x:Key="CultureInfoTemplate">
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</Window.Resources>

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<TabControl>
<TabItem Header="Window">
<StackPanel>
<CheckBox IsChecked="{Binding IsCurrentDirectoryDisplayed}"
Content="{x:Static assets:Resources.DisplayCurrentDirectory}"></CheckBox>
<CheckBox IsChecked="{Binding IsFunctionKeysDisplayed}"
Content="{x:Static assets:Resources.DisplayFunctionKeys}"></CheckBox>
<CheckBox IsChecked="{Binding IsCommandLineDisplayed}"
Content="{x:Static assets:Resources.DisplayCommandLine}"></CheckBox>
<CheckBox IsChecked="{Binding SaveWindowPositionSize}"
Content="{x:Static assets:Resources.SaveWindowPositionSize}"></CheckBox>
<CheckBox IsChecked="{Binding AllowOnlyOneInstance}"
Content="{x:Static assets:Resources.AllowOnlyOneInstance}"></CheckBox>
<RadioButton IsChecked="{Binding !IsDarkThemeEnabled}"
Content="{x:Static assets:Resources.LightTheme}"></RadioButton>
<RadioButton IsChecked="{Binding IsDarkThemeEnabled}"
Content="{x:Static assets:Resources.DarkTheme}"></RadioButton>
</StackPanel>
</TabItem>
<TabItem Header="Operation">
<StackPanel>
<CheckBox IsChecked="{Binding IsHiddenSystemFilesDisplayed}"
Content="{x:Static assets:Resources.ShowHiddenFiles}"></CheckBox>
<CheckBox IsChecked="{Binding SaveSettingsOnExit}"
Content="{x:Static assets:Resources.SaveSettingsOnExit}"></CheckBox>
<CheckBox IsChecked="{Binding ConfirmationWhenDeleteNonEmpty}"
Content="{x:Static assets:Resources.ShowNonEmptyConfirmation}"></CheckBox>
</StackPanel>
</TabItem>
<TabItem Header="Language">
<StackPanel>
<ListBox ItemsSource="{Binding AvailableCultures}"
ItemTemplate="{StaticResource CultureInfoTemplate}"
SelectedItem="{Binding SelectedCulture, Mode=TwoWay}"

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<TabControl TabStripPlacement="Left">
<TabItem Header="Window">
<StackPanel>
<CheckBox IsChecked="{Binding IsCurrentDirectoryDisplayed}"
Content="{x:Static assets:Resources.DisplayCurrentDirectory}"></CheckBox>
<CheckBox IsChecked="{Binding IsFunctionKeysDisplayed}"
Content="{x:Static assets:Resources.DisplayFunctionKeys}"></CheckBox>
<CheckBox IsChecked="{Binding IsCommandLineDisplayed}"
Content="{x:Static assets:Resources.DisplayCommandLine}"></CheckBox>
<CheckBox IsChecked="{Binding SaveWindowPositionSize}"
Content="{x:Static assets:Resources.SaveWindowPositionSize}"></CheckBox>
<CheckBox IsChecked="{Binding AllowOnlyOneInstance}"
Content="{x:Static assets:Resources.AllowOnlyOneInstance}"></CheckBox>
<RadioButton IsChecked="{Binding !IsDarkThemeEnabled}"
Content="{x:Static assets:Resources.LightTheme}"></RadioButton>
<RadioButton IsChecked="{Binding IsDarkThemeEnabled}"
Content="{x:Static assets:Resources.DarkTheme}"></RadioButton>
</StackPanel>
</TabItem>
<TabItem Header="Operation">
<StackPanel>
<CheckBox IsChecked="{Binding IsHiddenSystemFilesDisplayed}"
Content="{x:Static assets:Resources.ShowHiddenFiles}"></CheckBox>
<CheckBox IsChecked="{Binding SaveSettingsOnExit}"
Content="{x:Static assets:Resources.SaveSettingsOnExit}"></CheckBox>
<CheckBox IsChecked="{Binding ConfirmationWhenDeleteNonEmpty}"
Content="{x:Static assets:Resources.ShowNonEmptyConfirmation}"></CheckBox>
</StackPanel>
</TabItem>
<TabItem Header="Language">
<StackPanel>
<Label Content="{x:Static assets:Resources.Reboot}"/>
<ListBox ItemsSource="{Binding AvailableCultures}"
ItemTemplate="{StaticResource CultureInfoTemplate}"
SelectedItem="{Binding SelectedCulture, Mode=TwoWay}"
/>
<Label Content="{x:Static assets:Resources.Reboot}"/>
</StackPanel>
</TabItem>
</TabControl>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Margin="5" Command="{Binding OKCommand}" CommandParameter="{Binding $parent[Window]}"
Content="{x:Static assets:Resources.Save}"></Button>
<Button Margin="5" Command="{Binding CancelCommand}" CommandParameter="{Binding $parent[Window]}"
Content="{x:Static assets:Resources.Cancel}"></Button>
</StackPanel>
</Grid>
</StackPanel>
</TabItem>
<TabItem Header="Plugins">
<TabControl>
<TabItem Header="Lister (WLX)">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Button Content="Add" Command="{Binding AddFileCommand}"/>
<Button Content="Remove" Command="{Binding RemoveFileCommand}"/>
<Label Content="* supported only 64bit extensions"/>
</StackPanel>
<ListBox ItemsSource="{Binding ListerPlugins}"
SelectedItem="{Binding SelectedPlugin, Mode=TwoWay}"/>
</StackPanel>
</TabItem>
</TabControl>
</TabItem>
</TabControl>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Margin="5" Command="{Binding OKCommand}" CommandParameter="{Binding $parent[Window]}" IsDefault="True"
Content="{x:Static assets:Resources.Save}"></Button>
<Button Margin="5" Command="{Binding CancelCommand}" CommandParameter="{Binding $parent[Window]}" IsCancel="True"
Content="{x:Static assets:Resources.Cancel}"></Button>
</StackPanel>
</Grid>
</Window>
32 changes: 25 additions & 7 deletions src/SmartCommander/Views/ViewerWindow.axaml.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -13,16 +14,17 @@ 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<Grid>("GridPanel");
if (grid != null)
{
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)
Expand All @@ -31,7 +33,6 @@ private void OnWindowOpened(object? sender, EventArgs e)
}
}
}

}
}

Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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);
}
}
Loading