Fix subform styling consistency + Items button error handling

Global styles (App.axaml):
- Button: MinHeight=24, Padding=8,4, FontSize=11, centered
- SubformWindow Button: MinWidth=75 (dialogs only)
- Window: FontFamily + FontSize=11 for all dialogs
- TextBox.monospace, TextBlock.section-header, TextBlock.field-label

Subform fixes:
- SettingsEditorView: font sizing on dynamic controls
- InventoryView: standardize button widths
- DatabaseView: fix pagination buttons, status font
- EventFlagsView: standardize control fonts
- SimpleTrainerView: use style classes for labels
- BatchEditorView: fix inconsistent font sizes

Items button fix:
- OpenToolAsync now shows errors in status bar (was Debug.WriteLine)
- Items factory wrapped in try-catch with user-friendly error message
This commit is contained in:
montanon 2026-03-16 12:06:54 -03:00
parent 1dc713e674
commit 8375c79801
10 changed files with 103 additions and 34 deletions

View File

@ -1,5 +1,6 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="using:PKHeX.Avalonia.Views"
x:Class="PKHeX.Avalonia.App"
RequestedThemeVariant="Light">
<Application.Styles>
@ -17,6 +18,45 @@
<Setter Property="Padding" Value="2,1"/>
</Style>
<!-- Global button styling for consistent appearance -->
<Style Selector="Button">
<Setter Property="MinHeight" Value="24"/>
<Setter Property="Padding" Value="8,4"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
<!-- Dialog buttons get a minimum width so OK/Cancel/action buttons are uniform -->
<Style Selector="views|SubformWindow Button">
<Setter Property="MinWidth" Value="75"/>
</Style>
<!-- Monospace font for code/hex displays -->
<Style Selector="TextBox.monospace">
<Setter Property="FontFamily" Value="Consolas,Menlo,Courier New,monospace"/>
<Setter Property="FontSize" Value="11"/>
</Style>
<!-- Dialog window base styling -->
<Style Selector="Window">
<Setter Property="FontFamily" Value="Microsoft Sans Serif,Geneva,Helvetica,Arial,sans-serif"/>
<Setter Property="FontSize" Value="11"/>
</Style>
<!-- Section headers -->
<Style Selector="TextBlock.section-header">
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Margin" Value="0,4,0,4"/>
</Style>
<!-- Standard label in forms -->
<Style Selector="TextBlock.field-label">
<Setter Property="FontSize" Value="11"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<!-- PKMEditor tab styling: WinForms VerticalTabControl parity (96x40 per tab) -->
<Style Selector="TabControl.pkm-tabs">
<Setter Property="Background" Value="Transparent"/>

View File

@ -222,7 +222,8 @@ private async Task OpenToolAsync(SAVToolDescriptor? tool)
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"{tool.Name} error: {ex.Message}");
System.Diagnostics.Debug.WriteLine($"{tool.Name} error: {ex}");
SetStatusMessage?.Invoke($"{tool.Name}: {ex.Message}");
}
}

View File

@ -27,7 +27,7 @@ public static List<SAVToolDescriptor> GetAllTools()
// --- Item Pouch ---
new("Items",
sav => (sav.HasParty && sav is not SAV4BR) || sav is SAV7b,
sav => WithView<InventoryViewModel, InventoryView>(new InventoryViewModel(sav))),
CreateInventoryEditor),
// --- Pokedex ---
new("Pokédex",
@ -341,6 +341,19 @@ public static List<SAVToolDescriptor> GetAllTools()
// Dispatcher methods for gen-specific tools
// -------------------------------------------------------------------------
private static (object, Window) CreateInventoryEditor(SaveFile sav)
{
try
{
return WithView<InventoryViewModel, InventoryView>(new InventoryViewModel(sav));
}
catch (Exception ex)
{
throw new InvalidOperationException(
$"Failed to load inventory for {sav.GetType().Name} (Gen {sav.Generation}): {ex.Message}", ex);
}
}
private static (object, Window) CreateTrainerEditor(SaveFile sav)
{
try

View File

@ -7,6 +7,8 @@
Title="Batch Editor"
Width="520" Height="480"
MinWidth="400" MinHeight="380"
FontFamily="Microsoft Sans Serif,Geneva,Helvetica,Arial,sans-serif"
FontSize="11"
WindowStartupLocation="CenterOwner"
CanResize="True">
@ -15,8 +17,8 @@
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Sample" Command="{Binding AddSampleInstructionsCommand}" Width="80" />
<Button Content="Clear" Command="{Binding ClearInstructionsCommand}" Width="70" />
<Button Content="Execute" Command="{Binding ExecuteCommand}" Width="90"
<Button Content="Clear" Command="{Binding ClearInstructionsCommand}" Width="80" />
<Button Content="Execute" Command="{Binding ExecuteCommand}" Width="80"
IsEnabled="{Binding !IsExecuting}" />
<Button Content="Close" Click="OnCloseClick" Width="80" />
</StackPanel>
@ -24,7 +26,7 @@
<DockPanel>
<!-- Scope selection -->
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8" Margin="0,0,0,8">
<TextBlock Text="Scope:" VerticalAlignment="Center" />
<TextBlock Text="Scope:" VerticalAlignment="Center" FontSize="11" />
<ComboBox ItemsSource="{Binding ScopeOptions}"
SelectedIndex="{Binding SelectedScope}"
MinWidth="140" />
@ -32,7 +34,7 @@
<!-- Instructions label -->
<TextBlock DockPanel.Dock="Top" Text="Instructions (one per line, e.g. .Level=100):"
Margin="0,0,0,4" />
FontSize="11" Margin="0,0,0,4" />
<!-- Results log at bottom -->
<Border DockPanel.Dock="Bottom" Margin="0,8,0,0"
@ -41,7 +43,7 @@
<ScrollViewer>
<TextBlock Text="{Binding ResultLog}"
TextWrapping="Wrap" FontFamily="Consolas, Menlo, monospace"
FontSize="12" />
FontSize="11" />
</ScrollViewer>
</Border>
@ -55,7 +57,7 @@
AcceptsReturn="True" AcceptsTab="True"
TextWrapping="Wrap"
FontFamily="Consolas, Menlo, monospace"
FontSize="13"
FontSize="11"
Watermark="Enter batch instructions here..."
MinHeight="120" />
</DockPanel>

View File

@ -9,6 +9,8 @@
Title="PKM Database"
Width="560" Height="700"
MinWidth="450" MinHeight="500"
FontFamily="Microsoft Sans Serif,Geneva,Helvetica,Arial,sans-serif"
FontSize="11"
WindowStartupLocation="CenterOwner"
CanResize="True">
@ -16,7 +18,7 @@
<!-- Top: Search/Filter bar -->
<StackPanel DockPanel.Dock="Top" Spacing="6" Margin="0,0,0,8">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="Species:" VerticalAlignment="Center" />
<TextBlock Text="Species:" VerticalAlignment="Center" FontSize="11" />
<ComboBox ItemsSource="{Binding SpeciesList}"
SelectedIndex="{Binding FilterSpeciesIndex}"
MinWidth="180">
@ -28,21 +30,21 @@
</ComboBox>
<Button Content="Search" Command="{Binding SearchCommand}" Width="80"
IsEnabled="{Binding IsSearchEnabled}" />
<Button Content="Reset" Command="{Binding ResetFiltersCommand}" Width="70" />
<Button Content="Reset" Command="{Binding ResetFiltersCommand}" Width="80" />
</StackPanel>
</StackPanel>
<!-- Bottom: Status bar and paging -->
<StackPanel DockPanel.Dock="Bottom" Spacing="4" Margin="0,8,0,0">
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Center">
<Button Content="&lt;" Command="{Binding PreviousPageCommand}" Width="40" />
<Button Content="&lt;" Command="{Binding PreviousPageCommand}" Width="40" MinWidth="40" />
<TextBlock Text="{Binding CurrentPage, StringFormat='Page {0}'}"
VerticalAlignment="Center" />
VerticalAlignment="Center" FontSize="11" />
<TextBlock Text="{Binding TotalPages, StringFormat='/ {0}'}"
VerticalAlignment="Center" />
<Button Content="&gt;" Command="{Binding NextPageCommand}" Width="40" />
VerticalAlignment="Center" FontSize="11" />
<Button Content="&gt;" Command="{Binding NextPageCommand}" Width="40" MinWidth="40" />
</StackPanel>
<TextBlock Text="{Binding StatusText}" FontSize="12"
<TextBlock Text="{Binding StatusText}" FontSize="11"
HorizontalAlignment="Center" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8">
<Button Content="Close" Click="OnCloseClick" Width="80" />

View File

@ -7,6 +7,8 @@
Title="{Binding WindowTitle}"
Width="550" Height="550"
MinWidth="400" MinHeight="350"
FontFamily="Microsoft Sans Serif,Geneva,Helvetica,Arial,sans-serif"
FontSize="11"
WindowStartupLocation="CenterOwner"
CanResize="True">
@ -30,8 +32,8 @@
<ItemsControl ItemsSource="{Binding FilteredFlags}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:EventFlagModel">
<CheckBox IsChecked="{Binding Value}" Margin="4,1">
<TextBlock Text="{Binding Label}" />
<CheckBox IsChecked="{Binding Value}" Margin="4,2">
<TextBlock Text="{Binding Label}" FontSize="11" />
</CheckBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
@ -51,9 +53,11 @@
Minimum="0"
Maximum="65535"
Width="100"
FontSize="11"
VerticalAlignment="Center" />
<TextBlock Grid.Column="1"
Text="{Binding Label}"
FontSize="11"
VerticalAlignment="Center"
Margin="8,0,0,0" />
</Grid>

View File

@ -7,6 +7,8 @@
Title="Inventory Editor"
Width="500" Height="450"
MinWidth="400" MinHeight="350"
FontFamily="Microsoft Sans Serif,Geneva,Helvetica,Arial,sans-serif"
FontSize="11"
WindowStartupLocation="CenterOwner"
CanResize="True">
@ -14,8 +16,8 @@
<!-- Bottom buttons -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Right" Spacing="8" Margin="0,8,0,0">
<Button Content="Sort by Name" Command="{Binding SortByNameCommand}" Width="100" />
<Button Content="Sort by Count" Command="{Binding SortByCountCommand}" Width="100" />
<Button Content="Sort by Name" Command="{Binding SortByNameCommand}" MinWidth="90" />
<Button Content="Sort by Count" Command="{Binding SortByCountCommand}" MinWidth="90" />
<Button Content="OK" Click="OnOkClick" Width="80" />
<Button Content="Cancel" Click="OnCancelClick" Width="80" />
</StackPanel>

View File

@ -7,6 +7,8 @@
Title="Settings"
Width="550" Height="500"
MinWidth="400" MinHeight="350"
FontFamily="Microsoft Sans Serif,Geneva,Helvetica,Arial,sans-serif"
FontSize="11"
WindowStartupLocation="CenterOwner"
CanResize="True">
@ -19,7 +21,7 @@
</StackPanel>
<!-- Settings tabs populated in code-behind -->
<TabControl x:Name="SettingsTabs" />
<TabControl x:Name="SettingsTabs" Padding="4" />
</DockPanel>
</views:SubformWindow>

View File

@ -35,21 +35,22 @@ private void BuildSettingsTabs(SettingsEditorViewModel vm)
SettingsTabs.Items.Clear();
foreach (var category in vm.Categories)
{
var tab = new TabItem { Header = category.Name };
var tab = new TabItem { Header = category.Name, FontSize = 11 };
var scrollViewer = new ScrollViewer();
var panel = new StackPanel { Spacing = 4, Margin = new global::Avalonia.Thickness(4) };
var panel = new StackPanel { Spacing = 6, Margin = new global::Avalonia.Thickness(8) };
foreach (var prop in category.Properties)
{
var row = new Grid
{
ColumnDefinitions = ColumnDefinitions.Parse("200,*"),
Margin = new global::Avalonia.Thickness(2),
Margin = new global::Avalonia.Thickness(2, 1),
};
var label = new TextBlock
{
Text = prop.Name,
FontSize = 11,
VerticalAlignment = VerticalAlignment.Center,
};
Grid.SetColumn(label, 0);

View File

@ -7,6 +7,8 @@
Title="Simple Trainer Editor"
Width="420" Height="520"
MinWidth="350" MinHeight="400"
FontFamily="Microsoft Sans Serif,Geneva,Helvetica,Arial,sans-serif"
FontSize="11"
WindowStartupLocation="CenterOwner"
CanResize="True">
@ -22,55 +24,55 @@
<StackPanel Spacing="8">
<!-- Trainer Name -->
<StackPanel Spacing="4">
<TextBlock Text="OT Name" FontWeight="SemiBold" />
<TextBlock Text="OT Name" Classes="section-header" />
<TextBox Text="{Binding OtName}" MaxLength="{Binding MaxNameLength}" />
</StackPanel>
<!-- IDs -->
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto" Margin="0,4">
<StackPanel Grid.Column="0" Grid.Row="0" Spacing="4" Margin="0,0,4,0">
<TextBlock Text="TID" FontWeight="SemiBold" />
<TextBlock Text="TID" Classes="section-header" />
<NumericUpDown Value="{Binding Tid}" Minimum="0" Maximum="65535" />
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" Spacing="4" Margin="4,0,0,0"
IsVisible="{Binding HasSid}">
<TextBlock Text="SID" FontWeight="SemiBold" />
<TextBlock Text="SID" Classes="section-header" />
<NumericUpDown Value="{Binding Sid}" Minimum="0" Maximum="65535" />
</StackPanel>
</Grid>
<!-- Money -->
<StackPanel Spacing="4">
<TextBlock Text="Money" FontWeight="SemiBold" />
<TextBlock Text="Money" Classes="section-header" />
<Grid ColumnDefinitions="*,Auto">
<NumericUpDown Grid.Column="0" Value="{Binding Money}"
Minimum="0" Maximum="{Binding MaxMoney}" />
<Button Grid.Column="1" Content="Max" Command="{Binding MaxCashCommand}"
Margin="4,0,0,0" />
Margin="4,0,0,0" MinWidth="50" />
</Grid>
</StackPanel>
<!-- Gender -->
<StackPanel Spacing="4" IsVisible="{Binding HasGender}">
<TextBlock Text="Gender" FontWeight="SemiBold" />
<TextBlock Text="Gender" Classes="section-header" />
<ComboBox ItemsSource="{Binding GenderSymbols}"
SelectedIndex="{Binding Gender}" />
</StackPanel>
<!-- Play Time -->
<StackPanel Spacing="4">
<TextBlock Text="Play Time" FontWeight="SemiBold" />
<TextBlock Text="Play Time" Classes="section-header" />
<Grid ColumnDefinitions="*,*,*" Margin="0,0,0,0">
<StackPanel Grid.Column="0" Spacing="2" Margin="0,0,4,0">
<TextBlock Text="Hours" />
<TextBlock Text="Hours" Classes="field-label" />
<NumericUpDown Value="{Binding PlayedHours}" Minimum="0" Maximum="65535" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="2" Margin="4,0,4,0">
<TextBlock Text="Minutes" />
<TextBlock Text="Minutes" Classes="field-label" />
<NumericUpDown Value="{Binding PlayedMinutes}" Minimum="0" Maximum="59" />
</StackPanel>
<StackPanel Grid.Column="2" Spacing="2" Margin="4,0,0,0">
<TextBlock Text="Seconds" />
<TextBlock Text="Seconds" Classes="field-label" />
<NumericUpDown Value="{Binding PlayedSeconds}" Minimum="0" Maximum="59" />
</StackPanel>
</Grid>
@ -78,7 +80,7 @@
<!-- Badges -->
<StackPanel Spacing="4">
<TextBlock Text="Badges" FontWeight="SemiBold" />
<TextBlock Text="Badges" Classes="section-header" />
<WrapPanel>
<CheckBox Content="Badge 1" IsChecked="{Binding Badge1}" Margin="4,2" />
<CheckBox Content="Badge 2" IsChecked="{Binding Badge2}" Margin="4,2" />