From 657a70735fab488351002d7ed32f04ba261a0f93 Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sat, 21 Feb 2026 18:53:28 +0100 Subject: [PATCH 01/20] tooltip improvements --- WheelWizard/Views/App.axaml.cs | 1 + .../Components/StandardLibrary/Button.axaml | 4 +- .../StandardLibrary/StateBox.axaml.cs | 2 +- WheelWizard/Views/Pages/FriendsPage.axaml | 4 +- WheelWizard/Views/Pages/HomePage.axaml | 4 +- WheelWizard/Views/Pages/RoomsPage.axaml | 6 +- WheelWizard/Views/Pages/UserProfilePage.axaml | 2 +- .../Views/Styles/Styles/MiscStyles.axaml | 80 ++++- WheelWizard/Views/ToolTipBubbleBehavior.cs | 297 ++++++++++++++++++ 9 files changed, 388 insertions(+), 12 deletions(-) create mode 100644 WheelWizard/Views/ToolTipBubbleBehavior.cs diff --git a/WheelWizard/Views/App.axaml.cs b/WheelWizard/Views/App.axaml.cs index e1d16884..f5f4d622 100644 --- a/WheelWizard/Views/App.axaml.cs +++ b/WheelWizard/Views/App.axaml.cs @@ -38,6 +38,7 @@ public void SetServiceProvider(IServiceProvider serviceProvider) public override void Initialize() { AvaloniaXamlLoader.Load(this); + ToolTipBubbleBehavior.Initialize(); } private static void OpenGameBananaModWindow() diff --git a/WheelWizard/Views/Components/StandardLibrary/Button.axaml b/WheelWizard/Views/Components/StandardLibrary/Button.axaml index 94418edc..56f5222e 100644 --- a/WheelWizard/Views/Components/StandardLibrary/Button.axaml +++ b/WheelWizard/Views/Components/StandardLibrary/Button.axaml @@ -24,7 +24,7 @@ IconData="{StaticResource WheelIcon}" IconSize="25" ToolTip.Tip="Launch Dolphin" - ToolTip.Placement="Bottom" + ToolTip.Placement="Top" ToolTip.ShowDelay="50" HorizontalAlignment="Center" Margin="0,6,0,0" /> @@ -140,4 +140,4 @@ - \ No newline at end of file + diff --git a/WheelWizard/Views/Components/StandardLibrary/StateBox.axaml.cs b/WheelWizard/Views/Components/StandardLibrary/StateBox.axaml.cs index 632ef21b..9e7d7e5a 100644 --- a/WheelWizard/Views/Components/StandardLibrary/StateBox.axaml.cs +++ b/WheelWizard/Views/Components/StandardLibrary/StateBox.axaml.cs @@ -78,7 +78,7 @@ public StateBoxVariantType Variant public static readonly StyledProperty TipPlacementProperty = AvaloniaProperty.Register( nameof(TipPlacement), - PlacementMode.Right + PlacementMode.Top ); public PlacementMode TipPlacement diff --git a/WheelWizard/Views/Pages/FriendsPage.axaml b/WheelWizard/Views/Pages/FriendsPage.axaml index 5560178f..7bce881c 100644 --- a/WheelWizard/Views/Pages/FriendsPage.axaml +++ b/WheelWizard/Views/Pages/FriendsPage.axaml @@ -35,11 +35,11 @@ ToolTip.Tip="Add Friend" ToolTip.Placement="Top" ToolTip.ShowDelay="20" /> - - diff --git a/WheelWizard/Views/Pages/HomePage.axaml b/WheelWizard/Views/Pages/HomePage.axaml index 59f0e2f7..8fc3d86e 100644 --- a/WheelWizard/Views/Pages/HomePage.axaml +++ b/WheelWizard/Views/Pages/HomePage.axaml @@ -174,7 +174,7 @@ IconData="{StaticResource DolphinIcon}" IconSize="30" ToolTip.Tip="{x:Static lang:Common.Action_LaunchDolphin}" - ToolTip.Placement="Bottom" + ToolTip.Placement="Top" ToolTip.ShowDelay="50" Height="40" Click="DolphinButton_OnClick" @@ -188,4 +188,4 @@ Width="137" Angle="-35" X="40" Y="30" ExtendedHeight="1000" IsVisible="False" Background="{StaticResource Primary600}" Foreground="{StaticResource Primary800}" /> - \ No newline at end of file + diff --git a/WheelWizard/Views/Pages/RoomsPage.axaml b/WheelWizard/Views/Pages/RoomsPage.axaml index 2b0029b8..bb0d6b49 100644 --- a/WheelWizard/Views/Pages/RoomsPage.axaml +++ b/WheelWizard/Views/Pages/RoomsPage.axaml @@ -23,11 +23,11 @@ - - @@ -153,4 +153,4 @@ - \ No newline at end of file + diff --git a/WheelWizard/Views/Pages/UserProfilePage.axaml b/WheelWizard/Views/Pages/UserProfilePage.axaml index f4f8fcfc..7e10f668 100644 --- a/WheelWizard/Views/Pages/UserProfilePage.axaml +++ b/WheelWizard/Views/Pages/UserProfilePage.axaml @@ -78,7 +78,7 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs new file mode 100644 index 00000000..2ee82b6a --- /dev/null +++ b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs @@ -0,0 +1,150 @@ +using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Interactivity; +using WheelWizard.Views.Components; +using WheelWizard.Views.Pages.KitchenSink; + +namespace WheelWizard.Views.Pages; + +public partial class KitchenSinkPage : UserControlBase +{ + private readonly SectionDefinition[] _sections = + [ + SectionDefinition.Create(), + SectionDefinition.Create(), + SectionDefinition.Create(), + ]; + + private readonly List _allSectionBorders = []; + private Border? _singleSectionBorder; + private bool _isInitializing; + private bool _useNeutral900Blocks = true; + + public KitchenSinkPage() + { + InitializeComponent(); + BuildAllSections(); + PopulateSections(); + ApplyBlockBackgroundMode(); + } + + private void BuildAllSections() + { + _allSectionBorders.Clear(); + AllSectionsContainer.Children.Clear(); + + foreach (var section in _sections) + { + var sectionView = section.CreatePage(); + var sectionContainer = CreateSectionContainer(section.Label, section.Tooltip, sectionView, out var sectionBorder); + _allSectionBorders.Add(sectionBorder); + AllSectionsContainer.Children.Add(sectionContainer); + } + } + + private static StackPanel CreateSectionContainer( + string sectionName, + string? sectionTooltip, + Control sectionContent, + out Border sectionBorder + ) + { + var header = new FormFieldLabel { Text = sectionName, TipText = sectionTooltip ?? string.Empty }; + + sectionBorder = new Border { Child = sectionContent }; + sectionBorder.Classes.Add("KitchenSinkSectionBlock"); + + var sectionContainer = new StackPanel(); + sectionContainer.Children.Add(header); + sectionContainer.Children.Add(sectionBorder); + return sectionContainer; + } + + private void PopulateSections() + { + _isInitializing = true; + SectionDropdown.Items.Clear(); + SectionDropdown.Items.Add("All"); + + foreach (var section in _sections) + SectionDropdown.Items.Add(section.Label); + + SectionDropdown.SelectedIndex = 0; + _isInitializing = false; + + ApplySelectedSection(); + } + + private void SectionDropdown_OnSelectionChanged(object? sender, SelectionChangedEventArgs e) + { + if (_isInitializing) + return; + + ApplySelectedSection(); + } + + private void BackgroundSwitch_OnIsCheckedChanged(object? sender, RoutedEventArgs e) + { + _useNeutral900Blocks = BackgroundSwitch.IsChecked == true; + ApplyBlockBackgroundMode(); + } + + private void ApplySelectedSection() + { + var selectedLabel = SectionDropdown.SelectedItem as string ?? "All"; + var showAll = selectedLabel == "All"; + + AllSectionsScrollViewer.IsVisible = showAll; + SectionContent.IsVisible = !showAll; + _singleSectionBorder = null; + + if (showAll) + { + SectionContent.Content = null; + return; + } + + var sectionIndex = Array.FindIndex(_sections, x => x.Label == selectedLabel); + if (sectionIndex < 0) + { + SectionContent.Content = null; + return; + } + + var section = _sections[sectionIndex]; + var sectionContainer = CreateSectionContainer(section.Label, section.Tooltip, section.CreatePage(), out var sectionBorder); + _singleSectionBorder = sectionBorder; + SectionContent.Content = new ScrollViewer + { + HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, + VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + Content = sectionContainer, + }; + + ApplyBlockBackgroundMode(); + } + + private void ApplyBlockBackgroundMode() + { + foreach (var border in _allSectionBorders) + ApplyBackgroundClass(border); + + if (_singleSectionBorder != null) + ApplyBackgroundClass(_singleSectionBorder); + } + + private void ApplyBackgroundClass(Border border) + { + border.Classes.Set("BlockBackground900", _useNeutral900Blocks); + } + + private readonly record struct SectionDefinition(string Label, string? Tooltip, Func CreatePage) + { + public static SectionDefinition Create() + where T : KitchenSinkSectionPageBase, new() + { + var metadataInstance = new T(); + return new(metadataInstance.SectionName, metadataInstance.SectionTooltip, () => new T()); + } + } +} diff --git a/WheelWizard/Views/Pages/Settings/SettingsPage.axaml b/WheelWizard/Views/Pages/SettingsPage.axaml similarity index 97% rename from WheelWizard/Views/Pages/Settings/SettingsPage.axaml rename to WheelWizard/Views/Pages/SettingsPage.axaml index 769b470b..f80f4fd7 100644 --- a/WheelWizard/Views/Pages/Settings/SettingsPage.axaml +++ b/WheelWizard/Views/Pages/SettingsPage.axaml @@ -5,7 +5,7 @@ xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" xmlns:components="clr-namespace:WheelWizard.Views.Components" mc:Ignorable="d" d:DesignWidth="656" d:DesignHeight="876" - x:Class="WheelWizard.Views.Pages.Settings.SettingsPage"> + x:Class="WheelWizard.Views.Pages.SettingsPage"> diff --git a/WheelWizard/Views/Pages/Settings/SettingsPage.axaml.cs b/WheelWizard/Views/Pages/SettingsPage.axaml.cs similarity index 76% rename from WheelWizard/Views/Pages/Settings/SettingsPage.axaml.cs rename to WheelWizard/Views/Pages/SettingsPage.axaml.cs index 2bde8008..0e9ba539 100644 --- a/WheelWizard/Views/Pages/Settings/SettingsPage.axaml.cs +++ b/WheelWizard/Views/Pages/SettingsPage.axaml.cs @@ -1,8 +1,9 @@ using Avalonia.Controls; using Avalonia.Interactivity; +using WheelWizard.Views.Pages.Settings; using WheelWizard.Views.Popups; -namespace WheelWizard.Views.Pages.Settings; +namespace WheelWizard.Views.Pages; public partial class SettingsPage : UserControlBase { @@ -25,9 +26,9 @@ private void TopBarRadio_OnClick(object? sender, RoutedEventArgs e) if (sender is not RadioButton radioButton) return; - // As long as the Ks... files are next to this file, it works. - var namespaceName = GetType().Namespace; - var typeName = $"{namespaceName}.{radioButton.Tag}"; + // Settings sub-pages stay in the nested Settings namespace. + var settingsSubPagesNamespace = typeof(WhWzSettings).Namespace; + var typeName = $"{settingsSubPagesNamespace}.{radioButton.Tag}"; var type = Type.GetType(typeName); if (type == null || !typeof(UserControl).IsAssignableFrom(type)) return; diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml new file mode 100644 index 00000000..56dd06e1 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml.cs new file mode 100644 index 00000000..245358fd --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml.cs @@ -0,0 +1,12 @@ +namespace WheelWizard.Views.Pages.KitchenSink; + +public partial class KitchenSinkButtonsPage : KitchenSinkSectionPageBase +{ + public override string SectionName => "Buttons"; + public override string? SectionTooltip => "Button color variants and icon/text combinations."; + + public KitchenSinkButtonsPage() + { + InitializeComponent(); + } +} diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkSectionPageBase.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkSectionPageBase.cs new file mode 100644 index 00000000..64863b7e --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkSectionPageBase.cs @@ -0,0 +1,13 @@ +namespace WheelWizard.Views.Pages.KitchenSink; + +public interface IKitchenSinkSection +{ + string SectionName { get; } + string? SectionTooltip { get; } +} + +public abstract class KitchenSinkSectionPageBase : UserControlBase, IKitchenSinkSection +{ + public abstract string SectionName { get; } + public virtual string? SectionTooltip => null; +} diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml new file mode 100644 index 00000000..a7477ed3 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml.cs new file mode 100644 index 00000000..8c468d8e --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml.cs @@ -0,0 +1,12 @@ +namespace WheelWizard.Views.Pages.KitchenSink; + +public partial class KitchenSinkTextStylesPage : KitchenSinkSectionPageBase +{ + public override string SectionName => "Text Styles + Tooltips"; + public override string? SectionTooltip => "Typography classes and common tooltip placements."; + + public KitchenSinkTextStylesPage() + { + InitializeComponent(); + } +} diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml new file mode 100644 index 00000000..ded94299 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml.cs new file mode 100644 index 00000000..4d291d01 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml.cs @@ -0,0 +1,12 @@ +namespace WheelWizard.Views.Pages.KitchenSink; + +public partial class KitchenSinkToggleButtonsPage : KitchenSinkSectionPageBase +{ + public override string SectionName => "Toggle Buttons"; + public override string? SectionTooltip => "CheckBox, Switch, and RadioButton variants."; + + public KitchenSinkToggleButtonsPage() + { + InitializeComponent(); + } +} diff --git a/WheelWizard/Views/Popups/MiiManagement/MiiEditor/EditorGeneral.axaml.cs b/WheelWizard/Views/Popups/MiiManagement/MiiEditor/EditorGeneral.axaml.cs index b7f2607c..6fa7a230 100644 --- a/WheelWizard/Views/Popups/MiiManagement/MiiEditor/EditorGeneral.axaml.cs +++ b/WheelWizard/Views/Popups/MiiManagement/MiiEditor/EditorGeneral.axaml.cs @@ -86,8 +86,8 @@ private void Name_TextChanged(object sender, TextChangedEventArgs e) private OperationResult ValidateMiiName(string? _, string newName) { - newName = newName?.Trim(); - if (newName.Length is > 10 or < 3) + var trimmedName = newName?.Trim() ?? string.Empty; + if (trimmedName.Length is > 10 or < 3) return Fail(Phrases.HelperNote_NameMustBetween); return Ok(); @@ -95,8 +95,8 @@ private OperationResult ValidateMiiName(string? _, string newName) private OperationResult ValidateCreatorName(string newName) { - newName = newName?.Trim(); - if (newName.Length > 10) + var trimmedName = newName?.Trim() ?? string.Empty; + if (trimmedName.Length > 10) return Fail(Phrases.HelperNote_CreatorNameLess11); return Ok(); From 2f2f642c618a309fa35a84d5f429de780a6f7dcf Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sun, 22 Feb 2026 18:28:18 +0100 Subject: [PATCH 05/20] kitchen sink blocks --- .../StandardLibrary/FormFieldLabel.axaml | 4 +- .../StandardLibrary/FormFieldLabel.axaml.cs | 26 +++- WheelWizard/Views/Pages/KitchenSinkPage.axaml | 36 ++++- .../Views/Pages/KitchenSinkPage.axaml.cs | 123 ++++++++++++++---- 4 files changed, 160 insertions(+), 29 deletions(-) diff --git a/WheelWizard/Views/Components/StandardLibrary/FormFieldLabel.axaml b/WheelWizard/Views/Components/StandardLibrary/FormFieldLabel.axaml index 30239ad0..81ee970c 100644 --- a/WheelWizard/Views/Components/StandardLibrary/FormFieldLabel.axaml +++ b/WheelWizard/Views/Components/StandardLibrary/FormFieldLabel.axaml @@ -10,6 +10,7 @@ + + + + @@ -34,14 +63,15 @@ - + diff --git a/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs index 2ee82b6a..1b2c74f2 100644 --- a/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs +++ b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs @@ -1,6 +1,7 @@ using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Interactivity; +using Avalonia.Layout; using WheelWizard.Views.Components; using WheelWizard.Views.Pages.KitchenSink; @@ -15,6 +16,18 @@ public partial class KitchenSinkPage : UserControlBase SectionDefinition.Create(), ]; + // Add more configurable section groups here. + private readonly SectionCollectionDefinition[] _sectionCollections = + [ + SectionCollectionDefinition.Create( + "Basic Components", + typeof(KitchenSinkTextStylesPage), + typeof(KitchenSinkToggleButtonsPage), + typeof(KitchenSinkButtonsPage) + ), + ]; + + private readonly Dictionary _allSectionContainersById = []; private readonly List _allSectionBorders = []; private Border? _singleSectionBorder; private bool _isInitializing; @@ -30,6 +43,7 @@ public KitchenSinkPage() private void BuildAllSections() { + _allSectionContainersById.Clear(); _allSectionBorders.Clear(); AllSectionsContainer.Children.Clear(); @@ -37,39 +51,50 @@ private void BuildAllSections() { var sectionView = section.CreatePage(); var sectionContainer = CreateSectionContainer(section.Label, section.Tooltip, sectionView, out var sectionBorder); + _allSectionContainersById[section.Id] = sectionContainer; _allSectionBorders.Add(sectionBorder); AllSectionsContainer.Children.Add(sectionContainer); } } - private static StackPanel CreateSectionContainer( + private static Border CreateSectionContainer( string sectionName, string? sectionTooltip, Control sectionContent, out Border sectionBorder ) { - var header = new FormFieldLabel { Text = sectionName, TipText = sectionTooltip ?? string.Empty }; - - sectionBorder = new Border { Child = sectionContent }; + var header = new FormFieldLabel + { + Text = sectionName, + TipText = sectionTooltip ?? string.Empty + }; + var divider = new Border(); + divider.Classes.Add("KitchenSinkSectionDivider"); + var body = new StackPanel { Spacing = 8 }; + body.Children.Add(header); + body.Children.Add(divider); + body.Children.Add(sectionContent); + + sectionBorder = new Border { Child = body }; sectionBorder.Classes.Add("KitchenSinkSectionBlock"); - - var sectionContainer = new StackPanel(); - sectionContainer.Children.Add(header); - sectionContainer.Children.Add(sectionBorder); - return sectionContainer; + sectionBorder.VerticalAlignment = VerticalAlignment.Top; + sectionBorder.HorizontalAlignment = HorizontalAlignment.Stretch; + return sectionBorder; } private void PopulateSections() { _isInitializing = true; SectionDropdown.Items.Clear(); - SectionDropdown.Items.Add("All"); + + foreach (var collection in _sectionCollections) + SectionDropdown.Items.Add(SectionDropdownItem.ForCollection(collection)); foreach (var section in _sections) - SectionDropdown.Items.Add(section.Label); + SectionDropdown.Items.Add(SectionDropdownItem.ForSection(section)); - SectionDropdown.SelectedIndex = 0; + SectionDropdown.SelectedIndex = SectionDropdown.Items.Count > 0 ? 0 : -1; _isInitializing = false; ApplySelectedSection(); @@ -91,20 +116,47 @@ private void BackgroundSwitch_OnIsCheckedChanged(object? sender, RoutedEventArgs private void ApplySelectedSection() { - var selectedLabel = SectionDropdown.SelectedItem as string ?? "All"; - var showAll = selectedLabel == "All"; - - AllSectionsScrollViewer.IsVisible = showAll; - SectionContent.IsVisible = !showAll; - _singleSectionBorder = null; - - if (showAll) + var selectedItem = SectionDropdown.SelectedItem as SectionDropdownItem; + if (selectedItem == null) { + AllSectionsScrollViewer.IsVisible = false; + SectionContent.IsVisible = false; SectionContent.Content = null; + _singleSectionBorder = null; return; } - var sectionIndex = Array.FindIndex(_sections, x => x.Label == selectedLabel); + if (selectedItem.Collection is { } collection) + { + ShowCollection(collection); + return; + } + + if (string.IsNullOrWhiteSpace(selectedItem.SectionId)) + return; + + ShowSingleSection(selectedItem.SectionId); + } + + private void ShowCollection(SectionCollectionDefinition collection) + { + foreach (var section in _sections) + { + if (_allSectionContainersById.TryGetValue(section.Id, out var sectionContainer)) + sectionContainer.IsVisible = collection.Contains(section.Id); + } + + AllSectionsScrollViewer.IsVisible = true; + SectionContent.IsVisible = false; + _singleSectionBorder = null; + SectionContent.Content = null; + + ApplyBlockBackgroundMode(); + } + + private void ShowSingleSection(string sectionId) + { + var sectionIndex = Array.FindIndex(_sections, x => x.Id == sectionId); if (sectionIndex < 0) { SectionContent.Content = null; @@ -118,9 +170,14 @@ private void ApplySelectedSection() { HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + HorizontalContentAlignment = HorizontalAlignment.Stretch, + VerticalContentAlignment = VerticalAlignment.Top, Content = sectionContainer, }; + AllSectionsScrollViewer.IsVisible = false; + SectionContent.IsVisible = true; + ApplyBlockBackgroundMode(); } @@ -138,13 +195,33 @@ private void ApplyBackgroundClass(Border border) border.Classes.Set("BlockBackground900", _useNeutral900Blocks); } - private readonly record struct SectionDefinition(string Label, string? Tooltip, Func CreatePage) + private readonly record struct SectionDefinition(string Id, string Label, string? Tooltip, Func CreatePage) { public static SectionDefinition Create() where T : KitchenSinkSectionPageBase, new() { var metadataInstance = new T(); - return new(metadataInstance.SectionName, metadataInstance.SectionTooltip, () => new T()); + return new(typeof(T).Name, metadataInstance.SectionName, metadataInstance.SectionTooltip, () => new T()); } } + + private readonly record struct SectionCollectionDefinition(string Label, HashSet SectionIds) + { + public bool Contains(string sectionId) => SectionIds.Contains(sectionId); + + public static SectionCollectionDefinition Create(string label, params Type[] sectionTypes) + { + var sectionIds = sectionTypes.Select(static sectionType => sectionType.Name).ToHashSet(StringComparer.Ordinal); + return new(label, sectionIds); + } + } + + private sealed record SectionDropdownItem(string Label, string? SectionId, SectionCollectionDefinition? Collection) + { + public static SectionDropdownItem ForCollection(SectionCollectionDefinition collection) => new(collection.Label, null, collection); + + public static SectionDropdownItem ForSection(SectionDefinition section) => new(section.Label, section.Id, null); + + public override string ToString() => Label; + } } From 7a11c92ff6250ec5e4a9173955bea4a8ac6fe213 Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sun, 22 Feb 2026 19:27:33 +0100 Subject: [PATCH 06/20] . --- .../Views/Pages/KitchenSinkPage.axaml.cs | 6 +- .../kitchenSink/KitchenSinkButtonsPage.axaml | 111 +++++++++++++----- .../KitchenSinkButtonsPage.axaml.cs | 2 +- .../KitchenSinkTextStylesPage.axaml | 79 ++++++++----- .../KitchenSinkTextStylesPage.axaml.cs | 2 +- .../KitchenSinkToggleButtonsPage.axaml.cs | 2 +- 6 files changed, 135 insertions(+), 67 deletions(-) diff --git a/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs index 1b2c74f2..3a225463 100644 --- a/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs +++ b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs @@ -64,11 +64,7 @@ private static Border CreateSectionContainer( out Border sectionBorder ) { - var header = new FormFieldLabel - { - Text = sectionName, - TipText = sectionTooltip ?? string.Empty - }; + var header = new FormFieldLabel { Text = sectionName, TipText = sectionTooltip ?? string.Empty }; var divider = new Border(); divider.Classes.Add("KitchenSinkSectionDivider"); var body = new StackPanel { Spacing = 8 }; diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml index 56dd06e1..4c58928d 100644 --- a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml @@ -5,39 +5,86 @@ xmlns:components="clr-namespace:WheelWizard.Views.Components" mc:Ignorable="d" d:DesignWidth="620" d:DesignHeight="680" x:Class="WheelWizard.Views.Pages.KitchenSink.KitchenSinkButtonsPage"> - - - - - - - - - - - + + + + - - - - - - - + + - - - - - - + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml.cs index 245358fd..addf7ef7 100644 --- a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml.cs +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml.cs @@ -3,7 +3,7 @@ namespace WheelWizard.Views.Pages.KitchenSink; public partial class KitchenSinkButtonsPage : KitchenSinkSectionPageBase { public override string SectionName => "Buttons"; - public override string? SectionTooltip => "Button color variants and icon/text combinations."; + public override string? SectionTooltip => null; public KitchenSinkButtonsPage() { diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml index a7477ed3..3be42018 100644 --- a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml @@ -2,34 +2,59 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:components="clr-namespace:WheelWizard.Views.Components" mc:Ignorable="d" d:DesignWidth="620" d:DesignHeight="640" x:Class="WheelWizard.Views.Pages.KitchenSink.KitchenSinkTextStylesPage"> - - - - - - - - - - - - - + + + + + + + - + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml.cs index 8c468d8e..3f0b8f34 100644 --- a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml.cs +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkTextStylesPage.axaml.cs @@ -3,7 +3,7 @@ namespace WheelWizard.Views.Pages.KitchenSink; public partial class KitchenSinkTextStylesPage : KitchenSinkSectionPageBase { public override string SectionName => "Text Styles + Tooltips"; - public override string? SectionTooltip => "Typography classes and common tooltip placements."; + public override string? SectionTooltip => null; public KitchenSinkTextStylesPage() { diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml.cs index 4d291d01..4cf64052 100644 --- a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml.cs +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkToggleButtonsPage.axaml.cs @@ -3,7 +3,7 @@ namespace WheelWizard.Views.Pages.KitchenSink; public partial class KitchenSinkToggleButtonsPage : KitchenSinkSectionPageBase { public override string SectionName => "Toggle Buttons"; - public override string? SectionTooltip => "CheckBox, Switch, and RadioButton variants."; + public override string? SectionTooltip => null; public KitchenSinkToggleButtonsPage() { From 21888b6e5681e1c1408ef021f928ef00696827ba Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sun, 22 Feb 2026 19:38:16 +0100 Subject: [PATCH 07/20] more things --- .../Views/Pages/KitchenSinkPage.axaml.cs | 8 ++- .../kitchenSink/KitchenSinkButtonsPage.axaml | 42 +++++++++----- .../KitchenSinkDropdownsPage.axaml | 36 ++++++++++++ .../KitchenSinkDropdownsPage.axaml.cs | 12 ++++ .../KitchenSinkIconLabelsPage.axaml | 56 +++++++++++++++++++ .../KitchenSinkIconLabelsPage.axaml.cs | 12 ++++ .../KitchenSinkInputFieldsPage.axaml | 29 ++++++++++ .../KitchenSinkInputFieldsPage.axaml.cs | 12 ++++ 8 files changed, 193 insertions(+), 14 deletions(-) create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkDropdownsPage.axaml create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkDropdownsPage.axaml.cs create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconLabelsPage.axaml create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconLabelsPage.axaml.cs create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml.cs diff --git a/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs index 3a225463..30a50ce0 100644 --- a/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs +++ b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs @@ -13,7 +13,10 @@ public partial class KitchenSinkPage : UserControlBase [ SectionDefinition.Create(), SectionDefinition.Create(), + SectionDefinition.Create(), + SectionDefinition.Create(), SectionDefinition.Create(), + SectionDefinition.Create(), ]; // Add more configurable section groups here. @@ -23,7 +26,10 @@ public partial class KitchenSinkPage : UserControlBase "Basic Components", typeof(KitchenSinkTextStylesPage), typeof(KitchenSinkToggleButtonsPage), - typeof(KitchenSinkButtonsPage) + typeof(KitchenSinkInputFieldsPage), + typeof(KitchenSinkDropdownsPage), + typeof(KitchenSinkButtonsPage), + typeof(KitchenSinkIconLabelsPage) ), ]; diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml index 4c58928d..717aa57e 100644 --- a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkButtonsPage.axaml @@ -13,19 +13,35 @@ Margin="0,0,5,5" Variant="Default" Text="Text only" /> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkDropdownsPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkDropdownsPage.axaml.cs new file mode 100644 index 00000000..ed2c866d --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkDropdownsPage.axaml.cs @@ -0,0 +1,12 @@ +namespace WheelWizard.Views.Pages.KitchenSink; + +public partial class KitchenSinkDropdownsPage : KitchenSinkSectionPageBase +{ + public override string SectionName => "Dropdowns"; + public override string? SectionTooltip => null; + + public KitchenSinkDropdownsPage() + { + InitializeComponent(); + } +} diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconLabelsPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconLabelsPage.axaml new file mode 100644 index 00000000..cb1747af --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconLabelsPage.axaml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconLabelsPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconLabelsPage.axaml.cs new file mode 100644 index 00000000..ca8b3cf1 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconLabelsPage.axaml.cs @@ -0,0 +1,12 @@ +namespace WheelWizard.Views.Pages.KitchenSink; + +public partial class KitchenSinkIconLabelsPage : KitchenSinkSectionPageBase +{ + public override string SectionName => "Icon Labels"; + public override string? SectionTooltip => null; + + public KitchenSinkIconLabelsPage() + { + InitializeComponent(); + } +} diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml new file mode 100644 index 00000000..16093e06 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml.cs new file mode 100644 index 00000000..0204f3d2 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml.cs @@ -0,0 +1,12 @@ +namespace WheelWizard.Views.Pages.KitchenSink; + +public partial class KitchenSinkInputFieldsPage : KitchenSinkSectionPageBase +{ + public override string SectionName => "Input Fields"; + public override string? SectionTooltip => null; + + public KitchenSinkInputFieldsPage() + { + InitializeComponent(); + } +} From 29cd758cccfff436a87c5d6e721cffe5b92de495 Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sun, 22 Feb 2026 20:16:53 +0100 Subject: [PATCH 08/20] . --- .../BehaviorComponent/FeedbackTextBox.axaml | 6 ++ .../FeedbackTextBox.axaml.cs | 38 +++++++++-- WheelWizard/Views/Pages/FriendsPage.axaml.cs | 13 +++- .../Views/Pages/KitchenSinkPage.axaml.cs | 6 +- .../kitchenSink/KitchenSinkIconsPage.axaml | 68 +++++++++++++++++++ .../kitchenSink/KitchenSinkIconsPage.axaml.cs | 12 ++++ .../KitchenSinkInputFieldsPage.axaml | 23 ++++++- .../KitchenSinkStateBoxesPage.axaml | 60 ++++++++++++++++ .../KitchenSinkStateBoxesPage.axaml.cs | 12 ++++ .../Popups/Generic/TextInputWindow.axaml.cs | 20 ++++-- .../Views/Styles/Styles/TextBoxStyles.axaml | 25 ++++++- 11 files changed, 268 insertions(+), 15 deletions(-) create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconsPage.axaml create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconsPage.axaml.cs create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkStateBoxesPage.axaml create mode 100644 WheelWizard/Views/Pages/kitchenSink/KitchenSinkStateBoxesPage.axaml.cs diff --git a/WheelWizard/Views/BehaviorComponent/FeedbackTextBox.axaml b/WheelWizard/Views/BehaviorComponent/FeedbackTextBox.axaml index c67bb8af..47ae823d 100644 --- a/WheelWizard/Views/BehaviorComponent/FeedbackTextBox.axaml +++ b/WheelWizard/Views/BehaviorComponent/FeedbackTextBox.axaml @@ -19,6 +19,12 @@ IconData="{StaticResource WarningTriangle}" IconSize="15" FontSize="13" Margin="4,4,0,0" /> + diff --git a/WheelWizard/Views/BehaviorComponent/FeedbackTextBox.axaml.cs b/WheelWizard/Views/BehaviorComponent/FeedbackTextBox.axaml.cs index 8e82392a..0a0db6aa 100644 --- a/WheelWizard/Views/BehaviorComponent/FeedbackTextBox.axaml.cs +++ b/WheelWizard/Views/BehaviorComponent/FeedbackTextBox.axaml.cs @@ -17,6 +17,10 @@ public partial class FeedbackTextBox : UserControlBase nameof(ErrorMessage) ); + public static readonly StyledProperty WarningMessageProperty = AvaloniaProperty.Register( + nameof(WarningMessage) + ); + public static readonly StyledProperty TextProperty = AvaloniaProperty.Register(nameof(Text)); public static readonly StyledProperty WatermarkProperty = AvaloniaProperty.Register( @@ -51,6 +55,12 @@ public string ErrorMessage set => SetValue(ErrorMessageProperty, value); } + public string WarningMessage + { + get => GetValue(WarningMessageProperty); + set => SetValue(WarningMessageProperty, value); + } + public string Text { get => GetValue(TextProperty); @@ -89,6 +99,7 @@ public FeedbackTextBox() DataContext = this; InputField.TextChanged += (_, _) => RaiseEvent(new TextChangedEventArgs(TextChangedEvent, this)); + UpdateValidationState(hasError: !string.IsNullOrWhiteSpace(ErrorMessage), hasWarning: !string.IsNullOrWhiteSpace(WarningMessage)); // If there is uses for more other events, then we can always add them } @@ -100,16 +111,26 @@ private void UpdateStyleClasses(TextBoxVariantType variant) InputField.Classes.Remove("dark"); } - private void UpdateErrorState(bool hasError) + private void UpdateValidationState(bool hasError, bool hasWarning) { - if (!hasError) + if (hasError) + { + if (!InputField.Classes.Contains("error")) + InputField.Classes.Add("error"); + InputField.Classes.Remove("warning"); + return; + } + + InputField.Classes.Remove("error"); + + if (!hasWarning) { - InputField.Classes.Remove("error"); + InputField.Classes.Remove("warning"); return; } - if (!InputField.Classes.Contains("error")) - InputField.Classes.Add("error"); + if (!InputField.Classes.Contains("warning")) + InputField.Classes.Add("warning"); } protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) @@ -119,7 +140,10 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang if (change.Property == VariantProperty) UpdateStyleClasses(change.GetNewValue()); - if (change.Property == ErrorMessageProperty) - UpdateErrorState(hasError: !string.IsNullOrWhiteSpace(change.GetNewValue())); + if (change.Property == ErrorMessageProperty || change.Property == WarningMessageProperty) + UpdateValidationState( + hasError: !string.IsNullOrWhiteSpace(ErrorMessage), + hasWarning: !string.IsNullOrWhiteSpace(WarningMessage) + ); } } diff --git a/WheelWizard/Views/Pages/FriendsPage.axaml.cs b/WheelWizard/Views/Pages/FriendsPage.axaml.cs index 4a3afe4a..2d8b4957 100644 --- a/WheelWizard/Views/Pages/FriendsPage.axaml.cs +++ b/WheelWizard/Views/Pages/FriendsPage.axaml.cs @@ -169,6 +169,7 @@ private async void AddFriend_OnClick(object? sender, RoutedEventArgs e) .SetPlaceholderText("0000-0000-0000") .SetButtonText(Common.Action_Cancel, Common.Action_Submit) .SetValidation((_, newText) => ValidateFriendCodeInput(newText)) + .SetWarningValidation((_, newText) => ValidateFriendCodeWarning(newText)) .ShowDialog(); if (inputFriendCode == null) @@ -230,13 +231,23 @@ private OperationResult ValidateFriendCodeInput(string? rawFriendCode) if (currentProfileId != 0 && currentProfileId == friendProfileId) return Fail("You cannot add your own friend code."); + return Ok(); + } + + private string? ValidateFriendCodeWarning(string? rawFriendCode) + { + var normalizedFriendCodeResult = NormalizeFriendCode(rawFriendCode ?? string.Empty); + if (normalizedFriendCodeResult.IsFailure) + return null; + + var friendProfileId = FriendCodeGenerator.FriendCodeToProfileId(normalizedFriendCodeResult.Value); var duplicateFriend = GameLicenseService.ActiveCurrentFriends.Any(friend => { var existingPid = FriendCodeGenerator.FriendCodeToProfileId(friend.FriendCode); return existingPid != 0 && existingPid == friendProfileId; }); - return duplicateFriend ? Fail("This friend is already in your list.") : Ok(); + return duplicateFriend ? "This friend is already in your list." : null; } private static OperationResult NormalizeFriendCode(string friendCode) diff --git a/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs index 30a50ce0..78a48a41 100644 --- a/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs +++ b/WheelWizard/Views/Pages/KitchenSinkPage.axaml.cs @@ -17,6 +17,8 @@ public partial class KitchenSinkPage : UserControlBase SectionDefinition.Create(), SectionDefinition.Create(), SectionDefinition.Create(), + SectionDefinition.Create(), + SectionDefinition.Create(), ]; // Add more configurable section groups here. @@ -29,7 +31,9 @@ public partial class KitchenSinkPage : UserControlBase typeof(KitchenSinkInputFieldsPage), typeof(KitchenSinkDropdownsPage), typeof(KitchenSinkButtonsPage), - typeof(KitchenSinkIconLabelsPage) + typeof(KitchenSinkIconLabelsPage), + typeof(KitchenSinkStateBoxesPage), + typeof(KitchenSinkIconsPage) ), ]; diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconsPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconsPage.axaml new file mode 100644 index 00000000..e2295067 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconsPage.axaml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconsPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconsPage.axaml.cs new file mode 100644 index 00000000..dc6562b3 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkIconsPage.axaml.cs @@ -0,0 +1,12 @@ +namespace WheelWizard.Views.Pages.KitchenSink; + +public partial class KitchenSinkIconsPage : KitchenSinkSectionPageBase +{ + public override string SectionName => "Icons"; + public override string? SectionTooltip => null; + + public KitchenSinkIconsPage() + { + InitializeComponent(); + } +} diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml index 16093e06..7bce8c44 100644 --- a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkInputFieldsPage.axaml @@ -9,7 +9,10 @@ + + + @@ -20,10 +23,28 @@ Watermark="Enter display name..." Text="PlayerOne" ErrorMessage="This name is already in use." /> + + + + Text="Disabled behavior component" + IsEnabled="False" /> diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkStateBoxesPage.axaml b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkStateBoxesPage.axaml new file mode 100644 index 00000000..7a2f5839 --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkStateBoxesPage.axaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + diff --git a/WheelWizard/Views/Pages/kitchenSink/KitchenSinkStateBoxesPage.axaml.cs b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkStateBoxesPage.axaml.cs new file mode 100644 index 00000000..7b75436f --- /dev/null +++ b/WheelWizard/Views/Pages/kitchenSink/KitchenSinkStateBoxesPage.axaml.cs @@ -0,0 +1,12 @@ +namespace WheelWizard.Views.Pages.KitchenSink; + +public partial class KitchenSinkStateBoxesPage : KitchenSinkSectionPageBase +{ + public override string SectionName => "State Boxes"; + public override string? SectionTooltip => null; + + public KitchenSinkStateBoxesPage() + { + InitializeComponent(); + } +} diff --git a/WheelWizard/Views/Popups/Generic/TextInputWindow.axaml.cs b/WheelWizard/Views/Popups/Generic/TextInputWindow.axaml.cs index 73fbf1f9..d35898ba 100644 --- a/WheelWizard/Views/Popups/Generic/TextInputWindow.axaml.cs +++ b/WheelWizard/Views/Popups/Generic/TextInputWindow.axaml.cs @@ -17,6 +17,7 @@ public partial class TextInputWindow : PopupContent private TaskCompletionSource? _tcs; private string? _initialText; private Func? inputValidationFunc; // (oldText?, newText) => OperationResult + private Func? warningValidationFunc; // (oldText?, newText) => warningMessage? // Constructor with dynamic label parameter public TextInputWindow() @@ -82,6 +83,12 @@ public TextInputWindow SetValidation(Func vali return this; } + public TextInputWindow SetWarningValidation(Func warningValidationFunction) + { + warningValidationFunc = warningValidationFunction; + return this; + } + public new async Task ShowDialog() { _tcs = new(); @@ -117,11 +124,16 @@ private void InputField_TextChanged(object sender, TextChangedEventArgs e) // Update the Submit button's IsEnabled property based on input private void UpdateSubmitButtonState() { - var inputText = GetInputText(); - var validationResultError = inputValidationFunc?.Invoke(_initialText, inputText!).Error?.Message; + var inputText = GetInputText() ?? string.Empty; + var validationError = inputValidationFunc?.Invoke(_initialText, inputText).Error?.Message; + var warningMessage = warningValidationFunc?.Invoke(_initialText, inputText); + + var hasError = !string.IsNullOrWhiteSpace(validationError); + var hasWarning = !string.IsNullOrWhiteSpace(warningMessage); - SubmitButton.IsEnabled = validationResultError == null; - InputField.ErrorMessage = validationResultError ?? ""; + SubmitButton.IsEnabled = !hasError && !hasWarning; + InputField.ErrorMessage = hasError ? validationError! : string.Empty; + InputField.WarningMessage = !hasError && hasWarning ? warningMessage! : string.Empty; } private void CustomCharsButton_Click(object sender, EventArgs e) diff --git a/WheelWizard/Views/Styles/Styles/TextBoxStyles.axaml b/WheelWizard/Views/Styles/Styles/TextBoxStyles.axaml index 1d0fff4e..e85fd993 100644 --- a/WheelWizard/Views/Styles/Styles/TextBoxStyles.axaml +++ b/WheelWizard/Views/Styles/Styles/TextBoxStyles.axaml @@ -15,6 +15,13 @@ + + + + + + + @@ -81,6 +88,19 @@ + + + + + - \ No newline at end of file + + From 73df0dc51341b74fa5490c8f9f16eb20eff0e1b6 Mon Sep 17 00:00:00 2001 From: WantToBeeMe <93130991+WantToBeeMe@users.noreply.github.com> Date: Sun, 22 Feb 2026 20:50:55 +0100 Subject: [PATCH 09/20] cool --- .../WhWzLibrary => BehaviorComponent}/VrHistoryGraph.axaml | 7 ++++--- .../VrHistoryGraph.axaml.cs | 2 +- WheelWizard/Views/Pages/UserProfilePage.axaml | 6 +++--- WheelWizard/Views/Popups/PlayerProfileWindow.axaml | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) rename WheelWizard/Views/{Components/WhWzLibrary => BehaviorComponent}/VrHistoryGraph.axaml (97%) rename WheelWizard/Views/{Components/WhWzLibrary => BehaviorComponent}/VrHistoryGraph.axaml.cs (99%) diff --git a/WheelWizard/Views/Components/WhWzLibrary/VrHistoryGraph.axaml b/WheelWizard/Views/BehaviorComponent/VrHistoryGraph.axaml similarity index 97% rename from WheelWizard/Views/Components/WhWzLibrary/VrHistoryGraph.axaml rename to WheelWizard/Views/BehaviorComponent/VrHistoryGraph.axaml index 2e968a57..39cc3543 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/VrHistoryGraph.axaml +++ b/WheelWizard/Views/BehaviorComponent/VrHistoryGraph.axaml @@ -2,12 +2,13 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:behaviorComp="clr-namespace:WheelWizard.Views.BehaviorComponent" xmlns:components="clr-namespace:WheelWizard.Views.Components" mc:Ignorable="d" d:DesignWidth="560" d:DesignHeight="390" - x:Class="WheelWizard.Views.Components.VrHistoryGraph" - x:DataType="components:VrHistoryGraph"> + x:Class="WheelWizard.Views.BehaviorComponent.VrHistoryGraph" + x:DataType="behaviorComp:VrHistoryGraph"> - \ No newline at end of file + diff --git a/WheelWizard/Views/Components/StandardLibrary/OptionButton.axaml b/WheelWizard/Views/Components/StandardLibrary/OptionButton.axaml index d6bc7807..9356747a 100644 --- a/WheelWizard/Views/Components/StandardLibrary/OptionButton.axaml +++ b/WheelWizard/Views/Components/StandardLibrary/OptionButton.axaml @@ -27,7 +27,7 @@ - + - + @@ -112,4 +112,4 @@ - \ No newline at end of file + diff --git a/WheelWizard/Views/Layout.axaml b/WheelWizard/Views/Layout.axaml index e2478917..ffb12a9a 100644 --- a/WheelWizard/Views/Layout.axaml +++ b/WheelWizard/Views/Layout.axaml @@ -7,6 +7,7 @@ xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" xmlns:pages="clr-namespace:WheelWizard.Views.Pages" xmlns:components="clr-namespace:WheelWizard.Views.Components" + xmlns:patterns="clr-namespace:WheelWizard.Views.Patterns" Height="876" Width="656" WindowStartupLocation="CenterScreen" SystemDecorations="None" ExtendClientAreaToDecorationsHint="True" @@ -115,41 +116,41 @@ - - - - - - - - - - diff --git a/WheelWizard/Views/Layout.axaml.cs b/WheelWizard/Views/Layout.axaml.cs index 822be5b7..0874d86d 100644 --- a/WheelWizard/Views/Layout.axaml.cs +++ b/WheelWizard/Views/Layout.axaml.cs @@ -15,6 +15,7 @@ using WheelWizard.Utilities.RepeatedTasks; using WheelWizard.Views.Components; using WheelWizard.Views.Pages; +using WheelWizard.Views.Patterns; using WheelWizard.Views.Popups.Generic; using WheelWizard.WheelWizardData.Domain; using WheelWizard.WiiManagement; diff --git a/WheelWizard/Views/Pages/FriendsPage.axaml b/WheelWizard/Views/Pages/FriendsPage.axaml index b7b48699..3da39fbf 100644 --- a/WheelWizard/Views/Pages/FriendsPage.axaml +++ b/WheelWizard/Views/Pages/FriendsPage.axaml @@ -6,6 +6,7 @@ xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" xmlns:components="clr-namespace:WheelWizard.Views.Components" xmlns:behaviorComponent="clr-namespace:WheelWizard.Views.Patterns" + xmlns:patterns="clr-namespace:WheelWizard.Views.Patterns" xmlns:domain="clr-namespace:WheelWizard.WiiManagement.GameLicense.Domain" x:Class="WheelWizard.Views.Pages.FriendsPage"> @@ -74,7 +75,7 @@ ScrollViewer.VerticalScrollBarVisibility="Auto"> - - - - - @@ -189,7 +190,7 @@ RowDefinitions="Auto,16" VerticalAlignment="Center" ColumnDefinitions="*,1.1*,*"> - - + @@ -214,10 +215,10 @@ - - + + - - + @@ -243,10 +244,10 @@ - - + + - - + @@ -271,8 +272,8 @@ - - + + @@ -280,7 +281,7 @@ - - + @@ -303,8 +304,8 @@ - - + + diff --git a/WheelWizard/Views/Pages/MiiListPage.axaml b/WheelWizard/Views/Pages/MiiListPage.axaml index 72d5f9bb..6240715a 100644 --- a/WheelWizard/Views/Pages/MiiListPage.axaml +++ b/WheelWizard/Views/Pages/MiiListPage.axaml @@ -83,9 +83,9 @@ - + - \ No newline at end of file + diff --git a/WheelWizard/Views/Pages/MiiListPage.axaml.cs b/WheelWizard/Views/Pages/MiiListPage.axaml.cs index 1b81890d..90b70267 100644 --- a/WheelWizard/Views/Pages/MiiListPage.axaml.cs +++ b/WheelWizard/Views/Pages/MiiListPage.axaml.cs @@ -13,6 +13,7 @@ using WheelWizard.Shared.DependencyInjection; using WheelWizard.Shared.MessageTranslations; using WheelWizard.Views.Components; +using WheelWizard.Views.Patterns; using WheelWizard.Views.Popups.Generic; using WheelWizard.Views.Popups.MiiManagement; using WheelWizard.WiiManagement; diff --git a/WheelWizard/Views/Pages/ModsPage.axaml b/WheelWizard/Views/Pages/ModsPage.axaml index a7c7ff0a..d1172de8 100644 --- a/WheelWizard/Views/Pages/ModsPage.axaml +++ b/WheelWizard/Views/Pages/ModsPage.axaml @@ -4,6 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" xmlns:components="clr-namespace:WheelWizard.Views.Components" + xmlns:patterns="clr-namespace:WheelWizard.Views.Patterns" xmlns:pages="clr-namespace:WheelWizard.Views.Pages" mc:Ignorable="d" d:DesignWidth="656" d:DesignHeight="876" x:Class="WheelWizard.Views.Pages.ModsPage" @@ -208,7 +209,7 @@ - + @@ -229,4 +230,4 @@ - \ No newline at end of file + diff --git a/WheelWizard/Views/Pages/RoomDetailsPage.axaml b/WheelWizard/Views/Pages/RoomDetailsPage.axaml index 0c2a78e4..f1271c64 100644 --- a/WheelWizard/Views/Pages/RoomDetailsPage.axaml +++ b/WheelWizard/Views/Pages/RoomDetailsPage.axaml @@ -5,6 +5,7 @@ mc:Ignorable="d" d:DesignHeight="876" d:DesignWidth="456" xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" xmlns:components="clr-namespace:WheelWizard.Views.Components" + xmlns:patterns="clr-namespace:WheelWizard.Views.Patterns" xmlns:pages="clr-namespace:WheelWizard.Views.Pages" x:Class="WheelWizard.Views.Pages.RoomDetailsPage" x:DataType="pages:RoomDetailsPage"> @@ -86,7 +87,7 @@ SelectionChanged="PlayerView_SelectionChanged"> - @@ -139,7 +140,7 @@ SelectionChanged="PlayerView_SelectionChanged"> - - - + - - - \ No newline at end of file + + diff --git a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml index 11c10858..02ee9b18 100644 --- a/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml +++ b/WheelWizard/Views/Patterns/MiiImages/MiiImageLoaderWithHover.axaml @@ -9,7 +9,7 @@ xmlns:conv="clr-namespace:WheelWizard.Views.Converters" x:DataType="behaviorComp:MiiImageLoaderWithHover" x:Name="Self" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"> - - + diff --git a/WheelWizard/Views/Components/StandardLibrary/SidebarRadioButton.axaml b/WheelWizard/Views/Patterns/SidebarRadioButton.axaml similarity index 88% rename from WheelWizard/Views/Components/StandardLibrary/SidebarRadioButton.axaml rename to WheelWizard/Views/Patterns/SidebarRadioButton.axaml index 8a9f04a0..d96c53fd 100644 --- a/WheelWizard/Views/Components/StandardLibrary/SidebarRadioButton.axaml +++ b/WheelWizard/Views/Patterns/SidebarRadioButton.axaml @@ -2,27 +2,28 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" xmlns:pages="clr-namespace:WheelWizard.Views.Pages" - xmlns:components="clr-namespace:WheelWizard.Views.Components"> + xmlns:components="clr-namespace:WheelWizard.Views.Components" + xmlns:patterns="clr-namespace:WheelWizard.Views.Patterns"> - - - - - @@ -30,7 +31,7 @@ - - - - \ No newline at end of file + diff --git a/WheelWizard/Views/Components/StandardLibrary/SidebarRadioButton.axaml.cs b/WheelWizard/Views/Patterns/SidebarRadioButton.axaml.cs similarity index 98% rename from WheelWizard/Views/Components/StandardLibrary/SidebarRadioButton.axaml.cs rename to WheelWizard/Views/Patterns/SidebarRadioButton.axaml.cs index 7bc00fea..3e232f80 100644 --- a/WheelWizard/Views/Components/StandardLibrary/SidebarRadioButton.axaml.cs +++ b/WheelWizard/Views/Patterns/SidebarRadioButton.axaml.cs @@ -5,7 +5,7 @@ using Avalonia.Media; using WheelWizard.Views.Pages; -namespace WheelWizard.Views.Components; +namespace WheelWizard.Views.Patterns; public partial class SidebarRadioButton : RadioButton { diff --git a/WheelWizard/Views/Components/WhWzLibrary/FriendsListItem.axaml b/WheelWizard/Views/Patterns/WhWzLibrary/FriendsListItem.axaml similarity index 91% rename from WheelWizard/Views/Components/WhWzLibrary/FriendsListItem.axaml rename to WheelWizard/Views/Patterns/WhWzLibrary/FriendsListItem.axaml index 75567b28..6b363241 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/FriendsListItem.axaml +++ b/WheelWizard/Views/Patterns/WhWzLibrary/FriendsListItem.axaml @@ -3,38 +3,39 @@ xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" xmlns:components="clr-namespace:WheelWizard.Views.Components" xmlns:miiVars="using:WheelWizard.MiiImages.Domain" - xmlns:behaviorComponent="clr-namespace:WheelWizard.Views.Patterns"> + xmlns:behaviorComponent="clr-namespace:WheelWizard.Views.Patterns" + xmlns:patterns="clr-namespace:WheelWizard.Views.Patterns"> - - - - - - - - - diff --git a/WheelWizard/Views/Components/WhWzLibrary/FriendsListItem.axaml.cs b/WheelWizard/Views/Patterns/WhWzLibrary/FriendsListItem.axaml.cs similarity index 97% rename from WheelWizard/Views/Components/WhWzLibrary/FriendsListItem.axaml.cs rename to WheelWizard/Views/Patterns/WhWzLibrary/FriendsListItem.axaml.cs index 3a14bd0a..0926fc73 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/FriendsListItem.axaml.cs +++ b/WheelWizard/Views/Patterns/WhWzLibrary/FriendsListItem.axaml.cs @@ -1,11 +1,12 @@ -using Avalonia; +using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Interactivity; using WheelWizard.WheelWizardData; using WheelWizard.WiiManagement.MiiManagement.Domain.Mii; +using Badge = WheelWizard.Views.Components.Badge; -namespace WheelWizard.Views.Components; +namespace WheelWizard.Views.Patterns; public class FriendsListItem : TemplatedControl { diff --git a/WheelWizard/Views/Components/WhWzLibrary/GridModPanel.axaml b/WheelWizard/Views/Patterns/WhWzLibrary/GridModPanel.axaml similarity index 98% rename from WheelWizard/Views/Components/WhWzLibrary/GridModPanel.axaml rename to WheelWizard/Views/Patterns/WhWzLibrary/GridModPanel.axaml index da766fd9..718be87a 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/GridModPanel.axaml +++ b/WheelWizard/Views/Patterns/WhWzLibrary/GridModPanel.axaml @@ -3,7 +3,7 @@ xmlns:components="clr-namespace:WheelWizard.Views.Components" xmlns:pages="clr-namespace:WheelWizard.Views.Pages" xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" - x:Class="WheelWizard.Views.Components.GridModPanel" + x:Class="WheelWizard.Views.Patterns.GridModPanel" x:DataType="pages:ModListItem"> - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + diff --git a/WheelWizard/Views/Components/WhWzLibrary/MiiBlock.axaml.cs b/WheelWizard/Views/Patterns/WhWzLibrary/MiiBlock.axaml.cs similarity index 98% rename from WheelWizard/Views/Components/WhWzLibrary/MiiBlock.axaml.cs rename to WheelWizard/Views/Patterns/WhWzLibrary/MiiBlock.axaml.cs index 4603aa50..c55f1c76 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/MiiBlock.axaml.cs +++ b/WheelWizard/Views/Patterns/WhWzLibrary/MiiBlock.axaml.cs @@ -5,12 +5,11 @@ using Avalonia.Interactivity; using WheelWizard.MiiImages; using WheelWizard.MiiImages.Domain; -using WheelWizard.Views.Patterns; using WheelWizard.WiiManagement; using WheelWizard.WiiManagement.MiiManagement; using WheelWizard.WiiManagement.MiiManagement.Domain.Mii; -namespace WheelWizard.Views.Components; +namespace WheelWizard.Views.Patterns; public class MiiBlock : RadioButton { diff --git a/WheelWizard/Views/Components/WhWzLibrary/ModBrowserListItem.axaml b/WheelWizard/Views/Patterns/WhWzLibrary/ModBrowserListItem.axaml similarity index 91% rename from WheelWizard/Views/Components/WhWzLibrary/ModBrowserListItem.axaml rename to WheelWizard/Views/Patterns/WhWzLibrary/ModBrowserListItem.axaml index 1487b2e6..1d8014e6 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/ModBrowserListItem.axaml +++ b/WheelWizard/Views/Patterns/WhWzLibrary/ModBrowserListItem.axaml @@ -1,33 +1,34 @@ + xmlns:components="using:WheelWizard.Views.Components" + xmlns:patterns="clr-namespace:WheelWizard.Views.Patterns"> - - - - - - - - diff --git a/WheelWizard/Views/Components/WhWzLibrary/ModBrowserListItem.axaml.cs b/WheelWizard/Views/Patterns/WhWzLibrary/ModBrowserListItem.axaml.cs similarity index 98% rename from WheelWizard/Views/Components/WhWzLibrary/ModBrowserListItem.axaml.cs rename to WheelWizard/Views/Patterns/WhWzLibrary/ModBrowserListItem.axaml.cs index 199eae95..22cc887e 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/ModBrowserListItem.axaml.cs +++ b/WheelWizard/Views/Patterns/WhWzLibrary/ModBrowserListItem.axaml.cs @@ -3,7 +3,7 @@ using Avalonia.Controls.Primitives; using Avalonia.Media.Imaging; -namespace WheelWizard.Views.Components; +namespace WheelWizard.Views.Patterns; public class ModBrowserListItem : TemplatedControl { diff --git a/WheelWizard/Views/Components/WhWzLibrary/PlayerListItem.axaml b/WheelWizard/Views/Patterns/WhWzLibrary/PlayerListItem.axaml similarity index 91% rename from WheelWizard/Views/Components/WhWzLibrary/PlayerListItem.axaml rename to WheelWizard/Views/Patterns/WhWzLibrary/PlayerListItem.axaml index 667c90c4..bc58f7e6 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/PlayerListItem.axaml +++ b/WheelWizard/Views/Patterns/WhWzLibrary/PlayerListItem.axaml @@ -2,11 +2,12 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:lang="clr-namespace:WheelWizard.Resources.Languages" xmlns:components="using:WheelWizard.Views.Components" + xmlns:patterns="clr-namespace:WheelWizard.Views.Patterns" xmlns:miiVars="using:WheelWizard.MiiImages.Domain" xmlns:behaviorComponent="clr-namespace:WheelWizard.Views.Patterns"> - - - - - - - - - diff --git a/WheelWizard/Views/Components/WhWzLibrary/PlayerListItem.axaml.cs b/WheelWizard/Views/Patterns/WhWzLibrary/PlayerListItem.axaml.cs similarity index 95% rename from WheelWizard/Views/Components/WhWzLibrary/PlayerListItem.axaml.cs rename to WheelWizard/Views/Patterns/WhWzLibrary/PlayerListItem.axaml.cs index 8b26cc67..9a8e2db5 100644 --- a/WheelWizard/Views/Components/WhWzLibrary/PlayerListItem.axaml.cs +++ b/WheelWizard/Views/Patterns/WhWzLibrary/PlayerListItem.axaml.cs @@ -4,12 +4,13 @@ using Avalonia.Interactivity; using WheelWizard.WheelWizardData; using WheelWizard.WiiManagement.MiiManagement.Domain.Mii; +using Badge = WheelWizard.Views.Components.Badge; -namespace WheelWizard.Views.Components; +namespace WheelWizard.Views.Patterns; public class PlayerListItem : TemplatedControl { - private Button? _joinRoomButton; + private Avalonia.Controls.Button? _joinRoomButton; public static readonly StyledProperty IsOnlineProperty = AvaloniaProperty.Register(nameof(IsOnline)); public static readonly StyledProperty ShowJoinRoomButtonProperty = AvaloniaProperty.Register( @@ -147,7 +148,7 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) if (_joinRoomButton != null) _joinRoomButton.Click -= JoinRoom_OnClick; - _joinRoomButton = e.NameScope.Find