diff --git a/FModel/Extensions/VisualTreeExtensions.cs b/FModel/Extensions/VisualTreeExtensions.cs new file mode 100644 index 00000000..c898336f --- /dev/null +++ b/FModel/Extensions/VisualTreeExtensions.cs @@ -0,0 +1,18 @@ +using System.Windows; +using System.Windows.Media; + +namespace FModel.Extensions; + +public static class VisualTreeExtensions +{ + public static T FindAncestor(this DependencyObject current) where T : DependencyObject + { + while (current != null) + { + if (current is T t) + return t; + current = VisualTreeHelper.GetParent(current); + } + return null; + } +} diff --git a/FModel/Framework/Hotkey.cs b/FModel/Framework/Hotkey.cs index cc984965..8bed78aa 100644 --- a/FModel/Framework/Hotkey.cs +++ b/FModel/Framework/Hotkey.cs @@ -27,11 +27,13 @@ public class Hotkey : ViewModel public bool IsTriggered(Key e) { - return e == Key && Keyboard.Modifiers.HasFlag(Modifiers); + return Key != Key.None && e == Key && Keyboard.Modifiers.HasFlag(Modifiers); } public override string ToString() { + if (Key == Key.None) return string.Empty; + var str = new StringBuilder(); if (Modifiers.HasFlag(ModifierKeys.Control)) @@ -46,4 +48,4 @@ public class Hotkey : ViewModel str.Append(Key); return str.ToString(); } -} \ No newline at end of file +} diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 2e2a4e5a..2609d0a5 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.ComponentModel; using System.IO; using System.Linq; @@ -7,6 +8,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; +using FModel.Extensions; using FModel.Services; using FModel.Settings; using FModel.ViewModels; @@ -180,21 +182,21 @@ public partial class MainWindow }; } else if (_applicationView.Status.IsReady && UserSettings.Default.ExportData.IsTriggered(e.Key)) - ExportSelected("Save_Data"); + OnExportHotkey("Save_Data"); else if (_applicationView.Status.IsReady && UserSettings.Default.ExportProperties.IsTriggered(e.Key)) - ExportSelected("Save_Properties"); + OnExportHotkey("Save_Properties"); else if (_applicationView.Status.IsReady && UserSettings.Default.ExportTextures.IsTriggered(e.Key)) - ExportSelected("Save_Textures"); + OnExportHotkey("Save_Textures"); else if (_applicationView.Status.IsReady && UserSettings.Default.ExportModels.IsTriggered(e.Key)) - ExportSelected("Save_Models"); + OnExportHotkey("Save_Models"); else if (_applicationView.Status.IsReady && UserSettings.Default.ExportWorlds.IsTriggered(e.Key)) - ExportSelected("Save_Worlds"); + OnExportHotkey("Save_Worlds"); else if (_applicationView.Status.IsReady && UserSettings.Default.ExportAnimations.IsTriggered(e.Key)) - ExportSelected("Save_Animations"); + OnExportHotkey("Save_Animations"); else if (_applicationView.Status.IsReady && UserSettings.Default.ExportAudio.IsTriggered(e.Key)) - ExportSelected("Save_Audio"); + OnExportHotkey("Save_Audio"); else if (_applicationView.Status.IsReady && UserSettings.Default.ExportCode.IsTriggered(e.Key)) - ExportSelected("Save_Code"); + OnExportHotkey("Save_Code"); else if (_applicationView.Status.IsReady && UserSettings.Default.FeaturePreviewNewAssetExplorer && UserSettings.Default.SwitchAssetExplorer.IsTriggered(e.Key)) _applicationView.IsAssetsExplorerVisible = !_applicationView.IsAssetsExplorerVisible; else if (UserSettings.Default.AssetAddTab.IsTriggered(e.Key)) @@ -395,13 +397,20 @@ public partial class MainWindow childFolder.IsSelected = true; } - private void ExportSelected(string trigger) + private void OnExportHotkey(string trigger) { - var selectedItems = AssetsListName.SelectedItems.Cast().ToArray(); - if (selectedItems.Length == 0) + if (!_applicationView.Status.IsReady || Keyboard.FocusedElement is not DependencyObject focused) return; - _applicationView.RightClickMenuCommand.Execute(_applicationView, new object[] { trigger, selectedItems }); + IList selection = focused.FindAncestor() == AssetsFolderName + ? new[] { AssetsFolderName.SelectedItem } + : focused.FindAncestor()?.SelectedItems; + + var exportable = selection?.OfType().Where(static item => item is TreeItem or GameFileViewModel).ToArray() ?? []; + if (exportable.Length == 0) + return; + + _applicationView.RightClickMenuCommand.Execute(new object[] { trigger, exportable }); } private CustomPopupPlacement[] OnQueueToastCustomPopupPlacement(Size popupSize, Size targetSize, Point offset) diff --git a/FModel/Settings/UserSettings.cs b/FModel/Settings/UserSettings.cs index 3c79a238..aff57f4c 100644 --- a/FModel/Settings/UserSettings.cs +++ b/FModel/Settings/UserSettings.cs @@ -382,14 +382,14 @@ public sealed class UserSettings : ViewModel set => SetProperty(ref _assetRightTab, value); } - private Hotkey _assetAddTab = new(Key.OemPlus, ModifierKeys.Control); + private Hotkey _assetAddTab = new(Key.T, ModifierKeys.Control); public Hotkey AssetAddTab { get => _assetAddTab; set => SetProperty(ref _assetAddTab, value); } - private Hotkey _assetRemoveTab = new(Key.R, ModifierKeys.Control); + private Hotkey _assetRemoveTab = new(Key.W, ModifierKeys.Control); public Hotkey AssetRemoveTab { get => _assetRemoveTab; @@ -431,56 +431,56 @@ public sealed class UserSettings : ViewModel set => SetProperty(ref _nextAudio, value); } - private Hotkey _exportData = new(Key.D, ModifierKeys.Control); + private Hotkey _exportData = new(Key.None); public Hotkey ExportData { get => _exportData; set => SetProperty(ref _exportData, value); } - private Hotkey _exportProperties = new(Key.P, ModifierKeys.Control); + private Hotkey _exportProperties = new(Key.None); public Hotkey ExportProperties { get => _exportProperties; set => SetProperty(ref _exportProperties, value); } - private Hotkey _exportTextures = new(Key.T, ModifierKeys.Control); + private Hotkey _exportTextures = new(Key.None); public Hotkey ExportTextures { get => _exportTextures; set => SetProperty(ref _exportTextures, value); } - private Hotkey _exportModels = new(Key.M, ModifierKeys.Control); + private Hotkey _exportModels = new(Key.None); public Hotkey ExportModels { get => _exportModels; set => SetProperty(ref _exportModels, value); } - private Hotkey _exportWorlds = new(Key.W, ModifierKeys.Control); + private Hotkey _exportWorlds = new(Key.None); public Hotkey ExportWorlds { get => _exportWorlds; set => SetProperty(ref _exportWorlds, value); } - private Hotkey _exportAnimations = new(Key.N, ModifierKeys.Control); + private Hotkey _exportAnimations = new(Key.None); public Hotkey ExportAnimations { get => _exportAnimations; set => SetProperty(ref _exportAnimations, value); } - private Hotkey _exportAudio = new(Key.U, ModifierKeys.Control); + private Hotkey _exportAudio = new(Key.None); public Hotkey ExportAudio { get => _exportAudio; set => SetProperty(ref _exportAudio, value); } - private Hotkey _exportCode = new(Key.C, ModifierKeys.Control); + private Hotkey _exportCode = new(Key.None); public Hotkey ExportCode { get => _exportCode; diff --git a/FModel/Views/Resources/Controls/ContextMenus/FileContextMenu.xaml b/FModel/Views/Resources/Controls/ContextMenus/FileContextMenu.xaml index 414d4d43..36f90031 100644 --- a/FModel/Views/Resources/Controls/ContextMenus/FileContextMenu.xaml +++ b/FModel/Views/Resources/Controls/ContextMenus/FileContextMenu.xaml @@ -2,62 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI" xmlns:settings="clr-namespace:FModel.Settings" - xmlns:controls="clr-namespace:FModel.Views.Resources.Controls" xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"> - - - - - - - - - - - - - - - - @@ -178,8 +123,7 @@ + InputGestureText="{Binding ExportData, Source={x:Static settings:UserSettings.Default}}"> + InputGestureText="{Binding ExportProperties, Source={x:Static settings:UserSettings.Default}}"> @@ -219,21 +162,17 @@ - + InputGestureText="{Binding ExportTextures, Source={x:Static settings:UserSettings.Default}}"> - + - + @@ -244,20 +183,16 @@ - - - + + + + InputGestureText="{Binding ExportModels, Source={x:Static settings:UserSettings.Default}}"> @@ -285,8 +220,7 @@ + InputGestureText="{Binding ExportWorlds, Source={x:Static settings:UserSettings.Default}}"> @@ -318,8 +252,7 @@ + InputGestureText="{Binding ExportAnimations, Source={x:Static settings:UserSettings.Default}}"> @@ -347,8 +280,7 @@ + InputGestureText="{Binding ExportAudio, Source={x:Static settings:UserSettings.Default}}"> diff --git a/FModel/Views/Resources/Controls/ContextMenus/FolderContextMenu.xaml b/FModel/Views/Resources/Controls/ContextMenus/FolderContextMenu.xaml index d102f1f4..455b495a 100644 --- a/FModel/Views/Resources/Controls/ContextMenus/FolderContextMenu.xaml +++ b/FModel/Views/Resources/Controls/ContextMenus/FolderContextMenu.xaml @@ -1,5 +1,6 @@ @@ -18,7 +19,8 @@ + Command="{Binding RightClickMenuCommand}" + InputGestureText="{Binding ExportData, Source={x:Static settings:UserSettings.Default}}"> @@ -38,7 +40,8 @@ + Command="{Binding RightClickMenuCommand}" + InputGestureText="{Binding ExportProperties, Source={x:Static settings:UserSettings.Default}}"> @@ -58,7 +61,8 @@ + Command="{Binding RightClickMenuCommand}" + InputGestureText="{Binding ExportTextures, Source={x:Static settings:UserSettings.Default}}"> @@ -78,7 +82,8 @@ + Command="{Binding RightClickMenuCommand}" + InputGestureText="{Binding ExportCode, Source={x:Static settings:UserSettings.Default}}"> @@ -98,7 +103,8 @@ + Command="{Binding RightClickMenuCommand}" + InputGestureText="{Binding ExportModels, Source={x:Static settings:UserSettings.Default}}"> @@ -118,7 +124,8 @@ + Command="{Binding RightClickMenuCommand}" + InputGestureText="{Binding ExportWorlds, Source={x:Static settings:UserSettings.Default}}"> @@ -143,7 +150,8 @@ + Command="{Binding RightClickMenuCommand}" + InputGestureText="{Binding ExportAnimations, Source={x:Static settings:UserSettings.Default}}"> @@ -163,7 +171,8 @@ + Command="{Binding RightClickMenuCommand}" + InputGestureText="{Binding ExportAudio, Source={x:Static settings:UserSettings.Default}}"> diff --git a/FModel/Views/Resources/Controls/ContextMenus/FolderContextMenu.xaml.cs b/FModel/Views/Resources/Controls/ContextMenus/FolderContextMenu.xaml.cs index 89d08ec8..b1e1c8c9 100644 --- a/FModel/Views/Resources/Controls/ContextMenus/FolderContextMenu.xaml.cs +++ b/FModel/Views/Resources/Controls/ContextMenus/FolderContextMenu.xaml.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; +using FModel.Extensions; using FModel.Services; using FModel.Settings; using FModel.ViewModels; @@ -23,7 +24,7 @@ public partial class FolderContextMenuDictionary if (sender is not ContextMenu { PlacementTarget: FrameworkElement fe } menu) return; - var listBox = FindAncestor(fe); + var listBox = fe.FindAncestor(); if (listBox != null) { menu.DataContext = listBox.DataContext; @@ -31,7 +32,7 @@ public partial class FolderContextMenuDictionary return; } - var treeView = FindAncestor(fe); + var treeView = fe.FindAncestor(); if (treeView != null) { menu.DataContext = treeView.DataContext; @@ -39,17 +40,6 @@ public partial class FolderContextMenuDictionary } } - private static T FindAncestor(DependencyObject current) where T : DependencyObject - { - while (current != null) - { - if (current is T t) - return t; - current = VisualTreeHelper.GetParent(current); - } - return null; - } - private void OnFavoriteDirectoryClick(object sender, RoutedEventArgs e) { if (sender is not MenuItem { CommandParameter: IEnumerable list } || list.FirstOrDefault() is not TreeItem folder) diff --git a/FModel/Views/Resources/Controls/HotkeyControls.cs b/FModel/Views/Resources/Controls/HotkeyControls.cs index 474da0a8..e1bb4cf1 100644 --- a/FModel/Views/Resources/Controls/HotkeyControls.cs +++ b/FModel/Views/Resources/Controls/HotkeyControls.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Input; @@ -6,63 +5,6 @@ using FModel.Framework; namespace FModel.Views.Resources.Controls; -public class HotkeySetting : Control -{ - public string Label - { - get => (string) GetValue(LabelProperty); - set => SetValue(LabelProperty, value); - } - - public static readonly DependencyProperty LabelProperty = - DependencyProperty.Register(nameof(Label), typeof(string), typeof(HotkeySetting), new PropertyMetadata(string.Empty)); - - public Hotkey HotKey - { - get => (Hotkey) GetValue(HotKeyProperty); - set => SetValue(HotKeyProperty, value); - } - - public static readonly DependencyProperty HotKeyProperty = - DependencyProperty.Register(nameof(HotKey), typeof(Hotkey), typeof(HotkeySetting), new FrameworkPropertyMetadata(new Hotkey(Key.None), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); -} - -public class HotkeyDisplay : ItemsControl -{ - public Hotkey HotKey - { - get => (Hotkey) GetValue(HotKeyProperty); - set => SetValue(HotKeyProperty, value); - } - - public static readonly DependencyProperty HotKeyProperty = - DependencyProperty.Register(nameof(HotKey), typeof(Hotkey), typeof(HotkeyDisplay), new PropertyMetadata(new Hotkey(Key.None), OnHotKeyChanged)); - - private static void OnHotKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is HotkeyDisplay control) - control.ItemsSource = GetKeys(control.HotKey); - } - - private static IEnumerable GetKeys(Hotkey hotkey) - { - if (hotkey.Modifiers.HasFlag(ModifierKeys.Control)) - yield return "Ctrl"; - - if (hotkey.Modifiers.HasFlag(ModifierKeys.Shift)) - yield return "Shift"; - - if (hotkey.Modifiers.HasFlag(ModifierKeys.Alt)) - yield return "Alt"; - - if (hotkey.Modifiers.HasFlag(ModifierKeys.Windows)) - yield return "Win"; - - if (hotkey.Key != Key.None) - yield return hotkey.Key.ToString(); - } -} - /// /// https://tyrrrz.me/blog/hotkey-editor-control-in-wpf /// diff --git a/FModel/Views/Resources/Controls/HotkeyPresenter.cs b/FModel/Views/Resources/Controls/HotkeyPresenter.cs new file mode 100644 index 00000000..0f705ad5 --- /dev/null +++ b/FModel/Views/Resources/Controls/HotkeyPresenter.cs @@ -0,0 +1,24 @@ +using System; +using System.Windows; +using System.Windows.Controls; + +namespace FModel.Views.Resources.Controls; + +public class HotkeyPresenter : ItemsControl +{ + public static readonly DependencyProperty GestureProperty = DependencyProperty.Register( + nameof(Gesture), typeof(string), typeof(HotkeyPresenter), new PropertyMetadata(null, OnGestureChanged)); + + public string Gesture + { + get => (string) GetValue(GestureProperty); + set => SetValue(GestureProperty, value); + } + + private static void OnGestureChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((HotkeyPresenter) d).ItemsSource = e.NewValue is string gesture + ? gesture.Split('+', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + : null; + } +} diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index 0decd34a..53cefe2b 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -1124,6 +1124,28 @@ + + - - diff --git a/FModel/Views/SettingsView.xaml b/FModel/Views/SettingsView.xaml index 8f79fa02..cf904af8 100644 --- a/FModel/Views/SettingsView.xaml +++ b/FModel/Views/SettingsView.xaml @@ -412,107 +412,107 @@ - + - - - + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - - - - + + + + + + + + + + + + - + - - - - - - - + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + +