mirror of
https://github.com/RGBCube/serenity
synced 2025-07-28 23:37:35 +00:00
Ladybird+LibWeb: Add basic select element support
This commit is contained in:
parent
b439431488
commit
466153e680
28 changed files with 641 additions and 4 deletions
|
@ -36,7 +36,7 @@
|
|||
|
||||
@end
|
||||
|
||||
@interface LadybirdWebView : NSClipView
|
||||
@interface LadybirdWebView : NSClipView <NSMenuDelegate>
|
||||
|
||||
- (instancetype)init:(id<LadybirdWebViewObserver>)observer;
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ struct HideCursor {
|
|||
@property (nonatomic, strong) NSMenu* image_context_menu;
|
||||
@property (nonatomic, strong) NSMenu* audio_context_menu;
|
||||
@property (nonatomic, strong) NSMenu* video_context_menu;
|
||||
@property (nonatomic, strong) NSMenu* select_dropdown;
|
||||
@property (nonatomic, strong) NSTextField* status_label;
|
||||
@property (nonatomic, strong) NSAlert* dialog;
|
||||
|
||||
|
@ -608,6 +609,21 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
|
|||
[panel makeKeyAndOrderFront:nil];
|
||||
};
|
||||
|
||||
self.select_dropdown = [[NSMenu alloc] initWithTitle:@"Select Dropdown"];
|
||||
[self.select_dropdown setDelegate:self];
|
||||
|
||||
m_web_view_bridge->on_request_select_dropdown = [self](Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> items) {
|
||||
[self.select_dropdown removeAllItems];
|
||||
self.select_dropdown.minimumWidth = minimum_width;
|
||||
for (auto const& item : items) {
|
||||
[self selectDropdownAdd:self.select_dropdown
|
||||
item:item];
|
||||
}
|
||||
|
||||
auto* event = Ladybird::create_context_menu_mouse_event(self, content_position);
|
||||
[NSMenu popUpContextMenu:self.select_dropdown withEvent:event forView:self];
|
||||
};
|
||||
|
||||
m_web_view_bridge->on_get_all_cookies = [](auto const& url) {
|
||||
auto* delegate = (ApplicationDelegate*)[NSApp delegate];
|
||||
return [delegate cookieJar].get_all_cookies(url);
|
||||
|
@ -703,6 +719,48 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
|
|||
};
|
||||
}
|
||||
|
||||
- (void)selectDropdownAdd:(NSMenu*)menu item:(Web::HTML::SelectItem const&)item
|
||||
{
|
||||
if (item.type == Web::HTML::SelectItem::Type::OptionGroup) {
|
||||
NSMenuItem* subtitle = [[NSMenuItem alloc]
|
||||
initWithTitle:Ladybird::string_to_ns_string(item.label.value_or(""_string))
|
||||
action:nil
|
||||
keyEquivalent:@""];
|
||||
subtitle.enabled = false;
|
||||
[menu addItem:subtitle];
|
||||
|
||||
for (auto const& item : *item.items) {
|
||||
[self selectDropdownAdd:menu
|
||||
item:item];
|
||||
}
|
||||
}
|
||||
if (item.type == Web::HTML::SelectItem::Type::Option) {
|
||||
NSMenuItem* menuItem = [[NSMenuItem alloc]
|
||||
initWithTitle:Ladybird::string_to_ns_string(item.label.value_or(""_string))
|
||||
action:@selector(selectDropdownAction:)
|
||||
keyEquivalent:@""];
|
||||
[menuItem setRepresentedObject:Ladybird::string_to_ns_string(item.value.value_or(""_string))];
|
||||
[menuItem setEnabled:YES];
|
||||
[menuItem setState:item.selected ? NSControlStateValueOn : NSControlStateValueOff];
|
||||
[menu addItem:menuItem];
|
||||
}
|
||||
if (item.type == Web::HTML::SelectItem::Type::Separator) {
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)selectDropdownAction:(NSMenuItem*)menuItem
|
||||
{
|
||||
auto value = Ladybird::ns_string_to_string([menuItem representedObject]);
|
||||
m_web_view_bridge->select_dropdown_closed(value);
|
||||
}
|
||||
|
||||
- (void)menuDidClose:(NSMenu*)menu
|
||||
{
|
||||
if (!menu.highlightedItem)
|
||||
m_web_view_bridge->select_dropdown_closed({});
|
||||
}
|
||||
|
||||
- (void)colorPickerClosed:(NSNotification*)notification
|
||||
{
|
||||
m_web_view_bridge->color_picker_closed(Ladybird::ns_color_to_gfx_color([[NSColorPanel sharedColorPanel] color]));
|
||||
|
|
|
@ -226,6 +226,22 @@ Tab::Tab(BrowserWindow* window, WebContentOptions const& web_content_options, St
|
|||
m_dialog = nullptr;
|
||||
};
|
||||
|
||||
m_select_dropdown = new QMenu("Select Dropdown", this);
|
||||
QObject::connect(m_select_dropdown, &QMenu::aboutToHide, this, [this]() {
|
||||
if (!m_select_dropdown->activeAction())
|
||||
view().select_dropdown_closed({});
|
||||
});
|
||||
|
||||
view().on_request_select_dropdown = [this](Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> items) {
|
||||
m_select_dropdown->clear();
|
||||
m_select_dropdown->setMinimumWidth(minimum_width);
|
||||
for (auto const& item : items) {
|
||||
select_dropdown_add_item(m_select_dropdown, item);
|
||||
}
|
||||
|
||||
m_select_dropdown->exec(mapToGlobal(QPoint(content_position.x(), content_position.y())));
|
||||
};
|
||||
|
||||
QObject::connect(focus_location_editor_action, &QAction::triggered, this, &Tab::focus_location_editor);
|
||||
|
||||
view().on_received_source = [this](auto const& url, auto const& source) {
|
||||
|
@ -569,6 +585,37 @@ Tab::~Tab()
|
|||
close_sub_widgets();
|
||||
}
|
||||
|
||||
void Tab::select_dropdown_add_item(QMenu* menu, Web::HTML::SelectItem const& item)
|
||||
{
|
||||
if (item.type == Web::HTML::SelectItem::Type::OptionGroup) {
|
||||
QAction* subtitle = new QAction(qstring_from_ak_string(item.label.value_or(""_string)), this);
|
||||
subtitle->setDisabled(true);
|
||||
menu->addAction(subtitle);
|
||||
|
||||
for (auto const& item : *item.items) {
|
||||
select_dropdown_add_item(menu, item);
|
||||
}
|
||||
}
|
||||
if (item.type == Web::HTML::SelectItem::Type::Option) {
|
||||
QAction* action = new QAction(qstring_from_ak_string(item.label.value_or(""_string)), this);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(item.selected);
|
||||
action->setData(QVariant(qstring_from_ak_string(item.value.value_or(""_string))));
|
||||
QObject::connect(action, &QAction::triggered, this, &Tab::select_dropdown_action);
|
||||
menu->addAction(action);
|
||||
}
|
||||
if (item.type == Web::HTML::SelectItem::Type::Separator) {
|
||||
menu->addSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
void Tab::select_dropdown_action()
|
||||
{
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
auto value = action->data().value<QString>();
|
||||
view().select_dropdown_closed(ak_string_from_qstring(value));
|
||||
}
|
||||
|
||||
void Tab::update_reset_zoom_button()
|
||||
{
|
||||
auto zoom_level = view().zoom_level();
|
||||
|
|
|
@ -54,12 +54,15 @@ public:
|
|||
public slots:
|
||||
void focus_location_editor();
|
||||
void location_edit_return_pressed();
|
||||
void select_dropdown_action();
|
||||
|
||||
signals:
|
||||
void title_changed(int id, QString);
|
||||
void favicon_changed(int id, QIcon);
|
||||
|
||||
private:
|
||||
void select_dropdown_add_item(QMenu* menu, Web::HTML::SelectItem const& item);
|
||||
|
||||
virtual void resizeEvent(QResizeEvent*) override;
|
||||
virtual bool event(QEvent*) override;
|
||||
|
||||
|
@ -106,6 +109,8 @@ private:
|
|||
QAction* m_media_context_menu_loop_action { nullptr };
|
||||
URL m_media_context_menu_url;
|
||||
|
||||
QMenu* m_select_dropdown { nullptr };
|
||||
|
||||
int tab_index();
|
||||
|
||||
bool m_is_history_navigation { false };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue