StScrollView: Implement real fade effect
Implement an edge fade effect (top/bottom) using a ClutterOffscreenEffect subclass, replacing the former shadow hack. https://bugzilla.gnome.org/show_bug.cgi?id=639460
This commit is contained in:
parent
df3560143d
commit
00ba937171
@ -40,7 +40,7 @@ AlphabeticalView.prototype = {
|
||||
this.actor = new St.ScrollView({ x_fill: true,
|
||||
y_fill: false,
|
||||
y_align: St.Align.START,
|
||||
vshadows: true });
|
||||
vfade: true });
|
||||
this.actor.add_actor(box);
|
||||
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
},
|
||||
|
@ -386,7 +386,7 @@ Notification.prototype = {
|
||||
this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
|
||||
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
vshadows: true });
|
||||
vfade: true });
|
||||
this.actor.add(this._scrollArea, { row: 1,
|
||||
col: 1 });
|
||||
this._contentArea = new St.BoxLayout({ name: 'notification-body',
|
||||
|
@ -166,7 +166,7 @@ SearchResults.prototype = {
|
||||
|
||||
let scrollView = new St.ScrollView({ x_fill: true,
|
||||
y_fill: false,
|
||||
vshadows: true });
|
||||
vfade: true });
|
||||
scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
scrollView.add_actor(this._content);
|
||||
|
||||
|
@ -159,11 +159,17 @@ st_source_c = \
|
||||
st/st-widget.c \
|
||||
$(NULL)
|
||||
|
||||
st_non_gir_sources = \
|
||||
st/st-scroll-view-fade.c \
|
||||
st/st-scroll-view-fade.h \
|
||||
$(NULL)
|
||||
|
||||
noinst_LTLIBRARIES += libst-1.0.la
|
||||
|
||||
libst_1_0_la_LIBADD = -lm $(ST_LIBS)
|
||||
libst_1_0_la_SOURCES = \
|
||||
$(st_source_c) \
|
||||
$(st_source_c) \
|
||||
$(st_non_gir_sources) \
|
||||
$(st_source_private_h) \
|
||||
$(st_source_private_c) \
|
||||
$(st_source_h) \
|
||||
|
@ -262,7 +262,7 @@ St-1.0.gir: $(mutter) $(G_IR_SCANNER) libst-1.0.la Makefile
|
||||
--libtool="$(LIBTOOL)" \
|
||||
--library=libst-1.0.la \
|
||||
-DST_COMPILATION \
|
||||
$(filter-out %-private.h, $(addprefix $(srcdir)/,$(st_source_h))) \
|
||||
$(filter-out %-private.h $(st_non_gir_sources), $(addprefix $(srcdir)/,$(st_source_h))) \
|
||||
$(addprefix $(srcdir)/,$(st_source_c)) \
|
||||
$(srcdir)/st-enum-types.h \
|
||||
$(st_cflags) \
|
||||
|
348
src/st/st-scroll-view-fade.c
Normal file
348
src/st/st-scroll-view-fade.c
Normal file
@ -0,0 +1,348 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* st-scroll-view-fade.h: Edge fade effect for StScrollView
|
||||
*
|
||||
* Copyright 2010 Intel Corporation.
|
||||
* Copyright 2011 Adel Gadllah
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#define ST_SCROLL_VIEW_FADE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_SCROLL_VIEW_FADE, StScrollViewFadeClass))
|
||||
#define ST_IS_SCROLL_VIEW_FADE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_SCROLL_VIEW_FADE))
|
||||
#define ST_SCROLL_VIEW_FADE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_SCROLL_VIEW_FADE, StScrollViewFadeClass))
|
||||
|
||||
#include "st-scroll-view-fade.h"
|
||||
#include "st-scroll-view.h"
|
||||
#include "st-scroll-bar.h"
|
||||
#include "st-scrollable.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
typedef struct _StScrollViewFadeClass StScrollViewFadeClass;
|
||||
|
||||
#define FADE_OFFSET 68.0f
|
||||
|
||||
static const gchar *fade_glsl_shader =
|
||||
"uniform sampler2D tex;\n"
|
||||
"uniform float height;\n"
|
||||
"uniform float width;\n"
|
||||
"uniform float scrollbar_width;\n"
|
||||
"uniform float offset_bottom;\n"
|
||||
"uniform float offset_top;\n"
|
||||
"\n"
|
||||
"void main ()\n"
|
||||
"{\n"
|
||||
" vec4 color = cogl_color_in * texture2D (tex, vec2 (cogl_tex_coord_in[0].xy));\n"
|
||||
" float y = height * cogl_tex_coord_in[0].y;\n"
|
||||
" float x = width * cogl_tex_coord_in[0].x;\n"
|
||||
" float ratio = 0.0;\n"
|
||||
" float fade_bottom_start = height - offset_bottom;\n"
|
||||
" \n"
|
||||
" if (offset_top != 0.0 && y < offset_top && x < (width - scrollbar_width)) {\n"
|
||||
" ratio = y / offset_top;\n"
|
||||
" cogl_color_out = color * ratio;\n"
|
||||
" }\n"
|
||||
" else if (offset_bottom != 0.0 && y > fade_bottom_start && x < (width - scrollbar_width)) {\n"
|
||||
" ratio = (height - y)/(height - fade_bottom_start);\n"
|
||||
" cogl_color_out = color * ratio;\n"
|
||||
" }\n"
|
||||
" else { \n"
|
||||
" cogl_color_out = color;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
struct _StScrollViewFade
|
||||
{
|
||||
ClutterOffscreenEffect parent_instance;
|
||||
|
||||
/* a back pointer to our actor, so that we can query it */
|
||||
ClutterActor *actor;
|
||||
|
||||
CoglHandle shader;
|
||||
CoglHandle program;
|
||||
|
||||
gint tex_uniform;
|
||||
gint height_uniform;
|
||||
gint width_uniform;
|
||||
gint scrollbar_width_uniform;
|
||||
gint offset_top_uniform;
|
||||
gint offset_bottom_uniform;
|
||||
|
||||
StAdjustment *vadjustment;
|
||||
|
||||
guint is_attached : 1;
|
||||
};
|
||||
|
||||
struct _StScrollViewFadeClass
|
||||
{
|
||||
ClutterOffscreenEffectClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (StScrollViewFade,
|
||||
st_scroll_view_fade,
|
||||
CLUTTER_TYPE_OFFSCREEN_EFFECT);
|
||||
|
||||
static gboolean
|
||||
st_scroll_view_fade_pre_paint (ClutterEffect *effect)
|
||||
{
|
||||
StScrollViewFade *self = ST_SCROLL_VIEW_FADE (effect);
|
||||
ClutterEffectClass *parent_class;
|
||||
|
||||
if (self->shader == COGL_INVALID_HANDLE)
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
if (self->actor == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (self->program == COGL_INVALID_HANDLE)
|
||||
self->program = cogl_create_program ();
|
||||
|
||||
if (!self->is_attached)
|
||||
{
|
||||
g_assert (self->shader != COGL_INVALID_HANDLE);
|
||||
g_assert (self->program != COGL_INVALID_HANDLE);
|
||||
|
||||
cogl_program_attach_shader (self->program, self->shader);
|
||||
cogl_program_link (self->program);
|
||||
|
||||
cogl_handle_unref (self->shader);
|
||||
|
||||
self->is_attached = TRUE;
|
||||
|
||||
self->tex_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "tex");
|
||||
self->height_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "height");
|
||||
self->width_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "width");
|
||||
self->scrollbar_width_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "scrollbar_width");
|
||||
self->offset_top_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "offset_top");
|
||||
self->offset_bottom_uniform =
|
||||
cogl_program_get_uniform_location (self->program, "offset_bottom");
|
||||
}
|
||||
|
||||
parent_class = CLUTTER_EFFECT_CLASS (st_scroll_view_fade_parent_class);
|
||||
return parent_class->pre_paint (effect);
|
||||
}
|
||||
|
||||
static CoglHandle
|
||||
st_scroll_view_fade_create_texture (ClutterOffscreenEffect *effect,
|
||||
gfloat min_width,
|
||||
gfloat min_height)
|
||||
{
|
||||
return cogl_texture_new_with_size (min_width,
|
||||
min_height,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE);
|
||||
}
|
||||
|
||||
static void
|
||||
st_scroll_view_fade_paint_target (ClutterOffscreenEffect *effect)
|
||||
{
|
||||
StScrollViewFade *self = ST_SCROLL_VIEW_FADE (effect);
|
||||
ClutterOffscreenEffectClass *parent;
|
||||
CoglHandle material;
|
||||
|
||||
gdouble value, lower, upper, page_size;
|
||||
ClutterActor *vscroll = st_scroll_view_get_vscroll_bar (ST_SCROLL_VIEW (self->actor));
|
||||
|
||||
if (self->program == COGL_INVALID_HANDLE)
|
||||
goto out;
|
||||
|
||||
st_adjustment_get_values (self->vadjustment, &value, &lower, &upper, NULL, NULL, &page_size);
|
||||
|
||||
if (self->offset_top_uniform > -1) {
|
||||
if (value > lower + 0.1)
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_top_uniform, FADE_OFFSET);
|
||||
else
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_top_uniform, 0.0f);
|
||||
}
|
||||
|
||||
if (self->offset_bottom_uniform > -1) {
|
||||
if (value < upper - page_size - 0.1)
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_bottom_uniform, FADE_OFFSET);
|
||||
else
|
||||
cogl_program_set_uniform_1f (self->program, self->offset_bottom_uniform, 0.0f);
|
||||
}
|
||||
|
||||
if (self->tex_uniform > -1)
|
||||
cogl_program_set_uniform_1i (self->program, self->tex_uniform, 0);
|
||||
if (self->height_uniform > -1)
|
||||
cogl_program_set_uniform_1f (self->program, self->height_uniform, clutter_actor_get_height (self->actor));
|
||||
if (self->width_uniform > -1)
|
||||
cogl_program_set_uniform_1f (self->program, self->width_uniform, clutter_actor_get_width (self->actor));
|
||||
if (self->scrollbar_width_uniform > -1)
|
||||
cogl_program_set_uniform_1f (self->program, self->scrollbar_width_uniform, clutter_actor_get_width (vscroll));
|
||||
|
||||
material = clutter_offscreen_effect_get_target (effect);
|
||||
cogl_material_set_user_program (material, self->program);
|
||||
|
||||
out:
|
||||
parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (st_scroll_view_fade_parent_class);
|
||||
parent->paint_target (effect);
|
||||
}
|
||||
|
||||
static void
|
||||
on_vadjustment_changed (StAdjustment *adjustment,
|
||||
ClutterEffect *effect)
|
||||
{
|
||||
gdouble value, lower, upper, page_size;
|
||||
gboolean needs_fade;
|
||||
|
||||
st_adjustment_get_values (adjustment, &value, &lower, &upper, NULL, NULL, &page_size);
|
||||
needs_fade = (value > lower + 0.1) || (value < upper - page_size - 0.1);
|
||||
|
||||
clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), needs_fade);
|
||||
}
|
||||
|
||||
static void
|
||||
st_scroll_view_fade_set_actor (ClutterActorMeta *meta,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
StScrollViewFade *self = ST_SCROLL_VIEW_FADE (meta);
|
||||
ClutterActorMetaClass *parent;
|
||||
|
||||
g_return_if_fail (actor == NULL || ST_IS_SCROLL_VIEW (actor));
|
||||
|
||||
if (self->shader == COGL_INVALID_HANDLE)
|
||||
{
|
||||
clutter_actor_meta_set_enabled (meta, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->vadjustment)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (self->vadjustment,
|
||||
(gpointer)on_vadjustment_changed,
|
||||
self);
|
||||
self->vadjustment = NULL;
|
||||
}
|
||||
|
||||
if (actor)
|
||||
{
|
||||
StScrollView *scroll_view = ST_SCROLL_VIEW (actor);
|
||||
StScrollBar *vscroll = ST_SCROLL_BAR (st_scroll_view_get_vscroll_bar (scroll_view));
|
||||
self->vadjustment = ST_ADJUSTMENT (st_scroll_bar_get_adjustment (vscroll));
|
||||
|
||||
g_signal_connect (self->vadjustment, "changed",
|
||||
G_CALLBACK (on_vadjustment_changed),
|
||||
self);
|
||||
|
||||
on_vadjustment_changed (self->vadjustment, CLUTTER_EFFECT (self));
|
||||
}
|
||||
|
||||
parent = CLUTTER_ACTOR_META_CLASS (st_scroll_view_fade_parent_class);
|
||||
parent->set_actor (meta, actor);
|
||||
|
||||
/* we keep a back pointer here, to avoid going through the ActorMeta */
|
||||
self->actor = clutter_actor_meta_get_actor (meta);
|
||||
}
|
||||
|
||||
static void
|
||||
st_scroll_view_fade_dispose (GObject *gobject)
|
||||
{
|
||||
StScrollViewFade *self = ST_SCROLL_VIEW_FADE (gobject);
|
||||
|
||||
if (self->program != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (self->program);
|
||||
|
||||
self->program = COGL_INVALID_HANDLE;
|
||||
self->shader = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (self->vadjustment)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (self->vadjustment,
|
||||
(gpointer)on_vadjustment_changed,
|
||||
self);
|
||||
self->vadjustment = NULL;
|
||||
}
|
||||
|
||||
self->actor = NULL;
|
||||
|
||||
G_OBJECT_CLASS (st_scroll_view_fade_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
st_scroll_view_fade_class_init (StScrollViewFadeClass *klass)
|
||||
{
|
||||
ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = st_scroll_view_fade_dispose;
|
||||
|
||||
meta_class->set_actor = st_scroll_view_fade_set_actor;
|
||||
|
||||
effect_class->pre_paint = st_scroll_view_fade_pre_paint;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->create_texture = st_scroll_view_fade_create_texture;
|
||||
offscreen_class->paint_target = st_scroll_view_fade_paint_target;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
st_scroll_view_fade_init (StScrollViewFade *self)
|
||||
{
|
||||
static CoglHandle shader = COGL_INVALID_HANDLE;
|
||||
|
||||
if (shader == COGL_INVALID_HANDLE)
|
||||
{
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
|
||||
cogl_shader_source (shader, fade_glsl_shader);
|
||||
cogl_shader_compile (shader);
|
||||
if (!cogl_shader_is_compiled (shader))
|
||||
{
|
||||
gchar *log_buf = cogl_shader_get_info_log (shader);
|
||||
|
||||
g_warning (G_STRLOC ": Unable to compile the fade shader: %s",
|
||||
log_buf);
|
||||
g_free (log_buf);
|
||||
|
||||
cogl_handle_unref (shader);
|
||||
shader = COGL_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->shader = shader;
|
||||
self->is_attached = FALSE;
|
||||
self->tex_uniform = -1;
|
||||
self->height_uniform = -1;
|
||||
self->width_uniform = -1;
|
||||
self->scrollbar_width_uniform = -1;
|
||||
self->offset_top_uniform = -1;
|
||||
self->offset_bottom_uniform = -1;
|
||||
|
||||
if (shader != COGL_INVALID_HANDLE)
|
||||
cogl_handle_ref (self->shader);
|
||||
}
|
||||
|
||||
ClutterEffect *
|
||||
st_scroll_view_fade_new (void)
|
||||
{
|
||||
return g_object_new (ST_TYPE_SCROLL_VIEW_FADE, NULL);
|
||||
}
|
40
src/st/st-scroll-view-fade.h
Normal file
40
src/st/st-scroll-view-fade.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* st-scroll-view-fade.h: Edge fade effect for StScrollView
|
||||
*
|
||||
* Copyright 2010 Intel Corporation.
|
||||
* Copyright 2011 Adel Gadllah
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ST_SCROLL_VIEW_FADE_H__
|
||||
#define __ST_SCROLL_VIEW_FADE_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define ST_TYPE_SCROLL_VIEW_FADE (st_scroll_view_fade_get_type ())
|
||||
#define ST_SCROLL_VIEW_FADE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_SCROLL_VIEW_FADE, StScrollViewFade))
|
||||
#define ST_IS_SCROLL_VIEW_FADE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_SCROLL_VIEW_FADE))
|
||||
|
||||
typedef struct _StScrollViewFade StScrollViewFade;
|
||||
|
||||
GType st_scroll_view_fade_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterEffect *st_scroll_view_fade_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __ST_SCROLL_VIEW_FADE_H__ */
|
@ -62,6 +62,7 @@
|
||||
#include "st-marshal.h"
|
||||
#include "st-scroll-bar.h"
|
||||
#include "st-scrollable.h"
|
||||
#include "st-scroll-view-fade.h"
|
||||
#include <clutter/clutter.h>
|
||||
#include <math.h>
|
||||
|
||||
@ -93,20 +94,17 @@ struct _StScrollViewPrivate
|
||||
GtkPolicyType hscrollbar_policy;
|
||||
GtkPolicyType vscrollbar_policy;
|
||||
|
||||
ClutterActor *top_shadow;
|
||||
ClutterActor *bottom_shadow;
|
||||
|
||||
gfloat row_size;
|
||||
gfloat column_size;
|
||||
|
||||
gboolean vshadows;
|
||||
gboolean vfade;
|
||||
StScrollViewFade *vfade_effect;
|
||||
|
||||
gboolean row_size_set : 1;
|
||||
gboolean column_size_set : 1;
|
||||
guint mouse_scroll : 1;
|
||||
guint hscrollbar_visible : 1;
|
||||
guint vscrollbar_visible : 1;
|
||||
guint top_shadow_visible : 1;
|
||||
guint bottom_shadow_visible : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -117,7 +115,7 @@ enum {
|
||||
PROP_HSCROLLBAR_POLICY,
|
||||
PROP_VSCROLLBAR_POLICY,
|
||||
PROP_MOUSE_SCROLL,
|
||||
PROP_VSHADOWS
|
||||
PROP_VFADE
|
||||
};
|
||||
|
||||
static void
|
||||
@ -145,80 +143,50 @@ 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);
|
||||
case PROP_VFADE:
|
||||
g_value_set_boolean (value, priv->vfade);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_shadow_visibility (StScrollView *scroll)
|
||||
{
|
||||
StScrollViewPrivate *priv = scroll->priv;
|
||||
|
||||
if (priv->vshadows)
|
||||
{
|
||||
gdouble value, lower, upper, page_size;
|
||||
|
||||
st_adjustment_get_values (priv->vadjustment, &value, &lower, &upper, NULL, NULL, &page_size);
|
||||
|
||||
priv->top_shadow_visible = value > lower + 0.1;
|
||||
priv->bottom_shadow_visible = value < upper - page_size - 0.1;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->top_shadow_visible = FALSE;
|
||||
priv->bottom_shadow_visible = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* st_scroll_view_set_vshadows:
|
||||
* st_scroll_view_set_vfade:
|
||||
* @self: a #StScrollView
|
||||
* @vshadows: Whether to enable vertical shadows
|
||||
* @vfade: Whether to enable the vertical fade effect
|
||||
*
|
||||
* Sets whether to show shadows at the top and bottom of the area. Shadows
|
||||
* are omitted when fully scrolled to that edge.
|
||||
* Sets whether to fade the content at the top and bottom of the area when not
|
||||
* fully scrolled to that edge.
|
||||
*/
|
||||
void
|
||||
st_scroll_view_set_vshadows (StScrollView *self,
|
||||
gboolean vshadows)
|
||||
st_scroll_view_set_vfade (StScrollView *self,
|
||||
gboolean vfade)
|
||||
{
|
||||
StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv;
|
||||
|
||||
vshadows = vshadows != FALSE;
|
||||
if (priv->vshadows == vshadows)
|
||||
vfade = vfade != FALSE;
|
||||
if (priv->vfade == vfade)
|
||||
return;
|
||||
|
||||
priv->vshadows = vshadows;
|
||||
priv->vfade = vfade;
|
||||
|
||||
if (vshadows)
|
||||
if (vfade)
|
||||
{
|
||||
if (priv->top_shadow)
|
||||
{
|
||||
clutter_actor_show (priv->top_shadow);
|
||||
clutter_actor_show (priv->bottom_shadow);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
if (priv->vfade_effect == NULL)
|
||||
priv->vfade_effect = g_object_new (ST_TYPE_SCROLL_VIEW_FADE, NULL);
|
||||
|
||||
clutter_actor_set_parent (priv->bottom_shadow, CLUTTER_ACTOR (self));
|
||||
clutter_actor_set_parent (priv->top_shadow, CLUTTER_ACTOR (self));
|
||||
}
|
||||
clutter_actor_add_effect (CLUTTER_ACTOR (self), CLUTTER_EFFECT (priv->vfade_effect));
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
clutter_actor_hide (priv->top_shadow);
|
||||
clutter_actor_hide (priv->bottom_shadow);
|
||||
clutter_actor_remove_effect (CLUTTER_ACTOR (self), CLUTTER_EFFECT (priv->vfade_effect));
|
||||
priv->vfade_effect = NULL;
|
||||
}
|
||||
|
||||
update_shadow_visibility (self);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
|
||||
g_object_notify (G_OBJECT (self), "vshadows");
|
||||
g_object_notify (G_OBJECT (self), "vfade");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -232,8 +200,8 @@ st_scroll_view_set_property (GObject *object,
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_VSHADOWS:
|
||||
st_scroll_view_set_vshadows (self, g_value_get_boolean (value));
|
||||
case PROP_VFADE:
|
||||
st_scroll_view_set_vfade (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_MOUSE_SCROLL:
|
||||
st_scroll_view_set_mouse_scrolling (self,
|
||||
@ -259,6 +227,12 @@ st_scroll_view_dispose (GObject *object)
|
||||
{
|
||||
StScrollViewPrivate *priv = ST_SCROLL_VIEW (object)->priv;
|
||||
|
||||
if (priv->vfade_effect)
|
||||
{
|
||||
clutter_actor_remove_effect (CLUTTER_ACTOR (object), CLUTTER_EFFECT (priv->vfade_effect));
|
||||
priv->vfade_effect = NULL;
|
||||
}
|
||||
|
||||
if (priv->vscroll)
|
||||
clutter_actor_destroy (priv->vscroll);
|
||||
|
||||
@ -284,20 +258,6 @@ st_scroll_view_dispose (GObject *object)
|
||||
priv->vadjustment = NULL;
|
||||
}
|
||||
|
||||
/* since it's impossible to get a handle to these actors, we can
|
||||
* just directly unparent them and not go through destroy/remove */
|
||||
if (priv->top_shadow)
|
||||
{
|
||||
clutter_actor_unparent (priv->top_shadow);
|
||||
priv->top_shadow = NULL;
|
||||
}
|
||||
|
||||
if (priv->bottom_shadow)
|
||||
{
|
||||
clutter_actor_unparent (priv->bottom_shadow);
|
||||
priv->bottom_shadow = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (st_scroll_view_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@ -314,11 +274,6 @@ st_scroll_view_paint (ClutterActor *actor)
|
||||
clutter_actor_paint (priv->hscroll);
|
||||
if (priv->vscrollbar_visible && CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll))
|
||||
clutter_actor_paint (priv->vscroll);
|
||||
|
||||
if (priv->top_shadow_visible)
|
||||
clutter_actor_paint (priv->top_shadow);
|
||||
if (priv->bottom_shadow_visible)
|
||||
clutter_actor_paint (priv->bottom_shadow);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -532,18 +487,6 @@ st_scroll_view_get_preferred_height (ClutterActor *actor,
|
||||
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
|
||||
}
|
||||
|
||||
static gfloat
|
||||
get_shadow_height (ClutterActor *shadow)
|
||||
{
|
||||
gfloat natural_height;
|
||||
|
||||
/* The shadows are empty StBin and have no height-for-width behavior */
|
||||
|
||||
clutter_actor_get_preferred_height (shadow, -1, NULL, &natural_height);
|
||||
|
||||
return natural_height;
|
||||
}
|
||||
|
||||
static void
|
||||
st_scroll_view_allocate (ClutterActor *actor,
|
||||
const ClutterActorBox *box,
|
||||
@ -688,25 +631,6 @@ st_scroll_view_allocate (ClutterActor *actor,
|
||||
if (priv->child)
|
||||
clutter_actor_allocate (priv->child, &child_box, flags);
|
||||
|
||||
/* Shadows */
|
||||
if (priv->top_shadow && 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 = content_box.y1 + get_shadow_height (priv->top_shadow);
|
||||
clutter_actor_allocate (priv->top_shadow, &child_box, flags);
|
||||
}
|
||||
|
||||
if (priv->bottom_shadow && CLUTTER_ACTOR_IS_VISIBLE (priv->bottom_shadow))
|
||||
{
|
||||
child_box.x1 = content_box.x1;
|
||||
child_box.y1 = content_box.y2 - sb_height - get_shadow_height (priv->bottom_shadow);
|
||||
child_box.x2 = MAX (content_box.x1, content_box.x2 - sb_width);
|
||||
child_box.y2 = content_box.y2 - sb_height;
|
||||
clutter_actor_allocate (priv->bottom_shadow, &child_box, flags);
|
||||
}
|
||||
|
||||
priv->hscrollbar_visible = hscrollbar_visible;
|
||||
priv->vscrollbar_visible = vscrollbar_visible;
|
||||
}
|
||||
@ -719,12 +643,6 @@ st_scroll_view_style_changed (StWidget *widget)
|
||||
st_widget_style_changed (ST_WIDGET (priv->hscroll));
|
||||
st_widget_style_changed (ST_WIDGET (priv->vscroll));
|
||||
|
||||
if (priv->top_shadow)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -857,31 +775,16 @@ st_scroll_view_class_init (StScrollViewClass *klass)
|
||||
PROP_MOUSE_SCROLL,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("vshadows",
|
||||
pspec = g_param_spec_boolean ("vfade",
|
||||
"Vertical Shadows",
|
||||
"Show shadows at the top and and bottom of the area unless fully scrolled to that edge",
|
||||
"Fade the content 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,
|
||||
PROP_VFADE,
|
||||
pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
child_adjustment_changed_cb (StAdjustment *adjustment,
|
||||
StScrollView *scroll)
|
||||
{
|
||||
update_shadow_visibility (scroll);
|
||||
}
|
||||
|
||||
static void
|
||||
child_adjustment_notify_value (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
StScrollView *scroll)
|
||||
{
|
||||
update_shadow_visibility (scroll);
|
||||
}
|
||||
|
||||
static void
|
||||
st_scroll_view_init (StScrollView *self)
|
||||
{
|
||||
@ -897,10 +800,6 @@ st_scroll_view_init (StScrollView *self)
|
||||
NULL);
|
||||
|
||||
priv->vadjustment = g_object_new (ST_TYPE_ADJUSTMENT, NULL);
|
||||
g_signal_connect (priv->vadjustment, "changed",
|
||||
G_CALLBACK (child_adjustment_changed_cb), self);
|
||||
g_signal_connect (priv->vadjustment, "notify::value",
|
||||
G_CALLBACK (child_adjustment_notify_value), self);
|
||||
priv->vscroll = g_object_new (ST_TYPE_SCROLL_BAR,
|
||||
"adjustment", priv->vadjustment,
|
||||
"vertical", TRUE,
|
||||
@ -988,12 +887,6 @@ st_scroll_view_foreach_with_internals (ClutterContainer *container,
|
||||
|
||||
if (priv->vscroll != NULL)
|
||||
callback (priv->vscroll, user_data);
|
||||
|
||||
if (priv->top_shadow)
|
||||
{
|
||||
callback (priv->top_shadow, user_data);
|
||||
callback (priv->bottom_shadow, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -84,8 +84,8 @@ void st_scroll_view_set_policy (StScrollView *scroll,
|
||||
GtkPolicyType hscroll,
|
||||
GtkPolicyType vscroll);
|
||||
|
||||
void st_scroll_view_set_vshadows (StScrollView *self,
|
||||
gboolean vshadows);
|
||||
void st_scroll_view_set_vfade (StScrollView *self,
|
||||
gboolean vfade);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -319,17 +319,17 @@ function togglePolicy(button) {
|
||||
hpolicy.connect('clicked', function() { togglePolicy(hpolicy); });
|
||||
vpolicy.connect('clicked', function() { togglePolicy(vpolicy); });
|
||||
|
||||
let shadowsBox = new St.BoxLayout({ vertical: false });
|
||||
mainBox.add(shadowsBox);
|
||||
let fadeBox = new St.BoxLayout({ vertical: false });
|
||||
mainBox.add(fadeBox);
|
||||
|
||||
spacer = new St.Bin();
|
||||
shadowsBox.add(spacer, { expand: true });
|
||||
fadeBox.add(spacer, { expand: true });
|
||||
|
||||
shadowsBox.add(new St.Label({ text: 'Vertical Shadows: '}));
|
||||
let vshadows = new St.Button({ label: 'No', style: 'text-decoration: underline; color: #4444ff;' });
|
||||
shadowsBox.add(vshadows);
|
||||
fadeBox.add(new St.Label({ text: 'Vertical Fade: '}));
|
||||
let vfade = new St.Button({ label: 'No', style: 'text-decoration: underline; color: #4444ff;' });
|
||||
fadeBox.add(vfade);
|
||||
|
||||
function toggleShadows(button) {
|
||||
function toggleFade(button) {
|
||||
switch(button.label) {
|
||||
case 'No':
|
||||
button.label = 'Yes';
|
||||
@ -338,10 +338,10 @@ function toggleShadows(button) {
|
||||
button.label = 'No';
|
||||
break;
|
||||
}
|
||||
scrollView.set_vshadows(vshadows.label == 'Yes');
|
||||
scrollView.set_vfade(vfade.label == 'Yes');
|
||||
}
|
||||
|
||||
vshadows.connect('clicked', function() { toggleShadows(vshadows); });
|
||||
vfade.connect('clicked', function() { toggleFade(vfade); });
|
||||
|
||||
stage.show();
|
||||
Clutter.main();
|
||||
|
Loading…
Reference in New Issue
Block a user