[gnome-control-center/wip/feborges/new-users-panel: 17/18] user-accounts: Introduce arrow frame (UmArrowFrame)
- From: Felipe Borges <felipeborges src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/wip/feborges/new-users-panel: 17/18] user-accounts: Introduce arrow frame (UmArrowFrame)
- Date: Mon, 11 Jul 2016 12:53:47 +0000 (UTC)
commit eb9994258200ab60b14713451afee55a0f3481ef
Author: Felipe Borges <felipeborges gnome org>
Date: Fri Jul 8 12:46:11 2016 +0200
user-accounts: Introduce arrow frame (UmArrowFrame)
Type of GtkFrame which points to an item in an UmCarousel.
panels/user-accounts/Makefile.am | 2 +
panels/user-accounts/data/carousel.ui | 3 +-
panels/user-accounts/data/user-accounts-dialog.ui | 7 +-
panels/user-accounts/um-arrow-frame.c | 450 +++++++++++++++++++++
panels/user-accounts/um-arrow-frame.h | 41 ++
panels/user-accounts/um-carousel.c | 2 +-
panels/user-accounts/um-user-panel.c | 5 +
7 files changed, 505 insertions(+), 5 deletions(-)
---
diff --git a/panels/user-accounts/Makefile.am b/panels/user-accounts/Makefile.am
index c77359d..68dcfd9 100644
--- a/panels/user-accounts/Makefile.am
+++ b/panels/user-accounts/Makefile.am
@@ -50,6 +50,8 @@ libuser_accounts_la_SOURCES = \
run-passwd.c \
um-carousel.h \
um-carousel.c \
+ um-arrow-frame.h \
+ um-arrow-frame.c \
um-editable-button.h \
um-editable-button.c \
um-editable-combo.h \
diff --git a/panels/user-accounts/data/carousel.ui b/panels/user-accounts/data/carousel.ui
index 56a0e37..6082900 100644
--- a/panels/user-accounts/data/carousel.ui
+++ b/panels/user-accounts/data/carousel.ui
@@ -3,11 +3,12 @@
<!-- interface-requires gtk+ 3.8 -->
<template class="UmCarousel" parent="GtkGrid">
<property name="visible">True</property>
+ <property name="valign">start</property>
<child>
<object class="GtkOverlay">
<property name="visible">True</property>
<property name="expand">True</property>
- <property name="border_width">15</property>
+ <property name="border_width">30</property>
<child>
<object class="GtkStack" id="stack">
<property name="visible">True</property>
diff --git a/panels/user-accounts/data/user-accounts-dialog.ui
b/panels/user-accounts/data/user-accounts-dialog.ui
index 800af5a..59f402c 100644
--- a/panels/user-accounts/data/user-accounts-dialog.ui
+++ b/panels/user-accounts/data/user-accounts-dialog.ui
@@ -20,8 +20,6 @@
<child>
<object class="GtkVBox" id="accounts-vbox">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="border_width">0</property>
<child>
<object class="UmCarousel" id="carousel">
<property name="visible">True</property>
@@ -29,8 +27,11 @@
</object>
</child>
<child>
- <object class="GtkFrame" id="hbox2">
+ <object class="UmArrowFrame" id="arrow_frame">
<property name="visible">True</property>
+ <style>
+ <class name="background"/>
+ </style>
<child>
<object class="GtkVBox" id="main-user-vbox">
<property name="visible">True</property>
diff --git a/panels/user-accounts/um-arrow-frame.c b/panels/user-accounts/um-arrow-frame.c
new file mode 100644
index 0000000..742d08c
--- /dev/null
+++ b/panels/user-accounts/um-arrow-frame.c
@@ -0,0 +1,450 @@
+/* um-arrow-frame.c
+ *
+ * Copyright (C) 2016 Red Hat, Inc,
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Writen by: Felipe Borges <felipeborges gnome org>,
+ * Georges Basile Stavracas Neto <georges stavracas gmail com>
+ */
+
+#include "um-arrow-frame.h"
+
+#define ARROW_HEIGHT 16
+#define ARROW_WIDTH 36
+#define HANDLE_GAP (ARROW_HEIGHT + 5)
+
+typedef struct {
+ UmCarousel *carousel;
+ GtkWidget *item;
+
+ GdkWindow *handle_window;
+ gdouble offset;
+ gint margin_top;
+} UmArrowFramePrivate;
+
+struct _UmArrowFrame {
+ GtkFrame parent;
+
+ UmArrowFramePrivate *priv;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (UmArrowFrame, um_arrow_frame, GTK_TYPE_FRAME)
+
+GtkWidget*
+um_arrow_frame_new (void)
+{
+ return g_object_new (UM_TYPE_ARROW_FRAME, NULL);
+}
+
+static void
+um_arrow_frame_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (um_arrow_frame_parent_class)->finalize (object);
+}
+
+static void um_arrow_frame_set_item (UmCarousel *carousel, GtkToggleButton *item, UmArrowFrame *frame);
+
+static void
+item_destroyed (UmArrowFrame *frame)
+{
+ um_arrow_frame_set_carousel (frame, NULL);
+}
+
+static gint
+um_arrow_frame__get_row_x (UmArrowFrame *frame)
+{
+ GtkWidget *widget;
+ GtkWidget *row;
+ gint row_width;
+ gint dest_x;
+
+ widget = GTK_WIDGET (frame);
+
+ if (!frame->priv->item)
+ return gtk_widget_get_allocated_width (widget) / 2;
+
+ row = GTK_WIDGET (frame->priv->item);
+ row_width = gtk_widget_get_allocated_width (row);
+
+ gtk_widget_translate_coordinates (row,
+ widget,
+ row_width / 2,
+ 0,
+ &dest_x,
+ NULL);
+
+ return CLAMP (dest_x,
+ 0,
+ gtk_widget_get_allocated_width (widget));
+}
+
+static void
+um_arrow_frame__draw_arrow (UmArrowFrame *frame,
+ cairo_t *cr)
+{
+ GtkWidget *widget = GTK_WIDGET (frame);
+ GtkStyleContext *context;
+ GtkAllocation alloc;
+ GtkStateFlags state;
+ GtkBorder border;
+ GdkRGBA border_color;
+ gint border_width;
+ gint start_x;
+ gint start_y;
+ gint tip_x;
+ gint tip_y;
+ gint end_x;
+ gint end_y;
+
+ context = gtk_widget_get_style_context (widget);
+ state = gtk_style_context_get_state (context);
+
+ gtk_style_context_get_border (context,
+ state,
+ &border);
+
+ gtk_style_context_get (context,
+ state,
+ GTK_STYLE_PROPERTY_BORDER_COLOR, &border_color,
+ NULL);
+
+ /* widget size */
+ gtk_widget_get_allocation (widget, &alloc);
+
+ tip_x = um_arrow_frame__get_row_x (frame);
+ start_x = tip_x - (ARROW_WIDTH / 2);
+ end_x = tip_x + (ARROW_WIDTH / 2);
+
+ start_y = end_y = border.top + ARROW_HEIGHT;
+ tip_y = 0;
+ border_width = border.top;
+
+ /* draw arrow */
+ cairo_save (cr);
+
+ cairo_set_line_width (cr, 1.0);
+ cairo_move_to (cr, start_x, start_y);
+ cairo_line_to (cr, tip_x, tip_y);
+ cairo_line_to (cr, end_x, end_y);
+
+ /*
+ * Don't allow that gtk_render_background renders
+ * anything out of (tip_x, start_y) (end_x, end_y).
+ */
+ cairo_clip (cr);
+
+ /* render the arrow background */
+ gtk_render_background (context,
+ cr,
+ 0,
+ 0,
+ alloc.width,
+ alloc.height);
+
+ /* draw the border */
+ if (border_width > 0)
+ {
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+ gtk_style_context_get_border_color (context,
+ state,
+ &border_color);
+
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+ gdk_cairo_set_source_rgba (cr, &border_color);
+
+ cairo_set_line_width (cr, 1);
+ cairo_move_to (cr, start_x, start_y);
+ cairo_line_to (cr, tip_x, tip_y);
+ cairo_line_to (cr, end_x, end_y);
+
+ cairo_set_line_width (cr, border_width + 1);
+ cairo_stroke (cr);
+ }
+
+ cairo_restore (cr);
+}
+
+static void
+um_arrow_frame__draw_background (UmArrowFrame *frame,
+ cairo_t *cr)
+{
+ GtkWidget *widget = GTK_WIDGET (frame);
+ GtkStyleContext *context;
+ GtkAllocation alloc;
+ GtkStateFlags state;
+ GtkBorder margin;
+ gint start_x;
+ gint start_y;
+ gint start_gap;
+ gint end_x;
+ gint end_y;
+ gint end_gap;
+
+ context = gtk_widget_get_style_context (widget);
+ state = gtk_style_context_get_state (context);
+
+ /* widget size */
+ gtk_widget_get_allocation (widget, &alloc);
+
+ /* margin */
+ gtk_style_context_get_margin (context,
+ state,
+ &margin);
+
+ start_x = margin.left;
+ end_x = alloc.width + margin.right;
+
+ start_y = margin.top + ARROW_HEIGHT;
+ end_y = alloc.height - margin.bottom;
+
+ start_gap = ((end_y - start_y + ARROW_WIDTH) / 2);
+ end_gap = ((end_y - start_y + ARROW_WIDTH) / 2);
+
+ gtk_render_background (context,
+ cr,
+ start_x,
+ start_y,
+ end_x,
+ end_y);
+
+ gtk_render_frame_gap (context,
+ cr,
+ start_x,
+ start_y,
+ end_x,
+ end_y,
+ GTK_POS_TOP,
+ start_gap,
+ end_gap);
+
+}
+
+static gboolean
+um_arrow_frame_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ UmArrowFrame *frame = UM_ARROW_FRAME (widget);
+ GtkWidget *child;
+
+ um_arrow_frame__draw_background (frame, cr);
+ um_arrow_frame__draw_arrow (frame, cr);
+
+ child = gtk_bin_get_child (GTK_BIN (widget));
+
+ if (child)
+ {
+ gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr);
+ }
+
+ return TRUE;
+}
+
+static void
+um_arrow_frame_compute_child_allocation (GtkFrame *frame,
+ GtkAllocation *allocation)
+{
+ UmArrowFramePrivate *priv;
+
+ GTK_FRAME_CLASS (um_arrow_frame_parent_class)->compute_child_allocation (frame, allocation);
+
+ priv = UM_ARROW_FRAME (frame)->priv;
+}
+
+static void
+um_arrow_frame_get_preferred_height (GtkWidget *widget,
+ gint *minimum_height,
+ gint *natural_height)
+{
+ UmArrowFramePrivate *priv;
+
+ priv = UM_ARROW_FRAME (widget)->priv;
+
+ GTK_WIDGET_CLASS (um_arrow_frame_parent_class)->get_preferred_height (widget,
+ minimum_height,
+ natural_height);
+
+ *minimum_height += ARROW_HEIGHT;
+ *natural_height += ARROW_HEIGHT;
+
+ *natural_height = MAX (*minimum_height, *natural_height + priv->offset);
+}
+
+static void
+um_arrow_frame_realize (GtkWidget *widget)
+{
+ UmArrowFramePrivate *priv;
+ GtkAllocation allocation;
+ GdkWindowAttr attributes = { 0 };
+ GdkDisplay *display;
+ GdkWindow *parent_window;
+ gint attributes_mask;
+
+ priv = UM_ARROW_FRAME (widget)->priv;
+ display = gtk_widget_get_display (widget);
+ parent_window = gtk_widget_get_parent_window (widget);
+
+ gtk_widget_set_realized (widget, TRUE);
+
+ gtk_widget_set_window (widget, parent_window);
+ g_object_ref (parent_window);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_ONLY;
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.cursor = gdk_cursor_new_for_display (display, GDK_SB_H_DOUBLE_ARROW);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_POINTER_MOTION_MASK);
+
+ attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
+
+ priv->handle_window = gdk_window_new (parent_window,
+ &attributes,
+ attributes_mask);
+
+ gtk_widget_register_window (widget, priv->handle_window);
+
+ g_clear_object (&attributes.cursor);
+}
+
+static void
+um_arrow_frame_unrealize (GtkWidget *widget)
+{
+ UmArrowFramePrivate *priv;
+
+ priv = UM_ARROW_FRAME (widget)->priv;
+
+ if (priv->handle_window)
+ {
+ gdk_window_hide (priv->handle_window);
+ gtk_widget_unregister_window (widget, priv->handle_window);
+ g_clear_pointer (&priv->handle_window, gdk_window_destroy);
+ }
+
+ GTK_WIDGET_CLASS (um_arrow_frame_parent_class)->unrealize (widget);
+}
+
+static void
+um_arrow_frame_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ UmArrowFramePrivate *priv;
+
+ priv = UM_ARROW_FRAME (widget)->priv;
+
+ GTK_WIDGET_CLASS (um_arrow_frame_parent_class)->size_allocate (widget, allocation);
+
+ allocation->y = priv->margin_top - ARROW_HEIGHT;
+ gtk_widget_set_allocation (widget, allocation);
+
+ if (gtk_widget_get_realized (widget))
+ {
+ gdk_window_move_resize (priv->handle_window,
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+
+ gdk_window_raise (priv->handle_window);
+ }
+}
+
+static void
+um_arrow_frame_class_init (UmArrowFrameClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkFrameClass *frame_class = GTK_FRAME_CLASS (klass);
+
+ object_class->finalize = um_arrow_frame_finalize;
+
+ widget_class->draw = um_arrow_frame_draw;
+ widget_class->get_preferred_height = um_arrow_frame_get_preferred_height;
+ widget_class->realize = um_arrow_frame_realize;
+ widget_class->unrealize = um_arrow_frame_unrealize;
+ widget_class->size_allocate = um_arrow_frame_size_allocate;
+
+ frame_class->compute_child_allocation = um_arrow_frame_compute_child_allocation;
+
+ gtk_widget_class_set_css_name (widget_class, "arrow-frame");
+}
+
+static void
+um_arrow_frame_init (UmArrowFrame *self)
+{
+ GtkStyleProvider *provider;
+
+ self->priv = um_arrow_frame_get_instance_private (self);
+
+ provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+ gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider), "* {border-top: solid 1px; border-color:
@borders }", -1, NULL);
+ gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (self)),
+ provider,
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ g_object_unref (provider);
+}
+
+static void
+um_arrow_frame_set_item (UmCarousel *carousel,
+ GtkToggleButton *item,
+ UmArrowFrame *frame)
+{
+ g_return_if_fail (UM_IS_ARROW_FRAME (frame));
+
+ if (frame->priv->item) {
+ g_signal_handlers_disconnect_by_func (frame->priv->item, item_destroyed, frame);
+ }
+
+ frame->priv->item = GTK_WIDGET (item);
+
+ if (item) {
+ g_signal_connect_swapped (item, "destroy", G_CALLBACK (item_destroyed), frame);
+
+ gtk_widget_queue_draw (GTK_WIDGET (frame));
+ }
+}
+
+static void
+um_arrow_frame_set_margin_top (GtkWidget *widget,
+ GtkAllocation *allocation,
+ UmArrowFrame *frame)
+{
+ frame->priv->margin_top = allocation->height;
+}
+
+void
+um_arrow_frame_set_carousel (UmArrowFrame *frame,
+ UmCarousel *carousel)
+{
+ if (carousel == NULL)
+ return;
+
+ frame->priv->carousel = carousel;
+
+ g_signal_connect (carousel, "size-allocate", G_CALLBACK (um_arrow_frame_set_margin_top), frame);
+ g_signal_connect (carousel, "item-activated", G_CALLBACK (um_arrow_frame_set_item), frame);
+}
diff --git a/panels/user-accounts/um-arrow-frame.h b/panels/user-accounts/um-arrow-frame.h
new file mode 100644
index 0000000..090cc02
--- /dev/null
+++ b/panels/user-accounts/um-arrow-frame.h
@@ -0,0 +1,41 @@
+/* um-arrow-frame.c
+ *
+ * Copyright (C) 2016 Red Hat, Inc,
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Writen by: Felipe Borges <felipeborges gnome org>,
+ * Georges Basile Stavracas Neto <georges stavracas gmail com>
+ */
+
+#ifndef UM_ARROW_FRAME_H
+#define UM_ARROW_FRAME_H
+
+#include <gtk/gtk.h>
+#include "um-carousel.h"
+
+G_BEGIN_DECLS
+
+#define UM_TYPE_ARROW_FRAME (um_arrow_frame_get_type())
+
+G_DECLARE_FINAL_TYPE (UmArrowFrame, um_arrow_frame, UM, ARROW_FRAME, GtkFrame)
+
+GtkWidget* um_arrow_frame_new (void);
+
+void um_arrow_frame_set_carousel (UmArrowFrame *frame,
+ UmCarousel *carousel);
+
+G_END_DECLS
+
+#endif /* UM_ARROW_FRAME_H */
diff --git a/panels/user-accounts/um-carousel.c b/panels/user-accounts/um-carousel.c
index 6bf7037..ffc382c 100644
--- a/panels/user-accounts/um-carousel.c
+++ b/panels/user-accounts/um-carousel.c
@@ -93,7 +93,7 @@ create_item (UmCarousel *self,
priv->current_button = GTK_RADIO_BUTTON (item);
gtk_container_add (GTK_CONTAINER (item), child);
- gtk_widget_show (GTK_WIDGET (item));
+ gtk_widget_show (GTK_WIDGET (child));
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
gtk_style_context_add_class (gtk_widget_get_style_context (item), "flat");
diff --git a/panels/user-accounts/um-user-panel.c b/panels/user-accounts/um-user-panel.c
index 63e8d3c..948701e 100644
--- a/panels/user-accounts/um-user-panel.c
+++ b/panels/user-accounts/um-user-panel.c
@@ -41,6 +41,7 @@
#include "shell/cc-editable-entry.h"
+#include "um-arrow-frame.h"
#include "um-editable-button.h"
#include "um-editable-combo.h"
#include "um-user-image.h"
@@ -76,6 +77,7 @@ struct _CcUserPanelPrivate {
GSettings *login_screen_settings;
UmCarousel *carousel;
+ UmArrowFrame *arrow_frame;
GtkWidget *main_box;
GPermission *permission;
GtkWidget *language_chooser;
@@ -1244,6 +1246,7 @@ cc_user_panel_init (CcUserPanel *self)
type = um_user_image_get_type ();
type = um_cell_renderer_user_image_get_type ();
type = um_carousel_get_type ();
+ type = um_arrow_frame_get_type ();
gtk_widget_set_size_request (GTK_WIDGET (self), -1, 350);
@@ -1270,6 +1273,8 @@ cc_user_panel_init (CcUserPanel *self)
d->history_dialog = um_history_dialog_new ();
d->carousel = UM_CAROUSEL (get_widget (d, "carousel"));
+ d->arrow_frame = UM_ARROW_FRAME (get_widget (d, "arrow_frame"));
+ um_arrow_frame_set_carousel (d->arrow_frame, d->carousel);
g_signal_connect (d->carousel, "item-activated", G_CALLBACK (item_toggled), d);
d->selected_user = NULL;
d->users_list = g_list_store_new (act_user_get_type ());
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]