[gnome-control-center/wip/feborges/new-users-panel: 7/10] user-accounts: Draw arrow in UmCarousel
- From: Felipe Borges <felipeborges src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/wip/feborges/new-users-panel: 7/10] user-accounts: Draw arrow in UmCarousel
- Date: Sun, 18 Dec 2016 14:08:40 +0000 (UTC)
commit 91925a3b16ecf6840332dc6f44f735eea1625630
Author: Felipe Borges <felipeborges gnome org>
Date: Sun Dec 18 13:57:03 2016 +0100
user-accounts: Draw arrow in UmCarousel
The arrow is drawn using CSS.
https://bugzilla.gnome.org/show_bug.cgi?id=767065
panels/user-accounts/data/carousel.css | 21 ++++
panels/user-accounts/data/carousel.ui | 95 +++++++++++++------
panels/user-accounts/um-carousel.c | 113 +++++++++++++++++++---
panels/user-accounts/user-accounts.gresource.xml | 1 +
4 files changed, 186 insertions(+), 44 deletions(-)
---
diff --git a/panels/user-accounts/data/carousel.css b/panels/user-accounts/data/carousel.css
new file mode 100644
index 0000000..a644c95
--- /dev/null
+++ b/panels/user-accounts/data/carousel.css
@@ -0,0 +1,21 @@
+.carousel-arrow-container {
+ border-bottom: 1px solid @borders;
+}
+
+.carousel-inner-arrow {
+ border-left: 26px solid transparent;
+ border-right: 26px solid transparent;
+ border-bottom: 26px solid @theme_bg_color;
+ margin-bottom: -8px;
+}
+
+.carousel-arrow {
+ background: linear-gradient(45deg, transparent 50%, #D9D9D7 50%),
+ linear-gradient(-45deg, transparent 50%, #D9D9D7 50%),
+ linear-gradient(to bottom, @borders, @borders);
+ animation-duration: 0.75s;
+ animation-timing-function: linear;
+ animation-fill-mode: forwards;
+ padding: 1px;
+ margin-top: -5px;
+}
diff --git a/panels/user-accounts/data/carousel.ui b/panels/user-accounts/data/carousel.ui
index dea8a69..b7e12d9 100644
--- a/panels/user-accounts/data/carousel.ui
+++ b/panels/user-accounts/data/carousel.ui
@@ -20,51 +20,86 @@
</object>
</child>
<child type="overlay">
- <object class="GtkBox">
+ <object class="GtkOverlay">
<property name="visible">True</property>
- <property name="orientation">horizontal</property>
- <property name="border_width">12</property>
<child>
- <object class="GtkButton" id="go_back_button">
- <property name="visible">False</property>
- <property name="can_focus">True</property>
- <property name="valign">center</property>
- <style>
- <class name="circular"/>
- </style>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <property name="border_width">12</property>
<child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon-size">4</property>
- <property name="icon_name">go-previous-symbolic</property>
+ <object class="GtkButton" id="go_back_button">
+ <property name="visible">False</property>
+ <property name="can_focus">True</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="circular"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-size">4</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ </object>
+ </child>
+ <signal name="clicked" handler="um_carousel_goto_previous_page" object="UmCarousel"
swapped="no"/>
</object>
+ <packing>
+ <property name="pack_type">GTK_PACK_START</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="go_next_button">
+ <property name="can_focus">True</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="circular"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon-size">4</property>
+ <property name="icon_name">go-next-symbolic</property>
+ </object>
+ </child>
+ <signal name="clicked" handler="um_carousel_goto_next_page" object="UmCarousel"
swapped="no"/>
+ </object>
+ <packing>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
</child>
- <signal name="clicked" handler="um_carousel_goto_previous_page" object="UmCarousel"
swapped="no"/>
</object>
- <packing>
- <property name="pack_type">start</property>
- </packing>
</child>
- <child>
- <object class="GtkButton" id="go_next_button">
- <property name="can_focus">True</property>
- <property name="valign">center</property>
+ <child type="overlay">
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="valign">GTK_ALIGN_END</property>
<style>
- <class name="circular"/>
+ <class name="carousel-arrow-container"/>
</style>
<child>
- <object class="GtkImage">
+ <object class="GtkBox" id="arrow">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon-size">4</property>
- <property name="icon_name">go-next-symbolic</property>
+ <property name="height-request">36</property>
+ <property name="halign">GTK_ALIGN_START</property>
+ <style>
+ <class name="carousel-arrow"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <style>
+ <class name="carousel-inner-arrow"/>
+ </style>
+ </object>
+ </child>
</object>
</child>
- <signal name="clicked" handler="um_carousel_goto_next_page" object="UmCarousel"
swapped="no"/>
</object>
<packing>
- <property name="pack_type">end</property>
+ <property name="pass-through">True</property>
</packing>
</child>
</object>
diff --git a/panels/user-accounts/um-carousel.c b/panels/user-accounts/um-carousel.c
index d2ba85d..32e74cc 100644
--- a/panels/user-accounts/um-carousel.c
+++ b/panels/user-accounts/um-carousel.c
@@ -23,6 +23,8 @@
#include <glib-object.h>
#include <gtk/gtk.h>
+#define ARROW_WIDTH 28
+
struct _UmCarouselItem {
GtkToggleButton parent;
@@ -53,12 +55,16 @@ struct _UmCarousel {
GList *children;
gint visible_page;
UmCarouselItem *selected_item;
+ gint arrow_start_x;
GtkWidget *last_box;
+ GtkWidget *arrow;
/* Widgets */
GtkStack *stack;
GtkWidget *go_back_button;
GtkWidget *go_next_button;
+
+ GtkStyleProvider *provider;
};
G_DEFINE_TYPE (UmCarousel, um_carousel, GTK_TYPE_REVEALER)
@@ -73,6 +79,62 @@ static guint signals[NUM_SIGNALS] = { 0, };
#define ITEMS_PER_PAGE 3
static gint
+um_carousel_item_get_x (UmCarouselItem *item,
+ UmCarousel *carousel)
+{
+ GtkWidget *widget, *parent;
+ gint width;
+ gint dest_x;
+
+ parent = GTK_WIDGET (carousel->stack);
+ widget = GTK_WIDGET (item);
+
+ width = gtk_widget_get_allocated_width (widget);
+ gtk_widget_translate_coordinates (widget,
+ parent,
+ width / 2,
+ 0,
+ &dest_x,
+ NULL);
+
+ return CLAMP (dest_x - ARROW_WIDTH,
+ 0,
+ gtk_widget_get_allocated_width (parent));
+}
+
+static void
+um_carousel_move_arrow (UmCarousel *self)
+{
+ GtkStyleContext *context;
+ gchar *css;
+ gint end_x;
+
+ if (!self->selected_item)
+ return;
+
+ end_x = um_carousel_item_get_x (self->selected_item, self);
+
+ context = gtk_widget_get_style_context (self->arrow);
+ if (self->provider)
+ gtk_style_context_remove_provider (context, self->provider);
+ g_clear_object (&self->provider);
+
+ css = g_strdup_printf ("@keyframes arrow_keyframes-%d {\n"
+ " from { margin-left: %dpx; }\n"
+ " to { margin-left: %dpx; }\n"
+ "}\n"
+ "* {\n"
+ " animation-name: arrow_keyframes-%d;\n"
+ "}\n", end_x, self->arrow_start_x, end_x, end_x);
+
+ self->provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+ gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (self->provider), css, -1, NULL);
+ gtk_style_context_add_provider (context, self->provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ g_free (css);
+}
+
+static gint
get_last_page_number (UmCarousel *self)
{
if (g_list_length (self->children) == 0)
@@ -120,15 +182,29 @@ um_carousel_find_item (UmCarousel *self,
return NULL;
}
+static void
+on_item_toggled (UmCarouselItem *item,
+ gpointer user_data)
+{
+ UmCarousel *self = UM_CAROUSEL (user_data);
+
+ if (self->selected_item != NULL)
+ self->arrow_start_x = um_carousel_item_get_x (self->selected_item, self);
+
+ self->selected_item = item;
+
+ g_signal_emit (user_data, signals[ITEM_ACTIVATED], 0, item);
+
+ um_carousel_move_arrow (self);
+}
+
void
um_carousel_select_item (UmCarousel *self,
UmCarouselItem *item)
{
gchar *page_name;
- self->selected_item = item;
-
- g_signal_emit (self, signals[ITEM_ACTIVATED], 0, self->selected_item);
+ on_item_toggled (item, self);
self->visible_page = item->page;
page_name = g_strdup_printf ("%d", self->visible_page);
@@ -181,17 +257,6 @@ um_carousel_goto_next_page (GtkWidget *button,
}
static void
-on_item_toggled (UmCarouselItem *item,
- gpointer user_data)
-{
- UmCarousel *self = UM_CAROUSEL (user_data);
-
- self->selected_item = item;
-
- g_signal_emit (user_data, signals[ITEM_ACTIVATED], 0, item);
-}
-
-static void
um_carousel_add (GtkContainer *container,
GtkWidget *widget)
{
@@ -224,6 +289,10 @@ um_carousel_add (GtkContainer *container,
gtk_widget_show_all (self->last_box);
update_buttons_visibility (self);
+
+ /* If there's only one child, select it. */
+ if (self->children->next == NULL)
+ um_carousel_select_item_at_index (self, 0);
}
void
@@ -236,6 +305,7 @@ um_carousel_purge_items (UmCarousel *self)
g_list_free (self->children);
self->children = NULL;
self->visible_page = 0;
+ self->selected_item = NULL;
}
UmCarousel *
@@ -256,6 +326,7 @@ um_carousel_class_init (UmCarouselClass *klass)
gtk_widget_class_bind_template_child (wclass, UmCarousel, stack);
gtk_widget_class_bind_template_child (wclass, UmCarousel, go_back_button);
gtk_widget_class_bind_template_child (wclass, UmCarousel, go_next_button);
+ gtk_widget_class_bind_template_child (wclass, UmCarousel, arrow);
gtk_widget_class_bind_template_callback (wclass, um_carousel_goto_previous_page);
gtk_widget_class_bind_template_callback (wclass, um_carousel_goto_next_page);
@@ -275,5 +346,19 @@ um_carousel_class_init (UmCarouselClass *klass)
static void
um_carousel_init (UmCarousel *self)
{
+ GtkStyleProvider *provider;
+
gtk_widget_init_template (GTK_WIDGET (self));
+
+ provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+ gtk_css_provider_load_from_resource (GTK_CSS_PROVIDER (provider),
+ "/org/gnome/control-center/user-accounts/carousel.css");
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ provider,
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ g_object_unref (provider);
+
+ g_signal_connect_swapped (self->stack, "size-allocate", G_CALLBACK (um_carousel_move_arrow), self);
}
diff --git a/panels/user-accounts/user-accounts.gresource.xml
b/panels/user-accounts/user-accounts.gresource.xml
index 4bedc2d..fd960bc 100644
--- a/panels/user-accounts/user-accounts.gresource.xml
+++ b/panels/user-accounts/user-accounts.gresource.xml
@@ -8,6 +8,7 @@
<file alias="history-dialog.ui" preprocess="xml-stripblanks">data/history-dialog.ui</file>
<file alias="user-accounts-dialog.ui" preprocess="xml-stripblanks">data/user-accounts-dialog.ui</file>
<file alias="carousel.ui" preprocess="xml-stripblanks">data/carousel.ui</file>
+ <file alias="carousel.css">data/carousel.css</file>
<file alias="left-index-finger.png">data/icons/left-index-finger.png</file>
<file alias="left-middle-finger.png">data/icons/left-middle-finger.png</file>
<file alias="left-little-finger.png">data/icons/left-little-finger.png</file>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]