LibWeb: Support "order" property for items in GridFormattingContext
Closes https://github.com/SerenityOS/serenity/issues/20434
This commit is contained in:
parent
0a4b869233
commit
6354f950fd
Notes:
sideshowbarker
2024-07-17 04:57:23 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/6354f950fd Pull-request: https://github.com/SerenityOS/serenity/pull/20455 Issue: https://github.com/SerenityOS/serenity/issues/20434
3 changed files with 129 additions and 38 deletions
41
Tests/LibWeb/Layout/expected/grid/order.txt
Normal file
41
Tests/LibWeb/Layout/expected/grid/order.txt
Normal file
|
@ -0,0 +1,41 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (1,1) content-size 798x600 [BFC] children: not-inline
|
||||
BlockContainer <body> at (10,10) content-size 780x104 children: not-inline
|
||||
Box <div.grid-container> at (11,11) content-size 778x102 [GFC] children: not-inline
|
||||
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.grid-item.item-1> at (271.328125,12) content-size 100x100 [BFC] children: inline
|
||||
line 0 width: 7.9375, height: 21.84375, bottom: 21.84375, baseline: 16.921875
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [271.328125,12 7.9375x21.84375]
|
||||
"1"
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.grid-item.item-2> at (530.65625,12) content-size 100x100 [BFC] children: inline
|
||||
line 0 width: 11.015625, height: 21.84375, bottom: 21.84375, baseline: 16.921875
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [530.65625,12 11.015625x21.84375]
|
||||
"2"
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.grid-item.item-3> at (12,12) content-size 100x100 [BFC] children: inline
|
||||
line 0 width: 11.375, height: 21.84375, bottom: 21.84375, baseline: 16.921875
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [12,12 11.375x21.84375]
|
||||
"3"
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (10,114) content-size 780x0 children: inline
|
||||
TextNode <#text>
|
||||
|
||||
PaintableWithLines (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x602]
|
||||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x602]
|
||||
PaintableWithLines (BlockContainer<BODY>) [9,9 782x106]
|
||||
PaintableBox (Box<DIV>.grid-container) [10,10 780x104]
|
||||
PaintableWithLines (BlockContainer<DIV>.grid-item.item-1) [270.328125,11 102x102]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.grid-item.item-2) [529.65625,11 102x102]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.grid-item.item-3) [11,11 102x102]
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [10,114 780x0]
|
33
Tests/LibWeb/Layout/input/grid/order.html
Normal file
33
Tests/LibWeb/Layout/input/grid/order.html
Normal file
|
@ -0,0 +1,33 @@
|
|||
<style>
|
||||
* {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, auto);
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.item-1 {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.item-2 {
|
||||
order: 3;
|
||||
}
|
||||
|
||||
.item-3 {
|
||||
order: 1;
|
||||
}
|
||||
</style>
|
||||
<div class="grid-container">
|
||||
<div class="grid-item item-1">1</div>
|
||||
<div class="grid-item item-2">2</div>
|
||||
<div class="grid-item item-3">3</div>
|
||||
</div>
|
|
@ -1314,7 +1314,7 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
|
|||
// flex items), which are then assigned to predefined areas in the grid. They can be explicitly
|
||||
// placed using coordinates through the grid-placement properties or implicitly placed into
|
||||
// empty areas using auto-placement.
|
||||
Vector<JS::NonnullGCPtr<Box const>> boxes_to_place;
|
||||
HashMap<int, Vector<JS::NonnullGCPtr<Box const>>> order_item_bucket;
|
||||
grid_container().for_each_child_of_type<Box>([&](Box& child_box) {
|
||||
if (can_skip_is_anonymous_text_run(child_box))
|
||||
return IterationDecision::Continue;
|
||||
|
@ -1322,7 +1322,9 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
|
|||
if (child_box.is_out_of_flow(*this))
|
||||
return IterationDecision::Continue;
|
||||
|
||||
boxes_to_place.append(child_box);
|
||||
auto& order_bucket = order_item_bucket.ensure(child_box.computed_values().order());
|
||||
order_bucket.append(child_box);
|
||||
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
|
@ -1333,28 +1335,37 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
|
|||
// https://drafts.csswg.org/css-grid/#auto-placement-algo
|
||||
// 8.5. Grid Item Placement Algorithm
|
||||
|
||||
auto keys = order_item_bucket.keys();
|
||||
quick_sort(keys, [](auto& a, auto& b) { return a < b; });
|
||||
|
||||
// FIXME: 0. Generate anonymous grid items
|
||||
|
||||
// 1. Position anything that's not auto-positioned.
|
||||
for (size_t i = 0; i < boxes_to_place.size(); i++) {
|
||||
auto const& child_box = boxes_to_place[i];
|
||||
if (is_auto_positioned_row(child_box->computed_values().grid_row_start(), child_box->computed_values().grid_row_end())
|
||||
|| is_auto_positioned_column(child_box->computed_values().grid_column_start(), child_box->computed_values().grid_column_end()))
|
||||
continue;
|
||||
place_item_with_row_and_column_position(child_box);
|
||||
boxes_to_place.remove(i);
|
||||
i--;
|
||||
for (auto key : keys) {
|
||||
auto& boxes_to_place = order_item_bucket.get(key).value();
|
||||
for (size_t i = 0; i < boxes_to_place.size(); i++) {
|
||||
auto const& child_box = boxes_to_place[i];
|
||||
if (is_auto_positioned_row(child_box->computed_values().grid_row_start(), child_box->computed_values().grid_row_end())
|
||||
|| is_auto_positioned_column(child_box->computed_values().grid_column_start(), child_box->computed_values().grid_column_end()))
|
||||
continue;
|
||||
place_item_with_row_and_column_position(child_box);
|
||||
boxes_to_place.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Process the items locked to a given row.
|
||||
// FIXME: Do "dense" packing
|
||||
for (size_t i = 0; i < boxes_to_place.size(); i++) {
|
||||
auto const& child_box = boxes_to_place[i];
|
||||
if (is_auto_positioned_row(child_box->computed_values().grid_row_start(), child_box->computed_values().grid_row_end()))
|
||||
continue;
|
||||
place_item_with_row_position(child_box);
|
||||
boxes_to_place.remove(i);
|
||||
i--;
|
||||
for (auto key : keys) {
|
||||
auto& boxes_to_place = order_item_bucket.get(key).value();
|
||||
for (size_t i = 0; i < boxes_to_place.size(); i++) {
|
||||
auto const& child_box = boxes_to_place[i];
|
||||
if (is_auto_positioned_row(child_box->computed_values().grid_row_start(), child_box->computed_values().grid_row_end()))
|
||||
continue;
|
||||
place_item_with_row_position(child_box);
|
||||
boxes_to_place.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Determine the columns in the implicit grid.
|
||||
|
@ -1373,15 +1384,18 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
|
|||
// 3.3. If the largest column span among all the items without a definite column position is larger
|
||||
// than the width of the implicit grid, add columns to the end of the implicit grid to accommodate
|
||||
// that column span.
|
||||
for (auto const& child_box : boxes_to_place) {
|
||||
int column_span = 1;
|
||||
if (child_box->computed_values().grid_column_start().is_span())
|
||||
column_span = child_box->computed_values().grid_column_start().raw_value();
|
||||
else if (child_box->computed_values().grid_column_end().is_span())
|
||||
column_span = child_box->computed_values().grid_column_end().raw_value();
|
||||
for (auto key : keys) {
|
||||
auto& boxes_to_place = order_item_bucket.get(key).value();
|
||||
for (auto const& child_box : boxes_to_place) {
|
||||
int column_span = 1;
|
||||
if (child_box->computed_values().grid_column_start().is_span())
|
||||
column_span = child_box->computed_values().grid_column_start().raw_value();
|
||||
else if (child_box->computed_values().grid_column_end().is_span())
|
||||
column_span = child_box->computed_values().grid_column_end().raw_value();
|
||||
|
||||
if (column_span - 1 > m_occupation_grid.max_column_index())
|
||||
m_occupation_grid.set_max_column_index(column_span - 1);
|
||||
if (column_span - 1 > m_occupation_grid.max_column_index())
|
||||
m_occupation_grid.set_max_column_index(column_span - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Position the remaining grid items.
|
||||
|
@ -1389,23 +1403,26 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa
|
|||
// order:
|
||||
auto auto_placement_cursor_x = 0;
|
||||
auto auto_placement_cursor_y = 0;
|
||||
for (size_t i = 0; i < boxes_to_place.size(); i++) {
|
||||
auto const& child_box = boxes_to_place[i];
|
||||
// 4.1. For sparse packing:
|
||||
// FIXME: no distinction made. See #4.2
|
||||
for (auto key : keys) {
|
||||
auto& boxes_to_place = order_item_bucket.get(key).value();
|
||||
for (size_t i = 0; i < boxes_to_place.size(); i++) {
|
||||
auto const& child_box = boxes_to_place[i];
|
||||
// 4.1. For sparse packing:
|
||||
// FIXME: no distinction made. See #4.2
|
||||
|
||||
// 4.1.1. If the item has a definite column position:
|
||||
if (!is_auto_positioned_column(child_box->computed_values().grid_column_start(), child_box->computed_values().grid_column_end()))
|
||||
place_item_with_column_position(child_box, auto_placement_cursor_x, auto_placement_cursor_y);
|
||||
// 4.1.1. If the item has a definite column position:
|
||||
if (!is_auto_positioned_column(child_box->computed_values().grid_column_start(), child_box->computed_values().grid_column_end()))
|
||||
place_item_with_column_position(child_box, auto_placement_cursor_x, auto_placement_cursor_y);
|
||||
|
||||
// 4.1.2. If the item has an automatic grid position in both axes:
|
||||
else
|
||||
place_item_with_no_declared_position(child_box, auto_placement_cursor_x, auto_placement_cursor_y);
|
||||
// 4.1.2. If the item has an automatic grid position in both axes:
|
||||
else
|
||||
place_item_with_no_declared_position(child_box, auto_placement_cursor_x, auto_placement_cursor_y);
|
||||
|
||||
boxes_to_place.remove(i);
|
||||
i--;
|
||||
boxes_to_place.remove(i);
|
||||
i--;
|
||||
|
||||
// FIXME: 4.2. For dense packing:
|
||||
// FIXME: 4.2. For dense packing:
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: When final implicit grid sizes are known, we can offset their positions so leftmost grid track has 0 index.
|
||||
|
|
Loading…
Add table
Reference in a new issue