Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1756)

Unified Diff: Source/core/rendering/RenderGrid.cpp

Issue 148293008: [CSS Grid Layout] Add support to place items using named grid lines (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Added some more test cases for special grid area names Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/rendering/RenderGrid.h ('k') | Source/core/rendering/style/GridCoordinate.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/rendering/RenderGrid.cpp
diff --git a/Source/core/rendering/RenderGrid.cpp b/Source/core/rendering/RenderGrid.cpp
index 9cab4662c5b450d2a6f6d75bb8343b223807d156..b403d2557a97b58d2f41f0e77fc1bab07c6caa3b 100644
--- a/Source/core/rendering/RenderGrid.cpp
+++ b/Source/core/rendering/RenderGrid.cpp
@@ -219,9 +219,46 @@ void RenderGrid::removeChild(RenderObject* child)
dirtyGrid();
}
+void RenderGrid::createGridLineNamesMapsForDirection(GridTrackSizingDirection direction)
+{
+ NamedGridLinesMap& gridLinesMap = (direction == ForColumns) ? m_namedGridColumnLines : m_namedGridRowLines;
+ const OrderedNamedGridLines& orderedLinesMap = (direction == ForColumns) ? style()->orderedNamedGridColumnLines() : style()->orderedNamedGridRowLines();
+
+ gridLinesMap.clear();
+ OrderedNamedGridLines::const_iterator orderedLinesEnd = orderedLinesMap.end();
+ for (OrderedNamedGridLines::const_iterator it = orderedLinesMap.begin(); it != orderedLinesEnd; ++it) {
+ const Vector<String> gridLineNames = it->value;
+ for (size_t i = 0; i < gridLineNames.size(); ++i) {
+ NamedGridLinesMap::AddResult result = gridLinesMap.add(gridLineNames[i], Vector<size_t>());
+ result.storedValue->value.append(it->key);
+ }
+ }
+
+ NamedGridAreaMap::const_iterator gridAreasEnd = style()->namedGridArea().end();
+ for (NamedGridAreaMap::const_iterator it = style()->namedGridArea().begin(); it != gridAreasEnd; ++it) {
+ GridSpan areaSpan = direction == ForRows ? it->value.rows : it->value.columns;
+
+ NamedGridLinesMap::AddResult startResult = gridLinesMap.add(it->key + "-start", Vector<size_t>());
+ startResult.storedValue->value.append(areaSpan.initialPositionIndex);
+ NamedGridLinesMap::AddResult endResult = gridLinesMap.add(it->key + "-end", Vector<size_t>());
+ endResult.storedValue->value.append(areaSpan.finalPositionIndex + 1);
+ }
+
+ NamedGridLinesMap::const_iterator namedLinesEnd = gridLinesMap.end();
+ for (NamedGridLinesMap::iterator it = gridLinesMap.begin(); it != namedLinesEnd; ++it)
+ std::sort(it->value.begin(), it->value.end());
+}
Julien - ping for review 2014/03/31 23:36:21 I really don't understand what moving this code to
svillar 2014/04/01 08:00:42 So the idea would be to remove the map of grid lin
Julien - ping for review 2014/04/08 16:47:28 I see the point of splitting the 2 maps as only on
+
void RenderGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
+
+ bool gridLinesDefinitionChanged = namedGridLinesDefinitionDidChange(oldStyle);
+ if (gridLinesDefinitionChanged) {
+ createGridLineNamesMapsForDirection(ForColumns);
+ createGridLineNamesMapsForDirection(ForRows);
+ }
+
if (!oldStyle)
return;
@@ -230,9 +267,7 @@ void RenderGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl
// - named grid lines only impact grid items with named grid lines.
// - auto-flow changes only impacts auto-placed children.
- if (explicitGridDidResize(oldStyle)
- || namedGridLinesDefinitionDidChange(oldStyle)
- || oldStyle->gridAutoFlow() != style()->gridAutoFlow())
+ if (explicitGridDidResize(oldStyle) || gridLinesDefinitionChanged || oldStyle->gridAutoFlow() != style()->gridAutoFlow())
dirtyGrid();
}
@@ -244,8 +279,12 @@ bool RenderGrid::explicitGridDidResize(const RenderStyle* oldStyle) const
bool RenderGrid::namedGridLinesDefinitionDidChange(const RenderStyle* oldStyle) const
{
- return oldStyle->namedGridRowLines() != style()->namedGridRowLines()
- || oldStyle->namedGridColumnLines() != style()->namedGridColumnLines();
+ if (!oldStyle)
+ return true;
+
+ return oldStyle->orderedNamedGridRowLines() != style()->orderedNamedGridRowLines()
+ || oldStyle->orderedNamedGridColumnLines() != style()->orderedNamedGridColumnLines()
+ || oldStyle->namedGridArea() != style()->namedGridArea();
}
void RenderGrid::layoutBlock(bool relayoutChildren)
@@ -967,22 +1006,31 @@ GridSpan RenderGrid::resolveGridPositionsFromAutoPlacementPosition(const RenderB
return GridSpan(initialPosition, initialPosition);
}
+static bool isNonExistentNamedLineOrArea(GridPosition& position, RenderStyle& style, const NamedGridLinesMap& gridLinesMap)
+{
+ ASSERT(position.isNamedGridArea());
+ String lineName = position.namedGridLine();
Julien - ping for review 2014/04/08 16:47:28 Wouldn't passing this String directly to isNonExis
+
+ return !style.namedGridArea().contains(lineName) && !gridLinesMap.contains(lineName);
+}
+
PassOwnPtr<GridSpan> RenderGrid::resolveGridPositionsFromStyle(const RenderBox* gridItem, GridTrackSizingDirection direction) const
{
GridPosition initialPosition = (direction == ForColumns) ? gridItem->style()->gridColumnStart() : gridItem->style()->gridRowStart();
const GridPositionSide initialPositionSide = (direction == ForColumns) ? ColumnStartSide : RowStartSide;
GridPosition finalPosition = (direction == ForColumns) ? gridItem->style()->gridColumnEnd() : gridItem->style()->gridRowEnd();
const GridPositionSide finalPositionSide = (direction == ForColumns) ? ColumnEndSide : RowEndSide;
+ const NamedGridLinesMap& gridLines = (direction == ForColumns) ? m_namedGridColumnLines : m_namedGridRowLines;
// We must handle the placement error handling code here instead of in the StyleAdjuster because we don't want to
// overwrite the specified values.
if (initialPosition.isSpan() && finalPosition.isSpan())
finalPosition.setAutoPosition();
- if (initialPosition.isNamedGridArea() && !style()->namedGridArea().contains(initialPosition.namedGridLine()))
+ if (initialPosition.isNamedGridArea() && isNonExistentNamedLineOrArea(initialPosition, *style(), gridLines))
initialPosition.setAutoPosition();
- if (finalPosition.isNamedGridArea() && !style()->namedGridArea().contains(finalPosition.namedGridLine()))
+ if (finalPosition.isNamedGridArea() && isNonExistentNamedLineOrArea(finalPosition, *style(), gridLines))
finalPosition.setAutoPosition();
if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()) {
@@ -1019,7 +1067,7 @@ size_t RenderGrid::resolveNamedGridLinePositionFromStyle(const GridPosition& pos
{
ASSERT(!position.namedGridLine().isNull());
- const NamedGridLinesMap& gridLinesNames = (side == ColumnStartSide || side == ColumnEndSide) ? style()->namedGridColumnLines() : style()->namedGridRowLines();
+ const NamedGridLinesMap& gridLinesNames = gridLinesForSide(side);
NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
if (it == gridLinesNames.end()) {
if (position.isPositive())
@@ -1036,55 +1084,53 @@ size_t RenderGrid::resolveNamedGridLinePositionFromStyle(const GridPosition& pos
return GridPosition::adjustGridPositionForSide(it->value[namedGridLineIndex], side);
}
-size_t RenderGrid::resolveGridPositionFromStyle(const GridPosition& position, GridPositionSide side) const
+size_t RenderGrid::resolveExplicitPositionFromStyle(const GridPosition& position, GridPositionSide side) const
{
- switch (position.type()) {
- case ExplicitPosition: {
- ASSERT(position.integerPosition());
+ ASSERT(position.integerPosition());
- if (!position.namedGridLine().isNull())
- return resolveNamedGridLinePositionFromStyle(position, side);
+ if (!position.namedGridLine().isNull())
+ return resolveNamedGridLinePositionFromStyle(position, side);
- // Handle <integer> explicit position.
- if (position.isPositive())
- return GridPosition::adjustGridPositionForSide(position.integerPosition() - 1, side);
+ if (position.isPositive())
+ return GridPosition::adjustGridPositionForSide(position.integerPosition() - 1, side);
- size_t resolvedPosition = abs(position.integerPosition()) - 1;
- const size_t endOfTrack = explicitGridSizeForSide(side);
+ size_t resolvedPosition = abs(position.integerPosition()) - 1;
+ const size_t endOfTrack = explicitGridSizeForSide(side);
- // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
- if (endOfTrack < resolvedPosition)
- return 0;
+ // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
+ if (endOfTrack < resolvedPosition)
+ return 0;
- return GridPosition::adjustGridPositionForSide(endOfTrack - resolvedPosition, side);
- }
- case NamedGridAreaPosition:
- {
- NamedGridAreaMap::const_iterator it = style()->namedGridArea().find(position.namedGridLine());
- // Unknown grid area should have been computed to 'auto' by now.
- ASSERT_WITH_SECURITY_IMPLICATION(it != style()->namedGridArea().end());
- const GridCoordinate& gridAreaCoordinate = it->value;
- switch (side) {
- case ColumnStartSide:
- return gridAreaCoordinate.columns.initialPositionIndex;
- case ColumnEndSide:
- return gridAreaCoordinate.columns.finalPositionIndex;
- case RowStartSide:
- return gridAreaCoordinate.rows.initialPositionIndex;
- case RowEndSide:
- return gridAreaCoordinate.rows.finalPositionIndex;
+ return GridPosition::adjustGridPositionForSide(endOfTrack - resolvedPosition, side);
+}
+
+size_t RenderGrid::resolveGridPositionFromStyle(const GridPosition& position, GridPositionSide side) const
+{
+ // We shouldn't see any other type of position here because 'auto' and span depend on the opposite position for
+ // resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / myHeader).
+ ASSERT(position.type() == NamedGridAreaPosition || position.type() == ExplicitPosition);
+
+ if (position.type() == NamedGridAreaPosition) {
+ // Four implicit named grid lines are created for each grid area (areaName-{start|end} for rows and
+ // columns). Authors can either use the area names or the implicit grid line names.
+ NamedGridAreaMap::const_iterator areaIter = style()->namedGridArea().find(position.namedGridLine());
+ if (areaIter != style()->namedGridArea().end()) {
+ String implicitNamedGridLine = position.namedGridLine() + ((side == ColumnStartSide || side == RowStartSide) ? "-start" : "-end");
+ const NamedGridLinesMap& gridLineNames = gridLinesForSide(side);
+ NamedGridLinesMap::const_iterator lineIter = gridLineNames.find(implicitNamedGridLine);
+
+ if (lineIter != gridLineNames.end())
+ return GridPosition::adjustGridPositionForSide(lineIter->value[0], side);
+
+ return areaIter->value.positionForSide(side);
}
- ASSERT_NOT_REACHED();
- return 0;
+ // Fallback to a implicit grid line position if there is no grid area with that name.
+ GridPosition adjustedPosition;
+ adjustedPosition.setExplicitPosition(1, position.namedGridLine());
+ return resolveExplicitPositionFromStyle(adjustedPosition, side);
}
- case AutoPosition:
- case SpanPosition:
- // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader").
- ASSERT_NOT_REACHED();
- return 0;
- }
- ASSERT_NOT_REACHED();
- return 0;
+
+ return resolveExplicitPositionFromStyle(position, side);
}
PassOwnPtr<GridSpan> RenderGrid::resolveGridPositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) const
@@ -1110,7 +1156,7 @@ PassOwnPtr<GridSpan> RenderGrid::resolveNamedGridLinePositionAgainstOppositePosi
// Negative positions are not allowed per the specification and should have been handled during parsing.
ASSERT(position.spanPosition() > 0);
- const NamedGridLinesMap& gridLinesNames = (side == ColumnStartSide || side == ColumnEndSide) ? style()->namedGridColumnLines() : style()->namedGridRowLines();
+ const NamedGridLinesMap& gridLinesNames = gridLinesForSide(side);
NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
// If there is no named grid line of that name, we resolve the position to 'auto' (which is equivalent to 'span 1' in this case).
« no previous file with comments | « Source/core/rendering/RenderGrid.h ('k') | Source/core/rendering/style/GridCoordinate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698