mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
HexEditor: Port HexEditor to GML compilation
This commit is contained in:
parent
bcec05a7cb
commit
935aaab757
Notes:
sideshowbarker
2024-07-17 06:46:15 +09:00
Author: https://github.com/tetektoza Commit: https://github.com/SerenityOS/serenity/commit/935aaab757 Pull-request: https://github.com/SerenityOS/serenity/pull/21271 Reviewed-by: https://github.com/timschumi ✅
15 changed files with 147 additions and 51 deletions
|
@ -4,24 +4,21 @@ serenity_component(
|
|||
TARGETS HexEditor
|
||||
)
|
||||
|
||||
stringify_gml(HexEditorWindow.gml HexEditorWindowGML.h hex_editor_window_gml)
|
||||
stringify_gml(GoToOffsetDialog.gml GoToOffsetDialogGML.h go_to_offset_dialog_gml)
|
||||
stringify_gml(FindDialog.gml FindDialogGML.h find_dialog_gml)
|
||||
compile_gml(HexEditorWidget.gml HexEditorWidgetGML.cpp)
|
||||
compile_gml(GoToOffsetWidget.gml GoToOffsetWidgetGML.cpp)
|
||||
compile_gml(FindWidget.gml FindWidgetGML.cpp)
|
||||
|
||||
set(SOURCES
|
||||
FindDialog.cpp
|
||||
FindWidgetGML.cpp
|
||||
GoToOffsetDialog.cpp
|
||||
GoToOffsetWidgetGML.cpp
|
||||
HexDocument.cpp
|
||||
HexEditor.cpp
|
||||
HexEditorWidgetGML.cpp
|
||||
HexEditorWidget.cpp
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set(GENERATED_SOURCES
|
||||
FindDialogGML.h
|
||||
GoToOffsetDialogGML.h
|
||||
HexEditorWindowGML.h
|
||||
)
|
||||
|
||||
serenity_app(HexEditor ICON app-hex-editor)
|
||||
target_link_libraries(HexEditor PRIVATE LibCore LibGfx LibGUI LibConfig LibDesktop LibFileSystemAccessClient LibMain LibTextCodec)
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <AK/Array.h>
|
||||
#include <AK/Hex.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <Applications/HexEditor/FindDialogGML.h>
|
||||
#include <LibGUI/BoxLayout.h>
|
||||
#include <LibGUI/Button.h>
|
||||
#include <LibGUI/MessageBox.h>
|
||||
|
@ -32,7 +31,13 @@ static constexpr Array<Option, 2> options = {
|
|||
|
||||
GUI::Dialog::ExecResult FindDialog::show(GUI::Window* parent_window, String& out_text, ByteBuffer& out_buffer, bool& find_all)
|
||||
{
|
||||
auto dialog = FindDialog::construct();
|
||||
auto dialog_or_error = FindDialog::try_create();
|
||||
if (dialog_or_error.is_error()) {
|
||||
GUI::MessageBox::show(parent_window, "Couldn't load find dialog"sv, "Error while opening find dialog"sv, GUI::MessageBox::Type::Error);
|
||||
return ExecResult::Aborted;
|
||||
}
|
||||
|
||||
auto dialog = dialog_or_error.release_value();
|
||||
|
||||
if (parent_window)
|
||||
dialog->set_icon(parent_window->icon());
|
||||
|
@ -91,7 +96,15 @@ Result<ByteBuffer, String> FindDialog::process_input(String text_value, OptionId
|
|||
}
|
||||
}
|
||||
|
||||
FindDialog::FindDialog()
|
||||
ErrorOr<NonnullRefPtr<FindDialog>> FindDialog::try_create()
|
||||
{
|
||||
auto find_widget = TRY(HexEditor::FindWidget::try_create());
|
||||
auto find_dialog = TRY(adopt_nonnull_ref_or_enomem(new (nothrow)
|
||||
FindDialog(move(find_widget))));
|
||||
return find_dialog;
|
||||
}
|
||||
|
||||
FindDialog::FindDialog(NonnullRefPtr<HexEditor::FindWidget> find_widget)
|
||||
: Dialog(nullptr)
|
||||
{
|
||||
resize(280, 146);
|
||||
|
@ -99,15 +112,14 @@ FindDialog::FindDialog()
|
|||
set_resizable(false);
|
||||
set_title("Find");
|
||||
|
||||
auto main_widget = set_main_widget<GUI::Widget>();
|
||||
main_widget->load_from_gml(find_dialog_gml).release_value_but_fixme_should_propagate_errors();
|
||||
set_main_widget(find_widget);
|
||||
|
||||
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");
|
||||
m_text_editor = *find_widget->find_descendant_of_type_named<GUI::TextBox>("text_editor");
|
||||
m_find_button = *find_widget->find_descendant_of_type_named<GUI::Button>("find_button");
|
||||
m_find_all_button = *find_widget->find_descendant_of_type_named<GUI::Button>("find_all_button");
|
||||
m_cancel_button = *find_widget->find_descendant_of_type_named<GUI::Button>("cancel_button");
|
||||
|
||||
auto& radio_container = *main_widget->find_descendant_of_type_named<GUI::Widget>("radio_container");
|
||||
auto& radio_container = *find_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>();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "FindWidget.h"
|
||||
#include <AK/Result.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibGUI/Dialog.h>
|
||||
|
@ -17,10 +18,11 @@ enum OptionId {
|
|||
};
|
||||
|
||||
class FindDialog : public GUI::Dialog {
|
||||
C_OBJECT(FindDialog);
|
||||
C_OBJECT_ABSTRACT(FindDialog);
|
||||
|
||||
public:
|
||||
static ExecResult show(GUI::Window* parent_window, String& out_tex, ByteBuffer& out_buffer, bool& find_all);
|
||||
static ErrorOr<NonnullRefPtr<FindDialog>> try_create();
|
||||
|
||||
private:
|
||||
Result<ByteBuffer, String> process_input(String text_value, OptionId opt);
|
||||
|
@ -29,7 +31,7 @@ private:
|
|||
OptionId selected_option() const { return m_selected_option; }
|
||||
bool find_all() const { return m_find_all; }
|
||||
|
||||
FindDialog();
|
||||
FindDialog(NonnullRefPtr<HexEditor::FindWidget> find_widget);
|
||||
virtual ~FindDialog() override = default;
|
||||
|
||||
RefPtr<GUI::TextEditor> m_text_editor;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@GUI::Widget {
|
||||
@HexEditor::FindWidget {
|
||||
name: "main"
|
||||
fixed_width: 280
|
||||
fixed_height: 146
|
23
Userland/Applications/HexEditor/FindWidget.h
Normal file
23
Userland/Applications/HexEditor/FindWidget.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2023, the SerenityOS developers
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibGUI/Widget.h>
|
||||
|
||||
namespace HexEditor {
|
||||
|
||||
class FindWidget : public GUI::Widget {
|
||||
C_OBJECT_ABSTRACT(FindWidget)
|
||||
public:
|
||||
static ErrorOr<NonnullRefPtr<FindWidget>> try_create();
|
||||
virtual ~FindWidget() override = default;
|
||||
|
||||
private:
|
||||
FindWidget() = default;
|
||||
};
|
||||
|
||||
}
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
#include "GoToOffsetDialog.h"
|
||||
#include <Applications/HexEditor/GoToOffsetDialogGML.h>
|
||||
#include <LibGUI/BoxLayout.h>
|
||||
#include <LibGUI/Button.h>
|
||||
#include <LibGUI/ComboBox.h>
|
||||
|
@ -18,7 +17,14 @@
|
|||
|
||||
GUI::Dialog::ExecResult GoToOffsetDialog::show(GUI::Window* parent_window, int& history_offset, int& out_offset, int selection_offset, int buffer_size)
|
||||
{
|
||||
auto dialog = GoToOffsetDialog::construct();
|
||||
auto dialog_or_error = GoToOffsetDialog::try_create();
|
||||
if (dialog_or_error.is_error()) {
|
||||
GUI::MessageBox::show(parent_window, "Couldn't load \"go to offset\" dialog"sv, "Error while opening \"go to offset\" dialog"sv, GUI::MessageBox::Type::Error);
|
||||
return ExecResult::Aborted;
|
||||
}
|
||||
|
||||
auto dialog = dialog_or_error.release_value();
|
||||
|
||||
dialog->m_selection_offset = selection_offset;
|
||||
dialog->m_buffer_size = buffer_size;
|
||||
|
||||
|
@ -88,7 +94,15 @@ void GoToOffsetDialog::update_statusbar()
|
|||
m_statusbar->set_text(1, String::formatted("DEC: {}", new_offset).release_value_but_fixme_should_propagate_errors());
|
||||
}
|
||||
|
||||
GoToOffsetDialog::GoToOffsetDialog()
|
||||
ErrorOr<NonnullRefPtr<GoToOffsetDialog>> GoToOffsetDialog::try_create()
|
||||
{
|
||||
auto offset_widget = TRY(HexEditor::GoToOffsetWidget::try_create());
|
||||
auto offset_dialog = TRY(adopt_nonnull_ref_or_enomem(new (nothrow)
|
||||
GoToOffsetDialog(move(offset_widget))));
|
||||
return offset_dialog;
|
||||
}
|
||||
|
||||
GoToOffsetDialog::GoToOffsetDialog(NonnullRefPtr<HexEditor::GoToOffsetWidget> goto_offset_widget)
|
||||
: Dialog(nullptr)
|
||||
{
|
||||
resize(300, 80);
|
||||
|
@ -96,14 +110,13 @@ GoToOffsetDialog::GoToOffsetDialog()
|
|||
set_resizable(false);
|
||||
set_title("Go to Offset");
|
||||
|
||||
auto main_widget = set_main_widget<GUI::Widget>();
|
||||
main_widget->load_from_gml(go_to_offset_dialog_gml).release_value_but_fixme_should_propagate_errors();
|
||||
set_main_widget(goto_offset_widget);
|
||||
|
||||
m_text_editor = *main_widget->find_descendant_of_type_named<GUI::TextBox>("text_editor");
|
||||
m_go_button = *main_widget->find_descendant_of_type_named<GUI::Button>("go_button");
|
||||
m_offset_type_box = *main_widget->find_descendant_of_type_named<GUI::ComboBox>("offset_type");
|
||||
m_offset_from_box = *main_widget->find_descendant_of_type_named<GUI::ComboBox>("offset_from");
|
||||
m_statusbar = *main_widget->find_descendant_of_type_named<GUI::Statusbar>("statusbar");
|
||||
m_text_editor = *goto_offset_widget->find_descendant_of_type_named<GUI::TextBox>("text_editor");
|
||||
m_go_button = *goto_offset_widget->find_descendant_of_type_named<GUI::Button>("go_button");
|
||||
m_offset_type_box = *goto_offset_widget->find_descendant_of_type_named<GUI::ComboBox>("offset_type");
|
||||
m_offset_from_box = *goto_offset_widget->find_descendant_of_type_named<GUI::ComboBox>("offset_from");
|
||||
m_statusbar = *goto_offset_widget->find_descendant_of_type_named<GUI::Statusbar>("statusbar");
|
||||
|
||||
m_offset_type.append("Decimal"sv);
|
||||
m_offset_type.append("Hexadecimal"sv);
|
||||
|
|
|
@ -6,18 +6,20 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GoToOffsetWidget.h"
|
||||
#include <AK/Result.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGUI/Dialog.h>
|
||||
|
||||
class GoToOffsetDialog : public GUI::Dialog {
|
||||
C_OBJECT(GoToOffsetDialog);
|
||||
C_OBJECT_ABSTRACT(GoToOffsetDialog);
|
||||
|
||||
public:
|
||||
static ExecResult show(GUI::Window* parent_window, int& history_offset, int& out_offset, int selection_offset, int end);
|
||||
static ErrorOr<NonnullRefPtr<GoToOffsetDialog>> try_create();
|
||||
|
||||
private:
|
||||
GoToOffsetDialog();
|
||||
GoToOffsetDialog(NonnullRefPtr<HexEditor::GoToOffsetWidget> goto_offset_widget);
|
||||
virtual ~GoToOffsetDialog() override = default;
|
||||
void update_statusbar();
|
||||
int process_input();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@GUI::Widget {
|
||||
@HexEditor::GoToOffsetWidget {
|
||||
name: "main"
|
||||
fixed_width: 300
|
||||
fixed_height: 80
|
23
Userland/Applications/HexEditor/GoToOffsetWidget.h
Normal file
23
Userland/Applications/HexEditor/GoToOffsetWidget.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2023, the SerenityOS developers
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibGUI/Widget.h>
|
||||
|
||||
namespace HexEditor {
|
||||
|
||||
class GoToOffsetWidget : public GUI::Widget {
|
||||
C_OBJECT_ABSTRACT(GoToOffsetWidget)
|
||||
public:
|
||||
static ErrorOr<NonnullRefPtr<GoToOffsetWidget>> try_create();
|
||||
virtual ~GoToOffsetWidget() override = default;
|
||||
|
||||
private:
|
||||
GoToOffsetWidget() = default;
|
||||
};
|
||||
|
||||
}
|
|
@ -30,6 +30,8 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace HexEditor {
|
||||
|
||||
HexEditor::HexEditor()
|
||||
: m_document(make<HexDocumentMemory>(ByteBuffer::create_zeroed(0).release_value_but_fixme_should_propagate_errors()))
|
||||
{
|
||||
|
@ -287,7 +289,7 @@ void HexEditor::mousedown_event(GUI::MouseEvent& event)
|
|||
if (offset >= m_document->size())
|
||||
return;
|
||||
|
||||
dbgln_if(HEX_DEBUG, "HexEditor::mousedown_event(hex): offset={}", offset);
|
||||
dbgln_if(HEX_DEBUG, "Editor::mousedown_event(hex): offset={}", offset);
|
||||
|
||||
m_edit_mode = EditMode::Hex;
|
||||
m_cursor_at_low_nibble = false;
|
||||
|
@ -310,7 +312,7 @@ void HexEditor::mousedown_event(GUI::MouseEvent& event)
|
|||
if (offset >= m_document->size())
|
||||
return;
|
||||
|
||||
dbgln_if(HEX_DEBUG, "HexEditor::mousedown_event(text): offset={}", offset);
|
||||
dbgln_if(HEX_DEBUG, "Editor::mousedown_event(text): offset={}", offset);
|
||||
|
||||
m_position = offset;
|
||||
m_cursor_at_low_nibble = false;
|
||||
|
@ -416,7 +418,7 @@ void HexEditor::scroll_position_into_view(size_t position)
|
|||
|
||||
void HexEditor::keydown_event(GUI::KeyEvent& event)
|
||||
{
|
||||
dbgln_if(HEX_DEBUG, "HexEditor::keydown_event key={}", static_cast<u8>(event.key()));
|
||||
dbgln_if(HEX_DEBUG, "Editor::keydown_event key={}", static_cast<u8>(event.key()));
|
||||
|
||||
auto move_and_update_cursor_by = [&](i64 cursor_location_change) {
|
||||
size_t new_position = m_position + cursor_location_change;
|
||||
|
@ -914,3 +916,5 @@ GUI::UndoStack& HexEditor::undo_stack()
|
|||
{
|
||||
return m_undo_stack;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/TextAlignment.h>
|
||||
|
||||
namespace HexEditor {
|
||||
|
||||
class HexEditor : public GUI::AbstractScrollableWidget {
|
||||
C_OBJECT(HexEditor)
|
||||
public:
|
||||
|
@ -111,3 +113,5 @@ private:
|
|||
|
||||
void reset_cursor_blink_state();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include <AK/Forward.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <Applications/HexEditor/HexEditorWindowGML.h>
|
||||
#include <LibConfig/Client.h>
|
||||
#include <LibDesktop/Launcher.h>
|
||||
#include <LibFileSystemAccessClient/Client.h>
|
||||
|
@ -36,15 +35,20 @@
|
|||
#include <LibTextCodec/Decoder.h>
|
||||
#include <string.h>
|
||||
|
||||
REGISTER_WIDGET(HexEditor, HexEditor);
|
||||
namespace HexEditor {
|
||||
|
||||
HexEditorWidget::HexEditorWidget()
|
||||
ErrorOr<NonnullRefPtr<HexEditorWidget>> HexEditorWidget::create()
|
||||
{
|
||||
load_from_gml(hex_editor_window_gml).release_value_but_fixme_should_propagate_errors();
|
||||
auto widget = TRY(try_create());
|
||||
TRY(widget->setup());
|
||||
return widget;
|
||||
}
|
||||
|
||||
ErrorOr<void> HexEditorWidget::setup()
|
||||
{
|
||||
m_toolbar = *find_descendant_of_type_named<GUI::Toolbar>("toolbar");
|
||||
m_toolbar_container = *find_descendant_of_type_named<GUI::ToolbarContainer>("toolbar_container");
|
||||
m_editor = *find_descendant_of_type_named<HexEditor>("editor");
|
||||
m_editor = *find_descendant_of_type_named<::HexEditor::HexEditor>("editor");
|
||||
m_statusbar = *find_descendant_of_type_named<GUI::Statusbar>("statusbar");
|
||||
m_search_results = *find_descendant_of_type_named<GUI::TableView>("search_results");
|
||||
m_search_results_container = *find_descendant_of_type_named<GUI::Widget>("search_results_container");
|
||||
|
@ -60,9 +64,9 @@ HexEditorWidget::HexEditorWidget()
|
|||
m_editor->update();
|
||||
};
|
||||
|
||||
m_editor->on_status_change = [this](int position, HexEditor::EditMode edit_mode, int selection_start, int selection_end) {
|
||||
m_editor->on_status_change = [this](int position, HexEditor::HexEditor::EditMode edit_mode, int selection_start, int selection_end) {
|
||||
m_statusbar->set_text(0, String::formatted("Offset: {:#08X}", position).release_value_but_fixme_should_propagate_errors());
|
||||
m_statusbar->set_text(1, String::formatted("Edit Mode: {}", edit_mode == HexEditor::EditMode::Hex ? "Hex" : "Text").release_value_but_fixme_should_propagate_errors());
|
||||
m_statusbar->set_text(1, String::formatted("Edit Mode: {}", edit_mode == HexEditor::HexEditor::EditMode::Hex ? "Hex" : "Text").release_value_but_fixme_should_propagate_errors());
|
||||
m_statusbar->set_text(2, String::formatted("Selection Start: {}", selection_start).release_value_but_fixme_should_propagate_errors());
|
||||
m_statusbar->set_text(3, String::formatted("Selection End: {}", selection_end).release_value_but_fixme_should_propagate_errors());
|
||||
m_statusbar->set_text(4, String::formatted("Selected Bytes: {}", m_editor->selection_size()).release_value_but_fixme_should_propagate_errors());
|
||||
|
@ -279,6 +283,8 @@ HexEditorWidget::HexEditorWidget()
|
|||
GUI::Application::the()->on_action_leave = [this](GUI::Action&) {
|
||||
m_statusbar->set_override_text({});
|
||||
};
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void HexEditorWidget::update_inspector_values(size_t position)
|
||||
|
@ -647,3 +653,5 @@ void HexEditorWidget::drop_event(GUI::DropEvent& event)
|
|||
open_file(response.value().filename(), response.value().release_stream());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@GUI::Widget {
|
||||
@HexEditor::HexEditorWidget {
|
||||
name: "main"
|
||||
fill_with_background_color: true
|
||||
layout: @GUI::VerticalBoxLayout {
|
|
@ -19,18 +19,23 @@
|
|||
#include <LibGUI/Widget.h>
|
||||
#include <LibGUI/Window.h>
|
||||
|
||||
class HexEditor;
|
||||
|
||||
namespace HexEditor {
|
||||
class HexEditorWidget final : public GUI::Widget {
|
||||
C_OBJECT(HexEditorWidget)
|
||||
C_OBJECT_ABSTRACT(HexEditorWidget)
|
||||
public:
|
||||
virtual ~HexEditorWidget() override = default;
|
||||
void open_file(String const& filename, NonnullOwnPtr<Core::File>);
|
||||
ErrorOr<void> initialize_menubar(GUI::Window&);
|
||||
bool request_close();
|
||||
|
||||
static ErrorOr<NonnullRefPtr<HexEditorWidget>> create();
|
||||
|
||||
protected:
|
||||
static ErrorOr<NonnullRefPtr<HexEditorWidget>> try_create();
|
||||
|
||||
private:
|
||||
HexEditorWidget();
|
||||
ErrorOr<void> setup();
|
||||
HexEditorWidget() = default;
|
||||
void set_path(StringView);
|
||||
void update_title();
|
||||
void set_search_results_visible(bool visible);
|
||||
|
@ -85,3 +90,5 @@ private:
|
|||
bool m_value_inspector_little_endian { true };
|
||||
bool m_selecting_from_inspector { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
window->restore_size_and_position("HexEditor"sv, "Window"sv, { { 640, 400 } });
|
||||
window->save_size_and_position_on_close("HexEditor"sv, "Window"sv);
|
||||
|
||||
auto hex_editor_widget = window->set_main_widget<HexEditorWidget>();
|
||||
auto hex_editor_widget = TRY(HexEditor::HexEditorWidget::create());
|
||||
window->set_main_widget(hex_editor_widget);
|
||||
|
||||
window->on_close_request = [&]() -> GUI::Window::CloseRequestDecision {
|
||||
if (hex_editor_widget->request_close())
|
||||
|
|
Loading…
Reference in a new issue