[gnome-software/wip/hughsie/banner-next-gen] Implement the new featured banner carousel design
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/wip/hughsie/banner-next-gen] Implement the new featured banner carousel design
- Date: Tue, 16 Jul 2019 13:44:57 +0000 (UTC)
commit 2395a907e628078d686b60dd4b6f10f61e9dd5b7
Author: Richard Hughes <richard hughsie com>
Date: Tue Jul 16 14:44:05 2019 +0100
Implement the new featured banner carousel design
Fixes https://gitlab.gnome.org/GNOME/gnome-software/issues/425
src/gs-overview-page.c | 121 ++++++++++++++++++++++--------------------------
src/gs-overview-page.ui | 73 +++++++++++++++++++++++------
src/gtk-style.css | 19 ++++++++
3 files changed, 134 insertions(+), 79 deletions(-)
---
diff --git a/src/gs-overview-page.c b/src/gs-overview-page.c
index d6371c20..ad3f24ce 100644
--- a/src/gs-overview-page.c
+++ b/src/gs-overview-page.c
@@ -48,7 +48,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 +348,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 +372,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 +416,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 +424,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 +459,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 +478,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 +972,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 +1040,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 7097cd2d..78e3583c 100644
--- a/src/gs-overview-page.ui
+++ b/src/gs-overview-page.ui
@@ -92,23 +92,70 @@
</object>
</child>
<child>
- <object class="GtkStack" id="stack_featured">
+ <object class="GtkOverlay" id="overlay">
<property name="visible">True</property>
<property name="halign">fill</property>
- <property name="transition-type">crossfade</property>
+ <property name="valign">fill</property>
+ <property name="height-request">150</property>
+ <child type="overlay">
+ <object class="GtkStack" id="stack_featured">
+ <property name="visible">True</property>
+ <property name="halign">fill</property>
+ <property name="transition-type">crossfade</property>
+ </object>
+ </child>
+ <child type="overlay">
+ <object class="GtkButton" id="button_featured_back">
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="button_featured_back_accessible">
+ <property name="accessible-name" translatable="yes">Previous</property>
+ </object>
+ </child>
+ <style>
+ <class name="featured-button"/>
+ <class name="featured-button-left"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="back_image">
+ <property name="visible">True</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="overlay">
+ <object class="GtkButton" id="button_featured_forwards">
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="button_featured_forwards_accessible">
+ <property name="accessible-name" translatable="yes">Next</property>
+ </object>
+ </child>
+ <style>
+ <class name="featured-button"/>
+ <class name="featured-button-right"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="forwards_image">
+ <property name="visible">True</property>
+ <property name="icon_name">go-next-symbolic</property>
+ <property name="icon_size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
</child>
- <child>
- <object class="GtkBox" id="box_featured_switcher">
- <property name="visible">False</property>
- <property name="halign">center</property>
- <property name="homogeneous">True</property>
- <property name="orientation">horizontal</property>
- <property name="spacing">18</property>
- <property name="margin-top">6</property>
- </object>
- </child>
-
<child>
<object class="GtkLabel" id="category_heading">
<property name="visible">True</property>
diff --git a/src/gtk-style.css b/src/gtk-style.css
index 8e4d2793..e7a80354 100644
--- a/src/gtk-style.css
+++ b/src/gtk-style.css
@@ -524,3 +524,22 @@ flowboxchild {
.switcher-label {
opacity: 0.5;
}
+
+.featured-button {
+ background-image: none;
+ background-color: shade(@theme_bg_color, 0.8);
+ color: @theme_selected_fg_color;
+ opacity: 0.8;
+ border-radius: 60px;
+ box-shadow: none
+}
+
+.featured-button-left {
+ margin-left: -20px;
+ padding: 10px 10px 10px 20px;
+}
+
+.featured-button-right {
+ margin-right: -20px;
+ padding: 10px 20px 10px 10px;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]