Add top and bottom shadows to app browser

Add a 'vshadow' property to StScrollView, which, when turned on,
overlays gradient shadows on the top and bottom of the StScrollView.

Turn this on for the StScrollView used for the app browser.
https://bugzilla.gnome.org/show_bug.cgi?id=609604
This commit is contained in:
Maxim Ermilov 2010-02-23 01:07:42 +03:00
parent d8800c095a
commit fc39919856
4 changed files with 157 additions and 7 deletions

View File

@ -41,6 +41,22 @@ StScrollView
scrollbar-height: 16px; scrollbar-height: 16px;
} }
StScrollView > .top-shadow
{
background-gradient-direction: vertical;
background-gradient-start: rgba(0, 0, 0, 255);
background-gradient-end: rgba(0, 0, 0, 0);
height: 30px;
}
StScrollView > .bottom-shadow
{
background-gradient-direction: vertical;
background-gradient-start: rgba(0, 0, 0, 0);
background-gradient-end: rgba(0, 0, 0, 255);
height: 30px;
}
StScrollBar { StScrollBar {
background-color: #080808; background-color: #080808;
border: 1px solid #2d2d2d; border: 1px solid #2d2d2d;

View File

@ -91,7 +91,10 @@ AllAppDisplay.prototype = {
this.actor = new St.BoxLayout({ style_class: 'all-app', vertical: true }); this.actor = new St.BoxLayout({ style_class: 'all-app', vertical: true });
this.actor.hide(); this.actor.hide();
let view = new St.ScrollView({ x_fill: true, y_fill: false, style_class: 'all-app-scroll-view' }); let view = new St.ScrollView({ x_fill: true,
y_fill: false,
style_class: 'all-app-scroll-view',
vshadows: true });
this._scrollView = view; this._scrollView = view;
this.actor.add(bin); this.actor.add(bin);
this.actor.add(view, { expand: true, y_fill: false, y_align: St.Align.START }); this.actor.add(view, { expand: true, y_fill: false, y_align: St.Align.START });

View File

@ -37,6 +37,7 @@
#include "st-scroll-bar.h" #include "st-scroll-bar.h"
#include "st-scrollable.h" #include "st-scrollable.h"
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <math.h>
static void clutter_container_iface_init (ClutterContainerIface *iface); static void clutter_container_iface_init (ClutterContainerIface *iface);
@ -67,9 +68,13 @@ struct _StScrollViewPrivate
GtkPolicyType hscroll_policy; GtkPolicyType hscroll_policy;
GtkPolicyType vscroll_policy; GtkPolicyType vscroll_policy;
ClutterActor *top_shadow;
ClutterActor *bottom_shadow;
gfloat row_size; gfloat row_size;
gfloat column_size; gfloat column_size;
gboolean vshadows;
gboolean row_size_set : 1; gboolean row_size_set : 1;
gboolean column_size_set : 1; gboolean column_size_set : 1;
guint mouse_scroll : 1; guint mouse_scroll : 1;
@ -82,7 +87,8 @@ enum {
PROP_VSCROLL, PROP_VSCROLL,
PROP_HSCROLLBAR_POLICY, PROP_HSCROLLBAR_POLICY,
PROP_VSCROLLBAR_POLICY, PROP_VSCROLLBAR_POLICY,
PROP_MOUSE_SCROLL PROP_MOUSE_SCROLL,
PROP_VSHADOWS
}; };
static void static void
@ -110,11 +116,67 @@ st_scroll_view_get_property (GObject *object,
case PROP_MOUSE_SCROLL: case PROP_MOUSE_SCROLL:
g_value_set_boolean (value, priv->mouse_scroll); g_value_set_boolean (value, priv->mouse_scroll);
break; break;
case PROP_VSHADOWS:
g_value_set_boolean (value, priv->vshadows);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
} }
} }
static void
update_shadow_visibility (GObject *gobject,
GParamSpec *arg1,
gpointer user_data)
{
StAdjustment *vadjust = ST_ADJUSTMENT (gobject);
StScrollViewPrivate *priv = ST_SCROLL_VIEW (user_data)->priv;
gdouble value, lower, upper, page_size;
st_adjustment_get_values (vadjust, &value, &lower, &upper, NULL, NULL, &page_size);
if (fabs (value - lower) > 0.1 && priv->vshadows)
clutter_actor_show (priv->top_shadow);
else
clutter_actor_hide (priv->top_shadow);
if (fabs (upper - value - page_size) > 0.1 && priv->vshadows)
clutter_actor_show (priv->bottom_shadow);
else
clutter_actor_hide (priv->bottom_shadow);
}
/**
* st_scroll_view_set_vshadows:
* @self: a #StScrollView
* @vshadows: Whether to enable vertical shadows
*
* Sets whether to show shadows at the top and bottom of the area. Shadows
* are omitted when fully scrolled to that edge.
*/
void
st_scroll_view_set_vshadows (StScrollView *self,
gboolean vshadows)
{
StAdjustment *vadjust;
StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv;
vshadows = vshadows != FALSE;
if (priv->vshadows == vshadows)
return;
priv->vshadows = vshadows;
vadjust = st_scroll_bar_get_adjustment (ST_SCROLL_BAR(priv->vscroll));
if (!vadjust)
return;
update_shadow_visibility (G_OBJECT (vadjust), NULL, self);
g_object_notify (G_OBJECT (self), "vshadows");
}
static void static void
st_scroll_view_set_property (GObject *object, st_scroll_view_set_property (GObject *object,
guint property_id, guint property_id,
@ -126,6 +188,9 @@ st_scroll_view_set_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_VSHADOWS:
st_scroll_view_set_vshadows (self, g_value_get_boolean (value));
break;
case PROP_MOUSE_SCROLL: case PROP_MOUSE_SCROLL:
st_scroll_view_set_mouse_scrolling (self, st_scroll_view_set_mouse_scrolling (self,
g_value_get_boolean (value)); g_value_get_boolean (value));
@ -170,6 +235,11 @@ st_scroll_view_dispose (GObject *object)
static void static void
st_scroll_view_finalize (GObject *object) st_scroll_view_finalize (GObject *object)
{ {
StScrollViewPrivate *priv = ST_SCROLL_VIEW (object)->priv;
g_object_unref (priv->top_shadow);
g_object_unref (priv->bottom_shadow);
G_OBJECT_CLASS (st_scroll_view_parent_class)->finalize (object); G_OBJECT_CLASS (st_scroll_view_parent_class)->finalize (object);
} }
@ -186,6 +256,11 @@ st_scroll_view_paint (ClutterActor *actor)
clutter_actor_paint (priv->hscroll); clutter_actor_paint (priv->hscroll);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll)) if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll))
clutter_actor_paint (priv->vscroll); clutter_actor_paint (priv->vscroll);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->top_shadow))
clutter_actor_paint (priv->top_shadow);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->bottom_shadow))
clutter_actor_paint (priv->bottom_shadow);
} }
static void static void
@ -202,6 +277,11 @@ st_scroll_view_pick (ClutterActor *actor,
clutter_actor_paint (priv->hscroll); clutter_actor_paint (priv->hscroll);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll)) if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll))
clutter_actor_paint (priv->vscroll); clutter_actor_paint (priv->vscroll);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->top_shadow))
clutter_actor_paint (priv->top_shadow);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->bottom_shadow))
clutter_actor_paint (priv->bottom_shadow);
} }
static double static double
@ -372,6 +452,25 @@ st_scroll_view_allocate (ClutterActor *actor,
if (priv->child) if (priv->child)
clutter_actor_allocate (priv->child, &child_box, flags); clutter_actor_allocate (priv->child, &child_box, flags);
/*Shadows*/
if (CLUTTER_ACTOR_IS_VISIBLE (priv->top_shadow))
{
child_box.x1 = content_box.x1;
child_box.y1 = content_box.y1;
child_box.x2 = MAX (child_box.x1, content_box.x2 - sb_width);
child_box.y2 = MAX (child_box.y1, content_box.y1 + clutter_actor_get_height (priv->top_shadow));
clutter_actor_allocate (priv->top_shadow, &child_box, flags);
}
if (CLUTTER_ACTOR_IS_VISIBLE (priv->bottom_shadow))
{
child_box.x1 = content_box.x1;
child_box.y1 = content_box.y2 - clutter_actor_get_height (priv->bottom_shadow);
child_box.x2 = MAX (child_box.x1, content_box.x2 - sb_width);
child_box.y2 = content_box.y2 + 1;
clutter_actor_allocate (priv->bottom_shadow, &child_box, flags);
}
} }
static void static void
@ -382,6 +481,9 @@ st_scroll_view_style_changed (StWidget *widget)
st_widget_style_changed (ST_WIDGET (priv->hscroll)); st_widget_style_changed (ST_WIDGET (priv->hscroll));
st_widget_style_changed (ST_WIDGET (priv->vscroll)); st_widget_style_changed (ST_WIDGET (priv->vscroll));
st_widget_style_changed (ST_WIDGET (priv->top_shadow));
st_widget_style_changed (ST_WIDGET (priv->bottom_shadow));
ST_WIDGET_CLASS (st_scroll_view_parent_class)->style_changed (widget); ST_WIDGET_CLASS (st_scroll_view_parent_class)->style_changed (widget);
} }
@ -525,6 +627,14 @@ st_scroll_view_class_init (StScrollViewClass *klass)
PROP_MOUSE_SCROLL, PROP_MOUSE_SCROLL,
pspec); pspec);
pspec = g_param_spec_boolean ("vshadows",
"Vertical Shadows",
"Show shadows at the top and and bottom of the area unless fully scrolled to that edge",
FALSE,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_VSHADOWS,
pspec);
} }
static void static void
@ -536,6 +646,9 @@ child_adjustment_changed_cb (StAdjustment *adjustment,
scroll = ST_SCROLL_VIEW (clutter_actor_get_parent (bar)); scroll = ST_SCROLL_VIEW (clutter_actor_get_parent (bar));
if (bar == scroll->priv->vscroll)
update_shadow_visibility (G_OBJECT (adjustment), NULL, scroll);
/* Determine if this scroll-bar should be visible */ /* Determine if this scroll-bar should be visible */
st_adjustment_get_values (adjustment, NULL, st_adjustment_get_values (adjustment, NULL,
&lower, &upper, &lower, &upper,
@ -604,13 +717,16 @@ child_vadjustment_notify_cb (GObject *gobject,
vadjust = st_scroll_bar_get_adjustment (ST_SCROLL_BAR(priv->vscroll)); vadjust = st_scroll_bar_get_adjustment (ST_SCROLL_BAR(priv->vscroll));
if (vadjust) if (vadjust)
g_signal_handlers_disconnect_by_func (vadjust, {
child_adjustment_changed_cb, g_signal_handlers_disconnect_by_func (vadjust,
priv->vscroll); update_shadow_visibility,
user_data);
g_signal_handlers_disconnect_by_func (vadjust,
child_adjustment_changed_cb,
priv->vscroll);
}
if (priv->vscroll_policy == GTK_POLICY_NEVER) if (priv->vscroll_policy == GTK_POLICY_NEVER)
return; return;
st_scrollable_get_adjustments (ST_SCROLLABLE(actor), NULL, &vadjust); st_scrollable_get_adjustments (ST_SCROLLABLE(actor), NULL, &vadjust);
if (vadjust) if (vadjust)
{ {
@ -627,7 +743,10 @@ child_vadjustment_notify_cb (GObject *gobject,
{ {
g_signal_connect (vadjust, "changed", G_CALLBACK ( g_signal_connect (vadjust, "changed", G_CALLBACK (
child_adjustment_changed_cb), priv->vscroll); child_adjustment_changed_cb), priv->vscroll);
g_signal_connect (vadjust, "notify::value", G_CALLBACK (
update_shadow_visibility), user_data);
child_adjustment_changed_cb (vadjust, priv->vscroll); child_adjustment_changed_cb (vadjust, priv->vscroll);
update_shadow_visibility (G_OBJECT (vadjust), NULL, user_data);
} }
} }
} }
@ -646,6 +765,12 @@ st_scroll_view_init (StScrollView *self)
clutter_actor_set_parent (priv->hscroll, CLUTTER_ACTOR (self)); clutter_actor_set_parent (priv->hscroll, CLUTTER_ACTOR (self));
clutter_actor_set_parent (priv->vscroll, CLUTTER_ACTOR (self)); clutter_actor_set_parent (priv->vscroll, CLUTTER_ACTOR (self));
priv->top_shadow = g_object_new (ST_TYPE_BIN, "style-class", "top-shadow", NULL);
priv->bottom_shadow = g_object_new (ST_TYPE_BIN, "style-class", "bottom-shadow", NULL);
clutter_actor_set_parent (priv->bottom_shadow, CLUTTER_ACTOR (self));
clutter_actor_set_parent (priv->top_shadow, CLUTTER_ACTOR (self));
/* mouse scroll is enabled by default, so we also need to be reactive */ /* mouse scroll is enabled by default, so we also need to be reactive */
priv->mouse_scroll = TRUE; priv->mouse_scroll = TRUE;
g_object_set (G_OBJECT (self), "reactive", TRUE, NULL); g_object_set (G_OBJECT (self), "reactive", TRUE, NULL);
@ -725,6 +850,9 @@ st_scroll_view_foreach_with_internals (ClutterContainer *container,
if (priv->vscroll != NULL) if (priv->vscroll != NULL)
callback (priv->vscroll, user_data); callback (priv->vscroll, user_data);
callback (priv->top_shadow, user_data);
callback (priv->bottom_shadow, user_data);
} }
static void static void

View File

@ -88,6 +88,9 @@ void st_scroll_view_set_policy (StScrollView *scroll,
GtkPolicyType hscroll, GtkPolicyType hscroll,
GtkPolicyType vscroll); GtkPolicyType vscroll);
void st_scroll_view_set_vshadows (StScrollView *self,
gboolean vshadows);
G_END_DECLS G_END_DECLS
#endif /* __ST_SCROLL_VIEW_H__ */ #endif /* __ST_SCROLL_VIEW_H__ */