416 lines
12 KiB
C#
416 lines
12 KiB
C#
using Aurora;
|
|
using Aurora.View;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Data;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Navigation;
|
|
using System.Windows.Shapes;
|
|
|
|
namespace AuroraUIComponent.UserControls.Dialog
|
|
{
|
|
/// <summary>
|
|
/// WinCalculator.xaml에 대한 상호 작용 논리
|
|
/// </summary>
|
|
public partial class WinCalculator : Window, INotifyPropertyChanged
|
|
{
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
protected bool SetProperty<S>(
|
|
ref S storage,
|
|
S value,
|
|
[CallerMemberName] string propertyName = null)
|
|
{
|
|
if (Equals(storage, value))
|
|
return false;
|
|
storage = value;
|
|
OnPropertyChanged(propertyName);
|
|
return true;
|
|
}
|
|
|
|
protected void OnPropertyChanged(
|
|
[CallerMemberName] string propertyName = null)
|
|
=> PropertyChanged?.Invoke(
|
|
this,
|
|
new PropertyChangedEventArgs(propertyName)
|
|
);
|
|
|
|
public string Unit { get => _Unit; set => SetProperty(ref _Unit, value); }
|
|
public string _Unit;
|
|
|
|
public string Value {
|
|
get => _Value;
|
|
set {
|
|
SetProperty(ref _Value, value);
|
|
if (value != "") {
|
|
TextDisplay = value;
|
|
}
|
|
}
|
|
}
|
|
public string _Value;
|
|
|
|
public string TextDisplay { get => _TextDisplay; set => SetProperty(ref _TextDisplay, value); }
|
|
public string _TextDisplay;
|
|
|
|
public string TextHistory { get => _TextHistory; set => SetProperty(ref _TextHistory, value); }
|
|
public string _TextHistory;
|
|
|
|
public string TextRange {
|
|
get => _TextRange;
|
|
set => SetProperty(ref _TextRange, value);
|
|
}
|
|
|
|
public string _TextRange;
|
|
|
|
public string Op { get; set; }
|
|
public double? Op1 { get; set; }
|
|
|
|
public double Number;
|
|
private bool IsFirst = true;
|
|
private bool IsCalculated = false;
|
|
|
|
public int DecimalPlaces {
|
|
set {
|
|
SetProperty(ref _DecimalPlaces, value);
|
|
if (value > 0) {
|
|
ButtonPoint.IsEnabled = true;
|
|
} else {
|
|
ButtonPoint.IsEnabled = false;
|
|
}
|
|
}
|
|
get => _DecimalPlaces;
|
|
}
|
|
public int _DecimalPlaces;
|
|
|
|
public bool IsAllowMinus {
|
|
set {
|
|
ButtonMinus.IsEnabled = value;
|
|
if (value) {
|
|
ButtonMinus.Visibility = Visibility.Visible;
|
|
Grid.SetColumn(Button0, 1);
|
|
Grid.SetColumnSpan(Button0, 1);
|
|
} else {
|
|
ButtonMinus.Visibility = Visibility.Collapsed;
|
|
Grid.SetColumn(Button0, 0);
|
|
Grid.SetColumnSpan(Button0, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool _IsClosing = false;
|
|
private Window _OnwerWindow;
|
|
private FrameworkElement _Element;
|
|
public Action<string> ResultCallback;
|
|
|
|
public WinCalculator()
|
|
{
|
|
InitializeComponent();
|
|
Deactivated += WindowDeactivated;
|
|
DataContext = this;
|
|
}
|
|
|
|
private void WindowDeactivated(object sender, EventArgs e)
|
|
{
|
|
if (_IsClosing) {
|
|
return;
|
|
}
|
|
Close();
|
|
}
|
|
|
|
private void NumberButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
Button button = sender as Button;
|
|
var numStr = button.Content.ToString();
|
|
|
|
if (Op1 == null) TextHistory = "";
|
|
if (IsCalculated) {
|
|
Value = "0";
|
|
IsCalculated = false;
|
|
}
|
|
|
|
if (Value == "0") {
|
|
if (numStr == "0") {
|
|
return;
|
|
}
|
|
|
|
Value = numStr;
|
|
IsFirst = false;
|
|
return;
|
|
}
|
|
|
|
if (Value.StartsWith("-")) {
|
|
if (Value.Length > 1) {
|
|
if (Value.Substring(1) == "0") {
|
|
if (numStr == "0") {
|
|
return;
|
|
}
|
|
|
|
Value = "-" + numStr;
|
|
IsFirst = false;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IsFirst) {
|
|
Value = string.Empty;
|
|
IsFirst = false;
|
|
}
|
|
|
|
AddChracter(numStr);
|
|
}
|
|
|
|
private void ButtonMinus_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (IsCalculated) {
|
|
IsCalculated = false;
|
|
}
|
|
|
|
if (Value.StartsWith("-"))
|
|
Value = Value.Substring(1, Value.Length - 1);
|
|
else
|
|
Value = "-" + Value;
|
|
IsFirst = false;
|
|
}
|
|
|
|
private void ButtonPoint_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (IsCalculated) {
|
|
Value = "0";
|
|
IsCalculated = false;
|
|
}
|
|
|
|
if (Value.Contains(".")) {
|
|
return;
|
|
}
|
|
|
|
if (IsFirst) {
|
|
IsFirst = false;
|
|
}
|
|
|
|
if (Value.Length == 0) AddChracter("0");
|
|
AddChracter(".");
|
|
}
|
|
|
|
private void OperatorButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
Button button = sender as Button;
|
|
string op = button.Content.ToString();
|
|
|
|
if (Value.Length == 0) { // Change Operator
|
|
if (Op == TextHistory.Substring(TextHistory.Length - 1)) {
|
|
Op = op;
|
|
TextHistory = TextHistory.Substring(0, TextHistory.Length - 1) + op;
|
|
}
|
|
return;
|
|
}
|
|
|
|
double input;
|
|
if (double.TryParse(Value, out input)) {
|
|
if (Op1 == null) {
|
|
TextHistory = "";
|
|
Op1 = input;
|
|
} else {
|
|
Op1 = calculate(Op, (double)Op1, input);
|
|
TextDisplay = Op1.ToString();
|
|
}
|
|
Op = op;
|
|
Value = "";
|
|
|
|
if (input >= 0) {
|
|
TextHistory += input.ToString() + Op;
|
|
} else {
|
|
TextHistory += "(" + input.ToString() + ")" + Op;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CalculateButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
double input;
|
|
if (Op1 == null || !double.TryParse(Value, out input)) {
|
|
return;
|
|
}
|
|
|
|
Value = calculate(Op, (double)Op1, input).ToString();
|
|
Op1 = null;
|
|
|
|
if (input >= 0) {
|
|
TextHistory += input.ToString();
|
|
} else {
|
|
TextHistory += "(" + input.ToString() + ")";
|
|
}
|
|
IsCalculated = true;
|
|
}
|
|
|
|
private double calculate(string op, double op1, double op2)
|
|
{
|
|
switch (op) {
|
|
case "+": return op1 + op2;
|
|
case "-": return op1 - op2;
|
|
case "*": return Math.Round(op1 * op2, DecimalPlaces);
|
|
case "/": return Math.Round(op1 / op2, DecimalPlaces);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
private void ButtonBack_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (IsFirst) {
|
|
IsFirst = false;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(Value)) {
|
|
Value = Value.Substring(0, Value.Length - 1);
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(Value)) {
|
|
Value = "0";
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void ButtonClear_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
Value = "0";
|
|
Op1 = null;
|
|
TextHistory = "";
|
|
if (IsFirst) {
|
|
IsFirst = false;
|
|
}
|
|
}
|
|
|
|
private void ButtonOK_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (TextDisplay.Last() == '.') {
|
|
TextDisplay = TextDisplay.Substring(0, TextDisplay.Length - 1);
|
|
}
|
|
|
|
if (!double.TryParse(TextDisplay, out Number)) {
|
|
return;
|
|
}
|
|
|
|
if (ResultCallback != null)
|
|
ResultCallback(TextDisplay);
|
|
|
|
_IsClosing = true;
|
|
Close();
|
|
}
|
|
|
|
private void AddChracter(string text)
|
|
{
|
|
Value = Value + text;
|
|
}
|
|
|
|
private void ButtonCancel_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
_IsClosing = true;
|
|
Close();
|
|
}
|
|
|
|
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
|
|
{
|
|
SetWindowControl(_OnwerWindow, _Element);
|
|
}
|
|
|
|
internal void SetControl(FrameworkElement element)
|
|
{
|
|
Window main = Application.Current.MainWindow;
|
|
SetControl(main, element);
|
|
}
|
|
|
|
public void SetWindowControl(Window window, FrameworkElement element)
|
|
{
|
|
SetControl(window, element);
|
|
}
|
|
|
|
private void SetControl(Window window, FrameworkElement element)
|
|
{
|
|
_OnwerWindow = window;
|
|
_Element = element;
|
|
|
|
Window main = Application.Current.MainWindow;
|
|
Point mainPosition = main.PointToScreen(new Point(0d, 0d));
|
|
|
|
Point relativePoint = element.TransformToAncestor(window)
|
|
.Transform(new Point(0, 0));
|
|
|
|
Point position = element.PointToScreen(new Point(0d, 0d)),
|
|
controlPosition = window.PointToScreen(new Point(0d, 0d));
|
|
// Right
|
|
relativePoint.X += controlPosition.X;
|
|
relativePoint.Y += controlPosition.Y;
|
|
|
|
// 1. Right, Middle
|
|
Left = relativePoint.X + element.ActualWidth;
|
|
Top = relativePoint.Y - 45;
|
|
if (Left + this.Width < mainPosition.X + main.Width) {
|
|
if (Top + this.Height < mainPosition.Y + main.Height) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 2. MiddleRight, Bottom
|
|
Left = Left - this.Width;
|
|
Top = relativePoint.Y + element.ActualHeight;
|
|
if (Left + this.Width < mainPosition.X + main.Width) {
|
|
if (Top + this.Height < mainPosition.Y + main.Height) {
|
|
return;
|
|
}
|
|
// 3. MiddleRight, Top
|
|
Top = relativePoint.Y - this.Height;
|
|
if (Left + this.Width < mainPosition.X + main.Width) {
|
|
if (Top + this.Height < mainPosition.Y + main.Height) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 4. Left, Middle
|
|
Left = relativePoint.X - this.Width;
|
|
Top = relativePoint.Y - 45;
|
|
if (Top + this.Height < mainPosition.Y + main.Height) {
|
|
if (Left > mainPosition.X) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 3. Middle, Top
|
|
Left = relativePoint.X;
|
|
Top = relativePoint.Y - this.Height;
|
|
|
|
// 5. Left, Top
|
|
Left = relativePoint.X - this.Width + element.ActualWidth;
|
|
}
|
|
}
|
|
|
|
public class VisibleConverter : IValueConverter
|
|
{
|
|
private Visibility True { get; set; } = Visibility.Visible;
|
|
private Visibility False { get; set; } = Visibility.Collapsed;
|
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
if (value is string str) {
|
|
return !string.IsNullOrEmpty(str) ? True : False;
|
|
} else {
|
|
return False;
|
|
}
|
|
}
|
|
|
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|