Fixed GtkCellAreaIter to notify invalidation of sizes on flush
Also fixed GtkCellAreaBox to track the iters it creates and flush them when the overall layout configuration changes (add/remove/reorder/ spacing changed etc).
This commit is contained in:
parent
1dc7e3d885
commit
86fb6ab216
@ -97,7 +97,7 @@ static void gtk_cell_area_box_layout_reorder (GtkCellLayout
|
|||||||
gint position);
|
gint position);
|
||||||
|
|
||||||
|
|
||||||
/* CellInfo/CellGroup metadata handling */
|
/* CellInfo/CellGroup metadata handling and convenience functions */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GtkCellRenderer *renderer;
|
GtkCellRenderer *renderer;
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
GList *cells;
|
GList *cells;
|
||||||
|
|
||||||
guint id : 16;
|
guint id : 16;
|
||||||
guint expand : 1;
|
guint expand : 1;
|
||||||
} CellGroup;
|
} CellGroup;
|
||||||
|
|
||||||
@ -128,16 +128,20 @@ static GList *list_consecutive_cells (GtkCellAreaBox *box);
|
|||||||
static GList *construct_cell_groups (GtkCellAreaBox *box);
|
static GList *construct_cell_groups (GtkCellAreaBox *box);
|
||||||
static gint count_expand_groups (GtkCellAreaBox *box);
|
static gint count_expand_groups (GtkCellAreaBox *box);
|
||||||
static gint count_expand_cells (CellGroup *group);
|
static gint count_expand_cells (CellGroup *group);
|
||||||
|
static void iter_weak_notify (GtkCellAreaBox *box,
|
||||||
|
GtkCellAreaIter *dead_iter);
|
||||||
|
static void flush_iters (GtkCellAreaBox *box);
|
||||||
|
|
||||||
struct _GtkCellAreaBoxPrivate
|
struct _GtkCellAreaBoxPrivate
|
||||||
{
|
{
|
||||||
GtkOrientation orientation;
|
GtkOrientation orientation;
|
||||||
|
|
||||||
GList *cells;
|
GList *cells;
|
||||||
GList *groups;
|
GList *groups;
|
||||||
|
|
||||||
gint spacing;
|
GSList *iters;
|
||||||
|
|
||||||
|
gint spacing;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -168,6 +172,7 @@ gtk_cell_area_box_init (GtkCellAreaBox *box)
|
|||||||
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
|
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
|
||||||
priv->cells = NULL;
|
priv->cells = NULL;
|
||||||
priv->groups = NULL;
|
priv->groups = NULL;
|
||||||
|
priv->iters = NULL;
|
||||||
priv->spacing = 0;
|
priv->spacing = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +219,7 @@ gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
|
|||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* CellInfo/CellGroup Basics *
|
* CellInfo/CellGroup basics and convenience functions *
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
static CellInfo *
|
static CellInfo *
|
||||||
cell_info_new (GtkCellRenderer *renderer,
|
cell_info_new (GtkCellRenderer *renderer,
|
||||||
@ -379,6 +384,31 @@ count_expand_cells (CellGroup *group)
|
|||||||
return expand_cells;
|
return expand_cells;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
iter_weak_notify (GtkCellAreaBox *box,
|
||||||
|
GtkCellAreaIter *dead_iter)
|
||||||
|
{
|
||||||
|
GtkCellAreaBoxPrivate *priv = box->priv;
|
||||||
|
|
||||||
|
priv->iters = g_slist_remove (priv->iters, dead_iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
flush_iters (GtkCellAreaBox *box)
|
||||||
|
{
|
||||||
|
GtkCellAreaBoxPrivate *priv = box->priv;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
/* When the box layout changes, iters need to
|
||||||
|
* be flushed and sizes for the box get requested again
|
||||||
|
*/
|
||||||
|
for (l = priv->iters; l; l = l->next)
|
||||||
|
{
|
||||||
|
GtkCellAreaIter *iter = l->data;
|
||||||
|
|
||||||
|
gtk_cell_area_iter_flush (iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* GObjectClass *
|
* GObjectClass *
|
||||||
@ -386,6 +416,15 @@ count_expand_cells (CellGroup *group)
|
|||||||
static void
|
static void
|
||||||
gtk_cell_area_box_finalize (GObject *object)
|
gtk_cell_area_box_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
|
GtkCellAreaBox *box = GTK_CELL_AREA_BOX (object);
|
||||||
|
GtkCellAreaBoxPrivate *priv = box->priv;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
for (l = priv->iters; l; l = l->next)
|
||||||
|
g_object_weak_unref (G_OBJECT (l->data), (GWeakNotify)iter_weak_notify, box);
|
||||||
|
|
||||||
|
g_slist_free (priv->iters);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,15 +502,13 @@ gtk_cell_area_box_remove (GtkCellArea *area,
|
|||||||
|
|
||||||
priv->cells = g_list_delete_link (priv->cells, node);
|
priv->cells = g_list_delete_link (priv->cells, node);
|
||||||
|
|
||||||
/* Reconstruct cell groups
|
/* Reconstruct cell groups */
|
||||||
* XXX TODO: add a list of iters and weak_ref's on them, then
|
|
||||||
* flush the iters when we reconstruct groups, change spacing
|
|
||||||
* or child expand properties (i.e. notify size needs to be
|
|
||||||
* recalculated).
|
|
||||||
*/
|
|
||||||
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
|
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
|
||||||
g_list_free (priv->groups);
|
g_list_free (priv->groups);
|
||||||
priv->groups = construct_cell_groups (box);
|
priv->groups = construct_cell_groups (box);
|
||||||
|
|
||||||
|
/* Notify that size needs to be requested again */
|
||||||
|
flush_iters (box);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
g_warning ("Trying to remove a cell renderer that is not present GtkCellAreaBox");
|
g_warning ("Trying to remove a cell renderer that is not present GtkCellAreaBox");
|
||||||
@ -517,7 +554,16 @@ gtk_cell_area_box_render (GtkCellArea *area,
|
|||||||
static GtkCellAreaIter *
|
static GtkCellAreaIter *
|
||||||
gtk_cell_area_box_create_iter (GtkCellArea *area)
|
gtk_cell_area_box_create_iter (GtkCellArea *area)
|
||||||
{
|
{
|
||||||
return (GtkCellAreaIter *)g_object_new (GTK_TYPE_CELL_AREA_BOX_ITER, NULL);
|
GtkCellAreaBox *box = GTK_CELL_AREA_BOX (area);
|
||||||
|
GtkCellAreaBoxPrivate *priv = box->priv;
|
||||||
|
GtkCellAreaIter *iter =
|
||||||
|
(GtkCellAreaIter *)g_object_new (GTK_TYPE_CELL_AREA_BOX_ITER, NULL);
|
||||||
|
|
||||||
|
priv->iters = g_slist_prepend (priv->iters, iter);
|
||||||
|
|
||||||
|
g_object_weak_ref (G_OBJECT (iter), (GWeakNotify)iter_weak_notify, box);
|
||||||
|
|
||||||
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkSizeRequestMode
|
static GtkSizeRequestMode
|
||||||
@ -1012,6 +1058,14 @@ gtk_cell_area_box_layout_reorder (GtkCellLayout *cell_layout,
|
|||||||
|
|
||||||
priv->cells = g_list_delete_link (priv->cells, node);
|
priv->cells = g_list_delete_link (priv->cells, node);
|
||||||
priv->cells = g_list_insert (priv->cells, info, position);
|
priv->cells = g_list_insert (priv->cells, info, position);
|
||||||
|
|
||||||
|
/* Reconstruct cell groups */
|
||||||
|
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
|
||||||
|
g_list_free (priv->groups);
|
||||||
|
priv->groups = construct_cell_groups (box);
|
||||||
|
|
||||||
|
/* Notify that size needs to be requested again */
|
||||||
|
flush_iters (box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,10 +1103,13 @@ gtk_cell_area_box_pack_start (GtkCellAreaBox *box,
|
|||||||
|
|
||||||
priv->cells = g_list_append (priv->cells, info);
|
priv->cells = g_list_append (priv->cells, info);
|
||||||
|
|
||||||
/* Reconstruct cell groups (TODO, notify created iters that size needs renegotiation) */
|
/* Reconstruct cell groups */
|
||||||
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
|
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
|
||||||
g_list_free (priv->groups);
|
g_list_free (priv->groups);
|
||||||
priv->groups = construct_cell_groups (box);
|
priv->groups = construct_cell_groups (box);
|
||||||
|
|
||||||
|
/* Notify that size needs to be requested again */
|
||||||
|
flush_iters (box);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1080,10 +1137,13 @@ gtk_cell_area_box_pack_end (GtkCellAreaBox *box,
|
|||||||
|
|
||||||
priv->cells = g_list_append (priv->cells, info);
|
priv->cells = g_list_append (priv->cells, info);
|
||||||
|
|
||||||
/* Reconstruct cell groups (TODO, notify created iters that size needs renegotiation) */
|
/* Reconstruct cell groups */
|
||||||
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
|
g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
|
||||||
g_list_free (priv->groups);
|
g_list_free (priv->groups);
|
||||||
priv->groups = construct_cell_groups (box);
|
priv->groups = construct_cell_groups (box);
|
||||||
|
|
||||||
|
/* Notify that size needs to be requested again */
|
||||||
|
flush_iters (box);
|
||||||
}
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
@ -1108,7 +1168,9 @@ gtk_cell_area_box_set_spacing (GtkCellAreaBox *box,
|
|||||||
{
|
{
|
||||||
priv->spacing = spacing;
|
priv->spacing = spacing;
|
||||||
|
|
||||||
/* TODO, notify created iters that size needs renegotiation */
|
|
||||||
g_object_notify (G_OBJECT (box), "spacing");
|
g_object_notify (G_OBJECT (box), "spacing");
|
||||||
|
|
||||||
|
/* Notify that size needs to be requested again */
|
||||||
|
flush_iters (box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,6 +318,18 @@ gtk_cell_area_iter_real_flush_preferred_width (GtkCellAreaIter *iter)
|
|||||||
g_object_thaw_notify (G_OBJECT (iter));
|
g_object_thaw_notify (G_OBJECT (iter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
notify_invalid_height (gpointer width_ptr,
|
||||||
|
CachedSize *size,
|
||||||
|
GtkCellAreaIter *iter)
|
||||||
|
{
|
||||||
|
gint width = GPOINTER_TO_INT (width_ptr);
|
||||||
|
|
||||||
|
/* Notify size invalidated */
|
||||||
|
g_signal_emit (iter, cell_area_iter_signals[SIGNAL_HEIGHT_CHANGED],
|
||||||
|
0, width, -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_cell_area_iter_real_flush_preferred_height_for_width (GtkCellAreaIter *iter,
|
gtk_cell_area_iter_real_flush_preferred_height_for_width (GtkCellAreaIter *iter,
|
||||||
gint width)
|
gint width)
|
||||||
@ -326,11 +338,18 @@ gtk_cell_area_iter_real_flush_preferred_height_for_width (GtkCellAreaIter *iter,
|
|||||||
|
|
||||||
/* Flush all sizes for special -1 value */
|
/* Flush all sizes for special -1 value */
|
||||||
if (width < 0)
|
if (width < 0)
|
||||||
g_hash_table_remove_all (priv->heights);
|
{
|
||||||
|
g_hash_table_foreach (priv->heights, (GHFunc)notify_invalid_height, iter);
|
||||||
|
g_hash_table_remove_all (priv->heights);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
|
{
|
||||||
|
g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
|
||||||
|
|
||||||
/* XXX Should we bother signalling removed values as "size-changed" signals ? */
|
/* Notify size invalidated */
|
||||||
|
g_signal_emit (iter, cell_area_iter_signals[SIGNAL_HEIGHT_CHANGED],
|
||||||
|
0, width, -1, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -347,6 +366,18 @@ gtk_cell_area_iter_real_flush_preferred_height (GtkCellAreaIter *iter)
|
|||||||
g_object_thaw_notify (G_OBJECT (iter));
|
g_object_thaw_notify (G_OBJECT (iter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
notify_invalid_width (gpointer height_ptr,
|
||||||
|
CachedSize *size,
|
||||||
|
GtkCellAreaIter *iter)
|
||||||
|
{
|
||||||
|
gint height = GPOINTER_TO_INT (height_ptr);
|
||||||
|
|
||||||
|
/* Notify size invalidated */
|
||||||
|
g_signal_emit (iter, cell_area_iter_signals[SIGNAL_WIDTH_CHANGED],
|
||||||
|
0, height, -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_cell_area_iter_real_flush_preferred_width_for_height (GtkCellAreaIter *iter,
|
gtk_cell_area_iter_real_flush_preferred_width_for_height (GtkCellAreaIter *iter,
|
||||||
gint height)
|
gint height)
|
||||||
@ -355,11 +386,18 @@ gtk_cell_area_iter_real_flush_preferred_width_for_height (GtkCellAreaIter *iter,
|
|||||||
|
|
||||||
/* Flush all sizes for special -1 value */
|
/* Flush all sizes for special -1 value */
|
||||||
if (height < 0)
|
if (height < 0)
|
||||||
g_hash_table_remove_all (priv->widths);
|
{
|
||||||
|
g_hash_table_foreach (priv->widths, (GHFunc)notify_invalid_width, iter);
|
||||||
|
g_hash_table_remove_all (priv->widths);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
|
{
|
||||||
|
g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
|
||||||
|
|
||||||
/* XXX Should we bother signalling removed values as "size-changed" signals ? */
|
/* Notify size invalidated */
|
||||||
|
g_signal_emit (iter, cell_area_iter_signals[SIGNAL_WIDTH_CHANGED],
|
||||||
|
0, height, -1, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
|
Loading…
Reference in New Issue
Block a user