Compare commits

..

2 Commits

Author SHA1 Message Date
dd3cff0eaa AutoGrid and build.sh 2026-01-11 06:02:25 +05:00
a08838bb8b made buttons square and added hotkeys 2026-01-11 04:27:37 +05:00
11 changed files with 168 additions and 108 deletions

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "FusionCalculator"]
path = FusionCalculator
url = https://timerix.ddns.net:3322/Timerix/FusionCalculator.git
url = https://timerix.ddns.net/git/Timerix/FusionCalculator.git

View File

@@ -7,7 +7,7 @@ Requirements: git, bash, [dotnet8](https://dotnet.microsoft.com/en-us/download/d
1. ensure that [FusionCalculator](https://github.com/Timerix22/FusionCalculator) submodule is up-to-date.
```shell
git submodule init && git submodule update
it submodule update --init
```
2. Translate FusionCalculator to C#
```shell

View File

@@ -11,14 +11,14 @@
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style Selector="Button.cirlce">
<Setter Property="Height" Value="60"/>
<Setter Property="Width" Value="60"/>
<Setter Property="CornerRadius" Value="30"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Style Selector="Button.button">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="1"/>
<Setter Property="Padding" Value="0"/>
</Style>
<Style Selector="Button.gray">

View File

@@ -4,7 +4,6 @@ global using System.Globalization;
global using Avalonia;
global using Avalonia.Controls;
global using Avalonia.Interactivity;
global using Avalonia.Media;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;

View File

@@ -1,162 +1,176 @@
<Window
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ag="clr-namespace:AvaloniaAutoGrid;assembly=AvaloniaAutoGrid"
x:Class="SharpCalculator.Avalonia.MainWindow"
Title="SharpCalculator"
Icon="avares://SharpCalculator.Avalonia/assets/icon.ico"
FontFamily="Consolas" FontSize="24"
MinWidth="460" MinHeight="570"
Width="460" Height="570">
<Grid Margin="10">
<Grid.RowDefinitions>1* 40 1* 330</Grid.RowDefinitions>
<TextBox Name="Input" Grid.Row="0"
<!-- ReSharper disable Xaml.MissingGridIndex -->
<ag:AutoGrid Margin="10"
ColumnDefinitions="*"
RowDefinitions="1* 40 1* 330">
<TextBox Name="Input"
TextChanged="Input_OnTextChanged"
BorderThickness="2"
BorderBrush="#AAAAAA"
TextWrapping="Wrap"/>
TextWrapping="Wrap"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"/>
<TextBlock Grid.Row="1"
VerticalAlignment="Center"
Foreground="#AAAAAA"
Text="="/>
<TextBox Name="Output" Grid.Row="1"
Margin="16 0 0 0"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
IsReadOnly="True"
BorderThickness="0"
TextWrapping="NoWrap"/>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Foreground="#AAAAAA"
Text="="/>
<TextBox Name="Output"
Margin="16 0 0 0"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
IsReadOnly="True"
BorderThickness="0"
TextWrapping="NoWrap"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Disabled"/>
</StackPanel>
<TextBox Name="History" Grid.Row="2"
<TextBox Name="History"
Foreground="Gray"
BorderThickness="1"
BorderBrush="Gray"
IsReadOnly="True"
TextWrapping="NoWrap"
FontSize="18"/>
FontSize="18"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"/>
<Grid Grid.Row="3" VerticalAlignment="Bottom"
MinWidth="440" MaxWidth="440" MinHeight="320" MaxHeight="320">
<Grid.ColumnDefinitions>* * * * * * *</Grid.ColumnDefinitions>
<Grid.RowDefinitions>* * * * *</Grid.RowDefinitions>
<!-- ReSharper disable once Xaml.MissingGridIndex -->
<ag:AutoGrid
ColumnDefinitions="*"
RowDefinitions="*"
ColumnCount="7" RowCount="5"
VerticalAlignment="Bottom"
MinWidth="440" MaxWidth="440"
MinHeight="320" MaxHeight="320">
<!-- 1st row -->
<Button Classes="cirlce gray" Grid.Column="0" Grid.Row="0"
<Button Classes="button gray"
Click="ClearButton_OnClick" Content="AC"/>
<Button Classes="cirlce gray" Grid.Column="1" Grid.Row="0"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="("/>
<Button Classes="cirlce gray" Grid.Column="2" Grid.Row="0"
<Button Classes="button gray"
Click="MathButton_OnClick" Content=")" />
<Button Classes="cirlce orange" Grid.Column="3" Grid.Row="0"
<Button Classes="button orange"
Click="MathButton_OnClick" Content="/"/>
<Button Classes="cirlce gray" Grid.Column="4" Grid.Row="0"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="1/x"/>
<Button Classes="cirlce gray" Grid.Column="5" Grid.Row="0"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="sin"/>
<Button Classes="cirlce gray" Grid.Column="6" Grid.Row="0"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="asin"/>
<!-- 2nd row -->
<Button Classes="cirlce" Grid.Column="0" Grid.Row="1"
<Button Classes="button"
Click="MathButton_OnClick" Content="7"/>
<Button Classes="cirlce" Grid.Column="1" Grid.Row="1"
<Button Classes="button"
Click="MathButton_OnClick" Content="8"/>
<Button Classes="cirlce" Grid.Column="2" Grid.Row="1"
<Button Classes="button"
Click="MathButton_OnClick" Content="9"/>
<Button Classes="cirlce orange" Grid.Column="3" Grid.Row="1"
<Button Classes="button orange"
Click="MathButton_OnClick" Content="*"/>
<Button Classes="cirlce gray" Grid.Column="4" Grid.Row="1"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="^"/>
<Button Classes="cirlce gray" Grid.Column="5" Grid.Row="1"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="cos"/>
<Button Classes="cirlce gray" Grid.Column="6" Grid.Row="1"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="acos"/>
<!-- 3th row -->
<Button Classes="cirlce" Grid.Column="0" Grid.Row="2"
<Button Classes="button"
Click="MathButton_OnClick" Content="4"/>
<Button Classes="cirlce" Grid.Column="1" Grid.Row="2"
<Button Classes="button"
Click="MathButton_OnClick" Content="5"/>
<Button Classes="cirlce" Grid.Column="2" Grid.Row="2"
<Button Classes="button"
Click="MathButton_OnClick" Content="6"/>
<Button Classes="cirlce orange" Grid.Column="3" Grid.Row="2"
<Button Classes="button orange"
Click="MathButton_OnClick" Content="-"/>
<Button Classes="cirlce gray" Grid.Column="4" Grid.Row="2"
<Button Classes="button gray"
FontSize="22"
Click="MathButton_OnClick" Content="10^x"/>
<Button Classes="cirlce gray" Grid.Column="5" Grid.Row="2"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="tg"/>
<Button Classes="cirlce gray" Grid.Column="6" Grid.Row="2"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="atg"/>
<!-- 4th row -->
<Button Classes="cirlce" Grid.Column="0" Grid.Row="3"
<Button Classes="button"
Click="MathButton_OnClick" Content="1"/>
<Button Classes="cirlce" Grid.Column="1" Grid.Row="3"
<Button Classes="button"
Click="MathButton_OnClick" Content="2"/>
<Button Classes="cirlce" Grid.Column="2" Grid.Row="3"
<Button Classes="button"
Click="MathButton_OnClick" Content="3"/>
<Button Classes="cirlce orange" Grid.Column="3" Grid.Row="3"
<Button Classes="button orange"
Click="MathButton_OnClick" Content="+"/>
<Button Classes="cirlce gray" Grid.Column="4" Grid.Row="3"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="e"/>
<Button Classes="cirlce gray" Grid.Column="5" Grid.Row="3"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="ctg"/>
<Button Classes="cirlce gray" Grid.Column="6" Grid.Row="3"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="actg"/>
<!-- 5th row -->
<Button Classes="cirlce" Grid.Column="0" Grid.Row="4"
<Button Classes="button"
Click="MathButton_OnClick" Content="0"/>
<Button Classes="cirlce" Grid.Column="1" Grid.Row="4"
<Button Classes="button"
Click="MathButton_OnClick" Content="."/>
<Button Classes="cirlce" Grid.Column="2" Grid.Row="4"
<Button Classes="button"
Click="MathButton_OnClick" Content="%"/>
<Button Classes="cirlce orange" Grid.Column="3" Grid.Row="4"
<Button Classes="button orange"
Click="ResultButton_OnClick" Content="="/>
<Button Classes="cirlce gray" Grid.Column="4" Grid.Row="4"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="π"/>
<Button Classes="cirlce gray" Grid.Column="5" Grid.Row="4"
<Button Classes="button gray"
FontSize="22"
Click="MathButton_OnClick" Content="rand"/>
<Button Classes="cirlce gray" Grid.Column="6" Grid.Row="4"
<Button Classes="button gray"
Click="MathButton_OnClick" Content="ln"/>
</Grid>
</Grid>
</ag:AutoGrid>
</ag:AutoGrid>
</Window>

View File

@@ -1,3 +1,4 @@
using Avalonia.Input;
using FusionCalculator;
namespace SharpCalculator.Avalonia;
@@ -9,6 +10,31 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();
// https://github.com/AvaloniaUI/Avalonia/discussions/12179
KeyDownEvent.AddClassHandler<TopLevel>(GlobalOnKeyDown, handledEventsToo: true);
}
private void GlobalOnKeyDown(object? sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Enter:
CalculateResult();
break;
case Key.Delete:
Clear();
break;
}
}
private void CalculateResult()
{
if(Input.Text == null || Output.Text == null || Output.Text.StartsWith("Error"))
return;
string expression = Input.Text;
string result = Output.Text;
AppendToHistory($"{expression}={result}");
Input.Text = result;
}
private void AppendToHistory(string line) //function of appending expression to the history list
@@ -24,6 +50,23 @@ public partial class MainWindow : Window
.Replace(" ", " ");
}
private void Clear()
{
Input.Clear();
Output.Clear();
}
private void ResultButton_OnClick(object? sender, RoutedEventArgs e)
{
CalculateResult();
}
private void ClearButton_OnClick(object? sender, RoutedEventArgs e)
{
Clear();
}
private void MathButton_OnClick(object? sender, RoutedEventArgs e)
{
if (sender is not Button button)
@@ -48,30 +91,6 @@ public partial class MainWindow : Window
_ => buttonText
};
}
private void ClearButton_OnClick(object? sender, RoutedEventArgs e)
{
Input.Text = "";
Output.Text = "";
}
private void UndoButton_OnClick(object? sender, RoutedEventArgs e)
{
// delete last digit
// if (!string.IsNullOrEmpty(Input.Text))
// Input.Text = Input.Text.Remove(Input.Text.Length - 1);
Input.Undo();
}
private void ResultButton_OnClick(object? sender, RoutedEventArgs e)
{
if(Input.Text == null || Output.Text == null || Output.Text.StartsWith("Error"))
return;
string expression = Input.Text;
string result = Output.Text;
AppendToHistory($"{expression}={result}");
Input.Text = result;
}
private void Input_OnTextChanged(object? sender, TextChangedEventArgs e)
{

View File

@@ -1,8 +1,4 @@
using Avalonia;
using System;
using System.Globalization;
namespace SharpCalculator.Avalonia;
namespace SharpCalculator.Avalonia;
class Program
{

View File

@@ -1,20 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12</LangVersion>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>disable</ImplicitUsings>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<ApplicationIcon>assets\icon.ico</ApplicationIcon>
<PublishTrimmed>true</PublishTrimmed>
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.6" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.6" />
<PackageReference Include="Avalonia.Themes.Simple" Version="11.0.6" />
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.6" />
<PackageReference Include="Avalonia" Version="11.3.10" />
<PackageReference Include="Avalonia.Desktop" Version="11.3.10" />
<PackageReference Include="Avalonia.Themes.Simple" Version="11.3.10" />
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.3.10" />
<PackageReference Include="Russkyc.AvaloniaAutoGrid" Version="1.0.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
@@ -9,13 +9,13 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.6.4" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>

View File

@@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution_items", "solution_
.gitignore = .gitignore
.gitmodules = .gitmodules
README.md = README.md
build.sh = build.sh
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCalculator.Tests", "SharpCalculator.Tests\SharpCalculator.Tests.csproj", "{E929E48D-D11B-4FB5-AC6F-D0D50E2B3BD1}"

28
build.sh Normal file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -eo pipefail
outdir="bin"
project="SharpCalculator.Avalonia"
# Somebody broke dotnet10 sdk .target files
# To publish self-contained trimmed binary you should add <PublishTrimmed>true</PublishTrimmed> to project file.
# Command-line option -p:PublishTrimmed=true produces an error.
# Same with <PublishAot>true</PublishAot> if you want AOT compilation.
args="
--self-contained
--use-current-runtime
-p:PublishSingleFile=true
-p:TrimMode=partial
-p:EnableCompressionInSingleFile=true
-p:OptimizationPreference=Size
-p:InvariantGlobalization=true
-p:DebugType=none
-p:IncludeNativeLibrariesForSelfExtract=true"
rm -rf "$outdir"
command="dotnet publish $project -c Release -o $outdir $args"
echo "$command"
$command
find "$outdir" -name '*.pdb' -delete -printf "deleted '%p'\n"
tree -sh "$outdir"