summaryrefslogtreecommitdiffstats
path: root/subprojects/libhandy/examples/hdy-demo-window.c
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/libhandy/examples/hdy-demo-window.c')
-rw-r--r--subprojects/libhandy/examples/hdy-demo-window.c573
1 files changed, 573 insertions, 0 deletions
diff --git a/subprojects/libhandy/examples/hdy-demo-window.c b/subprojects/libhandy/examples/hdy-demo-window.c
new file mode 100644
index 0000000..55c872f
--- /dev/null
+++ b/subprojects/libhandy/examples/hdy-demo-window.c
@@ -0,0 +1,573 @@
+#include "hdy-demo-window.h"
+
+#include <glib/gi18n.h>
+#include "hdy-view-switcher-demo-window.h"
+
+struct _HdyDemoWindow
+{
+ HdyApplicationWindow parent_instance;
+
+ HdyLeaflet *content_box;
+ GtkStack *header_revealer;
+ GtkStack *header_stack;
+ GtkImage *theme_variant_image;
+ GtkStackSidebar *sidebar;
+ GtkStack *stack;
+ HdyComboRow *leaflet_transition_row;
+ HdyDeck *content_deck;
+ HdyComboRow *deck_transition_row;
+ GtkWidget *box_keypad;
+ GtkListBox *keypad_listbox;
+ HdyKeypad *keypad;
+ HdySearchBar *search_bar;
+ GtkEntry *search_entry;
+ GtkListBox *lists_listbox;
+ HdyComboRow *combo_row;
+ HdyComboRow *enum_combo_row;
+ HdyCarousel *carousel;
+ GtkBox *carousel_box;
+ GtkListBox *carousel_listbox;
+ GtkStack *carousel_indicators_stack;
+ HdyComboRow *carousel_orientation_row;
+ HdyComboRow *carousel_indicators_row;
+ GListStore *carousel_indicators_model;
+ HdyAvatar *avatar;
+ GtkEntry *avatar_text;
+ GtkFileChooserButton *avatar_filechooser;
+ GtkListBox *avatar_contacts;
+};
+
+G_DEFINE_TYPE (HdyDemoWindow, hdy_demo_window, HDY_TYPE_APPLICATION_WINDOW)
+
+static void
+theme_variant_button_clicked_cb (HdyDemoWindow *self)
+{
+ GtkSettings *settings = gtk_settings_get_default ();
+ gboolean prefer_dark_theme;
+
+ g_object_get (settings, "gtk-application-prefer-dark-theme", &prefer_dark_theme, NULL);
+ g_object_set (settings, "gtk-application-prefer-dark-theme", !prefer_dark_theme, NULL);
+}
+
+static gboolean
+prefer_dark_theme_to_icon_name_cb (GBinding *binding,
+ const GValue *from_value,
+ GValue *to_value,
+ gpointer user_data)
+{
+ g_value_set_string (to_value,
+ g_value_get_boolean (from_value) ? "light-mode-symbolic" :
+ "dark-mode-symbolic");
+
+ return TRUE;
+}
+
+static gboolean
+hdy_demo_window_key_pressed_cb (GtkWidget *sender,
+ GdkEvent *event,
+ HdyDemoWindow *self)
+{
+ GdkModifierType default_modifiers = gtk_accelerator_get_default_mod_mask ();
+ guint keyval;
+ GdkModifierType state;
+
+ gdk_event_get_keyval (event, &keyval);
+ gdk_event_get_state (event, &state);
+
+ if ((keyval == GDK_KEY_q || keyval == GDK_KEY_Q) &&
+ (state & default_modifiers) == GDK_CONTROL_MASK) {
+ gtk_widget_destroy (GTK_WIDGET (self));
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+update (HdyDemoWindow *self)
+{
+ const gchar *header_bar_name = "default";
+
+ if (g_strcmp0 (gtk_stack_get_visible_child_name (self->stack), "deck") == 0)
+ header_bar_name = "deck";
+ else if (g_strcmp0 (gtk_stack_get_visible_child_name (self->stack), "search-bar") == 0)
+ header_bar_name = "search-bar";
+
+ gtk_stack_set_visible_child_name (self->header_stack, header_bar_name);
+}
+
+static void
+hdy_demo_window_notify_deck_visible_child_cb (HdyDemoWindow *self)
+{
+ update (self);
+}
+
+static void
+hdy_demo_window_notify_visible_child_cb (GObject *sender,
+ GParamSpec *pspec,
+ HdyDemoWindow *self)
+{
+ update (self);
+
+ hdy_leaflet_navigate (self->content_box, HDY_NAVIGATION_DIRECTION_FORWARD);
+}
+
+static void
+hdy_demo_window_back_clicked_cb (GtkWidget *sender,
+ HdyDemoWindow *self)
+{
+ hdy_leaflet_navigate (self->content_box, HDY_NAVIGATION_DIRECTION_BACK);
+}
+
+static void
+hdy_demo_window_deck_back_clicked_cb (GtkWidget *sender,
+ HdyDemoWindow *self)
+{
+ hdy_deck_navigate (self->content_deck, HDY_NAVIGATION_DIRECTION_BACK);
+}
+
+static gchar *
+leaflet_transition_name (HdyEnumValueObject *value,
+ gpointer user_data)
+{
+ g_return_val_if_fail (HDY_IS_ENUM_VALUE_OBJECT (value), NULL);
+
+ switch (hdy_enum_value_object_get_value (value)) {
+ case HDY_LEAFLET_TRANSITION_TYPE_OVER:
+ return g_strdup (_("Over"));
+ case HDY_LEAFLET_TRANSITION_TYPE_UNDER:
+ return g_strdup (_("Under"));
+ case HDY_LEAFLET_TRANSITION_TYPE_SLIDE:
+ return g_strdup (_("Slide"));
+ default:
+ return NULL;
+ }
+}
+
+static void
+notify_leaflet_transition_cb (GObject *sender,
+ GParamSpec *pspec,
+ HdyDemoWindow *self)
+{
+ HdyComboRow *row = HDY_COMBO_ROW (sender);
+
+ g_assert (HDY_IS_COMBO_ROW (row));
+ g_assert (HDY_IS_DEMO_WINDOW (self));
+
+ hdy_leaflet_set_transition_type (HDY_LEAFLET (self->content_box), hdy_combo_row_get_selected_index (row));
+}
+
+static gchar *
+deck_transition_name (HdyEnumValueObject *value,
+ gpointer user_data)
+{
+ g_return_val_if_fail (HDY_IS_ENUM_VALUE_OBJECT (value), NULL);
+
+ switch (hdy_enum_value_object_get_value (value)) {
+ case HDY_DECK_TRANSITION_TYPE_OVER:
+ return g_strdup (_("Over"));
+ case HDY_DECK_TRANSITION_TYPE_UNDER:
+ return g_strdup (_("Under"));
+ case HDY_DECK_TRANSITION_TYPE_SLIDE:
+ return g_strdup (_("Slide"));
+ default:
+ return NULL;
+ }
+}
+
+static void
+notify_deck_transition_cb (GObject *sender,
+ GParamSpec *pspec,
+ HdyDemoWindow *self)
+{
+ HdyComboRow *row = HDY_COMBO_ROW (sender);
+
+ g_assert (HDY_IS_COMBO_ROW (row));
+ g_assert (HDY_IS_DEMO_WINDOW (self));
+
+ hdy_deck_set_transition_type (HDY_DECK (self->content_deck), hdy_combo_row_get_selected_index (row));
+}
+
+static void
+deck_go_next_row_activated_cb (HdyDemoWindow *self)
+{
+ g_assert (HDY_IS_DEMO_WINDOW (self));
+
+ hdy_deck_navigate (self->content_deck, HDY_NAVIGATION_DIRECTION_FORWARD);
+}
+
+static void
+view_switcher_demo_clicked_cb (GtkButton *btn,
+ HdyDemoWindow *self)
+{
+ HdyViewSwitcherDemoWindow *window = hdy_view_switcher_demo_window_new ();
+
+ gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (self));
+ gtk_widget_show (GTK_WIDGET (window));
+}
+
+static gchar *
+carousel_orientation_name (HdyEnumValueObject *value,
+ gpointer user_data)
+{
+ g_return_val_if_fail (HDY_IS_ENUM_VALUE_OBJECT (value), NULL);
+
+ switch (hdy_enum_value_object_get_value (value)) {
+ case GTK_ORIENTATION_HORIZONTAL:
+ return g_strdup (_("Horizontal"));
+ case GTK_ORIENTATION_VERTICAL:
+ return g_strdup (_("Vertical"));
+ default:
+ return NULL;
+ }
+}
+
+static void
+notify_carousel_orientation_cb (GObject *sender,
+ GParamSpec *pspec,
+ HdyDemoWindow *self)
+{
+ HdyComboRow *row = HDY_COMBO_ROW (sender);
+
+ g_assert (HDY_IS_COMBO_ROW (row));
+ g_assert (HDY_IS_DEMO_WINDOW (self));
+
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (self->carousel_box),
+ 1 - hdy_combo_row_get_selected_index (row));
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (self->carousel),
+ hdy_combo_row_get_selected_index (row));
+}
+
+static gchar *
+carousel_indicators_name (HdyValueObject *value)
+{
+ const gchar *style;
+
+ g_assert (HDY_IS_VALUE_OBJECT (value));
+
+ style = hdy_value_object_get_string (value);
+
+ if (!g_strcmp0 (style, "dots"))
+ return g_strdup (_("Dots"));
+
+ if (!g_strcmp0 (style, "lines"))
+ return g_strdup (_("Lines"));
+
+ return NULL;
+}
+
+static void
+notify_carousel_indicators_cb (GObject *sender,
+ GParamSpec *pspec,
+ HdyDemoWindow *self)
+{
+ HdyComboRow *row = HDY_COMBO_ROW (sender);
+ HdyValueObject *obj;
+
+ g_assert (HDY_IS_COMBO_ROW (row));
+ g_assert (HDY_IS_DEMO_WINDOW (self));
+
+ obj = g_list_model_get_item (G_LIST_MODEL (self->carousel_indicators_model),
+ hdy_combo_row_get_selected_index (row));
+
+ gtk_stack_set_visible_child_name (self->carousel_indicators_stack,
+ hdy_value_object_get_string (obj));
+}
+
+static void
+carousel_return_clicked_cb (GtkButton *btn,
+ HdyDemoWindow *self)
+{
+ g_autoptr (GList) children =
+ gtk_container_get_children (GTK_CONTAINER (self->carousel));
+
+ hdy_carousel_scroll_to (self->carousel, GTK_WIDGET (children->data));
+}
+
+HdyDemoWindow *
+hdy_demo_window_new (GtkApplication *application)
+{
+ return g_object_new (HDY_TYPE_DEMO_WINDOW, "application", application, NULL);
+}
+
+static void
+avatar_file_remove_cb (HdyDemoWindow *self)
+{
+ g_autofree gchar *file = NULL;
+
+ g_assert (HDY_IS_DEMO_WINDOW (self));
+
+ g_signal_handlers_disconnect_by_data (self->avatar, self);
+ file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (self->avatar_filechooser));
+ if (file)
+ gtk_file_chooser_unselect_filename (GTK_FILE_CHOOSER (self->avatar_filechooser), file);
+ hdy_avatar_set_image_load_func (self->avatar, NULL, NULL, NULL);
+}
+
+static GdkPixbuf *
+avatar_load_file (gint size, HdyDemoWindow *self)
+{
+ g_autoptr (GError) error = NULL;
+ g_autoptr (GdkPixbuf) pixbuf = NULL;
+ g_autofree gchar *file = NULL;
+ gint width, height;
+
+ g_assert (HDY_IS_DEMO_WINDOW (self));
+
+ file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (self->avatar_filechooser));
+
+ gdk_pixbuf_get_file_info (file, &width, &height);
+
+ pixbuf = gdk_pixbuf_new_from_file_at_scale (file,
+ (width <= height) ? size : -1,
+ (width >= height) ? size : -1,
+ TRUE,
+ &error);
+ if (error != NULL) {
+ g_critical ("Failed to create pixbuf from file: %s", error->message);
+
+ return NULL;
+ }
+
+ return g_steal_pointer (&pixbuf);
+}
+
+static void
+avatar_file_set_cb (HdyDemoWindow *self)
+{
+ g_assert (HDY_IS_DEMO_WINDOW (self));
+
+ hdy_avatar_set_image_load_func (self->avatar, (HdyAvatarImageLoadFunc) avatar_load_file, self, NULL);
+}
+
+static gchar *
+avatar_new_random_name (void)
+{
+ static const char *first_names[] = {
+ "Adam",
+ "Adrian",
+ "Anna",
+ "Charlotte",
+ "Frédérique",
+ "Ilaria",
+ "Jakub",
+ "Jennyfer",
+ "Julia",
+ "Justin",
+ "Mario",
+ "Miriam",
+ "Mohamed",
+ "Nourimane",
+ "Owen",
+ "Peter",
+ "Petra",
+ "Rachid",
+ "Rebecca",
+ "Sarah",
+ "Thibault",
+ "Wolfgang",
+ };
+ static const char *last_names[] = {
+ "Bailey",
+ "Berat",
+ "Chen",
+ "Farquharson",
+ "Ferber",
+ "Franco",
+ "Galinier",
+ "Han",
+ "Lawrence",
+ "Lepied",
+ "Lopez",
+ "Mariotti",
+ "Rossi",
+ "Urasawa",
+ "Zwickelman",
+ };
+
+ return g_strdup_printf ("%s %s",
+ first_names[g_random_int_range (0, G_N_ELEMENTS (first_names))],
+ last_names[g_random_int_range (0, G_N_ELEMENTS (last_names))]);
+}
+
+static void
+avatar_update_contacts (HdyDemoWindow *self)
+{
+ g_autoptr (GList) children = gtk_container_get_children (GTK_CONTAINER (self->avatar_contacts));
+
+ for (GList *child = children; child; child = child->next)
+ gtk_container_remove (GTK_CONTAINER (self->avatar_contacts), child->data);
+
+ for (int i = 0; i < 30; i++) {
+ g_autofree gchar *name = avatar_new_random_name ();
+ GtkWidget *contact = hdy_action_row_new ();
+ GtkWidget *avatar = hdy_avatar_new (40, name, TRUE);
+
+ gtk_widget_show (contact);
+ gtk_widget_show (avatar);
+
+ gtk_widget_set_margin_top (avatar, 12);
+ gtk_widget_set_margin_bottom (avatar, 12);
+
+ hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (contact), name);
+ hdy_action_row_add_prefix (HDY_ACTION_ROW (contact), avatar);
+ gtk_container_add (GTK_CONTAINER (self->avatar_contacts), contact);
+ }
+}
+
+static void
+hdy_demo_window_constructed (GObject *object)
+{
+ HdyDemoWindow *self = HDY_DEMO_WINDOW (object);
+
+ G_OBJECT_CLASS (hdy_demo_window_parent_class)->constructed (object);
+
+ hdy_search_bar_connect_entry (self->search_bar, self->search_entry);
+}
+
+
+static void
+hdy_demo_window_class_init (HdyDemoWindowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = hdy_demo_window_constructed;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/sm/puri/Handy/Demo/ui/hdy-demo-window.ui");
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, content_box);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, header_revealer);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, header_stack);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, theme_variant_image);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, sidebar);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, stack);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, leaflet_transition_row);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, content_deck);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, deck_transition_row);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, box_keypad);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, keypad_listbox);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, keypad);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, search_bar);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, search_entry);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, lists_listbox);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, combo_row);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, enum_combo_row);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, carousel);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, carousel_box);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, carousel_listbox);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, carousel_indicators_stack);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, carousel_orientation_row);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, carousel_indicators_row);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, avatar);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, avatar_text);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, avatar_filechooser);
+ gtk_widget_class_bind_template_child (widget_class, HdyDemoWindow, avatar_contacts);
+ gtk_widget_class_bind_template_callback_full (widget_class, "key_pressed_cb", G_CALLBACK(hdy_demo_window_key_pressed_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "notify_visible_child_cb", G_CALLBACK(hdy_demo_window_notify_visible_child_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "notify_deck_visible_child_cb", G_CALLBACK(hdy_demo_window_notify_deck_visible_child_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "back_clicked_cb", G_CALLBACK(hdy_demo_window_back_clicked_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "deck_back_clicked_cb", G_CALLBACK(hdy_demo_window_deck_back_clicked_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "notify_leaflet_transition_cb", G_CALLBACK(notify_leaflet_transition_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "notify_deck_transition_cb", G_CALLBACK(notify_deck_transition_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "deck_go_next_row_activated_cb", G_CALLBACK(deck_go_next_row_activated_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "theme_variant_button_clicked_cb", G_CALLBACK(theme_variant_button_clicked_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "view_switcher_demo_clicked_cb", G_CALLBACK(view_switcher_demo_clicked_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "notify_carousel_orientation_cb", G_CALLBACK(notify_carousel_orientation_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "notify_carousel_indicators_cb", G_CALLBACK(notify_carousel_indicators_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "carousel_return_clicked_cb", G_CALLBACK(carousel_return_clicked_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "avatar_file_remove_cb", G_CALLBACK(avatar_file_remove_cb));
+ gtk_widget_class_bind_template_callback_full (widget_class, "avatar_file_set_cb", G_CALLBACK(avatar_file_set_cb));
+}
+
+static void
+lists_page_init (HdyDemoWindow *self)
+{
+ GListStore *list_store;
+ HdyValueObject *obj;
+
+ list_store = g_list_store_new (HDY_TYPE_VALUE_OBJECT);
+
+ obj = hdy_value_object_new_string ("Foo");
+ g_list_store_insert (list_store, 0, obj);
+ g_clear_object (&obj);
+
+ obj = hdy_value_object_new_string ("Bar");
+ g_list_store_insert (list_store, 1, obj);
+ g_clear_object (&obj);
+
+ obj = hdy_value_object_new_string ("Baz");
+ g_list_store_insert (list_store, 2, obj);
+ g_clear_object (&obj);
+
+ hdy_combo_row_bind_name_model (self->combo_row, G_LIST_MODEL (list_store), (HdyComboRowGetNameFunc) hdy_value_object_dup_string, NULL, NULL);
+
+ hdy_combo_row_set_for_enum (self->enum_combo_row, GTK_TYPE_LICENSE, hdy_enum_value_row_name, NULL, NULL);
+ update (self);
+}
+
+static void
+carousel_page_init (HdyDemoWindow *self)
+{
+ HdyValueObject *obj;
+
+ hdy_combo_row_set_for_enum (self->carousel_orientation_row,
+ GTK_TYPE_ORIENTATION,
+ carousel_orientation_name,
+ NULL,
+ NULL);
+
+ self->carousel_indicators_model = g_list_store_new (HDY_TYPE_VALUE_OBJECT);
+
+ obj = hdy_value_object_new_string ("dots");
+ g_list_store_insert (self->carousel_indicators_model, 0, obj);
+ g_clear_object (&obj);
+
+ obj = hdy_value_object_new_string ("lines");
+ g_list_store_insert (self->carousel_indicators_model, 1, obj);
+ g_clear_object (&obj);
+
+ hdy_combo_row_bind_name_model (self->carousel_indicators_row,
+ G_LIST_MODEL (self->carousel_indicators_model),
+ (HdyComboRowGetNameFunc) carousel_indicators_name,
+ NULL,
+ NULL);
+}
+
+static void
+avatar_page_init (HdyDemoWindow *self)
+{
+ g_autofree gchar *name = avatar_new_random_name ();
+
+ gtk_entry_set_text (self->avatar_text, name);
+
+ avatar_update_contacts (self);
+}
+
+static void
+hdy_demo_window_init (HdyDemoWindow *self)
+{
+ GtkSettings *settings = gtk_settings_get_default ();
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_object_bind_property_full (settings, "gtk-application-prefer-dark-theme",
+ self->theme_variant_image, "icon-name",
+ G_BINDING_SYNC_CREATE,
+ prefer_dark_theme_to_icon_name_cb,
+ NULL,
+ NULL,
+ NULL);
+
+ hdy_combo_row_set_for_enum (self->leaflet_transition_row, HDY_TYPE_LEAFLET_TRANSITION_TYPE, leaflet_transition_name, NULL, NULL);
+ hdy_combo_row_set_selected_index (self->leaflet_transition_row, HDY_LEAFLET_TRANSITION_TYPE_OVER);
+
+ hdy_combo_row_set_for_enum (self->deck_transition_row, HDY_TYPE_DECK_TRANSITION_TYPE, deck_transition_name, NULL, NULL);
+ hdy_combo_row_set_selected_index (self->deck_transition_row, HDY_DECK_TRANSITION_TYPE_OVER);
+
+ lists_page_init (self);
+ carousel_page_init (self);
+ avatar_page_init (self);
+
+ hdy_leaflet_set_visible_child_name (self->content_box, "content");
+}