[gtkmm/dropdown-demo] Demos: Add DropDown demo
- From: Andreas Persson <andreasp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtkmm/dropdown-demo] Demos: Add DropDown demo
- Date: Sun, 20 Sep 2020 10:01:22 +0000 (UTC)
commit 7fea7f029b4e885a223e5d4ab82499c0616d8ba5
Author: Andreas Persson <andreasp56 outlook com>
Date: Sun Sep 20 12:00:39 2020 +0200
Demos: Add DropDown demo
demos/Makefile.am | 1 +
demos/gtk-demo/demo.gresource.xml | 1 +
demos/gtk-demo/demos.h | 2 +
demos/gtk-demo/example_dropdown.cc | 288 +++++++++++++++++++++++++++++++++++++
demos/gtk-demo/meson.build | 1 +
5 files changed, 293 insertions(+)
---
diff --git a/demos/Makefile.am b/demos/Makefile.am
index 23494c40..37b86205 100644
--- a/demos/Makefile.am
+++ b/demos/Makefile.am
@@ -41,6 +41,7 @@ GTK_DEMOS = \
gtk-demo/example_colorsel.cc \
gtk-demo/example_dialog.cc \
gtk-demo/example_drawingarea.cc \
+ gtk-demo/example_dropdown.cc \
gtk-demo/example_flowbox.cc \
gtk-demo/example_gestures.cc \
gtk-demo/example_glarea.cc \
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index 8d24adf1..a68c7d0b 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -42,6 +42,7 @@
<file>example_colorsel.cc</file>
<file>example_dialog.cc</file>
<file>example_drawingarea.cc</file>
+ <file>example_dropdown.cc</file>
<file>example_flowbox.cc</file>
<file>example_gestures.cc</file>
<file>example_glarea.cc</file>
diff --git a/demos/gtk-demo/demos.h b/demos/gtk-demo/demos.h
index 273c794e..e4c04614 100644
--- a/demos/gtk-demo/demos.h
+++ b/demos/gtk-demo/demos.h
@@ -18,6 +18,7 @@ Gtk::Window* do_builder();
Gtk::Window* do_colorsel();
Gtk::Window* do_dialog();
Gtk::Window* do_drawingarea();
+Gtk::Window* do_dropdown();
Gtk::Window* do_flowbox();
Gtk::Window* do_gestures();
Gtk::Window* do_glarea();
@@ -60,6 +61,7 @@ Demo testgtk_demos[] =
{ "Color Chooser", "example_colorsel.cc", sigc::ptr_fun(&do_colorsel), nullptr },
{ "Dialog and Message Boxes", "example_dialog.cc", sigc::ptr_fun(&do_dialog), nullptr },
{ "Drawing Area", "example_drawingarea.cc", sigc::ptr_fun(&do_drawingarea), nullptr },
+ { "Drop Downs", "example_dropdown.cc", sigc::ptr_fun(&do_dropdown), nullptr },
{ "Flow Box", "example_flowbox.cc", sigc::ptr_fun(&do_flowbox), nullptr },
{ "Gestures", "example_gestures.cc", sigc::ptr_fun(&do_gestures), nullptr },
{ "Header Bar", "example_headerbar.cc", sigc::ptr_fun(&do_headerbar), nullptr },
diff --git a/demos/gtk-demo/example_dropdown.cc b/demos/gtk-demo/example_dropdown.cc
new file mode 100644
index 00000000..a96e4c1b
--- /dev/null
+++ b/demos/gtk-demo/example_dropdown.cc
@@ -0,0 +1,288 @@
+/* Drop Downs
+ *
+ * The Gtk::DropDown widget is a modern alternative to Gtk::ComboBox.
+ * It uses list models instead of tree models, and the content is
+ * displayed using widgets instead of cell renderers.
+ *
+ * The examples here demonstrate how to use different kinds of
+ * list models with Gtk::DropDown, how to use search and how to
+ * display the selected item differently from the presentation
+ * in the popup.
+ */
+
+#include <gtkmm.h>
+#include <pangomm/cairofontmap.h>
+
+class StringHolder : public Glib::Object {
+public:
+ Glib::ustring m_title;
+ std::optional<Glib::ustring> m_icon;
+ std::optional<Glib::ustring> m_description;
+protected:
+ StringHolder(const Glib::ustring& title,
+ const std::optional<Glib::ustring>& icon,
+ const std::optional<Glib::ustring>& description);
+public:
+ static Glib::RefPtr<StringHolder> create(
+ const Glib::ustring& title,
+ const std::optional<Glib::ustring>& icon,
+ const std::optional<Glib::ustring>& description);
+};
+
+StringHolder::StringHolder(const Glib::ustring& title,
+ const std::optional<Glib::ustring>& icon,
+ const std::optional<Glib::ustring>& description)
+:
+ m_title(title),
+ m_icon(icon),
+ m_description(description)
+{
+}
+
+Glib::RefPtr<StringHolder> StringHolder::create(
+ const Glib::ustring& title,
+ const std::optional<Glib::ustring>& icon,
+ const std::optional<Glib::ustring>& description)
+{
+ return Glib::make_refptr_for_instance<StringHolder>(
+ new StringHolder(title, icon, description));
+}
+
+
+class Example_DropDown : public Gtk::Window
+{
+public:
+ Example_DropDown();
+ ~Example_DropDown() override;
+
+protected:
+ void strings_setup_item_single_line(const Glib::RefPtr<Gtk::ListItem>& item);
+ void strings_setup_item_full(const Glib::RefPtr<Gtk::ListItem>& item);
+ void strings_bind_item(const Glib::RefPtr<Gtk::ListItem>& item);
+ Glib::RefPtr<Gtk::ListItemFactory> strings_factory_new(bool full);
+ Glib::RefPtr<Gio::ListModel> strings_model_new(const std::vector<Glib::ustring>& titles,
+ const std::vector<Glib::ustring>& icons,
+ const std::vector<Glib::ustring>& descriptions);
+ Gtk::DropDown* drop_down_new_from_strings(const std::vector<Glib::ustring>& titles,
+ const std::vector<Glib::ustring>& icons,
+ const std::vector<Glib::ustring>& descriptions);
+ Glib::ustring get_family_name(const Glib::RefPtr<Glib::ObjectBase>& item);
+ Glib::ustring get_title(const Glib::RefPtr<Glib::ObjectBase>& item);
+
+ Gtk::Box m_box;
+ Gtk::CheckButton m_check;
+};
+
+Gtk::Window* do_dropdown()
+{
+ return new Example_DropDown();
+}
+
+void Example_DropDown::strings_setup_item_single_line(const Glib::RefPtr<Gtk::ListItem>& item)
+{
+ auto box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 10);
+
+ auto image = Gtk::make_managed<Gtk::Image>();
+ auto title = Gtk::make_managed<Gtk::Label>();
+ title->set_xalign(0.0);
+
+ box->append(*image);
+ box->append(*title);
+
+ item->set_data("title", title);
+ item->set_data("image", image);
+
+ item->set_child(*box);
+}
+
+void Example_DropDown::strings_setup_item_full(const Glib::RefPtr<Gtk::ListItem>& item)
+{
+ auto image = Gtk::make_managed<Gtk::Image>();
+ auto title = Gtk::make_managed<Gtk::Label>();
+ title->set_xalign(0.0);
+ auto description = Gtk::make_managed<Gtk::Label>();
+ description->set_xalign(0.0);
+ description->add_css_class("dim-label");
+
+ auto box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 10);
+ auto box2 = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 2);
+
+ box->append(*image);
+ box->append(*box2);
+ box2->append(*title);
+ box2->append(*description);
+
+ item->set_data("title", title);
+ item->set_data("image", image);
+ item->set_data("description", description);
+
+ item->set_child(*box);
+}
+
+void Example_DropDown::strings_bind_item(const Glib::RefPtr<Gtk::ListItem>& item)
+{
+ auto holder = std::dynamic_pointer_cast<StringHolder>(item->get_item());
+
+ auto title = static_cast<Gtk::Label*>(item->get_data("title"));
+ auto image = static_cast<Gtk::Image*>(item->get_data("image"));
+ auto description = static_cast<Gtk::Label*>(item->get_data("description"));
+
+ title->set_label(holder->m_title);
+ if (image)
+ {
+ if (holder->m_icon)
+ image->set_from_icon_name(*holder->m_icon);
+ else
+ image->clear();
+ image->set_visible(holder->m_icon.has_value());
+ }
+ if (description)
+ {
+ description->set_label(*holder->m_description);
+ description->set_visible(holder->m_description.has_value());
+ }
+}
+
+Glib::RefPtr<Gtk::ListItemFactory> Example_DropDown::strings_factory_new(bool full)
+{
+ auto factory = Gtk::SignalListItemFactory::create();
+ if (full)
+ factory->signal_setup().connect(
+ sigc::mem_fun(*this, &Example_DropDown::strings_setup_item_full));
+ else
+ factory->signal_setup().connect(
+ sigc::mem_fun(*this, &Example_DropDown::strings_setup_item_single_line));
+ factory->signal_bind().connect(
+ sigc::mem_fun(*this, &Example_DropDown::strings_bind_item));
+
+ return factory;
+}
+
+Glib::RefPtr<Gio::ListModel> Example_DropDown::strings_model_new(
+ const std::vector<Glib::ustring>& titles,
+ const std::vector<Glib::ustring>& icons,
+ const std::vector<Glib::ustring>& descriptions)
+{
+ auto store = Gio::ListStore<StringHolder>::create();
+ for (guint i = 0; i < titles.size(); i++)
+ {
+ auto icon = icons.empty() ? std::nullopt :
+ std::make_optional<Glib::ustring>(icons[i]);
+ auto description = descriptions.empty() ? std::nullopt :
+ std::make_optional<Glib::ustring>(descriptions[i]);
+ auto holder = StringHolder::create(titles[i], icon, description);
+ store->append(holder);
+ }
+
+ return store;
+}
+
+Gtk::DropDown* Example_DropDown::drop_down_new_from_strings(
+ const std::vector<Glib::ustring>& titles,
+ const std::vector<Glib::ustring>& icons,
+ const std::vector<Glib::ustring>& descriptions)
+{
+ g_return_val_if_fail(!titles.empty(), nullptr);
+ g_return_val_if_fail(icons.empty() || icons.size() == titles.size(), nullptr);
+ g_return_val_if_fail(descriptions.empty() || icons.size() == descriptions.size(), nullptr);
+
+ auto model = strings_model_new(titles, icons, descriptions);
+ auto factory = strings_factory_new(false);
+ Glib::RefPtr<Gtk::ListItemFactory> list_factory;
+ if (!icons.empty() || !descriptions.empty())
+ list_factory = strings_factory_new(true);
+
+ auto dropdown = Gtk::make_managed<Gtk::DropDown>(model);
+ dropdown->set_factory(factory);
+ dropdown->set_list_factory(list_factory);
+
+ return dropdown;
+}
+
+Glib::ustring Example_DropDown::get_family_name(const Glib::RefPtr<Glib::ObjectBase>& item)
+{
+ auto family = std::dynamic_pointer_cast<Pango::FontFamily>(item);
+ return family ? family->get_name() : "";
+}
+
+Glib::ustring Example_DropDown::get_title(const Glib::RefPtr<Glib::ObjectBase>& item)
+{
+ return std::dynamic_pointer_cast<StringHolder>(item)->m_title;
+}
+
+Example_DropDown::Example_DropDown()
+:
+ m_box(Gtk::Orientation::VERTICAL, 10),
+ m_check("Enable search")
+{
+ const std::vector<Glib::ustring> times{
+ "1 minute", "2 minutes", "5 minutes", "20 minutes"
+ };
+ const std::vector<Glib::ustring> many_times{
+ "1 minute", "2 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes",
+ "25 minutes", "30 minutes", "35 minutes", "40 minutes", "45 minutes", "50 minutes",
+ "55 minutes", "1 hour", "2 hours", "3 hours", "5 hours", "6 hours", "7 hours",
+ "8 hours", "9 hours", "10 hours", "11 hours", "12 hours"
+ };
+ const std::vector<Glib::ustring> device_titles{
+ "Digital Output", "Headphones", "Digital Output", "Analog Output"
+ };
+ const std::vector<Glib::ustring> device_icons{
+ "audio-card-symbolic", "audio-headphones-symbolic", "audio-card-symbolic",
+ "audio-card-symbolic"
+ };
+ const std::vector<Glib::ustring> device_descriptions{
+ "Built-in Audio", "Built-in audio", "Thinkpad Tunderbolt 3 Dock USB Audio",
+ "Thinkpad Tunderbolt 3 Dock USB Audio"
+ };
+
+ set_title("Drop Downs");
+ set_resizable(false);
+
+ m_box.set_margin_start(10);
+ m_box.set_margin_end(10);
+ m_box.set_margin_top(10);
+ m_box.set_margin_bottom(10);
+ set_child(m_box);
+
+ auto model = Pango::CairoFontMap::get_default();
+ auto dropdown = Gtk::make_managed<Gtk::DropDown>(model);
+ dropdown->set_selected(0);
+
+ auto expression = Gtk::ClosureExpression<Glib::ustring>::create(
+ sigc::mem_fun(*this, &Example_DropDown::get_family_name));
+ dropdown->set_expression(expression);
+ m_box.append(*dropdown);
+
+ auto adj = Gtk::Adjustment::create(-1, -1, model->get_n_items());
+ auto spin = Gtk::make_managed<Gtk::SpinButton>(adj);
+ spin->set_halign(Gtk::Align::START);
+ Glib::Binding::bind_property(dropdown->property_selected(),
+ spin->property_value(),
+ Glib::Binding::Flags::SYNC_CREATE |
+ Glib::Binding::Flags::BIDIRECTIONAL);
+ m_box.append(*spin);
+
+ Glib::Binding::bind_property(dropdown->property_enable_search(),
+ m_check.property_active(),
+ Glib::Binding::Flags::SYNC_CREATE |
+ Glib::Binding::Flags::BIDIRECTIONAL);
+ m_box.append(m_check);
+
+ dropdown = drop_down_new_from_strings(times, {}, {});
+ m_box.append(*dropdown);
+
+ dropdown = drop_down_new_from_strings(many_times, {}, {});
+ dropdown->set_enable_search();
+ expression = Gtk::ClosureExpression<Glib::ustring>::create(
+ sigc::mem_fun(*this, &Example_DropDown::get_title));
+ dropdown->set_expression(expression);
+ m_box.append(*dropdown);
+
+ dropdown = drop_down_new_from_strings(device_titles, device_icons, device_descriptions);
+ m_box.append(*dropdown);
+}
+
+Example_DropDown::~Example_DropDown()
+{
+}
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 4a5093b1..9850043d 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -12,6 +12,7 @@ gtkmm_demo_cc_files = [
'example_colorsel.cc',
'example_dialog.cc',
'example_drawingarea.cc',
+ 'example_dropdown.cc',
'example_flowbox.cc',
'example_gestures.cc',
'example_glarea.cc',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]