This is a more complex example with two SignalListItemFactory
objects and their signal handlers. This example would be simpler without the
checkmark in the dropdown menu.
File: examplewindow.h
(For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); ~ExampleWindow() override; protected: // Signal handlers: void on_setup_selected_item(const Glib::RefPtr<Gtk::ListItem>& list_item); void on_bind_selected_item(const Glib::RefPtr<Gtk::ListItem>& list_item); void on_setup_list_item(const Glib::RefPtr<Gtk::ListItem>& list_item); void on_bind_list_item(const Glib::RefPtr<Gtk::ListItem>& list_item); void on_unbind_list_item(const Glib::RefPtr<Gtk::ListItem>& list_item); void on_selected_item_changed(const Glib::RefPtr<Gtk::ListItem>& list_item); void on_dropdown_changed(); void create_model(); void liststore_add_item(const Glib::ustring& title, const Glib::ustring& icon, const Glib::ustring& description); // A Gio::ListStore item. class ModelColumns : public Glib::Object { public: Glib::ustring m_title; Glib::ustring m_icon; Glib::ustring m_description; static Glib::RefPtr<ModelColumns> create(const Glib::ustring& title, const Glib::ustring& icon, const Glib::ustring& description) { return Glib::make_refptr_for_instance<ModelColumns>( new ModelColumns(title, icon, description)); } protected: ModelColumns(const Glib::ustring& title, const Glib::ustring& icon, const Glib::ustring& description) : m_title(title), m_icon(icon), m_description(description) {} }; // ModelColumns // Child widget: Gtk::DropDown m_DropDown; Glib::RefPtr<Gio::ListStore<ModelColumns>> m_ListStore; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: examplewindow.cc
(For use with gtkmm 4)
#include "examplewindow.h" #include <iostream> ExampleWindow::ExampleWindow() { set_title("DropDown example"); // Add the DropDown to the window. set_child(m_DropDown); // Factory for presenting the selected item. auto factory = Gtk::SignalListItemFactory::create(); factory->signal_setup().connect( sigc::mem_fun(*this, &ExampleWindow::on_setup_selected_item)); factory->signal_bind().connect( sigc::mem_fun(*this, &ExampleWindow::on_bind_selected_item)); m_DropDown.set_factory(factory); // Factory for presenting the items in the dropdown list. factory = Gtk::SignalListItemFactory::create(); factory->signal_setup().connect( sigc::mem_fun(*this, &ExampleWindow::on_setup_list_item)); factory->signal_bind().connect( sigc::mem_fun(*this, &ExampleWindow::on_bind_list_item)); m_DropDown.set_list_factory(factory); // Create the model and fill it. create_model(); m_DropDown.set_model(m_ListStore); m_DropDown.set_selected(0); // Connect signal handler: m_DropDown.property_selected().signal_changed().connect( sigc::mem_fun(*this, &ExampleWindow::on_dropdown_changed)); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_dropdown_changed() { const auto selected = m_DropDown.get_selected(); std::cout << "DropDown changed: Row=" << selected << ", Title=" << m_ListStore->get_item(selected)->m_title << std::endl; } void ExampleWindow::create_model() { m_ListStore = Gio::ListStore<ModelColumns>::create(); liststore_add_item("Digital Output", "audio-card-symbolic", "Built-in Audio"); liststore_add_item("Headphones", "audio-headphones-symbolic", "Built-in Audio"); liststore_add_item("Digital Output", "audio-card-symbolic", "Thinkpad Tunderbolt 3 Dock USB Audio"); liststore_add_item("Analog Output", "audio-card-symbolic", "Thinkpad Tunderbolt 3 Dock USB Audio"); } void ExampleWindow::liststore_add_item(const Glib::ustring& title, const Glib::ustring& icon, const Glib::ustring& description) { m_ListStore->append(ModelColumns::create(title, icon, description)); } void ExampleWindow::on_setup_selected_item(const Glib::RefPtr<Gtk::ListItem>& list_item) { auto box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 10); box->append(*Gtk::make_managed<Gtk::Image>()); box->append(*Gtk::make_managed<Gtk::Label>()); list_item->set_child(*box); } void ExampleWindow::on_bind_selected_item(const Glib::RefPtr<Gtk::ListItem>& list_item) { auto col = std::dynamic_pointer_cast<ModelColumns>(list_item->get_item()); if (!col) return; auto box = dynamic_cast<Gtk::Box*>(list_item->get_child()); if (!box) return; auto image = dynamic_cast<Gtk::Image*>(box->get_first_child()); if (!image) return; image->set_from_icon_name(col->m_icon); auto label = dynamic_cast<Gtk::Label*>(image->get_next_sibling()); if (!label) return; label->set_text(col->m_title); } void ExampleWindow::on_setup_list_item(const Glib::RefPtr<Gtk::ListItem>& list_item) { auto hbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 10); auto vbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 2); hbox->append(*Gtk::make_managed<Gtk::Image>()); hbox->append(*vbox); auto title = Gtk::make_managed<Gtk::Label>(); title->set_xalign(0.0); vbox->append(*title); auto description = Gtk::make_managed<Gtk::Label>(); description->set_xalign(0.0); description->add_css_class("dim-label"); vbox->append(*description); auto checkmark = Gtk::make_managed<Gtk::Image>(); checkmark->set_from_icon_name("object-select-symbolic"); checkmark->set_visible(false); hbox->append(*checkmark); list_item->set_child(*hbox); } void ExampleWindow::on_bind_list_item(const Glib::RefPtr<Gtk::ListItem>& list_item) { auto col = std::dynamic_pointer_cast<ModelColumns>(list_item->get_item()); if (!col) return; auto hbox = dynamic_cast<Gtk::Box*>(list_item->get_child()); if (!hbox) return; auto image = dynamic_cast<Gtk::Image*>(hbox->get_first_child()); if (!image) return; image->set_from_icon_name(col->m_icon); auto vbox = dynamic_cast<Gtk::Box*>(image->get_next_sibling()); if (!vbox) return; auto title = dynamic_cast<Gtk::Label*>(vbox->get_first_child()); if (!title) return; title->set_text(col->m_title); auto description = dynamic_cast<Gtk::Label*>(title->get_next_sibling()); if (!description) return; description->set_text(col->m_description); auto connection = m_DropDown.property_selected_item().signal_changed().connect( sigc::bind(sigc::mem_fun(*this, &ExampleWindow::on_selected_item_changed), list_item)); list_item->set_data("connection", new sigc::connection(connection), Glib::destroy_notify_delete<sigc::connection>); on_selected_item_changed(list_item); } void ExampleWindow::on_unbind_list_item(const Glib::RefPtr<Gtk::ListItem>& list_item) { if (auto connection = static_cast<sigc::connection*>(list_item->get_data("connection"))) { connection->disconnect(); list_item->set_data("connection", nullptr); } } void ExampleWindow::on_selected_item_changed(const Glib::RefPtr<Gtk::ListItem>& list_item) { auto hbox = dynamic_cast<Gtk::Box*>(list_item->get_child()); if (!hbox) return; auto checkmark = dynamic_cast<Gtk::Image*>(hbox->get_last_child()); if (!checkmark) return; checkmark->set_visible(m_DropDown.get_selected_item() == list_item->get_item()); }
File: main.cc
(For use with gtkmm 4)
#include "examplewindow.h" #include <gtkmm/application.h> int main(int argc, char* argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); // Shows the window and returns when it is closed. return app->make_window_and_run<ExampleWindow>(argc, argv); }