From 76671d63d4f3ea18f8ad99e9ce9f0b2ec9a2599d Mon Sep 17 00:00:00 2001 From: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com> Date: Thu, 29 Dec 2022 14:24:05 +0000 Subject: Ava GUI: Restructure `Ryujinx.Ava` (#4165) * Restructure `Ryujinx.Ava` * Stylistic consistency * Update Ryujinx.Ava/UI/Controls/UserEditor.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Controls/UserEditor.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Controls/UserSelector.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Controls/SaveManager.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Controls/SaveManager.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Fix redundancies * Remove redunancies * Add back elses Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> --- .../Ui/Controls/ApplicationOpenedEventArgs.cs | 16 - Ryujinx.Ava/Ui/Controls/AvaloniaGlxContext.cs | 16 - Ryujinx.Ava/Ui/Controls/AvaloniaWglContext.cs | 16 - .../Ui/Controls/BitmapArrayValueConverter.cs | 35 -- Ryujinx.Ava/Ui/Controls/ButtonKeyAssigner.cs | 118 ------ Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs | 401 --------------------- Ryujinx.Ava/Ui/Controls/EmbeddedWindow.cs | 233 ------------ Ryujinx.Ava/Ui/Controls/GameGridView.axaml | 195 ---------- Ryujinx.Ava/Ui/Controls/GameGridView.axaml.cs | 82 ----- Ryujinx.Ava/Ui/Controls/GameListView.axaml | 235 ------------ Ryujinx.Ava/Ui/Controls/GameListView.axaml.cs | 82 ----- Ryujinx.Ava/Ui/Controls/Glyph.cs | 9 - Ryujinx.Ava/Ui/Controls/GlyphValueConverter.cs | 49 --- Ryujinx.Ava/Ui/Controls/HotKeyControl.cs | 52 --- Ryujinx.Ava/Ui/Controls/IGlContextExtension.cs | 25 -- Ryujinx.Ava/Ui/Controls/InputDialog.axaml | 32 -- Ryujinx.Ava/Ui/Controls/InputDialog.axaml.cs | 56 --- Ryujinx.Ava/Ui/Controls/KeyValueConverter.cs | 46 --- Ryujinx.Ava/Ui/Controls/MiniCommand.cs | 71 ---- Ryujinx.Ava/Ui/Controls/NavigationDialogHost.axaml | 11 - .../Ui/Controls/NavigationDialogHost.axaml.cs | 91 ----- Ryujinx.Ava/Ui/Controls/OffscreenTextBox.cs | 40 -- Ryujinx.Ava/Ui/Controls/OpenGLEmbeddedWindow.cs | 85 ----- .../Ui/Controls/OpenToolkitBindingsContext.cs | 20 - .../Ui/Controls/ProfileImageSelectionDialog.axaml | 32 -- .../Controls/ProfileImageSelectionDialog.axaml.cs | 105 ------ Ryujinx.Ava/Ui/Controls/RendererHost.axaml | 8 - Ryujinx.Ava/Ui/Controls/RendererHost.axaml.cs | 126 ------- Ryujinx.Ava/Ui/Controls/SPBOpenGLContext.cs | 47 --- Ryujinx.Ava/Ui/Controls/SaveManager.axaml | 103 ------ Ryujinx.Ava/Ui/Controls/SaveManager.axaml.cs | 160 -------- Ryujinx.Ava/Ui/Controls/UpdateWaitWindow.axaml | 43 --- Ryujinx.Ava/Ui/Controls/UpdateWaitWindow.axaml.cs | 20 - Ryujinx.Ava/Ui/Controls/UserEditor.axaml | 89 ----- Ryujinx.Ava/Ui/Controls/UserEditor.axaml.cs | 117 ------ Ryujinx.Ava/Ui/Controls/UserErrorDialog.cs | 91 ----- Ryujinx.Ava/Ui/Controls/UserRecoverer.axaml | 71 ---- Ryujinx.Ava/Ui/Controls/UserRecoverer.axaml.cs | 44 --- Ryujinx.Ava/Ui/Controls/UserResult.cs | 12 - Ryujinx.Ava/Ui/Controls/UserSelector.axaml | 146 -------- Ryujinx.Ava/Ui/Controls/UserSelector.axaml.cs | 77 ---- Ryujinx.Ava/Ui/Controls/VulkanEmbeddedWindow.cs | 53 --- Ryujinx.Ava/Ui/Controls/Win32NativeInterop.cs | 107 ------ 43 files changed, 3467 deletions(-) delete mode 100644 Ryujinx.Ava/Ui/Controls/ApplicationOpenedEventArgs.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/AvaloniaGlxContext.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/AvaloniaWglContext.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/BitmapArrayValueConverter.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/ButtonKeyAssigner.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/EmbeddedWindow.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/GameGridView.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/GameGridView.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/GameListView.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/GameListView.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/Glyph.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/GlyphValueConverter.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/HotKeyControl.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/IGlContextExtension.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/InputDialog.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/InputDialog.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/KeyValueConverter.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/MiniCommand.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/NavigationDialogHost.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/NavigationDialogHost.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/OffscreenTextBox.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/OpenGLEmbeddedWindow.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/OpenToolkitBindingsContext.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/RendererHost.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/RendererHost.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/SPBOpenGLContext.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/SaveManager.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/SaveManager.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/UpdateWaitWindow.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/UpdateWaitWindow.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/UserEditor.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/UserEditor.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/UserErrorDialog.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/UserRecoverer.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/UserRecoverer.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/UserResult.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/UserSelector.axaml delete mode 100644 Ryujinx.Ava/Ui/Controls/UserSelector.axaml.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/VulkanEmbeddedWindow.cs delete mode 100644 Ryujinx.Ava/Ui/Controls/Win32NativeInterop.cs (limited to 'Ryujinx.Ava/Ui/Controls') diff --git a/Ryujinx.Ava/Ui/Controls/ApplicationOpenedEventArgs.cs b/Ryujinx.Ava/Ui/Controls/ApplicationOpenedEventArgs.cs deleted file mode 100644 index 9909bd6a..00000000 --- a/Ryujinx.Ava/Ui/Controls/ApplicationOpenedEventArgs.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Avalonia.Interactivity; -using Ryujinx.Ui.App.Common; - -namespace Ryujinx.Ava.Ui.Controls -{ - public class ApplicationOpenedEventArgs : RoutedEventArgs - { - public ApplicationData Application { get; } - - public ApplicationOpenedEventArgs(ApplicationData application, RoutedEvent routedEvent) - { - Application = application; - RoutedEvent = routedEvent; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/AvaloniaGlxContext.cs b/Ryujinx.Ava/Ui/Controls/AvaloniaGlxContext.cs deleted file mode 100644 index d48de41d..00000000 --- a/Ryujinx.Ava/Ui/Controls/AvaloniaGlxContext.cs +++ /dev/null @@ -1,16 +0,0 @@ -using SPB.Graphics; -using System; -using System.Runtime.Versioning; - -namespace Ryujinx.Ava.Ui.Controls -{ - [SupportedOSPlatform("linux")] - internal class AvaloniaGlxContext : SPB.Platform.GLX.GLXOpenGLContext - { - public AvaloniaGlxContext(IntPtr handle) - : base(FramebufferFormat.Default, 0, 0, 0, false, null) - { - ContextHandle = handle; - } - } -} diff --git a/Ryujinx.Ava/Ui/Controls/AvaloniaWglContext.cs b/Ryujinx.Ava/Ui/Controls/AvaloniaWglContext.cs deleted file mode 100644 index 01e9b920..00000000 --- a/Ryujinx.Ava/Ui/Controls/AvaloniaWglContext.cs +++ /dev/null @@ -1,16 +0,0 @@ -using SPB.Graphics; -using System; -using System.Runtime.Versioning; - -namespace Ryujinx.Ava.Ui.Controls -{ - [SupportedOSPlatform("windows")] - internal class AvaloniaWglContext : SPB.Platform.WGL.WGLOpenGLContext - { - public AvaloniaWglContext(IntPtr handle) - : base(FramebufferFormat.Default, 0, 0, 0, false, null) - { - ContextHandle = handle; - } - } -} diff --git a/Ryujinx.Ava/Ui/Controls/BitmapArrayValueConverter.cs b/Ryujinx.Ava/Ui/Controls/BitmapArrayValueConverter.cs deleted file mode 100644 index d037e5f1..00000000 --- a/Ryujinx.Ava/Ui/Controls/BitmapArrayValueConverter.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Avalonia.Data.Converters; -using Avalonia.Media; -using Avalonia.Media.Imaging; -using System; -using System.Globalization; -using System.IO; - -namespace Ryujinx.Ava.Ui.Controls -{ - internal class BitmapArrayValueConverter : IValueConverter - { - public static BitmapArrayValueConverter Instance = new(); - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value == null) - { - return null; - } - - if (value is byte[] buffer && targetType == typeof(IImage)) - { - MemoryStream mem = new(buffer); - return new Bitmap(mem); - } - - throw new NotSupportedException(); - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotSupportedException(); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/ButtonKeyAssigner.cs b/Ryujinx.Ava/Ui/Controls/ButtonKeyAssigner.cs deleted file mode 100644 index a83ef961..00000000 --- a/Ryujinx.Ava/Ui/Controls/ButtonKeyAssigner.cs +++ /dev/null @@ -1,118 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Controls.Primitives; -using Avalonia.LogicalTree; -using Avalonia.Threading; -using Ryujinx.Input; -using Ryujinx.Input.Assigner; -using System; -using System.Linq; -using System.Threading.Tasks; - -namespace Ryujinx.Ava.Ui.Controls -{ - internal class ButtonKeyAssigner - { - internal class ButtonAssignedEventArgs : EventArgs - { - public ToggleButton Button { get; } - public bool IsAssigned { get; } - - public ButtonAssignedEventArgs(ToggleButton button, bool isAssigned) - { - Button = button; - IsAssigned = isAssigned; - } - } - - public ToggleButton ToggledButton { get; set; } - - private bool _isWaitingForInput; - private bool _shouldUnbind; - public event EventHandler ButtonAssigned; - - public ButtonKeyAssigner(ToggleButton toggleButton) - { - ToggledButton = toggleButton; - } - - public async void GetInputAndAssign(IButtonAssigner assigner, IKeyboard keyboard = null) - { - Dispatcher.UIThread.Post(() => - { - ToggledButton.IsChecked = true; - }); - - if (_isWaitingForInput) - { - Dispatcher.UIThread.Post(() => - { - Cancel(); - }); - - return; - } - - _isWaitingForInput = true; - - assigner.Initialize(); - - await Task.Run(async () => - { - while (true) - { - if (!_isWaitingForInput) - { - return; - } - - await Task.Delay(10); - - assigner.ReadInput(); - - if (assigner.HasAnyButtonPressed() || assigner.ShouldCancel() || (keyboard != null && keyboard.IsPressed(Key.Escape))) - { - break; - } - } - }); - - await Dispatcher.UIThread.InvokeAsync(() => - { - string pressedButton = assigner.GetPressedButton(); - - if (_shouldUnbind) - { - SetButtonText(ToggledButton, "Unbound"); - } - else if (pressedButton != "") - { - SetButtonText(ToggledButton, pressedButton); - } - - _shouldUnbind = false; - _isWaitingForInput = false; - - ToggledButton.IsChecked = false; - - ButtonAssigned?.Invoke(this, new ButtonAssignedEventArgs(ToggledButton, pressedButton != null)); - - static void SetButtonText(ToggleButton button, string text) - { - ILogical textBlock = button.GetLogicalDescendants().First(x => x is TextBlock); - - if (textBlock != null && textBlock is TextBlock block) - { - block.Text = text; - } - } - }); - } - - public void Cancel(bool shouldUnbind = false) - { - _isWaitingForInput = false; - ToggledButton.IsChecked = false; - _shouldUnbind = shouldUnbind; - } - } -} diff --git a/Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs b/Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs deleted file mode 100644 index eca47644..00000000 --- a/Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs +++ /dev/null @@ -1,401 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Controls.Primitives; -using Avalonia.Media; -using Avalonia.Threading; -using FluentAvalonia.Core; -using FluentAvalonia.UI.Controls; -using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.Ui.Models; -using Ryujinx.Ava.Ui.Windows; -using Ryujinx.Common.Logging; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Ryujinx.Ava.Ui.Controls -{ - public static class ContentDialogHelper - { - private static bool _isChoiceDialogOpen; - - private async static Task ShowContentDialog( - string title, - string primaryText, - string secondaryText, - string primaryButton, - string secondaryButton, - string closeButton, - int iconSymbol, - UserResult primaryButtonResult = UserResult.Ok, - ManualResetEvent deferResetEvent = null, - Func doWhileDeferred = null, - TypedEventHandler deferCloseAction = null) - { - UserResult result = UserResult.None; - - bool useOverlay = false; - Window mainWindow = null; - - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al) - { - foreach (var item in al.Windows) - { - if (item.IsActive && item is MainWindow window && window.ViewModel.IsGameRunning) - { - mainWindow = window; - useOverlay = true; - break; - } - } - } - - ContentDialog contentDialog = null; - ContentDialogOverlayWindow overlay = null; - - if (useOverlay) - { - overlay = new ContentDialogOverlayWindow() - { - Height = mainWindow.Bounds.Height, - Width = mainWindow.Bounds.Width, - Position = mainWindow.PointToScreen(new Point()) - }; - - mainWindow.PositionChanged += OverlayOnPositionChanged; - - void OverlayOnPositionChanged(object sender, PixelPointEventArgs e) - { - overlay.Position = mainWindow.PointToScreen(new Point()); - } - - contentDialog = overlay.ContentDialog; - - bool opened = false; - - overlay.Opened += OverlayOnActivated; - - async void OverlayOnActivated(object sender, EventArgs e) - { - if (opened) - { - return; - } - - opened = true; - - overlay.Position = mainWindow.PointToScreen(new Point()); - - await ShowDialog(); - } - - await overlay.ShowDialog(mainWindow); - } - else - { - contentDialog = new ContentDialog(); - - await ShowDialog(); - } - - async Task ShowDialog() - { - contentDialog.Title = title; - contentDialog.PrimaryButtonText = primaryButton; - contentDialog.SecondaryButtonText = secondaryButton; - contentDialog.CloseButtonText = closeButton; - contentDialog.Content = CreateDialogTextContent(primaryText, secondaryText, iconSymbol); - - contentDialog.PrimaryButtonCommand = MiniCommand.Create(() => - { - result = primaryButtonResult; - }); - contentDialog.SecondaryButtonCommand = MiniCommand.Create(() => - { - result = UserResult.No; - contentDialog.PrimaryButtonClick -= deferCloseAction; - }); - contentDialog.CloseButtonCommand = MiniCommand.Create(() => - { - result = UserResult.Cancel; - contentDialog.PrimaryButtonClick -= deferCloseAction; - }); - - if (deferResetEvent != null) - { - contentDialog.PrimaryButtonClick += deferCloseAction; - } - - if (useOverlay) - { - await contentDialog.ShowAsync(overlay, ContentDialogPlacement.Popup); - - overlay!.Close(); - } - else - { - await contentDialog.ShowAsync(ContentDialogPlacement.Popup); - } - } - - if (useOverlay) - { - overlay.Content = null; - overlay.Close(); - } - - return result; - } - - public async static Task ShowDeferredContentDialog( - StyleableWindow window, - string title, - string primaryText, - string secondaryText, - string primaryButton, - string secondaryButton, - string closeButton, - int iconSymbol, - ManualResetEvent deferResetEvent, - Func doWhileDeferred = null) - { - bool startedDeferring = false; - UserResult result = UserResult.None; - - return await ShowContentDialog( - title, - primaryText, - secondaryText, - primaryButton, - secondaryButton, - closeButton, - iconSymbol, - primaryButton == LocaleManager.Instance["InputDialogYes"] ? UserResult.Yes : UserResult.Ok, - deferResetEvent, - doWhileDeferred, - DeferClose); - - async void DeferClose(ContentDialog sender, ContentDialogButtonClickEventArgs args) - { - if (startedDeferring) - { - return; - } - - sender.PrimaryButtonClick -= DeferClose; - - startedDeferring = true; - - var deferral = args.GetDeferral(); - - result = primaryButton == LocaleManager.Instance["InputDialogYes"] ? UserResult.Yes : UserResult.Ok; - - sender.PrimaryButtonClick -= DeferClose; - -#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed - Task.Run(() => - { - deferResetEvent.WaitOne(); - - Dispatcher.UIThread.Post(() => - { - deferral.Complete(); - }); - }); -#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed - - if (doWhileDeferred != null) - { - await doWhileDeferred(window); - - deferResetEvent.Set(); - } - } - } - - private static Grid CreateDialogTextContent(string primaryText, string secondaryText, int symbol) - { - Grid content = new Grid(); - content.RowDefinitions = new RowDefinitions() { new RowDefinition(), new RowDefinition() }; - content.ColumnDefinitions = new ColumnDefinitions() { new ColumnDefinition(GridLength.Auto), new ColumnDefinition() }; - - content.MinHeight = 80; - - SymbolIcon icon = new SymbolIcon { Symbol = (Symbol)symbol, Margin = new Thickness(10) }; - icon.FontSize = 40; - icon.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center; - Grid.SetColumn(icon, 0); - Grid.SetRowSpan(icon, 2); - Grid.SetRow(icon, 0); - - TextBlock primaryLabel = new TextBlock() - { - Text = primaryText, - Margin = new Thickness(5), - TextWrapping = TextWrapping.Wrap, - MaxWidth = 450 - }; - TextBlock secondaryLabel = new TextBlock() - { - Text = secondaryText, - Margin = new Thickness(5), - TextWrapping = TextWrapping.Wrap, - MaxWidth = 450 - }; - - Grid.SetColumn(primaryLabel, 1); - Grid.SetColumn(secondaryLabel, 1); - Grid.SetRow(primaryLabel, 0); - Grid.SetRow(secondaryLabel, 1); - - content.Children.Add(icon); - content.Children.Add(primaryLabel); - content.Children.Add(secondaryLabel); - - return content; - } - - public static async Task CreateInfoDialog( - string primary, - string secondaryText, - string acceptButton, - string closeButton, - string title) - { - return await ShowContentDialog( - title, - primary, - secondaryText, - acceptButton, - "", - closeButton, - (int)Symbol.Important); - } - - internal static async Task CreateConfirmationDialog( - string primaryText, - string secondaryText, - string acceptButtonText, - string cancelButtonText, - string title, - UserResult primaryButtonResult = UserResult.Yes) - { - return await ShowContentDialog( - string.IsNullOrWhiteSpace(title) ? LocaleManager.Instance["DialogConfirmationTitle"] : title, - primaryText, - secondaryText, - acceptButtonText, - "", - cancelButtonText, - (int)Symbol.Help, - primaryButtonResult); - } - - internal static UpdateWaitWindow CreateWaitingDialog(string mainText, string secondaryText) - { - return new(mainText, secondaryText); - } - - internal static async Task CreateUpdaterInfoDialog(string primary, string secondaryText) - { - await ShowContentDialog( - LocaleManager.Instance["DialogUpdaterTitle"], - primary, - secondaryText, - "", - "", - LocaleManager.Instance["InputDialogOk"], - (int)Symbol.Important); - } - - internal static async Task CreateWarningDialog(string primary, string secondaryText) - { - await ShowContentDialog( - LocaleManager.Instance["DialogWarningTitle"], - primary, - secondaryText, - "", - "", - LocaleManager.Instance["InputDialogOk"], - (int)Symbol.Important); - } - - internal static async Task CreateErrorDialog(string errorMessage, string secondaryErrorMessage = "") - { - Logger.Error?.Print(LogClass.Application, errorMessage); - - await ShowContentDialog( - LocaleManager.Instance["DialogErrorTitle"], - LocaleManager.Instance["DialogErrorMessage"], - errorMessage, - secondaryErrorMessage, - "", - LocaleManager.Instance["InputDialogOk"], - (int)Symbol.Dismiss); - } - - internal static async Task CreateChoiceDialog(string title, string primary, string secondaryText) - { - if (_isChoiceDialogOpen) - { - return false; - } - - _isChoiceDialogOpen = true; - - UserResult response = - await ShowContentDialog( - title, - primary, - secondaryText, - LocaleManager.Instance["InputDialogYes"], - "", - LocaleManager.Instance["InputDialogNo"], - (int)Symbol.Help, - UserResult.Yes); - - _isChoiceDialogOpen = false; - - return response == UserResult.Yes; - } - - internal static async Task CreateExitDialog() - { - return await CreateChoiceDialog( - LocaleManager.Instance["DialogExitTitle"], - LocaleManager.Instance["DialogExitMessage"], - LocaleManager.Instance["DialogExitSubMessage"]); - } - - internal static async Task CreateStopEmulationDialog() - { - return await CreateChoiceDialog( - LocaleManager.Instance["DialogStopEmulationTitle"], - LocaleManager.Instance["DialogStopEmulationMessage"], - LocaleManager.Instance["DialogExitSubMessage"]); - } - - internal static async Task CreateInputDialog( - string title, - string mainText, - string subText, - uint maxLength = int.MaxValue, - string input = "") - { - var result = await InputDialog.ShowInputDialog( - title, - mainText, - input, - subText, - maxLength); - - if (result.Result == UserResult.Ok) - { - return result.Input; - } - - return string.Empty; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/EmbeddedWindow.cs b/Ryujinx.Ava/Ui/Controls/EmbeddedWindow.cs deleted file mode 100644 index 05b2cc5b..00000000 --- a/Ryujinx.Ava/Ui/Controls/EmbeddedWindow.cs +++ /dev/null @@ -1,233 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Input; -using Avalonia.Platform; -using Ryujinx.Ava.Ui.Helper; -using SPB.Graphics; -using SPB.Platform; -using SPB.Platform.GLX; -using System; -using System.Runtime.InteropServices; -using System.Runtime.Versioning; -using System.Threading.Tasks; -using static Ryujinx.Ava.Ui.Controls.Win32NativeInterop; - -namespace Ryujinx.Ava.Ui.Controls -{ - public class EmbeddedWindow : NativeControlHost - { - private WindowProc _wndProcDelegate; - private string _className; - - protected GLXWindow X11Window { get; set; } - protected IntPtr WindowHandle { get; set; } - protected IntPtr X11Display { get; set; } - protected IntPtr NsView { get; set; } - protected IntPtr MetalLayer { get; set; } - - private UpdateBoundsCallbackDelegate _updateBoundsCallback; - - public event EventHandler WindowCreated; - public event EventHandler SizeChanged; - - protected virtual void OnWindowDestroyed() { } - protected virtual void OnWindowDestroying() - { - WindowHandle = IntPtr.Zero; - X11Display = IntPtr.Zero; - } - - public EmbeddedWindow() - { - var stateObserverable = this.GetObservable(BoundsProperty); - - stateObserverable.Subscribe(StateChanged); - - this.Initialized += NativeEmbeddedWindow_Initialized; - } - - public virtual void OnWindowCreated() { } - - private void NativeEmbeddedWindow_Initialized(object sender, EventArgs e) - { - OnWindowCreated(); - - Task.Run(() => - { - WindowCreated?.Invoke(this, WindowHandle); - }); - } - - private void StateChanged(Rect rect) - { - SizeChanged?.Invoke(this, rect.Size); - _updateBoundsCallback?.Invoke(rect); - } - - protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent) - { - if (OperatingSystem.IsLinux()) - { - return CreateLinux(parent); - } - else if (OperatingSystem.IsWindows()) - { - return CreateWin32(parent); - } - else if (OperatingSystem.IsMacOS()) - { - return CreateMacOs(parent); - } - - return base.CreateNativeControlCore(parent); - } - - protected override void DestroyNativeControlCore(IPlatformHandle control) - { - OnWindowDestroying(); - - if (OperatingSystem.IsLinux()) - { - DestroyLinux(); - } - else if (OperatingSystem.IsWindows()) - { - DestroyWin32(control); - } - else if (OperatingSystem.IsMacOS()) - { - DestroyMacOS(); - } - else - { - base.DestroyNativeControlCore(control); - } - - OnWindowDestroyed(); - } - - [SupportedOSPlatform("linux")] - protected virtual IPlatformHandle CreateLinux(IPlatformHandle parent) - { - X11Window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100) as GLXWindow; - WindowHandle = X11Window.WindowHandle.RawHandle; - X11Display = X11Window.DisplayHandle.RawHandle; - - return new PlatformHandle(WindowHandle, "X11"); - } - - [SupportedOSPlatform("windows")] - IPlatformHandle CreateWin32(IPlatformHandle parent) - { - _className = "NativeWindow-" + Guid.NewGuid(); - _wndProcDelegate = WndProc; - var wndClassEx = new WNDCLASSEX - { - cbSize = Marshal.SizeOf(), - hInstance = GetModuleHandle(null), - lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate), - style = ClassStyles.CS_OWNDC, - lpszClassName = Marshal.StringToHGlobalUni(_className), - hCursor = LoadCursor(IntPtr.Zero, (IntPtr)Cursors.IDC_ARROW) - }; - - var atom = RegisterClassEx(ref wndClassEx); - - var handle = CreateWindowEx( - 0, - _className, - "NativeWindow", - WindowStyles.WS_CHILD, - 0, - 0, - 640, - 480, - parent.Handle, - IntPtr.Zero, - IntPtr.Zero, - IntPtr.Zero); - - WindowHandle = handle; - - Marshal.FreeHGlobal(wndClassEx.lpszClassName); - - return new PlatformHandle(WindowHandle, "HWND"); - } - - [SupportedOSPlatform("windows")] - IntPtr WndProc(IntPtr hWnd, WindowsMessages msg, IntPtr wParam, IntPtr lParam) - { - var point = new Point((long)lParam & 0xFFFF, ((long)lParam >> 16) & 0xFFFF); - var root = VisualRoot as Window; - bool isLeft = false; - switch (msg) - { - case WindowsMessages.LBUTTONDOWN: - case WindowsMessages.RBUTTONDOWN: - isLeft = msg == WindowsMessages.LBUTTONDOWN; - this.RaiseEvent(new PointerPressedEventArgs( - this, - new Pointer(0, PointerType.Mouse, true), - root, - this.TranslatePoint(point, root).Value, - (ulong)Environment.TickCount64, - new PointerPointProperties(isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton, isLeft ? PointerUpdateKind.LeftButtonPressed : PointerUpdateKind.RightButtonPressed), - KeyModifiers.None)); - break; - case WindowsMessages.LBUTTONUP: - case WindowsMessages.RBUTTONUP: - isLeft = msg == WindowsMessages.LBUTTONUP; - this.RaiseEvent(new PointerReleasedEventArgs( - this, - new Pointer(0, PointerType.Mouse, true), - root, - this.TranslatePoint(point, root).Value, - (ulong)Environment.TickCount64, - new PointerPointProperties(isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton, isLeft ? PointerUpdateKind.LeftButtonReleased : PointerUpdateKind.RightButtonReleased), - KeyModifiers.None, - isLeft ? MouseButton.Left : MouseButton.Right)); - break; - case WindowsMessages.MOUSEMOVE: - this.RaiseEvent(new PointerEventArgs( - PointerMovedEvent, - this, - new Pointer(0, PointerType.Mouse, true), - root, - this.TranslatePoint(point, root).Value, - (ulong)Environment.TickCount64, - new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.Other), - KeyModifiers.None)); - break; - } - return DefWindowProc(hWnd, msg, (IntPtr)wParam, (IntPtr)lParam); - } - - [SupportedOSPlatform("macos")] - IPlatformHandle CreateMacOs(IPlatformHandle parent) - { - MetalLayer = MetalHelper.GetMetalLayer(out IntPtr nsView, out _updateBoundsCallback); - - NsView = nsView; - - return new PlatformHandle(nsView, "NSView"); - } - - void DestroyLinux() - { - X11Window?.Dispose(); - } - - [SupportedOSPlatform("windows")] - void DestroyWin32(IPlatformHandle handle) - { - DestroyWindow(handle.Handle); - UnregisterClass(_className, GetModuleHandle(null)); - } - - [SupportedOSPlatform("macos")] - void DestroyMacOS() - { - MetalHelper.DestroyMetalLayer(NsView, MetalLayer); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/GameGridView.axaml b/Ryujinx.Ava/Ui/Controls/GameGridView.axaml deleted file mode 100644 index b0669463..00000000 --- a/Ryujinx.Ava/Ui/Controls/GameGridView.axaml +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/GameGridView.axaml.cs b/Ryujinx.Ava/Ui/Controls/GameGridView.axaml.cs deleted file mode 100644 index 4dfe4f0e..00000000 --- a/Ryujinx.Ava/Ui/Controls/GameGridView.axaml.cs +++ /dev/null @@ -1,82 +0,0 @@ -using Avalonia.Collections; -using Avalonia.Controls; -using Avalonia.Input; -using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; -using LibHac.Common; -using Ryujinx.Ava.Ui.ViewModels; -using Ryujinx.Ui.App.Common; -using System; - -namespace Ryujinx.Ava.Ui.Controls -{ - public partial class GameGridView : UserControl - { - private ApplicationData _selectedApplication; - public static readonly RoutedEvent ApplicationOpenedEvent = - RoutedEvent.Register(nameof(ApplicationOpened), RoutingStrategies.Bubble); - - public event EventHandler ApplicationOpened - { - add { AddHandler(ApplicationOpenedEvent, value); } - remove { RemoveHandler(ApplicationOpenedEvent, value); } - } - - public void GameList_DoubleTapped(object sender, RoutedEventArgs args) - { - if (sender is ListBox listBox) - { - if (listBox.SelectedItem is ApplicationData selected) - { - RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent)); - } - } - } - - public void GameList_SelectionChanged(object sender, SelectionChangedEventArgs args) - { - if (sender is ListBox listBox) - { - var selected = listBox.SelectedItem as ApplicationData; - - _selectedApplication = selected; - } - } - - public ApplicationData SelectedApplication => _selectedApplication; - - public GameGridView() - { - InitializeComponent(); - } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - - private void SearchBox_OnKeyUp(object sender, KeyEventArgs e) - { - (DataContext as MainWindowViewModel).SearchText = (sender as TextBox).Text; - } - - private void MenuBase_OnMenuOpened(object sender, EventArgs e) - { - var selection = SelectedApplication; - - if (selection != null) - { - if (sender is ContextMenu menu) - { - bool canHaveUserSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.UserAccountSaveDataSize > 0; - bool canHaveDeviceSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.DeviceSaveDataSize > 0; - bool canHaveBcatSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0; - - ((menu.Items as AvaloniaList)[2] as MenuItem).IsEnabled = canHaveUserSave; - ((menu.Items as AvaloniaList)[3] as MenuItem).IsEnabled = canHaveDeviceSave; - ((menu.Items as AvaloniaList)[4] as MenuItem).IsEnabled = canHaveBcatSave; - } - } - } - } -} diff --git a/Ryujinx.Ava/Ui/Controls/GameListView.axaml b/Ryujinx.Ava/Ui/Controls/GameListView.axaml deleted file mode 100644 index 2c41cef8..00000000 --- a/Ryujinx.Ava/Ui/Controls/GameListView.axaml +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/GameListView.axaml.cs b/Ryujinx.Ava/Ui/Controls/GameListView.axaml.cs deleted file mode 100644 index 1cca3bea..00000000 --- a/Ryujinx.Ava/Ui/Controls/GameListView.axaml.cs +++ /dev/null @@ -1,82 +0,0 @@ -using Avalonia.Collections; -using Avalonia.Controls; -using Avalonia.Input; -using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; -using LibHac.Common; -using Ryujinx.Ava.Ui.ViewModels; -using Ryujinx.Ui.App.Common; -using System; - -namespace Ryujinx.Ava.Ui.Controls -{ - public partial class GameListView : UserControl - { - private ApplicationData _selectedApplication; - public static readonly RoutedEvent ApplicationOpenedEvent = - RoutedEvent.Register(nameof(ApplicationOpened), RoutingStrategies.Bubble); - - public event EventHandler ApplicationOpened - { - add { AddHandler(ApplicationOpenedEvent, value); } - remove { RemoveHandler(ApplicationOpenedEvent, value); } - } - - public void GameList_DoubleTapped(object sender, RoutedEventArgs args) - { - if (sender is ListBox listBox) - { - if (listBox.SelectedItem is ApplicationData selected) - { - RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent)); - } - } - } - - public void GameList_SelectionChanged(object sender, SelectionChangedEventArgs args) - { - if (sender is ListBox listBox) - { - var selected = listBox.SelectedItem as ApplicationData; - - _selectedApplication = selected; - } - } - - public ApplicationData SelectedApplication => _selectedApplication; - - public GameListView() - { - InitializeComponent(); - } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - - private void SearchBox_OnKeyUp(object sender, KeyEventArgs e) - { - (DataContext as MainWindowViewModel).SearchText = (sender as TextBox).Text; - } - - private void MenuBase_OnMenuOpened(object sender, EventArgs e) - { - var selection = SelectedApplication; - - if (selection != null) - { - if (sender is ContextMenu menu) - { - bool canHaveUserSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.UserAccountSaveDataSize > 0; - bool canHaveDeviceSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.DeviceSaveDataSize > 0; - bool canHaveBcatSave = !Utilities.IsZeros(selection.ControlHolder.ByteSpan) && selection.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0; - - ((menu.Items as AvaloniaList)[2] as MenuItem).IsEnabled = canHaveUserSave; - ((menu.Items as AvaloniaList)[3] as MenuItem).IsEnabled = canHaveDeviceSave; - ((menu.Items as AvaloniaList)[4] as MenuItem).IsEnabled = canHaveBcatSave; - } - } - } - } -} diff --git a/Ryujinx.Ava/Ui/Controls/Glyph.cs b/Ryujinx.Ava/Ui/Controls/Glyph.cs deleted file mode 100644 index 74a3c94a..00000000 --- a/Ryujinx.Ava/Ui/Controls/Glyph.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Ava.Ui.Controls -{ - public enum Glyph : int - { - List, - Grid, - Chip - } -} diff --git a/Ryujinx.Ava/Ui/Controls/GlyphValueConverter.cs b/Ryujinx.Ava/Ui/Controls/GlyphValueConverter.cs deleted file mode 100644 index 63c6a17d..00000000 --- a/Ryujinx.Ava/Ui/Controls/GlyphValueConverter.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Avalonia.Data; -using Avalonia.Markup.Xaml; -using FluentAvalonia.UI.Controls; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Ava.Ui.Controls -{ - public class GlyphValueConverter : MarkupExtension - { - private string _key; - - private static Dictionary _glyphs = new Dictionary - { - { Glyph.List, char.ConvertFromUtf32((int)Symbol.List).ToString() }, - { Glyph.Grid, char.ConvertFromUtf32((int)Symbol.ViewAll).ToString() }, - { Glyph.Chip, char.ConvertFromUtf32(59748).ToString() } - }; - - public GlyphValueConverter(string key) - { - _key = key; - } - - public string this[string key] - { - get - { - if (_glyphs.TryGetValue(Enum.Parse(key), out var val)) - { - return val; - } - - return string.Empty; - } - } - - public override object ProvideValue(IServiceProvider serviceProvider) - { - Avalonia.Markup.Xaml.MarkupExtensions.ReflectionBindingExtension binding = new($"[{_key}]") - { - Mode = BindingMode.OneWay, - Source = this - }; - - return binding.ProvideValue(serviceProvider); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/HotKeyControl.cs b/Ryujinx.Ava/Ui/Controls/HotKeyControl.cs deleted file mode 100644 index d3ab1e8f..00000000 --- a/Ryujinx.Ava/Ui/Controls/HotKeyControl.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Input; -using System; -using System.Windows.Input; - -namespace Ryujinx.Ava.Ui.Controls -{ - public class HotKeyControl : ContentControl, ICommandSource - { - public static readonly StyledProperty CommandParameterProperty = - AvaloniaProperty.Register(nameof(CommandParameter)); - - public static readonly DirectProperty CommandProperty = - AvaloniaProperty.RegisterDirect(nameof(Command), - control => control.Command, (control, command) => control.Command = command, enableDataValidation: true); - - public static readonly StyledProperty HotKeyProperty = HotKeyManager.HotKeyProperty.AddOwner