
In StBin, StBoxLayout, and StTable, if a child has a potential allocation that is larger than its preferred size, we give it its preferred size instead. However, the corresponding get_preferred_height/width methods were not making the same assumption, which meant that if we had more width than the widget wanted, we would allocate it its preferred width, but with the height that corresponded to the larger width. Fix this by defining new helpers _st_actor_get_preferred_width() and _st_actor_get_preferred_height() and using them everywhere. Also, make StBin and StTable use _st_allocate_fill() rather than having nearly-identical duplicate copies of the code. https://bugzilla.gnome.org/show_bug.cgi?id=609848
166 lines
4.5 KiB
C
166 lines
4.5 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/**
|
|
* SECTION:shell-slicer
|
|
* @short_description: Display only part of another actor
|
|
*
|
|
* A #StBin that has 0 minimum size, and will clip its child
|
|
* in the middle.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "shell-slicer.h"
|
|
|
|
G_DEFINE_TYPE (ShellSlicer,
|
|
shell_slicer,
|
|
ST_TYPE_BIN);
|
|
|
|
static void
|
|
shell_slicer_get_preferred_width (ClutterActor *self,
|
|
gfloat for_height,
|
|
gfloat *min_width_p,
|
|
gfloat *natural_width_p)
|
|
{
|
|
ClutterActor *child = st_bin_get_child (ST_BIN (self));
|
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
|
|
|
|
st_theme_node_adjust_for_height (theme_node, &for_height);
|
|
|
|
if (min_width_p)
|
|
*min_width_p = 0;
|
|
|
|
if (child == NULL)
|
|
{
|
|
if (natural_width_p)
|
|
*natural_width_p = 0;
|
|
}
|
|
else
|
|
{
|
|
_st_actor_get_preferred_width (child, for_height, FALSE,
|
|
NULL,
|
|
natural_width_p);
|
|
}
|
|
|
|
st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
|
|
}
|
|
|
|
static void
|
|
shell_slicer_get_preferred_height (ClutterActor *self,
|
|
gfloat for_width,
|
|
gfloat *min_height_p,
|
|
gfloat *natural_height_p)
|
|
{
|
|
ClutterActor *child = st_bin_get_child (ST_BIN (self));
|
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
|
|
|
|
st_theme_node_adjust_for_width (theme_node, &for_width);
|
|
|
|
if (min_height_p)
|
|
*min_height_p = 0;
|
|
|
|
if (child == NULL)
|
|
{
|
|
if (natural_height_p)
|
|
*natural_height_p = 0;
|
|
}
|
|
else
|
|
{
|
|
_st_actor_get_preferred_height (child, for_width, FALSE,
|
|
NULL,
|
|
natural_height_p);
|
|
}
|
|
|
|
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
|
|
}
|
|
|
|
static void
|
|
shell_slicer_allocate (ClutterActor *self,
|
|
const ClutterActorBox *box,
|
|
ClutterAllocationFlags flags)
|
|
{
|
|
ClutterActor *child;
|
|
|
|
/* Chain up directly to ClutterActor to set actor->allocation. We explicitly skip our parent class
|
|
* StBin here because we want to override the allocate function. */
|
|
CLUTTER_ACTOR_CLASS (g_type_class_peek (clutter_actor_get_type ()))->allocate (self, box, flags);
|
|
|
|
child = st_bin_get_child (ST_BIN (self));
|
|
if (child)
|
|
clutter_actor_allocate_preferred_size (child, flags);
|
|
}
|
|
|
|
static void
|
|
shell_slicer_paint_child (ShellSlicer *self)
|
|
{
|
|
ClutterActor *child;
|
|
ClutterActorBox self_box;
|
|
ClutterActorBox child_box;
|
|
float width, height, child_width, child_height;
|
|
StAlign x_align, y_align;
|
|
double x_align_factor, y_align_factor;
|
|
|
|
child = st_bin_get_child (ST_BIN (self));
|
|
|
|
if (!child)
|
|
return;
|
|
|
|
st_bin_get_alignment (ST_BIN (self), &x_align, &y_align);
|
|
_st_get_align_factors (ST_WIDGET (self), x_align, y_align,
|
|
&x_align_factor, &y_align_factor);
|
|
|
|
clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &self_box);
|
|
clutter_actor_get_allocation_box (child, &child_box);
|
|
|
|
width = self_box.x2 - self_box.x1;
|
|
height = self_box.y2 - self_box.y1;
|
|
child_width = child_box.x2 - child_box.x1;
|
|
child_height = child_box.y2 - child_box.y1;
|
|
|
|
cogl_push_matrix ();
|
|
|
|
cogl_clip_push (0, 0, width, height);
|
|
cogl_translate ((int)(0.5 + x_align_factor * (width - child_width)),
|
|
(int)(0.5 + y_align_factor * (height - child_height)),
|
|
0);
|
|
|
|
clutter_actor_paint (child);
|
|
|
|
cogl_clip_pop ();
|
|
|
|
cogl_pop_matrix ();
|
|
}
|
|
|
|
static void
|
|
shell_slicer_paint (ClutterActor *self)
|
|
{
|
|
/* StWidget paints CSS elements */
|
|
CLUTTER_ACTOR_CLASS (g_type_class_peek (st_widget_get_type ()))->paint (self);
|
|
|
|
shell_slicer_paint_child (SHELL_SLICER (self));
|
|
}
|
|
|
|
static void
|
|
shell_slicer_pick (ClutterActor *self,
|
|
const ClutterColor *pick_color)
|
|
{
|
|
shell_slicer_paint_child (SHELL_SLICER (self));
|
|
}
|
|
|
|
static void
|
|
shell_slicer_class_init (ShellSlicerClass *klass)
|
|
{
|
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
|
|
|
actor_class->get_preferred_width = shell_slicer_get_preferred_width;
|
|
actor_class->get_preferred_height = shell_slicer_get_preferred_height;
|
|
actor_class->allocate = shell_slicer_allocate;
|
|
actor_class->paint = shell_slicer_paint;
|
|
actor_class->pick = shell_slicer_pick;
|
|
}
|
|
|
|
static void
|
|
shell_slicer_init (ShellSlicer *actor)
|
|
{
|
|
}
|