M module-apps/application-calculator/data/CalculatorInputProcessor.cpp => module-apps/application-calculator/data/CalculatorInputProcessor.cpp +20 -2
@@ 3,7 3,7 @@
#include "CalculatorInputProcessor.hpp"
-bool calc::InputProcessor::isSymbol(uint32_t code)
+bool calc::InputProcessor::isSymbol(uint32_t code) noexcept
{
using namespace symbols::codes;
@@ 25,7 25,25 @@ bool calc::InputProcessor::isSymbol(uint32_t code)
}
}
-bool calc::InputProcessor::isDecimalSeparator(uint32_t code)
+bool calc::InputProcessor::isOperation(uint32_t code) noexcept
+{
+ using namespace symbols::codes;
+
+ switch (code) {
+ case plus:
+ [[fallthrough]];
+ case minus:
+ [[fallthrough]];
+ case division:
+ [[fallthrough]];
+ case multiplication:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool calc::InputProcessor::isDecimalSeparator(uint32_t code) noexcept
{
using namespace symbols::codes;
M module-apps/application-calculator/data/CalculatorInputProcessor.hpp => module-apps/application-calculator/data/CalculatorInputProcessor.hpp +35 -5
@@ 3,6 3,7 @@
#pragma once
+#include <i18n/i18n.hpp>
#include <utf8/UTF8.hpp>
namespace gui
@@ 37,20 38,49 @@ namespace calc
inline constexpr auto comma = "\u002C";
inline constexpr auto asterisk = "\u002A";
inline constexpr auto solidus = "\u002F";
+
+ inline const std::string &equals_str()
+ {
+ return utils::translate("app_calculator_equals");
+ }
+
+ inline const std::string &decimal_separator_str()
+ {
+ return utils::translate("app_calculator_decimal_separator");
+ }
+
+ inline const std::string &error_str()
+ {
+ return utils::translate("app_calculator_error");
+ }
} // namespace strings
- } // namespace symbols
+
+ } // namespace symbols
+
+ namespace limits
+ {
+ inline constexpr auto MaxInputLength = 7u;
+ inline constexpr auto MaxDecimalDigits = 6u;
+
+ inline constexpr auto VeryLowPrecision = 4;
+ inline constexpr auto LowPrecision = 5;
+ inline constexpr auto Precision = 6;
+ inline constexpr auto HighPrecision = 8;
+ inline constexpr auto ExpLength = 1;
+ inline constexpr auto MinusExpLength = 2;
+ inline constexpr auto MaxStringLength = 7;
+ } // namespace limits
class InputProcessor
{
public:
- static inline constexpr auto DecimalDigitsLimit = 6;
-
virtual ~InputProcessor() = default;
virtual bool handle(const gui::InputEvent &event) = 0;
virtual void clear() = 0;
- static bool isSymbol(std::uint32_t code);
- static bool isDecimalSeparator(std::uint32_t c);
+ static bool isSymbol(std::uint32_t code) noexcept;
+ static bool isOperation(std::uint32_t code) noexcept;
+ static bool isDecimalSeparator(std::uint32_t c) noexcept;
};
} // namespace calc
M module-apps/application-calculator/data/CalculatorInputProcessorText.cpp => module-apps/application-calculator/data/CalculatorInputProcessorText.cpp +187 -41
@@ 7,6 7,15 @@
#include <gui/input/InputEvent.hpp>
#include <gui/widgets/Text.hpp>
#include <i18n/i18n.hpp>
+#include <module-utils/gsl/gsl_assert>
+
+namespace
+{
+ bool isDigit(gui::KeyCode code)
+ {
+ return gui::toNumeric(code) != gui::InvalidNumericKeyCode;
+ }
+} // namespace
calc::InputProcessorText::InputProcessorText(gsl::strict_not_null<gui::Text *> inputField) : inputField{inputField}
{}
@@ 30,43 39,52 @@ bool calc::InputProcessorText::handle(const gui::InputEvent &event)
return true;
}
- const auto lastChar = inputField->getText()[inputField->getText().length() - 1];
- const bool lastCharIsSymbol = isSymbol(lastChar);
- if (lastChar == symbols::codes::zero && isSymbol(getPenultimate()) && !isDecimalSeparator(getPenultimate()) &&
+ if (shouldRestoreInput(event)) {
+ restoreHiddenInput();
+ return true;
+ }
+
+ if (shouldHideInput(event)) {
+ hideCurrentInput();
+ }
+
+ const auto lastChar = lastCharacter();
+ const auto penultimateCharIsSymbol = penultimateCharacterIsSymbol();
+ const auto penultimateCharIsDecimalSeparator = penultimateCharacterIsDecimalSeparator();
+
+ if (lastChar == symbols::codes::zero && penultimateCharIsSymbol && !penultimateCharIsDecimalSeparator &&
event.is(gui::KeyCode::KEY_0)) {
return true;
}
- if (event.keyCode == gui::KeyCode::KEY_UP) {
- writeEquation(lastCharIsSymbol, symbols::strings::plus);
+ if (event.is(gui::KeyCode::KEY_UP)) {
+ handleOperation(symbols::strings::plus);
return true;
}
- if (event.keyCode == gui::KeyCode::KEY_DOWN) {
- if (lastChar != symbols::codes::minus) {
- writeEquation(lastCharIsSymbol, symbols::strings::minus);
- }
+ if (event.is(gui::KeyCode::KEY_DOWN)) {
+ handleOperation(symbols::strings::minus);
return true;
}
- if (event.keyCode == gui::KeyCode::KEY_LEFT) {
- writeEquation(lastCharIsSymbol, symbols::strings::multiplication);
+ if (event.is(gui::KeyCode::KEY_LEFT)) {
+ handleOperation(symbols::strings::multiplication);
return true;
}
- if (event.keyCode == gui::KeyCode::KEY_RIGHT) {
- writeEquation(lastCharIsSymbol, symbols::strings::division);
+ if (event.is(gui::KeyCode::KEY_RIGHT)) {
+ handleOperation(symbols::strings::division);
return true;
}
- if (event.keyCode == gui::KeyCode::KEY_LF) {
- if (!isPreviousNumberDecimal()) {
- writeEquation(lastCharIsSymbol, utils::translate("app_calculator_decimal_separator"));
+ if (event.is(gui::KeyCode::KEY_LF)) {
+ if (!isCurrentNumberDecimal()) {
+ addSymbol(symbols::strings::decimal_separator_str());
}
return true;
}
- if (lastChar == symbols::codes::zero && isSymbol(getPenultimate()) && !isDecimalSeparator(getPenultimate()) &&
+ if (lastChar == symbols::codes::zero && penultimateCharIsSymbol && !penultimateCharIsDecimalSeparator &&
!event.is(gui::KeyCode::KEY_0) && !event.is(gui::KeyCode::KEY_PND) && !event.is(gui::KeyCode::KEY_ENTER)) {
inputField->removeChar();
return false;
@@ 76,14 94,12 @@ bool calc::InputProcessorText::handle(const gui::InputEvent &event)
clear();
}
- if (event.keyCode == gui::KeyCode::KEY_ENTER) {
- auto result = Calculator().calculate(std::string(inputField->getText()));
- inputField->setText(result.value);
- clearInput = result.isError;
+ if (event.is(gui::KeyCode::KEY_ENTER)) {
+ compute();
return true;
}
- if (decimalLimitReached()) {
+ if (prohibidInput(event)) {
// Consume event to don't allow more decimals
return true;
}
@@ 94,15 110,85 @@ bool calc::InputProcessorText::handle(const gui::InputEvent &event)
void calc::InputProcessorText::clear()
{
inputField->clear();
+ hiddenPartOfEquation.clear();
clearInput = false;
}
-void calc::InputProcessorText::writeEquation(bool lastCharIsSymbol, const UTF8 &symbol)
+std::optional<uint32_t> calc::InputProcessorText::lastCharacter() const
+{
+ const auto &txt = inputField->getText();
+
+ if (txt.empty()) {
+ return {};
+ }
+
+ return txt[txt.length() - 1];
+}
+
+bool calc::InputProcessorText::lastCharacterIsSymbol() const
+{
+ const auto &c = lastCharacter();
+ return c ? isSymbol(*c) : false;
+}
+
+bool calc::InputProcessorText::lastCharacterIsOperation() const
+{
+ const auto &c = lastCharacter();
+ return c ? isOperation(*c) : false;
+}
+
+std::optional<uint32_t> calc::InputProcessorText::penultimateCharacter() const
+{
+ const auto &text = inputField->getText();
+ const auto len = text.length();
+
+ if (len < 2) {
+ return {};
+ }
+
+ return text[len - 2];
+}
+
+bool calc::InputProcessorText::penultimateCharacterIsSymbol() const
+{
+ const auto &c = penultimateCharacter();
+ return c ? isSymbol(*c) : false;
+}
+
+bool calc::InputProcessorText::penultimateCharacterIsDecimalSeparator() const
+{
+ const auto &c = penultimateCharacter();
+ return c ? isDecimalSeparator(*c) : false;
+}
+
+bool calc::InputProcessorText::shouldComputeBeforeNextOperation() const
+{
+ if (!hasHiddenPart()) {
+ return false;
+ }
+
+ if (inputField->getText().empty()) {
+ return false;
+ }
+
+ return true;
+}
+
+void calc::InputProcessorText::handleOperation(const UTF8 &operation)
+{
+ if (shouldComputeBeforeNextOperation()) {
+ compute();
+ }
+
+ addSymbol(operation);
+}
+
+void calc::InputProcessorText::addSymbol(const UTF8 &symbol)
{
if (!inputField->getText().empty()) {
- if (lastCharIsSymbol && symbol != symbols::strings::minus) {
- if (!isSymbol(getPenultimate()) && inputField->getText().length() > 1) {
+ if (lastCharacterIsSymbol() && symbol != symbols::strings::minus) {
+ if (!penultimateCharacterIsSymbol() && inputField->getText().length() > 1) {
inputField->removeChar();
inputField->addText(symbol);
}
@@ 116,7 202,50 @@ void calc::InputProcessorText::writeEquation(bool lastCharIsSymbol, const UTF8 &
}
}
-bool calc::InputProcessorText::isPreviousNumberDecimal() const
+bool calc::InputProcessorText::shouldHideInput(const gui::InputEvent &event) const
+{
+ if (!lastCharacterIsOperation()) {
+ return false;
+ }
+
+ if (!isDigit(event.keyCode) && !event.is(gui::KeyCode::KEY_DOWN)) {
+ return false;
+ }
+
+ if (inputField->getText() == symbols::strings::minus) {
+ return false;
+ }
+
+ return true;
+}
+
+bool calc::InputProcessorText::shouldRestoreInput(const gui::InputEvent &event) const
+{
+ return event.is(gui::KeyCode::KEY_PND) && inputField->isEmpty() && hasHiddenPart();
+}
+
+void calc::InputProcessorText::hideCurrentInput()
+{
+ Expects(hiddenPartOfEquation.empty());
+
+ hiddenPartOfEquation = inputField->getText();
+ inputField->clear();
+}
+
+void calc::InputProcessorText::restoreHiddenInput()
+{
+ Expects(!hiddenPartOfEquation.empty());
+
+ inputField->setText(hiddenPartOfEquation);
+ hiddenPartOfEquation.clear();
+}
+
+bool calc::InputProcessorText::hasHiddenPart() const
+{
+ return !hiddenPartOfEquation.empty();
+}
+
+bool calc::InputProcessorText::isCurrentNumberDecimal() const
{
if (!inputField->getText().empty()) {
std::vector<int> symbolsIndexes;
@@ 138,37 267,54 @@ bool calc::InputProcessorText::isPreviousNumberDecimal() const
else {
lastNumber = input.substr(*it, std::string::npos);
}
- return lastNumber.find(utils::translate("app_calculator_decimal_separator")) != std::string::npos;
+ return lastNumber.find(symbols::strings::decimal_separator_str()) != std::string::npos;
}
return false;
}
-bool calc::InputProcessorText::decimalLimitReached() const
+bool calc::InputProcessorText::inputContainsExponent() const
{
- if (!isPreviousNumberDecimal())
- return false;
+ return std::string{inputField->getText()}.find('e') != std::string::npos;
+}
- const auto &txt = std::string{inputField->getText()};
- const auto separator_pos = txt.find_last_of(utils::translate("app_calculator_decimal_separator"));
+bool calc::InputProcessorText::prohibidInput(const gui::InputEvent &event) const
+{
+ if (!isDigit(event.keyCode)) {
+ return false;
+ }
- if ((txt.size() - separator_pos) > DecimalDigitsLimit)
+ if (charactedLimitReached() || decimalLimitReached()) {
return true;
+ }
return false;
}
-bool calc::InputProcessorText::inputContainsExponent() const
+bool calc::InputProcessorText::charactedLimitReached() const
{
- return std::string{inputField->getText()}.find('e') != std::string::npos;
+ return inputField->getText().length() >= limits::MaxInputLength;
}
-std::uint32_t calc::InputProcessorText::getPenultimate() const
+bool calc::InputProcessorText::decimalLimitReached() const
{
- const auto &text = inputField->getText();
- const auto len = text.length();
+ if (!isCurrentNumberDecimal()) {
+ return false;
+ }
- if (len < 2)
- return 0;
+ const auto &txt = std::string{inputField->getText()};
+ const auto separator_pos = txt.find_last_of(symbols::strings::decimal_separator_str());
- return text[len - 2];
+ if ((txt.size() - separator_pos) > limits::MaxDecimalDigits) {
+ return true;
+ }
+
+ return false;
+}
+
+void calc::InputProcessorText::compute()
+{
+ auto result = Calculator().calculate(hiddenPartOfEquation + inputField->getText());
+ inputField->setText(result.value);
+ hiddenPartOfEquation.clear();
+ clearInput = result.isError;
}
M module-apps/application-calculator/data/CalculatorInputProcessorText.hpp => module-apps/application-calculator/data/CalculatorInputProcessorText.hpp +23 -4
@@ 23,17 23,36 @@ namespace calc
void clear() override;
private:
- void writeEquation(bool lastCharIsSymbol, const UTF8 &symbol);
+ std::optional<std::uint32_t> lastCharacter() const;
+ bool lastCharacterIsSymbol() const;
+ bool lastCharacterIsOperation() const;
- bool isPreviousNumberDecimal() const;
- bool decimalLimitReached() const;
+ std::optional<std::uint32_t> penultimateCharacter() const;
+ bool penultimateCharacterIsSymbol() const;
+ bool penultimateCharacterIsDecimalSeparator() const;
+
+ bool shouldComputeBeforeNextOperation() const;
+ void handleOperation(const UTF8 &operation);
+ void addSymbol(const UTF8 &symbol);
+
+ bool shouldHideInput(const gui::InputEvent &event) const;
+ bool shouldRestoreInput(const gui::InputEvent &event) const;
+ void hideCurrentInput();
+ void restoreHiddenInput();
+ bool hasHiddenPart() const;
+ bool isCurrentNumberDecimal() const;
bool inputContainsExponent() const;
- std::uint32_t getPenultimate() const;
+ bool prohibidInput(const gui::InputEvent &event) const;
+ bool charactedLimitReached() const;
+ bool decimalLimitReached() const;
+
+ void compute();
gui::Text *inputField{nullptr};
bool clearInput{false};
+ UTF8 hiddenPartOfEquation{};
};
} // namespace calc
M module-apps/application-calculator/data/CalculatorUtility.cpp => module-apps/application-calculator/data/CalculatorUtility.cpp +25 -16
@@ 3,6 3,7 @@
#include "CalculatorUtility.hpp"
#include "application-calculator/data/CalculatorInputProcessor.hpp"
+#include "application-calculator/widgets/CalculatorStyle.hpp"
#include <module-utils/tinyexpr/tinyexpr.h>
#include <i18n/i18n.hpp>
#include <Utils.hpp>
@@ 12,6 13,8 @@ namespace calc
{
Result Calculator::calculate(std::string source)
{
+ using namespace calc::limits;
+
source = prepareEquationForParser(source);
if (source.empty()) {
@@ 22,17 25,17 @@ namespace calc
double result = te_interp(source.c_str(), &error);
if (error == 0 && !std::isinf(result) && !std::isnan(result)) {
auto output = utils::to_string(result);
- if (output.length() > CalculatorConstants::maxStringLength) {
+ if (output.length() > MaxStringLength) {
output = getValueThatFitsOnScreen(result);
}
- if (utils::translate("app_calculator_decimal_separator") == symbols::strings::comma) {
+ if (symbols::strings::decimal_separator_str() == symbols::strings::comma) {
output.replace(output.find(symbols::strings::full_stop),
std::size(std::string_view(symbols::strings::full_stop)),
symbols::strings::comma);
}
return Result{source, output, false};
}
- return Result{source, utils::translate("app_calculator_error"), true};
+ return Result{source, symbols::strings::error_str(), true};
}
std::string Calculator::prepareEquationForParser(std::string input)
@@ 58,25 61,27 @@ namespace calc
std::string Calculator::getValueThatFitsOnScreen(double result)
{
+ using namespace calc::limits;
+
auto base = static_cast<long long>(result);
auto length = utils::to_string(base).length();
if (base < 0) {
length -= 1;
}
- if (length > CalculatorConstants::expLength + 1) {
+ if (length > ExpLength + 1) {
return convertToNumberWithPositiveExponent(result, length - 1);
}
- else if (length == CalculatorConstants::expLength + 1) {
+ else if (length == ExpLength + 1) {
if (result < 0) {
- return utils::to_string(getCoefficient(result, CalculatorConstants::veryLowPrecision));
+ return utils::to_string(getCoefficient(result, VeryLowPrecision));
}
- return utils::to_string(getCoefficient(result, CalculatorConstants::lowPrecision));
+ return utils::to_string(getCoefficient(result, LowPrecision));
}
else if (length == 1 && result < -1) {
- return utils::to_string(getCoefficient(result, CalculatorConstants::lowPrecision));
+ return utils::to_string(getCoefficient(result, LowPrecision));
}
else if (result > 1) {
- return utils::to_string(getCoefficient(result, CalculatorConstants::precision));
+ return utils::to_string(getCoefficient(result, Precision));
}
else {
return convertToNumberWithNegativeExponent(result, base);
@@ 85,9 90,11 @@ namespace calc
std::string Calculator::convertToNumberWithPositiveExponent(double result, uint32_t exponent)
{
+ using namespace calc::limits;
+
result /= pow(10, exponent);
auto exponentLength = utils::to_string(exponent).length();
- auto decimalPlace = CalculatorConstants::precision - exponentLength - CalculatorConstants::expLength;
+ auto decimalPlace = Precision - exponentLength - ExpLength;
if (result < 0) {
decimalPlace -= 1;
}
@@ 96,26 103,28 @@ namespace calc
std::string Calculator::convertToNumberWithNegativeExponent(double result, long long base)
{
- double frac = (result - base) * pow(10, CalculatorConstants::highPrecision);
+ using namespace calc::limits;
+
+ double frac = (result - base) * pow(10, HighPrecision);
if (result < 0) {
frac *= -1;
}
auto fractionalPart = static_cast<unsigned long int>(round(frac));
auto fracLength = utils::to_string(fractionalPart).length();
- auto exponent = CalculatorConstants::highPrecision - fracLength + 1;
- if (exponent > CalculatorConstants::minusExpLength + 1) {
+ auto exponent = HighPrecision - fracLength + 1;
+ if (exponent > MinusExpLength + 1) {
result *= pow(10, exponent);
auto exponentLength = utils::to_string(exponent).length();
- auto decimalPlace = CalculatorConstants::precision - exponentLength - CalculatorConstants::minusExpLength;
+ auto decimalPlace = Precision - exponentLength - MinusExpLength;
if (result < 0) {
decimalPlace -= 1;
}
return utils::to_string(getCoefficient(result, decimalPlace)) + "e-" + utils::to_string(exponent);
}
else if (result < 0) {
- return utils::to_string(getCoefficient(result, CalculatorConstants::lowPrecision));
+ return utils::to_string(getCoefficient(result, LowPrecision));
}
- return utils::to_string(getCoefficient(result, CalculatorConstants::precision));
+ return utils::to_string(getCoefficient(result, Precision));
}
long double Calculator::getCoefficient(double result, uint32_t precision)
M module-apps/application-calculator/data/CalculatorUtility.hpp => module-apps/application-calculator/data/CalculatorUtility.hpp +0 -11
@@ 6,17 6,6 @@
namespace calc
{
- namespace CalculatorConstants
- {
- inline constexpr auto veryLowPrecision = 4;
- inline constexpr auto lowPrecision = 5;
- inline constexpr auto precision = 6;
- inline constexpr auto highPrecision = 8;
- inline constexpr auto expLength = 1;
- inline constexpr auto minusExpLength = 2;
- inline constexpr auto maxStringLength = 7;
- } // namespace CalculatorConstants
-
struct Result
{
std::string equation;
M module-apps/application-calculator/tests/CalculatorInput_tests.cpp => module-apps/application-calculator/tests/CalculatorInput_tests.cpp +151 -15
@@ 20,7 20,6 @@ SCENARIO("Input Processor tests")
GIVEN("An empty input")
{
utils::setDisplayLanguage("English");
-
auto inputField = gui::Text{};
auto processor = calc::InputProcessorText{gsl::make_strict_not_null(&inputField)};
@@ 111,6 110,41 @@ SCENARIO("Input Processor tests")
REQUIRE(inputField.isEmpty());
}
}
+
+ AND_WHEN("We continue to type")
+ {
+ passShortKeyPresses(
+ {KeyCodes::NumericKey1, KeyCodes::NumericKey2, KeyCodes::NumericKey3, KeyCodes::NumericKey4});
+
+ THEN("The input is limited to predefined limit")
+ {
+ REQUIRE(inputField.getText().length() == calc::limits::MaxInputLength);
+ }
+
+ AND_WHEN("We try do delete input")
+ {
+ passShortKeyPresses({4, KeyCodes::NumericKeyPnd});
+
+ THEN("Input is deleted")
+ {
+ REQUIRE(inputField.getText() == "123");
+ }
+ }
+
+ AND_WHEN("We try to compute")
+ {
+ passShortKeyPresses({MinusKey,
+ KeyCodes::NumericKey1,
+ KeyCodes::NumericKey2,
+ KeyCodes::NumericKey3,
+ KeyCodes::JoystickEnter});
+
+ THEN("We are able to")
+ {
+ REQUIRE(inputField.getText() == "1234000");
+ }
+ }
+ }
}
WHEN("We enter leading zeros")
@@ 160,7 194,7 @@ SCENARIO("Input Processor tests")
}
}
- AND_WHEN("We try to enter more than 6 decimals")
+ AND_WHEN("We try to enter more than 5 decimals")
{
passShortKeyPresses({KeyCodes::NumericKey4,
KeyCodes::NumericKey5,
@@ 169,9 203,29 @@ SCENARIO("Input Processor tests")
KeyCodes::NumericKey8,
KeyCodes::NumericKey9});
- THEN("The input is truncated to 6 decimals")
+ THEN("The input is truncated")
{
- REQUIRE(inputField.getText() == "0.123456");
+ REQUIRE(inputField.getText() == "0.12345");
+ }
+
+ AND_WHEN("We try do delete input")
+ {
+ passShortKeyPresses({3, KeyCodes::NumericKeyPnd});
+
+ THEN("Input is deleted")
+ {
+ REQUIRE(inputField.getText() == "0.12");
+ }
+ }
+
+ AND_WHEN("We try to do operations")
+ {
+ passShortKeyPresses({PlusKey, KeyCodes::NumericKey2, KeyCodes::JoystickEnter});
+
+ THEN("It is posible")
+ {
+ REQUIRE(inputField.getText() == "2.12345");
+ }
}
}
}
@@ 214,6 268,17 @@ SCENARIO("Input Processor tests")
{
REQUIRE(inputField.getText() == "-23");
}
+
+ AND_WHEN("We try to subtract a negitive number")
+ {
+ passShortKeyPresses(
+ {MinusKey, MinusKey, KeyCodes::NumericKey1, KeyCodes::NumericKey3, KeyCodes::JoystickEnter});
+
+ THEN("The result is computed properly")
+ {
+ REQUIRE(inputField.getText() == "-10");
+ }
+ }
}
WHEN("We enter a number")
@@ 247,9 312,19 @@ SCENARIO("Input Processor tests")
{
passShortKeyPresses({KeyCodes::NumericKey4, KeyCodes::NumericKey5, KeyCodes::NumericKey6});
- THEN("It is shown")
+ THEN("Previos input is hidden")
{
- REQUIRE(inputField.getText() == "123+456");
+ REQUIRE(inputField.getText() == "456");
+ }
+
+ AND_WHEN("We press enter")
+ {
+ passShortKeyPress(KeyCodes::JoystickEnter);
+
+ THEN("The result is computed")
+ {
+ REQUIRE(inputField.getText() == "579");
+ }
}
}
@@ 257,9 332,39 @@ SCENARIO("Input Processor tests")
{
passShortKeyPresses({MinusKey, KeyCodes::NumericKey5, KeyCodes::NumericKey6});
- THEN("It is shown")
+ THEN("Previous input is hidden and negative number is shown")
+ {
+ REQUIRE(inputField.getText() == "-56");
+ }
+
+ AND_WHEN("We press enter")
{
- REQUIRE(inputField.getText() == "123+-56");
+ passShortKeyPress(KeyCodes::JoystickEnter);
+
+ THEN("The result is computed")
+ {
+ REQUIRE(inputField.getText() == "67");
+ }
+ }
+
+ AND_WHEN("We delete the input")
+ {
+ passShortKeyPresses({3, KeyCodes::NumericKeyPnd});
+
+ THEN("Input is deleted")
+ {
+ REQUIRE(inputField.getText().empty());
+ }
+
+ AND_WHEN("We press # again")
+ {
+ passShortKeyPress(KeyCodes::NumericKeyPnd);
+
+ THEN("Previous input is restored")
+ {
+ REQUIRE(inputField.getText() == "123+");
+ }
+ }
}
}
@@ 290,7 395,7 @@ SCENARIO("Input Processor tests")
THEN("It is shown")
{
- REQUIRE(inputField.getText() == "123+4.56");
+ REQUIRE(inputField.getText() == "4.56");
}
AND_WHEN("We press the fraction key again")
@@ 300,11 405,11 @@ SCENARIO("Input Processor tests")
THEN("It is ignored")
{
- REQUIRE(inputField.getText() == "123+4.56456");
+ REQUIRE(inputField.getText() == "4.56456");
}
}
- AND_WHEN("We try to enter more than 6 decimals")
+ AND_WHEN("We try to enter more than 5 decimals")
{
passShortKeyPresses({KeyCodes::NumericKey4,
KeyCodes::NumericKey5,
@@ 313,9 418,9 @@ SCENARIO("Input Processor tests")
KeyCodes::NumericKey8,
KeyCodes::NumericKey9});
- THEN("The input is truncated to 6 decimals")
+ THEN("The input is truncated")
{
- REQUIRE(inputField.getText() == "123+4.564567");
+ REQUIRE(inputField.getText() == "4.56456");
}
}
}
@@ 354,7 459,9 @@ SCENARIO("Input Processor tests")
WHEN("We do BIG math")
{
- inputField.setText("99999×99999");
+ passShortKeyPresses({5, KeyCodes::NumericKey9});
+ passShortKeyPress(MultiplicationKey);
+ passShortKeyPresses({5, KeyCodes::NumericKey9});
passShortKeyPress(KeyCodes::JoystickEnter);
THEN("Output contains exponent")
@@ 368,7 475,36 @@ SCENARIO("Input Processor tests")
THEN("Input is cleared before typing")
{
- REQUIRE(inputField.getText() == "4-56");
+ REQUIRE(inputField.getText() == "56");
+ }
+ }
+ }
+
+ WHEN("We enter an equation")
+ {
+ passShortKeyPresses({3, KeyCodes::NumericKey1});
+ passShortKeyPress(MultiplicationKey);
+ passShortKeyPress(KeyCodes::NumericKey4);
+
+ AND_WHEN("We press another operation")
+ {
+ passShortKeyPress(PlusKey);
+
+ THEN("The previous operation is computed first")
+ {
+ REQUIRE(inputField.getText() == "444+");
+ }
+
+ AND_WHEN("We continue input")
+ {
+ passShortKeyPress(MinusKey);
+ passShortKeyPresses({3, KeyCodes::NumericKey1});
+ passShortKeyPress(KeyCodes::JoystickEnter);
+
+ THEN("The following equation is computed properly")
+ {
+ REQUIRE(inputField.getText() == "333");
+ }
}
}
}
M module-apps/application-calculator/tests/CalculatorUtility_tests.cpp => module-apps/application-calculator/tests/CalculatorUtility_tests.cpp +4 -3
@@ 3,6 3,7 @@
#include <catch2/catch.hpp>
#include "application-calculator/data/CalculatorUtility.hpp"
+#include "application-calculator/data/CalculatorInputProcessor.hpp"
#include <i18n/i18n.hpp>
#include <cstring>
@@ 97,7 98,7 @@ TEST_CASE("Calculator utilities")
SECTION("Division by 0")
{
auto result = calculator.calculate("15+5÷0");
- REQUIRE(result.value == utils::translate("app_calculator_error"));
+ REQUIRE(result.value == calc::symbols::strings::error_str());
REQUIRE(result.equation == "15+5/0");
REQUIRE(result.isError);
}
@@ 105,7 106,7 @@ TEST_CASE("Calculator utilities")
SECTION("Division 0 by 0")
{
auto result = calculator.calculate("0÷0");
- REQUIRE(result.value == utils::translate("app_calculator_error"));
+ REQUIRE(result.value == calc::symbols::strings::error_str());
REQUIRE(result.equation == "0/0");
REQUIRE(result.isError);
}
@@ 113,7 114,7 @@ TEST_CASE("Calculator utilities")
SECTION("Result exceeds maximum number")
{
auto result = calculator.calculate("1.79769e+308×2");
- REQUIRE(result.value == utils::translate("app_calculator_error"));
+ REQUIRE(result.value == calc::symbols::strings::error_str());
REQUIRE(result.equation == "1.79769e+308*2");
REQUIRE(result.isError);
}
M module-apps/application-calculator/widgets/CalculatorStyle.hpp => module-apps/application-calculator/widgets/CalculatorStyle.hpp +3 -4
@@ 8,8 8,6 @@
namespace style::calculator
{
inline constexpr auto grid_cells = 9;
- inline constexpr auto equals = "app_calculator_equals";
- inline constexpr auto decimal_separator = "app_calculator_decimal_separator";
namespace window
{
@@ 19,7 17,8 @@ namespace style::calculator
inline constexpr auto math_box_cell_width = style::window::default_body_width / 3;
inline constexpr auto input_offset_top = style::header::height + 20;
inline constexpr auto input_height = 100;
- inline constexpr auto input_width = 380;
- inline constexpr auto input_margin = 50;
+ inline constexpr auto input_width = 400;
+ inline constexpr auto input_margin = 40;
} // namespace window
+
} // namespace style::calculator
M module-apps/application-calculator/windows/CalculatorMainWindow.cpp => module-apps/application-calculator/windows/CalculatorMainWindow.cpp +2 -3
@@ 4,7 4,6 @@
#include "CalculatorMainWindow.hpp"
#include "application-calculator/widgets/CalculatorStyle.hpp"
#include "application-calculator/data/CalculatorInputProcessorText.hpp"
-#include <i18n/i18n.hpp>
namespace gui
{
@@ 24,8 23,8 @@ namespace gui
bottomBar->setActive(gui::BottomBar::Side::RIGHT, true);
bottomBar->setActive(gui::BottomBar::Side::LEFT, true);
bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::translate(style::strings::common::back));
- bottomBar->setText(gui::BottomBar::Side::CENTER, utils::translate(style::calculator::equals));
- bottomBar->setText(gui::BottomBar::Side::LEFT, utils::translate(style::calculator::decimal_separator));
+ bottomBar->setText(gui::BottomBar::Side::CENTER, calc::symbols::strings::equals_str());
+ bottomBar->setText(gui::BottomBar::Side::LEFT, calc::symbols::strings::decimal_separator_str());
bottomBar->setFont(BottomBar::Side::LEFT, style::window::font::largelight);
mathOperationInput = new gui::Text(this,