diff --git a/Userland/Applications/HexEditor/CMakeLists.txt b/Userland/Applications/HexEditor/CMakeLists.txt index a758818ba06..154f980adda 100644 --- a/Userland/Applications/HexEditor/CMakeLists.txt +++ b/Userland/Applications/HexEditor/CMakeLists.txt @@ -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) diff --git a/Userland/Applications/HexEditor/FindDialog.cpp b/Userland/Applications/HexEditor/FindDialog.cpp index 4d20ddfc1ba..f7b3c715470 100644 --- a/Userland/Applications/HexEditor/FindDialog.cpp +++ b/Userland/Applications/HexEditor/FindDialog.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -32,7 +31,13 @@ static constexpr Array 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 FindDialog::process_input(String text_value, OptionId } } -FindDialog::FindDialog() +ErrorOr> 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 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(); - 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("text_editor"); - m_find_button = *main_widget->find_descendant_of_type_named("find_button"); - m_find_all_button = *main_widget->find_descendant_of_type_named("find_all_button"); - m_cancel_button = *main_widget->find_descendant_of_type_named("cancel_button"); + m_text_editor = *find_widget->find_descendant_of_type_named("text_editor"); + m_find_button = *find_widget->find_descendant_of_type_named("find_button"); + m_find_all_button = *find_widget->find_descendant_of_type_named("find_all_button"); + m_cancel_button = *find_widget->find_descendant_of_type_named("cancel_button"); - auto& radio_container = *main_widget->find_descendant_of_type_named("radio_container"); + auto& radio_container = *find_widget->find_descendant_of_type_named("radio_container"); for (size_t i = 0; i < options.size(); i++) { auto action = options[i]; auto& radio = radio_container.add(); diff --git a/Userland/Applications/HexEditor/FindDialog.h b/Userland/Applications/HexEditor/FindDialog.h index 40c68184d43..6f7fc12ecab 100644 --- a/Userland/Applications/HexEditor/FindDialog.h +++ b/Userland/Applications/HexEditor/FindDialog.h @@ -6,6 +6,7 @@ #pragma once +#include "FindWidget.h" #include #include #include @@ -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> try_create(); private: Result 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 find_widget); virtual ~FindDialog() override = default; RefPtr m_text_editor; diff --git a/Userland/Applications/HexEditor/FindDialog.gml b/Userland/Applications/HexEditor/FindWidget.gml similarity index 97% rename from Userland/Applications/HexEditor/FindDialog.gml rename to Userland/Applications/HexEditor/FindWidget.gml index 728ef5f4f91..11d5ad8a5c1 100644 --- a/Userland/Applications/HexEditor/FindDialog.gml +++ b/Userland/Applications/HexEditor/FindWidget.gml @@ -1,4 +1,4 @@ -@GUI::Widget { +@HexEditor::FindWidget { name: "main" fixed_width: 280 fixed_height: 146 diff --git a/Userland/Applications/HexEditor/FindWidget.h b/Userland/Applications/HexEditor/FindWidget.h new file mode 100644 index 00000000000..d0e83bbc98f --- /dev/null +++ b/Userland/Applications/HexEditor/FindWidget.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023, the SerenityOS developers + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace HexEditor { + +class FindWidget : public GUI::Widget { + C_OBJECT_ABSTRACT(FindWidget) +public: + static ErrorOr> try_create(); + virtual ~FindWidget() override = default; + +private: + FindWidget() = default; +}; + +} diff --git a/Userland/Applications/HexEditor/GoToOffsetDialog.cpp b/Userland/Applications/HexEditor/GoToOffsetDialog.cpp index a0d4d067c9a..62d318264d0 100644 --- a/Userland/Applications/HexEditor/GoToOffsetDialog.cpp +++ b/Userland/Applications/HexEditor/GoToOffsetDialog.cpp @@ -5,7 +5,6 @@ */ #include "GoToOffsetDialog.h" -#include #include #include #include @@ -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> 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 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(); - 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("text_editor"); - m_go_button = *main_widget->find_descendant_of_type_named("go_button"); - m_offset_type_box = *main_widget->find_descendant_of_type_named("offset_type"); - m_offset_from_box = *main_widget->find_descendant_of_type_named("offset_from"); - m_statusbar = *main_widget->find_descendant_of_type_named("statusbar"); + m_text_editor = *goto_offset_widget->find_descendant_of_type_named("text_editor"); + m_go_button = *goto_offset_widget->find_descendant_of_type_named("go_button"); + m_offset_type_box = *goto_offset_widget->find_descendant_of_type_named("offset_type"); + m_offset_from_box = *goto_offset_widget->find_descendant_of_type_named("offset_from"); + m_statusbar = *goto_offset_widget->find_descendant_of_type_named("statusbar"); m_offset_type.append("Decimal"sv); m_offset_type.append("Hexadecimal"sv); diff --git a/Userland/Applications/HexEditor/GoToOffsetDialog.h b/Userland/Applications/HexEditor/GoToOffsetDialog.h index bdfaaf66c7f..660f10dc289 100644 --- a/Userland/Applications/HexEditor/GoToOffsetDialog.h +++ b/Userland/Applications/HexEditor/GoToOffsetDialog.h @@ -6,18 +6,20 @@ #pragma once +#include "GoToOffsetWidget.h" #include #include #include 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> try_create(); private: - GoToOffsetDialog(); + GoToOffsetDialog(NonnullRefPtr goto_offset_widget); virtual ~GoToOffsetDialog() override = default; void update_statusbar(); int process_input(); diff --git a/Userland/Applications/HexEditor/GoToOffsetDialog.gml b/Userland/Applications/HexEditor/GoToOffsetWidget.gml similarity index 97% rename from Userland/Applications/HexEditor/GoToOffsetDialog.gml rename to Userland/Applications/HexEditor/GoToOffsetWidget.gml index 9504757f940..bc686222b39 100644 --- a/Userland/Applications/HexEditor/GoToOffsetDialog.gml +++ b/Userland/Applications/HexEditor/GoToOffsetWidget.gml @@ -1,4 +1,4 @@ -@GUI::Widget { +@HexEditor::GoToOffsetWidget { name: "main" fixed_width: 300 fixed_height: 80 diff --git a/Userland/Applications/HexEditor/GoToOffsetWidget.h b/Userland/Applications/HexEditor/GoToOffsetWidget.h new file mode 100644 index 00000000000..8bd5752df00 --- /dev/null +++ b/Userland/Applications/HexEditor/GoToOffsetWidget.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023, the SerenityOS developers + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace HexEditor { + +class GoToOffsetWidget : public GUI::Widget { + C_OBJECT_ABSTRACT(GoToOffsetWidget) +public: + static ErrorOr> try_create(); + virtual ~GoToOffsetWidget() override = default; + +private: + GoToOffsetWidget() = default; +}; + +} diff --git a/Userland/Applications/HexEditor/HexEditor.cpp b/Userland/Applications/HexEditor/HexEditor.cpp index 9d427033df6..1ca9a0a788b 100644 --- a/Userland/Applications/HexEditor/HexEditor.cpp +++ b/Userland/Applications/HexEditor/HexEditor.cpp @@ -30,6 +30,8 @@ #include #include +namespace HexEditor { + HexEditor::HexEditor() : m_document(make(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(event.key())); + dbgln_if(HEX_DEBUG, "Editor::keydown_event key={}", static_cast(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; } + +} diff --git a/Userland/Applications/HexEditor/HexEditor.h b/Userland/Applications/HexEditor/HexEditor.h index a2397495bcc..af8af9df345 100644 --- a/Userland/Applications/HexEditor/HexEditor.h +++ b/Userland/Applications/HexEditor/HexEditor.h @@ -21,6 +21,8 @@ #include #include +namespace HexEditor { + class HexEditor : public GUI::AbstractScrollableWidget { C_OBJECT(HexEditor) public: @@ -111,3 +113,5 @@ private: void reset_cursor_blink_state(); }; + +} diff --git a/Userland/Applications/HexEditor/HexEditorWidget.cpp b/Userland/Applications/HexEditor/HexEditorWidget.cpp index aaf35ec8fd7..d91fec4fceb 100644 --- a/Userland/Applications/HexEditor/HexEditorWidget.cpp +++ b/Userland/Applications/HexEditor/HexEditorWidget.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -36,15 +35,20 @@ #include #include -REGISTER_WIDGET(HexEditor, HexEditor); +namespace HexEditor { -HexEditorWidget::HexEditorWidget() +ErrorOr> 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 HexEditorWidget::setup() +{ m_toolbar = *find_descendant_of_type_named("toolbar"); m_toolbar_container = *find_descendant_of_type_named("toolbar_container"); - m_editor = *find_descendant_of_type_named("editor"); + m_editor = *find_descendant_of_type_named<::HexEditor::HexEditor>("editor"); m_statusbar = *find_descendant_of_type_named("statusbar"); m_search_results = *find_descendant_of_type_named("search_results"); m_search_results_container = *find_descendant_of_type_named("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()); } } + +} diff --git a/Userland/Applications/HexEditor/HexEditorWindow.gml b/Userland/Applications/HexEditor/HexEditorWidget.gml similarity index 97% rename from Userland/Applications/HexEditor/HexEditorWindow.gml rename to Userland/Applications/HexEditor/HexEditorWidget.gml index 0b7a4e89ee8..9aaedf335ec 100644 --- a/Userland/Applications/HexEditor/HexEditorWindow.gml +++ b/Userland/Applications/HexEditor/HexEditorWidget.gml @@ -1,4 +1,4 @@ -@GUI::Widget { +@HexEditor::HexEditorWidget { name: "main" fill_with_background_color: true layout: @GUI::VerticalBoxLayout { diff --git a/Userland/Applications/HexEditor/HexEditorWidget.h b/Userland/Applications/HexEditor/HexEditorWidget.h index a18289a83b5..500e7592900 100644 --- a/Userland/Applications/HexEditor/HexEditorWidget.h +++ b/Userland/Applications/HexEditor/HexEditorWidget.h @@ -19,18 +19,23 @@ #include #include -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); ErrorOr initialize_menubar(GUI::Window&); bool request_close(); + static ErrorOr> create(); + +protected: + static ErrorOr> try_create(); + private: - HexEditorWidget(); + ErrorOr 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 }; }; + +} diff --git a/Userland/Applications/HexEditor/main.cpp b/Userland/Applications/HexEditor/main.cpp index b23434d3aa8..ade8c15f239 100644 --- a/Userland/Applications/HexEditor/main.cpp +++ b/Userland/Applications/HexEditor/main.cpp @@ -37,7 +37,8 @@ ErrorOr 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(); + 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())