From fbc55a75b4432d545b5db44a704665a6f7e73577 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 7 Feb 2025 23:09:02 -0700 Subject: [PATCH] API changes to MetaButton, mostly to allow submenus to be hung from the built menu --- libs/widgets/metabutton.cc | 46 ++++++++++++++++++++++++++++--- libs/widgets/widgets/metabutton.h | 24 ++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/libs/widgets/metabutton.cc b/libs/widgets/metabutton.cc index 9809b98f1d..312530ffe8 100644 --- a/libs/widgets/metabutton.cc +++ b/libs/widgets/metabutton.cc @@ -71,16 +71,39 @@ MetaButton::add_item (std::string const& label, std::string const& menutext, sig } } +void +MetaButton::add_item (std::string const& label, std::string const & menutext, Gtk::Menu& submenu, sigc::slot const & cb) +{ + using namespace Menu_Helpers; + + add_sizing_text (label); + MenuList& items = _menu.items (); + items.push_back (MetaElement (label, menutext, cb, sigc::mem_fun (*this, &MetaButton::activate_item), submenu)); + if (items.size () == 1) { + _menu.set_active (0); + update_button (dynamic_cast (&items.back ())); + set_text (label); + } +} + +bool +MetaButton::is_menu_popup_event (GdkEventButton* ev) const +{ + return ((ev->type == GDK_BUTTON_PRESS && ev->button == 3) || + (ev->type == GDK_BUTTON_PRESS && ev->button == 1 && ev->x > (get_width () - _diameter - 7))); +} + bool MetaButton::on_button_press_event (GdkEventButton* ev) { MetaMenuItem const* current_active = dynamic_cast (_menu.get_active ()); - if (ev->type == GDK_BUTTON_PRESS && ev->button == 3) { + if (is_menu_popup_event (ev)) { Gtkmm2ext::anchored_menu_popup (&_menu, this, current_active ? current_active->menutext () : "", ev->button, ev->time); - } else if (ev->type == GDK_BUTTON_PRESS && ev->button == 1 && ev->x > (get_width () - _diameter - 7)) { - Gtkmm2ext::anchored_menu_popup (&_menu, this, current_active ? current_active->menutext () : "", ev->button, ev->time); - } else if (ev->type == GDK_BUTTON_PRESS && ev->button == 1) { + return true; + } + + if (ev->type == GDK_BUTTON_PRESS && ev->button == 1) { if (current_active) { current_active->activate (); } @@ -136,6 +159,21 @@ MetaButton::set_active (std::string const& menulabel) } } +void +MetaButton::set_by_menutext (std::string const & mt) +{ + guint c = 0; + for (auto & i : _menu.items()) { + if (i.get_label() == mt) { + _menu.set_active (c); + _active = c; + update_button (dynamic_cast (&i)); + break; + } + ++c; + } +} + void MetaButton::set_index (guint index) { diff --git a/libs/widgets/widgets/metabutton.h b/libs/widgets/widgets/metabutton.h index 3e7716f581..c0c3a690ec 100644 --- a/libs/widgets/widgets/metabutton.h +++ b/libs/widgets/widgets/metabutton.h @@ -33,16 +33,22 @@ public: virtual ~MetaButton (); void add_item (std::string const& label, std::string const& menutext, sigc::slot const&); + void add_item (std::string const& label, std::string const& menutext, Gtk::Menu&, sigc::slot const&); void clear_items (); void set_active (std::string const&); void set_index (guint); + void set_by_menutext (std::string const & mt); guint index () const { return _active; } + Gtk::Menu& menu() { return _menu; } + + bool is_menu_popup_event (GdkEventButton* ev) const; + protected: bool on_button_press_event (GdkEventButton*); bool on_motion_notify_event (GdkEventMotion*); @@ -60,6 +66,14 @@ private: { } + MetaMenuItem (std::string const& label, std::string const& menutext, sigc::slot const & cb, Gtk::Menu& submenu) + : Gtk::MenuItem (menutext, false) + , _label (label) + , _cb (cb) + { + set_submenu (submenu); + } + void activate () const { _cb (); @@ -94,6 +108,16 @@ private: child_->signal_activate ().connect (sigc::bind (wrap, mmi)); child_->show (); } + MetaElement (std::string const& label, std::string const & menutext, sigc::slot const & cb, SlotActivate const & wrap, Gtk::Menu& submenu) + : Gtk::Menu_Helpers::MenuElem ("") + { + MetaMenuItem* mmi = manage (new MetaMenuItem (label, menutext, cb, submenu)); + child_->unreference (); + set_child (mmi); + child_->signal_activate ().connect (sigc::bind (wrap, mmi)); + child_->show (); + } + }; void activate_item (MetaMenuItem const*);