mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 05:31:07 +00:00
listview: Support CSS border-spacing
Hopefully the code can deal with gaps between the tiles. We use gtk_list_item_manager_get_nearest_tile() when necessary.
This commit is contained in:
parent
5583fa60c1
commit
196372f124
@ -23,6 +23,8 @@
|
||||
|
||||
#include "gtkadjustment.h"
|
||||
#include "gtkbitset.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
#include "gtkcsspositionvalueprivate.h"
|
||||
#include "gtkdragsourceprivate.h"
|
||||
#include "gtkdropcontrollermotion.h"
|
||||
#include "gtkgesturedrag.h"
|
||||
@ -1995,6 +1997,30 @@ gtk_list_base_get_orientation (GtkListBase *self)
|
||||
return priv->orientation;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_list_base_get_border_spacing (GtkListBase *self,
|
||||
int *xspacing,
|
||||
int *yspacing)
|
||||
{
|
||||
GtkCssStyle *style = gtk_css_node_get_style (gtk_widget_get_css_node (GTK_WIDGET (self)));
|
||||
GtkCssValue *border_spacing = style->size->border_spacing;
|
||||
|
||||
if (gtk_list_base_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
if (xspacing)
|
||||
*xspacing = _gtk_css_position_value_get_y (border_spacing, 0);
|
||||
if (yspacing)
|
||||
*yspacing = _gtk_css_position_value_get_x (border_spacing, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xspacing)
|
||||
*xspacing = _gtk_css_position_value_get_x (border_spacing, 0);
|
||||
if (yspacing)
|
||||
*yspacing = _gtk_css_position_value_get_y (border_spacing, 0);
|
||||
}
|
||||
}
|
||||
|
||||
GtkListItemManager *
|
||||
gtk_list_base_get_manager (GtkListBase *self)
|
||||
{
|
||||
|
@ -62,6 +62,9 @@ struct _GtkListBaseClass
|
||||
GtkOrientation gtk_list_base_get_orientation (GtkListBase *self);
|
||||
#define gtk_list_base_get_opposite_orientation(self) OPPOSITE_ORIENTATION(gtk_list_base_get_orientation(self))
|
||||
guint gtk_list_base_get_focus_position (GtkListBase *self);
|
||||
void gtk_list_base_get_border_spacing (GtkListBase *self,
|
||||
int *xspacing,
|
||||
int *yspacing);
|
||||
GtkListItemManager * gtk_list_base_get_manager (GtkListBase *self);
|
||||
GtkScrollablePolicy gtk_list_base_get_scroll_policy (GtkListBase *self,
|
||||
GtkOrientation orientation);
|
||||
|
@ -193,22 +193,23 @@ gtk_list_view_split (GtkListBase *base,
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (base);
|
||||
GtkListTile *new_tile;
|
||||
guint row_height;
|
||||
int spacing, row_height;
|
||||
|
||||
row_height = tile->area.height / tile->n_items;
|
||||
gtk_list_base_get_border_spacing (GTK_LIST_BASE (self), NULL, &spacing);
|
||||
row_height = (tile->area.height - (tile->n_items - 1) * spacing) / tile->n_items;
|
||||
|
||||
new_tile = gtk_list_tile_split (self->item_manager, tile, n_items);
|
||||
gtk_list_tile_set_area_size (self->item_manager,
|
||||
tile,
|
||||
tile->area.width,
|
||||
row_height * tile->n_items);
|
||||
row_height * tile->n_items + spacing * (tile->n_items - 1));
|
||||
gtk_list_tile_set_area (self->item_manager,
|
||||
new_tile,
|
||||
&(GdkRectangle) {
|
||||
tile->area.x,
|
||||
tile->area.y + tile->area.height,
|
||||
tile->area.y + tile->area.height + spacing,
|
||||
tile->area.width,
|
||||
row_height * new_tile->n_items
|
||||
row_height * new_tile->n_items + spacing * (new_tile->n_items - 1)
|
||||
});
|
||||
|
||||
return new_tile;
|
||||
@ -239,6 +240,9 @@ gtk_list_view_get_allocation (GtkListBase *base,
|
||||
{
|
||||
/* item is not allocated yet */
|
||||
GtkListTile *other;
|
||||
int spacing;
|
||||
|
||||
gtk_list_base_get_border_spacing (GTK_LIST_BASE (self), NULL, &spacing);
|
||||
|
||||
for (other = gtk_rb_tree_node_get_previous (tile);
|
||||
other;
|
||||
@ -248,7 +252,7 @@ gtk_list_view_get_allocation (GtkListBase *base,
|
||||
{
|
||||
area->x = other->area.x;
|
||||
area->width = other->area.width;
|
||||
area->y = other->area.y + other->area.height;
|
||||
area->y = other->area.y + other->area.height + spacing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -262,7 +266,7 @@ gtk_list_view_get_allocation (GtkListBase *base,
|
||||
{
|
||||
area->x = other->area.x;
|
||||
area->width = other->area.width;
|
||||
area->y = other->area.y;
|
||||
area->y = MAX (0, other->area.y - spacing);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -272,36 +276,6 @@ gtk_list_view_get_allocation (GtkListBase *base,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GtkBitset *
|
||||
gtk_list_view_get_items_in_rect (GtkListBase *base,
|
||||
const cairo_rectangle_int_t *rect)
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (base);
|
||||
guint first, last, n_items;
|
||||
GtkBitset *result;
|
||||
GtkListTile *tile;
|
||||
|
||||
result = gtk_bitset_new_empty ();
|
||||
|
||||
n_items = gtk_list_base_get_n_items (base);
|
||||
if (n_items == 0)
|
||||
return result;
|
||||
|
||||
tile = gtk_list_item_manager_get_tile_at (self->item_manager, 0, rect->y);
|
||||
if (tile)
|
||||
first = gtk_list_tile_get_position (self->item_manager, tile);
|
||||
else
|
||||
first = rect->y < 0 ? 0 : n_items - 1;
|
||||
tile = gtk_list_item_manager_get_tile_at (self->item_manager, 0, rect->y + rect->height);
|
||||
if (tile)
|
||||
last = gtk_list_tile_get_position (self->item_manager, tile);
|
||||
else
|
||||
last = rect->y + rect->height < 0 ? 0 : n_items - 1;
|
||||
|
||||
gtk_bitset_add_range_closed (result, first, last);
|
||||
return result;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_list_view_move_focus_along (GtkListBase *base,
|
||||
guint pos,
|
||||
@ -326,9 +300,8 @@ gtk_list_view_get_position_from_allocation (GtkListBase *base,
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (base);
|
||||
GtkListTile *tile;
|
||||
int row_height, tile_pos;
|
||||
|
||||
tile = gtk_list_item_manager_get_tile_at (self->item_manager, x, y);
|
||||
tile = gtk_list_item_manager_get_nearest_tile (self->item_manager, x, y);
|
||||
if (tile == NULL)
|
||||
return FALSE;
|
||||
|
||||
@ -344,22 +317,60 @@ gtk_list_view_get_position_from_allocation (GtkListBase *base,
|
||||
}
|
||||
|
||||
*pos = gtk_list_tile_get_position (self->item_manager, tile);
|
||||
row_height = (tile->area.height / tile->n_items);
|
||||
tile_pos = (y - tile->area.y) / row_height;
|
||||
|
||||
*pos += tile_pos;
|
||||
|
||||
if (area)
|
||||
*area = tile->area;
|
||||
|
||||
if (tile->n_items > 1)
|
||||
{
|
||||
area->x = tile->area.x;
|
||||
area->width = tile->area.width;
|
||||
area->y = tile->area.y + tile_pos * row_height;
|
||||
area->height = row_height;
|
||||
int row_height, tile_pos, spacing;
|
||||
|
||||
gtk_list_base_get_border_spacing (GTK_LIST_BASE (self), NULL, &spacing);
|
||||
row_height = (tile->area.height - (tile->n_items - 1) * spacing) / tile->n_items;
|
||||
if (y >= tile->area.y + tile->area.height)
|
||||
tile_pos = tile->n_items - 1;
|
||||
else
|
||||
tile_pos = (y - tile->area.y) / (row_height + spacing);
|
||||
|
||||
*pos += tile_pos;
|
||||
if (area)
|
||||
{
|
||||
area->y = tile->area.y + tile_pos * (row_height + spacing);
|
||||
area->height = row_height;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GtkBitset *
|
||||
gtk_list_view_get_items_in_rect (GtkListBase *base,
|
||||
const cairo_rectangle_int_t *rect)
|
||||
{
|
||||
guint first, last;
|
||||
cairo_rectangle_int_t area;
|
||||
GtkBitset *result;
|
||||
|
||||
result = gtk_bitset_new_empty ();
|
||||
|
||||
if (!gtk_list_view_get_position_from_allocation (base, rect->x, rect->y, &first, &area))
|
||||
return result;
|
||||
if (area.y + area.height < rect->y)
|
||||
first++;
|
||||
|
||||
if (!gtk_list_view_get_position_from_allocation (base,
|
||||
rect->x + rect->width - 1,
|
||||
rect->y + rect->height - 1,
|
||||
&last, &area))
|
||||
return result;
|
||||
if (area.y >= rect->y + rect->height)
|
||||
last--;
|
||||
|
||||
if (last >= first)
|
||||
gtk_bitset_add_range_closed (result, first, last);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_list_view_move_focus_across (GtkListBase *base,
|
||||
guint pos,
|
||||
@ -432,9 +443,14 @@ gtk_list_view_measure_list (GtkWidget *widget,
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (widget);
|
||||
GtkListTile *tile;
|
||||
int min, nat, child_min, child_nat;
|
||||
int min, nat, child_min, child_nat, spacing;
|
||||
GArray *min_heights, *nat_heights;
|
||||
guint n_unknown;
|
||||
guint n_unknown, n_items;
|
||||
|
||||
n_items = gtk_list_base_get_n_items (GTK_LIST_BASE (self));
|
||||
if (n_items == 0)
|
||||
return;
|
||||
gtk_list_base_get_border_spacing (GTK_LIST_BASE (self), NULL, &spacing);
|
||||
|
||||
min_heights = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
nat_heights = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
@ -470,8 +486,8 @@ gtk_list_view_measure_list (GtkWidget *widget,
|
||||
g_array_free (min_heights, TRUE);
|
||||
g_array_free (nat_heights, TRUE);
|
||||
|
||||
*minimum = min;
|
||||
*natural = nat;
|
||||
*minimum = min + spacing * (n_items - 1);
|
||||
*natural = nat + spacing * (n_items - 1);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -500,7 +516,7 @@ gtk_list_view_size_allocate (GtkWidget *widget,
|
||||
GtkListView *self = GTK_LIST_VIEW (widget);
|
||||
GtkListTile *tile;
|
||||
GArray *heights;
|
||||
int min, nat, row_height, y, list_width;
|
||||
int min, nat, row_height, y, list_width, spacing;
|
||||
GtkOrientation orientation, opposite_orientation;
|
||||
GtkScrollablePolicy scroll_policy, opposite_scroll_policy;
|
||||
|
||||
@ -508,6 +524,7 @@ gtk_list_view_size_allocate (GtkWidget *widget,
|
||||
opposite_orientation = OPPOSITE_ORIENTATION (orientation);
|
||||
scroll_policy = gtk_list_base_get_scroll_policy (GTK_LIST_BASE (self), orientation);
|
||||
opposite_scroll_policy = gtk_list_base_get_scroll_policy (GTK_LIST_BASE (self), opposite_orientation);
|
||||
gtk_list_base_get_border_spacing (GTK_LIST_BASE (self), NULL, &spacing);
|
||||
|
||||
/* step 0: exit early if list is empty */
|
||||
tile = gtk_list_tile_gc (self->item_manager, gtk_list_item_manager_get_first (self->item_manager));
|
||||
@ -559,9 +576,15 @@ gtk_list_view_size_allocate (GtkWidget *widget,
|
||||
{
|
||||
gtk_list_tile_set_area_position (self->item_manager, tile, 0, y);
|
||||
if (tile->widget == NULL)
|
||||
gtk_list_tile_set_area_size (self->item_manager, tile, list_width, row_height * tile->n_items);
|
||||
{
|
||||
gtk_list_tile_set_area_size (self->item_manager,
|
||||
tile,
|
||||
list_width,
|
||||
row_height * tile->n_items
|
||||
+ spacing * (tile->n_items - 1));
|
||||
}
|
||||
|
||||
y += tile->area.height;
|
||||
y += tile->area.height + spacing;
|
||||
}
|
||||
|
||||
/* step 4: allocate the rest */
|
||||
|
Loading…
Reference in New Issue
Block a user