GoToOffsetDialog.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright (c) 2021-2022, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "GoToOffsetDialog.h"
  7. #include <AK/String.h>
  8. #include <Applications/HexEditor/GoToOffsetDialogGML.h>
  9. #include <LibGUI/BoxLayout.h>
  10. #include <LibGUI/Button.h>
  11. #include <LibGUI/ComboBox.h>
  12. #include <LibGUI/ItemListModel.h>
  13. #include <LibGUI/Label.h>
  14. #include <LibGUI/MessageBox.h>
  15. #include <LibGUI/Statusbar.h>
  16. #include <LibGUI/TextBox.h>
  17. #include <LibGUI/Widget.h>
  18. GUI::Dialog::ExecResult GoToOffsetDialog::show(GUI::Window* parent_window, int& history_offset, int& out_offset, int selection_offset, int buffer_size)
  19. {
  20. auto dialog = GoToOffsetDialog::construct();
  21. dialog->m_selection_offset = selection_offset;
  22. dialog->m_buffer_size = buffer_size;
  23. if (parent_window)
  24. dialog->set_icon(parent_window->icon());
  25. if (history_offset)
  26. dialog->m_text_editor->set_text(String::formatted("{}", history_offset));
  27. auto result = dialog->exec();
  28. if (result != ExecResult::OK)
  29. return result;
  30. auto input_offset = dialog->process_input();
  31. history_offset = move(input_offset);
  32. auto new_offset = dialog->calculate_new_offset(input_offset);
  33. dbgln("Go to offset: value={}", new_offset);
  34. out_offset = move(new_offset);
  35. return ExecResult::OK;
  36. }
  37. int GoToOffsetDialog::process_input()
  38. {
  39. auto input_offset = m_text_editor->text().trim_whitespace();
  40. int offset;
  41. auto type = m_offset_type_box->text().trim_whitespace();
  42. if (type == "Decimal") {
  43. offset = String::formatted("{}", input_offset).to_int().value_or(0);
  44. } else if (type == "Hexadecimal") {
  45. offset = strtol(String::formatted("{}", input_offset).characters(), nullptr, 16);
  46. } else {
  47. VERIFY_NOT_REACHED();
  48. }
  49. return offset;
  50. }
  51. int GoToOffsetDialog::calculate_new_offset(int input_offset)
  52. {
  53. int new_offset;
  54. auto from = m_offset_from_box->text().trim_whitespace();
  55. if (from == "Start") {
  56. new_offset = input_offset;
  57. } else if (from == "End") {
  58. new_offset = m_buffer_size - input_offset;
  59. } else if (from == "Here") {
  60. new_offset = input_offset + m_selection_offset;
  61. } else {
  62. VERIFY_NOT_REACHED();
  63. }
  64. if (new_offset > m_buffer_size)
  65. new_offset = m_buffer_size;
  66. if (new_offset < 0)
  67. new_offset = 0;
  68. return new_offset;
  69. }
  70. void GoToOffsetDialog::update_statusbar()
  71. {
  72. auto new_offset = calculate_new_offset(process_input());
  73. m_statusbar->set_text(0, String::formatted("HEX: {:#08X}", new_offset));
  74. m_statusbar->set_text(1, String::formatted("DEC: {}", new_offset));
  75. }
  76. GoToOffsetDialog::GoToOffsetDialog()
  77. : Dialog(nullptr)
  78. {
  79. resize(300, 80);
  80. center_on_screen();
  81. set_resizable(false);
  82. set_title("Go to Offset");
  83. auto& main_widget = set_main_widget<GUI::Widget>();
  84. if (!main_widget.load_from_gml(go_to_offset_dialog_gml))
  85. VERIFY_NOT_REACHED();
  86. m_text_editor = *main_widget.find_descendant_of_type_named<GUI::TextBox>("text_editor");
  87. m_go_button = *main_widget.find_descendant_of_type_named<GUI::Button>("go_button");
  88. m_offset_type_box = *main_widget.find_descendant_of_type_named<GUI::ComboBox>("offset_type");
  89. m_offset_from_box = *main_widget.find_descendant_of_type_named<GUI::ComboBox>("offset_from");
  90. m_statusbar = *main_widget.find_descendant_of_type_named<GUI::Statusbar>("statusbar");
  91. m_offset_type.append("Decimal");
  92. m_offset_type.append("Hexadecimal");
  93. m_offset_type_box->set_model(GUI::ItemListModel<String>::create(m_offset_type));
  94. m_offset_type_box->set_selected_index(0);
  95. m_offset_type_box->set_only_allow_values_from_model(true);
  96. m_offset_from.append("Start");
  97. m_offset_from.append("Here");
  98. m_offset_from.append("End");
  99. m_offset_from_box->set_model(GUI::ItemListModel<String>::create(m_offset_from));
  100. m_offset_from_box->set_selected_index(0);
  101. m_offset_from_box->set_only_allow_values_from_model(true);
  102. m_text_editor->on_return_pressed = [this] {
  103. m_go_button->click();
  104. };
  105. m_go_button->on_click = [this](auto) {
  106. done(ExecResult::OK);
  107. };
  108. m_text_editor->on_change = [this]() {
  109. auto text = m_text_editor->text();
  110. if (text.starts_with("0x")) {
  111. m_offset_type_box->set_selected_index(1);
  112. m_text_editor->set_text(text.replace("0x", ""));
  113. }
  114. update_statusbar();
  115. };
  116. m_offset_type_box->on_change = [this](auto&, auto&) {
  117. update_statusbar();
  118. };
  119. m_offset_from_box->on_change = [this](auto&, auto&) {
  120. update_statusbar();
  121. };
  122. update_statusbar();
  123. }