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/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/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/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 71ffac9..d5fc5e7 100644 --- a/src/AdvancedCalculator/Views/MainView.axaml +++ b/src/AdvancedCalculator/Views/MainView.axaml @@ -10,92 +10,184 @@ x:DataType="vm:MainViewModel"> + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +