LibWebView+UI: Add an option to toggle a menu's visibility
This requires setting up an observer interface akin to menu actions.
This commit is contained in:
parent
a1b545e179
commit
11d80c122e
4 changed files with 98 additions and 0 deletions
|
|
@ -134,4 +134,28 @@ void Menu::add_action(NonnullRefPtr<Action> action)
|
|||
m_items.append(move(action));
|
||||
}
|
||||
|
||||
void Menu::set_visible(bool visible)
|
||||
{
|
||||
if (m_visible == visible)
|
||||
return;
|
||||
m_visible = visible;
|
||||
|
||||
for (auto& observer : m_observers)
|
||||
observer->on_visible_state_changed(*this);
|
||||
}
|
||||
|
||||
void Menu::add_observer(NonnullOwnPtr<Observer> observer)
|
||||
{
|
||||
observer->on_visible_state_changed(*this);
|
||||
|
||||
m_observers.append(move(observer));
|
||||
}
|
||||
|
||||
void Menu::remove_observer(Observer const& observer)
|
||||
{
|
||||
m_observers.remove_first_matching([&](auto const& candidate) {
|
||||
return candidate.ptr() == &observer;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,6 +224,9 @@ public:
|
|||
void set_render_group_icon(bool render_group_icon) { m_render_group_icon = render_group_icon; }
|
||||
bool render_group_icon() const { return m_render_group_icon; }
|
||||
|
||||
bool visible() const { return m_visible; }
|
||||
void set_visible(bool);
|
||||
|
||||
template<typename Callback>
|
||||
void for_each_action(Callback const& callback)
|
||||
{
|
||||
|
|
@ -235,6 +238,15 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
struct Observer {
|
||||
virtual ~Observer() = default;
|
||||
|
||||
virtual void on_visible_state_changed(Menu&) { }
|
||||
};
|
||||
|
||||
void add_observer(NonnullOwnPtr<Observer>);
|
||||
void remove_observer(Observer const& observer);
|
||||
|
||||
Function<void(Gfx::IntPoint)> on_activation;
|
||||
|
||||
private:
|
||||
|
|
@ -247,9 +259,11 @@ private:
|
|||
Vector<MenuItem> m_items;
|
||||
|
||||
HashMap<StringView, String> m_properties;
|
||||
Vector<NonnullOwnPtr<Observer>, 1> m_observers;
|
||||
|
||||
bool m_is_group { false };
|
||||
bool m_render_group_icon { false };
|
||||
bool m_visible { true };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,6 +187,27 @@ private:
|
|||
__weak id m_control { nil };
|
||||
};
|
||||
|
||||
class MenuObserver final : public WebView::Menu::Observer {
|
||||
public:
|
||||
static NonnullOwnPtr<MenuObserver> create(NSMenuItem* item)
|
||||
{
|
||||
return adopt_own(*new MenuObserver(item));
|
||||
}
|
||||
|
||||
virtual void on_visible_state_changed(WebView::Menu& menu) override
|
||||
{
|
||||
[m_item setHidden:!menu.visible()];
|
||||
}
|
||||
|
||||
private:
|
||||
explicit MenuObserver(NSMenuItem* item)
|
||||
: m_item(item)
|
||||
{
|
||||
}
|
||||
|
||||
__weak NSMenuItem* m_item { nil };
|
||||
};
|
||||
|
||||
static void initialize_native_icon(WebView::Action& action, id control)
|
||||
{
|
||||
static constexpr CGFloat const MENU_ICON_SIZE = 16;
|
||||
|
|
@ -357,6 +378,21 @@ static void initialize_native_control(WebView::Action& action, id control)
|
|||
action.add_observer(move(observer));
|
||||
}
|
||||
|
||||
static void initialize_native_menu(WebView::Menu& menu, NSMenuItem* item)
|
||||
{
|
||||
auto observer = MenuObserver::create(item);
|
||||
|
||||
auto* guard = [[DeallocGuard alloc] init:[menu = menu.make_weak_ptr(), observer = observer.ptr()]() {
|
||||
if (menu)
|
||||
menu->remove_observer(*observer);
|
||||
}];
|
||||
|
||||
static char guard_key = 0;
|
||||
objc_setAssociatedObject(item, &guard_key, guard, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
|
||||
menu.add_observer(move(observer));
|
||||
}
|
||||
|
||||
static void add_items_to_menu(NSMenu* nsmenu, WebView::Menu& menu)
|
||||
{
|
||||
for (auto& menu_item : menu.items()) {
|
||||
|
|
@ -421,6 +457,7 @@ NSMenuItem* create_application_menu_item(WebView::Menu& menu)
|
|||
action:nil
|
||||
keyEquivalent:@""];
|
||||
[item setSubmenu:create_application_menu(menu)];
|
||||
initialize_native_menu(menu, item);
|
||||
|
||||
if (menu.render_group_icon())
|
||||
set_control_image(item, @"folder");
|
||||
|
|
|
|||
|
|
@ -97,6 +97,28 @@ private:
|
|||
IncludeActionIcon m_include_action_icon { IncludeActionIcon::Yes };
|
||||
};
|
||||
|
||||
class MenuObserver final : public WebView::Menu::Observer {
|
||||
public:
|
||||
static NonnullOwnPtr<MenuObserver> create(QMenu& qmenu)
|
||||
{
|
||||
return adopt_own(*new MenuObserver(qmenu));
|
||||
}
|
||||
|
||||
virtual void on_visible_state_changed(WebView::Menu& menu) override
|
||||
{
|
||||
if (m_menu && m_menu->menuAction())
|
||||
m_menu->menuAction()->setVisible(menu.visible());
|
||||
}
|
||||
|
||||
private:
|
||||
explicit MenuObserver(QMenu& qmenu)
|
||||
: m_menu(&qmenu)
|
||||
{
|
||||
}
|
||||
|
||||
QPointer<QMenu> m_menu;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static void add_properties(QObject& object, T& menu_or_action)
|
||||
{
|
||||
|
|
@ -224,6 +246,7 @@ static void initialize_native_control(WebView::Action& action, QAction& qaction,
|
|||
|
||||
static void add_items_to_menu(QMenu& qmenu, QWidget& parent, WebView::Menu& menu)
|
||||
{
|
||||
menu.add_observer(MenuObserver::create(qmenu));
|
||||
add_properties(qmenu, menu);
|
||||
|
||||
for (auto& menu_item : menu.items()) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue