mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-05-26 06:59:15 +00:00
refactor: completely overhaul app icon management for cleaner workflow
This commit is contained in:
@@ -1,28 +1,84 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Media.Imaging;
|
using Avalonia.Media.Imaging;
|
||||||
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Common;
|
||||||
using System.Reflection;
|
using Svg.Skia;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Controls
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
public class RyujinxLogo : Image
|
public class RyujinxLogo : Image
|
||||||
{
|
{
|
||||||
// The UI specifically uses a thicker bordered variant of the icon to avoid crunching out the border at lower resolutions.
|
public static ReactiveObject<Bitmap> CurrentLogoBitmap { get; private set; } = new();
|
||||||
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
|
|
||||||
// The border gets reduced to colored pixels in the 4 corners.
|
|
||||||
public static readonly Bitmap Bitmap =
|
|
||||||
new(Assembly.GetAssembly(typeof(MainWindowViewModel))!
|
|
||||||
.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
|
|
||||||
|
|
||||||
public RyujinxLogo()
|
public RyujinxLogo()
|
||||||
{
|
{
|
||||||
Margin = new Thickness(7, 7, 7, 0);
|
Margin = new Thickness(7, 7, 7, 0);
|
||||||
Height = 25;
|
Height = 25;
|
||||||
Width = 25;
|
Width = 25;
|
||||||
Source = Bitmap;
|
Source = CurrentLogoBitmap.Value;
|
||||||
IsVisible = !ConfigurationState.Instance.ShowOldUI;
|
IsVisible = !ConfigurationState.Instance.ShowOldUI;
|
||||||
|
ConfigurationState.Instance.UI.SelectedWindowIcon.Event += WindowIconChanged_Event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void RefreshAppIconFromSettings()
|
||||||
|
{
|
||||||
|
SetNewAppIcon(ConfigurationState.Instance.UI.SelectedWindowIcon.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetNewAppIcon(string newIconName)
|
||||||
|
{
|
||||||
|
string defaultIconName = "Bordered Ryupride";
|
||||||
|
if (string.IsNullOrEmpty(newIconName))
|
||||||
|
{
|
||||||
|
SetDefaultAppIcon(defaultIconName);
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationIcon selectedIcon = RyujinxApp.AvailableApplicationIcons.FirstOrDefault(x => x.Name == newIconName);
|
||||||
|
if (selectedIcon == null)
|
||||||
|
{
|
||||||
|
// Always try to fallback to "Bordered Ryupride" as a default
|
||||||
|
// If not found, fallback to first found icon
|
||||||
|
if (newIconName != defaultIconName)
|
||||||
|
{
|
||||||
|
SetDefaultAppIcon(defaultIconName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RyujinxApp.AvailableApplicationIcons.Count > 0)
|
||||||
|
{
|
||||||
|
SetDefaultAppIcon(RyujinxApp.AvailableApplicationIcons.First().Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream activeIconStream = EmbeddedResources.GetStream(selectedIcon.FullPath);
|
||||||
|
if (activeIconStream != null)
|
||||||
|
{
|
||||||
|
// SVG files need to be converted to an image first
|
||||||
|
if (selectedIcon.FullPath.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// TODO: Convert SVG to a bitmap
|
||||||
|
using SKSvg svg = new();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CurrentLogoBitmap.Value = new Bitmap(activeIconStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetDefaultAppIcon(string defaultIconName)
|
||||||
|
{
|
||||||
|
// Doing this triggers the WindowIconChanged_Event, which will then
|
||||||
|
// call SetNewAppIcon again
|
||||||
|
ConfigurationState.Instance.UI.SelectedWindowIcon.Value = defaultIconName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WindowIconChanged_Event(object _, ReactiveEventArgs<string> rArgs) => SetNewAppIcon(rArgs.NewValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Avalonia;
|
|||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Input.Platform;
|
using Avalonia.Input.Platform;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
@@ -11,6 +10,7 @@ using Gommon;
|
|||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Common.Models;
|
using Ryujinx.Ava.Common.Models;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
|
using Ryujinx.Ava.UI.Controls;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Views.Dialog;
|
using Ryujinx.Ava.UI.Views.Dialog;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
@@ -58,6 +58,7 @@ namespace Ryujinx.Ava
|
|||||||
Name = FormatTitle();
|
Name = FormatTitle();
|
||||||
|
|
||||||
RetrieveAvailableAppIcons();
|
RetrieveAvailableAppIcons();
|
||||||
|
RyujinxLogo.RefreshAppIconFromSettings();
|
||||||
|
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
|
||||||
@@ -80,9 +81,6 @@ namespace Ryujinx.Ava
|
|||||||
{
|
{
|
||||||
ApplyConfiguredTheme(ConfigurationState.Instance.UI.BaseStyle);
|
ApplyConfiguredTheme(ConfigurationState.Instance.UI.BaseStyle);
|
||||||
ConfigurationState.Instance.UI.BaseStyle.Event += ThemeChanged_Event;
|
ConfigurationState.Instance.UI.BaseStyle.Event += ThemeChanged_Event;
|
||||||
|
|
||||||
UpdateAppIcon(ConfigurationState.Instance.UI.SelectedWindowIcon);
|
|
||||||
ConfigurationState.Instance.UI.SelectedWindowIcon.Event += WindowIconChanged_Event;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,28 +180,5 @@ namespace Ryujinx.Ava
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UpdateAppIcon(string newIconName)
|
|
||||||
{
|
|
||||||
if (newIconName.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
newIconName = "Classic Ryugay";
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplicationIcon selectedIcon = AvailableApplicationIcons.FirstOrDefault(x => x.Name == newIconName);
|
|
||||||
if (selectedIcon == null)
|
|
||||||
{
|
|
||||||
// Fallback to default icon if the selected one is not found
|
|
||||||
UpdateAppIcon("Classic Ryugay");
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream activeIconStream = EmbeddedResources.GetStream(selectedIcon.FullPath);
|
|
||||||
if (activeIconStream != null)
|
|
||||||
{
|
|
||||||
MainWindow.Icon = new Bitmap(activeIconStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WindowIconChanged_Event(object _, ReactiveEventArgs<string> rArgs) => UpdateAppIcon(rArgs.NewValue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using FluentAvalonia.UI.Windowing;
|
using FluentAvalonia.UI.Windowing;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Systems.Configuration;
|
using Ryujinx.Ava.Systems.Configuration;
|
||||||
using Ryujinx.Ava.UI.Controls;
|
using Ryujinx.Ava.UI.Controls;
|
||||||
|
using Ryujinx.Common;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Windows
|
namespace Ryujinx.Ava.UI.Windows
|
||||||
@@ -39,7 +41,8 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
TitleBar.Height = titleBarHeight.Value;
|
TitleBar.Height = titleBarHeight.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Icon = RyujinxLogo.Bitmap;
|
Icon = RyujinxLogo.CurrentLogoBitmap.Value;
|
||||||
|
RyujinxLogo.CurrentLogoBitmap.Event += WindowIconChanged_Event;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LocaleChanged()
|
private void LocaleChanged()
|
||||||
@@ -53,6 +56,12 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome | ExtendClientAreaChromeHints.OSXThickTitleBar;
|
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome | ExtendClientAreaChromeHints.OSXThickTitleBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WindowIconChanged_Event(object _, ReactiveEventArgs<Bitmap> rArgs) => UpdateIcon(rArgs.NewValue);
|
||||||
|
private void UpdateIcon(Bitmap newIcon)
|
||||||
|
{
|
||||||
|
Icon = newIcon;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class StyleableWindow : Window
|
public abstract class StyleableWindow : Window
|
||||||
@@ -73,7 +82,8 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
LocaleManager.Instance.LocaleChanged += LocaleChanged;
|
LocaleManager.Instance.LocaleChanged += LocaleChanged;
|
||||||
LocaleChanged();
|
LocaleChanged();
|
||||||
|
|
||||||
Icon = new WindowIcon(RyujinxLogo.Bitmap);
|
Icon = new WindowIcon(RyujinxLogo.CurrentLogoBitmap.Value);
|
||||||
|
RyujinxLogo.CurrentLogoBitmap.Event += WindowIconChanged_Event;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LocaleChanged()
|
private void LocaleChanged()
|
||||||
@@ -87,5 +97,11 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome | ExtendClientAreaChromeHints.OSXThickTitleBar;
|
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome | ExtendClientAreaChromeHints.OSXThickTitleBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WindowIconChanged_Event(object _, ReactiveEventArgs<Bitmap> rArgs) => UpdateIcon(rArgs.NewValue);
|
||||||
|
private void UpdateIcon(Bitmap newIcon)
|
||||||
|
{
|
||||||
|
Icon = new WindowIcon(newIcon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user