diff options
author | Caolán McNamara <caolanm@redhat.com> | 2020-10-19 09:35:00 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2020-10-20 13:01:27 +0200 |
commit | fb3c3b2861b6e658c260a22cc58c3f69be327b18 (patch) | |
tree | eac276e95bb0e6a2309a061fa12076cacc979f9a /vcl | |
parent | d8e2ad45000a08c5e5b6e028c2c8fcc69c06fd74 (diff) |
add MenuToggleButton for split toggle/menu button
which is uniquely used in the start center
Change-Id: I098e79ce34a9d99f8fb2eccb3dd04fa27e38427b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104534
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/UIConfig_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/inc/salvtables.hxx | 3 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 37 | ||||
-rw-r--r-- | vcl/source/control/menubtn.cxx | 4 | ||||
-rw-r--r-- | vcl/source/window/builder.cxx | 33 | ||||
-rw-r--r-- | vcl/uiconfig/ui/menutogglebutton.ui | 40 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 320 |
7 files changed, 414 insertions, 24 deletions
diff --git a/vcl/UIConfig_vcl.mk b/vcl/UIConfig_vcl.mk index 7941303b69da..a6ba276250a0 100644 --- a/vcl/UIConfig_vcl.mk +++ b/vcl/UIConfig_vcl.mk @@ -16,6 +16,7 @@ $(eval $(call gb_UIConfig_add_uifiles,vcl,\ vcl/uiconfig/ui/editmenu \ vcl/uiconfig/ui/errornocontentdialog \ vcl/uiconfig/ui/errornoprinterdialog \ + vcl/uiconfig/ui/menutogglebutton \ vcl/uiconfig/ui/moreoptionsdialog \ vcl/uiconfig/ui/printdialog \ vcl/uiconfig/ui/printerdevicepage \ diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index a2fb935da53d..5a715b128f87 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -63,6 +63,9 @@ public: virtual std::unique_ptr<weld::MenuButton> weld_menu_button(const OString& id) override; + virtual std::unique_ptr<weld::MenuToggleButton> + weld_menu_toggle_button(const OString& id) override; + virtual std::unique_ptr<weld::LinkButton> weld_link_button(const OString& id) override; virtual std::unique_ptr<weld::ToggleButton> weld_toggle_button(const OString& id) override; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 093d79ce018b..4ebf0bda3b55 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -71,6 +71,7 @@ #include <vcl/virdev.hxx> #include <bitmaps.hlst> #include <calendar.hxx> +#include <vcl/menubtn.hxx> #include <verticaltabctrl.hxx> #include <window.h> #include <wizdlg.hxx> @@ -2669,6 +2670,35 @@ IMPL_LINK_NOARG(SalInstanceMenuButton, ActivateHdl, ::MenuButton*, void) namespace { + +class SalInstanceMenuToggleButton : public SalInstanceMenuButton, public virtual weld::MenuToggleButton +{ +private: + VclPtr<::MenuToggleButton> m_xMenuToggleButton; + +public: + SalInstanceMenuToggleButton(::MenuToggleButton* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : SalInstanceMenuButton(pButton, pBuilder, bTakeOwnership) + , m_xMenuToggleButton(pButton) + { + m_xMenuToggleButton->SetDelayMenu(true); + m_xMenuToggleButton->SetDropDown(PushButtonDropdownStyle::SplitMenuButton); + } + + virtual void set_active(bool active) override + { + disable_notify_events(); + m_xMenuToggleButton->SetActive(active); + enable_notify_events(); + } + + virtual bool get_active() const override { return m_xMenuToggleButton->GetActive(); } +}; + +} + +namespace +{ class SalInstanceLinkButton : public SalInstanceContainer, public virtual weld::LinkButton { private: @@ -6682,6 +6712,13 @@ std::unique_ptr<weld::MenuButton> SalInstanceBuilder::weld_menu_button(const OSt : nullptr; } +std::unique_ptr<weld::MenuToggleButton> SalInstanceBuilder::weld_menu_toggle_button(const OString& id) +{ + MenuToggleButton* pButton = m_xBuilder->get<MenuToggleButton>(id); + return pButton ? std::make_unique<SalInstanceMenuToggleButton>(pButton, this, false) + : nullptr; +} + std::unique_ptr<weld::LinkButton> SalInstanceBuilder::weld_link_button(const OString& id) { FixedHyperlink* pButton = m_xBuilder->get<FixedHyperlink>(id); diff --git a/vcl/source/control/menubtn.cxx b/vcl/source/control/menubtn.cxx index d1488f308c6f..643cf048b84b 100644 --- a/vcl/source/control/menubtn.cxx +++ b/vcl/source/control/menubtn.cxx @@ -280,5 +280,9 @@ void MenuToggleButton::SetActive( bool bSel ) mbIsActive = bSel; } +bool MenuToggleButton::GetActive() const +{ + return mbIsActive; +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx index a3b91e718f49..7072c1f42934 100644 --- a/vcl/source/window/builder.cxx +++ b/vcl/source/window/builder.cxx @@ -886,6 +886,18 @@ namespace return sRet; } + OUString extractWidgetName(VclBuilder::stringmap& rMap) + { + OUString sRet; + VclBuilder::stringmap::iterator aFind = rMap.find("name"); + if (aFind != rMap.end()) + { + sRet = aFind->second; + rMap.erase(aFind); + } + return sRet; + } + OUString extractValuePos(VclBuilder::stringmap& rMap) { OUString sRet("top"); @@ -1324,13 +1336,13 @@ namespace return xWindow; } - VclPtr<Button> extractStockAndBuildMenuToggleButton(vcl::Window *pParent, VclBuilder::stringmap &rMap) + VclPtr<MenuButton> extractStockAndBuildMenuToggleButton(vcl::Window *pParent, VclBuilder::stringmap &rMap) { WinBits nBits = WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER|WB_3DLOOK; nBits |= extractRelief(rMap); - VclPtr<Button> xWindow = VclPtr<MenuToggleButton>::Create(pParent, nBits); + VclPtr<MenuButton> xWindow = VclPtr<MenuToggleButton>::Create(pParent, nBits); if (extractStock(rMap)) { @@ -1826,12 +1838,25 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString & } else if (name == "GtkMenuButton") { - VclPtr<MenuButton> xButton = extractStockAndBuildMenuButton(pParent, rMap); + VclPtr<MenuButton> xButton; + OUString sMenu = extractPopupMenu(rMap); if (!sMenu.isEmpty()) m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu); + + OUString sType = extractWidgetName(rMap); + fprintf(stderr, "special name is %s\n", sType.toUtf8().getStr()); + if (sType.isEmpty()) + { + xButton = extractStockAndBuildMenuButton(pParent, rMap); + xButton->SetAccessibleRole(css::accessibility::AccessibleRole::BUTTON_MENU); + } + else + { + xButton = extractStockAndBuildMenuToggleButton(pParent, rMap); + } + xButton->SetImageAlign(ImageAlign::Left); //default to left - xButton->SetAccessibleRole(css::accessibility::AccessibleRole::BUTTON_MENU); if (!extractDrawIndicator(rMap)) xButton->SetDropDown(PushButtonDropdownStyle::NONE); diff --git a/vcl/uiconfig/ui/menutogglebutton.ui b/vcl/uiconfig/ui/menutogglebutton.ui new file mode 100644 index 000000000000..47a72b10dd7a --- /dev/null +++ b/vcl/uiconfig/ui/menutogglebutton.ui @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.36.0 --> +<interface domain="vcl"> + <requires lib="gtk+" version="3.18"/> + <object class="GtkBox" id="box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <child> + <object class="GtkToggleButton" id="togglebutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_underline">True</property> + <property name="always_show_image">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="menubutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="always_show_image">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <style> + <class name="linked"/> + </style> + </object> +</interface> diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 3e2a7e7c69bd..67dd9751053b 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -6755,6 +6755,7 @@ class GtkInstanceButton : public GtkInstanceContainer, public virtual weld::Butt private: GtkButton* m_pButton; gulong m_nSignalId; + std::unique_ptr<vcl::Font> m_xFont; static void signalClicked(GtkButton*, gpointer widget) { @@ -6794,6 +6795,7 @@ private: return pChild; } +protected: GtkWidget* get_label_widget() { GtkWidget* pChild = gtk_bin_get_child(GTK_BIN(m_pButton)); @@ -6869,10 +6871,18 @@ public: virtual void set_font(const vcl::Font& rFont) override { + m_xFont.reset(new vcl::Font(rFont)); GtkWidget* pChild = get_label_widget(); ::set_font(GTK_LABEL(pChild), rFont); } + virtual vcl::Font get_font() override + { + if (m_xFont) + return *m_xFont; + return GtkInstanceWidget::get_font(); + } + // allow us to block buttons with click handlers making dialogs return a response bool has_click_handler() const { @@ -7039,8 +7049,9 @@ namespace { class GtkInstanceToggleButton : public GtkInstanceButton, public virtual weld::ToggleButton { -private: +protected: GtkToggleButton* m_pToggleButton; +private: gulong m_nSignalId; static void signalToggled(GtkToggleButton*, gpointer widget) @@ -7271,8 +7282,9 @@ GtkPositionType show_menu(GtkWidget* pMenuButton, GtkWindow* pMenu) class GtkInstanceMenuButton : public GtkInstanceToggleButton, public MenuHelper, public virtual weld::MenuButton { -private: +protected: GtkMenuButton* m_pMenuButton; +private: GtkBox* m_pBox; GtkImage* m_pImage; GtkWidget* m_pLabel; @@ -7428,24 +7440,7 @@ public: , m_nSignalId(0) { m_pLabel = gtk_bin_get_child(GTK_BIN(m_pMenuButton)); - //do it "manually" so we can have the dropdown image in GtkMenuButtons shown - //on the right at the same time as this image is shown on the left - g_object_ref(m_pLabel); - gtk_container_remove(GTK_CONTAINER(m_pMenuButton), m_pLabel); - - gint nImageSpacing(2); - GtkStyleContext *pContext = gtk_widget_get_style_context(GTK_WIDGET(m_pMenuButton)); - gtk_style_context_get_style(pContext, "image-spacing", &nImageSpacing, nullptr); - m_pBox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, nImageSpacing)); - - gtk_box_pack_start(m_pBox, m_pLabel, true, true, 0); - g_object_unref(m_pLabel); - - if (gtk_toggle_button_get_mode(GTK_TOGGLE_BUTTON(m_pMenuButton))) - gtk_box_pack_end(m_pBox, gtk_image_new_from_icon_name("pan-down-symbolic", GTK_ICON_SIZE_BUTTON), false, false, 0); - - gtk_container_add(GTK_CONTAINER(m_pMenuButton), GTK_WIDGET(m_pBox)); - gtk_widget_show_all(GTK_WIDGET(m_pBox)); + m_pBox = formatMenuButton(m_pLabel); } virtual void set_size_request(int nWidth, int nHeight) override @@ -7600,6 +7595,31 @@ public: void set_menu(weld::Menu* pMenu); + static GtkBox* formatMenuButton(GtkWidget* pLabel) + { + // format the GtkMenuButton "manually" so we can have the dropdown image in GtkMenuButtons shown + // on the right at the same time as an image is shown on the left + g_object_ref(pLabel); + GtkWidget* pContainer = gtk_widget_get_parent(pLabel); + gtk_container_remove(GTK_CONTAINER(pContainer), pLabel); + + gint nImageSpacing(2); + GtkStyleContext *pContext = gtk_widget_get_style_context(pContainer); + gtk_style_context_get_style(pContext, "image-spacing", &nImageSpacing, nullptr); + GtkBox* pBox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, nImageSpacing)); + + gtk_box_pack_start(pBox, pLabel, true, true, 0); + g_object_unref(pLabel); + + if (gtk_toggle_button_get_mode(GTK_TOGGLE_BUTTON(pContainer))) + gtk_box_pack_end(pBox, gtk_image_new_from_icon_name("pan-down-symbolic", GTK_ICON_SIZE_BUTTON), false, false, 0); + + gtk_container_add(GTK_CONTAINER(pContainer), GTK_WIDGET(pBox)); + gtk_widget_show_all(GTK_WIDGET(pBox)); + + return pBox; + } + virtual ~GtkInstanceMenuButton() override { if (m_pMenuHack) @@ -7611,6 +7631,247 @@ public: } }; +class GtkInstanceMenuToggleButton : public GtkInstanceToggleButton, public MenuHelper + , public virtual weld::MenuToggleButton +{ +private: + GtkContainer* m_pContainer; + GtkButton* m_pToggleMenuButton; + GtkBox* m_pBox; + gulong m_nMenuBtnClickedId; + gulong m_nToggleStateFlagsChangedId; + gulong m_nMenuBtnStateFlagsChangedId; + + static void signalToggleStateFlagsChanged(GtkWidget* pWidget, GtkStateFlags /*eFlags*/, gpointer widget) + { + GtkInstanceMenuToggleButton* pThis = static_cast<GtkInstanceMenuToggleButton*>(widget); + // mirror togglebutton state to menubutton + gtk_widget_set_state_flags(GTK_WIDGET(pThis->m_pToggleMenuButton), gtk_widget_get_state_flags(pWidget), true); + } + + static void signalMenuBtnStateFlagsChanged(GtkWidget* pWidget, GtkStateFlags /*eFlags*/, gpointer widget) + { + GtkInstanceMenuToggleButton* pThis = static_cast<GtkInstanceMenuToggleButton*>(widget); + // mirror menubutton to togglebutton, keeping depressed state of menubutton + GtkStateFlags eToggleFlags = gtk_widget_get_state_flags(GTK_WIDGET(pThis->m_pToggleButton)); + GtkStateFlags eFlags = gtk_widget_get_state_flags(pWidget); + GtkStateFlags eFinalFlags = static_cast<GtkStateFlags>((eFlags & ~GTK_STATE_FLAG_ACTIVE) | + (eToggleFlags & GTK_STATE_FLAG_ACTIVE)); + gtk_widget_set_state_flags(GTK_WIDGET(pThis->m_pToggleButton), eFinalFlags, true); + } + + static void signalMenuBtnClicked(GtkButton*, gpointer widget) + { + GtkInstanceMenuToggleButton* pThis = static_cast<GtkInstanceMenuToggleButton*>(widget); + pThis->launch_menu(); + } + + void launch_menu() + { + gtk_widget_set_state_flags(GTK_WIDGET(m_pToggleMenuButton), gtk_widget_get_state_flags(GTK_WIDGET(m_pToggleButton)), true); + GtkWidget* pWidget = GTK_WIDGET(m_pToggleButton); + + //run in a sub main loop because we need to keep vcl PopupMenu alive to use + //it during DispatchCommand, returning now to the outer loop causes the + //launching PopupMenu to be destroyed, instead run the subloop here + //until the gtk menu is destroyed + GMainLoop* pLoop = g_main_loop_new(nullptr, true); + gulong nSignalId = g_signal_connect_swapped(G_OBJECT(m_pMenu), "deactivate", G_CALLBACK(g_main_loop_quit), pLoop); + +#if GTK_CHECK_VERSION(3,22,0) + if (gtk_check_version(3, 22, 0) == nullptr) + { + // Send a keyboard event through gtk_main_do_event to toggle any active tooltip offs + // before trying to launch the menu + // https://gitlab.gnome.org/GNOME/gtk/issues/1785 + GdkEvent *pKeyEvent = GtkSalFrame::makeFakeKeyPress(pWidget); + gtk_main_do_event(pKeyEvent); + + GdkEvent *pTriggerEvent = gtk_get_current_event(); + if (!pTriggerEvent) + pTriggerEvent = pKeyEvent; + + gtk_menu_popup_at_widget(m_pMenu, pWidget, GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, pTriggerEvent); + + gdk_event_free(pKeyEvent); + } +#else + else + { + guint nButton; + guint32 nTime; + + //typically there is an event, and we can then distinguish if this was + //launched from the keyboard (gets auto-mnemoniced) or the mouse (which + //doesn't) + GdkEvent *pEvent = gtk_get_current_event(); + if (pEvent) + { + gdk_event_get_button(pEvent, &nButton); + nTime = gdk_event_get_time(pEvent); + } + else + { + nButton = 0; + nTime = GtkSalFrame::GetLastInputEventTime(); + } + + gtk_menu_popup(m_pMenu, nullptr, nullptr, nullptr, nullptr, nButton, nTime); + } +#endif + + if (g_main_loop_is_running(pLoop)) + { + gdk_threads_leave(); + g_main_loop_run(pLoop); + gdk_threads_enter(); + } + g_main_loop_unref(pLoop); + g_signal_handler_disconnect(m_pMenu, nSignalId); + } + +public: + GtkInstanceMenuToggleButton(GtkBuilder* pMenuToggleButtonBuilder, GtkMenuButton* pMenuButton, + GtkInstanceBuilder* pBuilder, bool bTakeOwnership) + : GtkInstanceToggleButton(GTK_TOGGLE_BUTTON(gtk_builder_get_object(pMenuToggleButtonBuilder, "togglebutton")), + pBuilder, bTakeOwnership) + , MenuHelper(gtk_menu_button_get_popup(pMenuButton), false) + , m_pContainer(GTK_CONTAINER(gtk_builder_get_object(pMenuToggleButtonBuilder, "box"))) + , m_pToggleMenuButton(GTK_BUTTON(gtk_builder_get_object(pMenuToggleButtonBuilder, "menubutton"))) + , m_nMenuBtnClickedId(g_signal_connect(m_pToggleMenuButton, "clicked", G_CALLBACK(signalMenuBtnClicked), this)) + , m_nToggleStateFlagsChangedId(g_signal_connect(m_pToggleButton, "state-flags-changed", G_CALLBACK(signalToggleStateFlagsChanged), this)) + , m_nMenuBtnStateFlagsChangedId(g_signal_connect(m_pToggleMenuButton, "state-flags-changed", G_CALLBACK(signalMenuBtnStateFlagsChanged), this)) + { + m_pBox = GtkInstanceMenuButton::formatMenuButton(gtk_bin_get_child(GTK_BIN(pMenuButton))); + + insertAsParent(GTK_WIDGET(pMenuButton), GTK_WIDGET(m_pContainer)); + gtk_widget_hide(GTK_WIDGET(pMenuButton)); + + // move the first GtkMenuButton child, as created by GtkInstanceMenuButton ctor, into the GtkToggleButton + // instead, leaving just the indicator behind in the GtkMenuButton + GtkWidget* pButtonBox = gtk_bin_get_child(GTK_BIN(pMenuButton)); + GList* pChildren = gtk_container_get_children(GTK_CONTAINER(pButtonBox)); + int nGroup = 0; + for (GList* pChild = g_list_first(pChildren); pChild && nGroup < 2; pChild = g_list_next(pChild), ++nGroup) + { + GtkWidget* pWidget = static_cast<GtkWidget*>(pChild->data); + g_object_ref(pWidget); + gtk_container_remove(GTK_CONTAINER(pButtonBox), pWidget); + if (nGroup == 0) + gtk_container_add(GTK_CONTAINER(m_pToggleButton), pWidget); + else + gtk_container_add(GTK_CONTAINER(m_pToggleMenuButton), pWidget); + gtk_widget_show_all(pWidget); + g_object_unref(pWidget); + } + g_list_free(pChildren); + + // match the GtkToggleButton relief to the GtkMenuButton + GtkReliefStyle eStyle = gtk_button_get_relief(GTK_BUTTON(pMenuButton)); + gtk_button_set_relief(GTK_BUTTON(m_pToggleButton), eStyle); + gtk_button_set_relief(GTK_BUTTON(m_pToggleMenuButton), eStyle); + + // move the GtkMenuButton margins up to the new parent + gtk_widget_set_margin_top(GTK_WIDGET(m_pContainer), + gtk_widget_get_margin_top(GTK_WIDGET(pMenuButton))); + gtk_widget_set_margin_bottom(GTK_WIDGET(m_pContainer), + gtk_widget_get_margin_bottom(GTK_WIDGET(pMenuButton))); + gtk_widget_set_margin_left(GTK_WIDGET(m_pContainer), + gtk_widget_get_margin_left(GTK_WIDGET(pMenuButton))); + gtk_widget_set_margin_right(GTK_WIDGET(m_pContainer), + gtk_widget_get_margin_right(GTK_WIDGET(pMenuButton))); + + gtk_menu_detach(m_pMenu); + gtk_menu_attach_to_widget(m_pMenu, GTK_WIDGET(m_pToggleButton), nullptr); + } + + virtual void disable_notify_events() override + { + g_signal_handler_block(m_pToggleMenuButton, m_nMenuBtnClickedId); + GtkInstanceToggleButton::disable_notify_events(); + } + + virtual void enable_notify_events() override + { + GtkInstanceToggleButton::enable_notify_events(); + g_signal_handler_unblock(m_pToggleMenuButton, m_nMenuBtnClickedId); + } + + virtual ~GtkInstanceMenuToggleButton() + { + g_signal_handler_disconnect(m_pToggleButton, m_nToggleStateFlagsChangedId); + g_signal_handler_disconnect(m_pToggleMenuButton, m_nMenuBtnStateFlagsChangedId); + g_signal_handler_disconnect(m_pToggleMenuButton, m_nMenuBtnClickedId); + } + + virtual void insert_item(int pos, const OUString& rId, const OUString& rStr, + const OUString* pIconName, VirtualDevice* pImageSurface, TriState eCheckRadioFalse) override + { + MenuHelper::insert_item(pos, rId, rStr, pIconName, pImageSurface, eCheckRadioFalse); + } + + virtual void insert_separator(int pos, const OUString& rId) override + { + MenuHelper::insert_separator(pos, rId); + } + + virtual void remove_item(const OString& rId) override + { + MenuHelper::remove_item(rId); + } + + virtual void clear() override + { + clear_items(); + } + + virtual void set_item_active(const OString& rIdent, bool bActive) override + { + MenuHelper::set_item_active(rIdent, bActive); + } + + virtual void set_item_sensitive(const OString& rIdent, bool bSensitive) override + { + MenuHelper::set_item_sensitive(rIdent, bSensitive); + } + + virtual void set_item_label(const OString& rIdent, const OUString& rLabel) override + { + MenuHelper::set_item_label(rIdent, rLabel); + } + + virtual OUString get_item_label(const OString& rIdent) const override + { + return MenuHelper::get_item_label(rIdent); + } + + virtual void set_item_visible(const OString& rIdent, bool bVisible) override + { + MenuHelper::set_item_visible(rIdent, bVisible); + } + + virtual void set_item_help_id(const OString& rIdent, const OString& rHelpId) override + { + MenuHelper::set_item_help_id(rIdent, rHelpId); + } + + virtual OString get_item_help_id(const OString& rIdent) const override + { + return MenuHelper::get_item_help_id(rIdent); + } + + virtual void signal_activate(GtkMenuItem* pItem) override + { + const gchar* pStr = gtk_buildable_get_name(GTK_BUILDABLE(pItem)); + signal_selected(OString(pStr, pStr ? strlen(pStr) : 0)); + } + + virtual void set_popover(weld::Widget* /*pPopover*/) override + { + assert(false && "not implemented"); + } +}; + class GtkInstanceMenu : public MenuHelper, public virtual weld::Menu { protected: @@ -13645,6 +13906,14 @@ void GtkInstanceDrawingArea::im_context_set_cursor_location(const tools::Rectang namespace { +GtkBuilder* makeMenuToggleButtonBuilder() +{ + OUString aUri(AllSettings::GetUIRootDir() + "vcl/ui/menutogglebutton.ui"); + OUString aPath; + osl::FileBase::getSystemPathFromFileURL(aUri, aPath); + return gtk_builder_new_from_file(OUStringToOString(aPath, RTL_TEXTENCODING_UTF8).getStr()); +} + GtkBuilder* makeComboBoxBuilder() { OUString aUri(AllSettings::GetUIRootDir() + "vcl/ui/combobox.ui"); @@ -16423,6 +16692,17 @@ public: return std::make_unique<GtkInstanceMenuButton>(pButton, nullptr, this, false); } + virtual std::unique_ptr<weld::MenuToggleButton> weld_menu_toggle_button(const OString &id) override + { + GtkMenuButton* pButton = GTK_MENU_BUTTON(gtk_builder_get_object(m_pBuilder, id.getStr())); + if (!pButton) + return nullptr; + auto_add_parentless_widgets_to_container(GTK_WIDGET(pButton)); + // gtk doesn't come with exactly the the concept + GtkBuilder* pMenuToggleButton = makeMenuToggleButtonBuilder(); + return std::make_unique<GtkInstanceMenuToggleButton>(pMenuToggleButton, pButton, this, false); + } + virtual std::unique_ptr<weld::LinkButton> weld_link_button(const OString &id) override { GtkLinkButton* pButton = GTK_LINK_BUTTON(gtk_builder_get_object(m_pBuilder, id.getStr())); |