diff --git a/Ladybird/AppKit/UI/Inspector.mm b/Ladybird/AppKit/UI/Inspector.mm index 6d843ab771a..acaf7943a11 100644 --- a/Ladybird/AppKit/UI/Inspector.mm +++ b/Ladybird/AppKit/UI/Inspector.mm @@ -176,6 +176,16 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; m_inspector_client->context_menu_screenshot_dom_node(); } +- (void)createChildElement:(id)sender +{ + m_inspector_client->context_menu_create_child_element(); +} + +- (void)createChildTextNode:(id)sender +{ + m_inspector_client->context_menu_create_child_text_node(); +} + - (void)deleteDOMNode:(id)sender { m_inspector_client->context_menu_remove_dom_node(); @@ -198,6 +208,24 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; #pragma mark - Properties ++ (NSMenuItem*)make_create_child_menu +{ + auto* create_child_menu = [[NSMenu alloc] init]; + [create_child_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Create child element" + action:@selector(createChildElement:) + keyEquivalent:@""]]; + [create_child_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Create child text node" + action:@selector(createChildTextNode:) + keyEquivalent:@""]]; + + auto* create_child_menu_item = [[NSMenuItem alloc] initWithTitle:@"Create child" + action:nil + keyEquivalent:@""]; + [create_child_menu_item setSubmenu:create_child_menu]; + + return create_child_menu_item; +} + - (NSMenu*)dom_node_text_context_menu { if (!_dom_node_text_context_menu) { @@ -236,6 +264,7 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; [_dom_node_tag_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Add attribute" action:@selector(addDOMAttribute:) keyEquivalent:@""]]; + [_dom_node_tag_context_menu addItem:[Inspector make_create_child_menu]]; [_dom_node_tag_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Delete node" action:@selector(deleteDOMNode:) keyEquivalent:@""]]; @@ -281,6 +310,7 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; [_dom_node_attribute_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Add attribute" action:@selector(addDOMAttribute:) keyEquivalent:@""]]; + [_dom_node_attribute_context_menu addItem:[Inspector make_create_child_menu]]; [_dom_node_attribute_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Delete node" action:@selector(deleteDOMNode:) keyEquivalent:@""]]; diff --git a/Ladybird/Qt/InspectorWidget.cpp b/Ladybird/Qt/InspectorWidget.cpp index a7762f7b580..9ce350821f2 100644 --- a/Ladybird/Qt/InspectorWidget.cpp +++ b/Ladybird/Qt/InspectorWidget.cpp @@ -36,6 +36,12 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view) m_screenshot_node_action = new QAction("Take node &screenshot", this); connect(m_screenshot_node_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_screenshot_dom_node(); }); + m_create_child_element_action = new QAction("Create child &element", this); + connect(m_create_child_element_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_create_child_element(); }); + + m_create_child_text_node_action = new QAction("Create child &text node", this); + connect(m_create_child_text_node_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_create_child_text_node(); }); + m_delete_node_action = new QAction("&Delete node", this); connect(m_delete_node_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_remove_dom_node(); }); @@ -54,10 +60,15 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view) m_dom_node_text_context_menu->addSeparator(); m_dom_node_text_context_menu->addAction(m_delete_node_action); + auto* create_child_menu = new QMenu("Create child", this); + create_child_menu->addAction(m_create_child_element_action); + create_child_menu->addAction(m_create_child_text_node_action); + m_dom_node_tag_context_menu = new QMenu("DOM tag context menu", this); m_dom_node_tag_context_menu->addAction(m_edit_node_action); m_dom_node_tag_context_menu->addSeparator(); m_dom_node_tag_context_menu->addAction(m_add_attribute_action); + m_dom_node_tag_context_menu->addMenu(create_child_menu); m_dom_node_tag_context_menu->addAction(m_delete_node_action); m_dom_node_tag_context_menu->addSeparator(); m_dom_node_tag_context_menu->addAction(m_copy_node_action); @@ -69,6 +80,7 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view) m_dom_node_attribute_context_menu->addAction(m_remove_attribute_action); m_dom_node_attribute_context_menu->addSeparator(); m_dom_node_attribute_context_menu->addAction(m_add_attribute_action); + m_dom_node_attribute_context_menu->addMenu(create_child_menu); m_dom_node_attribute_context_menu->addAction(m_delete_node_action); m_dom_node_attribute_context_menu->addSeparator(); m_dom_node_attribute_context_menu->addAction(m_copy_node_action); diff --git a/Ladybird/Qt/InspectorWidget.h b/Ladybird/Qt/InspectorWidget.h index 2c9289b40ab..25646bfd37d 100644 --- a/Ladybird/Qt/InspectorWidget.h +++ b/Ladybird/Qt/InspectorWidget.h @@ -46,6 +46,8 @@ private: QAction* m_edit_node_action { nullptr }; QAction* m_copy_node_action { nullptr }; QAction* m_screenshot_node_action { nullptr }; + QAction* m_create_child_element_action { nullptr }; + QAction* m_create_child_text_node_action { nullptr }; QAction* m_delete_node_action { nullptr }; QAction* m_add_attribute_action { nullptr }; QAction* m_remove_attribute_action { nullptr }; diff --git a/Userland/Applications/Browser/InspectorWidget.cpp b/Userland/Applications/Browser/InspectorWidget.cpp index 1252d860e53..f19d6393fed 100644 --- a/Userland/Applications/Browser/InspectorWidget.cpp +++ b/Userland/Applications/Browser/InspectorWidget.cpp @@ -32,11 +32,19 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view) m_edit_node_action = GUI::Action::create("&Edit node"sv, [this](auto&) { m_inspector_client->context_menu_edit_dom_node(); }); m_copy_node_action = GUI::Action::create("&Copy HTML"sv, [this](auto&) { m_inspector_client->context_menu_copy_dom_node(); }); m_screenshot_node_action = GUI::Action::create("Take node &screenshot"sv, [this](auto&) { m_inspector_client->context_menu_screenshot_dom_node(); }); + m_create_child_element_action = GUI::Action::create("Create child &element"sv, [this](auto&) { m_inspector_client->context_menu_create_child_element(); }); + m_create_child_text_node_action = GUI::Action::create("Create child &text node"sv, [this](auto&) { m_inspector_client->context_menu_create_child_text_node(); }); m_delete_node_action = GUI::Action::create("&Delete node"sv, [this](auto&) { m_inspector_client->context_menu_remove_dom_node(); }); m_add_attribute_action = GUI::Action::create("&Add attribute"sv, [this](auto&) { m_inspector_client->context_menu_add_dom_node_attribute(); }); m_remove_attribute_action = GUI::Action::create("&Remove attribute"sv, [this](auto&) { m_inspector_client->context_menu_remove_dom_node_attribute(); }); m_copy_attribute_value_action = GUI::Action::create("Copy attribute &value"sv, [this](auto&) { m_inspector_client->context_menu_copy_dom_node_attribute_value(); }); + auto add_create_child_menu = [&](auto& menu) { + auto create_child_menu = menu.add_submenu("Create child"_string); + create_child_menu->add_action(*m_create_child_element_action); + create_child_menu->add_action(*m_create_child_text_node_action); + }; + m_dom_node_text_context_menu = GUI::Menu::construct(); m_dom_node_text_context_menu->add_action(*m_edit_node_action); m_dom_node_text_context_menu->add_action(*m_copy_node_action); @@ -47,6 +55,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view) m_dom_node_tag_context_menu->add_action(*m_edit_node_action); m_dom_node_tag_context_menu->add_separator(); m_dom_node_tag_context_menu->add_action(*m_add_attribute_action); + add_create_child_menu(*m_dom_node_tag_context_menu); m_dom_node_tag_context_menu->add_action(*m_delete_node_action); m_dom_node_tag_context_menu->add_separator(); m_dom_node_tag_context_menu->add_action(*m_copy_node_action); @@ -58,6 +67,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view) m_dom_node_attribute_context_menu->add_action(*m_remove_attribute_action); m_dom_node_attribute_context_menu->add_separator(); m_dom_node_attribute_context_menu->add_action(*m_add_attribute_action); + add_create_child_menu(*m_dom_node_attribute_context_menu); m_dom_node_attribute_context_menu->add_action(*m_delete_node_action); m_dom_node_attribute_context_menu->add_separator(); m_dom_node_attribute_context_menu->add_action(*m_copy_node_action); diff --git a/Userland/Applications/Browser/InspectorWidget.h b/Userland/Applications/Browser/InspectorWidget.h index 41b4c5acdf4..b3718d8816c 100644 --- a/Userland/Applications/Browser/InspectorWidget.h +++ b/Userland/Applications/Browser/InspectorWidget.h @@ -42,6 +42,8 @@ private: RefPtr m_edit_node_action; RefPtr m_copy_node_action; RefPtr m_screenshot_node_action; + RefPtr m_create_child_element_action; + RefPtr m_create_child_text_node_action; RefPtr m_delete_node_action; RefPtr m_add_attribute_action; RefPtr m_remove_attribute_action; diff --git a/Userland/Libraries/LibWebView/InspectorClient.cpp b/Userland/Libraries/LibWebView/InspectorClient.cpp index f15e561ff87..060b9443169 100644 --- a/Userland/Libraries/LibWebView/InspectorClient.cpp +++ b/Userland/Libraries/LibWebView/InspectorClient.cpp @@ -254,6 +254,26 @@ void InspectorClient::context_menu_screenshot_dom_node() m_context_menu_data.clear(); } +void InspectorClient::context_menu_create_child_element() +{ + VERIFY(m_context_menu_data.has_value()); + + m_pending_selection = m_content_web_view.create_child_element(m_context_menu_data->dom_node_id); + inspect(); + + m_context_menu_data.clear(); +} + +void InspectorClient::context_menu_create_child_text_node() +{ + VERIFY(m_context_menu_data.has_value()); + + m_pending_selection = m_content_web_view.create_child_text_node(m_context_menu_data->dom_node_id); + inspect(); + + m_context_menu_data.clear(); +} + void InspectorClient::context_menu_remove_dom_node() { VERIFY(m_context_menu_data.has_value()); diff --git a/Userland/Libraries/LibWebView/InspectorClient.h b/Userland/Libraries/LibWebView/InspectorClient.h index cdc1d3e5374..a1d998f17eb 100644 --- a/Userland/Libraries/LibWebView/InspectorClient.h +++ b/Userland/Libraries/LibWebView/InspectorClient.h @@ -29,6 +29,8 @@ public: void context_menu_edit_dom_node(); void context_menu_copy_dom_node(); void context_menu_screenshot_dom_node(); + void context_menu_create_child_element(); + void context_menu_create_child_text_node(); void context_menu_remove_dom_node(); void context_menu_add_dom_node_attribute(); void context_menu_remove_dom_node_attribute();