aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Ava/UI/Helpers
diff options
context:
space:
mode:
authorMary Guillemard <mary@mary.zone>2024-03-02 12:51:05 +0100
committerGitHub <noreply@github.com>2024-03-02 12:51:05 +0100
commitec6cb0abb4b7669895b6e96fd7581c93b5abd691 (patch)
tree128c862ff5faea0b219467656d4023bee7faefb5 /src/Ryujinx.Ava/UI/Helpers
parent53b5985da6b9d7b281d9fc25b93bfd1d1918a107 (diff)
infra: Make Avalonia the default UI (#6375)
* misc: Move Ryujinx project to Ryujinx.Gtk3 This breaks release CI for now but that's fine. Signed-off-by: Mary Guillemard <mary@mary.zone> * misc: Move Ryujinx.Ava project to Ryujinx This breaks CI for now, but it's fine. Signed-off-by: Mary Guillemard <mary@mary.zone> * infra: Make Avalonia the default UI Should fix CI after the previous changes. GTK3 isn't build by the release job anymore, only by PR CI. This also ensure that the test-ava update package is still generated to allow update from the old testing channel. Signed-off-by: Mary Guillemard <mary@mary.zone> * Fix missing copy in create_app_bundle.sh Signed-off-by: Mary Guillemard <mary@mary.zone> * Fix syntax error Signed-off-by: Mary Guillemard <mary@mary.zone> --------- Signed-off-by: Mary Guillemard <mary@mary.zone>
Diffstat (limited to 'src/Ryujinx.Ava/UI/Helpers')
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs16
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs36
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs118
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs425
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/Glyph.cs9
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs42
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs46
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/LocalizedNeverConverter.cs43
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs102
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs71
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs70
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs39
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/TimeZoneConverter.cs28
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs90
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/UserResult.cs12
-rw-r--r--src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs125
16 files changed, 0 insertions, 1272 deletions
diff --git a/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs b/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs
deleted file mode 100644
index bc5622b5..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Avalonia.Interactivity;
-using Ryujinx.UI.App.Common;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- public class ApplicationOpenedEventArgs : RoutedEventArgs
- {
- public ApplicationData Application { get; }
-
- public ApplicationOpenedEventArgs(ApplicationData application, RoutedEvent routedEvent)
- {
- Application = application;
- RoutedEvent = routedEvent;
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs b/src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs
deleted file mode 100644
index 42bd8d5a..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs
+++ /dev/null
@@ -1,36 +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.Helpers
-{
- 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();
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs b/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs
deleted file mode 100644
index 7e8ba734..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/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.Helpers
-{
- 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<ButtonAssignedEventArgs> 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/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs b/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs
deleted file mode 100644
index 15b7ddd1..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs
+++ /dev/null
@@ -1,425 +0,0 @@
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Layout;
-using Avalonia.Media;
-using Avalonia.Threading;
-using FluentAvalonia.Core;
-using FluentAvalonia.UI.Controls;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.UI.Windows;
-using Ryujinx.Common.Logging;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- public static class ContentDialogHelper
- {
- private static bool _isChoiceDialogOpen;
- private static ContentDialogOverlayWindow _contentDialogOverlayWindow;
-
- private async static Task<UserResult> ShowContentDialog(
- string title,
- object content,
- string primaryButton,
- string secondaryButton,
- string closeButton,
- UserResult primaryButtonResult = UserResult.Ok,
- ManualResetEvent deferResetEvent = null,
- TypedEventHandler<ContentDialog, ContentDialogButtonClickEventArgs> deferCloseAction = null)
- {
- UserResult result = UserResult.None;
-
- ContentDialog contentDialog = new()
- {
- Title = title,
- PrimaryButtonText = primaryButton,
- SecondaryButtonText = secondaryButton,
- CloseButtonText = closeButton,
- Content = content,
- 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;
- }
-
- await ShowAsync(contentDialog);
-
- return result;
- }
-
- public async static Task<UserResult> ShowTextDialog(
- string title,
- string primaryText,
- string secondaryText,
- string primaryButton,
- string secondaryButton,
- string closeButton,
- int iconSymbol,
- UserResult primaryButtonResult = UserResult.Ok,
- ManualResetEvent deferResetEvent = null,
- TypedEventHandler<ContentDialog, ContentDialogButtonClickEventArgs> deferCloseAction = null)
- {
- Grid content = CreateTextDialogContent(primaryText, secondaryText, iconSymbol);
-
- return await ShowContentDialog(title, content, primaryButton, secondaryButton, closeButton, primaryButtonResult, deferResetEvent, deferCloseAction);
- }
-
- public async static Task<UserResult> ShowDeferredContentDialog(
- StyleableWindow window,
- string title,
- string primaryText,
- string secondaryText,
- string primaryButton,
- string secondaryButton,
- string closeButton,
- int iconSymbol,
- ManualResetEvent deferResetEvent,
- Func<Window, Task> doWhileDeferred = null)
- {
- bool startedDeferring = false;
-
- return await ShowTextDialog(
- title,
- primaryText,
- secondaryText,
- primaryButton,
- secondaryButton,
- closeButton,
- iconSymbol,
- primaryButton == LocaleManager.Instance[LocaleKeys.InputDialogYes] ? UserResult.Yes : UserResult.Ok,
- deferResetEvent,
- DeferClose);
-
- async void DeferClose(ContentDialog sender, ContentDialogButtonClickEventArgs args)
- {
- if (startedDeferring)
- {
- return;
- }
-
- sender.PrimaryButtonClick -= DeferClose;
-
- startedDeferring = true;
-
- var deferral = args.GetDeferral();
-
- sender.PrimaryButtonClick -= DeferClose;
-
- _ = Task.Run(() =>
- {
- deferResetEvent.WaitOne();
-
- Dispatcher.UIThread.Post(() =>
- {
- deferral.Complete();
- });
- });
-
- if (doWhileDeferred != null)
- {
- await doWhileDeferred(window);
-
- deferResetEvent.Set();
- }
- }
- }
-
- private static Grid CreateTextDialogContent(string primaryText, string secondaryText, int symbol)
- {
- Grid content = new()
- {
- RowDefinitions = new RowDefinitions { new(), new() },
- ColumnDefinitions = new ColumnDefinitions { new(GridLength.Auto), new() },
-
- MinHeight = 80,
- };
-
- SymbolIcon icon = new()
- {
- Symbol = (Symbol)symbol,
- Margin = new Thickness(10),
- FontSize = 40,
- VerticalAlignment = VerticalAlignment.Center,
- };
-
- Grid.SetColumn(icon, 0);
- Grid.SetRowSpan(icon, 2);
- Grid.SetRow(icon, 0);
-
- TextBlock primaryLabel = new()
- {
- Text = primaryText,
- Margin = new Thickness(5),
- TextWrapping = TextWrapping.Wrap,
- MaxWidth = 450,
- };
-
- TextBlock secondaryLabel = new()
- {
- 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<UserResult> CreateInfoDialog(
- string primary,
- string secondaryText,
- string acceptButton,
- string closeButton,
- string title)
- {
- return await ShowTextDialog(
- title,
- primary,
- secondaryText,
- acceptButton,
- "",
- closeButton,
- (int)Symbol.Important);
- }
-
- internal static async Task<UserResult> CreateConfirmationDialog(
- string primaryText,
- string secondaryText,
- string acceptButtonText,
- string cancelButtonText,
- string title,
- UserResult primaryButtonResult = UserResult.Yes)
- {
- return await ShowTextDialog(
- string.IsNullOrWhiteSpace(title) ? LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle] : title,
- primaryText,
- secondaryText,
- acceptButtonText,
- "",
- cancelButtonText,
- (int)Symbol.Help,
- primaryButtonResult);
- }
-
- internal static async Task CreateUpdaterInfoDialog(string primary, string secondaryText)
- {
- await ShowTextDialog(
- LocaleManager.Instance[LocaleKeys.DialogUpdaterTitle],
- primary,
- secondaryText,
- "",
- "",
- LocaleManager.Instance[LocaleKeys.InputDialogOk],
- (int)Symbol.Important);
- }
-
- internal static async Task CreateWarningDialog(string primary, string secondaryText)
- {
- await ShowTextDialog(
- LocaleManager.Instance[LocaleKeys.DialogWarningTitle],
- primary,
- secondaryText,
- "",
- "",
- LocaleManager.Instance[LocaleKeys.InputDialogOk],
- (int)Symbol.Important);
- }
-
- internal static async Task CreateErrorDialog(string errorMessage, string secondaryErrorMessage = "")
- {
- Logger.Error?.Print(LogClass.Application, errorMessage);
-
- await ShowTextDialog(
- LocaleManager.Instance[LocaleKeys.DialogErrorTitle],
- LocaleManager.Instance[LocaleKeys.DialogErrorMessage],
- errorMessage,
- secondaryErrorMessage,
- "",
- LocaleManager.Instance[LocaleKeys.InputDialogOk],
- (int)Symbol.Dismiss);
- }
-
- internal static async Task<bool> CreateChoiceDialog(string title, string primary, string secondaryText)
- {
- if (_isChoiceDialogOpen)
- {
- return false;
- }
-
- _isChoiceDialogOpen = true;
-
- UserResult response = await ShowTextDialog(
- title,
- primary,
- secondaryText,
- LocaleManager.Instance[LocaleKeys.InputDialogYes],
- "",
- LocaleManager.Instance[LocaleKeys.InputDialogNo],
- (int)Symbol.Help,
- UserResult.Yes);
-
- _isChoiceDialogOpen = false;
-
- return response == UserResult.Yes;
- }
-
- internal static async Task<bool> CreateExitDialog()
- {
- return await CreateChoiceDialog(
- LocaleManager.Instance[LocaleKeys.DialogExitTitle],
- LocaleManager.Instance[LocaleKeys.DialogExitMessage],
- LocaleManager.Instance[LocaleKeys.DialogExitSubMessage]);
- }
-
- internal static async Task<bool> CreateStopEmulationDialog()
- {
- return await CreateChoiceDialog(
- LocaleManager.Instance[LocaleKeys.DialogStopEmulationTitle],
- LocaleManager.Instance[LocaleKeys.DialogStopEmulationMessage],
- LocaleManager.Instance[LocaleKeys.DialogExitSubMessage]);
- }
-
- public static async Task<ContentDialogResult> ShowAsync(ContentDialog contentDialog)
- {
- ContentDialogResult result;
- bool isTopDialog = true;
-
- Window parent = GetMainWindow();
-
- if (_contentDialogOverlayWindow != null)
- {
- isTopDialog = false;
- }
-
- if (parent is MainWindow window)
- {
- parent.Activate();
-
- _contentDialogOverlayWindow = new ContentDialogOverlayWindow
- {
- Height = parent.Bounds.Height,
- Width = parent.Bounds.Width,
- Position = parent.PointToScreen(new Point()),
- ShowInTaskbar = false,
- };
-
- parent.PositionChanged += OverlayOnPositionChanged;
-
- void OverlayOnPositionChanged(object sender, PixelPointEventArgs e)
- {
- if (_contentDialogOverlayWindow is null)
- {
- return;
- }
-
- _contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
- }
-
- _contentDialogOverlayWindow.ContentDialog = contentDialog;
-
- bool opened = false;
-
- _contentDialogOverlayWindow.Opened += OverlayOnActivated;
-
- async void OverlayOnActivated(object sender, EventArgs e)
- {
- if (opened)
- {
- return;
- }
-
- opened = true;
-
- _contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
-
- result = await ShowDialog();
- }
-
- result = await _contentDialogOverlayWindow.ShowDialog<ContentDialogResult>(parent);
- }
- else
- {
- result = await ShowDialog();
- }
-
- async Task<ContentDialogResult> ShowDialog()
- {
- if (_contentDialogOverlayWindow is not null)
- {
- result = await contentDialog.ShowAsync(_contentDialogOverlayWindow);
-
- _contentDialogOverlayWindow!.Close();
- }
- else
- {
- result = ContentDialogResult.None;
-
- Logger.Warning?.Print(LogClass.UI, "Content dialog overlay failed to populate. Default value has been returned.");
- }
-
- return result;
- }
-
- if (isTopDialog && _contentDialogOverlayWindow is not null)
- {
- _contentDialogOverlayWindow.Content = null;
- _contentDialogOverlayWindow.Close();
- _contentDialogOverlayWindow = null;
- }
-
- return result;
- }
-
- public static Task ShowWindowAsync(Window dialogWindow, Window mainWindow = null)
- {
- mainWindow ??= GetMainWindow();
-
- return dialogWindow.ShowDialog(_contentDialogOverlayWindow ?? mainWindow);
- }
-
- private static Window GetMainWindow()
- {
- if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al)
- {
- foreach (Window item in al.Windows)
- {
- if (item is MainWindow window)
- {
- return window;
- }
- }
- }
-
- return null;
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/Glyph.cs b/src/Ryujinx.Ava/UI/Helpers/Glyph.cs
deleted file mode 100644
index f257dc02..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/Glyph.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Ryujinx.Ava.UI.Helpers
-{
- public enum Glyph
- {
- List,
- Grid,
- Chip,
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs b/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs
deleted file mode 100644
index 7da23648..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using Avalonia.Markup.Xaml;
-using FluentAvalonia.UI.Controls;
-using System;
-using System.Collections.Generic;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- public class GlyphValueConverter : MarkupExtension
- {
- private readonly string _key;
-
- private static readonly Dictionary<Glyph, string> _glyphs = new()
- {
- { Glyph.List, char.ConvertFromUtf32((int)Symbol.List) },
- { Glyph.Grid, char.ConvertFromUtf32((int)Symbol.ViewAll) },
- { Glyph.Chip, char.ConvertFromUtf32(59748) },
- };
-
- public GlyphValueConverter(string key)
- {
- _key = key;
- }
-
- public string this[string key]
- {
- get
- {
- if (_glyphs.TryGetValue(Enum.Parse<Glyph>(key), out var val))
- {
- return val;
- }
-
- return string.Empty;
- }
- }
-
- public override object ProvideValue(IServiceProvider serviceProvider)
- {
- return this[_key];
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs b/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs
deleted file mode 100644
index 028ed6bf..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using Avalonia.Data.Converters;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.Configuration.Hid.Controller;
-using System;
-using System.Globalization;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- internal class KeyValueConverter : IValueConverter
- {
- public static KeyValueConverter Instance = new();
-
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value == null)
- {
- return null;
- }
-
- return value.ToString();
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- object key = null;
-
- if (value != null)
- {
- if (targetType == typeof(Key))
- {
- key = Enum.Parse<Key>(value.ToString());
- }
- else if (targetType == typeof(GamepadInputId))
- {
- key = Enum.Parse<GamepadInputId>(value.ToString());
- }
- else if (targetType == typeof(StickInputId))
- {
- key = Enum.Parse<StickInputId>(value.ToString());
- }
- }
-
- return key;
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/LocalizedNeverConverter.cs b/src/Ryujinx.Ava/UI/Helpers/LocalizedNeverConverter.cs
deleted file mode 100644
index 26fe36c4..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/LocalizedNeverConverter.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using Avalonia.Data.Converters;
-using Avalonia.Markup.Xaml;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.UI.Common.Helper;
-using System;
-using System.Globalization;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- /// <summary>
- /// This <see cref="IValueConverter"/> makes sure that the string "Never" that's returned by <see cref="ValueFormatUtils.FormatDateTime"/> is properly localized in the Avalonia UI.
- /// After the Avalonia UI has been made the default and the GTK UI is removed, <see cref="ValueFormatUtils"/> should be updated to directly return a localized string.
- /// </summary>
- internal class LocalizedNeverConverter : MarkupExtension, IValueConverter
- {
- private static readonly LocalizedNeverConverter _instance = new();
-
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value is not string valStr)
- {
- return "";
- }
-
- if (valStr == "Never")
- {
- return LocaleManager.Instance[LocaleKeys.Never];
- }
-
- return valStr;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotSupportedException();
- }
-
- public override object ProvideValue(IServiceProvider serviceProvider)
- {
- return _instance;
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs b/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs
deleted file mode 100644
index fc714541..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-using Avalonia.Logging;
-using Avalonia.Utilities;
-using Ryujinx.Common.Logging;
-using System;
-using System.Text;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- using AvaLogger = Avalonia.Logging.Logger;
- using AvaLogLevel = LogEventLevel;
- using RyuLogClass = LogClass;
- using RyuLogger = Ryujinx.Common.Logging.Logger;
-
- internal class LoggerAdapter : ILogSink
- {
- public static void Register()
- {
- AvaLogger.Sink = new LoggerAdapter();
- }
-
- private static RyuLogger.Log? GetLog(AvaLogLevel level)
- {
- return level switch
- {
- AvaLogLevel.Verbose => RyuLogger.Debug,
- AvaLogLevel.Debug => RyuLogger.Debug,
- AvaLogLevel.Information => RyuLogger.Debug,
- AvaLogLevel.Warning => RyuLogger.Debug,
- AvaLogLevel.Error => RyuLogger.Error,
- AvaLogLevel.Fatal => RyuLogger.Error,
- _ => throw new ArgumentOutOfRangeException(nameof(level), level, null),
- };
- }
-
- public bool IsEnabled(AvaLogLevel level, string area)
- {
- return GetLog(level) != null;
- }
-
- public void Log(AvaLogLevel level, string area, object source, string messageTemplate)
- {
- GetLog(level)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, null));
- }
-
- public void Log(AvaLogLevel level, string area, object source, string messageTemplate, params object[] propertyValues)
- {
- GetLog(level)?.PrintMsg(RyuLogClass.UI, Format(level, area, messageTemplate, source, propertyValues));
- }
-
- private static string Format(AvaLogLevel level, string area, string template, object source, object[] v)
- {
- var result = new StringBuilder();
- var r = new CharacterReader(template.AsSpan());
- int i = 0;
-
- result.Append('[');
- result.Append(level);
- result.Append("] ");
-
- result.Append('[');
- result.Append(area);
- result.Append("] ");
-
- while (!r.End)
- {
- var c = r.Take();
-
- if (c != '{')
- {
- result.Append(c);
- }
- else
- {
- if (r.Peek != '{')
- {
- result.Append('\'');
- result.Append(i < v.Length ? v[i++] : null);
- result.Append('\'');
- r.TakeUntil('}');
- r.Take();
- }
- else
- {
- result.Append('{');
- r.Take();
- }
- }
- }
-
- if (source != null)
- {
- result.Append(" (");
- result.Append(source.GetType().Name);
- result.Append(" #");
- result.Append(source.GetHashCode());
- result.Append(')');
- }
-
- return result.ToString();
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs b/src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs
deleted file mode 100644
index 7e1bb9a6..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using System.Windows.Input;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- public sealed class MiniCommand<T> : MiniCommand, ICommand
- {
- private readonly Action<T> _callback;
- private bool _busy;
- private readonly Func<T, Task> _asyncCallback;
-
- public MiniCommand(Action<T> callback)
- {
- _callback = callback;
- }
-
- public MiniCommand(Func<T, Task> callback)
- {
- _asyncCallback = callback;
- }
-
- private bool Busy
- {
- get => _busy;
- set
- {
- _busy = value;
- CanExecuteChanged?.Invoke(this, EventArgs.Empty);
- }
- }
-
- public override event EventHandler CanExecuteChanged;
- public override bool CanExecute(object parameter) => !_busy;
-
- public override async void Execute(object parameter)
- {
- if (Busy)
- {
- return;
- }
- try
- {
- Busy = true;
- if (_callback != null)
- {
- _callback((T)parameter);
- }
- else
- {
- await _asyncCallback((T)parameter);
- }
- }
- finally
- {
- Busy = false;
- }
- }
- }
-
- public abstract class MiniCommand : ICommand
- {
- public static MiniCommand Create(Action callback) => new MiniCommand<object>(_ => callback());
- public static MiniCommand Create<TArg>(Action<TArg> callback) => new MiniCommand<TArg>(callback);
- public static MiniCommand CreateFromTask(Func<Task> callback) => new MiniCommand<object>(_ => callback());
-
- public abstract bool CanExecute(object parameter);
- public abstract void Execute(object parameter);
- public abstract event EventHandler CanExecuteChanged;
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs b/src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs
deleted file mode 100644
index 656a8b52..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Controls.Notifications;
-using Avalonia.Threading;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Common;
-using System;
-using System.Collections.Concurrent;
-using System.Threading;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- public static class NotificationHelper
- {
- private const int MaxNotifications = 4;
- private const int NotificationDelayInMs = 5000;
-
- private static WindowNotificationManager _notificationManager;
-
- private static readonly BlockingCollection<Notification> _notifications = new();
-
- public static void SetNotificationManager(Window host)
- {
- _notificationManager = new WindowNotificationManager(host)
- {
- Position = NotificationPosition.BottomRight,
- MaxItems = MaxNotifications,
- Margin = new Thickness(0, 0, 15, 40),
- };
-
- var maybeAsyncWorkQueue = new Lazy<AsyncWorkQueue<Notification>>(
- () => new AsyncWorkQueue<Notification>(notification =>
- {
- Dispatcher.UIThread.Post(() =>
- {
- _notificationManager.Show(notification);
- });
- },
- "UI.NotificationThread",
- _notifications),
- LazyThreadSafetyMode.ExecutionAndPublication);
-
- _notificationManager.TemplateApplied += (sender, args) =>
- {
- // NOTE: Force creation of the AsyncWorkQueue.
- _ = maybeAsyncWorkQueue.Value;
- };
-
- host.Closing += (sender, args) =>
- {
- if (maybeAsyncWorkQueue.IsValueCreated)
- {
- maybeAsyncWorkQueue.Value.Dispose();
- }
- };
- }
-
- public static void Show(string title, string text, NotificationType type, bool waitingExit = false, Action onClick = null, Action onClose = null)
- {
- var delay = waitingExit ? TimeSpan.FromMilliseconds(0) : TimeSpan.FromMilliseconds(NotificationDelayInMs);
-
- _notifications.Add(new Notification(title, text, type, delay, onClick, onClose));
- }
-
- public static void ShowError(string message)
- {
- Show(LocaleManager.Instance[LocaleKeys.DialogErrorTitle], $"{LocaleManager.Instance[LocaleKeys.DialogErrorMessage]}\n\n{message}", NotificationType.Error);
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs b/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs
deleted file mode 100644
index a055f335..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Input;
-using Avalonia.Interactivity;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- public class OffscreenTextBox : TextBox
- {
- public static RoutedEvent<KeyEventArgs> GetKeyDownRoutedEvent()
- {
- return KeyDownEvent;
- }
-
- public static RoutedEvent<KeyEventArgs> GetKeyUpRoutedEvent()
- {
- return KeyUpEvent;
- }
-
- public void SendKeyDownEvent(KeyEventArgs keyEvent)
- {
- OnKeyDown(keyEvent);
- }
-
- public void SendKeyUpEvent(KeyEventArgs keyEvent)
- {
- OnKeyUp(keyEvent);
- }
-
- public void SendText(string text)
- {
- OnTextInput(new TextInputEventArgs
- {
- Text = text,
- Source = this,
- RoutedEvent = TextInputEvent,
- });
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/TimeZoneConverter.cs b/src/Ryujinx.Ava/UI/Helpers/TimeZoneConverter.cs
deleted file mode 100644
index 876d51f7..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/TimeZoneConverter.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using Avalonia.Data.Converters;
-using System;
-using System.Globalization;
-using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- internal class TimeZoneConverter : IValueConverter
- {
- public static TimeZoneConverter Instance = new();
-
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value == null)
- {
- return null;
- }
-
- var timeZone = (TimeZone)value;
- return string.Format("{0} {1} {2}", timeZone.UtcDifference, timeZone.Location, timeZone.Abbreviation);
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs b/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs
deleted file mode 100644
index 9a44b862..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.UI.Common;
-using Ryujinx.UI.Common.Helper;
-using System.Threading.Tasks;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- internal class UserErrorDialog
- {
- private const string SetupGuideUrl = "https://github.com/Ryujinx/Ryujinx/wiki/Ryujinx-Setup-&-Configuration-Guide";
-
- private static string GetErrorCode(UserError error)
- {
- return $"RYU-{(uint)error:X4}";
- }
-
- private static string GetErrorTitle(UserError error)
- {
- return error switch
- {
- UserError.NoKeys => LocaleManager.Instance[LocaleKeys.UserErrorNoKeys],
- UserError.NoFirmware => LocaleManager.Instance[LocaleKeys.UserErrorNoFirmware],
- UserError.FirmwareParsingFailed => LocaleManager.Instance[LocaleKeys.UserErrorFirmwareParsingFailed],
- UserError.ApplicationNotFound => LocaleManager.Instance[LocaleKeys.UserErrorApplicationNotFound],
- UserError.Unknown => LocaleManager.Instance[LocaleKeys.UserErrorUnknown],
- _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefined],
- };
- }
-
- private static string GetErrorDescription(UserError error)
- {
- return error switch
- {
- UserError.NoKeys => LocaleManager.Instance[LocaleKeys.UserErrorNoKeysDescription],
- UserError.NoFirmware => LocaleManager.Instance[LocaleKeys.UserErrorNoFirmwareDescription],
- UserError.FirmwareParsingFailed => LocaleManager.Instance[LocaleKeys.UserErrorFirmwareParsingFailedDescription],
- UserError.ApplicationNotFound => LocaleManager.Instance[LocaleKeys.UserErrorApplicationNotFoundDescription],
- UserError.Unknown => LocaleManager.Instance[LocaleKeys.UserErrorUnknownDescription],
- _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefinedDescription],
- };
- }
-
- private static bool IsCoveredBySetupGuide(UserError error)
- {
- return error switch
- {
- UserError.NoKeys or
- UserError.NoFirmware or
- UserError.FirmwareParsingFailed => true,
- _ => false,
- };
- }
-
- private static string GetSetupGuideUrl(UserError error)
- {
- if (!IsCoveredBySetupGuide(error))
- {
- return null;
- }
-
- return error switch
- {
- UserError.NoKeys => SetupGuideUrl + "#initial-setup---placement-of-prodkeys",
- UserError.NoFirmware => SetupGuideUrl + "#initial-setup-continued---installation-of-firmware",
- _ => SetupGuideUrl,
- };
- }
-
- public static async Task ShowUserErrorDialog(UserError error)
- {
- string errorCode = GetErrorCode(error);
-
- bool isInSetupGuide = IsCoveredBySetupGuide(error);
-
- string setupButtonLabel = isInSetupGuide ? LocaleManager.Instance[LocaleKeys.OpenSetupGuideMessage] : "";
-
- var result = await ContentDialogHelper.CreateInfoDialog(
- LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogUserErrorDialogMessage, errorCode, GetErrorTitle(error)),
- GetErrorDescription(error) + (isInSetupGuide
- ? LocaleManager.Instance[LocaleKeys.DialogUserErrorDialogInfoMessage]
- : ""), setupButtonLabel, LocaleManager.Instance[LocaleKeys.InputDialogOk],
- LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogUserErrorDialogTitle, errorCode));
-
- if (result == UserResult.Ok)
- {
- OpenHelper.OpenUrl(GetSetupGuideUrl(error));
- }
- }
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/UserResult.cs b/src/Ryujinx.Ava/UI/Helpers/UserResult.cs
deleted file mode 100644
index 2fcd35ae..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/UserResult.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Ryujinx.Ava.UI.Helpers
-{
- public enum UserResult
- {
- Ok,
- Yes,
- No,
- Abort,
- Cancel,
- None,
- }
-}
diff --git a/src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs b/src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs
deleted file mode 100644
index 4834df80..00000000
--- a/src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs
+++ /dev/null
@@ -1,125 +0,0 @@
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-
-namespace Ryujinx.Ava.UI.Helpers
-{
- [SupportedOSPlatform("windows")]
- internal partial class Win32NativeInterop
- {
- [Flags]
- public enum ClassStyles : uint
- {
- CsClassdc = 0x40,
- CsOwndc = 0x20,
- }
-
- [Flags]
- public enum WindowStyles : uint
- {
- WsChild = 0x40000000,
- }
-
- public enum Cursors : uint
- {
- IdcArrow = 32512,
- }
-
- [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
- public enum WindowsMessages : uint
- {
- Mousemove = 0x0200,
- Lbuttondown = 0x0201,
- Lbuttonup = 0x0202,
- Lbuttondblclk = 0x0203,
- Rbuttondown = 0x0204,
- Rbuttonup = 0x0205,
- Rbuttondblclk = 0x0206,
- Mbuttondown = 0x0207,
- Mbuttonup = 0x0208,
- Mbuttondblclk = 0x0209,
- Mousewheel = 0x020A,
- Xbuttondown = 0x020B,
- Xbuttonup = 0x020C,
- Xbuttondblclk = 0x020D,
- Mousehwheel = 0x020E,
- Mouselast = 0x020E,
- }
-
- [UnmanagedFunctionPointer(CallingConvention.Winapi)]
- internal delegate IntPtr WindowProc(IntPtr hWnd, WindowsMessages msg, IntPtr wParam, IntPtr lParam);
-
- [StructLayout(LayoutKind.Sequential)]
- public struct WndClassEx
- {
- public int cbSize;
- public ClassStyles style;
- public IntPtr lpfnWndProc; // not WndProc
- public int cbClsExtra;
- public int cbWndExtra;
- public IntPtr hInstance;
- public IntPtr hIcon;
- public IntPtr hCursor;
- public IntPtr hbrBackground;
- public IntPtr lpszMenuName;
- public IntPtr lpszClassName;
- public IntPtr hIconSm;
-
- public WndClassEx()
- {
- cbSize = Marshal.SizeOf<WndClassEx>();
- }
- }
-
- public static IntPtr CreateEmptyCursor()
- {
- return CreateCursor(IntPtr.Zero, 0, 0, 1, 1, new byte[] { 0xFF }, new byte[] { 0x00 });
- }
-
- public static IntPtr CreateArrowCursor()
- {
- return LoadCursor(IntPtr.Zero, (IntPtr)Cursors.IdcArrow);
- }
-
- [LibraryImport("user32.dll")]
- public static partial IntPtr SetCursor(IntPtr handle);
-
- [LibraryImport("user32.dll")]
- public static partial IntPtr CreateCursor(IntPtr hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight, [In] byte[] pvAndPlane, [In] byte[] pvXorPlane);
-
- [LibraryImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClassExW")]
- public static partial ushort RegisterClassEx(ref WndClassEx param);
-
- [LibraryImport("user32.dll", SetLastError = true, EntryPoint = "UnregisterClassW")]
- public static partial short UnregisterClass([MarshalAs(UnmanagedType.LPWStr)] string lpClassName, IntPtr instance);
-
- [LibraryImport("user32.dll", EntryPoint = "DefWindowProcW")]
- public static partial IntPtr DefWindowProc(IntPtr hWnd, WindowsMessages msg, IntPtr wParam, IntPtr lParam);
-
- [LibraryImport("kernel32.dll", EntryPoint = "GetModuleHandleA")]
- public static partial IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPStr)] string lpModuleName);
-
- [LibraryImport("user32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static partial bool DestroyWindow(IntPtr hwnd);
-
- [LibraryImport("user32.dll", SetLastError = true, EntryPoint = "LoadCursorA")]
- public static partial IntPtr LoadCursor(IntPtr hInstance, IntPtr lpCursorName);
-
- [LibraryImport("user32.dll", SetLastError = true, EntryPoint = "CreateWindowExW")]
- public static partial IntPtr CreateWindowEx(
- uint dwExStyle,
- [MarshalAs(UnmanagedType.LPWStr)] string lpClassName,
- [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName,
- WindowStyles dwStyle,
- int x,
- int y,
- int nWidth,
- int nHeight,
- IntPtr hWndParent,
- IntPtr hMenu,
- IntPtr hInstance,
- IntPtr lpParam);
- }
-}