diff options
author | Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com> | 2023-08-12 01:47:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-12 02:47:22 +0200 |
commit | 7b2225c6b0939b9720c56a89cb0c91311b2e19e5 (patch) | |
tree | b4f44692dc843b720ae73c94688d51f7dc9a0ae4 /src | |
parent | fe15c77d30b94a8b720b520dcacf39a0c832d58f (diff) |
Ava UI: Avalonia 11 & FluentAvalonia 2 Support (#4362)1.1.980
* It builds
(Doesn’t run waiting on FluentAvalonia Preview 5 Release)
* Enable CompiledBindings by default
* Ignore `PointerPressedEventArgs` Init warning
* Define MIME and UTI Types
* Update `UserProfileImageSelectorView` to StorageProvider API
* PFS0 Magic
* Update `MainWindowViewModel` to StorageProvider API
* Update `SettingsUIView` to StorageProvider API
* Update `ApplicationHelper` to StorageProvider API
* Use `IsCheckChanged`
* Rename events
* Update Fluent Avalonia to Preivew 5
* More package updates
* Fix long selection bar
* return glyph value directly, instead of using a binding
* fix menu item checkboxes
* Fix build
* Update to Preview 6
Unicorn conflict
Fix remaining package oopsie
* Fix issues from merge
* Fix some warnings
* Warnings
* Squashed commit of the following:
commit 79d1c190dba48e405a833f654691e47509a29792
Author: Mary <mary@mary.zone>
Date: Sun Apr 16 11:38:07 2023 +0200
chore: Update Silk.NET to 2.17.1 (#4686)
commit 2bc88467eb377a0ca1a8b51700300422422c8c37
Author: Ac_K <Acoustik666@gmail.com>
Date: Sun Apr 16 09:37:31 2023 +0000
Update README.md
commit baf8752e74488a419074ae1d484e54a00bc01973
Author: Vincenzo Nizza <vincenzonizzaufficio@gmail.com>
Date: Sun Apr 16 11:19:33 2023 +0200
Ensure the updater doesn't delete hidden or system files (#4626)
* Copy desktop.ini to update directory if it exists in HomeDir
* EnumerateFilesToDelete() exclude files with "Hidden" and "System" attributes
commit d5e4378aea086d9219f890e33cf81d566d96b9ae
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sun Apr 16 09:02:06 2023 +0000
nuget: bump DynamicData from 7.13.1 to 7.13.5 (#4654)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 7.13.1 to 7.13.5.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/7.13.1...7.13.5)
---
updated-dependencies:
- dependency-name: DynamicData
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
commit 6dbcdfea47e60aadefd59a75e43549793481f853
Author: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Date: Sun Apr 16 09:09:02 2023 +0200
Ava: Fix nca extraction window never closing & minor cleanup (#4569)
* ava: Remove unused doWhileDeferred parameters
* ava: Minimally improve swkbd dialog
It's currently impossible to get the dialog to redirect focus to the InputBox.
* ava: Fix nca extraction dialog never closing
Also contains some minor cleanup
commit c5258cf082b10f335f81487f22b7eeb86075e09e
Author: NitroTears <73270647+NitroTears@users.noreply.github.com>
Date: Sun Apr 16 11:03:35 2023 +1000
Ability to hide file types in Game List (#4555)
* Added HiddenFileTypes to config state, and check to file enumeration
* Added hiddenfiletypes checkboxes to the UI
* Added Ava version of HiddenFileTypes
* Inverted Hide to Show with file types, minor formatting
* all variables with a reference to 'hidden' is now 'shown'
* one more variable name changed
* review feedback
* added FileTypes extension methof to get the correlating config value
* moved extension method to new folder and file in Ryujinx.Ui.Common
* added default case for ToggleFileType
* changed exception type to OutOfRangeException
commit 5c89e22bb98072adc240c2eb2d26d25fa119fe7d
Author: Daniel Shala <daniel.shala08@gmail.com>
Date: Sat Apr 15 18:11:24 2023 +0200
Added check for eventual symlink when displaying game files. (#4526)
* Added check for eventual symlink when displaying game files.
* Moved symlink check logic
* Moved symlink check logic
* Fixed prev commit
---------
Co-authored-by: Daniel Shala <danielshala00@gmail.com>
commit 11ecff2ff04633d261b9a43db792f6438df63f40
Author: Alex Barney <thealexbarney@gmail.com>
Date: Fri Apr 14 16:00:34 2023 -0700
Rename Hipc to Cmif where appropriate (#3880)
commit 4c3f09644a033dbf70258c4c0e5a848263b16bbd
Author: MutantAura <44103205+MutantAura@users.noreply.github.com>
Date: Wed Apr 12 20:18:40 2023 +0100
Move swkbd message null check into constructor (#4671)
commit e187a8870a6f19ac0a85b08aece3c1a1e196e379
Author: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Date: Wed Apr 12 03:09:47 2023 +0200
HLE: Deal with empty title names properly (#4643)
* hle: Deal with empty titleNames in some languages
* gui: Fix displaying the wrong title name
* Remove unnecessary bounds check
* Fix a NRE when getting the version string
* Restore empty string logic
commit a64fee29dc6b8e523d61abb7e79ceaa95a558c6c
Author: riperiperi <rhy3756547@hotmail.com>
Date: Tue Apr 11 08:23:41 2023 +0100
Vulkan: add situational "Fast Flush" mode (#4667)
* Flush in the middle of long command buffers.
* Vulkan: add situational "Fast Flush" mode
The AutoFlushCounter class was added to periodically flush Vulkan command buffers throughout a frame, which reduces latency to the GPU as commands are submitted and processed much sooner. This was done by allowing command buffers to flush when framebuffer attachments changed.
However, some games have incredibly long render passes with a large number of draws, and really aggressive data access that forces GPU sync.
The Vulkan backend could potentially end up building a single command buffer for 4-5ms if a pass has enough draws, such as in BOTW. In the scenario where sync is waited on immediately after submission, this would have to wait for the completion of a much longer command buffer than usual.
The solution is to force command buffer submission periodically in a "fast flush" mode. This will end up splitting render passes, but it will only enable if sync is aggressive enough.
This should improve performance in GPU limited scenarios, or in games that aggressively wait on synchronization. In some games, it may only kick in when res scaling. It won't trigger in games like SMO where sync is not an issue.
Improves performance in Pokemon Scarlet/Violet (res scaled) and BOTW (in general).
* Add conversions in milliseconds next to flush timers.
commit 9ef94c8292beda825fa76e05ad2e561c6d571c95
Author: riperiperi <rhy3756547@hotmail.com>
Date: Tue Apr 11 07:55:04 2023 +0100
ARMeilleure: Move TPIDR_EL0 and TPIDRRO_EL0 to NativeContext (#4661)
* ARMeilleure: Move TPIDR_EL0 and TPIDRRO_EL0 to NativeContext
Some games access these system registers several tens of thousands of times in a second from many different threads. While this isn't really crippling, it is a lot of wasted time spent in a reverse pinvoke transition.
Example games are Pokemon Scarlet/Violet and BOTW. These games have a lot of different potential bottlenecks so it's unlikely you will see a consistent improvement, but it definitely disappears from the cpu profile.
* Remove unreachable code.
* Add ulong conversion for offsets
* Nit
commit 915d6d044cbf8c89935f14b8c7e085ad729f0e28
Author: riperiperi <rhy3756547@hotmail.com>
Date: Tue Apr 11 07:32:31 2023 +0100
OpenGL: Fix OBS/Overlays again by binding FB before present (#4668)
This seems to have been removed by the Post-Processing PR, but it is required for the display in OBS to be the right way up and properly scaled.
I've tested this with AA and FSR on MK8D and it seems to behave properly. Testing is welcome.
commit a4780ab33b9ca6b698917ded3ef6db6e6716cad1
Author: MutantAura <44103205+MutantAura@users.noreply.github.com>
Date: Mon Apr 10 23:04:31 2023 +0100
Force activate parent window before dialog is shown (#4663)
* Fix build
Extraction dialogue not working
* Avalonia Preview 7
Needs Fluent Avalonia update still…
* Fix Render Scaling
* Update Fluent Avalonia
* Remove `pfs0` as runnable file type
* Restore Info.plist formatting
* Plist Format
* Update Avalonia.Svg.Skia
* Update theme code (TODO)
* swtich to using theme variants for light dark
* Fix crashes
* Text centering issues
* Update `TitleUpdateViewModel` to StorageProvider API
* Fixed for new PR
(Will crash on launch)
* Fixes…
* UI: Fix sections extraction (#4820)
* UI: Fix sections extraction
There is currently an issue when the update NCA doesn't contains the section we want to extract, this is fixed by adding a check.
I have fixed the inverted handler of ExeFs/Logo introduced in #4755.
Fixes #4521
* Addresses feedback
* Fix issues…
* Preview 8
* Fix fuck ups
* Fixes
* More cleanup
* Ava 11 RC
Maybe there is a god
* Update FluentAvalonia
* update svg
* Second RC (kill me)
* It builds
* Ava 11
* Remove unnecessary usings
* Fix build
* Formatting
* GAS GAS GAS!!!!
* Fix DLC Window Crash
* Linux runner try not to crash challenge (impossible)
* Add app.manifest
* Fix accidental Silk.NET.Vulkan bump
* Try fix truncation
* Linux fix popup Windows
* Fix cutoff text on windows
* Status bar styling fixes
* Volume Toggle Split Button Fixes
* Fix load bar color
* Fix shortcuts
* Best we're gonna get
* Fix spacing
Co-authored-by: Exhigh <exhigh01@gmail.com>
* Formatting
* Fix Profile Dropdown
* Fix Window Startup Position
* Format Fixes
* Fix stupid mistake
* Fix accidental change
* Scaling Handler (peri pls make sure is working)
* Remove Locale Reflection Binding Use + Unsued Usings
* Fix formatting
Code styling
Ughhhh
Fix interface
Make TimeZoneConverter internal
* Remove bell workaround (no longer needed)
* Disable accent menu
* Update to Ava 11.0.2
* Peri suggestions
* Formatting
* Cleanup a bunch of jank
* Dependency update
* Berry fixes and suggestions
* Final suggestions
* Rename assemblyIdentity to Ryujinx.Emulator.Avalonia
---------
Co-authored-by: Emmanuel Hansen <emmausssss@gmail.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
Co-authored-by: Exhigh <exhigh01@gmail.com>
Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
Diffstat (limited to 'src')
73 files changed, 1103 insertions, 1036 deletions
diff --git a/src/Ryujinx.Ava/App.axaml b/src/Ryujinx.Ava/App.axaml index 72bc0dee..eab318b7 100644 --- a/src/Ryujinx.Ava/App.axaml +++ b/src/Ryujinx.Ava/App.axaml @@ -3,7 +3,15 @@ xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sty="using:FluentAvalonia.Styling"> + <Application.Resources> + <ResourceDictionary> + <ResourceDictionary.MergedDictionaries> + <MergeResourceInclude Source="/Assets/Styles/Themes.xaml"/> + </ResourceDictionary.MergedDictionaries> + </ResourceDictionary> + </Application.Resources> <Application.Styles> <sty:FluentAvaloniaTheme PreferSystemTheme="False" /> + <StyleInclude Source="/Assets/Styles/Styles.xaml"/> </Application.Styles> </Application>
\ No newline at end of file diff --git a/src/Ryujinx.Ava/App.axaml.cs b/src/Ryujinx.Ava/App.axaml.cs index 4ecc424a..031e7e44 100644 --- a/src/Ryujinx.Ava/App.axaml.cs +++ b/src/Ryujinx.Ava/App.axaml.cs @@ -3,7 +3,6 @@ using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; using Avalonia.Styling; using Avalonia.Threading; -using FluentAvalonia.Styling; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; @@ -24,6 +23,11 @@ namespace Ryujinx.Ava Name = $"Ryujinx {Program.Version}"; AvaloniaXamlLoader.Load(this); + + if (OperatingSystem.IsMacOS()) + { + Process.Start("/usr/bin/defaults", "write org.ryujinx.Ryujinx ApplePressAndHoldEnabled -bool false"); + } } public override void OnFrameworkInitializationCompleted() @@ -89,8 +93,6 @@ namespace Ryujinx.Ava string themePath = ConfigurationState.Instance.Ui.CustomThemePath; bool enableCustomTheme = ConfigurationState.Instance.Ui.EnableCustomTheme; - const string BaseStyleUrl = "avares://Ryujinx.Ava/Assets/Styles/Base{0}.xaml"; - if (string.IsNullOrWhiteSpace(baseStyle)) { ConfigurationState.Instance.Ui.BaseStyle.Value = "Dark"; @@ -98,31 +100,12 @@ namespace Ryujinx.Ava baseStyle = ConfigurationState.Instance.Ui.BaseStyle; } - var theme = AvaloniaLocator.Current.GetService<FluentAvaloniaTheme>(); - - theme.RequestedTheme = baseStyle; - - var currentStyles = this.Styles; - - // Remove all styles except the base style. - if (currentStyles.Count > 1) + RequestedThemeVariant = baseStyle switch { - currentStyles.RemoveRange(1, currentStyles.Count - 1); - } - - IStyle newStyles = null; - - // Load requested style, and fallback to Dark theme if loading failed. - try - { - newStyles = (Styles)AvaloniaXamlLoader.Load(new Uri(string.Format(BaseStyleUrl, baseStyle), UriKind.Absolute)); - } - catch (XamlLoadException) - { - newStyles = (Styles)AvaloniaXamlLoader.Load(new Uri(string.Format(BaseStyleUrl, "Dark"), UriKind.Absolute)); - } - - currentStyles.Add(newStyles); + "Light" => ThemeVariant.Light, + "Dark" => ThemeVariant.Dark, + _ => ThemeVariant.Default + }; if (enableCustomTheme) { @@ -133,7 +116,7 @@ namespace Ryujinx.Ava var themeContent = File.ReadAllText(themePath); var customStyle = AvaloniaRuntimeXamlLoader.Parse<IStyle>(themeContent); - currentStyles.Add(customStyle); + Styles.Add(customStyle); } catch (Exception ex) { diff --git a/src/Ryujinx.Ava/AppHost.cs b/src/Ryujinx.Ava/AppHost.cs index 786b4507..a8388e9c 100644 --- a/src/Ryujinx.Ava/AppHost.cs +++ b/src/Ryujinx.Ava/AppHost.cs @@ -3,6 +3,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Input; +using Avalonia.Rendering; using Avalonia.Threading; using LibHac.Tools.FsSystem; using Ryujinx.Audio.Backends.Dummy; @@ -54,6 +55,7 @@ using static Ryujinx.Ava.UI.Helpers.Win32NativeInterop; using AntiAliasing = Ryujinx.Common.Configuration.AntiAliasing; using Image = SixLabors.ImageSharp.Image; using InputManager = Ryujinx.Input.HLE.InputManager; +using IRenderer = Ryujinx.Graphics.GAL.IRenderer; using Key = Ryujinx.Input.Key; using MouseButton = Ryujinx.Input.MouseButton; using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter; @@ -167,9 +169,9 @@ namespace Ryujinx.Ava ConfigurationState.Instance.HideCursor.Event += HideCursorState_Changed; - _topLevel.PointerMoved += TopLevel_PointerEnterOrMoved; - _topLevel.PointerEnter += TopLevel_PointerEnterOrMoved; - _topLevel.PointerLeave += TopLevel_PointerLeave; + _topLevel.PointerMoved += TopLevel_PointerEnteredOrMoved; + _topLevel.PointerEntered += TopLevel_PointerEnteredOrMoved; + _topLevel.PointerExited += TopLevel_PointerExited; if (OperatingSystem.IsWindows()) { @@ -194,26 +196,23 @@ namespace Ryujinx.Ava _gpuDoneEvent = new ManualResetEvent(false); } - private void TopLevel_PointerEnterOrMoved(object sender, PointerEventArgs e) + private void TopLevel_PointerEnteredOrMoved(object sender, PointerEventArgs e) { if (sender is MainWindow window) { _lastCursorMoveTime = Stopwatch.GetTimestamp(); - if (RendererHost.EmbeddedWindow.TransformedBounds != null) - { - var point = e.GetCurrentPoint(window).Position; - var bounds = RendererHost.EmbeddedWindow.TransformedBounds.Value.Clip; + var point = e.GetCurrentPoint(window).Position; + var bounds = RendererHost.EmbeddedWindow.Bounds; - _isCursorInRenderer = point.X >= bounds.X && - point.X <= bounds.Width + bounds.X && - point.Y >= bounds.Y && - point.Y <= bounds.Height + bounds.Y; - } + _isCursorInRenderer = point.X >= bounds.X && + point.X <= bounds.Width + bounds.X && + point.Y >= bounds.Y && + point.Y <= bounds.Height + bounds.Y; } } - private void TopLevel_PointerLeave(object sender, PointerEventArgs e) + private void TopLevel_PointerExited(object sender, PointerEventArgs e) { _isCursorInRenderer = false; } @@ -265,7 +264,7 @@ namespace Ryujinx.Ava { if (_renderer != null) { - double scale = _topLevel.PlatformImpl.RenderScaling; + double scale = _topLevel.RenderScaling; _renderer.Window?.SetSize((int)(size.Width * scale), (int)(size.Height * scale)); } @@ -359,7 +358,7 @@ namespace Ryujinx.Ava _viewModel.SetUiProgressHandlers(Device); - RendererHost.SizeChanged += Window_SizeChanged; + RendererHost.BoundsChanged += Window_BoundsChanged; _isActive = true; @@ -469,9 +468,9 @@ namespace Ryujinx.Ava ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAntiAliasing; ConfigurationState.Instance.Graphics.EnableColorSpacePassthrough.Event -= UpdateColorSpacePassthrough; - _topLevel.PointerMoved -= TopLevel_PointerEnterOrMoved; - _topLevel.PointerEnter -= TopLevel_PointerEnterOrMoved; - _topLevel.PointerLeave -= TopLevel_PointerLeave; + _topLevel.PointerMoved -= TopLevel_PointerEnteredOrMoved; + _topLevel.PointerEntered -= TopLevel_PointerEnteredOrMoved; + _topLevel.PointerExited -= TopLevel_PointerExited; _gpuCancellationTokenSource.Cancel(); _gpuCancellationTokenSource.Dispose(); @@ -849,7 +848,7 @@ namespace Ryujinx.Ava return deviceDriver; } - private void Window_SizeChanged(object sender, Size e) + private void Window_BoundsChanged(object sender, Size e) { Width = (int)e.Width; Height = (int)e.Height; @@ -899,7 +898,7 @@ namespace Ryujinx.Ava Width = (int)RendererHost.Bounds.Width; Height = (int)RendererHost.Bounds.Height; - _renderer.Window.SetSize((int)(Width * _topLevel.PlatformImpl.RenderScaling), (int)(Height * _topLevel.PlatformImpl.RenderScaling)); + _renderer.Window.SetSize((int)(Width * _topLevel.RenderScaling), (int)(Height * _topLevel.RenderScaling)); _chrono.Start(); diff --git a/src/Ryujinx.Ava/Assets/Styles/BaseDark.xaml b/src/Ryujinx.Ava/Assets/Styles/BaseDark.xaml deleted file mode 100644 index c7f6266f..00000000 --- a/src/Ryujinx.Ava/Assets/Styles/BaseDark.xaml +++ /dev/null @@ -1,65 +0,0 @@ -<Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - <StyleInclude Source="avares://Ryujinx.Ava/Assets/Styles/Styles.xaml" /> - <Design.PreviewWith> - <Border Height="2000" Padding="20"> - <StackPanel Spacing="5"> - <TextBlock Text="Code Font Family" /> - <Grid RowDefinitions="*,Auto"> - <Menu Grid.Row="1" Width="100"> - <MenuItem Header="File"> - <MenuItem Header="Test 1" /> - <MenuItem Header="Test 2" /> - <MenuItem Header="Test 3"> - <MenuItem.Icon> - <CheckBox Margin="0" IsChecked="{Binding Checkbox, Mode=TwoWay}" /> - </MenuItem.Icon> - </MenuItem> - </MenuItem> - </Menu> - <StackPanel Orientation="Horizontal"> - <Button - Name="btnAdd" - HorizontalAlignment="Right" - Content="Add" /> - <Button - Name="btnRem" - HorizontalAlignment="Right" - Content="Add" /> - <TextBox - Width="100" - VerticalAlignment="Center" - Text="Rrrrr" - UseFloatingWatermark="True" - Watermark="Hello" /> - <CheckBox>Test Check</CheckBox> - </StackPanel> - </Grid> - </StackPanel> - </Border> - </Design.PreviewWith> - <Styles.Resources> - <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" Color="{DynamicResource DataGridSelectionColor}" /> - <SolidColorBrush x:Key="ThemeAccentColorBrush" Color="{DynamicResource SystemAccentColor}" /> - <SolidColorBrush x:Key="ThemeAccentBrush4" Color="{DynamicResource ThemeAccentColor4}" /> - <Color x:Key="ControlFillColorSecondary">#008AA8</Color> - <SolidColorBrush x:Key="ControlFillColorSecondaryBrush" Color="{StaticResource ControlFillColorSecondary}" /> - <StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="ControlFillColorSecondaryBrush" /> - <Color x:Key="SystemAccentColor">#FF00C3E3</Color> - <Color x:Key="SystemAccentColorDark1">#FF99b000</Color> - <Color x:Key="SystemAccentColorDark2">#FF006d7d</Color> - <Color x:Key="SystemAccentColorDark3">#FF00525E</Color> - <Color x:Key="SystemAccentColorLight1">#FF00dbff</Color> - <Color x:Key="SystemAccentColorLight2">#FF19dfff</Color> - <Color x:Key="SystemAccentColorLight3">#FF33e3ff</Color> - <Color x:Key="DataGridSelectionColor">#FF00FABB</Color> - <Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color> - <Color x:Key="ThemeControlBorderColor">#FF505050</Color> - <Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color> - <Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color> - <Color x:Key="ThemeForegroundColor">#FFFFFFFF</Color> - <Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color> - <Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color> - <Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color> - <Color x:Key="SecondaryTextColor">#A0FFFFFF</Color> - </Styles.Resources> -</Styles>
\ No newline at end of file diff --git a/src/Ryujinx.Ava/Assets/Styles/BaseLight.xaml b/src/Ryujinx.Ava/Assets/Styles/BaseLight.xaml deleted file mode 100644 index 70cb051c..00000000 --- a/src/Ryujinx.Ava/Assets/Styles/BaseLight.xaml +++ /dev/null @@ -1,57 +0,0 @@ -<Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - <StyleInclude Source="avares://Ryujinx.Ava/Assets/Styles/Styles.xaml" /> - <Design.PreviewWith> - <Border Height="2000" Padding="20"> - <StackPanel Spacing="5"> - <TextBlock Text="Code Font Family" /> - <Grid RowDefinitions="*,Auto"> - <Menu Grid.Row="1" Width="100"> - <MenuItem Header="File"> - <MenuItem Header="Test 1" /> - <MenuItem Header="Test 2" /> - <MenuItem Header="Test 3"> - <MenuItem.Icon> - <CheckBox Margin="0" IsChecked="{Binding Checkbox, Mode=TwoWay}" /> - </MenuItem.Icon> - </MenuItem> - </MenuItem> - </Menu> - <StackPanel Orientation="Horizontal"> - <Button - Name="btnAdd" - HorizontalAlignment="Right" - Content="Add" /> - <Button - Name="btnRem" - HorizontalAlignment="Right" - Content="Add" /> - <TextBox - Width="100" - VerticalAlignment="Center" - Text="Rrrrr" - UseFloatingWatermark="True" - Watermark="Hello" /> - <CheckBox>Test Check</CheckBox> - </StackPanel> - </Grid> - </StackPanel> - </Border> - </Design.PreviewWith> - <Styles.Resources> - <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" Color="{DynamicResource DataGridSelectionColor}" /> - <SolidColorBrush x:Key="ThemeAccentColorBrush" Color="{DynamicResource SystemAccentColor}" /> - <SolidColorBrush x:Key="ThemeAccentBrush4" Color="{DynamicResource ThemeAccentColor4}" /> - <Color x:Key="SystemAccentColor">#FF00C3E3</Color> - <Color x:Key="ThemeAccentColor4">#FFe8e8e8</Color> - <Color x:Key="DataGridSelectionColor">#FF00FABB</Color> - <Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color> - <Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color> - <Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color> - <Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color> - <Color x:Key="ThemeForegroundColor">#FF000000</Color> - <Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color> - <Color x:Key="AppListBackgroundColor">#b3ffffff</Color> - <Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color> - <Color x:Key="SecondaryTextColor">#A0000000</Color> - </Styles.Resources> -</Styles>
\ No newline at end of file diff --git a/src/Ryujinx.Ava/Assets/Styles/Styles.xaml b/src/Ryujinx.Ava/Assets/Styles/Styles.xaml index 681b4fea..146e60b5 100644 --- a/src/Ryujinx.Ava/Assets/Styles/Styles.xaml +++ b/src/Ryujinx.Ava/Assets/Styles/Styles.xaml @@ -3,17 +3,20 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"> <Design.PreviewWith> - <Border Height="2000" Padding="20"> + <Border Height="2000" + Padding="20"> <StackPanel Spacing="5"> <TextBlock Text="Code Font Family" /> <Grid RowDefinitions="*,Auto"> - <Menu Grid.Row="1" Width="100"> + <Menu Grid.Row="1" + Width="100"> <MenuItem Header="File"> <MenuItem Header="Test 1" /> <MenuItem Header="Test 2" /> <MenuItem Header="Test 3"> <MenuItem.Icon> - <CheckBox Margin="0" IsChecked="{Binding Checkbox, Mode=TwoWay}" /> + <CheckBox Margin="0" + IsChecked="{ReflectionBinding Checkbox, Mode=TwoWay}" /> </MenuItem.Icon> </MenuItem> </MenuItem> @@ -42,57 +45,80 @@ </Border> </Design.PreviewWith> <Style Selector="Border.small"> - <Setter Property="Width" Value="100" /> + <Setter Property="Width" + Value="100" /> </Style> <Style Selector="Border.normal"> - <Setter Property="Width" Value="130" /> + <Setter Property="Width" + Value="130" /> </Style> <Style Selector="Border.large"> - <Setter Property="Width" Value="160" /> + <Setter Property="Width" + Value="160" /> </Style> <Style Selector="Border.huge"> - <Setter Property="Width" Value="200" /> + <Setter Property="Width" + Value="200" /> </Style> <Style Selector="Border.settings"> - <Setter Property="Background" Value="{DynamicResource ThemeDarkColor}" /> - <Setter Property="BorderBrush" Value="{DynamicResource MenuFlyoutPresenterBorderColor}" /> - <Setter Property="BorderThickness" Value="1" /> - <Setter Property="CornerRadius" Value="5" /> + <Setter Property="Background" + Value="{DynamicResource ThemeDarkColor}" /> + <Setter Property="BorderBrush" + Value="{DynamicResource MenuFlyoutPresenterBorderColor}" /> + <Setter Property="BorderThickness" + Value="1" /> + <Setter Property="CornerRadius" + Value="5" /> </Style> <Style Selector="Image.small"> - <Setter Property="Width" Value="50" /> + <Setter Property="Width" + Value="50" /> </Style> <Style Selector="Image.normal"> - <Setter Property="Width" Value="80" /> + <Setter Property="Width" + Value="80" /> </Style> <Style Selector="Image.large"> - <Setter Property="Width" Value="100" /> + <Setter Property="Width" + Value="100" /> </Style> <Style Selector="Image.huge"> - <Setter Property="Width" Value="120" /> + <Setter Property="Width" + Value="120" /> </Style> <Style Selector="#TitleBarHost > Image"> - <Setter Property="Margin" Value="10" /> + <Setter Property="Margin" + Value="10" /> </Style> <Style Selector="#TitleBarHost > Label"> - <Setter Property="Margin" Value="5" /> - <Setter Property="FontSize" Value="14" /> + <Setter Property="Margin" + Value="5" /> + <Setter Property="FontSize" + Value="14" /> </Style> <Style Selector="Button.SystemCaption"> - <Setter Property="MinWidth" Value="10" /> + <Setter Property="MinWidth" + Value="10" /> </Style> <Style Selector="DataGridColumnHeader"> - <Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}" /> - <Setter Property="HorizontalContentAlignment" Value="Center" /> - <Setter Property="BorderThickness" Value="1" /> - <Setter Property="VerticalContentAlignment" Value="Center" /> - <Setter Property="Background" Value="{DynamicResource ThemeControlBorderColor}" /> - <Setter Property="SeparatorBrush" Value="{DynamicResource ThemeControlBorderColor}" /> - <Setter Property="Padding" Value="5" /> - <Setter Property="Background" Value="{DynamicResource ThemeContentBackgroundColor}" /> + <Setter Property="Foreground" + Value="{DynamicResource ThemeForegroundBrush}" /> + <Setter Property="HorizontalContentAlignment" + Value="Center" /> + <Setter Property="BorderThickness" + Value="1" /> + <Setter Property="VerticalContentAlignment" + Value="Center" /> + <Setter Property="SeparatorBrush" + Value="{DynamicResource ThemeControlBorderColor}" /> + <Setter Property="Padding" + Value="5" /> + <Setter Property="Background" + Value="{DynamicResource ThemeContentBackgroundColor}" /> <Setter Property="Template"> <ControlTemplate> - <Grid Background="{TemplateBinding Background}" ColumnDefinitions="*,Auto"> + <Grid Background="{TemplateBinding Background}" + ColumnDefinitions="*,Auto"> <Grid Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" @@ -122,193 +148,262 @@ </Setter> </Style> <Style Selector="DataGrid"> - <Setter Property="RowBackground" Value="{DynamicResource ThemeAccentBrush4}" /> - <Setter Property="AlternatingRowBackground" Value="#00FFFFFF" /> - <Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}" /> - <Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderLowColor}" /> - <Setter Property="BorderThickness" Value="{DynamicResource ThemeBorderThickness}" /> + <Setter Property="RowBackground" + Value="{DynamicResource ThemeAccentBrush4}" /> + <Setter Property="Background" + Value="{DynamicResource ThemeBackgroundBrush}" /> + <Setter Property="BorderBrush" + Value="{DynamicResource ThemeBorderLowColor}" /> + <Setter Property="BorderThickness" + Value="{DynamicResource ThemeBorderThickness}" /> </Style> <Style Selector="DataGridRow:selected:focus /template/ Rectangle#BackgroundRectangle"> - <Setter Property="Fill" Value="{DynamicResource SystemAccentColor}" /> - <Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedBackgroundOpacity}" /> + <Setter Property="Fill" + Value="{DynamicResource SystemAccentColor}" /> + <Setter Property="Opacity" + Value="{DynamicResource DataGridRowSelectedBackgroundOpacity}" /> </Style> <Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle"> - <Setter Property="Fill" Value="{DynamicResource SystemListLowColor}" /> + <Setter Property="Fill" + Value="{DynamicResource SystemListLowColor}" /> </Style> <Style Selector="DataGridRow:selected /template/ Rectangle#BackgroundRectangle"> - <Setter Property="Fill" Value="{DynamicResource SystemAccentColor}" /> - <Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedUnfocusedBackgroundOpacity}" /> + <Setter Property="Fill" + Value="{DynamicResource SystemAccentColor}" /> + <Setter Property="Opacity" + Value="{DynamicResource DataGridRowSelectedUnfocusedBackgroundOpacity}" /> </Style> <Style Selector="DataGridRow:selected:pointerover /template/ Rectangle#BackgroundRectangle"> - <Setter Property="Fill" Value="{DynamicResource SystemAccentColor}" /> - <Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedHoveredUnfocusedBackgroundOpacity}" /> + <Setter Property="Fill" + Value="{DynamicResource SystemAccentColor}" /> + <Setter Property="Opacity" + Value="{DynamicResource DataGridRowSelectedHoveredUnfocusedBackgroundOpacity}" /> </Style> <Style Selector="DataGridRow:selected:pointerover:focus /template/ Rectangle#BackgroundRectangle"> - <Setter Property="Fill" Value="{DynamicResource SystemAccentColor}" /> - <Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedHoveredBackgroundOpacity}" /> + <Setter Property="Fill" + Value="{DynamicResource SystemAccentColor}" /> + <Setter Property="Opacity" + Value="{DynamicResource DataGridRowSelectedHoveredBackgroundOpacity}" /> </Style> <Style Selector="DataGridCell"> - <Setter Property="HorizontalAlignment" Value="Center" /> - <Setter Property="HorizontalContentAlignment" Value="Center" /> + <Setter Property="HorizontalAlignment" + Value="Center" /> + <Setter Property="HorizontalContentAlignment" + Value="Center" /> </Style> <Style Selector="DataGridCell.Left"> - <Setter Property="HorizontalAlignment" Value="Left" /> + <Setter Property="HorizontalAlignment" + Value="Left" /> </Style> <Style Selector="CheckBox"> - <Setter Property="BorderThickness" Value="1" /> + <Setter Property="BorderThickness" + Value="1" /> </Style> <Style Selector="MenuItem"> - <Setter Property="Height" Value="{DynamicResource MenuItemHeight}" /> - <Setter Property="Padding" Value="{DynamicResource MenuItemPadding}" /> - <Setter Property="FontSize" Value="12" /> + <Setter Property="Height" + Value="{DynamicResource MenuItemHeight}" /> + <Setter Property="Padding" + Value="{DynamicResource MenuItemPadding}" /> + <Setter Property="FontSize" + Value="12" /> </Style> <Style Selector="MenuItem:selected /template/ Border#root"> - <Setter Property="Background" Value="{DynamicResource ThemeControlBorderColor}" /> - <Setter Property="BorderBrush" Value="{DynamicResource ThemeControlBorderColor}" /> + <Setter Property="Background" + Value="{DynamicResource ThemeControlBorderColor}" /> + <Setter Property="BorderBrush" + Value="{DynamicResource ThemeControlBorderColor}" /> </Style> <Style Selector="TabItem > ScrollViewer"> - <Setter Property="Background" Value="{DynamicResource ThemeBackgroundColor}" /> - <Setter Property="Margin" Value="0,-5,0,0" /> + <Setter Property="Background" + Value="{DynamicResource ThemeBackgroundColor}" /> + <Setter Property="Margin" + Value="0,-5,0,0" /> </Style> <Style Selector="TabItem > ScrollViewer > Border"> - <Setter Property="BorderThickness" Value="0,1,0,0" /> - <Setter Property="Background" Value="{DynamicResource ThemeBackgroundColor}" /> - <Setter Property="BorderBrush" Value="{DynamicResource HighlightBrush}" /> + <Setter Property="BorderThickness" + Value="0,1,0,0" /> + <Setter Property="Background" + Value="{DynamicResource ThemeBackgroundColor}" /> + <Setter Property="BorderBrush" + Value="{DynamicResource HighlightBrush}" /> </Style> <Style Selector="Button"> - <Setter Property="MinWidth" Value="80" /> + <Setter Property="MinWidth" + Value="80" /> </Style> <Style Selector="ProgressBar /template/ Border#ProgressBarTrack"> - <Setter Property="IsVisible" Value="False" /> + <Setter Property="IsVisible" + Value="False" /> </Style> <Style Selector="ToggleButton"> - <Setter Property="Padding" Value="0,-5,0,0" /> + <Setter Property="Padding" + Value="0,-5,0,0" /> </Style> <Style Selector="TabItem"> - <Setter Property="FontSize" Value="14" /> - <Setter Property="BorderThickness" Value="0,0,1,0" /> - <Setter Property="BorderBrush" Value="{DynamicResource ThemeButtonForegroundColor}" /> - <Setter Property="Background" Value="{DynamicResource HighlightColor}" /> + <Setter Property="FontSize" + Value="14" /> + <Setter Property="BorderThickness" + Value="0,0,1,0" /> + <Setter Property="BorderBrush" + Value="{DynamicResource ThemeButtonForegroundColor}" /> + <Setter Property="Background" + Value="{DynamicResource SystemAccentColorLight2}" /> </Style> <Style Selector="TabItem:pointerover"> - <Setter Property="Foreground" Value="{DynamicResource ThemeButtonForegroundColor}" /> + <Setter Property="Foreground" + Value="{DynamicResource ThemeButtonForegroundColor}" /> </Style> <Style Selector="TabItem:selected"> - <Setter Property="Background" Value="{DynamicResource HighlightColor}" /> - <Setter Property="Foreground" Value="{DynamicResource ThemeBackgroundColor}" /> + <Setter Property="Background" + Value="{DynamicResource SystemAccentColorLight2}" /> + <Setter Property="Foreground" + Value="{DynamicResource ThemeBackgroundColor}" /> </Style> <Style Selector="TextBlock"> - <Setter Property="Margin" Value="{DynamicResource TextMargin}" /> - <Setter Property="FontSize" Value="{DynamicResource FontSize}" /> - <Setter Property="VerticalAlignment" Value="Center" /> - <Setter Property="TextWrapping" Value="WrapWithOverflow" /> + <Setter Property="Margin" + Value="{DynamicResource TextMargin}" /> + <Setter Property="FontSize" + Value="{DynamicResource FontSize}" /> + <Setter Property="VerticalAlignment" + Value="Center" /> + <Setter Property="TextWrapping" + Value="WrapWithOverflow" /> </Style> <Style Selector="TextBlock.h1"> - <Setter Property="Margin" Value="{DynamicResource TextMargin}" /> - <Setter Property="VerticalAlignment" Value="Center" /> - <Setter Property="FontWeight" Value="Bold" /> - <Setter Property="FontSize" Value="16" /> - <Setter Property="TextWrapping" Value="WrapWithOverflow" /> + <Setter Property="Margin" + Value="{DynamicResource TextMargin}" /> + <Setter Property="VerticalAlignment" + Value="Center" /> + <Setter Property="FontWeight" + Value="Bold" /> + <Setter Property="FontSize" + Value="16" /> + <Setter Property="TextWrapping" + Value="WrapWithOverflow" /> </Style> <Style Selector="Separator"> - <Setter Property="Background" Value="{DynamicResource ThemeControlBorderColor}" /> - <Setter Property="Foreground" Value="{DynamicResource ThemeControlBorderColor}" /> - <Setter Property="MinHeight" Value="1" /> + <Setter Property="Background" + Value="{DynamicResource ThemeControlBorderColor}" /> + <Setter Property="Foreground" + Value="{DynamicResource ThemeControlBorderColor}" /> + <Setter Property="MinHeight" + Value="1" /> </Style> <Style Selector=":is(Button).DateTimeFlyoutButtonStyle"> - <Setter Property="Background" Value="{DynamicResource HighlightColor}" /> - <Setter Property="Foreground" Value="{DynamicResource ThemeBackgroundColor}" /> + <Setter Property="Background" + Value="{DynamicResource SystemAccentColorLight2}" /> + <Setter Property="Foreground" + Value="{DynamicResource ThemeBackgroundColor}" /> </Style> <Style Selector="DatePickerPresenter"> - <Setter Property="BorderThickness" Value="1" /> - <Setter Property="BorderBrush" Value="{DynamicResource ThemeButtonForegroundColor}" /> + <Setter Property="BorderThickness" + Value="1" /> + <Setter Property="BorderBrush" + Value="{DynamicResource ThemeButtonForegroundColor}" /> </Style> <Style Selector="DataGridCell"> - <Setter Property="FontSize" Value="14" /> + <Setter Property="FontSize" + Value="14" /> </Style> <Style Selector="CheckBox TextBlock"> - <Setter Property="Margin" Value="0,5,0,0" /> + <Setter Property="Margin" + Value="0,5,0,0" /> </Style> <Style Selector="ContextMenu"> - <Setter Property="BorderBrush" Value="{DynamicResource MenuFlyoutPresenterBorderBrush}" /> - <Setter Property="BorderThickness" Value="{DynamicResource MenuFlyoutPresenterBorderThemeThickness}" /> + <Setter Property="BorderBrush" + Value="{DynamicResource MenuFlyoutPresenterBorderBrush}" /> + <Setter Property="BorderThickness" + Value="{DynamicResource MenuFlyoutPresenterBorderThemeThickness}" /> </Style> <Style Selector="TextBox"> - <Setter Property="VerticalContentAlignment" Value="Center" /> + <Setter Property="VerticalContentAlignment" + Value="Center" /> </Style> <Style Selector="TextBox.NumberBoxTextBoxStyle"> - <Setter Property="Foreground" Value="{DynamicResource ThemeForegroundColor}" /> + <Setter Property="Foreground" + Value="{DynamicResource ThemeForegroundColor}" /> </Style> <Style Selector="ListBox ListBoxItem"> - <Setter Property="Padding" Value="0" /> - <Setter Property="Margin" Value="0" /> - <Setter Property="CornerRadius" Value="5" /> - <Setter Property="Background" Value="{DynamicResource AppListBackgroundColor}" /> - <Setter Property="BorderThickness" Value="2"/> + <Setter Property="Padding" + Value="0" /> + <Setter Property="Margin" + Value="0" /> + <Setter Property="CornerRadius" + Value="5" /> + <Setter Property="Background" + Value="{DynamicResource AppListBackgroundColor}" /> + <Setter Property="BorderThickness" + Value="2"/> <Style.Animations> <Animation Duration="0:0:0.7"> <KeyFrame Cue="0%"> - <Setter Property="MaxHeight" Value="0" /> - <Setter Property="Opacity" Value="0.0" /> + <Setter Property="MaxHeight" + Value="0" /> + <Setter Property="Opacity" + Value="0.0" /> </KeyFrame> <KeyFrame Cue="50%"> - <Setter Property="MaxHeight" Value="1000" /> - <Setter Property="Opacity" Value="0.3" /> + <Setter Property="MaxHeight" + Value="1000" /> + <Setter Property="Opacity" + Value="0.3" /> </KeyFrame> <KeyFrame Cue="100%"> - <Setter Property="MaxHeight" Value="1000" /> - <Setter Property="Opacity" Value="1.0" /> + <Setter Property="MaxHeight" + Value="1000" /> + <Setter Property="Opacity" + Value="1.0" /> </KeyFrame> </Animation> </Style.Animations> </Style> <Style Selector="ListBox ListBoxItem:selected /template/ ContentPresenter"> - <Setter Property="Background" Value="{DynamicResource AppListBackgroundColor}" /> + <Setter Property="Background" + Value="{DynamicResource AppListBackgroundColor}" /> + </Style> + <Style Selector="ListBox"> + <Setter Property="Background" + Value="{DynamicResource ThemeContentBackgroundColor}" /> + </Style> + <Style Selector="FlyoutPresenter, ContextMenu, MenuFlyoutPresenter"> + <Setter Property="BorderBrush" + Value="{DynamicResource MenuFlyoutPresenterBorderColor}" /> </Style> <Style Selector="ListBox ListBoxItem:pointerover /template/ ContentPresenter"> - <Setter Property="Background" Value="{DynamicResource AppListHoverBackgroundColor}" /> + <Setter Property="Background" + Value="{DynamicResource AppListHoverBackgroundColor}" /> </Style> <Styles.Resources> - <SolidColorBrush x:Key="ThemeAccentColorBrush" Color="{DynamicResource SystemAccentColor}" /> - <StaticResource x:Key="ListViewItemBackgroundSelected" ResourceKey="ThemeAccentColorBrush" /> - <StaticResource x:Key="ListViewItemBackgroundPressed" ResourceKey="SystemAccentColorDark1" /> - <StaticResource x:Key="ListViewItemBackgroundPointerOver" ResourceKey="SystemAccentColorDark2" /> - <StaticResource x:Key="ListViewItemBackgroundSelectedPressed" ResourceKey="ThemeAccentColorBrush" /> - <StaticResource x:Key="ListViewItemBackgroundSelectedPointerOver" ResourceKey="SystemAccentColorDark2" /> + <SolidColorBrush x:Key="ThemeAccentColorBrush" + Color="{DynamicResource SystemAccentColor}" /> + <StaticResource x:Key="ListViewItemBackgroundSelected" + ResourceKey="ThemeAccentColorBrush" /> + <StaticResource x:Key="ListViewItemBackgroundPressed" + ResourceKey="SystemAccentColorDark1" /> + <StaticResource x:Key="ListViewItemBackgroundPointerOver" + ResourceKey="SystemAccentColorDark2" /> + <StaticResource x:Key="ListViewItemBackgroundSelectedPressed" + ResourceKey="ThemeAccentColorBrush" /> + <StaticResource x:Key="ListViewItemBackgroundSelectedPointerOver" + ResourceKey="SystemAccentColorDark2" /> <SolidColorBrush x:Key="DataGridGridLinesBrush" Opacity="0.4" Color="{DynamicResource SystemBaseMediumLowColor}" /> - <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" Color="{DynamicResource DataGridSelectionColor}" /> - <SolidColorBrush x:Key="MenuFlyoutPresenterBorderBrush" Color="{DynamicResource MenuFlyoutPresenterBorderColor}" /> - <SolidColorBrush x:Key="FlyoutBorderThemeBrush" Color="{DynamicResource MenuFlyoutPresenterBorderColor}" /> - <SolidColorBrush x:Key="ListBoxBackground" Color="{DynamicResource ThemeContentBackgroundColor}" /> - <SolidColorBrush x:Key="ThemeForegroundBrush" Color="{DynamicResource ThemeForegroundColor}" /> - <SolidColorBrush x:Key="ThemeAccentBrush4" Color="{DynamicResource ThemeAccentColor4}" /> - <SolidColorBrush x:Key="SplitButtonBackgroundChecked" Color="#00E81123" /> - <SolidColorBrush x:Key="SplitButtonBackgroundCheckedPointerOver" Color="#00E81123" /> - <SolidColorBrush x:Key="SplitButtonBackgroundCheckedPressed" Color="#00E81123" /> - <SolidColorBrush x:Key="SplitButtonBackgroundCheckedDisabled" Color="#00E81123" /> + <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" + Color="{DynamicResource DataGridSelectionColor}" /> + <SolidColorBrush x:Key="SplitButtonBackgroundChecked" + Color="#00E81123" /> + <SolidColorBrush x:Key="SplitButtonBackgroundCheckedPointerOver" + Color="#00E81123" /> + <SolidColorBrush x:Key="SplitButtonBackgroundCheckedPressed" + Color="#00E81123" /> + <SolidColorBrush x:Key="SplitButtonBackgroundCheckedDisabled" + Color="#00E81123" /> <Thickness x:Key="PageMargin">40 0 40 0</Thickness> <Thickness x:Key="Margin">0 5 0 5</Thickness> <Thickness x:Key="MenuItemPadding">5 0 5 0</Thickness> - <Color x:Key="MenuFlyoutPresenterBorderColor">#00000000</Color> - <Color x:Key="SystemAccentColor">#FF00C3E3</Color> - <Color x:Key="SystemAccentColorDark1">#FF00C3E3</Color> - <Color x:Key="SystemAccentColorDark2">#FF00C3E3</Color> - <Color x:Key="SystemAccentColorDark3">#FF00C3E3</Color> - <Color x:Key="SystemAccentColorLight1">#FF00C3E3</Color> - <Color x:Key="SystemAccentColorLight2">#FF00C3E3</Color> - <Color x:Key="SystemAccentColorLight3">#FF00C3E3</Color> - <Color x:Key="DataGridSelectionColor">#FF00FABB</Color> - <Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color> - <Color x:Key="ThemeControlBorderColor">#FF505050</Color> - <Color x:Key="VsyncEnabled">#FF2EEAC9</Color> - <Color x:Key="VsyncDisabled">#FFFF4554</Color> - <Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color> - <Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color> - <Color x:Key="SecondaryTextColor">#A0FFFFFF</Color> <x:Double x:Key="ScrollBarThickness">15</x:Double> <x:Double x:Key="FontSizeSmall">8</x:Double> <x:Double x:Key="FontSizeNormal">10</x:Double> diff --git a/src/Ryujinx.Ava/Assets/Styles/Themes.xaml b/src/Ryujinx.Ava/Assets/Styles/Themes.xaml new file mode 100644 index 00000000..0f323f84 --- /dev/null +++ b/src/Ryujinx.Ava/Assets/Styles/Themes.xaml @@ -0,0 +1,85 @@ +<ResourceDictionary xmlns="https://github.com/avaloniaui" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + <ResourceDictionary.ThemeDictionaries> + <ResourceDictionary x:Key="Default"> + <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" + Color="{DynamicResource DataGridSelectionColor}" /> + <SolidColorBrush x:Key="ThemeAccentColorBrush" + Color="{DynamicResource SystemAccentColor}" /> + <SolidColorBrush x:Key="ThemeAccentBrush4" + Color="{DynamicResource ThemeAccentColor4}" /> + <Color x:Key="SystemAccentColor">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorDark1">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorDark2">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorDark3">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorLight1">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorLight2">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorLight3">#FF00C3E3</Color> + <Color x:Key="ThemeAccentColor4">#FFe8e8e8</Color> + <Color x:Key="DataGridSelectionColor">#FF00FABB</Color> + <Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color> + <Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color> + <Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color> + <Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color> + <Color x:Key="ThemeForegroundColor">#FF000000</Color> + <Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color> + <Color x:Key="AppListBackgroundColor">#b3ffffff</Color> + <Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color> + <Color x:Key="SecondaryTextColor">#A0000000</Color> + <Color x:Key="VsyncEnabled">#FF2EEAC9</Color> + <Color x:Key="VsyncDisabled">#FFFF4554</Color> + </ResourceDictionary> + <ResourceDictionary x:Key="Light"> + <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" + Color="{DynamicResource DataGridSelectionColor}" /> + <SolidColorBrush x:Key="ThemeAccentColorBrush" + Color="{DynamicResource SystemAccentColor}" /> + <SolidColorBrush x:Key="ThemeAccentBrush4" + Color="{DynamicResource ThemeAccentColor4}" /> + <Color x:Key="SystemAccentColor">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorDark1">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorDark2">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorDark3">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorLight1">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorLight2">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorLight3">#FF00C3E3</Color> + <Color x:Key="ThemeAccentColor4">#FFe8e8e8</Color> + <Color x:Key="DataGridSelectionColor">#FF00FABB</Color> + <Color x:Key="ThemeContentBackgroundColor">#FFF0F0F0</Color> + <Color x:Key="ThemeControlBorderColor">#FFd6d6d6</Color> + <Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color> + <Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color> + <Color x:Key="ThemeForegroundColor">#FF000000</Color> + <Color x:Key="MenuFlyoutPresenterBorderColor">#C1C1C1</Color> + <Color x:Key="AppListBackgroundColor">#b3ffffff</Color> + <Color x:Key="AppListHoverBackgroundColor">#80cccccc</Color> + <Color x:Key="SecondaryTextColor">#A0000000</Color> + </ResourceDictionary> + <ResourceDictionary x:Key="Dark"> + <SolidColorBrush x:Key="DataGridSelectionBackgroundBrush" + Color="{DynamicResource DataGridSelectionColor}" /> + <SolidColorBrush x:Key="ThemeAccentColorBrush" + Color="{DynamicResource SystemAccentColor}" /> + <SolidColorBrush x:Key="ThemeAccentBrush4" + Color="{DynamicResource ThemeAccentColor4}" /> + <Color x:Key="ControlFillColorSecondary">#008AA8</Color> + <Color x:Key="SystemAccentColor">#FF00C3E3</Color> + <Color x:Key="SystemAccentColorDark1">#FF99b000</Color> + <Color x:Key="SystemAccentColorDark2">#FF006d7d</Color> + <Color x:Key="SystemAccentColorDark3">#FF00525E</Color> + <Color x:Key="SystemAccentColorLight1">#FF00dbff</Color> + <Color x:Key="SystemAccentColorLight2">#FF19dfff</Color> + <Color x:Key="SystemAccentColorLight3">#FF33e3ff</Color> + <Color x:Key="DataGridSelectionColor">#FF00FABB</Color> + <Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color> + <Color x:Key="ThemeControlBorderColor">#FF505050</Color> + <Color x:Key="TextOnAccentFillColorPrimary">#FFFFFFFF</Color> + <Color x:Key="SystemChromeWhiteColor">#FFFFFFFF</Color> + <Color x:Key="ThemeForegroundColor">#FFFFFFFF</Color> + <Color x:Key="MenuFlyoutPresenterBorderColor">#3D3D3D</Color> + <Color x:Key="AppListBackgroundColor">#0FFFFFFF</Color> + <Color x:Key="AppListHoverBackgroundColor">#1EFFFFFF</Color> + <Color x:Key="SecondaryTextColor">#A0FFFFFF</Color> + </ResourceDictionary> + </ResourceDictionary.ThemeDictionaries> +</ResourceDictionary> diff --git a/src/Ryujinx.Ava/Common/ApplicationHelper.cs b/src/Ryujinx.Ava/Common/ApplicationHelper.cs index d28d5aac..9e475753 100644 --- a/src/Ryujinx.Ava/Common/ApplicationHelper.cs +++ b/src/Ryujinx.Ava/Common/ApplicationHelper.cs @@ -1,5 +1,5 @@ -using Avalonia.Controls; using Avalonia.Controls.Notifications; +using Avalonia.Platform.Storage; using Avalonia.Threading; using LibHac; using LibHac.Account; @@ -143,14 +143,20 @@ namespace Ryujinx.Ava.Common } } - public static async Task ExtractSection(NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) + public static async Task ExtractSection(IStorageProvider storageProvider, NcaSectionType ncaSectionType, string titleFilePath, string titleName, int programIndex = 0) { - OpenFolderDialog folderDialog = new() + var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], - }; + AllowMultiple = false + }); - string destination = await folderDialog.ShowAsync(_owner); + if (result.Count == 0) + { + return; + } + + var destination = result[0].Path.LocalPath; var cancellationToken = new CancellationTokenSource(); UpdateWaitWindow waitingDialog = new( @@ -158,148 +164,145 @@ namespace Ryujinx.Ava.Common LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogNcaExtractionMessage, ncaSectionType, Path.GetFileName(titleFilePath)), cancellationToken); - if (!string.IsNullOrWhiteSpace(destination)) + Thread extractorThread = new(() => { - Thread extractorThread = new(() => - { - Dispatcher.UIThread.Post(waitingDialog.Show); + Dispatcher.UIThread.Post(waitingDialog.Show); - using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read); + using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read); - Nca mainNca = null; - Nca patchNca = null; + Nca mainNca = null; + Nca patchNca = null; - string extension = Path.GetExtension(titleFilePath).ToLower(); - if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci") - { - PartitionFileSystem pfs; + string extension = Path.GetExtension(titleFilePath).ToLower(); + if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci") + { + PartitionFileSystem pfs; - if (extension == ".xci") - { - pfs = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure); - } - else - { - pfs = new PartitionFileSystem(file.AsStorage()); - } + if (extension == ".xci") + { + pfs = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure); + } + else + { + pfs = new PartitionFileSystem(file.AsStorage()); + } - foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) - { - using var ncaFile = new UniqueRef<IFile>(); + foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) + { + using var ncaFile = new UniqueRef<IFile>(); - pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); + pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); - Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage()); - if (nca.Header.ContentType == NcaContentType.Program) + Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage()); + if (nca.Header.ContentType == NcaContentType.Program) + { + int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); + if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()) + { + patchNca = nca; + } + else { - int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); - if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()) - { - patchNca = nca; - } - else - { - mainNca = nca; - } + mainNca = nca; } } } - else if (extension == ".nca") - { - mainNca = new Nca(_virtualFileSystem.KeySet, file.AsStorage()); - } + } + else if (extension == ".nca") + { + mainNca = new Nca(_virtualFileSystem.KeySet, file.AsStorage()); + } - if (mainNca == null) - { - Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA was not present in the selected file"); + if (mainNca == null) + { + Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA was not present in the selected file"); - Dispatcher.UIThread.InvokeAsync(async () => - { - waitingDialog.Close(); + Dispatcher.UIThread.InvokeAsync(async () => + { + waitingDialog.Close(); - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionMainNcaNotFoundErrorMessage]); - }); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionMainNcaNotFoundErrorMessage]); + }); - return; - } + return; + } - (Nca updatePatchNca, _) = ApplicationLibrary.GetGameUpdateData(_virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), programIndex, out _); - if (updatePatchNca != null) - { - patchNca = updatePatchNca; - } + (Nca updatePatchNca, _) = ApplicationLibrary.GetGameUpdateData(_virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), programIndex, out _); + if (updatePatchNca != null) + { + patchNca = updatePatchNca; + } - int index = Nca.GetSectionIndexFromType(ncaSectionType, mainNca.Header.ContentType); + int index = Nca.GetSectionIndexFromType(ncaSectionType, mainNca.Header.ContentType); - try + try + { + bool sectionExistsInPatch = false; + if (patchNca != null) { - bool sectionExistsInPatch = false; - if (patchNca != null) - { - sectionExistsInPatch = patchNca.CanOpenSection(index); - } + sectionExistsInPatch = patchNca.CanOpenSection(index); + } - IFileSystem ncaFileSystem = sectionExistsInPatch ? mainNca.OpenFileSystemWithPatch(patchNca, index, IntegrityCheckLevel.ErrorOnInvalid) - : mainNca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid); + IFileSystem ncaFileSystem = sectionExistsInPatch ? mainNca.OpenFileSystemWithPatch(patchNca, index, IntegrityCheckLevel.ErrorOnInvalid) + : mainNca.OpenFileSystem(index, IntegrityCheckLevel.ErrorOnInvalid); - FileSystemClient fsClient = _horizonClient.Fs; + FileSystemClient fsClient = _horizonClient.Fs; - string source = DateTime.Now.ToFileTime().ToString()[10..]; - string output = DateTime.Now.ToFileTime().ToString()[10..]; + string source = DateTime.Now.ToFileTime().ToString()[10..]; + string output = DateTime.Now.ToFileTime().ToString()[10..]; - using var uniqueSourceFs = new UniqueRef<IFileSystem>(ncaFileSystem); - using var uniqueOutputFs = new UniqueRef<IFileSystem>(new LocalFileSystem(destination)); + using var uniqueSourceFs = new UniqueRef<IFileSystem>(ncaFileSystem); + using var uniqueOutputFs = new UniqueRef<IFileSystem>(new LocalFileSystem(destination)); - fsClient.Register(source.ToU8Span(), ref uniqueSourceFs.Ref); - fsClient.Register(output.ToU8Span(), ref uniqueOutputFs.Ref); + fsClient.Register(source.ToU8Span(), ref uniqueSourceFs.Ref); + fsClient.Register(output.ToU8Span(), ref uniqueOutputFs.Ref); - (Result? resultCode, bool canceled) = CopyDirectory(fsClient, $"{source}:/", $"{output}:/", cancellationToken.Token); + (Result? resultCode, bool canceled) = CopyDirectory(fsClient, $"{source}:/", $"{output}:/", cancellationToken.Token); - if (!canceled) + if (!canceled) + { + if (resultCode.Value.IsFailure()) { - if (resultCode.Value.IsFailure()) - { - Logger.Error?.Print(LogClass.Application, $"LibHac returned error code: {resultCode.Value.ErrorCode}"); - - Dispatcher.UIThread.InvokeAsync(async () => - { - waitingDialog.Close(); + Logger.Error?.Print(LogClass.Application, $"LibHac returned error code: {resultCode.Value.ErrorCode}"); - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionCheckLogErrorMessage]); - }); - } - else if (resultCode.Value.IsSuccess()) + Dispatcher.UIThread.InvokeAsync(async () => { - Dispatcher.UIThread.Post(waitingDialog.Close); + waitingDialog.Close(); - NotificationHelper.Show( - LocaleManager.Instance[LocaleKeys.DialogNcaExtractionTitle], - $"{titleName}\n\n{LocaleManager.Instance[LocaleKeys.DialogNcaExtractionSuccessMessage]}", - NotificationType.Information); - } + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionCheckLogErrorMessage]); + }); } - - fsClient.Unmount(source.ToU8Span()); - fsClient.Unmount(output.ToU8Span()); - } - catch (ArgumentException ex) - { - Logger.Error?.Print(LogClass.Application, $"{ex.Message}"); - - Dispatcher.UIThread.InvokeAsync(async () => + else if (resultCode.Value.IsSuccess()) { - waitingDialog.Close(); + Dispatcher.UIThread.Post(waitingDialog.Close); - await ContentDialogHelper.CreateErrorDialog(ex.Message); - }); + NotificationHelper.Show( + LocaleManager.Instance[LocaleKeys.DialogNcaExtractionTitle], + $"{titleName}\n\n{LocaleManager.Instance[LocaleKeys.DialogNcaExtractionSuccessMessage]}", + NotificationType.Information); + } } - }) + + fsClient.Unmount(source.ToU8Span()); + fsClient.Unmount(output.ToU8Span()); + } + catch (ArgumentException ex) { - Name = "GUI.NcaSectionExtractorThread", - IsBackground = true, - }; - extractorThread.Start(); - } + Logger.Error?.Print(LogClass.Application, $"{ex.Message}"); + + Dispatcher.UIThread.InvokeAsync(async () => + { + waitingDialog.Close(); + + await ContentDialogHelper.CreateErrorDialog(ex.Message); + }); + } + }) + { + Name = "GUI.NcaSectionExtractorThread", + IsBackground = true, + }; + extractorThread.Start(); } public static (Result? result, bool canceled) CopyDirectory(FileSystemClient fs, string sourcePath, string destPath, CancellationToken token) diff --git a/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs b/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs index f12d0214..856ed6f7 100644 --- a/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs +++ b/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs @@ -31,7 +31,6 @@ namespace Ryujinx.Ava.Input _control.KeyDown += OnKeyPress; _control.KeyUp += OnKeyRelease; _control.TextInput += Control_TextInput; - _control.AddHandler(InputElement.TextInputEvent, Control_LastChanceTextInput, RoutingStrategies.Bubble); } private void Control_TextInput(object sender, TextInputEventArgs e) @@ -39,12 +38,6 @@ namespace Ryujinx.Ava.Input TextInput?.Invoke(this, e.Text); } - private void Control_LastChanceTextInput(object sender, TextInputEventArgs e) - { - // Swallow event - e.Handled = true; - } - public event Action<string> OnGamepadConnected { add { } diff --git a/src/Ryujinx.Ava/Program.cs b/src/Ryujinx.Ava/Program.cs index 5241f91f..86f38c34 100644 --- a/src/Ryujinx.Ava/Program.cs +++ b/src/Ryujinx.Ava/Program.cs @@ -59,15 +59,12 @@ namespace Ryujinx.Ava { EnableMultiTouch = true, EnableIme = true, - UseEGL = false, - UseGpu = true, + RenderingMode = new[] { X11RenderingMode.Glx, X11RenderingMode.Software }, }) .With(new Win32PlatformOptions { - EnableMultitouch = true, - UseWgl = false, - AllowEglInitialization = false, - CompositionBackdropCornerRadius = 8.0f, + WinUICompositionBackdropCornerRadius = 8.0f, + RenderingMode = new[] { Win32RenderingMode.AngleEgl, Win32RenderingMode.Software }, }) .UseSkia(); } diff --git a/src/Ryujinx.Ava/Ryujinx.Ava.csproj b/src/Ryujinx.Ava/Ryujinx.Ava.csproj index 1fac5400..a4c1ebf1 100644 --- a/src/Ryujinx.Ava/Ryujinx.Ava.csproj +++ b/src/Ryujinx.Ava/Ryujinx.Ava.csproj @@ -10,6 +10,8 @@ <RootNamespace>Ryujinx.Ava</RootNamespace> <ApplicationIcon>Ryujinx.ico</ApplicationIcon> <TieredPGO>true</TieredPGO> + <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> + <ApplicationManifest>app.manifest</ApplicationManifest> </PropertyGroup> <Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))"> @@ -26,7 +28,7 @@ <ItemGroup> <PackageReference Include="Avalonia" /> <PackageReference Include="Avalonia.Desktop" /> - <PackageReference Include="Avalonia.Diagnostics" /> + <PackageReference Include="Avalonia.Diagnostics" Condition="'$(Configuration)'=='Debug'" /> <PackageReference Include="Avalonia.Controls.DataGrid" /> <PackageReference Include="Avalonia.Markup.Xaml.Loader" /> <PackageReference Include="Avalonia.Svg" /> @@ -34,7 +36,6 @@ <PackageReference Include="jp2masa.Avalonia.Flexbox" /> <PackageReference Include="DynamicData" /> <PackageReference Include="FluentAvaloniaUI" /> - <PackageReference Include="XamlNameReferenceGenerator" /> <PackageReference Include="OpenTK.Core" /> <PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" /> @@ -97,10 +98,7 @@ <SubType>Designer</SubType> </AvaloniaResource> <AvaloniaResource Include="Assets\Fonts\SegoeFluentIcons.ttf" /> - <AvaloniaResource Include="Assets\Styles\BaseLight.xaml"> - <Generator>MSBuild:Compile</Generator> - </AvaloniaResource> - <AvaloniaResource Include="Assets\Styles\BaseDark.xaml"> + <AvaloniaResource Include="Assets\Styles\Themes.xaml"> <Generator>MSBuild:Compile</Generator> </AvaloniaResource> <AvaloniaResource Include="Assets\Styles\Styles.xaml" /> @@ -123,8 +121,7 @@ <None Remove="Assets\Locales\zh_CN.json" /> <None Remove="Assets\Locales\zh_TW.json" /> <None Remove="Assets\Styles\Styles.xaml" /> - <None Remove="Assets\Styles\BaseDark.xaml" /> - <None Remove="Assets\Styles\BaseLight.xaml" /> + <None Remove="Assets\Styles\Themes.xaml" /> </ItemGroup> <ItemGroup> diff --git a/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml b/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml index 211b4725..a70fc8d4 100644 --- a/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml +++ b/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml @@ -38,7 +38,7 @@ Grid.Column="1" Margin="10" VerticalAlignment="Stretch" - Text="{Binding Message}" + Text="{ReflectionBinding Message}" TextWrapping="Wrap" /> <StackPanel Name="ButtonStack" diff --git a/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs b/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs index b77cc402..ec6f7682 100644 --- a/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs @@ -4,9 +4,6 @@ using Avalonia.Threading; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Windows; using System.Threading.Tasks; -#if DEBUG -using Avalonia; -#endif namespace Ryujinx.Ava.UI.Applet { @@ -21,9 +18,7 @@ namespace Ryujinx.Ava.UI.Applet Message = message; DataContext = this; InitializeComponent(); -#if DEBUG - this.AttachDevTools(); -#endif + int responseId = 0; if (buttons != null) @@ -44,9 +39,6 @@ namespace Ryujinx.Ava.UI.Applet { DataContext = this; InitializeComponent(); -#if DEBUG - this.AttachDevTools(); -#endif } public string Message { get; set; } diff --git a/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml b/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml index 65504569..64b23f98 100644 --- a/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml +++ b/src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml @@ -34,13 +34,13 @@ Grid.Row="1" Grid.Column="1" Margin="5" - Text="{Binding MainText}" + Text="{ReflectionBinding MainText}" TextWrapping="Wrap" /> <TextBlock Grid.Row="2" Grid.Column="1" Margin="5" - Text="{Binding SecondaryText}" + Text="{ReflectionBinding SecondaryText}" TextWrapping="Wrap" /> <TextBox Name="Input" @@ -50,7 +50,7 @@ VerticalAlignment="Center" Focusable="True" KeyUp="Message_KeyUp" - Text="{Binding Message}" + Text="{ReflectionBinding Message}" TextInput="Message_TextInput" TextWrapping="Wrap" UseFloatingWatermark="True" /> diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml index 29547f5f..93638fc5 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml @@ -2,7 +2,9 @@ x:Class="Ryujinx.Ava.UI.Controls.ApplicationContextMenu" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"> + xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" + xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" + x:DataType="viewModels:MainWindowViewModel"> <MenuItem Click="RunApplication_Click" Header="{locale:Locale GameListContextMenuRunApplication}" /> diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs index 77b4f520..f54e9df8 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs @@ -299,7 +299,11 @@ namespace Ryujinx.Ava.UI.Controls if (viewModel?.SelectedApplication != null) { - await ApplicationHelper.ExtractSection(NcaSectionType.Code, viewModel.SelectedApplication.Path, viewModel.SelectedApplication.TitleName); + await ApplicationHelper.ExtractSection( + viewModel.StorageProvider, + NcaSectionType.Code, + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.TitleName); } } @@ -309,7 +313,11 @@ namespace Ryujinx.Ava.UI.Controls if (viewModel?.SelectedApplication != null) { - await ApplicationHelper.ExtractSection(NcaSectionType.Data, viewModel.SelectedApplication.Path, viewModel.SelectedApplication.TitleName); + await ApplicationHelper.ExtractSection( + viewModel.StorageProvider, + NcaSectionType.Data, + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.TitleName); } } @@ -319,7 +327,11 @@ namespace Ryujinx.Ava.UI.Controls if (viewModel?.SelectedApplication != null) { - await ApplicationHelper.ExtractSection(NcaSectionType.Logo, viewModel.SelectedApplication.Path, viewModel.SelectedApplication.TitleName); + await ApplicationHelper.ExtractSection( + viewModel.StorageProvider, + NcaSectionType.Logo, + viewModel.SelectedApplication.Path, + viewModel.SelectedApplication.TitleName); } } diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml index 3d55793f..214fc075 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml @@ -11,7 +11,9 @@ d:DesignHeight="450" d:DesignWidth="800" Focusable="True" - mc:Ignorable="d"> + mc:Ignorable="d" + xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" + x:DataType="viewModels:MainWindowViewModel"> <UserControl.Resources> <helpers:BitmapArrayValueConverter x:Key="ByteImage" /> <controls:ApplicationContextMenu x:Key="ApplicationContextMenu" /> @@ -27,7 +29,7 @@ VerticalAlignment="Stretch" ContextFlyout="{StaticResource ApplicationContextMenu}" DoubleTapped="GameList_DoubleTapped" - Items="{Binding AppsObservableList}" + ItemsSource="{Binding AppsObservableList}" SelectionChanged="GameList_SelectionChanged"> <ListBox.ItemsPanel> <ItemsPanelTemplate> @@ -43,8 +45,8 @@ <Setter Property="Margin" Value="5" /> <Setter Property="CornerRadius" Value="4" /> </Style> - <Style Selector="ListBoxItem:selected /template/ Border#SelectionIndicator"> - <Setter Property="MinHeight" Value="{Binding $parent[UserControl].DataContext.GridItemSelectorSize}" /> + <Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator"> + <Setter Property="MinHeight" Value="{ReflectionBinding $parent[UserControl].DataContext.GridItemSelectorSize}" /> </Style> </ListBox.Styles> <ListBox.ItemTemplate> @@ -54,10 +56,10 @@ Margin="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - Classes.huge="{Binding $parent[UserControl].DataContext.IsGridHuge}" - Classes.large="{Binding $parent[UserControl].DataContext.IsGridLarge}" - Classes.normal="{Binding $parent[UserControl].DataContext.IsGridMedium}" - Classes.small="{Binding $parent[UserControl].DataContext.IsGridSmall}" + Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}" + Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}" + Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}" + Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}" ClipToBounds="True" CornerRadius="4"> <Grid> @@ -76,9 +78,9 @@ Margin="0,10,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - IsVisible="{Binding $parent[UserControl].DataContext.ShowNames}"> + IsVisible="{ReflectionBinding $parent[UserControl].DataContext.ShowNames}"> <TextBlock - HorizontalAlignment="Stretch" + HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding TitleName}" TextAlignment="Center" diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs index efdc9ab0..821d6fd9 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs @@ -1,7 +1,6 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ui.App.Common; @@ -25,12 +24,7 @@ namespace Ryujinx.Ava.UI.Controls InitializeComponent(); } - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - - public void GameList_DoubleTapped(object sender, RoutedEventArgs args) + public void GameList_DoubleTapped(object sender, TappedEventArgs args) { if (sender is ListBox listBox) { diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml b/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml index 227b4723..75bbf9d0 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml @@ -10,7 +10,9 @@ d:DesignHeight="450" d:DesignWidth="800" Focusable="True" - mc:Ignorable="d"> + mc:Ignorable="d" + xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" + x:DataType="viewModels:MainWindowViewModel"> <UserControl.Resources> <helpers:BitmapArrayValueConverter x:Key="ByteImage" /> <controls:ApplicationContextMenu x:Key="ApplicationContextMenu" /> @@ -27,7 +29,7 @@ VerticalAlignment="Stretch" ContextFlyout="{StaticResource ApplicationContextMenu}" DoubleTapped="GameList_DoubleTapped" - Items="{Binding AppsObservableList}" + ItemsSource="{Binding AppsObservableList}" SelectionChanged="GameList_SelectionChanged"> <ListBox.ItemsPanel> <ItemsPanelTemplate> @@ -39,8 +41,8 @@ </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.Styles> - <Style Selector="ListBoxItem:selected /template/ Border#SelectionIndicator"> - <Setter Property="MinHeight" Value="{Binding $parent[UserControl].DataContext.ListItemSelectorSize}" /> + <Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator"> + <Setter Property="MinHeight" Value="{ReflectionBinding $parent[UserControl].DataContext.ListItemSelectorSize}" /> </Style> </ListBox.Styles> <ListBox.ItemTemplate> @@ -65,10 +67,10 @@ Grid.RowSpan="3" Grid.Column="0" Margin="0" - Classes.huge="{Binding $parent[UserControl].DataContext.IsGridHuge}" - Classes.large="{Binding $parent[UserControl].DataContext.IsGridLarge}" - Classes.normal="{Binding $parent[UserControl].DataContext.IsGridMedium}" - Classes.small="{Binding $parent[UserControl].DataContext.IsGridSmall}" + Classes.huge="{ReflectionBinding $parent[UserControl].DataContext.IsGridHuge}" + Classes.large="{ReflectionBinding $parent[UserControl].DataContext.IsGridLarge}" + Classes.normal="{ReflectionBinding $parent[UserControl].DataContext.IsGridMedium}" + Classes.small="{ReflectionBinding $parent[UserControl].DataContext.IsGridSmall}" Source="{Binding Icon, Converter={StaticResource ByteImage}}" /> <Border Grid.Column="2" diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs index 1646fc1b..dd60503a 100644 --- a/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs @@ -1,7 +1,6 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ui.App.Common; @@ -25,12 +24,7 @@ namespace Ryujinx.Ava.UI.Controls InitializeComponent(); } - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - - public void GameList_DoubleTapped(object sender, RoutedEventArgs args) + public void GameList_DoubleTapped(object sender, TappedEventArgs args) { if (sender is ListBox listBox) { diff --git a/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs b/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs index 4e4b971e..7da23648 100644 --- a/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs +++ b/src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs @@ -1,6 +1,4 @@ -using Avalonia.Data; using Avalonia.Markup.Xaml; -using Avalonia.Markup.Xaml.MarkupExtensions; using FluentAvalonia.UI.Controls; using System; using System.Collections.Generic; @@ -38,13 +36,7 @@ namespace Ryujinx.Ava.UI.Helpers public override object ProvideValue(IServiceProvider serviceProvider) { - ReflectionBindingExtension binding = new($"[{_key}]") - { - Mode = BindingMode.OneWay, - Source = this, - }; - - return binding.ProvideValue(serviceProvider); + return this[_key]; } } } diff --git a/src/Ryujinx.Ava/UI/Helpers/HotKeyControl.cs b/src/Ryujinx.Ava/UI/Helpers/HotKeyControl.cs deleted file mode 100644 index 4ae903b4..00000000 --- a/src/Ryujinx.Ava/UI/Helpers/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.Helpers -{ - public class HotKeyControl : ContentControl, ICommandSource - { - public static readonly StyledProperty<object> CommandParameterProperty = - AvaloniaProperty.Register<HotKeyControl, object>(nameof(CommandParameter)); - - public static readonly DirectProperty<HotKeyControl, ICommand> CommandProperty = - AvaloniaProperty.RegisterDirect<HotKeyControl, ICommand>(nameof(Command), - control => control.Command, (control, command) => control.Command = command, enableDataValidation: true); - - public static readonly StyledProperty<KeyGesture> HotKeyProperty = HotKeyManager.HotKeyProperty.AddOwner<Button>(); - - private ICommand _command; - private bool _commandCanExecute; - - public ICommand Command - { - get { return _command; } - set { SetAndRaise(CommandProperty, ref _command, value); } - } - - public KeyGesture HotKey - { - get { return GetValue(HotKeyProperty); } - set { SetValue(HotKeyProperty, value); } - } - - public object CommandParameter - { - get { return GetValue(CommandParameterProperty); } - set { SetValue(CommandParameterProperty, value); } - } - - public void CanExecuteChanged(object sender, EventArgs e) - { - var canExecute = Command == null || Command.CanExecute(CommandParameter); - - if (canExecute != _commandCanExecute) - { - _commandCanExecute = canExecute; - UpdateIsEffectivelyEnabled(); - } - } - } -} diff --git a/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs b/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs index dc8e3f94..0b178988 100644 --- a/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs +++ b/src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs @@ -42,21 +42,6 @@ namespace Ryujinx.Ava.UI.Helpers GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, null)); } - public void Log<T0>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0) - { - GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0 })); - } - - public void Log<T0, T1>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0, T1 propertyValue1) - { - GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0, propertyValue1 })); - } - - public void Log<T0, T1, T2>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) - { - GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0, propertyValue1, propertyValue2 })); - } - 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)); diff --git a/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs b/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs index 670d3b36..a055f335 100644 --- a/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs +++ b/src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs @@ -31,7 +31,6 @@ namespace Ryujinx.Ava.UI.Helpers OnTextInput(new TextInputEventArgs { Text = text, - Device = KeyboardDevice.Instance, Source = this, RoutedEvent = TextInputEvent, }); diff --git a/src/Ryujinx.Ava/UI/Helpers/TimeZoneConverter.cs b/src/Ryujinx.Ava/UI/Helpers/TimeZoneConverter.cs new file mode 100644 index 00000000..4ec0ff30 --- /dev/null +++ b/src/Ryujinx.Ava/UI/Helpers/TimeZoneConverter.cs @@ -0,0 +1,28 @@ +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/Models/UserProfile.cs b/src/Ryujinx.Ava/UI/Models/UserProfile.cs index e1698b4d..7a9237fe 100644 --- a/src/Ryujinx.Ava/UI/Models/UserProfile.cs +++ b/src/Ryujinx.Ava/UI/Models/UserProfile.cs @@ -1,4 +1,3 @@ -using Avalonia; using Avalonia.Media; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.ViewModels; @@ -88,7 +87,8 @@ namespace Ryujinx.Ava.UI.Models private void UpdateBackground() { - Application.Current.Styles.TryGetResource("ControlFillColorSecondary", out object color); + var currentApplication = Avalonia.Application.Current; + currentApplication.Styles.TryGetResource("ControlFillColorSecondary", currentApplication.ActualThemeVariant, out object color); if (color is not null) { diff --git a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs index e324b484..fa55c8d3 100644 --- a/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs +++ b/src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Ava.UI.Renderer private UpdateBoundsCallbackDelegate _updateBoundsCallback; public event EventHandler<IntPtr> WindowCreated; - public event EventHandler<Size> SizeChanged; + public event EventHandler<Size> BoundsChanged; public EmbeddedWindow() { @@ -67,7 +67,7 @@ namespace Ryujinx.Ava.UI.Renderer private void StateChanged(Rect rect) { - SizeChanged?.Invoke(this, rect.Size); + BoundsChanged?.Invoke(this, rect.Size); _updateBoundsCallback?.Invoke(rect); } @@ -149,9 +149,10 @@ namespace Ryujinx.Ava.UI.Renderer msg == WindowsMessages.Rbuttonup || msg == WindowsMessages.Mousemove) { - Point rootVisualPosition = this.TranslatePoint(new Point((long)lParam & 0xFFFF, (long)lParam >> 16 & 0xFFFF), VisualRoot).Value; + Point rootVisualPosition = this.TranslatePoint(new Point((long)lParam & 0xFFFF, (long)lParam >> 16 & 0xFFFF), this).Value; Pointer pointer = new(0, PointerType.Mouse, true); +#pragma warning disable CS0618 // Type or member is obsolete (As of Avalonia 11, the constructors for PointerPressedEventArgs & PointerEventArgs are marked as obsolete) switch (msg) { case WindowsMessages.Lbuttondown: @@ -164,7 +165,7 @@ namespace Ryujinx.Ava.UI.Renderer var evnt = new PointerPressedEventArgs( this, pointer, - VisualRoot, + this, rootVisualPosition, (ulong)Environment.TickCount64, properties, @@ -184,7 +185,7 @@ namespace Ryujinx.Ava.UI.Renderer var evnt = new PointerReleasedEventArgs( this, pointer, - VisualRoot, + this, rootVisualPosition, (ulong)Environment.TickCount64, properties, @@ -201,7 +202,7 @@ namespace Ryujinx.Ava.UI.Renderer PointerMovedEvent, this, pointer, - VisualRoot, + this, rootVisualPosition, (ulong)Environment.TickCount64, new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.Other), @@ -212,6 +213,7 @@ namespace Ryujinx.Ava.UI.Renderer break; } } +#pragma warning restore CS0618 } } diff --git a/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs b/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs index b74265a3..12c18e4a 100644 --- a/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs +++ b/src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Renderer public readonly EmbeddedWindow EmbeddedWindow; public event EventHandler<EventArgs> WindowCreated; - public event Action<object, Size> SizeChanged; + public event Action<object, Size> BoundsChanged; public RendererHost() { @@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.Renderer private void Initialize() { EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated; - EmbeddedWindow.SizeChanged += CurrentWindow_SizeChanged; + EmbeddedWindow.BoundsChanged += CurrentWindow_BoundsChanged; Content = EmbeddedWindow; } @@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Renderer if (EmbeddedWindow != null) { EmbeddedWindow.WindowCreated -= CurrentWindow_WindowCreated; - EmbeddedWindow.SizeChanged -= CurrentWindow_SizeChanged; + EmbeddedWindow.BoundsChanged -= CurrentWindow_BoundsChanged; } GC.SuppressFinalize(this); @@ -55,9 +55,9 @@ namespace Ryujinx.Ava.UI.Renderer Dispose(); } - private void CurrentWindow_SizeChanged(object sender, Size e) + private void CurrentWindow_BoundsChanged(object sender, Size e) { - SizeChanged?.Invoke(sender, e); + BoundsChanged?.Invoke(sender, e); } private void CurrentWindow_WindowCreated(object sender, IntPtr e) diff --git a/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs index fddcd71a..70ede4c1 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs @@ -1,4 +1,3 @@ -using Avalonia; using Avalonia.Media.Imaging; using Avalonia.Platform; using Avalonia.Threading; @@ -88,21 +87,19 @@ namespace Ryujinx.Ava.UI.ViewModels { Version = Program.Version; - var assets = AvaloniaLocator.Current.GetService<IAssetLoader>(); - if (ConfigurationState.Instance.Ui.BaseStyle.Value == "Light") { - GithubLogo = new Bitmap(assets.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_GitHub_Light.png?assembly=Ryujinx.Ui.Common"))); - DiscordLogo = new Bitmap(assets.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Discord_Light.png?assembly=Ryujinx.Ui.Common"))); - PatreonLogo = new Bitmap(assets.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Patreon_Light.png?assembly=Ryujinx.Ui.Common"))); - TwitterLogo = new Bitmap(assets.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Twitter_Light.png?assembly=Ryujinx.Ui.Common"))); + GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_GitHub_Light.png?assembly=Ryujinx.Ui.Common"))); + DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Discord_Light.png?assembly=Ryujinx.Ui.Common"))); + PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Patreon_Light.png?assembly=Ryujinx.Ui.Common"))); + TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Twitter_Light.png?assembly=Ryujinx.Ui.Common"))); } else { - GithubLogo = new Bitmap(assets.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_GitHub_Dark.png?assembly=Ryujinx.Ui.Common"))); - DiscordLogo = new Bitmap(assets.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Discord_Dark.png?assembly=Ryujinx.Ui.Common"))); - PatreonLogo = new Bitmap(assets.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Patreon_Dark.png?assembly=Ryujinx.Ui.Common"))); - TwitterLogo = new Bitmap(assets.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Twitter_Dark.png?assembly=Ryujinx.Ui.Common"))); + GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_GitHub_Dark.png?assembly=Ryujinx.Ui.Common"))); + DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Discord_Dark.png?assembly=Ryujinx.Ui.Common"))); + PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Patreon_Dark.png?assembly=Ryujinx.Ui.Common"))); + TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.Ui.Common.Resources.Logo_Twitter_Dark.png?assembly=Ryujinx.Ui.Common"))); } Dispatcher.UIThread.InvokeAsync(DownloadPatronsJson); diff --git a/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs index f2f56947..74b73751 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -1,6 +1,6 @@ using Avalonia.Collections; -using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Platform.Storage; using Avalonia.Threading; using DynamicData; using LibHac.Common; @@ -90,12 +90,19 @@ namespace Ryujinx.Ava.UI.ViewModels get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count); } + public IStorageProvider StorageProvider; + public DownloadableContentManagerViewModel(VirtualFileSystem virtualFileSystem, ulong titleId) { _virtualFileSystem = virtualFileSystem; _titleId = titleId; + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + StorageProvider = desktop.MainWindow.StorageProvider; + } + _downloadableContentJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "dlc.json"); try @@ -195,29 +202,24 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { - OpenFileDialog dialog = new() + var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle], AllowMultiple = true, - }; - - dialog.Filters.Add(new FileDialogFilter - { - Name = "NSP", - Extensions = { "nsp" }, - }); - - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) - { - string[] files = await dialog.ShowAsync(desktop.MainWindow); - - if (files != null) + FileTypeFilter = new List<FilePickerFileType> { - foreach (string file in files) + new("NSP") { - await AddDownloadableContent(file); + Patterns = new[] { "*.nsp" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" }, + MimeTypes = new[] { "application/x-nx-nsp" } } } + }); + + foreach (var file in result) + { + await AddDownloadableContent(file.Path.LocalPath); } } diff --git a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs index e8d68f76..aa6e0326 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs @@ -3,6 +3,7 @@ using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Input; using Avalonia.Media; +using Avalonia.Platform.Storage; using Avalonia.Threading; using DynamicData; using DynamicData.Binding; @@ -105,8 +106,6 @@ namespace Ryujinx.Ava.UI.ViewModels public ApplicationData ListSelectedApplication; public ApplicationData GridSelectedApplication; - public event Action ReloadGameList; - private string TitleName { get; set; } internal AppHost AppHost { get; set; } @@ -131,6 +130,7 @@ namespace Ryujinx.Ava.UI.ViewModels public void Initialize( ContentManager contentManager, + IStorageProvider storageProvider, ApplicationLibrary applicationLibrary, VirtualFileSystem virtualFileSystem, AccountManager accountManager, @@ -144,6 +144,7 @@ namespace Ryujinx.Ava.UI.ViewModels TopLevel topLevel) { ContentManager = contentManager; + StorageProvider = storageProvider; ApplicationLibrary = applicationLibrary; VirtualFileSystem = virtualFileSystem; AccountManager = accountManager; @@ -891,6 +892,7 @@ namespace Ryujinx.Ava.UI.ViewModels } public ContentManager ContentManager { get; private set; } + public IStorageProvider StorageProvider { get; private set; } public ApplicationLibrary ApplicationLibrary { get; private set; } public VirtualFileSystem VirtualFileSystem { get; private set; } public AccountManager AccountManager { get; private set; } @@ -1188,7 +1190,9 @@ namespace Ryujinx.Ava.UI.ViewModels { Application.Current.Styles.TryGetResource(args.VSyncEnabled ? "VsyncEnabled" - : "VsyncDisabled", out object color); + : "VsyncDisabled", + Avalonia.Application.Current.ActualThemeVariant, + out object color); if (color is not null) { @@ -1259,6 +1263,16 @@ namespace Ryujinx.Ava.UI.ViewModels ShowMenuAndStatusBar = false; } + public void ToggleStartGamesInFullscreen() + { + StartGamesInFullscreen = !StartGamesInFullscreen; + } + + public void ToggleShowConsole() + { + ShowConsole = !ShowConsole; + } + public void SetListMode() { Glyph = Glyph.List; @@ -1271,43 +1285,57 @@ namespace Ryujinx.Ava.UI.ViewModels public async void InstallFirmwareFromFile() { - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { - OpenFileDialog dialog = new() { AllowMultiple = false }; - dialog.Filters.Add(new FileDialogFilter { Name = LocaleManager.Instance[LocaleKeys.FileDialogAllTypes], Extensions = { "xci", "zip" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "XCI", Extensions = { "xci" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "ZIP", Extensions = { "zip" } }); - - string[] file = await dialog.ShowAsync(desktop.MainWindow); - - if (file != null && file.Length > 0) + AllowMultiple = false, + FileTypeFilter = new List<FilePickerFileType> { - await HandleFirmwareInstallation(file[0]); + new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes]) + { + Patterns = new[] { "*.xci", "*.zip" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" }, + MimeTypes = new[] { "application/x-nx-xci", "application/zip" } + }, + new("XCI") + { + Patterns = new[] { "*.xci" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" }, + MimeTypes = new[] { "application/x-nx-xci" } + }, + new("ZIP") + { + Patterns = new[] { "*.zip" }, + AppleUniformTypeIdentifiers = new[] { "public.zip-archive" }, + MimeTypes = new[] { "application/zip" } + }, } + }); + + if (result.Count > 0) + { + await HandleFirmwareInstallation(result[0].Path.LocalPath); } } public async void InstallFirmwareFromFolder() { - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions { - OpenFolderDialog dialog = new(); - - string folder = await dialog.ShowAsync(desktop.MainWindow); + AllowMultiple = false + }); - if (!string.IsNullOrEmpty(folder)) - { - await HandleFirmwareInstallation(folder); - } + if (result.Count > 0) + { + await HandleFirmwareInstallation(result[0].Path.LocalPath); } } - public static void OpenRyujinxFolder() + public void OpenRyujinxFolder() { OpenHelper.OpenFolder(AppDataManager.BaseDirPath); } - public static void OpenLogsFolder() + public void OpenLogsFolder() { string logPath = Path.Combine(ReleaseInformation.GetBaseApplicationDirectory(), "Logs"); @@ -1349,25 +1377,6 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public void ToggleFileType(string fileType) - { - _ = fileType switch - { -#pragma warning disable IDE0055 // Disable formatting - "NSP" => ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NSP, - "PFS0" => ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.PFS0, - "XCI" => ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.XCI, - "NCA" => ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NCA, - "NRO" => ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NRO, - "NSO" => ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NSO, - _ => throw new ArgumentOutOfRangeException(fileType), -#pragma warning restore IDE0055 - }; - - ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); - LoadApplications(); - } - public async void ManageProfiles() { await NavigationDialogHost.Show(AccountManager, ContentManager, VirtualFileSystem, LibHacHorizonManager.RyujinxClient); @@ -1378,78 +1387,84 @@ namespace Ryujinx.Ava.UI.ViewModels AppHost.Device.System.SimulateWakeUpMessage(); } - public async void LoadApplications() - { - await Dispatcher.UIThread.InvokeAsync(() => - { - Applications.Clear(); - - StatusBarVisible = true; - StatusBarProgressMaximum = 0; - StatusBarProgressValue = 0; - - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0); - }); - - ReloadGameList?.Invoke(); - } - public async void OpenFile() { - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { - OpenFileDialog dialog = new() + Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], + AllowMultiple = false, + FileTypeFilter = new List<FilePickerFileType> { - Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], - }; - - dialog.Filters.Add(new FileDialogFilter - { - Name = LocaleManager.Instance[LocaleKeys.AllSupportedFormats], - Extensions = + new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) + { + Patterns = new[] { "*.nsp", "*.xci", "*.nca", "*.nro", "*.nso" }, + AppleUniformTypeIdentifiers = new[] + { + "com.ryujinx.nsp", + "com.ryujinx.xci", + "com.ryujinx.nca", + "com.ryujinx.nro", + "com.ryujinx.nso" + }, + MimeTypes = new[] + { + "application/x-nx-nsp", + "application/x-nx-xci", + "application/x-nx-nca", + "application/x-nx-nro", + "application/x-nx-nso" + } + }, + new("NSP") { - "nsp", - "pfs0", - "xci", - "nca", - "nro", - "nso", + Patterns = new[] { "*.nsp" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" }, + MimeTypes = new[] { "application/x-nx-nsp" } + }, + new("XCI") + { + Patterns = new[] { "*.xci" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" }, + MimeTypes = new[] { "application/x-nx-xci" } + }, + new("NCA") + { + Patterns = new[] { "*.nca" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nca" }, + MimeTypes = new[] { "application/x-nx-nca" } + }, + new("NRO") + { + Patterns = new[] { "*.nro" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nro" }, + MimeTypes = new[] { "application/x-nx-nro" } + }, + new("NSO") + { + Patterns = new[] { "*.nso" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nso" }, + MimeTypes = new[] { "application/x-nx-nso" } }, - }); - -#pragma warning disable IDE0055 // Disable formatting - dialog.Filters.Add(new FileDialogFilter { Name = "NSP", Extensions = { "nsp" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "PFS0", Extensions = { "pfs0" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "XCI", Extensions = { "xci" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "NCA", Extensions = { "nca" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "NRO", Extensions = { "nro" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "NSO", Extensions = { "nso" } }); -#pragma warning restore IDE0055 - - string[] files = await dialog.ShowAsync(desktop.MainWindow); - - if (files != null && files.Length > 0) - { - LoadApplication(files[0]); } + }); + + if (result.Count > 0) + { + LoadApplication(result[0].Path.LocalPath); } } public async void OpenFolder() { - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions { - OpenFolderDialog dialog = new() - { - Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle], - }; - - string folder = await dialog.ShowAsync(desktop.MainWindow); + Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle], + AllowMultiple = false + }); - if (!string.IsNullOrWhiteSpace(folder) && Directory.Exists(folder)) - { - LoadApplication(folder); - } + if (result.Count > 0) + { + LoadApplication(result[0].Path.LocalPath); } } diff --git a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs index 740d888b..e3bca205 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs @@ -1,7 +1,7 @@ using Avalonia; using Avalonia.Collections; -using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Platform.Storage; using Avalonia.Threading; using LibHac.Common; using LibHac.Fs; @@ -70,12 +70,19 @@ namespace Ryujinx.Ava.UI.ViewModels } } + public IStorageProvider StorageProvider; + public TitleUpdateViewModel(VirtualFileSystem virtualFileSystem, ulong titleId) { VirtualFileSystem = virtualFileSystem; TitleId = titleId; + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + StorageProvider = desktop.MainWindow.StorageProvider; + } + TitleUpdateJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "updates.json"); try @@ -202,29 +209,23 @@ namespace Ryujinx.Ava.UI.ViewModels public async void Add() { - OpenFileDialog dialog = new() + var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { - Title = LocaleManager.Instance[LocaleKeys.SelectUpdateDialogTitle], AllowMultiple = true, - }; - - dialog.Filters.Add(new FileDialogFilter - { - Name = "NSP", - Extensions = { "nsp" }, - }); - - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) - { - string[] files = await dialog.ShowAsync(desktop.MainWindow); - - if (files != null) + FileTypeFilter = new List<FilePickerFileType> { - foreach (string file in files) + new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) { - AddUpdate(file); + Patterns = new[] { "*.nsp" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" }, + MimeTypes = new[] { "application/x-nx-nsp" } } } + }); + + foreach (var file in result) + { + AddUpdate(file.Path.LocalPath); } SortUpdates(); diff --git a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml index 2395b353..65a66d9e 100644 --- a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml @@ -14,7 +14,6 @@ d:DesignWidth="800" x:Class="Ryujinx.Ava.UI.Views.Input.ControllerInputView" x:DataType="viewModels:ControllerInputViewModel" - x:CompileBindings="True" mc:Ignorable="d" Focusable="True"> <Design.DataContext> @@ -66,7 +65,7 @@ HorizontalAlignment="Stretch" VerticalAlignment="Center" SelectionChanged="PlayerIndexBox_OnSelectionChanged" - Items="{Binding PlayerIndexes}" + ItemsSource="{Binding PlayerIndexes}" SelectedIndex="{Binding PlayerId}"> <ComboBox.ItemTemplate> <DataTemplate> @@ -94,15 +93,15 @@ HorizontalAlignment="Left" VerticalAlignment="Center" Text="{locale:Locale ControllerSettingsProfile}" /> - <ui:ComboBox + <ui:FAComboBox Grid.Column="1" IsEditable="True" Name="ProfileBox" HorizontalAlignment="Stretch" VerticalAlignment="Center" SelectedIndex="0" - Items="{Binding ProfilesList}" - Text="{Binding ProfileName}" /> + ItemsSource="{Binding ProfilesList}" + Text="{Binding ProfileName, Mode=TwoWay}" /> <Button Grid.Column="2" MinWidth="0" @@ -170,7 +169,7 @@ Name="DeviceBox" HorizontalAlignment="Stretch" VerticalAlignment="Center" - Items="{Binding DeviceList}" + ItemsSource="{Binding DeviceList}" SelectedIndex="{Binding Device}" /> <Button Grid.Column="2" @@ -203,8 +202,8 @@ <ComboBox Grid.Column="1" HorizontalAlignment="Stretch" - Items="{ReflectionBinding Controllers}" - SelectedIndex="{ReflectionBinding Controller}"> + ItemsSource="{Binding Controllers}" + SelectedIndex="{Binding Controller}"> <ComboBox.ItemTemplate> <DataTemplate DataType="models:ControllerModel"> <TextBlock Text="{Binding Name}" /> @@ -723,7 +722,7 @@ <Button Margin="10" Grid.Column="1" - Command="{ReflectionBinding ShowMotionConfig}"> + Command="{Binding ShowMotionConfig}"> <TextBlock Text="{locale:Locale ControllerSettingsConfigureGeneral}" /> </Button> </Grid> @@ -750,7 +749,7 @@ <Button Margin="10" Grid.Column="1" - Command="{ReflectionBinding ShowRumbleConfig}"> + Command="{Binding ShowRumbleConfig}"> <TextBlock Text="{locale:Locale ControllerSettingsConfigureGeneral}" /> </Button> </Grid> diff --git a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs index 19009f5f..35129706 100644 --- a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs @@ -31,8 +31,7 @@ namespace Ryujinx.Ava.UI.Views.Input { if (visual is ToggleButton button && visual is not CheckBox) { - button.Checked += Button_Checked; - button.Unchecked += Button_Unchecked; + button.IsCheckedChanged += Button_IsCheckedChanged; } } } @@ -47,48 +46,56 @@ namespace Ryujinx.Ava.UI.Views.Input } } - private void Button_Checked(object sender, RoutedEventArgs e) + private void Button_IsCheckedChanged(object sender, RoutedEventArgs e) { if (sender is ToggleButton button) { - if (_currentAssigner != null && button == _currentAssigner.ToggledButton) + if ((bool)button.IsChecked) { - return; - } + if (_currentAssigner != null && button == _currentAssigner.ToggledButton) + { + return; + } - bool isStick = button.Tag != null && button.Tag.ToString() == "stick"; + bool isStick = button.Tag != null && button.Tag.ToString() == "stick"; - if (_currentAssigner == null && (bool)button.IsChecked) - { - _currentAssigner = new ButtonKeyAssigner(button); + if (_currentAssigner == null) + { + _currentAssigner = new ButtonKeyAssigner(button); - FocusManager.Instance.Focus(this, NavigationMethod.Pointer); + this.Focus(NavigationMethod.Pointer); - PointerPressed += MouseClick; + PointerPressed += MouseClick; - IKeyboard keyboard = (IKeyboard)ViewModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations. - IButtonAssigner assigner = CreateButtonAssigner(isStick); + IKeyboard keyboard = (IKeyboard)ViewModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations. + IButtonAssigner assigner = CreateButtonAssigner(isStick); - _currentAssigner.ButtonAssigned += (sender, e) => + _currentAssigner.ButtonAssigned += (sender, e) => + { + if (e.IsAssigned) + { + ViewModel.IsModified = true; + } + }; + + _currentAssigner.GetInputAndAssign(assigner, keyboard); + } + else { - if (e.IsAssigned) + if (_currentAssigner != null) { - ViewModel.IsModified = true; - } - }; + ToggleButton oldButton = _currentAssigner.ToggledButton; - _currentAssigner.GetInputAndAssign(assigner, keyboard); + _currentAssigner.Cancel(); + _currentAssigner = null; + button.IsChecked = false; + } + } } else { - if (_currentAssigner != null) - { - ToggleButton oldButton = _currentAssigner.ToggledButton; - - _currentAssigner.Cancel(); - _currentAssigner = null; - button.IsChecked = false; - } + _currentAssigner?.Cancel(); + _currentAssigner = null; } } } @@ -120,12 +127,6 @@ namespace Ryujinx.Ava.UI.Views.Input return assigner; } - private void Button_Unchecked(object sender, RoutedEventArgs e) - { - _currentAssigner?.Cancel(); - _currentAssigner = null; - } - private void MouseClick(object sender, PointerPressedEventArgs e) { bool shouldUnbind = false; diff --git a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml index b1832437..71d5d746 100644 --- a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml @@ -8,7 +8,6 @@ xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" x:Class="Ryujinx.Ava.UI.Views.Input.MotionInputView" - x:CompileBindings="True" x:DataType="viewModels:MotionInputViewModel" Focusable="True"> <Grid Margin="10"> diff --git a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml index 3882ebe2..16190d39 100644 --- a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml @@ -8,7 +8,6 @@ mc:Ignorable="d" x:Class="Ryujinx.Ava.UI.Views.Input.RumbleInputView" x:DataType="viewModels:RumbleInputViewModel" - x:CompileBindings="True" Focusable="True"> <Grid Margin="10"> <Grid.RowDefinitions> diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml index d5b5efcd..30358ada 100644 --- a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml @@ -7,8 +7,7 @@ mc:Ignorable="d" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" x:DataType="viewModels:MainWindowViewModel" - x:Class="Ryujinx.Ava.UI.Views.Main.MainMenuBarView" - x:CompileBindings="True"> + x:Class="Ryujinx.Ava.UI.Views.Main.MainMenuBarView"> <Design.DataContext> <viewModels:MainWindowViewModel /> </Design.DataContext> @@ -25,12 +24,12 @@ </Menu.ItemsPanel> <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarFile}"> <MenuItem - Command="{ReflectionBinding OpenFile}" + Command="{Binding OpenFile}" Header="{locale:Locale MenuBarFileOpenFromFile}" IsEnabled="{Binding EnableNonGameRunningControls}" ToolTip.Tip="{locale:Locale LoadApplicationFileTooltip}" /> <MenuItem - Command="{ReflectionBinding OpenFolder}" + Command="{Binding OpenFolder}" Header="{locale:Locale MenuBarFileOpenUnpacked}" IsEnabled="{Binding EnableNonGameRunningControls}" ToolTip.Tip="{locale:Locale LoadApplicationFolderTooltip}" /> @@ -42,11 +41,11 @@ </MenuItem> <Separator /> <MenuItem - Command="{ReflectionBinding OpenRyujinxFolder}" + Command="{Binding OpenRyujinxFolder}" Header="{locale:Locale MenuBarFileOpenEmuFolder}" ToolTip.Tip="{locale:Locale OpenRyujinxFolderTooltip}" /> <MenuItem - Command="{ReflectionBinding OpenLogsFolder}" + Command="{Binding OpenLogsFolder}" Header="{locale:Locale MenuBarFileOpenLogsFolder}" ToolTip.Tip="{locale:Locale OpenRyujinxLogsTooltip}" /> <Separator /> @@ -57,35 +56,75 @@ </MenuItem> <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarOptions}"> <MenuItem - Command="{ReflectionBinding ToggleFullscreen}" + Padding="-10,0,0,0" + Command="{Binding ToggleFullscreen}" Header="{locale:Locale MenuBarOptionsToggleFullscreen}" InputGesture="F11" /> - <MenuItem> + <MenuItem + Padding="0" + Command="{Binding ToggleStartGamesInFullscreen}" + Header="{locale:Locale MenuBarOptionsStartGamesInFullscreen}"> <MenuItem.Icon> - <CheckBox IsChecked="{Binding StartGamesInFullscreen, Mode=TwoWay}" - MinWidth="250"> - <TextBlock Text="{locale:Locale MenuBarOptionsStartGamesInFullscreen}"/> - </CheckBox> + <CheckBox + MinWidth="{DynamicResource CheckBoxSize}" + MinHeight="{DynamicResource CheckBoxSize}" + IsChecked="{Binding StartGamesInFullscreen, Mode=TwoWay}" + Padding="0" /> </MenuItem.Icon> + <MenuItem.Styles> + <Style Selector="Viewbox#PART_IconPresenter"> + <Setter Property="MaxHeight" Value="36" /> + <Setter Property="MinHeight" Value="36" /> + <Setter Property="MaxWidth" Value="36" /> + <Setter Property="MinWidth" Value="36" /> + </Style> + <Style Selector="ContentPresenter#PART_HeaderPresenter"> + <Setter Property="Padding" Value="-10,0,0,0" /> + </Style> + </MenuItem.Styles> </MenuItem> - <MenuItem IsVisible="{Binding ShowConsoleVisible}"> + <MenuItem + Padding="0" + IsVisible="{Binding ShowConsoleVisible}" + Command="{Binding ToggleShowConsole}" + Header="{locale:Locale MenuBarOptionsShowConsole}"> <MenuItem.Icon> - <CheckBox IsChecked="{Binding ShowConsole, Mode=TwoWay}" - MinWidth="250"> - <TextBlock Text="{locale:Locale MenuBarOptionsShowConsole}"/> - </CheckBox> + <CheckBox + MinWidth="{DynamicResource CheckBoxSize}" + MinHeight="{DynamicResource CheckBoxSize}" + IsChecked="{Binding ShowConsole, Mode=TwoWay}" + Padding="0" /> </MenuItem.Icon> + <MenuItem.Styles> + <Style Selector="Viewbox#PART_IconPresenter"> + <Setter Property="MaxHeight" Value="36" /> + <Setter Property="MinHeight" Value="36" /> + <Setter Property="MaxWidth" Value="36" /> + <Setter Property="MinWidth" Value="36" /> + </Style> + <Style Selector="ContentPresenter#PART_HeaderPresenter"> + <Setter Property="Padding" Value="-10,0,0,0" /> + </Style> + </MenuItem.Styles> </MenuItem> <Separator /> - <MenuItem Name="ChangeLanguageMenuItem" Header="{locale:Locale MenuBarOptionsChangeLanguage}" /> - <MenuItem Name="ToggleFileTypesMenuItem" Header="{locale:Locale MenuBarShowFileTypes}" /> + <MenuItem + Name="ChangeLanguageMenuItem" + Padding="-10,0,0,0" + Header="{locale:Locale MenuBarOptionsChangeLanguage}" /> + <MenuItem + Name="ToggleFileTypesMenuItem" + Padding="-10,0,0,0" + Header="{locale:Locale MenuBarShowFileTypes}" /> <Separator /> <MenuItem Click="OpenSettings" + Padding="-10,0,0,0" Header="{locale:Locale MenuBarOptionsSettings}" ToolTip.Tip="{locale:Locale OpenSettingsTooltip}" /> <MenuItem - Command="{ReflectionBinding ManageProfiles}" + Command="{Binding ManageProfiles}" + Padding="-10,0,0,0" Header="{locale:Locale MenuBarOptionsManageUserProfiles}" IsEnabled="{Binding EnableNonGameRunningControls}" ToolTip.Tip="{locale:Locale OpenProfileManagerTooltip}" /> @@ -113,7 +152,7 @@ InputGesture="Escape" IsEnabled="{Binding IsGameRunning}" ToolTip.Tip="{locale:Locale StopEmulationTooltip}" /> - <MenuItem Command="{ReflectionBinding SimulateWakeUpMessage}" Header="{locale:Locale MenuBarOptionsSimulateWakeUpMessage}" /> + <MenuItem Command="{Binding SimulateWakeUpMessage}" Header="{locale:Locale MenuBarOptionsSimulateWakeUpMessage}" /> <Separator /> <MenuItem Name="ScanAmiiboMenuItem" @@ -122,12 +161,12 @@ Header="{locale:Locale MenuBarActionsScanAmiibo}" IsEnabled="{Binding IsAmiiboRequested}" /> <MenuItem - Command="{ReflectionBinding TakeScreenshot}" + Command="{Binding TakeScreenshot}" Header="{locale:Locale MenuBarFileToolsTakeScreenshot}" InputGesture="{Binding ScreenshotKey}" IsEnabled="{Binding IsGameRunning}" /> <MenuItem - Command="{ReflectionBinding HideUi}" + Command="{Binding HideUi}" Header="{locale:Locale MenuBarFileToolsHideUi}" InputGesture="{Binding ShowUiKey}" IsEnabled="{Binding IsGameRunning}" /> @@ -138,8 +177,8 @@ </MenuItem> <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarTools}"> <MenuItem Header="{locale:Locale MenuBarToolsInstallFirmware}" IsEnabled="{Binding EnableNonGameRunningControls}"> - <MenuItem Command="{ReflectionBinding InstallFirmwareFromFile}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromFile}" /> - <MenuItem Command="{ReflectionBinding InstallFirmwareFromFolder}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromDirectory}" /> + <MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromFile}" /> + <MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromDirectory}" /> </MenuItem> <MenuItem Header="{locale:Locale MenuBarToolsManageFileTypes}" IsVisible="{Binding ManageFileTypesVisible}"> <MenuItem Header="{locale:Locale MenuBarToolsInstallFileTypes}" Click="InstallFileTypes_Click"/> diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs index ae52f071..af8c4dab 100644 --- a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs @@ -30,8 +30,8 @@ namespace Ryujinx.Ava.UI.Views.Main { InitializeComponent(); - ToggleFileTypesMenuItem.Items = GenerateToggleFileTypeItems(); - ChangeLanguageMenuItem.Items = GenerateLanguageMenuItems(); + ToggleFileTypesMenuItem.ItemsSource = GenerateToggleFileTypeItems(); + ChangeLanguageMenuItem.ItemsSource = GenerateLanguageMenuItems(); } private CheckBox[] GenerateToggleFileTypeItems() @@ -45,7 +45,7 @@ namespace Ryujinx.Ava.UI.Views.Main { Content = $".{fileName}", IsChecked = ((FileTypes)item).GetConfigValue(ConfigurationState.Instance.Ui.ShownFileTypes), - Command = MiniCommand.Create(() => ViewModel.ToggleFileType(fileName)), + Command = MiniCommand.Create(() => Window.ToggleFileType(fileName)), }); } diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml b/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml index 16705695..58e06a1c 100644 --- a/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml @@ -8,7 +8,6 @@ xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Ryujinx.Ava.UI.Views.Main.MainStatusBarView" - x:CompileBindings="True" x:DataType="viewModels:MainWindowViewModel"> <Design.DataContext> <viewModels:MainWindowViewModel /> @@ -46,7 +45,7 @@ Margin="0,0,5,0" VerticalAlignment="Center" Background="Transparent" - Command="{ReflectionBinding LoadApplications}"> + Click="Refresh_OnClick"> <ui:SymbolIcon Width="50" Height="100" @@ -64,7 +63,7 @@ Grid.Column="2" Height="6" VerticalAlignment="Center" - Foreground="{DynamicResource HighlightColor}" + Foreground="{DynamicResource SystemAccentColorLight2}" IsVisible="{Binding StatusBarVisible}" Maximum="{Binding StatusBarProgressMaximum}" Value="{Binding StatusBarProgressValue}" /> @@ -93,6 +92,7 @@ Height="12" Margin="0" BorderBrush="Gray" + Background="Gray" BorderThickness="1" IsVisible="{Binding !ShowLoadProgress}" /> <TextBlock @@ -109,6 +109,7 @@ Height="12" Margin="0" BorderBrush="Gray" + Background="Gray" BorderThickness="1" IsVisible="{Binding !ShowLoadProgress}" /> <TextBlock @@ -125,20 +126,32 @@ Height="12" Margin="0" BorderBrush="Gray" + Background="Gray" BorderThickness="1" IsVisible="{Binding !ShowLoadProgress}" /> - <ui:ToggleSplitButton + <ToggleSplitButton Name="VolumeStatus" Padding="5,0,5,0" HorizontalAlignment="Left" VerticalAlignment="Center" VerticalContentAlignment="Center" - Background="{DynamicResource ThemeContentBackgroundColor}" - BorderThickness="0" Content="{Binding VolumeStatusText}" IsChecked="{Binding VolumeMuted}" - IsVisible="{Binding !ShowLoadProgress}"> - <ui:ToggleSplitButton.Flyout> + IsVisible="{Binding !ShowLoadProgress}" + Background="Transparent" + BorderThickness="0" + CornerRadius="0"> + <ToggleSplitButton.Styles> + <Style Selector=":checked"> + <Style Selector="^:checked ContentPresenter"> + <Setter Property="Foreground" Value="{DynamicResource ThemeForegroundColor}" /> + </Style> + </Style> + <Style Selector="Border#SeparatorBorder"> + <Setter Property="Opacity" Value="0" /> + </Style> + </ToggleSplitButton.Styles> + <ToggleSplitButton.Flyout> <Flyout Placement="Bottom" ShowMode="TransientWithDismissOnPointerMoveAway"> <Grid Margin="0"> <Slider @@ -156,13 +169,14 @@ Value="{Binding Volume}" /> </Grid> </Flyout> - </ui:ToggleSplitButton.Flyout> - </ui:ToggleSplitButton> + </ToggleSplitButton.Flyout> + </ToggleSplitButton> <Border Width="2" Height="12" Margin="0" BorderBrush="Gray" + Background="Gray" BorderThickness="1" IsVisible="{Binding !ShowLoadProgress}" /> <TextBlock @@ -177,6 +191,7 @@ Height="12" Margin="0" BorderBrush="Gray" + Background="Gray" BorderThickness="1" IsVisible="{Binding !ShowLoadProgress}" /> <TextBlock @@ -191,6 +206,7 @@ Height="12" Margin="0" BorderBrush="Gray" + Background="Gray" BorderThickness="1" IsVisible="{Binding !ShowLoadProgress}" /> <TextBlock @@ -205,6 +221,7 @@ Height="12" Margin="0" BorderBrush="Gray" + Background="Gray" BorderThickness="1" IsVisible="{Binding !ShowLoadProgress}" /> <TextBlock @@ -229,4 +246,4 @@ Text="{locale:Locale StatusBarSystemVersion}" /> </StackPanel> </Grid> -</UserControl>
\ No newline at end of file +</UserControl> diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs index 0640869c..a0acc277 100644 --- a/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs @@ -1,6 +1,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Input; +using Avalonia.Interactivity; using Ryujinx.Ava.UI.Windows; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; @@ -48,5 +49,10 @@ namespace Ryujinx.Ava.UI.Views.Main ConfigurationState.Instance.Graphics.AspectRatio.Value = (int)aspectRatio + 1 > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1; } + + private void Refresh_OnClick(object sender, RoutedEventArgs e) + { + Window.LoadApplications(); + } } } diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml b/src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml index f7dbf2b2..f5a17742 100644 --- a/src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml +++ b/src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml @@ -9,7 +9,6 @@ xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Ryujinx.Ava.UI.Views.Main.MainViewControls" - x:CompileBindings="True" x:DataType="viewModels:MainWindowViewModel"> <Design.DataContext> <viewModels:MainWindowViewModel /> @@ -23,7 +22,7 @@ MinWidth="40" Margin="5,2,0,2" VerticalAlignment="Stretch" - Command="{ReflectionBinding SetListMode}" + Command="{Binding SetListMode}" IsEnabled="{Binding IsGrid}"> <ui:FontIcon Margin="0" @@ -37,7 +36,7 @@ MinWidth="40" Margin="5,2,5,2" VerticalAlignment="Stretch" - Command="{ReflectionBinding SetGridMode}" + Command="{Binding SetGridMode}" IsEnabled="{Binding IsList}"> <ui:FontIcon Margin="0" @@ -79,13 +78,13 @@ KeyUp="SearchBox_OnKeyUp" Text="{Binding SearchText}" Watermark="{locale:Locale MenuSearch}" /> - <ui:DropDownButton + <DropDownButton Width="150" HorizontalAlignment="Right" VerticalAlignment="Center" Content="{Binding SortName}" DockPanel.Dock="Right"> - <ui:DropDownButton.Flyout> + <DropDownButton.Flyout> <Flyout Placement="Bottom"> <StackPanel Margin="0" @@ -164,8 +163,8 @@ Tag="Descending" /> </StackPanel> </Flyout> - </ui:DropDownButton.Flyout> - </ui:DropDownButton> + </DropDownButton.Flyout> + </DropDownButton> <TextBlock Margin="10,0" HorizontalAlignment="Right" diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml index 35283353..5dc0fef5 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml @@ -1,4 +1,4 @@ -<UserControl +<UserControl x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsAudioView" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" @@ -8,7 +8,6 @@ xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:SettingsViewModel"> <Design.DataContext> <viewModels:SettingsViewModel /> diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml index e98b963c..c74d3dd5 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml @@ -7,7 +7,6 @@ xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:SettingsViewModel"> <Design.DataContext> <viewModels:SettingsViewModel /> diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml index 670de69c..9dc67dad 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml @@ -1,4 +1,4 @@ -<UserControl +<UserControl x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsGraphicsView" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" @@ -9,7 +9,6 @@ xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" Design.Width="1000" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:SettingsViewModel"> <Design.DataContext> <viewModels:SettingsViewModel /> @@ -54,7 +53,7 @@ HorizontalContentAlignment="Left" ToolTip.Tip="{locale:Locale SettingsTabGraphicsPreferredGpuTooltip}" SelectedIndex="{Binding PreferredGpuIndex}" - Items="{Binding AvailableGpus}"/> + ItemsSource="{Binding AvailableGpus}"/> </StackPanel> </StackPanel> <Separator Height="1" /> diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml index 361125bf..a53c1dfe 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml @@ -1,4 +1,4 @@ -<UserControl +<UserControl x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsHotkeysView" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" @@ -8,7 +8,6 @@ xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:SettingsViewModel" Focusable="True"> <Design.DataContext> @@ -17,7 +16,7 @@ <UserControl.Resources> <helpers:KeyValueConverter x:Key="Key" /> </UserControl.Resources> - <ScrollViewer + <ScrollViewer Name="HotkeysPage" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs index 4bbd0133..b6f2d6c0 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs @@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Views.Settings { _currentAssigner = new ButtonKeyAssigner(button); - FocusManager.Instance?.Focus(this, NavigationMethod.Pointer); + this.Focus(NavigationMethod.Pointer); PointerPressed += MouseClick; diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml index 22ff38f5..81f4b68b 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml @@ -8,7 +8,6 @@ xmlns:views="clr-namespace:Ryujinx.Ava.UI.Views.Input" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:SettingsViewModel"> <Design.DataContext> <viewModels:SettingsViewModel /> diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml index 948e7181..0fc9ea1b 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml @@ -8,7 +8,6 @@ xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:SettingsViewModel"> <Design.DataContext> <viewModels:SettingsViewModel /> diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml index ab8a7f6d..6ce1bb94 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml @@ -7,7 +7,6 @@ xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:SettingsViewModel"> <Design.DataContext> <viewModels:SettingsViewModel /> @@ -37,7 +36,7 @@ <ComboBox SelectedIndex="{Binding NetworkInterfaceIndex}" ToolTip.Tip="{locale:Locale NetworkInterfaceTooltip}" HorizontalContentAlignment="Left" - Items="{Binding NetworkInterfaceList}" + ItemsSource="{Binding NetworkInterfaceList}" Width="250" /> </StackPanel> </StackPanel> diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml index cc60ef24..e6f7c6e4 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml @@ -3,12 +3,15 @@ xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" - x:CompileBindings="True" - x:DataType="viewModels:SettingsViewModel" - mc:Ignorable="d"> + xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" + mc:Ignorable="d" + x:DataType="viewModels:SettingsViewModel"> + <UserControl.Resources> + <helpers:TimeZoneConverter x:Key="TimeZone" /> + </UserControl.Resources> <Design.DataContext> <viewModels:SettingsViewModel /> </Design.DataContext> @@ -24,18 +27,24 @@ HorizontalAlignment="Stretch" Orientation="Vertical" Spacing="10"> - <TextBlock Classes="h1" Text="{locale:Locale SettingsTabSystemCore}" /> - <StackPanel Margin="10,0,0,0" Orientation="Vertical"> - <StackPanel Margin="0,0,0,10" Orientation="Horizontal"> + <TextBlock + Classes="h1" + Text="{locale:Locale SettingsTabSystemCore}" /> + <StackPanel + Margin="10,0,0,0" + Orientation="Vertical"> + <StackPanel + Margin="0,0,0,10" + Orientation="Horizontal"> <TextBlock - Width="250" VerticalAlignment="Center" - Text="{locale:Locale SettingsTabSystemSystemRegion}" /> + Text="{locale:Locale SettingsTabSystemSystemRegion}" + Width="250" /> <ComboBox - Width="350" - HorizontalContentAlignment="Left" SelectedIndex="{Binding Region}" - ToolTip.Tip="{locale:Locale RegionTooltip}"> + ToolTip.Tip="{locale:Locale RegionTooltip}" + HorizontalContentAlignment="Left" + Width="350"> <ComboBoxItem> <TextBlock Text="{locale:Locale SettingsTabSystemSystemRegionJapan}" /> </ComboBoxItem> @@ -59,17 +68,19 @@ </ComboBoxItem> </ComboBox> </StackPanel> - <StackPanel Margin="0,0,0,10" Orientation="Horizontal"> + <StackPanel + Margin="0,0,0,10" + Orientation="Horizontal"> <TextBlock - Width="250" VerticalAlignment="Center" Text="{locale:Locale SettingsTabSystemSystemLanguage}" - ToolTip.Tip="{locale:Locale LanguageTooltip}" /> + ToolTip.Tip="{locale:Locale LanguageTooltip}" + Width="250" /> <ComboBox - Width="350" - HorizontalContentAlignment="Left" SelectedIndex="{Binding Language}" - ToolTip.Tip="{locale:Locale LanguageTooltip}"> + ToolTip.Tip="{locale:Locale LanguageTooltip}" + HorizontalContentAlignment="Left" + Width="350"> <ComboBoxItem> <TextBlock Text="{locale:Locale SettingsTabSystemSystemLanguageJapanese}" /> </ComboBoxItem> @@ -126,63 +137,84 @@ </ComboBoxItem> </ComboBox> </StackPanel> - <StackPanel Margin="0,0,0,10" Orientation="Horizontal"> + <StackPanel + Margin="0,0,0,10" + Orientation="Horizontal"> <TextBlock - Width="250" VerticalAlignment="Center" Text="{locale:Locale SettingsTabSystemSystemTimeZone}" - ToolTip.Tip="{locale:Locale TimezoneTooltip}" /> + ToolTip.Tip="{locale:Locale TimezoneTooltip}" + Width="250" /> <AutoCompleteBox Name="TimeZoneBox" Width="350" - FilterMode="Contains" - Items="{Binding TimeZones}" MaxDropDownHeight="500" + FilterMode="Contains" + ItemsSource="{Binding TimeZones}" SelectionChanged="TimeZoneBox_OnSelectionChanged" Text="{Binding Path=TimeZone, Mode=OneWay}" TextChanged="TimeZoneBox_OnTextChanged" - ToolTip.Tip="{locale:Locale TimezoneTooltip}" /> + ToolTip.Tip="{locale:Locale TimezoneTooltip}" + ValueMemberBinding="{Binding Mode=OneWay, Converter={StaticResource TimeZone}}" /> </StackPanel> - <StackPanel Margin="0,0,0,10" Orientation="Horizontal"> + <StackPanel + Margin="0,0,0,10" + Orientation="Horizontal"> <TextBlock - Width="250" VerticalAlignment="Center" Text="{locale:Locale SettingsTabSystemSystemTime}" - ToolTip.Tip="{locale:Locale TimeTooltip}" /> + ToolTip.Tip="{locale:Locale TimeTooltip}" + Width="250"/> <DatePicker - Width="350" - VerticalAlignment="Center" + VerticalAlignment="Center" SelectedDate="{Binding CurrentDate}" - ToolTip.Tip="{locale:Locale TimeTooltip}" /> + ToolTip.Tip="{locale:Locale TimeTooltip}" + Width="350" /> </StackPanel> - <StackPanel Margin="250,0,0,10" Orientation="Horizontal"> + <StackPanel + Margin="250,0,0,10" + Orientation="Horizontal"> <TimePicker - Width="350" VerticalAlignment="Center" ClockIdentifier="24HourClock" SelectedTime="{Binding CurrentTime}" + Width="350" ToolTip.Tip="{locale:Locale TimeTooltip}" /> </StackPanel> <CheckBox IsChecked="{Binding EnableVsync}"> - <TextBlock Text="{locale:Locale SettingsTabSystemEnableVsync}" ToolTip.Tip="{locale:Locale VSyncToggleTooltip}" /> + <TextBlock + Text="{locale:Locale SettingsTabSystemEnableVsync}" + ToolTip.Tip="{locale:Locale VSyncToggleTooltip}" /> </CheckBox> <CheckBox IsChecked="{Binding EnableFsIntegrityChecks}"> - <TextBlock Text="{locale:Locale SettingsTabSystemEnableFsIntegrityChecks}" ToolTip.Tip="{locale:Locale FsIntegrityToggleTooltip}" /> + <TextBlock + Text="{locale:Locale SettingsTabSystemEnableFsIntegrityChecks}" + ToolTip.Tip="{locale:Locale FsIntegrityToggleTooltip}" /> </CheckBox> </StackPanel> <Separator Height="1" /> - <StackPanel Orientation="Vertical" Spacing="2"> - <TextBlock Classes="h1" Text="{locale:Locale SettingsTabSystemHacks}" /> - <TextBlock Foreground="{DynamicResource SecondaryTextColor}" Text="{locale:Locale SettingsTabSystemHacksNote}" /> + <StackPanel + Orientation="Vertical" + Spacing="2"> + <TextBlock + Classes="h1" + Text="{locale:Locale SettingsTabSystemHacks}" /> + <TextBlock + Foreground="{DynamicResource SecondaryTextColor}" + Text="{locale:Locale SettingsTabSystemHacksNote}" /> </StackPanel> <StackPanel Margin="10,0,0,0" HorizontalAlignment="Stretch" Orientation="Vertical"> - <CheckBox IsChecked="{Binding ExpandDramSize}" ToolTip.Tip="{locale:Locale DRamTooltip}"> + <CheckBox + IsChecked="{Binding ExpandDramSize}" + ToolTip.Tip="{locale:Locale DRamTooltip}"> <TextBlock Text="{locale:Locale SettingsTabSystemExpandDramSize}" /> </CheckBox> - <CheckBox IsChecked="{Binding IgnoreMissingServices}" ToolTip.Tip="{locale:Locale IgnoreMissingServicesTooltip}"> + <CheckBox + IsChecked="{Binding IgnoreMissingServices}" + ToolTip.Tip="{locale:Locale IgnoreMissingServicesTooltip}"> <TextBlock Text="{locale:Locale SettingsTabSystemIgnoreMissingServices}" /> </CheckBox> </StackPanel> diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs index 4acf2f44..216561dc 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs @@ -1,9 +1,5 @@ using Avalonia.Controls; -using Avalonia.Data; -using Avalonia.Data.Converters; using Ryujinx.Ava.UI.ViewModels; -using System; -using System.Linq; using TimeZone = Ryujinx.Ava.UI.Models.TimeZone; namespace Ryujinx.Ava.UI.Views.Settings @@ -15,15 +11,6 @@ namespace Ryujinx.Ava.UI.Views.Settings public SettingsSystemView() { InitializeComponent(); - - FuncMultiValueConverter<string, string> converter = new(parts => string.Format("{0} {1} {2}", parts.ToArray()).Trim()); - MultiBinding tzMultiBinding = new() { Converter = converter }; - - tzMultiBinding.Bindings.Add(new Binding("UtcDifference")); - tzMultiBinding.Bindings.Add(new Binding("Location")); - tzMultiBinding.Bindings.Add(new Binding("Abbreviation")); - - TimeZoneBox.ValueMemberBinding = tzMultiBinding; } private void TimeZoneBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) @@ -39,13 +26,11 @@ namespace Ryujinx.Ava.UI.Views.Settings } } - private void TimeZoneBox_OnTextChanged(object sender, EventArgs e) + private void TimeZoneBox_OnTextChanged(object sender, TextChangedEventArgs e) { if (sender is AutoCompleteBox box && box.SelectedItem is TimeZone timeZone) { - { - ViewModel.ValidateAndSetTimeZone(timeZone.Location); - } + ViewModel.ValidateAndSetTimeZone(timeZone.Location); } } } diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml index c92d5672..b7471d38 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml @@ -7,7 +7,6 @@ xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:SettingsViewModel"> <Design.DataContext> <viewModels:SettingsViewModel /> @@ -66,7 +65,7 @@ <ListBox Name="GameList" MinHeight="230" - Items="{Binding GameDirectories}"> + ItemsSource="{Binding GameDirectories}"> <ListBox.Styles> <Style Selector="ListBoxItem"> <Setter Property="Padding" Value="10" /> diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs index 132435e0..a38a8865 100644 --- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs @@ -1,7 +1,7 @@ -using Avalonia; using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Interactivity; +using Avalonia.Platform.Storage; +using Avalonia.VisualTree; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.ViewModels; using System.Collections.Generic; @@ -30,13 +30,16 @@ namespace Ryujinx.Ava.UI.Views.Settings } else { - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + if (this.GetVisualRoot() is Window window) { - path = await new OpenFolderDialog().ShowAsync(desktop.MainWindow); + var result = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions + { + AllowMultiple = false + }); - if (!string.IsNullOrWhiteSpace(path)) + if (result.Count > 0) { - ViewModel.GameDirectories.Add(path); + ViewModel.GameDirectories.Add(result[0].Path.LocalPath); ViewModel.DirectoryChanged = true; } } @@ -61,22 +64,25 @@ namespace Ryujinx.Ava.UI.Views.Settings public async void BrowseTheme(object sender, RoutedEventArgs e) { - var dialog = new OpenFileDialog + var window = this.GetVisualRoot() as Window; + var result = await window.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { Title = LocaleManager.Instance[LocaleKeys.SettingsSelectThemeFileDialogTitle], AllowMultiple = false, - }; - - dialog.Filters.Add(new FileDialogFilter { Extensions = { "xaml" }, Name = LocaleManager.Instance[LocaleKeys.SettingsXamlThemeFile] }); - - if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) - { - var file = await dialog.ShowAsync(desktop.MainWindow); - - if (file != null && file.Length > 0) + FileTypeFilter = new List<FilePickerFileType> { - ViewModel.CustomThemePath = file[0]; + new("xml") + { + Patterns = new[] { "*.xaml" }, + AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xaml" }, + MimeTypes = new[] { "application/xaml+xml" } + } } + }); + + if (result.Count > 0) + { + ViewModel.CustomThemePath = result[0].Path.LocalPath; } } } diff --git a/src/Ryujinx.Ava/UI/Views/User/UserEditorView.axaml b/src/Ryujinx.Ava/UI/Views/User/UserEditorView.axaml index 7e55f25e..ab83c2cd 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserEditorView.axaml +++ b/src/Ryujinx.Ava/UI/Views/User/UserEditorView.axaml @@ -13,7 +13,6 @@ Padding="0" mc:Ignorable="d" Focusable="True" - x:CompileBindings="True" x:DataType="models:TempProfile"> <UserControl.Resources> <helpers:BitmapArrayValueConverter x:Key="ByteImage" /> diff --git a/src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml b/src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml index d46fcefc..21dfc909 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml +++ b/src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml @@ -12,7 +12,6 @@ xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" - x:CompileBindings="True" x:DataType="viewModels:UserFirmwareAvatarSelectorViewModel" Focusable="True"> <Design.DataContext> @@ -36,7 +35,7 @@ BorderThickness="0" SelectedIndex="{Binding SelectedIndex}" Height="400" - Items="{Binding Images}" + ItemsSource="{Binding Images}" HorizontalAlignment="Stretch" VerticalAlignment="Center"> <ListBox.ItemsPanel> @@ -54,7 +53,7 @@ <Setter Property="MaxWidth" Value="85" /> <Setter Property="MinWidth" Value="85" /> </Style> - <Style Selector="ListBoxItem /template/ Border#SelectionIndicator"> + <Style Selector="ListBoxItem /template/ Rectangle#SelectionIndicator"> <Setter Property="MinHeight" Value="70" /> </Style> </ListBox.Styles> diff --git a/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml b/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml index b9f51fdc..65fbd443 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml +++ b/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml @@ -9,7 +9,6 @@ Focusable="True" mc:Ignorable="d" x:Class="Ryujinx.Ava.UI.Views.User.UserProfileImageSelectorView" - x:CompileBindings="True" x:DataType="viewModles:UserProfileImageSelectorViewModel" Width="500" d:DesignWidth="500"> diff --git a/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs b/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs index 26b77dcd..e9bf4408 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs +++ b/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs @@ -1,5 +1,6 @@ using Avalonia.Controls; using Avalonia.Interactivity; +using Avalonia.Platform.Storage; using Avalonia.VisualTree; using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Navigation; @@ -10,6 +11,7 @@ using Ryujinx.Ava.UI.ViewModels; using Ryujinx.HLE.FileSystem; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; +using System.Collections.Generic; using System.IO; using Image = SixLabors.ImageSharp.Image; @@ -63,33 +65,25 @@ namespace Ryujinx.Ava.UI.Views.User private async void Import_OnClick(object sender, RoutedEventArgs e) { - OpenFileDialog dialog = new(); - dialog.Filters.Add(new FileDialogFilter + var window = this.GetVisualRoot() as Window; + var result = await window.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { - Name = LocaleManager.Instance[LocaleKeys.AllSupportedFormats], - Extensions = { "jpg", "jpeg", "png", "bmp" }, - }); - dialog.Filters.Add(new FileDialogFilter { Name = "JPEG", Extensions = { "jpg", "jpeg" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "PNG", Extensions = { "png" } }); - dialog.Filters.Add(new FileDialogFilter { Name = "BMP", Extensions = { "bmp" } }); - - dialog.AllowMultiple = false; - - string[] image = await dialog.ShowAsync(((TopLevel)_parent.GetVisualRoot()) as Window); - - if (image != null) - { - if (image.Length > 0) + AllowMultiple = false, + FileTypeFilter = new List<FilePickerFileType> { - string imageFile = image[0]; - - _profile.Image = ProcessProfileImage(File.ReadAllBytes(imageFile)); - - if (_profile.Image != null) + new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) { - _parent.GoBack(); + Patterns = new[] { "*.jpg", "*.jpeg", "*.png", "*.bmp" }, + AppleUniformTypeIdentifiers = new[] { "public.jpeg", "public.png", "com.microsoft.bmp" }, + MimeTypes = new[] { "image/jpeg", "image/png", "image/bmp" } } } + }); + + if (result.Count > 0) + { + _profile.Image = ProcessProfileImage(File.ReadAllBytes(result[0].Path.LocalPath)); + _parent.GoBack(); } } diff --git a/src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml b/src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml index 62b5e184..debf4b84 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml +++ b/src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml @@ -12,7 +12,6 @@ xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" x:Class="Ryujinx.Ava.UI.Views.User.UserRecovererView" - x:CompileBindings="True" x:DataType="viewModels:UserProfileViewModel" Focusable="True"> <Design.DataContext> @@ -33,7 +32,7 @@ <ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - Items="{Binding LostProfiles}"> + ItemsSource="{Binding LostProfiles}"> <ListBox.ItemTemplate> <DataTemplate> <Border diff --git a/src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml b/src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml index ec931dd9..8bc5125a 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml +++ b/src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml @@ -14,7 +14,6 @@ Height="450" Width="550" x:Class="Ryujinx.Ava.UI.Views.User.UserSaveManagerView" - x:CompileBindings="True" x:DataType="viewModels:UserSaveManagerViewModel" Focusable="True"> <Design.DataContext> @@ -107,8 +106,7 @@ VerticalAlignment="Stretch"> <ListBox Name="SaveList" - VirtualizationMode="None" - Items="{Binding Views}" + ItemsSource="{Binding Views}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <ListBox.Styles> @@ -117,7 +115,7 @@ <Setter Property="Margin" Value="5" /> <Setter Property="CornerRadius" Value="4" /> </Style> - <Style Selector="ListBoxItem:selected /template/ Border#SelectionIndicator"> + <Style Selector="ListBoxItem:selected /template/ Rectangle#SelectionIndicator"> <Setter Property="IsVisible" Value="False" /> </Style> </ListBox.Styles> diff --git a/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml b/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml index 9a6ba054..818a21d6 100644 --- a/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml +++ b/src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml @@ -15,7 +15,6 @@ d:DesignWidth="800" mc:Ignorable="d" Focusable="True" - x:CompileBindings="True" x:DataType="viewModels:UserProfileViewModel"> <UserControl.Resources> <helpers:BitmapArrayValueConverter x:Key="ByteImage" /> @@ -38,7 +37,7 @@ VerticalAlignment="Center" SelectionChanged="ProfilesList_SelectionChanged" Background="Transparent" - Items="{Binding Profiles}"> + ItemsSource="{Binding Profiles}"> <ListBox.ItemsPanel> <ItemsPanelTemplate> <flex:FlexPanel @@ -53,7 +52,7 @@ <Setter Property="Margin" Value="5 5 0 5" /> <Setter Property="CornerRadius" Value="5" /> </Style> - <Style Selector="Border#SelectionIndicator"> + <Style Selector="Rectangle#SelectionIndicator"> <Setter Property="Opacity" Value="0" /> </Style> </ListBox.Styles> @@ -61,8 +60,8 @@ <DataTemplate DataType="models:UserProfile"> <Grid - PointerEnter="Grid_PointerEntered" - PointerLeave="Grid_OnPointerExited"> + PointerEntered="Grid_PointerEntered" + PointerExited="Grid_OnPointerExited"> <Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" diff --git a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml index cc7556a6..a8fd11b2 100644 --- a/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml @@ -13,7 +13,6 @@ Margin="0,-12,0,0" d:DesignHeight="260" d:DesignWidth="550" - x:CompileBindings="True" x:DataType="viewModel:AboutWindowViewModel" Focusable="True" mc:Ignorable="d"> @@ -64,14 +63,14 @@ FontWeight="Bold" Text="Ryujinx" TextAlignment="Center" - Width="100" /> + Width="110" /> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="11" Text="(REE-YOU-JINX)" TextAlignment="Center" - Width="100" /> + Width="110" /> </flex:FlexPanel> </Grid> <TextBlock @@ -265,4 +264,4 @@ </StackPanel> </Grid> </Grid> -</UserControl>
\ No newline at end of file +</UserControl> diff --git a/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml b/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml index 90d47b8e..caf7c1f3 100644 --- a/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml @@ -1,4 +1,4 @@ -<window:StyleableWindow +<window:StyleableWindow xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" @@ -6,14 +6,15 @@ xmlns:window="clr-namespace:Ryujinx.Ava.UI.Windows" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" - mc:Ignorable="d" - d:DesignWidth="400" + mc:Ignorable="d" + d:DesignWidth="400" d:DesignHeight="350" x:Class="Ryujinx.Ava.UI.Windows.AmiiboWindow" + x:DataType="viewModels:AmiiboWindowViewModel" CanResize="False" WindowStartupLocation="CenterOwner" - Width="800" - MinHeight="650" + Width="800" + MinHeight="650" Height="650" SizeToContent="Manual" MinWidth="600" @@ -35,11 +36,11 @@ </Grid.ColumnDefinitions> <StackPanel Spacing="10" Orientation="Horizontal" HorizontalAlignment="Left"> <TextBlock VerticalAlignment="Center" Text="{locale:Locale AmiiboSeriesLabel}" /> - <ComboBox SelectedIndex="{Binding SeriesSelectedIndex}" Items="{Binding AmiiboSeries}" MinWidth="100" /> + <ComboBox SelectedIndex="{Binding SeriesSelectedIndex}" ItemsSource="{Binding AmiiboSeries}" MinWidth="100" /> </StackPanel> <StackPanel Spacing="10" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right"> <TextBlock VerticalAlignment="Center" Text="{locale:Locale AmiiboCharacterLabel}" /> - <ComboBox SelectedIndex="{Binding AmiiboSelectedIndex}" MinWidth="100" Items="{Binding AmiiboList}" /> + <ComboBox SelectedIndex="{Binding AmiiboSelectedIndex}" MinWidth="100" ItemsSource="{Binding AmiiboList}" /> </StackPanel> </Grid> <StackPanel Margin="20" Grid.Row="2"> diff --git a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml index 11e86211..b9cbcb9c 100644 --- a/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml @@ -40,7 +40,7 @@ HorizontalAlignment="Center" VerticalAlignment="Center" LineHeight="18" - Text="{Binding Heading}" + Text="{ReflectionBinding Heading}" TextAlignment="Center" TextWrapping="Wrap" /> <TextBlock @@ -61,7 +61,7 @@ MinWidth="160" HorizontalAlignment="Center" VerticalAlignment="Center" - Text="{Binding BuildId}" + Text="{ReflectionBinding BuildId}" IsReadOnly="True" /> <Border Grid.Row="3" @@ -77,7 +77,7 @@ MinHeight="300" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - Items="{Binding LoadedCheats}"> + ItemsSource="{ReflectionBinding LoadedCheats}"> <TreeView.Styles> <Styles> <Style Selector="TreeViewItem:empty /template/ ItemsPresenter"> @@ -120,15 +120,15 @@ Name="SaveButton" MinWidth="90" Margin="5" - Command="{Binding Save}" - IsVisible="{Binding !NoCheatsFound}"> + Command="{ReflectionBinding Save}" + IsVisible="{ReflectionBinding !NoCheatsFound}"> <TextBlock Text="{locale:Locale SettingsButtonSave}" /> </Button> <Button Name="CancelButton" MinWidth="90" Margin="5" - Command="{Binding Close}"> + Command="{ReflectionBinding Close}"> <TextBlock Text="{locale:Locale InputDialogCancel}" /> </Button> </DockPanel> diff --git a/src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs index a33ee518..2b12d72f 100644 --- a/src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs @@ -1,8 +1,5 @@ using Avalonia.Controls; using Avalonia.Media; -#if DEBUG -using Avalonia; -#endif namespace Ryujinx.Ava.UI.Windows { @@ -11,11 +8,9 @@ namespace Ryujinx.Ava.UI.Windows public ContentDialogOverlayWindow() { InitializeComponent(); -#if DEBUG - this.AttachDevTools(); -#endif + ExtendClientAreaToDecorationsHint = true; - TransparencyLevelHint = WindowTransparencyLevel.Transparent; + TransparencyLevelHint = new[] { WindowTransparencyLevel.Transparent }; WindowStartupLocation = WindowStartupLocation.Manual; SystemDecorations = SystemDecorations.None; ExtendClientAreaTitleBarHeightHint = 0; diff --git a/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml b/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml index f4ba4f9c..1f57f34c 100644 --- a/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml @@ -11,7 +11,6 @@ Width="500" Height="380" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:DownloadableContentManagerViewModel" Focusable="True"> <Grid> @@ -53,8 +52,8 @@ </StackPanel> <TextBox Grid.Column="2" - MinHeight="27" - MaxHeight="27" + MinHeight="29" + MaxHeight="29" HorizontalAlignment="Stretch" Watermark="{locale:Locale Search}" Text="{Binding Search}" /> @@ -71,12 +70,11 @@ Padding="2.5"> <ListBox AutoScrollToSelectedItem="False" - VirtualizationMode="None" SelectionMode="Multiple, Toggle" Background="Transparent" SelectionChanged="OnSelectionChanged" SelectedItems="{Binding SelectedDownloadableContents, Mode=TwoWay}" - Items="{Binding Views}"> + ItemsSource="{Binding Views}"> <ListBox.DataTemplates> <DataTemplate DataType="models:DownloadableContentModel"> diff --git a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml index fa07d977..0d9a5949 100644 --- a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml @@ -18,9 +18,9 @@ MinHeight="672" d:DesignHeight="720" d:DesignWidth="1280" - x:CompileBindings="True" x:DataType="viewModels:MainWindowViewModel" mc:Ignorable="d" + WindowStartupLocation="Manual" Focusable="True"> <Window.Styles> <Style Selector="TitleBar:fullscreen"> @@ -33,19 +33,19 @@ <Window.Resources> <helpers:BitmapArrayValueConverter x:Key="ByteImage" /> </Window.Resources> + <Window.KeyBindings> + <KeyBinding Gesture="Alt+Return" Command="{Binding ToggleFullscreen}" /> + <KeyBinding Gesture="F11" Command="{Binding ToggleFullscreen}" /> + <KeyBinding Gesture="Ctrl+Cmd+F" Command="{Binding ToggleFullscreen}" /> + <KeyBinding Gesture="F9" Command="{Binding ToggleDockMode}" /> + <KeyBinding Gesture="Escape" Command="{Binding ExitCurrentState}" /> + </Window.KeyBindings> <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <helpers:OffscreenTextBox Name="HiddenTextBox" Grid.Row="0" /> - <StackPanel Grid.Row="0" IsVisible="False"> - <helpers:HotKeyControl Name="FullscreenHotKey" Command="{ReflectionBinding ToggleFullscreen}" /> - <helpers:HotKeyControl Name="FullscreenHotKey2" Command="{ReflectionBinding ToggleFullscreen}" /> - <helpers:HotKeyControl Name="FullscreenHotKeyMacOS" Command="{ReflectionBinding ToggleFullscreen}" /> - <helpers:HotKeyControl Name="DockToggleHotKey" Command="{ReflectionBinding ToggleDockMode}" /> - <helpers:HotKeyControl Name="ExitHotKey" Command="{ReflectionBinding ExitCurrentState}" /> - </StackPanel> <Grid Grid.Row="1" HorizontalAlignment="Stretch" @@ -67,7 +67,7 @@ VerticalAlignment="Stretch" IsVisible="{Binding ShowMenuAndStatusBar}" Orientation="Vertical"> - <main:MainMenuBarView + <main:MainMenuBarView Name="MenuBarView" /> </StackPanel> <ContentControl @@ -197,7 +197,7 @@ </Grid> </Grid> </Grid> - <main:MainStatusBarView + <main:MainStatusBarView Name="StatusBarView" Grid.Row="2" /> </Grid> diff --git a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs index d79bdc56..d32360e0 100644 --- a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs @@ -1,6 +1,7 @@ using Avalonia; using Avalonia.Controls; -using Avalonia.Input; +using Avalonia.Controls.Primitives; +using Avalonia.Interactivity; using Avalonia.Threading; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common; @@ -21,7 +22,6 @@ using Ryujinx.Ui.Common; using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Helper; using System; -using System.ComponentModel; using System.IO; using System.Runtime.Versioning; using System.Threading.Tasks; @@ -85,6 +85,7 @@ namespace Ryujinx.Ava.UI.Windows ViewModel.Initialize( ContentManager, + StorageProvider, ApplicationLibrary, VirtualFileSystem, AccountManager, @@ -102,11 +103,16 @@ namespace Ryujinx.Ava.UI.Windows LoadGameList(); this.GetObservable(IsActiveProperty).Subscribe(IsActiveChanged); + this.ScalingChanged += OnScalingChanged; } ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated; ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded; - ViewModel.ReloadGameList += ReloadGameList; + } + + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); NotificationHelper.SetNotificationManager(this); } @@ -130,10 +136,9 @@ namespace Ryujinx.Ava.UI.Windows _isLoading = false; } - protected override void HandleScalingChanged(double scale) + private void OnScalingChanged(object sender, EventArgs e) { - Program.DesktopScaleFactor = scale; - base.HandleScalingChanged(scale); + Program.DesktopScaleFactor = this.RenderScaling; } public void AddApplication(ApplicationData applicationData) @@ -221,16 +226,6 @@ namespace Ryujinx.Ava.UI.Windows }); } - protected override void HandleWindowStateChanged(WindowState state) - { - ViewModel.WindowState = state; - - if (state != WindowState.Minimized) - { - Renderer.Start(); - } - } - private void Initialize() { _userChannelPersistence = new UserChannelPersistence(); @@ -367,14 +362,12 @@ namespace Ryujinx.Ava.UI.Windows ApplicationList.ApplicationOpened += Application_Opened; ApplicationList.DataContext = ViewModel; - - LoadHotKeys(); } private void SetWindowSizePosition() { PixelPoint savedPoint = new(ConfigurationState.Instance.Ui.WindowStartup.WindowPositionX, - ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY); + ConfigurationState.Instance.Ui.WindowStartup.WindowPositionY); ViewModel.WindowHeight = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight * Program.WindowScaleFactor; ViewModel.WindowWidth = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth * Program.WindowScaleFactor; @@ -447,18 +440,7 @@ namespace Ryujinx.Ava.UI.Windows #pragma warning restore IDE0055 } - public void LoadHotKeys() - { -#pragma warning disable IDE0055 // Disable formatting - HotKeyManager.SetHotKey(FullscreenHotKey, new KeyGesture(Key.Enter, KeyModifiers.Alt)); - HotKeyManager.SetHotKey(FullscreenHotKey2, new KeyGesture(Key.F11)); - HotKeyManager.SetHotKey(FullscreenHotKeyMacOS, new KeyGesture(Key.F, KeyModifiers.Control | KeyModifiers.Meta)); - HotKeyManager.SetHotKey(DockToggleHotKey, new KeyGesture(Key.F9)); - HotKeyManager.SetHotKey(ExitHotKey, new KeyGesture(Key.Escape)); -#pragma warning restore IDE0055 - } - - private void VolumeStatus_CheckedChanged(object sender, SplitButtonClickEventArgs e) + private void VolumeStatus_CheckedChanged(object sender, RoutedEventArgs e) { var volumeSplitButton = sender as ToggleSplitButton; if (ViewModel.IsGameRunning) @@ -476,7 +458,7 @@ namespace Ryujinx.Ava.UI.Windows } } - protected override void OnClosing(CancelEventArgs e) + protected override void OnClosing(WindowClosingEventArgs e) { if (!ViewModel.IsClosing && ViewModel.AppHost != null && ConfigurationState.Instance.ShowConfirmExit) { @@ -548,6 +530,25 @@ namespace Ryujinx.Ava.UI.Windows ReloadGameList(); } + public void ToggleFileType(string fileType) + { + _ = fileType switch + { +#pragma warning disable IDE0055 // Disable formatting + "NSP" => ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NSP, + "PFS0" => ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.PFS0, + "XCI" => ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.XCI, + "NCA" => ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NCA, + "NRO" => ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NRO, + "NSO" => ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NSO, + _ => throw new ArgumentOutOfRangeException(fileType), +#pragma warning restore IDE0055 + }; + + ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); + LoadApplications(); + } + private void ReloadGameList() { if (_isLoading) diff --git a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml index 4b248db7..a0a75f61 100644 --- a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml @@ -15,7 +15,6 @@ MinWidth="800" MinHeight="480" WindowStartupLocation="CenterOwner" - x:CompileBindings="True" x:DataType="viewModels:SettingsViewModel" mc:Ignorable="d" Focusable="True"> @@ -59,44 +58,44 @@ IsSelected="True" Content="{locale:Locale SettingsTabGeneral}" Tag="UiPage" - Icon="New" /> + IconSource="New" /> <ui:NavigationViewItem Content="{locale:Locale SettingsTabInput}" Tag="InputPage" - Icon="Games" /> + IconSource="Games" /> <ui:NavigationViewItem Content="{locale:Locale SettingsTabHotkeys}" Tag="HotkeysPage" - Icon="Keyboard" /> + IconSource="Keyboard" /> <ui:NavigationViewItem Content="{locale:Locale SettingsTabSystem}" Tag="SystemPage" - Icon="Settings" /> + IconSource="Settings" /> <ui:NavigationViewItem Content="{locale:Locale SettingsTabCpu}" Tag="CpuPage"> - <ui:NavigationViewItem.Icon> - <ui:FontIcon + <ui:NavigationViewItem.IconSource> + <ui:FontIconSource FontFamily="avares://Ryujinx.Ava/Assets/Fonts#Segoe Fluent Icons" Glyph="{helpers:GlyphValueConverter Chip}" /> - </ui:NavigationViewItem.Icon> + </ui:NavigationViewItem.IconSource> </ui:NavigationViewItem> <ui:NavigationViewItem Content="{locale:Locale SettingsTabGraphics}" Tag="GraphicsPage" - Icon="Image" /> + IconSource="Image" /> <ui:NavigationViewItem Content="{locale:Locale SettingsTabAudio}" - Icon="Audio" + IconSource="Audio" Tag="AudioPage" /> <ui:NavigationViewItem Content="{locale:Locale SettingsTabNetwork}" Tag="NetworkPage" - Icon="Globe" /> + IconSource="Globe" /> <ui:NavigationViewItem Content="{locale:Locale SettingsTabLogging}" Tag="LoggingPage" - Icon="Document" /> + IconSource="Document" /> </ui:NavigationView.MenuItems> <ui:NavigationView.Styles> <Style Selector="Grid#PlaceholderGrid"> @@ -115,14 +114,14 @@ HotKey="Enter" Classes="accent" Content="{locale:Locale SettingsButtonOk}" - Command="{ReflectionBinding OkButton}" /> + Command="{Binding OkButton}" /> <Button HotKey="Escape" Content="{locale:Locale SettingsButtonCancel}" - Command="{ReflectionBinding CancelButton}" /> + Command="{Binding CancelButton}" /> <Button Content="{locale:Locale SettingsButtonApply}" - Command="{ReflectionBinding ApplyButton}" /> + Command="{Binding ApplyButton}" /> </ReversibleStackPanel> </Grid> </window:StyleableWindow> diff --git a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs index 518c2d32..d7bb0b88 100644 --- a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs @@ -1,10 +1,10 @@ +using Avalonia.Controls; using FluentAvalonia.Core; using FluentAvalonia.UI.Controls; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.HLE.FileSystem; using System; -using System.ComponentModel; namespace Ryujinx.Ava.UI.Windows { @@ -41,7 +41,7 @@ namespace Ryujinx.Ava.UI.Windows if (Owner is MainWindow window && ViewModel.DirectoryChanged) { - window.ViewModel.LoadApplications(); + window.LoadApplications(); } } @@ -93,7 +93,7 @@ namespace Ryujinx.Ava.UI.Windows } } - protected override void OnClosing(CancelEventArgs e) + protected override void OnClosing(WindowClosingEventArgs e) { HotkeysPage.Dispose(); InputPage.Dispose(); diff --git a/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs b/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs index ca23a5ba..43e42804 100644 --- a/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs +++ b/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs @@ -11,12 +11,12 @@ namespace Ryujinx.Ava.UI.Windows { public class StyleableWindow : Window { - public IBitmap IconImage { get; set; } + public Bitmap IconImage { get; set; } public StyleableWindow() { WindowStartupLocation = WindowStartupLocation.CenterOwner; - TransparencyLevelHint = WindowTransparencyLevel.None; + TransparencyLevelHint = new[] { WindowTransparencyLevel.None }; using Stream stream = Assembly.GetAssembly(typeof(ConfigurationState)).GetManifestResourceStream("Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png"); diff --git a/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml b/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml index e9858038..78fc6b28 100644 --- a/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml +++ b/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml @@ -11,7 +11,6 @@ Width="500" Height="300" mc:Ignorable="d" - x:CompileBindings="True" x:DataType="viewModels:TitleUpdateViewModel" Focusable="True"> <Grid> @@ -29,10 +28,9 @@ CornerRadius="5" Padding="2.5"> <ListBox - VirtualizationMode="None" Background="Transparent" SelectedItem="{Binding SelectedUpdate, Mode=TwoWay}" - Items="{Binding Views}"> + ItemsSource="{Binding Views}"> <ListBox.DataTemplates> <DataTemplate DataType="models:TitleUpdateModel"> @@ -103,7 +101,7 @@ <Button Name="AddButton" MinWidth="90" - Command="{ReflectionBinding Add}"> + Command="{Binding Add}"> <TextBlock Text="{locale:Locale SettingsTabGeneralAdd}" /> </Button> <Button diff --git a/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs index f4fcad31..7ece6335 100644 --- a/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs +++ b/src/Ryujinx.Ava/UI/Windows/TitleUpdateWindow.axaml.cs @@ -61,7 +61,7 @@ namespace Ryujinx.Ava.UI.Windows if (VisualRoot is MainWindow window) { - window.ViewModel.LoadApplications(); + window.LoadApplications(); } ((ContentDialog)Parent).Hide(); diff --git a/src/Ryujinx.Ava/app.manifest b/src/Ryujinx.Ava/app.manifest new file mode 100644 index 00000000..920136fb --- /dev/null +++ b/src/Ryujinx.Ava/app.manifest @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> + <assemblyIdentity version="1.0.0.0" name="Ryujinx.Emulator.Avalonia"/> + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- Windows 10 & 11 --> + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> + </application> + </compatibility> +</assembly> |