NumericInput.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*
  2. * Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "NumericInput.h"
  7. #include "ctype.h"
  8. NumericInput::NumericInput()
  9. {
  10. set_text("0");
  11. on_change = [&] {
  12. auto number_opt = text().to_int();
  13. if (number_opt.has_value()) {
  14. set_current_number(number_opt.value(), false);
  15. return;
  16. }
  17. StringBuilder builder;
  18. bool first = true;
  19. for (auto& ch : text()) {
  20. if (isdigit(ch) || (first && ((ch == '-' && m_min_number < 0) || ch == '+')))
  21. builder.append(ch);
  22. first = false;
  23. }
  24. auto new_number_opt = builder.to_string().to_int();
  25. if (!new_number_opt.has_value()) {
  26. m_needs_text_reset = true;
  27. set_text(builder.to_string());
  28. return;
  29. } else {
  30. m_needs_text_reset = false;
  31. }
  32. set_text(builder.to_string());
  33. set_current_number(new_number_opt.value(), false);
  34. };
  35. on_up_pressed = [&] {
  36. if (m_current_number < m_max_number)
  37. set_current_number(m_current_number + 1);
  38. };
  39. on_down_pressed = [&] {
  40. if (m_current_number > m_min_number)
  41. set_current_number(m_current_number - 1);
  42. };
  43. on_focusout = [&] { on_focus_lost(); };
  44. on_return_pressed = [&] { on_focus_lost(); };
  45. on_escape_pressed = [&] { on_focus_lost(); };
  46. }
  47. void NumericInput::set_min_number(i32 number)
  48. {
  49. m_min_number = number;
  50. if (m_current_number < number)
  51. set_current_number(number);
  52. }
  53. void NumericInput::set_max_number(i32 number)
  54. {
  55. m_max_number = number;
  56. if (m_current_number > number)
  57. set_current_number(number);
  58. }
  59. void NumericInput::on_focus_lost()
  60. {
  61. if (m_needs_text_reset) {
  62. set_text(String::number(m_current_number));
  63. m_needs_text_reset = false;
  64. }
  65. if (on_number_changed)
  66. on_number_changed(m_current_number);
  67. }
  68. void NumericInput::set_current_number(i32 number, bool call_change_handler)
  69. {
  70. if (number == m_current_number)
  71. return;
  72. m_current_number = clamp(number, m_min_number, m_max_number);
  73. set_text(String::number(m_current_number));
  74. if (on_number_changed && call_change_handler)
  75. on_number_changed(m_current_number);
  76. }