NS_IMETHODIMP nsDeckFrame::DoLayout(nsBoxLayoutState& aState) { // Make sure we tweak the state so it does not resize our children. // We will do that. uint32_t oldFlags = aState.LayoutFlags(); aState.SetLayoutFlags(NS_FRAME_NO_SIZE_VIEW | NS_FRAME_NO_VISIBILITY); // do a normal layout nsresult rv = nsBoxFrame::DoLayout(aState); // run though each child. Hide all but the selected one nsIFrame* box = nsBox::GetChildBox(this); nscoord count = 0; while (box) { // make collapsed children not show up if (count != mIndex) HideBox(box); box = GetNextBox(box); count++; } aState.SetLayoutFlags(oldFlags); return rv; }
/** * This is redefined because row groups have a funny property. If they are flexible * then their flex must be equal to the sum of their children's flexes. */ nscoord nsGridRowGroupFrame::GetFlex(nsBoxLayoutState& aState) { // if we are flexible out flexibility is determined by our columns. // so first get the our flex. If not 0 then our flex is the sum of // our columns flexes. if (!DoesNeedRecalc(mFlex)) return mFlex; if (nsBoxFrame::GetFlex(aState) == 0) return 0; // ok we are flexible add up our children nscoord totalFlex = 0; nsIFrame* child = nsBox::GetChildBox(this); while (child) { totalFlex += child->GetFlex(aState); child = GetNextBox(child); } mFlex = totalFlex; return totalFlex; }
void nsSprocketLayout::PopulateBoxSizes(nsIFrame* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, int32_t& aFlexes) { // used for the equal size flag nscoord biggestPrefWidth = 0; nscoord biggestMinWidth = 0; nscoord smallestMaxWidth = NS_INTRINSICSIZE; nsFrameState frameState = nsFrameState(0); GetFrameState(aBox, frameState); //if (frameState & NS_STATE_CURRENTLY_IN_DEBUG) // printf("In debug\n"); aMinSize = 0; aMaxSize = NS_INTRINSICSIZE; bool isHorizontal; if (IsHorizontal(aBox)) isHorizontal = true; else isHorizontal = false; // this is a nice little optimization // it turns out that if we only have 1 flexable child // then it does not matter what its preferred size is // there is nothing to flex it relative. This is great // because we can avoid asking for a preferred size in this // case. Why is this good? Well you might have html inside it // and asking html for its preferred size is rather expensive. // so we can just optimize it out this way. // set flexes nsIFrame* child = nsBox::GetChildBox(aBox); aFlexes = 0; nsBoxSize* currentBox = nullptr; #if 0 nsBoxSize* start = aBoxSizes; while(child) { // ok if we started with a list move down the list // until we reach the end. Then start looking at childen. // This feature is used extensively for Grid. nscoord flex = 0; if (!start) { if (!currentBox) { aBoxSizes = new (aState) nsBoxSize(); currentBox = aBoxSizes; } else { currentBox->next = new (aState) nsBoxSize(); currentBox = currentBox->next; } flex = child->GetFlex(aState); currentBox->flex = flex; currentBox->collapsed = child->IsCollapsed(); } else { flex = start->flex; start = start->next; } if (flex > 0) aFlexes++; child = GetNextBox(child); } #endif // get pref, min, max child = nsBox::GetChildBox(aBox); currentBox = aBoxSizes; nsBoxSize* last = nullptr; nscoord maxFlex = 0; int32_t childCount = 0; while(child) { while (currentBox && currentBox->bogus) { last = currentBox; currentBox = currentBox->next; } ++childCount; nsSize pref(0,0); nsSize minSize(0,0); nsSize maxSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE); nscoord ascent = 0; bool collapsed = child->IsCollapsed(); if (!collapsed) { // only one flexible child? Cool we will just make its preferred size // 0 then and not even have to ask for it. //if (flexes != 1) { pref = child->GetPrefSize(aState); minSize = child->GetMinSize(aState); maxSize = nsBox::BoundsCheckMinMax(minSize, child->GetMaxSize(aState)); ascent = child->GetBoxAscent(aState); nsMargin margin; child->GetMargin(margin); ascent += margin.top; //} pref = nsBox::BoundsCheck(minSize, pref, maxSize); AddMargin(child, pref); AddMargin(child, minSize); AddMargin(child, maxSize); } if (!currentBox) { // create one. currentBox = new (aState) nsBoxSize(); if (!aBoxSizes) { aBoxSizes = currentBox; last = aBoxSizes; } else { last->next = currentBox; last = currentBox; } nscoord minWidth; nscoord maxWidth; nscoord prefWidth; // get sizes from child if (isHorizontal) { minWidth = minSize.width; maxWidth = maxSize.width; prefWidth = pref.width; } else { minWidth = minSize.height; maxWidth = maxSize.height; prefWidth = pref.height; } nscoord flex = child->GetFlex(aState); // set them if you collapsed you are not flexible. if (collapsed) { currentBox->flex = 0; } else { if (flex > maxFlex) { maxFlex = flex; } currentBox->flex = flex; } // we specified all our children are equal size; if (frameState & NS_STATE_EQUAL_SIZE) { if (prefWidth > biggestPrefWidth) biggestPrefWidth = prefWidth; if (minWidth > biggestMinWidth) biggestMinWidth = minWidth; if (maxWidth < smallestMaxWidth) smallestMaxWidth = maxWidth; } else { // not we can set our children right now. currentBox->pref = prefWidth; currentBox->min = minWidth; currentBox->max = maxWidth; } NS_ASSERTION(minWidth <= prefWidth && prefWidth <= maxWidth,"Bad min, pref, max widths!"); } if (!isHorizontal) { if (minSize.width > aMinSize) aMinSize = minSize.width; if (maxSize.width < aMaxSize) aMaxSize = maxSize.width; } else { if (minSize.height > aMinSize) aMinSize = minSize.height; if (maxSize.height < aMaxSize) aMaxSize = maxSize.height; } currentBox->collapsed = collapsed; aFlexes += currentBox->flex; child = nsBox::GetNextBox(child); last = currentBox; currentBox = currentBox->next; } if (childCount > 0) { nscoord maxAllowedFlex = nscoord_MAX / childCount; if (MOZ_UNLIKELY(maxFlex > maxAllowedFlex)) { // clamp all the flexes currentBox = aBoxSizes; while (currentBox) { currentBox->flex = std::min(currentBox->flex, maxAllowedFlex); currentBox = currentBox->next; } } } #ifdef DEBUG else { NS_ASSERTION(maxFlex == 0, "How did that happen?"); } #endif // we specified all our children are equal size; if (frameState & NS_STATE_EQUAL_SIZE) { smallestMaxWidth = std::max(smallestMaxWidth, biggestMinWidth); biggestPrefWidth = nsBox::BoundsCheck(biggestMinWidth, biggestPrefWidth, smallestMaxWidth); currentBox = aBoxSizes; while(currentBox) { if (!currentBox->collapsed) { currentBox->pref = biggestPrefWidth; currentBox->min = biggestMinWidth; currentBox->max = smallestMaxWidth; } else { currentBox->pref = 0; currentBox->min = 0; currentBox->max = 0; } currentBox = currentBox->next; } } }