mirror of
https://github.com/RGBCube/serenity
synced 2025-05-22 19:35:06 +00:00

This commit has no behavior changes. In particular, this does not fix any of the wrong uses of the previous default parameter (which used to be 'false', meaning "only replace the first occurence in the string"). It simply replaces the default uses by String::replace(..., ReplaceMode::FirstOnly), leaving them incorrect.
150 lines
4.3 KiB
C++
150 lines
4.3 KiB
C++
/*
|
|
* Copyright (c) 2021-2022, the SerenityOS developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include "FindDialog.h"
|
|
#include <AK/Array.h>
|
|
#include <AK/Hex.h>
|
|
#include <AK/String.h>
|
|
#include <AK/StringView.h>
|
|
#include <Applications/HexEditor/FindDialogGML.h>
|
|
#include <LibGUI/BoxLayout.h>
|
|
#include <LibGUI/Button.h>
|
|
#include <LibGUI/MessageBox.h>
|
|
#include <LibGUI/RadioButton.h>
|
|
#include <LibGUI/TextBox.h>
|
|
#include <LibGUI/Widget.h>
|
|
|
|
struct Option {
|
|
StringView title;
|
|
OptionId opt;
|
|
bool enabled;
|
|
bool default_action;
|
|
};
|
|
|
|
static constexpr Array<Option, 2> options = {
|
|
{
|
|
{ "ASCII String", OPTION_ASCII_STRING, true, true },
|
|
{ "Hex value", OPTION_HEX_VALUE, true, false },
|
|
}
|
|
};
|
|
|
|
GUI::Dialog::ExecResult FindDialog::show(GUI::Window* parent_window, String& out_text, ByteBuffer& out_buffer, bool& find_all)
|
|
{
|
|
auto dialog = FindDialog::construct();
|
|
|
|
if (parent_window)
|
|
dialog->set_icon(parent_window->icon());
|
|
|
|
if (!out_text.is_empty() && !out_text.is_null())
|
|
dialog->m_text_editor->set_text(out_text);
|
|
|
|
dialog->m_find_button->set_enabled(!dialog->m_text_editor->text().is_empty());
|
|
dialog->m_find_all_button->set_enabled(!dialog->m_text_editor->text().is_empty());
|
|
|
|
auto result = dialog->exec();
|
|
|
|
if (result != ExecResult::OK)
|
|
return result;
|
|
|
|
auto selected_option = dialog->selected_option();
|
|
auto processed = dialog->process_input(dialog->text_value(), selected_option);
|
|
|
|
out_text = dialog->text_value();
|
|
|
|
if (processed.is_error()) {
|
|
GUI::MessageBox::show_error(parent_window, processed.error());
|
|
result = ExecResult::Aborted;
|
|
} else {
|
|
out_buffer = move(processed.value());
|
|
}
|
|
|
|
find_all = dialog->find_all();
|
|
|
|
dbgln("Find: value={} option={} find_all={}", out_text.characters(), (int)selected_option, find_all);
|
|
return result;
|
|
}
|
|
|
|
Result<ByteBuffer, String> FindDialog::process_input(String text_value, OptionId opt)
|
|
{
|
|
dbgln("process_input opt={}", (int)opt);
|
|
switch (opt) {
|
|
case OPTION_ASCII_STRING: {
|
|
if (text_value.is_empty())
|
|
return String("Input is empty");
|
|
|
|
return text_value.to_byte_buffer();
|
|
}
|
|
|
|
case OPTION_HEX_VALUE: {
|
|
auto decoded = decode_hex(text_value.replace(" ", "", ReplaceMode::All));
|
|
if (decoded.is_error())
|
|
return String::formatted("Input is invalid: {}", decoded.error().string_literal());
|
|
|
|
return decoded.value();
|
|
}
|
|
|
|
default:
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
}
|
|
|
|
FindDialog::FindDialog()
|
|
: Dialog(nullptr)
|
|
{
|
|
resize(280, 146);
|
|
center_on_screen();
|
|
set_resizable(false);
|
|
set_title("Find");
|
|
|
|
auto& main_widget = set_main_widget<GUI::Widget>();
|
|
if (!main_widget.load_from_gml(find_dialog_gml))
|
|
VERIFY_NOT_REACHED();
|
|
|
|
m_text_editor = *main_widget.find_descendant_of_type_named<GUI::TextBox>("text_editor");
|
|
m_find_button = *main_widget.find_descendant_of_type_named<GUI::Button>("find_button");
|
|
m_find_all_button = *main_widget.find_descendant_of_type_named<GUI::Button>("find_all_button");
|
|
m_cancel_button = *main_widget.find_descendant_of_type_named<GUI::Button>("cancel_button");
|
|
|
|
auto& radio_container = *main_widget.find_descendant_of_type_named<GUI::Widget>("radio_container");
|
|
for (size_t i = 0; i < options.size(); i++) {
|
|
auto action = options[i];
|
|
auto& radio = radio_container.add<GUI::RadioButton>();
|
|
radio.set_enabled(action.enabled);
|
|
radio.set_text(action.title);
|
|
|
|
radio.on_checked = [this, i](auto) {
|
|
m_selected_option = options[i].opt;
|
|
};
|
|
|
|
if (action.default_action) {
|
|
radio.set_checked(true);
|
|
m_selected_option = options[i].opt;
|
|
}
|
|
}
|
|
|
|
m_text_editor->on_change = [this]() {
|
|
m_find_button->set_enabled(!m_text_editor->text().is_empty());
|
|
m_find_all_button->set_enabled(!m_text_editor->text().is_empty());
|
|
};
|
|
|
|
m_find_button->on_click = [this](auto) {
|
|
auto text = m_text_editor->text();
|
|
if (!text.is_empty()) {
|
|
m_text_value = text;
|
|
done(ExecResult::OK);
|
|
}
|
|
};
|
|
m_find_button->set_default(true);
|
|
|
|
m_find_all_button->on_click = [this](auto) {
|
|
m_find_all = true;
|
|
m_find_button->click();
|
|
};
|
|
|
|
m_cancel_button->on_click = [this](auto) {
|
|
done(ExecResult::Cancel);
|
|
};
|
|
}
|