Commit 69243d0f authored by rego@igalia.com's avatar rego@igalia.com

[CSS Grid Layout] Fix issues adding new items to grid

First if the grid auto flow property is different to none, the grid is
marked as dirty when a new child is added. Because of if it contains
auto-placed items, they might need to be re-positioned.

Then if the new item has definite positions and auto flow is none, the
grid will grow as required and place the new item without being marked
as dirty.

The test was not working properly, as it was adding the PASS messages
as auto-placed grid items which was marking the grid as dirty and force
a re-calculation of the position.

Moving the results of the test to a different div make the test fails
without this patch. Test expectation was updated accordingly.

BUG=248151
TEST=fast/css-grid-layout/grid-item-addition-auto-placement-update.html

Review URL: https://codereview.chromium.org/198703004

git-svn-id: svn://svn.chromium.org/blink/trunk@169784 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 1a0a1c26
This test checks that the tracks' auto positions are recomputed after adding a grid item. This test checks that the tracks' auto positions are recomputed after adding a grid item.
XXXXX XXXXX XXXXX
XXXXX XXXXX XXXXX
XXXXX XXXXX XXXXX
XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX
PASS PASS
PASS PASS
PASS PASS
PASS PASS
PASS PASS
XXXXX XXXXX XXXXX
PASS PASS
PASS PASS
PASS PASS
PASS PASS
PASS PASS
XXXXX XXXXX XXXXX
PASS PASS
PASS PASS
PASS PASS
PASS PASS
PASS PASS
XXXXX XXXXX XXXXX
PASS PASS
PASS PASS
PASS PASS
......
...@@ -21,30 +21,31 @@ function testAddition(gridElementID, position, autoFlowElementID, size) ...@@ -21,30 +21,31 @@ function testAddition(gridElementID, position, autoFlowElementID, size)
var autoFlowElement = document.getElementById(autoFlowElementID); var autoFlowElement = document.getElementById(autoFlowElementID);
autoFlowElement.setAttribute("data-expected-width", size.width); autoFlowElement.setAttribute("data-expected-width", size.width);
autoFlowElement.setAttribute("data-expected-height", size.height); autoFlowElement.setAttribute("data-expected-height", size.height);
checkLayout("#" + autoFlowElementID); checkLayout("#" + autoFlowElementID, document.getElementById("test-output"));
} }
function testAdditions() function testAdditions()
{ {
checkLayout("#autoFlowColumnElement"); var testOutput = document.getElementById("test-output");
checkLayout("#autoFlowColumnElement", testOutput);
testAddition("gridAutoFlowColumn", { 'row': '1', 'column': '1' }, "autoFlowColumnElement", { 'width': '50', 'height': '100' }); testAddition("gridAutoFlowColumn", { 'row': '1', 'column': '1' }, "autoFlowColumnElement", { 'width': '50', 'height': '100' });
testAddition("gridAutoFlowColumn", { 'row': '1', 'column': '2' }, "autoFlowColumnElement", { 'width': '50', 'height': '100' }); testAddition("gridAutoFlowColumn", { 'row': '1', 'column': '2' }, "autoFlowColumnElement", { 'width': '50', 'height': '100' });
testAddition("gridAutoFlowColumn", { 'row': '2', 'column': '2' }, "autoFlowColumnElement", { 'width': '50', 'height': '100' }); testAddition("gridAutoFlowColumn", { 'row': '2', 'column': '2' }, "autoFlowColumnElement", { 'width': '50', 'height': '100' });
testAddition("gridAutoFlowColumn", { 'row': '2', 'column': '1' }, "autoFlowColumnElement", { 'width': '170', 'height': '50' }); testAddition("gridAutoFlowColumn", { 'row': '2', 'column': '1' }, "autoFlowColumnElement", { 'width': '170', 'height': '50' });
checkLayout("#autoFlowRowElement"); checkLayout("#autoFlowRowElement", testOutput);
testAddition("gridAutoFlowRow", { 'row': '1', 'column': '1' }, "autoFlowRowElement", { 'width': '100', 'height': '50' }); testAddition("gridAutoFlowRow", { 'row': '1', 'column': '1' }, "autoFlowRowElement", { 'width': '100', 'height': '50' });
testAddition("gridAutoFlowRow", { 'row': '2', 'column': '1' }, "autoFlowRowElement", { 'width': '100', 'height': '50' }); testAddition("gridAutoFlowRow", { 'row': '2', 'column': '1' }, "autoFlowRowElement", { 'width': '100', 'height': '50' });
testAddition("gridAutoFlowRow", { 'row': '2', 'column': '2' }, "autoFlowRowElement", { 'width': '100', 'height': '50' }); testAddition("gridAutoFlowRow", { 'row': '2', 'column': '2' }, "autoFlowRowElement", { 'width': '100', 'height': '50' });
testAddition("gridAutoFlowRow", { 'row': '1', 'column': '2' }, "autoFlowRowElement", { 'width': '50', 'height': '30' }); testAddition("gridAutoFlowRow", { 'row': '1', 'column': '2' }, "autoFlowRowElement", { 'width': '50', 'height': '30' });
checkLayout("#gridAutoFlowColumnWithAuto"); checkLayout("#gridAutoFlowColumnWithAuto", testOutput);
testAddition("gridAutoFlowColumnWithAuto", { 'row': 'auto', 'column': '1' }, "autoFlowColumnElementWithAuto", { 'width': '50', 'height': '100' }); testAddition("gridAutoFlowColumnWithAuto", { 'row': 'auto', 'column': '1' }, "autoFlowColumnElementWithAuto", { 'width': '50', 'height': '100' });
testAddition("gridAutoFlowColumnWithAuto", { 'row': '1', 'column': '1' }, "autoFlowColumnElementWithAuto", { 'width': '100', 'height': '50' }); testAddition("gridAutoFlowColumnWithAuto", { 'row': '1', 'column': '1' }, "autoFlowColumnElementWithAuto", { 'width': '100', 'height': '50' });
testAddition("gridAutoFlowColumnWithAuto", { 'row': 'auto', 'column': '2' }, "autoFlowColumnElementWithAuto", { 'width': '100', 'height': '100' }); testAddition("gridAutoFlowColumnWithAuto", { 'row': 'auto', 'column': '2' }, "autoFlowColumnElementWithAuto", { 'width': '100', 'height': '100' });
testAddition("gridAutoFlowColumnWithAuto", { 'row': '2', 'column': '2' }, "autoFlowColumnElementWithAuto", { 'width': '170', 'height': '50' }); testAddition("gridAutoFlowColumnWithAuto", { 'row': '2', 'column': '2' }, "autoFlowColumnElementWithAuto", { 'width': '170', 'height': '50' });
checkLayout("#gridAutoFlowRowWithAuto"); checkLayout("#gridAutoFlowRowWithAuto", testOutput);
testAddition("gridAutoFlowRowWithAuto", { 'row': '1', 'column': 'auto' }, "autoFlowRowElementWithAuto", { 'width': '100', 'height': '50' }); testAddition("gridAutoFlowRowWithAuto", { 'row': '1', 'column': 'auto' }, "autoFlowRowElementWithAuto", { 'width': '100', 'height': '50' });
testAddition("gridAutoFlowRowWithAuto", { 'row': 'auto', 'column': '1' }, "autoFlowRowElementWithAuto", { 'width': '100', 'height': '50' }); testAddition("gridAutoFlowRowWithAuto", { 'row': 'auto', 'column': '1' }, "autoFlowRowElementWithAuto", { 'width': '100', 'height': '50' });
testAddition("gridAutoFlowRowWithAuto", { 'row': '1', 'column': '2' }, "autoFlowRowElementWithAuto", { 'width': '50', 'height': '100' }); testAddition("gridAutoFlowRowWithAuto", { 'row': '1', 'column': '2' }, "autoFlowRowElementWithAuto", { 'width': '50', 'height': '100' });
...@@ -80,5 +81,7 @@ window.addEventListener("load", testAdditions, false); ...@@ -80,5 +81,7 @@ window.addEventListener("load", testAdditions, false);
</div> </div>
</div> </div>
<div id="test-output"></div>
</body> </body>
</html> </html>
...@@ -191,19 +191,27 @@ void RenderGrid::addChild(RenderObject* newChild, RenderObject* beforeChild) ...@@ -191,19 +191,27 @@ void RenderGrid::addChild(RenderObject* newChild, RenderObject* beforeChild)
return; return;
} }
if (style()->gridAutoFlow() != AutoFlowNone) {
// The grid needs to be recomputed as it might contain auto-placed items that will change their position.
dirtyGrid();
return;
}
RenderBox* newChildBox = toRenderBox(newChild); RenderBox* newChildBox = toRenderBox(newChild);
OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(newChildBox, ForRows); OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(newChildBox, ForRows);
OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(newChildBox, ForColumns); OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(newChildBox, ForColumns);
if (!rowPositions || !columnPositions) { if (!rowPositions || !columnPositions) {
// The new child requires the auto-placement algorithm to run so we need to recompute the grid fully. // The new child requires the auto-placement algorithm to run so we need to recompute the grid fully.
dirtyGrid(); dirtyGrid();
return;
} else { } else {
if (gridRowCount() <= rowPositions->finalPositionIndex || gridColumnCount() <= columnPositions->finalPositionIndex) { // Ensure that the grid is big enough to contain new grid item.
// FIXME: We could just insert the new child provided we had a primitive to arbitrarily grow the grid. if (gridRowCount() <= rowPositions->finalPositionIndex)
dirtyGrid(); growGrid(ForRows, rowPositions->finalPositionIndex);
} else { if (gridColumnCount() <= columnPositions->finalPositionIndex)
insertItemIntoGrid(newChildBox, GridCoordinate(*rowPositions, *columnPositions)); growGrid(ForColumns, columnPositions->finalPositionIndex);
}
insertItemIntoGrid(newChildBox, GridCoordinate(*rowPositions, *columnPositions));
} }
} }
...@@ -708,16 +716,18 @@ bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection dire ...@@ -708,16 +716,18 @@ bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection dire
} }
#endif #endif
void RenderGrid::growGrid(GridTrackSizingDirection direction) void RenderGrid::growGrid(GridTrackSizingDirection direction, size_t maximumPositionIndex)
{ {
if (direction == ForColumns) { if (direction == ForColumns) {
const size_t oldColumnSize = m_grid[0].size(); ASSERT(maximumPositionIndex >= m_grid[0].size());
for (size_t row = 0; row < m_grid.size(); ++row) for (size_t row = 0; row < m_grid.size(); ++row)
m_grid[row].grow(oldColumnSize + 1); m_grid[row].grow(maximumPositionIndex + 1);
} else { } else {
ASSERT(maximumPositionIndex >= m_grid.size());
const size_t oldRowSize = m_grid.size(); const size_t oldRowSize = m_grid.size();
m_grid.grow(oldRowSize + 1); m_grid.grow(maximumPositionIndex + 1);
m_grid[oldRowSize].grow(m_grid[0].size()); for (size_t row = oldRowSize; row < m_grid.size(); ++row)
m_grid[row].grow(m_grid[0].size());
} }
} }
...@@ -823,7 +833,7 @@ void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>& au ...@@ -823,7 +833,7 @@ void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>& au
continue; continue;
} }
growGrid(autoPlacementMinorAxisDirection()); growGrid(autoPlacementMinorAxisDirection(), autoPlacementMinorAxisDirection() == ForColumns ? m_grid[0].size() : m_grid.size());
OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea(); OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea();
ASSERT(emptyGridArea); ASSERT(emptyGridArea);
insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex); insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
...@@ -862,7 +872,7 @@ void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem) ...@@ -862,7 +872,7 @@ void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
// We didn't find an empty grid area so we need to create an extra major axis line and insert our gridItem in it. // We didn't find an empty grid area so we need to create an extra major axis line and insert our gridItem in it.
const size_t columnIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? m_grid[0].size() : minorAxisIndex; const size_t columnIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? m_grid[0].size() : minorAxisIndex;
const size_t rowIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? minorAxisIndex : m_grid.size(); const size_t rowIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? minorAxisIndex : m_grid.size();
growGrid(autoPlacementMajorAxisDirection()); growGrid(autoPlacementMajorAxisDirection(), autoPlacementMajorAxisDirection() == ForColumns ? m_grid[0].size() : m_grid.size());
insertItemIntoGrid(gridItem, rowIndex, columnIndex); insertItemIntoGrid(gridItem, rowIndex, columnIndex);
} }
......
...@@ -80,7 +80,7 @@ private: ...@@ -80,7 +80,7 @@ private:
LayoutUnit computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirection, const Length&) const; LayoutUnit computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirection, const Length&) const;
void resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection, GridSizingData&, LayoutUnit& availableLogicalSpace); void resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection, GridSizingData&, LayoutUnit& availableLogicalSpace);
void growGrid(GridTrackSizingDirection); void growGrid(GridTrackSizingDirection, size_t maximumPosition);
void insertItemIntoGrid(RenderBox*, size_t rowTrack, size_t columnTrack); void insertItemIntoGrid(RenderBox*, size_t rowTrack, size_t columnTrack);
void insertItemIntoGrid(RenderBox*, const GridCoordinate&); void insertItemIntoGrid(RenderBox*, const GridCoordinate&);
void placeItemsOnGrid(); void placeItemsOnGrid();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment