mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 06:17:35 +00:00
Ladybird/AppKit: Add an Inspector context menu to edit the DOM
This commit is contained in:
parent
be53596fe6
commit
154d201d41
1 changed files with 154 additions and 0 deletions
|
@ -7,9 +7,11 @@
|
||||||
#include <LibWebView/InspectorClient.h>
|
#include <LibWebView/InspectorClient.h>
|
||||||
#include <LibWebView/ViewImplementation.h>
|
#include <LibWebView/ViewImplementation.h>
|
||||||
|
|
||||||
|
#import <UI/Event.h>
|
||||||
#import <UI/Inspector.h>
|
#import <UI/Inspector.h>
|
||||||
#import <UI/LadybirdWebView.h>
|
#import <UI/LadybirdWebView.h>
|
||||||
#import <UI/Tab.h>
|
#import <UI/Tab.h>
|
||||||
|
#import <Utilities/Conversions.h>
|
||||||
|
|
||||||
#if !__has_feature(objc_arc)
|
#if !__has_feature(objc_arc)
|
||||||
# error "This project requires ARC"
|
# error "This project requires ARC"
|
||||||
|
@ -18,6 +20,9 @@
|
||||||
static constexpr CGFloat const WINDOW_WIDTH = 875;
|
static constexpr CGFloat const WINDOW_WIDTH = 875;
|
||||||
static constexpr CGFloat const WINDOW_HEIGHT = 825;
|
static constexpr CGFloat const WINDOW_HEIGHT = 825;
|
||||||
|
|
||||||
|
static constexpr NSInteger CONTEXT_MENU_EDIT_NODE_TAG = 1;
|
||||||
|
static constexpr NSInteger CONTEXT_MENU_REMOVE_ATTRIBUTE_TAG = 2;
|
||||||
|
|
||||||
@interface Inspector ()
|
@interface Inspector ()
|
||||||
{
|
{
|
||||||
OwnPtr<WebView::InspectorClient> m_inspector_client;
|
OwnPtr<WebView::InspectorClient> m_inspector_client;
|
||||||
|
@ -25,11 +30,18 @@ static constexpr CGFloat const WINDOW_HEIGHT = 825;
|
||||||
|
|
||||||
@property (nonatomic, strong) Tab* tab;
|
@property (nonatomic, strong) Tab* tab;
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSMenu* dom_node_text_context_menu;
|
||||||
|
@property (nonatomic, strong) NSMenu* dom_node_tag_context_menu;
|
||||||
|
@property (nonatomic, strong) NSMenu* dom_node_attribute_context_menu;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation Inspector
|
@implementation Inspector
|
||||||
|
|
||||||
@synthesize tab = _tab;
|
@synthesize tab = _tab;
|
||||||
|
@synthesize dom_node_text_context_menu = _dom_node_text_context_menu;
|
||||||
|
@synthesize dom_node_tag_context_menu = _dom_node_tag_context_menu;
|
||||||
|
@synthesize dom_node_attribute_context_menu = _dom_node_attribute_context_menu;
|
||||||
|
|
||||||
- (instancetype)init:(Tab*)tab
|
- (instancetype)init:(Tab*)tab
|
||||||
{
|
{
|
||||||
|
@ -52,6 +64,51 @@ static constexpr CGFloat const WINDOW_HEIGHT = 825;
|
||||||
[self.web_view setPostsBoundsChangedNotifications:YES];
|
[self.web_view setPostsBoundsChangedNotifications:YES];
|
||||||
|
|
||||||
m_inspector_client = make<WebView::InspectorClient>([[tab web_view] view], [[self web_view] view]);
|
m_inspector_client = make<WebView::InspectorClient>([[tab web_view] view], [[self web_view] view]);
|
||||||
|
__weak Inspector* weak_self = self;
|
||||||
|
|
||||||
|
m_inspector_client->on_requested_dom_node_text_context_menu = [weak_self](auto position) {
|
||||||
|
Inspector* strong_self = weak_self;
|
||||||
|
if (strong_self == nil) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* event = Ladybird::create_context_menu_mouse_event(strong_self.web_view, position);
|
||||||
|
[NSMenu popUpContextMenu:strong_self.dom_node_text_context_menu withEvent:event forView:strong_self.web_view];
|
||||||
|
};
|
||||||
|
|
||||||
|
m_inspector_client->on_requested_dom_node_tag_context_menu = [weak_self](auto position, auto const& tag) {
|
||||||
|
Inspector* strong_self = weak_self;
|
||||||
|
if (strong_self == nil) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto edit_node_text = MUST(String::formatted("Edit \"{}\"", tag));
|
||||||
|
|
||||||
|
auto* edit_node_menu_item = [strong_self.dom_node_tag_context_menu itemWithTag:CONTEXT_MENU_EDIT_NODE_TAG];
|
||||||
|
[edit_node_menu_item setTitle:Ladybird::string_to_ns_string(edit_node_text)];
|
||||||
|
|
||||||
|
auto* event = Ladybird::create_context_menu_mouse_event(strong_self.web_view, position);
|
||||||
|
[NSMenu popUpContextMenu:strong_self.dom_node_tag_context_menu withEvent:event forView:strong_self.web_view];
|
||||||
|
};
|
||||||
|
|
||||||
|
m_inspector_client->on_requested_dom_node_attribute_context_menu = [weak_self](auto position, auto const& attribute) {
|
||||||
|
Inspector* strong_self = weak_self;
|
||||||
|
if (strong_self == nil) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto edit_attribute_text = MUST(String::formatted("Edit attribute \"{}\"", attribute));
|
||||||
|
auto remove_attribute_text = MUST(String::formatted("Remove attribute \"{}\"", attribute));
|
||||||
|
|
||||||
|
auto* edit_node_menu_item = [strong_self.dom_node_attribute_context_menu itemWithTag:CONTEXT_MENU_EDIT_NODE_TAG];
|
||||||
|
[edit_node_menu_item setTitle:Ladybird::string_to_ns_string(edit_attribute_text)];
|
||||||
|
|
||||||
|
auto* remove_attribute_menu_item = [strong_self.dom_node_attribute_context_menu itemWithTag:CONTEXT_MENU_REMOVE_ATTRIBUTE_TAG];
|
||||||
|
[remove_attribute_menu_item setTitle:Ladybird::string_to_ns_string(remove_attribute_text)];
|
||||||
|
|
||||||
|
auto* event = Ladybird::create_context_menu_mouse_event(strong_self.web_view, position);
|
||||||
|
[NSMenu popUpContextMenu:strong_self.dom_node_attribute_context_menu withEvent:event forView:strong_self.web_view];
|
||||||
|
};
|
||||||
|
|
||||||
auto* scroll_view = [[NSScrollView alloc] init];
|
auto* scroll_view = [[NSScrollView alloc] init];
|
||||||
[scroll_view setHasVerticalScroller:YES];
|
[scroll_view setHasVerticalScroller:YES];
|
||||||
|
@ -92,4 +149,101 @@ static constexpr CGFloat const WINDOW_HEIGHT = 825;
|
||||||
m_inspector_client->select_hovered_node();
|
m_inspector_client->select_hovered_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Private methods
|
||||||
|
|
||||||
|
- (void)editDOMNode:(id)sender
|
||||||
|
{
|
||||||
|
m_inspector_client->context_menu_edit_dom_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)deleteDOMNode:(id)sender
|
||||||
|
{
|
||||||
|
m_inspector_client->context_menu_remove_dom_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addDOMAttribute:(id)sender
|
||||||
|
{
|
||||||
|
m_inspector_client->context_menu_add_dom_node_attribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeDOMAttribute:(id)sender
|
||||||
|
{
|
||||||
|
m_inspector_client->context_menu_remove_dom_node_attribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Properties
|
||||||
|
|
||||||
|
- (NSMenu*)dom_node_text_context_menu
|
||||||
|
{
|
||||||
|
if (!_dom_node_text_context_menu) {
|
||||||
|
_dom_node_text_context_menu = [[NSMenu alloc] initWithTitle:@"DOM Text Context Menu"];
|
||||||
|
|
||||||
|
[_dom_node_text_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Edit text"
|
||||||
|
action:@selector(editDOMNode:)
|
||||||
|
keyEquivalent:@""]];
|
||||||
|
|
||||||
|
[_dom_node_text_context_menu addItem:[NSMenuItem separatorItem]];
|
||||||
|
|
||||||
|
[_dom_node_text_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Delete node"
|
||||||
|
action:@selector(deleteDOMNode:)
|
||||||
|
keyEquivalent:@""]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _dom_node_text_context_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMenu*)dom_node_tag_context_menu
|
||||||
|
{
|
||||||
|
if (!_dom_node_tag_context_menu) {
|
||||||
|
_dom_node_tag_context_menu = [[NSMenu alloc] initWithTitle:@"DOM Tag Context Menu"];
|
||||||
|
|
||||||
|
auto* edit_node_menu_item = [[NSMenuItem alloc] initWithTitle:@"Edit tag"
|
||||||
|
action:@selector(editDOMNode:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[edit_node_menu_item setTag:CONTEXT_MENU_EDIT_NODE_TAG];
|
||||||
|
[_dom_node_tag_context_menu addItem:edit_node_menu_item];
|
||||||
|
|
||||||
|
[_dom_node_tag_context_menu addItem:[NSMenuItem separatorItem]];
|
||||||
|
|
||||||
|
[_dom_node_tag_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Add attribute"
|
||||||
|
action:@selector(addDOMAttribute:)
|
||||||
|
keyEquivalent:@""]];
|
||||||
|
[_dom_node_tag_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Delete node"
|
||||||
|
action:@selector(deleteDOMNode:)
|
||||||
|
keyEquivalent:@""]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _dom_node_tag_context_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMenu*)dom_node_attribute_context_menu
|
||||||
|
{
|
||||||
|
if (!_dom_node_attribute_context_menu) {
|
||||||
|
_dom_node_attribute_context_menu = [[NSMenu alloc] initWithTitle:@"DOM Attribute Context Menu"];
|
||||||
|
|
||||||
|
auto* edit_node_menu_item = [[NSMenuItem alloc] initWithTitle:@"Edit attribute"
|
||||||
|
action:@selector(editDOMNode:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[edit_node_menu_item setTag:CONTEXT_MENU_EDIT_NODE_TAG];
|
||||||
|
[_dom_node_attribute_context_menu addItem:edit_node_menu_item];
|
||||||
|
|
||||||
|
auto* remove_attribute_menu_item = [[NSMenuItem alloc] initWithTitle:@"Remove attribute"
|
||||||
|
action:@selector(removeDOMAttribute:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[remove_attribute_menu_item setTag:CONTEXT_MENU_REMOVE_ATTRIBUTE_TAG];
|
||||||
|
[_dom_node_attribute_context_menu addItem:remove_attribute_menu_item];
|
||||||
|
|
||||||
|
[_dom_node_attribute_context_menu addItem:[NSMenuItem separatorItem]];
|
||||||
|
|
||||||
|
[_dom_node_attribute_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Add attribute"
|
||||||
|
action:@selector(addDOMAttribute:)
|
||||||
|
keyEquivalent:@""]];
|
||||||
|
[_dom_node_attribute_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Delete node"
|
||||||
|
action:@selector(deleteDOMNode:)
|
||||||
|
keyEquivalent:@""]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _dom_node_attribute_context_menu;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue