From 0b062651176340c8415f9cc2ccf24f17f9dbcc91 Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Wed, 27 Aug 2025 03:00:31 -0500 Subject: [PATCH 1/4] UI: Replace two-column Grid with SplitView; add narrow pane toggle; add WidthToBooleanConverter and width-based DisplayMode triggers for a responsive layout across Web, Desktop, Android. --- .../Converters/WidthToBooleanConverter.cs | 31 +++ src/AdvancedCalculator/Views/MainView.axaml | 205 +++++++++++------- 2 files changed, 153 insertions(+), 83 deletions(-) create mode 100644 src/AdvancedCalculator/Converters/WidthToBooleanConverter.cs diff --git a/src/AdvancedCalculator/Converters/WidthToBooleanConverter.cs b/src/AdvancedCalculator/Converters/WidthToBooleanConverter.cs new file mode 100644 index 0000000..6efa5f6 --- /dev/null +++ b/src/AdvancedCalculator/Converters/WidthToBooleanConverter.cs @@ -0,0 +1,31 @@ +using System; +using System.Globalization; +using Avalonia.Data.Converters; + +namespace AdvancedCalculator.Converters; + +// Returns true if width (double) is less than the provided threshold (parameter), +// otherwise false. Default threshold is 640 when parameter is null or invalid. +public class WidthToBooleanConverter : IValueConverter +{ + public static readonly WidthToBooleanConverter Instance = new(); + + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo? culture) + { + if (value is double width) + { + double threshold = 640; + if (parameter is double p) + threshold = p; + else if (parameter is string s && double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var parsed)) + threshold = parsed; + + return width < threshold; + } + return false; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo? culture) + => throw new NotSupportedException(); +} + diff --git a/src/AdvancedCalculator/Views/MainView.axaml b/src/AdvancedCalculator/Views/MainView.axaml index 71ffac9..35b2c61 100644 --- a/src/AdvancedCalculator/Views/MainView.axaml +++ b/src/AdvancedCalculator/Views/MainView.axaml @@ -10,92 +10,131 @@ x:DataType="vm:MainViewModel"> + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 055c2fae036353bc8663198f20f906bc165a5f6c Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Wed, 27 Aug 2025 03:03:07 -0500 Subject: [PATCH 2/4] UX touch-friendly: add Evaluate button; increase min sizes/spacing; make variables/functions tap-to-insert via InsertVariable/InsertFunction commands. --- .../ViewModels/MainViewModel.cs | 31 ++++++++ src/AdvancedCalculator/Views/MainView.axaml | 77 +++++++++++-------- 2 files changed, 74 insertions(+), 34 deletions(-) diff --git a/src/AdvancedCalculator/ViewModels/MainViewModel.cs b/src/AdvancedCalculator/ViewModels/MainViewModel.cs index 1611402..7be1cf6 100644 --- a/src/AdvancedCalculator/ViewModels/MainViewModel.cs +++ b/src/AdvancedCalculator/ViewModels/MainViewModel.cs @@ -41,6 +41,37 @@ public partial class MainViewModel : ViewModelBase IsFunctionsPanelOpen = !IsFunctionsPanelOpen; } + // Insert helpers for touch: appends tokens to the input box + [RelayCommand] + private void InsertVariable(string? variableName) + { + if (string.IsNullOrWhiteSpace(variableName)) + return; + InsertToken(variableName); + } + + [RelayCommand] + private void InsertFunction(string? functionName) + { + if (string.IsNullOrWhiteSpace(functionName)) + return; + InsertToken(functionName + "()"); + } + + private void InsertToken(string token) + { + if (string.IsNullOrEmpty(InputText)) + { + InputText = token; + return; + } + + if (!char.IsWhiteSpace(InputText[^1])) + InputText += " "; + + InputText += token; + } + [RelayCommand(AllowConcurrentExecutions = false)] private async Task Submit() { diff --git a/src/AdvancedCalculator/Views/MainView.axaml b/src/AdvancedCalculator/Views/MainView.axaml index 35b2c61..f693853 100644 --- a/src/AdvancedCalculator/Views/MainView.axaml +++ b/src/AdvancedCalculator/Views/MainView.axaml @@ -49,44 +49,52 @@ - + - - - - - - - - + - - - - - + @@ -113,7 +121,7 @@ - + + - - - - - + + + + From a212870d09e5880f51e842726890b1825bf2b592 Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Wed, 27 Aug 2025 03:07:30 -0500 Subject: [PATCH 3/4] A11y + empty states: add AutomationProperties names to controls; overlay empty-state hints for Variables and History; add input Watermark. --- src/AdvancedCalculator/Views/MainView.axaml | 124 +++++++++++++------- 1 file changed, 84 insertions(+), 40 deletions(-) diff --git a/src/AdvancedCalculator/Views/MainView.axaml b/src/AdvancedCalculator/Views/MainView.axaml index f693853..ba2be2e 100644 --- a/src/AdvancedCalculator/Views/MainView.axaml +++ b/src/AdvancedCalculator/Views/MainView.axaml @@ -48,35 +48,56 @@ - - - - - - - - + + + + + + + + + + + + + + + + ItemsSource="{x:Static m:FunctionDefinitionItem.DefinedFunctions}" + AutomationProperties.Name="Functions list"> - + - From 7e40c1dc0bb878a1c4d7ded75867e01b15ae236b Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Wed, 27 Aug 2025 03:15:47 -0500 Subject: [PATCH 4/4] Styles: add shared Typography/Scroll resources; add platform overrides (Desktop/Android/Browser) and load via App; switch icons to resource-based sizes and cap history text lines. --- .../Styles/Android.axaml | 17 +++++++++ .../Styles/Browser.axaml | 16 +++++++++ .../Styles/Desktop.axaml | 16 +++++++++ src/AdvancedCalculator/App.axaml | 2 ++ src/AdvancedCalculator/App.axaml.cs | 36 +++++++++++++++++++ src/AdvancedCalculator/Styles/Scroll.axaml | 21 +++++++++++ .../Styles/Typography.axaml | 30 ++++++++++++++++ src/AdvancedCalculator/Views/MainView.axaml | 12 +++---- 8 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 src/AdvancedCalculator.Android/Styles/Android.axaml create mode 100644 src/AdvancedCalculator.Browser/Styles/Browser.axaml create mode 100644 src/AdvancedCalculator.Desktop/Styles/Desktop.axaml create mode 100644 src/AdvancedCalculator/Styles/Scroll.axaml create mode 100644 src/AdvancedCalculator/Styles/Typography.axaml diff --git a/src/AdvancedCalculator.Android/Styles/Android.axaml b/src/AdvancedCalculator.Android/Styles/Android.axaml new file mode 100644 index 0000000..30f7e04 --- /dev/null +++ b/src/AdvancedCalculator.Android/Styles/Android.axaml @@ -0,0 +1,17 @@ + + + 16 + 18 + 24 + 1.35 + + + + + + diff --git a/src/AdvancedCalculator.Browser/Styles/Browser.axaml b/src/AdvancedCalculator.Browser/Styles/Browser.axaml new file mode 100644 index 0000000..3842c71 --- /dev/null +++ b/src/AdvancedCalculator.Browser/Styles/Browser.axaml @@ -0,0 +1,16 @@ + + + 15 + 22 + 1.3 + + + + + + diff --git a/src/AdvancedCalculator.Desktop/Styles/Desktop.axaml b/src/AdvancedCalculator.Desktop/Styles/Desktop.axaml new file mode 100644 index 0000000..7a951d8 --- /dev/null +++ b/src/AdvancedCalculator.Desktop/Styles/Desktop.axaml @@ -0,0 +1,16 @@ + + + 13 + 1.2 + 20 + + + + + + diff --git a/src/AdvancedCalculator/App.axaml b/src/AdvancedCalculator/App.axaml index 5e686cd..8d7bed3 100644 --- a/src/AdvancedCalculator/App.axaml +++ b/src/AdvancedCalculator/App.axaml @@ -6,6 +6,8 @@ + + diff --git a/src/AdvancedCalculator/App.axaml.cs b/src/AdvancedCalculator/App.axaml.cs index e967b3b..32716eb 100644 --- a/src/AdvancedCalculator/App.axaml.cs +++ b/src/AdvancedCalculator/App.axaml.cs @@ -5,6 +5,8 @@ using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Data.Core.Plugins; using Avalonia.Markup.Xaml; +using Avalonia.Styling; +using System; namespace AdvancedCalculator; @@ -21,6 +23,40 @@ public partial class App : Application // Without this line you will get duplicate validations from both Avalonia and CT BindingPlugins.DataValidators.RemoveAt(0); + // Load platform-specific styles (typography, scrollbars overrides) + try + { + var styles = Current?.Styles; + if (styles is not null) + { + if (OperatingSystem.IsAndroid()) + { + styles.Add(new StyleInclude(new Uri("avares://AdvancedCalculator/")) + { + Source = new Uri("avares://AdvancedCalculator.Android/Styles/Android.axaml") + }); + } + else if (OperatingSystem.IsBrowser()) + { + styles.Add(new StyleInclude(new Uri("avares://AdvancedCalculator/")) + { + Source = new Uri("avares://AdvancedCalculator.Browser/Styles/Browser.axaml") + }); + } + else + { + styles.Add(new StyleInclude(new Uri("avares://AdvancedCalculator/")) + { + Source = new Uri("avares://AdvancedCalculator.Desktop/Styles/Desktop.axaml") + }); + } + } + } + catch + { + // If a platform-specific style dictionary is missing, continue without failing. + } + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { desktop.MainWindow = new MainWindow diff --git a/src/AdvancedCalculator/Styles/Scroll.axaml b/src/AdvancedCalculator/Styles/Scroll.axaml new file mode 100644 index 0000000..ea9284d --- /dev/null +++ b/src/AdvancedCalculator/Styles/Scroll.axaml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/src/AdvancedCalculator/Styles/Typography.axaml b/src/AdvancedCalculator/Styles/Typography.axaml new file mode 100644 index 0000000..eb80272 --- /dev/null +++ b/src/AdvancedCalculator/Styles/Typography.axaml @@ -0,0 +1,30 @@ + + + 12 + 14 + 16 + 20 + + 18 + 22 + 26 + + 1.1 + 1.25 + 1.4 + + + + + + + + diff --git a/src/AdvancedCalculator/Views/MainView.axaml b/src/AdvancedCalculator/Views/MainView.axaml index ba2be2e..d5fc5e7 100644 --- a/src/AdvancedCalculator/Views/MainView.axaml +++ b/src/AdvancedCalculator/Views/MainView.axaml @@ -59,8 +59,8 @@ Background="Transparent" BorderThickness="0" Padding="8" MinHeight="44" AutomationProperties.Name="Insert variable"> - + @@ -132,11 +132,11 @@ - + - - + +