Re: Failure to add radio buttons to popup menu.

Kjell Ahlstedt via gtkmm-list <[email protected]> Sun, 6 Dec 2020 16:39:42 +0100
Newsgroups gmane.comp.gnome.gtkmm
Message-ID <[email protected]>
I combined ideas from the book/menus/main_menu and book/menus/popup 
examples in gtkmm-documentation. Then it works. See attached files.

On 2020-12-04 16:51, Carlo Wood wrote:
> Hi Kjell,
>
> I've been trying for days to get radio buttons working
> in my popup menu. I can't get closer than "it doesn't work".
>
> Most notably, the line
>
>      refActionGroup->add_action_radio_string("radio",
>      sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_radio),
>      "'A'");
>
> doesn't even cause the call back function to be called
> when I click on the radio menu entry.
>
> Can you please tell me what I do wrong and how it should
> be done?
>
> I reproduced my problem by editing
> gtkmm-documentation/-/blob/gtkmm-3-24/examples/book/menus/popup
>
> The cloned repository and commit can be found here:
>
> https://gitlab.gnome.org/carlo.wood/gtkmm-documentation/-/commit/e106f79c78bba7ad265817a74897f09501d024db
>
> If you clone my repository, please note that the change was
> made to the gtkmm-3-24 branch (not master)!
>
> Or you can copy the two changed files from here:
>
> https://gitlab.gnome.org/carlo.wood/gtkmm-documentation/-/blob/gtkmm-3-24/examples/book/menus/popup/examplewindow.cc
> https://gitlab.gnome.org/carlo.wood/gtkmm-documentation/-/blob/gtkmm-3-24/examples/book/menus/popup/examplewindow.h
>
> Any pointers would be greatly appreciated.
>
> Regards,
> Carlo Wood
> _______________________________________________
> gtkmm-list mailing list
> [email protected]
> https://mail.gnome.org/mailman/listinfo/gtkmm-list

_______________________________________________
gtkmm-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
examplewindow.h (text/x-chdr, 1.4 KB)
/* gtkmm example Copyright (C) 2002 gtkmm development team
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm.h>

#include <memory>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

protected:
  //Signal handlers:
  bool on_button_press_event(GdkEventButton* button_event) override;

  void on_menu_file_popup_normal();
  void on_menu_file_popup_radio(Glib::ustring const& parameter);

  //Child widgets:
  Gtk::Box m_Box;
  Gtk::EventBox m_EventBox;
  Gtk::Label m_Label;

  Glib::RefPtr<Gtk::Builder> m_refBuilder;

  // One set of choices:
  Glib::RefPtr<Gio::SimpleAction> m_refChoice;

  std::unique_ptr<Gtk::Menu> m_pMenuPopup;
};

#endif //GTKMM_EXAMPLEWINDOW_H
examplewindow.cc (text/x-c++src, 3.9 KB)
/* gtkmm example Copyright (C) 2002-2013 gtkmm development team
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "examplewindow.h"
#include <iostream>

ExampleWindow::ExampleWindow()
: m_Box(Gtk::ORIENTATION_VERTICAL),
  m_Label("Right-click to see the popup menu."),
  m_pMenuPopup(nullptr)
{
  set_title("popup example");
  set_default_size(200, 200);

  add(m_Box);

  //Add an event box that can catch button_press events:
  m_Box.pack_start(m_EventBox);
  m_EventBox.signal_button_press_event().connect(sigc::mem_fun(*this,
              &ExampleWindow::on_button_press_event) );

  m_EventBox.add(m_Label);

  //Create actions:

  //Fill menu:

  auto refActionGroup =
    Gio::SimpleActionGroup::create();

  refActionGroup->add_action("normal",
    sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_normal));

  m_refChoice = refActionGroup->add_action_radio_string("radio",
    sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_radio), "A");

  insert_action_group("examplepopup", refActionGroup);

  m_refBuilder = Gtk::Builder::create();

  //Layout the actions in a menubar and toolbar:
  Glib::ustring ui_info =
    "<interface>"
    "  <menu id='menu-examplepopup'>"
    "    <section>"
    "      <item>"
    "        <attribute name='label' translatable='yes'>Normal</attribute>"
    "        <attribute name='action'>examplepopup.normal</attribute>"
    "      </item>"
    "      <item>"
    "        <attribute name='label' translatable='yes'>Radio 1</attribute>"
    "        <attribute name='action'>examplepopup.radio</attribute>"
    "          <attribute name='target'>A</attribute>"
    "      </item>"
    "      <item>"
    "        <attribute name='label' translatable='yes'>Radio 2</attribute>"
    "        <attribute name='action'>examplepopup.radio</attribute>"
    "          <attribute name='target'>B</attribute>"
    "      </item>"
    "    </section>"
    "  </menu>"
    "</interface>";

  try
  {
    m_refBuilder->add_from_string(ui_info);
  }
  catch(const Glib::Error& ex)
  {
    std::cerr << "building menus failed: " <<  ex.what();
  }

  //Get the menu:
  auto object = m_refBuilder->get_object("menu-examplepopup");
  auto gmenu =  Glib::RefPtr<Gio::Menu>::cast_dynamic(object);
  if(!gmenu)
    g_warning("GMenu not found");

  m_pMenuPopup = std::make_unique<Gtk::Menu>(gmenu);

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_menu_file_popup_normal()
{
   std::cout << "The popup menu item 'normal' was selected." << std::endl;
}

void ExampleWindow::on_menu_file_popup_radio(Glib::ustring const& parameter)
{
   std::cout << "The popup radio menu item " << parameter << " was selected." << std::endl;

  //The radio action's state does not change automatically:
  m_refChoice->change_state(parameter);
}

bool ExampleWindow::on_button_press_event(GdkEventButton* button_event)
{
  if( (button_event->type == GDK_BUTTON_PRESS) && (button_event->button == 3) )
  {
    if(!m_pMenuPopup->get_attach_widget())
    {
      m_pMenuPopup->attach_to_widget(*this);
    }

    if(m_pMenuPopup)
      m_pMenuPopup->popup_at_pointer((GdkEvent*)button_event);

      // Menu::popup_at_pointer() is new in gtkmm 3.22.
      // If you have an older revision, try this:
      //m_pMenuPopup->popup(button_event->button, button_event->time);

    return true; //It has been handled.
  }
  else
    return false;
}