Browse Source

Import shortcut button works

flabbet 2 years ago
parent
commit
174b6a3484

BIN
src/PixiEditor/Images/SocialMedia/flabbet.png


+ 9 - 0
src/PixiEditor/Models/Commands/Templates/ICustomShortcutFormat.cs

@@ -0,0 +1,9 @@
+using PixiEditor.Models.Commands.Templates.Parsers;
+
+namespace PixiEditor.Models.Commands.Templates;
+
+public interface ICustomShortcutFormat
+{
+    public KeysParser KeysParser { get; }
+    public string[] CustomShortcutExtensions { get; }
+}

+ 4 - 2
src/PixiEditor/Models/Commands/Templates/Providers/AsepriteProvider.cs

@@ -8,7 +8,7 @@ internal partial class ShortcutProvider
 {
     public static AsepriteProvider Aseprite { get; } = new();
 
-    internal class AsepriteProvider : ShortcutProvider, IShortcutDefaults, IShortcutInstallation
+    internal class AsepriteProvider : ShortcutProvider, IShortcutDefaults, IShortcutInstallation, ICustomShortcutFormat
     {
         private static string InstallationPath { get; } = Path.Combine(
             Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Aseprite", "user.aseprite-keys");
@@ -26,9 +26,11 @@ internal partial class ShortcutProvider
         
         public ShortcutsTemplate GetInstalledShortcuts()
         {
-            return _parser.Parse(InstallationPath);
+            return _parser.Parse(InstallationPath, true);
         }
 
         public List<Shortcut> DefaultShortcuts => _parser.Defaults;
+        public KeysParser KeysParser => _parser;
+        public string[] CustomShortcutExtensions => new[] { ".aseprite-keys" };
     }
 }

+ 15 - 10
src/PixiEditor/Models/Commands/Templates/Providers/Parsers/AsepriteKeysParser.cs

@@ -26,7 +26,7 @@ public class AsepriteKeysParser : KeysParser
     {
     }
 
-    public override ShortcutsTemplate Parse(string path)
+    public override ShortcutsTemplate Parse(string path, bool applyDefaults)
     {
         if (!File.Exists(path))
         {
@@ -38,28 +38,30 @@ public class AsepriteKeysParser : KeysParser
             throw new ArgumentException("File is not aseprite-keys file", nameof(path));
         }
         
-        return LoadAndParse(path);
+        return LoadAndParse(path, applyDefaults);
     }
 
-    private ShortcutsTemplate LoadAndParse(string path)
+    private ShortcutsTemplate LoadAndParse(string path, bool applyDefaults)
     {
         XmlDocument doc = new XmlDocument();
         doc.Load(path);
         
         List<KeyDefinition> keyDefinitions = new List<KeyDefinition>(); // DefaultShortcut is actually mapped shortcut.
 
-        LoadCommands(doc, keyDefinitions);
-        LoadTools(doc, keyDefinitions);
+        LoadCommands(doc, keyDefinitions, applyDefaults);
+        LoadTools(doc, keyDefinitions, applyDefaults);
         
         ShortcutsTemplate template = ShortcutsTemplate.FromKeyDefinitions(keyDefinitions);
         return template;
     }
 
-    private void LoadCommands(XmlDocument document, List<KeyDefinition> keyDefinitions)
+    private void LoadCommands(XmlDocument document, List<KeyDefinition> keyDefinitions, bool applyDefaults)
     {
         XmlNodeList commands = document.SelectNodes("keyboard/commands/key");
-        ApplyDefaults(keyDefinitions, "PixiEditor");
-
+        if (applyDefaults)
+        {
+            ApplyDefaults(keyDefinitions, "PixiEditor");
+        }
 
         foreach (XmlNode commandNode in commands)
         {
@@ -129,10 +131,13 @@ public class AsepriteKeysParser : KeysParser
     /// Each tool entry is a key XML node with command attribute under 'tool' parameter and shortcut under 'shortcut' parameter.
     /// </summary>
     /// <param name="keyDefinitions">Definitions to write to</param>
-    private void LoadTools(XmlDocument document, List<KeyDefinition> keyDefinitions)
+    private void LoadTools(XmlDocument document, List<KeyDefinition> keyDefinitions, bool applyDefaults)
     {
         XmlNodeList tools = document.SelectNodes("keyboard/tools/key");
-        ApplyDefaults(keyDefinitions, "PixiEditor.Tools");
+        if (applyDefaults)
+        {
+            ApplyDefaults(keyDefinitions, "PixiEditor.Tools");
+        }
 
         foreach (XmlNode tool in tools)
         {

+ 7 - 1
src/PixiEditor/Models/Commands/Templates/Providers/Parsers/KeysParser.cs

@@ -26,7 +26,13 @@ public abstract class KeysParser
         MapFileName = mapFileName;
     }
     
-    public abstract ShortcutsTemplate Parse(string filePath);
+    /// <summary>
+    ///     Parses custom shortcuts file into ShortcutTemplate.
+    /// </summary>
+    /// <param name="filePath">Path to the file.</param>
+    /// <param name="applyTemplateDefaults">If true, all shortcuts available in the key map will be loaded, and then overwritten by entries in the file. If false, only entries from the file will be applied.</param>
+    /// <returns>Parsed ShortcutTemplate.</returns>
+    public abstract ShortcutsTemplate Parse(string filePath, bool applyTemplateDefaults);
     
     private Dictionary<string, KeyDefinition> LoadKeysMap()
     {

+ 1 - 1
src/PixiEditor/Models/Commands/Templates/ShortcutProvider.cs

@@ -31,7 +31,7 @@ internal partial class ShortcutProvider
         Name = name;
     }
 
-    public static IEnumerable<ShortcutProvider> GetProviders() => new ShortcutProvider[]
+    public static ShortcutProvider[] GetProviders() => new ShortcutProvider[]
     {
         #if DEBUG
         Debug,

+ 2 - 0
src/PixiEditor/PixiEditor.csproj

@@ -337,6 +337,8 @@
 		<Resource Include="Images\TemplateLogos\Aseprite.png" />
 		<None Remove="Images\TemplateLogos\Aseprite-Hover.png" />
 		<Resource Include="Images\TemplateLogos\Aseprite-Hover.png" />
+		<None Remove="Images\SocialMedia\flabbet.png" />
+		<Resource Include="Images\SocialMedia\flabbet.png" />
 	</ItemGroup>
 	<ItemGroup>
 		<None Include="..\LICENSE">

+ 23 - 0
src/PixiEditor/Styles/ThemeStyle.xaml

@@ -228,6 +228,29 @@
             </Setter.Value>
         </Setter>
     </Style>
+    
+    <Style x:Key="HyperlinkTextButton" TargetType="{x:Type Button}">
+        <Setter Property="OverridesDefaultStyle" Value="True"/>
+        <Setter Property="Foreground" Value="White"/>
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="Button">
+                    <Border BorderThickness="0" Name="brd"
+                            Background="{TemplateBinding Background}">
+                        <ContentPresenter />
+                    </Border>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsMouseOver" Value="True">
+                            <Setter Property="TextBlock.TextDecorations" Value="Underline"/>
+                        </Trigger>
+                        <Trigger Property="IsMouseOver" Value="False">
+                            <Setter Property="TextBlock.TextDecorations" Value="{x:Null}"/>
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
 
 
     <Style TargetType="Button" x:Key="ImageButtonStyle">

+ 60 - 4
src/PixiEditor/ViewModels/SettingsWindowViewModel.cs

@@ -1,4 +1,5 @@
 using System.IO;
+using System.Text;
 using PixiEditor.Helpers;
 using PixiEditor.Models.Commands;
 using PixiEditor.Models.Dialogs;
@@ -7,6 +8,7 @@ using System.Windows;
 using System.Windows.Input;
 using Microsoft.Win32;
 using PixiEditor.Models.Commands.Attributes.Commands;
+using PixiEditor.Models.Commands.Templates;
 using PixiEditor.Models.UserPreferences;
 using PixiEditor.Views.Dialogs;
 
@@ -60,6 +62,8 @@ internal class SettingsWindowViewModel : ViewModelBase
 
     public List<GroupSearchResult> Commands { get; }
 
+    private static List<ICustomShortcutFormat> _customShortcutFormats;
+
     [Command.Internal("PixiEditor.Shortcuts.Reset")]
     public static void ResetCommand()
     {
@@ -87,18 +91,19 @@ internal class SettingsWindowViewModel : ViewModelBase
     [Command.Internal("PixiEditor.Shortcuts.Import")]
     public static void ImportShortcuts()
     {
+        _customShortcutFormats ??= ShortcutProvider.GetProviders().OfType<ICustomShortcutFormat>().ToList();
         var dialog = new OpenFileDialog();
-        dialog.Filter = "PixiShorts (*.pixisc)|*.pixisc|json (*.json)|*.json|All files (*.*)|*.*";
+        string filterEntries = $"PixiShorts (*.pixisc)|*.pixisc|json (*.json)|*.json{BuildCustomParsersFormat(_customShortcutFormats, out string extensionsString)}";
+        extensionsString = $"*.pixisc;*json;{extensionsString}";
+        dialog.Filter = $"All Shortcut ({extensionsString})|{extensionsString}|{filterEntries}|All files (*.*)|*.*";
         dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
         if (dialog.ShowDialog().GetValueOrDefault())
         {
             List<Shortcut> shortcuts = new List<Shortcut>();
             try
             {
-                shortcuts = ShortcutFile.LoadTemplate(dialog.FileName)?.Shortcuts.ToList();
-                if (shortcuts is null)
+                if (!TryImport(dialog, ref shortcuts))
                 {
-                    NoticeDialog.Show("Shortcuts file was not in a valid format", "Invalid file");
                     return;
                 }
             }
@@ -117,6 +122,57 @@ internal class SettingsWindowViewModel : ViewModelBase
         Keyboard.ClearFocus();
     }
 
+    private static bool TryImport(OpenFileDialog dialog, ref List<Shortcut> shortcuts)
+    {
+        if (dialog.FileName.EndsWith(".pixisc") || dialog.FileName.EndsWith(".json"))
+        {
+            shortcuts = ShortcutFile.LoadTemplate(dialog.FileName)?.Shortcuts.ToList();
+            if (shortcuts is null)
+            {
+                NoticeDialog.Show("Shortcuts file was not in a valid format", "Invalid file");
+                return false;
+            }
+        }
+        else
+        {
+            var provider = _customShortcutFormats.FirstOrDefault(x =>
+                x.CustomShortcutExtensions.Contains(Path.GetExtension(dialog.FileName), StringComparer.OrdinalIgnoreCase));
+            if (provider is null)
+            {
+                NoticeDialog.Show("This file format is unsupported.", "Invalid file");
+                return false;
+            }
+
+            shortcuts = provider.KeysParser.Parse(dialog.FileName, false)?.Shortcuts.ToList();
+        }
+
+        return true;
+    }
+
+    private static string BuildCustomParsersFormat(IList<ICustomShortcutFormat> customFormats, out string extensionsString)
+    {
+        if (customFormats is null || customFormats.Count == 0)
+        {
+            extensionsString = string.Empty;
+            return string.Empty;
+        }
+
+        StringBuilder builder = new StringBuilder();
+        StringBuilder extensionsBuilder = new StringBuilder();
+        foreach (ICustomShortcutFormat format in customFormats)
+        {
+            foreach (var extension in format.CustomShortcutExtensions)
+            {
+                string extensionWithoutDot = extension.TrimStart('.');
+                extensionsBuilder.Append($"*.{extensionWithoutDot};");
+                builder.Append($"|{extensionWithoutDot} (*.{extensionWithoutDot})|*.{extensionWithoutDot}");
+            }
+        }
+
+        extensionsString = extensionsBuilder.ToString();
+        return builder.ToString();
+    }
+
     [Command.Internal("PixiEditor.Shortcuts.OpenTemplatePopup")]
     public static void OpenTemplatePopup()
     {

+ 36 - 5
src/PixiEditor/Views/Dialogs/AboutPopup.xaml

@@ -7,8 +7,8 @@
         xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
         xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours"
         mc:Ignorable="d" WindowStyle="None"
-        Title="About" WindowStartupLocation="CenterScreen" 
-        Height="300" Width="400">
+        Title="About" WindowStartupLocation="CenterScreen"
+        Height="300" Width="400" Name="aboutPopup">
     <Window.CommandBindings>
         <CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute"
                         Executed="CommandBinding_Executed_Close" />
@@ -27,8 +27,39 @@
         <local:DialogTitleBar DockPanel.Dock="Top"
                              TitleText="{Binding ElementName=popup, Path=Title}" 
                              CloseCommand="{x:Static SystemCommands.CloseWindowCommand}"/>
-        <Grid DockPanel.Dock="Bottom">
-            
-        </Grid>
+        <StackPanel DataContext="{Binding ElementName=aboutPopup}" Orientation="Vertical" DockPanel.Dock="Bottom" Margin="10">
+            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top">
+                <Image Source="../../Images/PixiEditorLogo.png" Height="40" VerticalAlignment="Center"/>
+                <TextBlock FontSize="40" FontWeight="SemiBold" Foreground="White" VerticalAlignment="Center" Margin="10,0,0,0">PixiEditor</TextBlock>
+            </StackPanel>
+            <TextBlock Foreground="White" HorizontalAlignment="Center" FontSize="20" FontWeight="Medium" Text="{Binding VersionText}"/>
+            <Label Content="Project Maintainers" Style="{StaticResource Header2}" Margin="10 5"/>
+            <StackPanel Orientation="Horizontal" Margin="20 0">
+                <Ellipse Width="32" Height="32">
+                    <Ellipse.Fill>
+                        <ImageBrush ImageSource="/Images/SocialMedia/flabbet.png"/>
+                    </Ellipse.Fill>
+                </Ellipse>
+                <TextBlock Text="Krzysztof Krysiński (flabbet)" Foreground="White" VerticalAlignment="Center" Margin="10 0 0 0" FontSize="16">
+                </TextBlock>
+            </StackPanel>
+            <StackPanel Orientation="Horizontal" Margin="20 0">
+                <Ellipse Width="32" Height="32">
+                    <Ellipse.Fill>
+                        <ImageBrush ImageSource="/Images/SocialMedia/flabbet.png"/>
+                    </Ellipse.Fill>
+                </Ellipse>
+                <TextBlock Text="Egor Mozgovoy (Equbuxu)" Foreground="White" VerticalAlignment="Center" Margin="10 0 0 0" FontSize="16">
+                </TextBlock>
+            </StackPanel>
+            <StackPanel Orientation="Horizontal" Margin="20 0">
+                <Ellipse Width="32" Height="32">
+                    <Ellipse.Fill>
+                        <ImageBrush ImageSource="/Images/SocialMedia/flabbet.png"/>
+                    </Ellipse.Fill>
+                </Ellipse>
+                <Button Style="{StaticResource HyperlinkTextButton}" Content="Philip Kreuz (CPK)" Foreground="White" VerticalAlignment="Center" Margin="10 0 0 0" FontSize="16"/>
+            </StackPanel>
+        </StackPanel>
     </DockPanel>
 </Window>

+ 2 - 0
src/PixiEditor/Views/Dialogs/AboutPopup.xaml.cs

@@ -1,10 +1,12 @@
 using System.Windows;
 using System.Windows.Input;
+using PixiEditor.Helpers;
 
 namespace PixiEditor.Views.Dialogs;
 
 public partial class AboutPopup : Window
 {
+    public static string VersionText => $"Version: {VersionHelpers.GetCurrentAssemblyVersionString()}";
     public AboutPopup()
     {
         InitializeComponent();

+ 1 - 1
src/PixiEditor/Views/UserControls/CommandSearch/CommandSearchControl.xaml

@@ -20,7 +20,7 @@
             <RowDefinition Height="Auto" />
         </Grid.RowDefinitions>
 
-        <TextBox Text="{Binding SearchTerm, Mode=TwoWay, ElementName=uc, UpdateSourceTrigger=PropertyChanged}" FontSize="18"
+        <TextBox Text="{Binding SearchTerm, Mode=TwoWay, ElementName=uc, UpdateSourceTrigger=PropertyChanged}" FontSize="17"
                  Padding="5"
                  x:Name="textBox">
             <i:Interaction.Behaviors>