mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:07:45 +00:00
HexEditor: Construct user interface from GML
This commit is contained in:
parent
6738a966ec
commit
e5e00bec8f
4 changed files with 75 additions and 28 deletions
|
@ -1,8 +1,11 @@
|
||||||
|
compile_gml(HexEditorWindow.gml HexEditorWindowGML.h hex_editor_window_gml)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
HexEditor.cpp
|
HexEditor.cpp
|
||||||
HexEditorWidget.cpp
|
HexEditorWidget.cpp
|
||||||
FindDialog.cpp
|
FindDialog.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
|
HexEditorWindowGML.h
|
||||||
)
|
)
|
||||||
|
|
||||||
serenity_app(HexEditor ICON app-hex-editor)
|
serenity_app(HexEditor ICON app-hex-editor)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "FindDialog.h"
|
#include "FindDialog.h"
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
|
#include <Applications/HexEditor/HexEditorWindowGML.h>
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
#include <LibGUI/Action.h>
|
#include <LibGUI/Action.h>
|
||||||
#include <LibGUI/BoxLayout.h>
|
#include <LibGUI/BoxLayout.h>
|
||||||
|
@ -21,16 +22,19 @@
|
||||||
#include <LibGUI/TextBox.h>
|
#include <LibGUI/TextBox.h>
|
||||||
#include <LibGUI/TextEditor.h>
|
#include <LibGUI/TextEditor.h>
|
||||||
#include <LibGUI/Toolbar.h>
|
#include <LibGUI/Toolbar.h>
|
||||||
|
#include <LibGUI/ToolbarContainer.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
REGISTER_WIDGET(HexEditor, HexEditor);
|
||||||
|
|
||||||
HexEditorWidget::HexEditorWidget()
|
HexEditorWidget::HexEditorWidget()
|
||||||
{
|
{
|
||||||
set_fill_with_background_color(true);
|
load_from_gml(hex_editor_window_gml);
|
||||||
set_layout<GUI::VerticalBoxLayout>();
|
m_toolbar = *find_descendant_of_type_named<GUI::Toolbar>("toolbar");
|
||||||
layout()->set_spacing(2);
|
m_toolbar_container = *find_descendant_of_type_named<GUI::ToolbarContainer>("toolbar_container");
|
||||||
|
m_editor = *find_descendant_of_type_named<HexEditor>("editor");
|
||||||
m_editor = add<HexEditor>();
|
m_statusbar = *find_descendant_of_type_named<GUI::Statusbar>("statusbar");
|
||||||
|
|
||||||
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::EditMode edit_mode, int selection_start, int selection_end) {
|
||||||
m_statusbar->set_text(0, String::formatted("Offset: {:#08X}", position));
|
m_statusbar->set_text(0, String::formatted("Offset: {:#08X}", position));
|
||||||
|
@ -47,8 +51,6 @@ HexEditorWidget::HexEditorWidget()
|
||||||
update_title();
|
update_title();
|
||||||
};
|
};
|
||||||
|
|
||||||
m_statusbar = add<GUI::Statusbar>(5);
|
|
||||||
|
|
||||||
m_new_action = GUI::Action::create("New", { Mod_Ctrl, Key_N }, Gfx::Bitmap::load_from_file("/res/icons/16x16/new.png"), [this](const GUI::Action&) {
|
m_new_action = GUI::Action::create("New", { Mod_Ctrl, Key_N }, Gfx::Bitmap::load_from_file("/res/icons/16x16/new.png"), [this](const GUI::Action&) {
|
||||||
if (m_document_dirty) {
|
if (m_document_dirty) {
|
||||||
if (GUI::MessageBox::show(window(), "Save changes to current file first?", "Warning", GUI::MessageBox::Type::Warning, GUI::MessageBox::InputType::OKCancel) != GUI::Dialog::ExecResult::ExecOK)
|
if (GUI::MessageBox::show(window(), "Save changes to current file first?", "Warning", GUI::MessageBox::Type::Warning, GUI::MessageBox::InputType::OKCancel) != GUI::Dialog::ExecResult::ExecOK)
|
||||||
|
@ -108,6 +110,37 @@ HexEditorWidget::HexEditorWidget()
|
||||||
dbgln("Wrote document to {}", save_path.value());
|
dbgln("Wrote document to {}", save_path.value());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m_find_action = GUI::Action::create("&Find", { Mod_Ctrl, Key_F }, Gfx::Bitmap::load_from_file("/res/icons/16x16/find.png"), [&](const GUI::Action&) {
|
||||||
|
auto old_buffer = m_search_buffer;
|
||||||
|
if (FindDialog::show(window(), m_search_text, m_search_buffer) == GUI::InputBox::ExecOK) {
|
||||||
|
|
||||||
|
bool same_buffers = false;
|
||||||
|
if (old_buffer.size() == m_search_buffer.size()) {
|
||||||
|
if (memcmp(old_buffer.data(), m_search_buffer.data(), old_buffer.size()) == 0)
|
||||||
|
same_buffers = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = m_editor->find_and_highlight(m_search_buffer, same_buffers ? last_found_index() : 0);
|
||||||
|
|
||||||
|
if (result == -1) {
|
||||||
|
GUI::MessageBox::show(window(), String::formatted("Pattern \"{}\" not found in this file", m_search_text), "Not found", GUI::MessageBox::Type::Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_editor->update();
|
||||||
|
m_last_found_index = result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
m_layout_toolbar_action = GUI::Action::create_checkable("&Toolbar", [&](auto& action) {
|
||||||
|
m_toolbar_container->set_visible(action.is_checked());
|
||||||
|
});
|
||||||
|
|
||||||
|
m_toolbar->add_action(*m_new_action);
|
||||||
|
m_toolbar->add_action(*m_open_action);
|
||||||
|
m_toolbar->add_action(*m_save_action);
|
||||||
|
m_toolbar->add_separator();
|
||||||
|
m_toolbar->add_action(*m_find_action);
|
||||||
|
|
||||||
m_editor->set_focus(true);
|
m_editor->set_focus(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,27 +205,7 @@ void HexEditorWidget::initialize_menubar(GUI::Menubar& menubar)
|
||||||
m_editor->copy_selected_hex_to_clipboard_as_c_code();
|
m_editor->copy_selected_hex_to_clipboard_as_c_code();
|
||||||
}));
|
}));
|
||||||
edit_menu.add_separator();
|
edit_menu.add_separator();
|
||||||
edit_menu.add_action(GUI::Action::create("&Find", { Mod_Ctrl, Key_F }, Gfx::Bitmap::load_from_file("/res/icons/16x16/find.png"), [&](const GUI::Action&) {
|
edit_menu.add_action(*m_find_action);
|
||||||
auto old_buffer = m_search_buffer;
|
|
||||||
if (FindDialog::show(window(), m_search_text, m_search_buffer) == GUI::InputBox::ExecOK) {
|
|
||||||
|
|
||||||
bool same_buffers = false;
|
|
||||||
if (old_buffer.size() == m_search_buffer.size()) {
|
|
||||||
if (memcmp(old_buffer.data(), m_search_buffer.data(), old_buffer.size()) == 0)
|
|
||||||
same_buffers = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = m_editor->find_and_highlight(m_search_buffer, same_buffers ? last_found_index() : 0);
|
|
||||||
|
|
||||||
if (result == -1) {
|
|
||||||
GUI::MessageBox::show(window(), String::formatted("Pattern \"{}\" not found in this file", m_search_text), "Not found", GUI::MessageBox::Type::Warning);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_editor->update();
|
|
||||||
m_last_found_index = result;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
edit_menu.add_action(GUI::Action::create("Find &Next", { Mod_None, Key_F3 }, Gfx::Bitmap::load_from_file("/res/icons/16x16/find-next.png"), [&](const GUI::Action&) {
|
edit_menu.add_action(GUI::Action::create("Find &Next", { Mod_None, Key_F3 }, Gfx::Bitmap::load_from_file("/res/icons/16x16/find-next.png"), [&](const GUI::Action&) {
|
||||||
if (m_search_text.is_empty() || m_search_buffer.is_empty()) {
|
if (m_search_text.is_empty() || m_search_buffer.is_empty()) {
|
||||||
GUI::MessageBox::show(window(), "Nothing to search for", "Not found", GUI::MessageBox::Type::Warning);
|
GUI::MessageBox::show(window(), "Nothing to search for", "Not found", GUI::MessageBox::Type::Warning);
|
||||||
|
@ -209,6 +222,8 @@ void HexEditorWidget::initialize_menubar(GUI::Menubar& menubar)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
auto& view_menu = menubar.add_menu("&View");
|
auto& view_menu = menubar.add_menu("&View");
|
||||||
|
view_menu.add_action(*m_layout_toolbar_action);
|
||||||
|
m_layout_toolbar_action->set_checked(true);
|
||||||
m_bytes_per_row_actions.set_exclusive(true);
|
m_bytes_per_row_actions.set_exclusive(true);
|
||||||
auto& bytes_per_row_menu = view_menu.add_submenu("Bytes per &Row");
|
auto& bytes_per_row_menu = view_menu.add_submenu("Bytes per &Row");
|
||||||
for (int i = 8; i <= 32; i += 8) {
|
for (int i = 8; i <= 32; i += 8) {
|
||||||
|
|
|
@ -44,12 +44,16 @@ private:
|
||||||
RefPtr<GUI::Action> m_open_action;
|
RefPtr<GUI::Action> m_open_action;
|
||||||
RefPtr<GUI::Action> m_save_action;
|
RefPtr<GUI::Action> m_save_action;
|
||||||
RefPtr<GUI::Action> m_save_as_action;
|
RefPtr<GUI::Action> m_save_as_action;
|
||||||
|
RefPtr<GUI::Action> m_find_action;
|
||||||
RefPtr<GUI::Action> m_goto_decimal_offset_action;
|
RefPtr<GUI::Action> m_goto_decimal_offset_action;
|
||||||
RefPtr<GUI::Action> m_goto_hex_offset_action;
|
RefPtr<GUI::Action> m_goto_hex_offset_action;
|
||||||
|
RefPtr<GUI::Action> m_layout_toolbar_action;
|
||||||
|
|
||||||
GUI::ActionGroup m_bytes_per_row_actions;
|
GUI::ActionGroup m_bytes_per_row_actions;
|
||||||
|
|
||||||
RefPtr<GUI::Statusbar> m_statusbar;
|
RefPtr<GUI::Statusbar> m_statusbar;
|
||||||
|
RefPtr<GUI::Toolbar> m_toolbar;
|
||||||
|
RefPtr<GUI::ToolbarContainer> m_toolbar_container;
|
||||||
|
|
||||||
bool m_document_dirty { false };
|
bool m_document_dirty { false };
|
||||||
};
|
};
|
||||||
|
|
25
Userland/Applications/HexEditor/HexEditorWindow.gml
Normal file
25
Userland/Applications/HexEditor/HexEditorWindow.gml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
@GUI::Widget {
|
||||||
|
name: "main"
|
||||||
|
fill_with_background_color: true
|
||||||
|
|
||||||
|
layout: @GUI::VerticalBoxLayout {
|
||||||
|
spacing: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::ToolbarContainer {
|
||||||
|
name: "toolbar_container"
|
||||||
|
|
||||||
|
@GUI::Toolbar {
|
||||||
|
name: "toolbar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@HexEditor::HexEditor {
|
||||||
|
name: "editor"
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Statusbar {
|
||||||
|
name: "statusbar"
|
||||||
|
label_count: 5
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue