st-scroll-view: Add :overlay-scrollbars property

If enabled, scrollbars take away from the allocation given to the
view's content. This is usually preferrable to painting the bars on
top of the content, but there are exceptions, for instance when the
content needs to be centered with regard to the view as a whole.
Add a :overlay-scrollbars property to account for those cases.

https://bugzilla.gnome.org/show_bug.cgi?id=694261
This commit is contained in:
Florian Müllner 2013-02-21 22:30:09 +01:00
parent 7425b382d6
commit 1bd8c67041
3 changed files with 91 additions and 8 deletions

View File

@ -101,6 +101,7 @@ struct _StScrollViewPrivate
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;
guint overlay_scrollbars : 1;
guint hscrollbar_visible : 1; guint hscrollbar_visible : 1;
guint vscrollbar_visible : 1; guint vscrollbar_visible : 1;
}; };
@ -115,6 +116,7 @@ enum {
PROP_HSCROLLBAR_VISIBLE, PROP_HSCROLLBAR_VISIBLE,
PROP_VSCROLLBAR_VISIBLE, PROP_VSCROLLBAR_VISIBLE,
PROP_MOUSE_SCROLL, PROP_MOUSE_SCROLL,
PROP_OVERLAY_SCROLLBARS,
}; };
static void static void
@ -148,6 +150,9 @@ 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_OVERLAY_SCROLLBARS:
g_value_set_boolean (value, priv->overlay_scrollbars);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
} }
@ -212,6 +217,10 @@ st_scroll_view_set_property (GObject *object,
st_scroll_view_set_mouse_scrolling (self, st_scroll_view_set_mouse_scrolling (self,
g_value_get_boolean (value)); g_value_get_boolean (value));
break; break;
case PROP_OVERLAY_SCROLLBARS:
st_scroll_view_set_overlay_scrollbars (self,
g_value_get_boolean (value));
break;
case PROP_HSCROLLBAR_POLICY: case PROP_HSCROLLBAR_POLICY:
st_scroll_view_set_policy (self, st_scroll_view_set_policy (self,
g_value_get_enum (value), g_value_get_enum (value),
@ -376,14 +385,14 @@ st_scroll_view_get_preferred_width (ClutterActor *actor,
account_for_vscrollbar = FALSE; account_for_vscrollbar = FALSE;
break; break;
case GTK_POLICY_ALWAYS: case GTK_POLICY_ALWAYS:
account_for_vscrollbar = TRUE; account_for_vscrollbar = !priv->overlay_scrollbars;
break; break;
case GTK_POLICY_AUTOMATIC: case GTK_POLICY_AUTOMATIC:
/* For automatic scrollbars, we always request space for the vertical /* For automatic scrollbars, we always request space for the vertical
* scrollbar; we won't know whether we actually need one until our * scrollbar; we won't know whether we actually need one until our
* height is assigned in allocate(). * height is assigned in allocate().
*/ */
account_for_vscrollbar = TRUE; account_for_vscrollbar = !priv->overlay_scrollbars;
break; break;
} }
@ -448,14 +457,14 @@ st_scroll_view_get_preferred_height (ClutterActor *actor,
account_for_hscrollbar = FALSE; account_for_hscrollbar = FALSE;
break; break;
case GTK_POLICY_ALWAYS: case GTK_POLICY_ALWAYS:
account_for_hscrollbar = TRUE; account_for_hscrollbar = !priv->overlay_scrollbars;
break; break;
case GTK_POLICY_AUTOMATIC: case GTK_POLICY_AUTOMATIC:
/* For automatic scrollbars, we always request space for the horizontal /* For automatic scrollbars, we always request space for the horizontal
* scrollbar; we won't know whether we actually need one until our * scrollbar; we won't know whether we actually need one until our
* width is assigned in allocate(). * width is assigned in allocate().
*/ */
account_for_hscrollbar = TRUE; account_for_hscrollbar = !priv->overlay_scrollbars;
break; break;
} }
@ -626,14 +635,15 @@ st_scroll_view_allocate (ClutterActor *actor,
clutter_actor_allocate (priv->hscroll, &child_box, flags); clutter_actor_allocate (priv->hscroll, &child_box, flags);
} }
/* In case the scrollbar policy is NEVER, we don't trim the content /* In case the scrollbar policy is NEVER or scrollbars should be
* box allocation by the scrollbar size. * overlayed, we don't trim the content box allocation by the
* scrollbar size.
* Fold this into the scrollbar sizes to simplify the rest of the * Fold this into the scrollbar sizes to simplify the rest of the
* computations. * computations.
*/ */
if (priv->hscrollbar_policy == GTK_POLICY_NEVER) if (priv->hscrollbar_policy == GTK_POLICY_NEVER || priv->overlay_scrollbars)
sb_height = 0; sb_height = 0;
if (priv->vscrollbar_policy == GTK_POLICY_NEVER) if (priv->vscrollbar_policy == GTK_POLICY_NEVER || priv->overlay_scrollbars)
sb_width = 0; sb_width = 0;
/* Child */ /* Child */
@ -828,6 +838,14 @@ st_scroll_view_class_init (StScrollViewClass *klass)
PROP_MOUSE_SCROLL, PROP_MOUSE_SCROLL,
pspec); pspec);
pspec = g_param_spec_boolean ("overlay-scrollbars",
"Use Overlay Scrollbars",
"Overlay scrollbars over the content",
FALSE,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_OVERLAY_SCROLLBARS,
pspec);
} }
static void static void
@ -1090,6 +1108,49 @@ st_scroll_view_get_mouse_scrolling (StScrollView *scroll)
return priv->mouse_scroll; return priv->mouse_scroll;
} }
/**
* st_scroll_view_set_overlay_scrollbars:
* @scroll: A #StScrollView
* @enabled: Whether to enable overlay scrollbars
*
* Sets whether scrollbars are painted on top of the content.
*/
void
st_scroll_view_set_overlay_scrollbars (StScrollView *scroll,
gboolean enabled)
{
StScrollViewPrivate *priv;
g_return_if_fail (ST_IS_SCROLL_VIEW (scroll));
priv = ST_SCROLL_VIEW (scroll)->priv;
if (priv->overlay_scrollbars != enabled)
{
priv->overlay_scrollbars = enabled;
g_object_notify (G_OBJECT (scroll), "overlay-scrollbars");
clutter_actor_queue_relayout (CLUTTER_ACTOR (scroll));
}
}
/**
* st_scroll_view_get_overlay_scrollbars:
* @scroll: A #StScrollView
*
* Gets the value set by st_scroll_view_set_overlay_scrollbars().
*/
gboolean
st_scroll_view_get_overlay_scrollbars (StScrollView *scroll)
{
StScrollViewPrivate *priv;
g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), FALSE);
priv = ST_SCROLL_VIEW (scroll)->priv;
return priv->overlay_scrollbars;
}
/** /**
* st_scroll_view_set_policy: * st_scroll_view_set_policy:
* @scroll: A #StScrollView * @scroll: A #StScrollView

View File

@ -80,6 +80,10 @@ void st_scroll_view_set_mouse_scrolling (StScrollView *scroll,
gboolean enabled); gboolean enabled);
gboolean st_scroll_view_get_mouse_scrolling (StScrollView *scroll); gboolean st_scroll_view_get_mouse_scrolling (StScrollView *scroll);
void st_scroll_view_set_overlay_scrollbars (StScrollView *scroll,
gboolean enabled);
gboolean st_scroll_view_get_overlay_scrollbars (StScrollView *scroll);
void st_scroll_view_set_policy (StScrollView *scroll, void st_scroll_view_set_policy (StScrollView *scroll,
GtkPolicyType hscroll, GtkPolicyType hscroll,
GtkPolicyType vscroll); GtkPolicyType vscroll);

View File

@ -339,6 +339,10 @@ function test() {
let vfade = new St.Button({ label: 'No', style: 'text-decoration: underline; color: #4444ff;' }); let vfade = new St.Button({ label: 'No', style: 'text-decoration: underline; color: #4444ff;' });
fadeBox.add(vfade); fadeBox.add(vfade);
fadeBox.add(new St.Label({ text: 'Overlay scrollbars: '}));
let overlay = new St.Button({ label: 'No', style: 'text-decoration: underline; color: #4444ff;' });
fadeBox.add(overlay);
function togglePadding(button) { function togglePadding(button) {
switch(button.label) { switch(button.label) {
case 'No': case 'No':
@ -388,6 +392,20 @@ function test() {
vfade.connect('clicked', function() { toggleFade(vfade); }); vfade.connect('clicked', function() { toggleFade(vfade); });
toggleFade(vfade); toggleFade(vfade);
function toggleOverlay(button) {
switch(button.label) {
case 'No':
button.label = 'Yes';
break;
case 'Yes':
button.label = 'No';
break;
}
scrollView.overlay_scrollbars = (button.label == 'Yes');
}
overlay.connect('clicked', function() { toggleOverlay(overlay); });
UI.main(stage); UI.main(stage);
} }
test(); test();