Centralize computations of border and padding into StThemeNode

Rather than repeating the computation of borders in many different
widget subclasses, add helper functions:

 st_theme_node_adjust_for_height()
 st_theme_node_adjust_preferred_width()
 st_theme_node_adjust_for_width()
 st_theme_node_adjust_preferred_height()
 st_theme_node_get_content_box()

That are used in get_preferred_width()/get_preferred_height() and
allocate() methods to consistently apply the necessary adjustments.
This allows removing the StPadding type.

Queueing a relayout when the borders/padding change is moved from
st_widget_real_style_changed() to the invoking code to allow access
to the old StThemeNode for comparison. (Should this be added as
a parameter to the signal?)

Borders are included in the geometry adjustments, but borders
are not yet drawn.

https://bugzilla.gnome.org/show_bug.cgi?id=595993
This commit is contained in:
Owen W. Taylor
2009-09-20 13:41:13 -04:00
parent 8c72623da3
commit 076e902b2c
12 changed files with 446 additions and 387 deletions

View File

@ -28,6 +28,7 @@
#include "config.h"
#endif
#include <math.h>
#include <stdlib.h>
#include <string.h>
@ -47,9 +48,6 @@
*/
struct _StWidgetPrivate
{
StPadding border;
StPadding padding;
StTheme *theme;
StThemeNode *theme_node;
gchar *pseudo_class;
@ -106,6 +104,9 @@ G_DEFINE_ABSTRACT_TYPE (StWidget, st_widget, CLUTTER_TYPE_ACTOR);
#define ST_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_WIDGET, StWidgetPrivate))
static void st_widget_recompute_style (StWidget *widget,
StThemeNode *old_theme_node);
static void
st_widget_set_property (GObject *gobject,
guint prop_id,
@ -484,7 +485,6 @@ st_widget_real_style_changed (StWidget *self)
const char *bg_file = NULL;
gboolean relayout_needed = FALSE;
gboolean has_changed = FALSE;
StPadding padding;
ClutterColor color;
/* application has request this widget is not stylable */
@ -500,21 +500,6 @@ st_widget_real_style_changed (StWidget *self)
has_changed = TRUE;
}
padding.top = st_theme_node_get_padding (theme_node, ST_SIDE_TOP);
padding.right = st_theme_node_get_padding (theme_node, ST_SIDE_RIGHT);
padding.bottom = st_theme_node_get_padding (theme_node, ST_SIDE_BOTTOM);
padding.left = st_theme_node_get_padding (theme_node, ST_SIDE_LEFT);
if (priv->padding.top != padding.top ||
priv->padding.left != padding.left ||
priv->padding.right != padding.right ||
priv->padding.bottom != padding.bottom)
{
priv->padding = padding;
has_changed = TRUE;
relayout_needed = TRUE;
}
if (priv->border_image)
{
clutter_actor_unparent (priv->border_image);
@ -597,18 +582,21 @@ st_widget_real_style_changed (StWidget *self)
void
st_widget_style_changed (StWidget *widget)
{
StThemeNode *old_theme_node = NULL;
widget->priv->is_style_dirty = TRUE;
if (widget->priv->theme_node)
{
g_object_unref (widget->priv->theme_node);
old_theme_node = widget->priv->theme_node;
widget->priv->theme_node = NULL;
}
/* update the style only if we are mapped */
if (!CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (widget)))
return;
if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (widget)))
st_widget_recompute_style (widget, old_theme_node);
st_widget_ensure_style (widget);
if (old_theme_node)
g_object_unref (old_theme_node);
}
static void
@ -1064,6 +1052,20 @@ st_widget_init (StWidget *actor)
g_signal_connect (actor, "notify::name", G_CALLBACK (st_widget_name_notify), NULL);
}
static void
st_widget_recompute_style (StWidget *widget,
StThemeNode *old_theme_node)
{
StThemeNode *new_theme_node = st_widget_get_theme_node (widget);
if (!old_theme_node ||
!st_theme_node_geometry_equal (old_theme_node, new_theme_node))
clutter_actor_queue_relayout ((ClutterActor *) widget);
g_signal_emit (widget, signals[STYLE_CHANGED], 0);
widget->priv->is_style_dirty = FALSE;
}
/**
* st_widget_ensure_style:
* @widget: A #StWidget
@ -1077,10 +1079,7 @@ st_widget_ensure_style (StWidget *widget)
g_return_if_fail (ST_IS_WIDGET (widget));
if (widget->priv->is_style_dirty)
{
g_signal_emit (widget, signals[STYLE_CHANGED], 0);
widget->priv->is_style_dirty = FALSE;
}
st_widget_recompute_style (widget, NULL);
}
/**
@ -1117,25 +1116,6 @@ st_widget_get_background_image (StWidget *actor)
return priv->background_image;
}
/**
* st_widget_get_padding:
* @widget: A #StWidget
* @padding: A pointer to an #StPadding to fill
*
* Gets the padding of the widget, set using the "padding" CSS property. This
* function should normally only be used by subclasses.
*
*/
void
st_widget_get_padding (StWidget *widget,
StPadding *padding)
{
g_return_if_fail (ST_IS_WIDGET (widget));
g_return_if_fail (padding != NULL);
*padding = widget->priv->padding;
}
/**
* st_widget_set_has_tooltip:
* @widget: A #StWidget