Загрузка данных


using System;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WpfCalculator
{
    public partial class MainWindow : Window
    {
        // Переменные для хранения состояния вычислений
        private double _currentValue = 0;
        private string _currentOperator = "";
        private bool _isNewInput = true; // Флаг, показывающий, что сейчас начнется ввод нового числа
        private bool _isResultDisplayed = false; // Показывает, что на экране результат предыдущего вычисления

        public MainWindow()
        {
            InitializeComponent();
            InputBox.Focus();
        }

        // --- ОБРАБОТЧИКИ КНОПОК ---

        // Обработка цифр (0-9)
        private void DigitButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = (Button)sender;
            string digit = button.Content.ToString();

            // Если только что был результат (=) и не нажат оператор, сбрасываем для нового ввода
            if (_isResultDisplayed && string.IsNullOrEmpty(_currentOperator))
            {
                InputBox.Text = "0";
                _isResultDisplayed = false;
            }

            if (_isNewInput)
            {
                InputBox.Text = digit;
                _isNewInput = false;
            }
            else
            {
                // Проверка на переполнение длины (опционально)
                if (InputBox.Text.Length < 15)
                {
                    // Убираем ведущий ноль, если он один
                    if (InputBox.Text == "0" && digit != ".")
                        InputBox.Text = digit;
                    else
                        InputBox.Text += digit;
                }
            }
            
            _isResultDisplayed = false;
            InputBox.Focus();
        }

        // Обработка десятичной точки
        private void DecimalButton_Click(object sender, RoutedEventArgs e)
        {
            if (_isResultDisplayed && string.IsNullOrEmpty(_currentOperator))
            {
                InputBox.Text = "0";
                _isResultDisplayed = false;
            }

            if (_isNewInput)
            {
                InputBox.Text = "0.";
                _isNewInput = false;
            }
            else
            {
                if (!InputBox.Text.Contains("."))
                    InputBox.Text += ".";
            }
            
            _isResultDisplayed = false;
            InputBox.Focus();
        }

        // Обработка операторов (+, -, *, /, ^)
        private void OperatorButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = (Button)sender;
            string op = button.Content.ToString();

            // Если пользователь ввел число и сразу жмет оператор еще раз
            if (!_isNewInput)
            {
                // Если есть предыдущий оператор, выполняем вычисление
                if (!string.IsNullOrEmpty(_currentOperator))
                {
                    PerformCalculation();
                }
                else
                {
                    // Просто сохраняем текущее значение
                    _currentValue = double.Parse(InputBox.Text, CultureInfo.InvariantCulture);
                }
            }
            // Если это был результат (=) и теперь нажали оператор
            else if (_isResultDisplayed)
            {
                _currentValue = double.Parse(InputBox.Text, CultureInfo.InvariantCulture);
            }

            _currentOperator = op;
            _isNewInput = true;
            _isResultDisplayed = false;
            InputBox.Focus();
        }

        // Обработка равно (=)
        private void EqualsButton_Click(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(_currentOperator) && !_isNewInput)
            {
                PerformCalculation();
                _currentOperator = "";
                _isNewInput = true;
                _isResultDisplayed = true;
            }
            InputBox.Focus();
        }

        // Обработка очистки (C)
        private void ClearButton_Click(object sender, RoutedEventArgs e)
        {
            InputBox.Text = "0";
            _currentValue = 0;
            _currentOperator = "";
            _isNewInput = true;
            _isResultDisplayed = false;
            InputBox.Focus();
        }

        // --- ЛОГИКА ВЫЧИСЛЕНИЙ ---
        private void PerformCalculation()
        {
            try
            {
                double newValue = double.Parse(InputBox.Text, CultureInfo.InvariantCulture);
                double result = 0;

                switch (_currentOperator)
                {
                    case "+":
                        result = _currentValue + newValue;
                        break;
                    case "-":
                        result = _currentValue - newValue;
                        break;
                    case "*":
                        result = _currentValue * newValue;
                        break;
                    case "/":
                        if (Math.Abs(newValue) < 0.0000001)
                        {
                            MessageBox.Show("Деление на ноль невозможно.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                            ClearButton_Click(null, null);
                            return;
                        }
                        result = _currentValue / newValue;
                        break;
                    case "^":
                        result = Math.Pow(_currentValue, newValue);
                        break;
                }

                InputBox.Text = result.ToString(CultureInfo.InvariantCulture);
                _currentValue = result;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Ошибка вычисления: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                ClearButton_Click(null, null);
            }
        }

        // --- ВАЛИДАЦИЯ ВВОДА С КЛАВИАТУРЫ ---

        /// <summary>
        /// Метод обработки ввода текста. Здесь мы разрешаем или запрещаем ввод символа.
        /// </summary>
        private void InputBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            // Разрешаем ввод только: цифр, одной точки, знака минус в начале
            string newText = InputBox.Text.Insert(InputBox.SelectionStart, e.Text);
            
            // Проверяем, является ли строка валидным числом (с учетом ввода минуса в начале)
            // Используем флаг AllowDecimalPoint для проверки на ввод числа с плавающей точкой
            bool isValid = double.TryParse(newText, NumberStyles.Any, CultureInfo.InvariantCulture, out _);
            
            // Дополнительная проверка для случаев, когда ввод начинается с "-" или содержит только "-"
            if (newText == "-" || (newText.StartsWith("-") && newText.Count(c => c == '-') == 1 && 
                newText.Replace("-", "").All(c => char.IsDigit(c) || c == '.')))
            {
                isValid = true;
            }

            // Проверка на несколько точек
            if (newText.Count(c => c == '.') > 1)
            {
                isValid = false;
            }

            // Проверка на несколько минусов
            if (newText.Count(c => c == '-') > 1 || (newText.IndexOf('-') > 0))
            {
                isValid = false;
            }

            // Если ввод не валиден, отказываем (e.Handled = true)
            e.Handled = !isValid;

            // Сбрасываем флаг, так как пользователь что-то ввел руками
            if (isValid)
            {
                _isNewInput = false;
                _isResultDisplayed = false;
            }
        }

        /// <summary>
        /// Обработка нажатия клавиш (Enter, Backspace и т.д.)
        /// </summary>
        private void InputBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                EqualsButton_Click(null, null);
                e.Handled = true;
            }
            else if (e.Key == Key.Escape)
            {
                ClearButton_Click(null, null);
                e.Handled = true;
            }
            else if (e.Key == Key.Back || e.Key == Key.Delete)
            {
                // Разрешаем стирание
                _isNewInput = false;
                _isResultDisplayed = false;
            }
            // Цифровые клавиши с NumPad
            else if (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9)
            {
                string digit = ((int)(e.Key - Key.NumPad0)).ToString();
                // Симулируем нажатие кнопки цифры
                if (_isNewInput || InputBox.Text == "0")
                    InputBox.Text = digit;
                else
                    InputBox.Text += digit;
                _isNewInput = false;
                _isResultDisplayed = false;
                e.Handled = true;
            }
            // Операторы с NumPad
            else if (e.Key == Key.Add)
            {
                OperatorButton_Click(new Button { Content = "+" }, null);
                e.Handled = true;
            }
            else if (e.Key == Key.Subtract)
            {
                OperatorButton_Click(new Button { Content = "-" }, null);
                e.Handled = true;
            }
            else if (e.Key == Key.Multiply)
            {
                OperatorButton_Click(new Button { Content = "*" }, null);
                e.Handled = true;
            }
            else if (e.Key == Key.Divide)
            {
                OperatorButton_Click(new Button { Content = "/" }, null);
                e.Handled = true;
            }
            else if (e.Key == Key.Decimal)
            {
                DecimalButton_Click(null, null);
                e.Handled = true;
            }
        }
    }
}