123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- /*
- * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
- * Copyright (c) 2021, Max Wipfli <mail@maxwipfli.ch>
- * Copyright (c) 2022, the SerenityOS developers.
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include "Keypad.h"
- #include "KeypadValue.h"
- #include <AK/IntegralMath.h>
- #include <AK/StringBuilder.h>
- void Keypad::type_digit(int digit)
- {
- u64 previous_value = 0;
- switch (m_state) {
- case State::External:
- m_state = State::TypingInteger;
- m_negative = false;
- m_int_value = digit;
- m_frac_value = 0;
- m_frac_length = 0;
- break;
- case State::TypingInteger:
- VERIFY(m_frac_value.value() == 0);
- VERIFY(m_frac_length == 0);
- previous_value = m_int_value.value();
- m_int_value *= 10;
- m_int_value += digit;
- if (m_int_value.has_overflow())
- m_int_value = previous_value;
- break;
- case State::TypingDecimal:
- previous_value = m_frac_value.value();
- m_frac_value *= 10;
- m_frac_value += digit;
- if (m_frac_value.has_overflow())
- m_frac_value = previous_value;
- else
- m_frac_length++;
- break;
- }
- }
- void Keypad::type_decimal_point()
- {
- switch (m_state) {
- case State::External:
- m_negative = false;
- m_int_value = 0;
- m_frac_value = 0;
- m_frac_length = 0;
- m_state = State::TypingDecimal;
- break;
- case State::TypingInteger:
- VERIFY(m_frac_value.value() == 0);
- VERIFY(m_frac_length == 0);
- m_state = State::TypingDecimal;
- break;
- case State::TypingDecimal:
- // Ignore it.
- break;
- }
- }
- void Keypad::type_backspace()
- {
- switch (m_state) {
- case State::External:
- m_negative = false;
- m_int_value = 0;
- m_frac_value = 0;
- m_frac_length = 0;
- break;
- case State::TypingDecimal:
- if (m_frac_length > 0) {
- m_frac_value /= 10;
- m_frac_length--;
- break;
- }
- VERIFY(m_frac_value.value() == 0);
- m_state = State::TypingInteger;
- [[fallthrough]];
- case State::TypingInteger:
- VERIFY(m_frac_value.value() == 0);
- VERIFY(m_frac_length == 0);
- m_int_value /= 10;
- if (m_int_value.value() == 0)
- m_negative = false;
- break;
- }
- }
- KeypadValue Keypad::value() const
- {
- KeypadValue frac_part = { (i64)m_frac_value.value(), m_frac_length };
- KeypadValue int_part = { (i64)m_int_value.value() };
- KeypadValue res = int_part + frac_part;
- if (m_negative)
- res = -res;
- return res;
- }
- void Keypad::set_value(KeypadValue value)
- {
- m_state = State::External;
- if (value.m_value < 0) {
- m_negative = true;
- value = -value;
- } else
- m_negative = false;
- m_int_value = value.m_value / AK::pow<u64>(10, value.m_decimal_places);
- m_frac_value = value.m_value % AK::pow<u64>(10, value.m_decimal_places);
- m_frac_length = value.m_decimal_places;
- }
- String Keypad::to_string() const
- {
- StringBuilder builder;
- if (m_negative)
- builder.append('-');
- builder.appendff("{}", m_int_value.value());
- // NOTE: This is so the decimal point appears on screen as soon as you type it.
- if (m_frac_length > 0 || m_state == State::TypingDecimal)
- builder.append('.');
- if (m_frac_length > 0) {
- // FIXME: This disables the compiletime format string check since we can't parse '}}' here correctly.
- // remove the 'StringView { }' when that's fixed.
- builder.appendff("{:0{}}"sv, m_frac_value.value(), m_frac_length);
- }
- return builder.to_string();
- }
|