From d1f68790d336196fe6267acd291eb1934542d337 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Tue, 16 Jul 2019 14:44:05 +0100 Subject: [PATCH] Implement the new featured banner carousel design Fixes https://gitlab.gnome.org/GNOME/gnome-software/issues/425 --- src/gs-overview-page.c | 123 ++++++++++++++++++---------------------- src/gs-overview-page.ui | 73 +++++++++++++++++++----- src/gtk-style.css | 12 ++++ 3 files changed, 127 insertions(+), 81 deletions(-) diff --git a/src/gs-overview-page.c b/src/gs-overview-page.c index d6371c20f..d522cf86c 100644 --- a/src/gs-overview-page.c +++ b/src/gs-overview-page.c @@ -22,8 +22,6 @@ #define N_TILES 9 #define FEATURED_ROTATE_TIME 30 /* seconds */ -#define FEATURED_SWITCHER_ACTIVE_TEXT "●" -#define FEATURED_SWITCHER_INACTIVE_TEXT "○" typedef struct { @@ -48,7 +46,8 @@ typedef struct GtkWidget *infobar_third_party; GtkWidget *label_third_party; GtkWidget *stack_featured; - GtkWidget *box_featured_switcher; + GtkWidget *button_featured_back; + GtkWidget *button_featured_forwards; GtkWidget *box_overview; GtkWidget *box_popular; GtkWidget *box_popular_rotating; @@ -347,22 +346,19 @@ out: gs_overview_page_decrement_action_cnt (self); } -static gboolean -gs_overview_page_featured_rotate_cb (gpointer user_data) +static void +_feature_banner_forward (GsOverviewPage *self) { - GsOverviewPage *self = GS_OVERVIEW_PAGE (user_data); GsOverviewPagePrivate *priv = gs_overview_page_get_instance_private (self); GtkWidget *visible_child; GtkWidget *next_child = NULL; - GList *button_link; GList *banner_link; g_autoptr(GList) banners = NULL; - g_autoptr(GList) buttons = NULL; visible_child = gtk_stack_get_visible_child (GTK_STACK (priv->stack_featured)); banners = gtk_container_get_children (GTK_CONTAINER (priv->stack_featured)); if (banners == NULL) - return G_SOURCE_CONTINUE; + return; /* find banner after the currently visible one */ for (banner_link = banners; banner_link != NULL; banner_link = banner_link->next) { @@ -374,24 +370,43 @@ gs_overview_page_featured_rotate_cb (gpointer user_data) } } if (next_child == NULL) - next_child = g_list_nth_data (banners, 0); - + next_child = g_list_first(banners)->data; gtk_stack_set_visible_child (GTK_STACK (priv->stack_featured), next_child); +} + +static void +_feature_banner_back (GsOverviewPage *self) +{ + GsOverviewPagePrivate *priv = gs_overview_page_get_instance_private (self); + GtkWidget *visible_child; + GtkWidget *next_child = NULL; + GList *banner_link; + g_autoptr(GList) banners = NULL; + + visible_child = gtk_stack_get_visible_child (GTK_STACK (priv->stack_featured)); + banners = gtk_container_get_children (GTK_CONTAINER (priv->stack_featured)); + if (banners == NULL) + return; - /* update switcher */ - buttons = gtk_container_get_children (GTK_CONTAINER (priv->box_featured_switcher)); - for (banner_link = banners, button_link = buttons; - banner_link != NULL && button_link != NULL; - banner_link = banner_link->next, button_link = button_link->next) { - GtkWidget *event_box = button_link->data, *label; - - label = gtk_bin_get_child (GTK_BIN (event_box)); - if (banner_link->data == next_child) - gtk_label_set_label (GTK_LABEL (label), FEATURED_SWITCHER_ACTIVE_TEXT); - else - gtk_label_set_label (GTK_LABEL (label), FEATURED_SWITCHER_INACTIVE_TEXT); + /* find banner before the currently visible one */ + for (banner_link = banners; banner_link != NULL; banner_link = banner_link->next) { + GtkWidget *child = banner_link->data; + if (child == visible_child) { + if (banner_link->prev != NULL) + next_child = banner_link->prev->data; + break; + } } + if (next_child == NULL) + next_child = g_list_last(banners)->data; + gtk_stack_set_visible_child (GTK_STACK (priv->stack_featured), next_child); +} +static gboolean +gs_overview_page_featured_rotate_cb (gpointer user_data) +{ + GsOverviewPage *self = GS_OVERVIEW_PAGE (user_data); + _feature_banner_forward (self); return G_SOURCE_CONTINUE; } @@ -399,7 +414,6 @@ static void featured_reset_rotate_timer (GsOverviewPage *self) { GsOverviewPagePrivate *priv = gs_overview_page_get_instance_private (self); - if (priv->featured_rotate_timer_id != 0) g_source_remove (priv->featured_rotate_timer_id); priv->featured_rotate_timer_id = g_timeout_add_seconds (FEATURED_ROTATE_TIME, @@ -408,31 +422,17 @@ featured_reset_rotate_timer (GsOverviewPage *self) } static void -featured_switcher_clicked (GtkWidget *event_box, GdkEventButton *event, gpointer data) +_featured_back_clicked_cb (GsCategoryTile *tile, gpointer data) { GsOverviewPage *self = GS_OVERVIEW_PAGE (data); - GsOverviewPagePrivate *priv = gs_overview_page_get_instance_private (self); - g_autoptr(GList) buttons = NULL; - g_autoptr(GList) banners = NULL; - GList *button_link, *banner_link; + _feature_banner_back (self); +} - buttons = gtk_container_get_children (GTK_CONTAINER (priv->box_featured_switcher)); - banners = gtk_container_get_children (GTK_CONTAINER (priv->stack_featured)); - for (button_link = buttons, banner_link = banners; - button_link != NULL && banner_link != NULL; - button_link = button_link->next, banner_link = banner_link->next) { - GtkWidget *e = button_link->data; - GtkWidget *label; - - label = gtk_bin_get_child (GTK_BIN (e)); - if (e == event_box) { - gtk_stack_set_visible_child (GTK_STACK (priv->stack_featured), banner_link->data); - featured_reset_rotate_timer (self); - gtk_label_set_label (GTK_LABEL (label), FEATURED_SWITCHER_ACTIVE_TEXT); - } else { - gtk_label_set_label (GTK_LABEL (label), FEATURED_SWITCHER_INACTIVE_TEXT); - } - } +static void +_featured_forward_clicked_cb (GsCategoryTile *tile, gpointer data) +{ + GsOverviewPage *self = GS_OVERVIEW_PAGE (data); + _feature_banner_forward (self); } static void @@ -457,8 +457,6 @@ gs_overview_page_get_featured_cb (GObject *source_object, gtk_widget_hide (priv->featured_heading); gs_container_remove_all (GTK_CONTAINER (priv->stack_featured)); - gtk_widget_hide (priv->box_featured_switcher); - gs_container_remove_all (GTK_CONTAINER (priv->box_featured_switcher)); if (list == NULL) { g_warning ("failed to get featured apps: %s", error->message); @@ -478,31 +476,13 @@ gs_overview_page_get_featured_cb (GObject *source_object, } for (guint i = 0; i < gs_app_list_length (list); i++) { GsApp *app = gs_app_list_index (list, i); - GtkWidget *event_box; - GtkWidget *label; - GtkWidget *tile; - - tile = gs_feature_tile_new (app); + GtkWidget *tile = gs_feature_tile_new (app); g_signal_connect (tile, "clicked", G_CALLBACK (app_tile_clicked), self); gtk_container_add (GTK_CONTAINER (priv->stack_featured), tile); - - event_box = gtk_event_box_new (); - gtk_widget_show (event_box); - g_signal_connect (event_box, "button_release_event", - G_CALLBACK (featured_switcher_clicked), self); - gtk_container_add (GTK_CONTAINER (priv->box_featured_switcher), event_box); - - label = gtk_label_new (i == 0 ? FEATURED_SWITCHER_ACTIVE_TEXT : FEATURED_SWITCHER_INACTIVE_TEXT); - gtk_style_context_add_class (gtk_widget_get_style_context (label), - "switcher-label"); - gtk_widget_show (label); - gtk_container_add (GTK_CONTAINER (event_box), label); } gtk_widget_show (priv->featured_heading); - gtk_widget_set_visible (priv->box_featured_switcher, gs_app_list_length (list) > 1); - priv->empty = FALSE; featured_reset_rotate_timer (self); @@ -990,6 +970,12 @@ gs_overview_page_init (GsOverviewPage *self) { GsOverviewPagePrivate *priv = gs_overview_page_get_instance_private (self); gtk_widget_init_template (GTK_WIDGET (self)); + + g_signal_connect (priv->button_featured_back, "clicked", + G_CALLBACK (_featured_back_clicked_cb), self); + g_signal_connect (priv->button_featured_forwards, "clicked", + G_CALLBACK (_featured_forward_clicked_cb), self); + priv->settings = g_settings_new ("org.gnome.software"); } @@ -1052,7 +1038,8 @@ gs_overview_page_class_init (GsOverviewPageClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GsOverviewPage, infobar_third_party); gtk_widget_class_bind_template_child_private (widget_class, GsOverviewPage, label_third_party); gtk_widget_class_bind_template_child_private (widget_class, GsOverviewPage, stack_featured); - gtk_widget_class_bind_template_child_private (widget_class, GsOverviewPage, box_featured_switcher); + gtk_widget_class_bind_template_child_private (widget_class, GsOverviewPage, button_featured_back); + gtk_widget_class_bind_template_child_private (widget_class, GsOverviewPage, button_featured_forwards); gtk_widget_class_bind_template_child_private (widget_class, GsOverviewPage, box_overview); gtk_widget_class_bind_template_child_private (widget_class, GsOverviewPage, box_popular); gtk_widget_class_bind_template_child_private (widget_class, GsOverviewPage, box_popular_rotating); diff --git a/src/gs-overview-page.ui b/src/gs-overview-page.ui index 7097cd2d0..612283f37 100644 --- a/src/gs-overview-page.ui +++ b/src/gs-overview-page.ui @@ -92,23 +92,70 @@ - + True fill - crossfade + fill + 150 + + + True + fill + crossfade + + + + + True + True + True + start + center + + + Previous + + + + + + True + go-previous-symbolic + 1 + + + + + + + True + True + True + end + center + + + Next + + + + + + True + go-next-symbolic + 1 + + + + - - - False - center - True - horizontal - 18 - 6 - - - True diff --git a/src/gtk-style.css b/src/gtk-style.css index 8e4d27939..754749784 100644 --- a/src/gtk-style.css +++ b/src/gtk-style.css @@ -524,3 +524,15 @@ flowboxchild { .switcher-label { opacity: 0.5; } + +.featured-button-left { + border-radius: 60px; + margin-left: -25px; + padding: 10px 5px 10px 20px; +} + +.featured-button-right { + border-radius: 60px; + margin-right: -25px; + padding: 10px 20px 10px 5px; +} -- GitLab