[gnome-shell] Add top and bottom shadows to app browser



commit fc39919856363fbaffe8957ddfc203d208b4e78e
Author: Maxim Ermilov <zaspire rambler ru>
Date:   Tue Feb 23 01:07:42 2010 +0300

    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

 data/theme/gnome-shell.css |   16 +++++
 js/ui/appDisplay.js        |    5 +-
 src/st/st-scroll-view.c    |  140 ++++++++++++++++++++++++++++++++++++++++++--
 src/st/st-scroll-view.h    |    3 +
 4 files changed, 157 insertions(+), 7 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index c8cd419..f5ab8a4 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -41,6 +41,22 @@ StScrollView
   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 {
     background-color: #080808;
     border: 1px solid #2d2d2d;
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index f8fea7a..fd9445e 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -91,7 +91,10 @@ AllAppDisplay.prototype = {
         this.actor = new St.BoxLayout({ style_class: 'all-app', vertical: true });
         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.actor.add(bin);
         this.actor.add(view, { expand: true, y_fill: false, y_align: St.Align.START });
diff --git a/src/st/st-scroll-view.c b/src/st/st-scroll-view.c
index bf46347..7fef4a0 100644
--- a/src/st/st-scroll-view.c
+++ b/src/st/st-scroll-view.c
@@ -37,6 +37,7 @@
 #include "st-scroll-bar.h"
 #include "st-scrollable.h"
 #include <clutter/clutter.h>
+#include <math.h>
 
 static void clutter_container_iface_init (ClutterContainerIface *iface);
 
@@ -67,9 +68,13 @@ struct _StScrollViewPrivate
   GtkPolicyType hscroll_policy;
   GtkPolicyType vscroll_policy;
 
+  ClutterActor *top_shadow;
+  ClutterActor *bottom_shadow;
+
   gfloat        row_size;
   gfloat        column_size;
 
+  gboolean      vshadows;
   gboolean      row_size_set : 1;
   gboolean      column_size_set : 1;
   guint         mouse_scroll : 1;
@@ -82,7 +87,8 @@ enum {
   PROP_VSCROLL,
   PROP_HSCROLLBAR_POLICY,
   PROP_VSCROLLBAR_POLICY,
-  PROP_MOUSE_SCROLL
+  PROP_MOUSE_SCROLL,
+  PROP_VSHADOWS
 };
 
 static void
@@ -110,12 +116,68 @@ st_scroll_view_get_property (GObject    *object,
     case PROP_MOUSE_SCROLL:
       g_value_set_boolean (value, priv->mouse_scroll);
       break;
+    case PROP_VSHADOWS:
+      g_value_set_boolean (value, priv->vshadows);
+      break;
     default:
       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
 st_scroll_view_set_property (GObject      *object,
                              guint         property_id,
                              const GValue *value,
@@ -126,6 +188,9 @@ st_scroll_view_set_property (GObject      *object,
 
   switch (property_id)
     {
+    case PROP_VSHADOWS:
+      st_scroll_view_set_vshadows (self, g_value_get_boolean (value));
+      break;
     case PROP_MOUSE_SCROLL:
       st_scroll_view_set_mouse_scrolling (self,
                                           g_value_get_boolean (value));
@@ -170,6 +235,11 @@ st_scroll_view_dispose (GObject *object)
 static void
 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);
 }
 
@@ -186,6 +256,11 @@ st_scroll_view_paint (ClutterActor *actor)
     clutter_actor_paint (priv->hscroll);
   if (CLUTTER_ACTOR_IS_VISIBLE (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
@@ -202,6 +277,11 @@ st_scroll_view_pick (ClutterActor       *actor,
     clutter_actor_paint (priv->hscroll);
   if (CLUTTER_ACTOR_IS_VISIBLE (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
@@ -372,6 +452,25 @@ st_scroll_view_allocate (ClutterActor          *actor,
 
   if (priv->child)
     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
@@ -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->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);
 }
 
@@ -525,6 +627,14 @@ st_scroll_view_class_init (StScrollViewClass *klass)
                                    PROP_MOUSE_SCROLL,
                                    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
@@ -536,6 +646,9 @@ child_adjustment_changed_cb (StAdjustment *adjustment,
 
   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 */
   st_adjustment_get_values (adjustment, NULL,
                             &lower, &upper,
@@ -604,13 +717,16 @@ child_vadjustment_notify_cb (GObject    *gobject,
 
   vadjust = st_scroll_bar_get_adjustment (ST_SCROLL_BAR(priv->vscroll));
   if (vadjust)
-    g_signal_handlers_disconnect_by_func (vadjust,
-                                          child_adjustment_changed_cb,
-                                          priv->vscroll);
-
+    {
+      g_signal_handlers_disconnect_by_func (vadjust,
+                                            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)
     return;
-
   st_scrollable_get_adjustments (ST_SCROLLABLE(actor), NULL, &vadjust);
   if (vadjust)
     {
@@ -627,7 +743,10 @@ child_vadjustment_notify_cb (GObject    *gobject,
         {
           g_signal_connect (vadjust, "changed", G_CALLBACK (
                             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);
+          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->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 */
   priv->mouse_scroll = TRUE;
   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)
     callback (priv->vscroll, user_data);
+
+  callback (priv->top_shadow, user_data);
+  callback (priv->bottom_shadow, user_data);
 }
 
 static void
diff --git a/src/st/st-scroll-view.h b/src/st/st-scroll-view.h
index 75e32b3..bcd4bbb 100644
--- a/src/st/st-scroll-view.h
+++ b/src/st/st-scroll-view.h
@@ -88,6 +88,9 @@ void          st_scroll_view_set_policy          (StScrollView   *scroll,
                                                   GtkPolicyType   hscroll,
                                                   GtkPolicyType   vscroll);
 
+void          st_scroll_view_set_vshadows        (StScrollView *self,
+                                                  gboolean      vshadows);
+
 G_END_DECLS
 
 #endif /* __ST_SCROLL_VIEW_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]