Added proper handling of right to left layouting of cells to GtkCellAreaBox.

This commit is contained in:
Tristan Van Berkom 2010-12-05 15:20:46 +09:00
parent c6e1463d1e
commit f24c21f1f0
2 changed files with 80 additions and 24 deletions

View File

@ -2986,8 +2986,6 @@ gtk_cell_area_activate_cell (GtkCellArea *area,
priv = area->priv; priv = area->priv;
/* Remove margins from the background area to produce the cell area. /* Remove margins from the background area to produce the cell area.
*
* XXX Maybe have to do some rtl mode treatment here...
*/ */
gtk_cell_area_inner_cell_area (area, widget, cell_area, &inner_area); gtk_cell_area_inner_cell_area (area, widget, cell_area, &inner_area);

View File

@ -205,6 +205,10 @@ struct _GtkCellAreaBoxPrivate
GSList *contexts; GSList *contexts;
gint spacing; gint spacing;
/* We hold on to the rtl state from a widget we are requested for
* so that we can navigate focus correctly */
gboolean rtl;
}; };
enum { enum {
@ -244,6 +248,7 @@ gtk_cell_area_box_init (GtkCellAreaBox *box)
priv->cells = NULL; priv->cells = NULL;
priv->contexts = NULL; priv->contexts = NULL;
priv->spacing = 0; priv->spacing = 0;
priv->rtl = FALSE;
} }
static void static void
@ -636,13 +641,17 @@ allocate_cells_manually (GtkCellAreaBox *box,
GtkRequestedSize *sizes; GtkRequestedSize *sizes;
gint i; gint i;
gint nvisible = 0, nexpand = 0, group_expand; gint nvisible = 0, nexpand = 0, group_expand;
gint avail_size, extra_size, extra_extra; gint avail_size, extra_size, extra_extra, full_size;
gint position = 0, for_size; gint position = 0, for_size;
gboolean rtl;
if (!priv->cells) if (!priv->cells)
return NULL; return NULL;
/* For vertical oriented boxes, we just let the cell renderers realign themselves for rtl */
rtl = (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
cells = list_consecutive_cells (box); cells = list_consecutive_cells (box);
/* Count the visible and expand cells */ /* Count the visible and expand cells */
@ -662,13 +671,13 @@ allocate_cells_manually (GtkCellAreaBox *box,
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{ {
avail_size = width; full_size = avail_size = width;
for_size = height; for_size = height;
} }
else else
{ {
avail_size = height; full_size = avail_size = height;
for_size = width; for_size = width;
} }
/* Go ahead and collect the requests on the fly */ /* Go ahead and collect the requests on the fly */
@ -722,7 +731,12 @@ allocate_cells_manually (GtkCellAreaBox *box,
} }
} }
cell = allocated_cell_new (info->renderer, position, sizes[i].minimum_size); if (rtl)
cell = allocated_cell_new (info->renderer,
full_size - (position + sizes[i].minimum_size),
sizes[i].minimum_size);
else
cell = allocated_cell_new (info->renderer, position, sizes[i].minimum_size);
allocated_cells = g_slist_prepend (allocated_cells, cell); allocated_cells = g_slist_prepend (allocated_cells, cell);
@ -755,16 +769,27 @@ get_allocated_cells (GtkCellAreaBox *box,
GList *cell_list; GList *cell_list;
GSList *allocated_cells = NULL; GSList *allocated_cells = NULL;
gint i, j, n_allocs; gint i, j, n_allocs;
gint for_size; gint for_size, full_size;
gboolean rtl;
group_allocs = gtk_cell_area_box_context_get_orientation_allocs (context, &n_allocs); group_allocs = gtk_cell_area_box_context_get_orientation_allocs (context, &n_allocs);
if (!group_allocs) if (!group_allocs)
return allocate_cells_manually (box, widget, width, height); return allocate_cells_manually (box, widget, width, height);
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
for_size = height; {
full_size = width;
for_size = height;
}
else else
for_size = width; {
full_size = height;
for_size = width;
}
/* For vertical oriented boxes, we just let the cell renderers realign themselves for rtl */
rtl = (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
for (i = 0; i < n_allocs; i++) for (i = 0; i < n_allocs; i++)
{ {
@ -777,8 +802,14 @@ get_allocated_cells (GtkCellAreaBox *box,
if (group->n_cells == 1) if (group->n_cells == 1)
{ {
CellInfo *info = group->cells->data; CellInfo *info = group->cells->data;
AllocatedCell *cell = AllocatedCell *cell;
allocated_cell_new (info->renderer, group_allocs[i].position, group_allocs[i].size);
if (rtl)
cell = allocated_cell_new (info->renderer,
full_size - (group_allocs[i].position + group_allocs[i].size),
group_allocs[i].size);
else
cell = allocated_cell_new (info->renderer, group_allocs[i].position, group_allocs[i].size);
allocated_cells = g_slist_prepend (allocated_cells, cell); allocated_cells = g_slist_prepend (allocated_cells, cell);
} }
@ -854,7 +885,12 @@ get_allocated_cells (GtkCellAreaBox *box,
} }
} }
cell = allocated_cell_new (info->renderer, position, sizes[j].minimum_size); if (rtl)
cell = allocated_cell_new (info->renderer,
full_size - (position + sizes[j].minimum_size),
sizes[j].minimum_size);
else
cell = allocated_cell_new (info->renderer, position, sizes[j].minimum_size);
allocated_cells = g_slist_prepend (allocated_cells, cell); allocated_cells = g_slist_prepend (allocated_cells, cell);
@ -1184,6 +1220,10 @@ gtk_cell_area_box_render (GtkCellArea *area,
GdkRectangle focus_rect = { 0, }; GdkRectangle focus_rect = { 0, };
gboolean first_focus_cell = TRUE; gboolean first_focus_cell = TRUE;
gboolean focus_all = FALSE; gboolean focus_all = FALSE;
gboolean rtl;
rtl = (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
/* Make sure we dont paint a focus rectangle while there /* Make sure we dont paint a focus rectangle while there
* is an editable widget in play * is an editable widget in play
@ -1232,18 +1272,28 @@ gtk_cell_area_box_render (GtkCellArea *area,
* be user resizable and can be resized to be smaller than * be user resizable and can be resized to be smaller than
* the actual requested area). */ * the actual requested area). */
if (cell_background.x > cell_area->x + cell_area->width || if (cell_background.x > cell_area->x + cell_area->width ||
cell_background.x + cell_background.width < cell_area->x ||
cell_background.y > cell_area->y + cell_area->height) cell_background.y > cell_area->y + cell_area->height)
break; break;
/* Special case for the last cell... let the last cell consume the remaining /* Special case for the last cell (or first cell in rtl)... let the last cell consume
* space in the area (the last cell is allowed to consume the remaining space if * the remaining space in the area (the last cell is allowed to consume the remaining
* the space given for rendering is actually larger than allocation, this can * space if the space given for rendering is actually larger than allocation, this can
* happen in the expander GtkTreeViewColumn where only the deepest depth column * happen in the expander GtkTreeViewColumn where only the deepest depth column
* receives the allocation... shallow columns recieve more width). */ * receives the allocation... shallow columns recieve more width). */
if (!l->next) if (!l->next)
{ {
cell_background.width = cell_area->x + cell_area->width - cell_background.x; if (rtl)
cell_background.height = cell_area->y + cell_area->height - cell_background.y; {
/* Fill the leading space for the first cell in the area (still last in the list) */
cell_background.width = (cell_background.x - cell_area->x) + cell_background.width;
cell_background.x = cell_area->x;
}
else
{
cell_background.width = cell_area->x + cell_area->width - cell_background.x;
cell_background.height = cell_area->y + cell_area->height - cell_background.y;
}
} }
else else
{ {
@ -1560,6 +1610,10 @@ compute_size (GtkCellAreaBox *box,
*minimum_size = min_size; *minimum_size = min_size;
*natural_size = nat_size; *natural_size = nat_size;
/* Update rtl state for focus navigation to work */
priv->rtl = (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
} }
GtkRequestedSize * GtkRequestedSize *
@ -1766,6 +1820,10 @@ compute_size_for_opposing_orientation (GtkCellAreaBox *box,
*natural_size = nat_size; *natural_size = nat_size;
g_free (orientation_sizes); g_free (orientation_sizes);
/* Update rtl state for focus navigation to work */
priv->rtl = (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
} }
@ -1925,10 +1983,10 @@ gtk_cell_area_box_focus (GtkCellArea *area,
switch (direction) switch (direction)
{ {
case GTK_DIR_TAB_FORWARD: case GTK_DIR_TAB_FORWARD:
cycle = FOCUS_NEXT; cycle = priv->rtl ? FOCUS_PREV : FOCUS_NEXT;
break; break;
case GTK_DIR_TAB_BACKWARD: case GTK_DIR_TAB_BACKWARD:
cycle = FOCUS_PREV; cycle = priv->rtl ? FOCUS_NEXT : FOCUS_PREV;
break; break;
case GTK_DIR_UP: case GTK_DIR_UP:
if (priv->orientation == GTK_ORIENTATION_VERTICAL || !focus_cell) if (priv->orientation == GTK_ORIENTATION_VERTICAL || !focus_cell)
@ -1940,11 +1998,11 @@ gtk_cell_area_box_focus (GtkCellArea *area,
break; break;
case GTK_DIR_LEFT: case GTK_DIR_LEFT:
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL || !focus_cell) if (priv->orientation == GTK_ORIENTATION_HORIZONTAL || !focus_cell)
cycle = FOCUS_PREV; cycle = priv->rtl ? FOCUS_NEXT : FOCUS_PREV;
break; break;
case GTK_DIR_RIGHT: case GTK_DIR_RIGHT:
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL || !focus_cell) if (priv->orientation == GTK_ORIENTATION_HORIZONTAL || !focus_cell)
cycle = FOCUS_NEXT; cycle = priv->rtl ? FOCUS_PREV : FOCUS_NEXT;
break; break;
default: default:
break; break;