UI: Upgrade to Avalonia 11 release

This commit is contained in:
Sour 2023-07-07 17:26:01 +09:00
parent 6798a22fee
commit 3e36c3949e
37 changed files with 132 additions and 141 deletions

View file

@ -10,9 +10,9 @@ using System;
namespace Mesen.Controls
{
public class ButtonWithIcon : Button, IStyleable
public class ButtonWithIcon : Button
{
Type IStyleable.StyleKey => typeof(Button);
protected override Type StyleKeyOverride => typeof(Button);
public static readonly StyledProperty<string> TextProperty = AvaloniaProperty.Register<ButtonWithIcon, string>(nameof(Text), "");
public static readonly StyledProperty<string> IconProperty = AvaloniaProperty.Register<ButtonWithIcon, string>(nameof(Icon), "");

View file

@ -70,9 +70,9 @@ namespace Mesen.Controls
AvaloniaXamlLoader.Load(this);
}
protected override void OnLoaded()
protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded();
base.OnLoaded(e);
InitComboBox(true);
}

View file

@ -9,9 +9,9 @@ using Mesen.Localization;
namespace Mesen.Controls
{
public class EnumRadioButton : RadioButton, IStyleable
public class EnumRadioButton : RadioButton
{
Type IStyleable.StyleKey => typeof(RadioButton);
protected override Type StyleKeyOverride => typeof(RadioButton);
public static readonly StyledProperty<Enum> ValueProperty = AvaloniaProperty.Register<EnumRadioButton, Enum>(nameof(Value), defaultBindingMode: BindingMode.TwoWay);
public static readonly StyledProperty<Enum> CheckedWhenProperty = AvaloniaProperty.Register<EnumRadioButton, Enum>(nameof(CheckedWhen));

View file

@ -10,9 +10,9 @@ using System;
namespace Mesen.Controls
{
public class IconButton : Button, IStyleable
public class IconButton : Button
{
Type IStyleable.StyleKey => typeof(Button);
protected override Type StyleKeyOverride => typeof(Button);
public static readonly StyledProperty<string> IconProperty = AvaloniaProperty.Register<KeyBindingButton, string>(nameof(Icon), "");

View file

@ -9,9 +9,9 @@ using System.Globalization;
namespace Mesen.Controls
{
public class ImageAspectRatio : Image, IStyleable
public class ImageAspectRatio : Image
{
Type IStyleable.StyleKey => typeof(Image);
protected override Type StyleKeyOverride => typeof(Image);
public ImageAspectRatio()
{

View file

@ -13,9 +13,9 @@ using System;
namespace Mesen.Controls
{
public class KeyBindingButton : Button, IStyleable
public class KeyBindingButton : Button
{
Type IStyleable.StyleKey => typeof(Button);
protected override Type StyleKeyOverride => typeof(Button);
public static readonly StyledProperty<UInt16> KeyBindingProperty = AvaloniaProperty.Register<KeyBindingButton, UInt16>(nameof(KeyBinding), 0, false, Avalonia.Data.BindingMode.TwoWay);

View file

@ -9,9 +9,9 @@ using System.Collections;
namespace Mesen.Controls
{
public class MesenMenu : Menu, IStyleable
public class MesenMenu : Menu
{
Type IStyleable.StyleKey => typeof(Menu);
protected override Type StyleKeyOverride => typeof(Menu);
private void SubmenuOpened(object? sender, RoutedEventArgs e) {
MenuItem menuItem = (MenuItem)sender!;

View file

@ -9,9 +9,9 @@ using System.Globalization;
namespace Mesen.Controls
{
public class MesenNumericTextBox : TextBox, IStyleable
public class MesenNumericTextBox : TextBox
{
Type IStyleable.StyleKey => typeof(TextBox);
protected override Type StyleKeyOverride => typeof(TextBox);
private static HexConverter _hexConverter = new HexConverter();

View file

@ -14,9 +14,9 @@ using System.Threading.Tasks;
namespace Mesen.Controls
{
public class MesenScrollContentPresenter : ScrollContentPresenter, IStyleable
public class MesenScrollContentPresenter : ScrollContentPresenter
{
Type IStyleable.StyleKey => typeof(ScrollContentPresenter);
protected override Type StyleKeyOverride => typeof(ScrollContentPresenter);
protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
{

View file

@ -11,9 +11,9 @@ using System;
namespace Mesen.Controls
{
public class MultiKeyBindingButton : Button, IStyleable
public class MultiKeyBindingButton : Button
{
Type IStyleable.StyleKey => typeof(Button);
protected override Type StyleKeyOverride => typeof(Button);
public static readonly StyledProperty<KeyCombination> KeyBindingProperty = AvaloniaProperty.Register<KeyBindingButton, KeyCombination>(nameof(KeyBinding), new KeyCombination(), false, Avalonia.Data.BindingMode.TwoWay);

View file

@ -13,6 +13,7 @@ namespace Mesen
{
public NativeRenderer()
{
Focusable = true;
}
public IntPtr Handle { get; private set; }

View file

@ -23,8 +23,6 @@
</StackPanel>
<StackPanel Margin="10 0 0 0">
<ItemsPresenter
AreVerticalSnapPointsRegular="{TemplateBinding AreVerticalSnapPointsRegular}"
AreHorizontalSnapPointsRegular="{TemplateBinding AreHorizontalSnapPointsRegular}"
ItemsPanel="{TemplateBinding ItemsPanel}"
/>
</StackPanel>

View file

@ -13,6 +13,7 @@
VerticalAlignment="Center"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Focusable="True"
>
<Panel
HorizontalAlignment="Stretch"

View file

@ -65,9 +65,11 @@ namespace Mesen.Debugger.Controls
private void UpdateToolbar()
{
foreach(object item in Items) {
if(item is ContextMenuAction act) {
act.Update();
if(Items != null) {
foreach(object item in Items) {
if(item is ContextMenuAction act) {
act.Update();
}
}
}
}

View file

@ -13,9 +13,9 @@ using System;
namespace Mesen.Debugger.Controls
{
public class DebuggerKeyBindingButton : Button, IStyleable
public class DebuggerKeyBindingButton : Button
{
Type IStyleable.StyleKey => typeof(Button);
protected override Type StyleKeyOverride => typeof(Button);
public static readonly StyledProperty<DbgShortKeys> KeyBindingProperty = AvaloniaProperty.Register<DebuggerKeyBindingButton, DbgShortKeys>(nameof(KeyBinding), new DbgShortKeys(), false, Avalonia.Data.BindingMode.TwoWay);

View file

@ -312,10 +312,10 @@ namespace Mesen.Debugger.Controls
Brush? b = lineStyle.TextBgColor.HasValue ? new SolidColorBrush(lineStyle.TextBgColor.Value.ToUInt32()) : null;
Pen? p = lineStyle.OutlineColor.HasValue ? new Pen(lineStyle.OutlineColor.Value.ToUInt32()) : null;
if(b != null) {
context.DrawRectangle(b, null, new Rect(Math.Round(x + codeIndent + leftMargin), Math.Round(y), Math.Round(text.WidthIncludingTrailingWhitespace), Math.Round(LetterSize.Height) - 1));
context.DrawRectangle(b, null, new Rect(Math.Round(x + codeIndent + leftMargin) - 0.5, Math.Round(y) - 0.5, Math.Round(text.WidthIncludingTrailingWhitespace) + 1, Math.Round(LetterSize.Height)));
}
if(p != null) {
context.DrawRectangle(p, new Rect(Math.Round(x + codeIndent + leftMargin), Math.Round(y), Math.Round(text.WidthIncludingTrailingWhitespace), Math.Round(LetterSize.Height) - 1));
context.DrawRectangle(p, new Rect(Math.Round(x + codeIndent + leftMargin) - 0.5, Math.Round(y) - 0.5, Math.Round(text.WidthIncludingTrailingWhitespace) + 1, Math.Round(LetterSize.Height)));
}
}

View file

@ -12,9 +12,9 @@ using System.Xml;
namespace Mesen.Debugger.Controls
{
public class MesenTextEditor : TextEditor, IStyleable
public class MesenTextEditor : TextEditor
{
Type IStyleable.StyleKey => typeof(TextEditor);
protected override Type StyleKeyOverride => typeof(TextEditor);
public static readonly StyledProperty<string> TextBindingProperty = AvaloniaProperty.Register<MesenTextEditor, string>(nameof(TextBinding), "", defaultBindingMode: Avalonia.Data.BindingMode.TwoWay);

View file

@ -55,8 +55,12 @@ namespace Mesen.Debugger
{
if(_savedRootDef != null) {
//Restore previous layout
if(FromDockDefinition(_savedRootDef) is IRootDock savedRootLayout) {
return savedRootLayout;
try {
if(FromDockDefinition(_savedRootDef) is IRootDock savedRootLayout) {
return savedRootLayout;
}
} catch {
//Reset layout if any error occurs
}
}
@ -68,55 +72,55 @@ namespace Mesen.Debugger
var mainLayout = new ProportionalDock {
Orientation = Orientation.Vertical,
VisibleDockables = CreateList<IDockable>(
new ProportionalDock {
Proportion = 0.75,
Orientation = Orientation.Horizontal,
ActiveDockable = null,
VisibleDockables = CreateList<IDockable>(
new ToolDock {
Proportion = 0.60,
VisibleDockables = CreateList<IDockable>(DisassemblyTool)
},
new ProportionalDockSplitter(),
new ProportionalDock {
Proportion = 0.40,
Orientation = Orientation.Vertical,
VisibleDockables = CreateList<IDockable>(
new ToolDock {
Proportion = 0.5,
VisibleDockables = CreateList<IDockable>(StatusTool)
},
new ProportionalDockSplitter(),
new ToolDock {
Proportion = 0.5,
VisibleDockables = CreateList<IDockable>(LabelListTool, FunctionListTool, FindResultListTool, ControllerListTool)
}
)
}
)
},
new ProportionalDockSplitter(),
new ProportionalDock {
Proportion = 0.25,
Orientation = Orientation.Horizontal,
VisibleDockables = CreateList<IDockable>(
new ToolDock {
Proportion = 0.33,
VisibleDockables = CreateList<IDockable>(WatchListTool)
},
new ProportionalDockSplitter(),
new ToolDock {
Proportion = 0.33,
VisibleDockables = CreateList<IDockable>(BreakpointListTool)
},
new ProportionalDockSplitter(),
new ToolDock {
Proportion = 0.33,
VisibleDockables = CreateList<IDockable>(CallStackTool)
}
)
}
)
new ProportionalDock {
Proportion = 0.75,
Orientation = Orientation.Horizontal,
ActiveDockable = null,
VisibleDockables = CreateList<IDockable>(
new ToolDock {
Proportion = 0.60,
VisibleDockables = CreateList<IDockable>(DisassemblyTool)
},
new ProportionalDockSplitter(),
new ProportionalDock {
Proportion = 0.40,
Orientation = Orientation.Vertical,
VisibleDockables = CreateList<IDockable>(
new ToolDock {
Proportion = 0.5,
VisibleDockables = CreateList<IDockable>(StatusTool)
},
new ProportionalDockSplitter(),
new ToolDock {
Proportion = 0.5,
VisibleDockables = CreateList<IDockable>(LabelListTool, FunctionListTool, FindResultListTool, ControllerListTool)
}
)
}
)
},
new ProportionalDockSplitter(),
new ProportionalDock {
Proportion = 0.25,
Orientation = Orientation.Horizontal,
VisibleDockables = CreateList<IDockable>(
new ToolDock {
Proportion = 0.33,
VisibleDockables = CreateList<IDockable>(WatchListTool)
},
new ProportionalDockSplitter(),
new ToolDock {
Proportion = 0.33,
VisibleDockables = CreateList<IDockable>(BreakpointListTool)
},
new ProportionalDockSplitter(),
new ToolDock {
Proportion = 0.33,
VisibleDockables = CreateList<IDockable>(CallStackTool)
}
)
}
)
};
var root = CreateRootDock();

View file

@ -95,9 +95,9 @@ namespace Mesen.Debugger.Views
}
}
public class WatchListTextBox : TextBox, IStyleable
public class WatchListTextBox : TextBox
{
Type IStyleable.StyleKey => typeof(TextBox);
protected override Type StyleKeyOverride => typeof(TextBox);
private WatchListView? _listView;
private bool _inOnGotFocus = false;

View file

@ -16,7 +16,7 @@
xmlns:dm="clr-namespace:Dock.Model;assembly=Dock.Model.Avalonia"
xmlns:dmc="clr-namespace:Dock.Model.Controls;assembly=Dock.Model.Avalonia"
mc:Ignorable="d"
DragDrop.AllowDrop="True"
DragDrop.AllowDrop="True"
x:Class="Mesen.Debugger.Windows.DebuggerWindow"
x:DataType="vm:DebuggerWindowViewModel"
Title="{CompiledBinding Title}"
@ -130,7 +130,7 @@
DockPanel.Dock="Bottom"
/>
<idc:DockControl Layout="{CompiledBinding DockLayout}"/>
<idc:DockControl Layout="{CompiledBinding DockLayout}" />
</DockPanel>
</DockPanel>
</Window>

View file

@ -207,7 +207,7 @@ namespace Mesen.Debugger.Windows
Dispatcher.UIThread.Post(() => {
if(!ToolRefreshHelper.LimitFps(this, 20)) {
//Prevent watch update when user is typing a new watch entry
bool updatingWatchEntry = FocusManager.Instance?.Current is TextBox txt && txt.FindAncestorOfType<WatchListView>() != null;
bool updatingWatchEntry = TopLevel.GetTopLevel(this)?.FocusManager?.GetFocusedElement() is TextBox txt && txt.FindAncestorOfType<WatchListView>() != null;
_model.PartialRefresh(!updatingWatchEntry);
}
});

View file

@ -332,7 +332,7 @@ namespace Mesen.Debugger.Windows
_insertOffset = insertOffset;
}
public IBitmap Image
public IImage Image
{
get
{

View file

@ -54,7 +54,7 @@ namespace Mesen.Debugger.Windows
break;
case ConsoleNotificationType.PpuFrameDone:
if(FocusManager.Instance?.Current is TextBox) {
if(TopLevel.GetTopLevel(this)?.FocusManager?.GetFocusedElement() is TextBox) {
return;
}

View file

@ -75,8 +75,7 @@ namespace Mesen
instance.Init(args);
if(instance.FirstInstance) {
Program.CommandLineArgs = (string[])args.Clone();
bool useWgl = args.Any(arg => arg.ToLowerInvariant() == "-wgl");
BuildAvaloniaApp(useWgl).StartWithClassicDesktopLifetime(args, ShutdownMode.OnMainWindowClose);
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args, ShutdownMode.OnMainWindowClose);
EmuApi.Release();
}
@ -151,17 +150,12 @@ namespace Mesen
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
{
return BuildAvaloniaApp(false);
}
public static AppBuilder BuildAvaloniaApp(bool useWgl)
=> AppBuilder.Configure<App>()
.UseReactiveUI()
.UsePlatformDetect()
.With(new Win32PlatformOptions { AllowEglInitialization = true, UseWgl = useWgl })
.With(new X11PlatformOptions { UseGpu = true, UseEGL = false })
.With(new AvaloniaNativePlatformOptions { UseGpu = true })
.With(new Win32PlatformOptions { })
.With(new X11PlatformOptions { })
.With(new AvaloniaNativePlatformOptions { })
.LogToTrace();
}
}

View file

@ -9,9 +9,9 @@ using DataBoxControl.Primitives.Layout;
namespace DataBoxControl.Controls;
public class DataBoxPanel : VirtualizingStackPanel, IStyleable
public class DataBoxPanel : VirtualizingStackPanel
{
Type IStyleable.StyleKey => typeof(DataBoxPanel);
protected override Type StyleKeyOverride => typeof(DataBoxPanel);
internal DataBox? DataBox { get; set; }

View file

@ -310,7 +310,7 @@ public class DataBox : TemplatedControl
if(e.Key == Key.Space) {
ProcessKeyPress(" ");
e.Handled = true;
} else if(IsKeyboardFocusWithin && FocusManager.Instance?.Current is CheckBox) {
} else if(IsKeyboardFocusWithin && TopLevel.GetTopLevel(this)?.FocusManager?.GetFocusedElement() is CheckBox) {
//Allow up/down arrow keys to work properly when focus is on a checkbox column
_rowsPresenter?.ContainerFromIndex(Selection.SelectedIndex)?.Focus();
}

View file

@ -7,10 +7,10 @@ using Avalonia.Styling;
namespace DataBoxControl;
public class DataBoxCell : ContentControl, IStyleable
public class DataBoxCell : ContentControl
{
internal DataBox? DataBox { get; set; }
internal DataBoxColumn? Column { get; set; }
Type IStyleable.StyleKey => typeof(DataBoxCell);
protected override Type StyleKeyOverride => typeof(DataBoxCell);
}

View file

@ -17,7 +17,7 @@ using DataBoxControl.Controls;
namespace DataBoxControl;
[PseudoClasses(":pressed", ":sortascending", ":sortdescending")]
public class DataBoxColumnHeader : ContentControl, IStyleable
public class DataBoxColumnHeader : ContentControl
{
public static readonly StyledProperty<IBrush?> SeparatorBrushProperty =
AvaloniaProperty.Register<DataBoxColumnHeader, IBrush?>(nameof(SeparatorBrush));
@ -39,7 +39,7 @@ public class DataBoxColumnHeader : ContentControl, IStyleable
UpdatePseudoClassesIsPressed(IsPressed);
}
Type IStyleable.StyleKey => typeof(DataBoxColumnHeader);
protected override Type StyleKeyOverride => typeof(DataBoxColumnHeader);
internal DataBox? DataBox { get; set; }

View file

@ -7,11 +7,11 @@ using DataBoxControl.Primitives;
namespace DataBoxControl;
public class DataBoxRow : ListBoxItem, IStyleable
public class DataBoxRow : ListBoxItem
{
private Rectangle? _bottomGridLine;
Type IStyleable.StyleKey => typeof(DataBoxRow);
protected override Type StyleKeyOverride => typeof(DataBoxRow);
internal DataBox? DataBox { get; set; }

View file

@ -11,9 +11,9 @@ using DataBoxControl.Primitives.Layout;
namespace DataBoxControl.Primitives;
public class DataBoxCellsPresenter : Panel, IStyleable
public class DataBoxCellsPresenter : Panel
{
Type IStyleable.StyleKey => typeof(DataBoxCellsPresenter);
protected override Type StyleKeyOverride => typeof(DataBoxCellsPresenter);
internal DataBox? DataBox { get; set; }

View file

@ -8,12 +8,12 @@ using DataBoxControl.Primitives.Layout;
namespace DataBoxControl.Primitives;
public class DataBoxColumnHeadersPresenter : Panel, IStyleable
public class DataBoxColumnHeadersPresenter : Panel
{
private List<IDisposable>? _columnActualWidthDisposables;
private List<DataBoxColumnHeader>? _columnHeaders;
Type IStyleable.StyleKey => typeof(DataBoxColumnHeadersPresenter);
protected override Type StyleKeyOverride => typeof(DataBoxColumnHeadersPresenter);
internal DataBox? DataBox { get; set; }

View file

@ -10,11 +10,11 @@ using Avalonia.VisualTree;
namespace DataBoxControl.Primitives;
public class DataBoxRowsPresenter : ListBox, IStyleable
public class DataBoxRowsPresenter : ListBox
{
internal DataBox? DataBox { get; set; }
Type IStyleable.StyleKey => typeof(DataBoxRowsPresenter);
protected override Type StyleKeyOverride => typeof(DataBoxRowsPresenter);
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
{

View file

@ -83,14 +83,14 @@
<None Remove="Utilities\DipSwitchDefinitions.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.0.0-preview8" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" />
<PackageReference Include="Avalonia.Diagnostics" Version="11.0.0-preview8" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-preview8" />
<PackageReference Include="Dock.Avalonia" Version="11.0.0-preview8.2" />
<PackageReference Include="Dock.Model.Mvvm" Version="11.0.0-preview8.2" />
<PackageReference Include="Avalonia" Version="11.0.0" />
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.0.0" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.0" />
<PackageReference Include="Avalonia.Diagnostics" Version="11.0.0" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0" />
<PackageReference Include="Dock.Avalonia" Version="11.0.0" />
<PackageReference Include="Dock.Model.Mvvm" Version="11.0.0" />
<PackageReference Include="Dotnet.Bundle" Version="*" />
<PackageReference Include="Microsoft.Win32.Registry" Version="6.0.0-preview.5.21301.5" />
<PackageReference Include="ReactiveUI.Fody" Version="18.4.1" />

View file

@ -10,22 +10,12 @@ namespace Mesen.Utilities
{
public static Image FromAsset(string source)
{
IAssetLoader? assetLoader = AvaloniaLocator.Current.GetService<IAssetLoader>();
if(assetLoader != null) {
return new Image() { Source = new Bitmap(assetLoader.Open(new Uri("avares://Mesen/" + source))) };
} else {
throw new Exception("AssetLoader unavailable");
}
return new Image() { Source = new Bitmap(AssetLoader.Open(new Uri("avares://Mesen/" + source))) };
}
public static Bitmap BitmapFromAsset(string source)
{
IAssetLoader? assetLoader = AvaloniaLocator.Current.GetService<IAssetLoader>();
if(assetLoader != null) {
return new Bitmap(assetLoader.Open(new Uri("avares://Mesen/" + source)));
} else {
throw new Exception("AssetLoader unavailable");
}
return new Bitmap(AssetLoader.Open(new Uri("avares://Mesen/" + source)));
}
}
}

View file

@ -52,7 +52,7 @@ namespace Mesen.Utilities
/// </item>
/// </list>
/// </remarks>
public partial class MesenList<T> : IAvaloniaList<T>, IList, INotifyCollectionChangedDebug
public partial class MesenList<T> : IAvaloniaList<T>, IList
{
private readonly List<T> _inner;
private NotifyCollectionChangedEventHandler? _collectionChanged;
@ -620,9 +620,6 @@ namespace Mesen.Utilities
}
}
/// <inheritdoc/>
Delegate[]? INotifyCollectionChangedDebug.GetCollectionChangedSubscribers() => _collectionChanged?.GetInvocationList();
/// <summary>
/// Raises the <see cref="CollectionChanged"/> event with an add action.
/// </summary>

View file

@ -15,7 +15,7 @@ namespace Mesen.Views
InitializeComponent();
MainMenu = this.GetControl<Menu>("ActionMenu");
MainMenu.MenuClosed += (s, e) => {
MainMenu.Closed += (s, e) => {
//When an option is selected in the menu (e.g with enter or mouse click)
//steal focus away from the menu to ensure pressing e.g left/right goes to the
//game only and doesn't re-activate the main menu

View file

@ -103,8 +103,12 @@ namespace Mesen.Windows
private static void InitGlobalShortcuts()
{
PlatformHotkeyConfiguration hotkeyConfig = AvaloniaLocator.Current.GetRequiredService<PlatformHotkeyConfiguration>();
List<KeyGesture> gestures = hotkeyConfig.OpenContextMenu;
if(Application.Current?.PlatformSettings == null) {
return;
}
PlatformHotkeyConfiguration hotkeyConfig = Application.Current.PlatformSettings.HotkeyConfiguration;
List <KeyGesture> gestures = hotkeyConfig.OpenContextMenu;
for(int i = gestures.Count - 1; i >= 0; i--) {
if(gestures[i].Key == Key.F10 && gestures[i].KeyModifiers == KeyModifiers.Shift) {
//Disable Shift-F10 shortcut to open context menu - interferes with default shortcut for step back