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; }
nsresult nsBox::SyncLayout(nsBoxLayoutState& aState) { /* if (IsCollapsed()) { CollapseChild(aState, this, true); return NS_OK; } */ if (GetStateBits() & NS_FRAME_IS_DIRTY) Redraw(aState); RemoveStateBits(NS_FRAME_HAS_DIRTY_CHILDREN | NS_FRAME_IS_DIRTY | NS_FRAME_FIRST_REFLOW | NS_FRAME_IN_REFLOW); nsPresContext* presContext = aState.PresContext(); uint32_t flags = 0; GetLayoutFlags(flags); uint32_t stateFlags = aState.LayoutFlags(); flags |= stateFlags; nsRect visualOverflow; if (ComputesOwnOverflowArea()) { visualOverflow = GetVisualOverflowRect(); } else { nsRect rect(nsPoint(0, 0), GetSize()); nsOverflowAreas overflowAreas(rect, rect); if (!DoesClipChildren() && !IsCollapsed()) { // See if our child frames caused us to overflow after being laid // out. If so, store the overflow area. This normally can't happen // in XUL, but it can happen with the CSS 'outline' property and // possibly with other exotic stuff (e.g. relatively positioned // frames in HTML inside XUL). nsLayoutUtils::UnionChildOverflow(this, overflowAreas); } FinishAndStoreOverflow(overflowAreas, GetSize()); visualOverflow = overflowAreas.VisualOverflow(); } nsIView* view = GetView(); if (view) { // Make sure the frame's view is properly sized and positioned and has // things like opacity correct nsContainerFrame::SyncFrameViewAfterReflow(presContext, this, view, visualOverflow, flags); } return NS_OK; }
void nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState) { if (mNeedsRecalc) { nsSize size; nsPresContext* presContext = aBoxLayoutState.PresContext(); nsIRenderingContext* rendContext = aBoxLayoutState.GetRenderingContext(); if (rendContext) { GetTextSize(presContext, *rendContext, mTitle, size, mAscent); mTextSize = size; mNeedsRecalc = PR_FALSE; } } }
NS_IMETHODIMP nsTextBoxFrame::DoLayout(nsBoxLayoutState& aBoxLayoutState) { if (mNeedsReflowCallback) { nsIReflowCallback* cb = new nsAsyncAccesskeyUpdate(this); if (cb) { PresContext()->PresShell()->PostReflowCallback(cb); } mNeedsReflowCallback = PR_FALSE; } mState |= NS_STATE_NEED_LAYOUT; nsresult rv = nsLeafBoxFrame::DoLayout(aBoxLayoutState); const nsStyleText* textStyle = GetStyleText(); if (textStyle->mTextShadow) { nsPoint origin(0,0); nsRect textRect = CalcTextRect(*aBoxLayoutState.GetRenderingContext(), origin); nsRect overflowRect(nsLayoutUtils::GetTextShadowRectsUnion(textRect, this)); overflowRect.UnionRect(overflowRect, nsRect(nsPoint(0, 0), GetSize())); FinishAndStoreOverflow(&overflowRect, GetSize()); } return rv; }
/* * Run down through our children dirtying them recursively. */ void nsGridRowGroupLayout::DirtyRows(nsIBox* aBox, nsBoxLayoutState& aState) { if (aBox) { // mark us dirty // XXXldb We probably don't want to walk up the ancestor chain // calling MarkIntrinsicWidthsDirty for every row group. aState.PresShell()->FrameNeedsReflow(aBox, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY); nsIBox* child = aBox->GetChildBox(); while(child) { // walk into scrollframes nsIBox* deepChild = nsGrid::GetScrolledBox(child); // walk into other monuments nsIGridPart* monument = nsGrid::GetPartFromBox(deepChild); if (monument) monument->DirtyRows(deepChild, aState); child = child->GetNextBox(); } } }
NS_IMETHODIMP nsListBoxBodyFrame::DoLayout(nsBoxLayoutState& aBoxLayoutState) { if (mScrolling) aBoxLayoutState.SetPaintingDisabled(PR_TRUE); nsresult rv = nsBoxFrame::DoLayout(aBoxLayoutState); if (mScrolling) aBoxLayoutState.SetPaintingDisabled(PR_FALSE); // if we are scrolled and the row height changed // make sure we are scrolled to a correct index. if (mAdjustScroll) PostReflowCallback(); return rv; }
void nsGridRowLeafLayout::DirtyRows(nsIBox* aBox, nsBoxLayoutState& aState) { if (aBox) { // mark us dirty // XXXldb We probably don't want to walk up the ancestor chain // calling MarkIntrinsicWidthsDirty for every row. aState.PresShell()->FrameNeedsReflow(aBox, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY); } }
void nsSplitterFrameInner::SetPreferredSize(nsBoxLayoutState& aState, nsIBox* aChildBox, nscoord aOnePixel, PRBool aIsHorizontal, nscoord* aSize) { //printf("current=%d, pref=%d", current/onePixel, pref/onePixel); nscoord current = 0; nsRect rect(aChildBox->GetRect()); if (aIsHorizontal) current = rect.width; else current = rect.height; nscoord pref = 0; if (!aSize) { if (aIsHorizontal) pref = rect.width; else pref = rect.height; } else { pref = *aSize; } nsMargin margin(0,0,0,0); aChildBox->GetMargin(margin); nsCOMPtr<nsIAtom> attribute; if (aIsHorizontal) { pref -= (margin.left + margin.right); attribute = nsGkAtoms::width; } else { pref -= (margin.top + margin.bottom); attribute = nsGkAtoms::height; } nsIContent* content = aChildBox->GetContent(); // set its preferred size. nsAutoString prefValue; prefValue.AppendInt(pref/aOnePixel); if (content->AttrValueIs(kNameSpaceID_None, attribute, prefValue, eCaseMatters)) return; nsWeakFrame weakBox(aChildBox); content->SetAttr(kNameSpaceID_None, attribute, prefValue, PR_TRUE); ENSURE_TRUE(weakBox.IsAlive()); aState.PresShell()->FrameNeedsReflow(aChildBox, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY); }
nsresult nsIFrame::Redraw(nsBoxLayoutState& aState) { if (aState.PaintingDisabled()) return NS_OK; // nsStackLayout, at least, expects us to repaint descendants even // if a damage rect is provided InvalidateFrameSubtree(); return NS_OK; }
void nsPopupSetFrame::RepositionPopup(nsPopupFrameList* aEntry, nsBoxLayoutState& aState) { // Sync up the view. if (aEntry && aEntry->mElementContent) { nsIFrame* frameToSyncTo = nsnull; nsPresContext* presContext = aState.PresContext(); presContext->PresShell()->GetPrimaryFrameFor(aEntry->mElementContent, &frameToSyncTo ); ((nsMenuPopupFrame*)(aEntry->mPopupFrame))->SyncViewWithFrame(presContext, aEntry->mPopupAnchor, aEntry->mPopupAlign, frameToSyncTo, aEntry->mXPos, aEntry->mYPos); } }
NS_IMETHODIMP nsListBoxBodyFrame::DoXULLayout(nsBoxLayoutState& aBoxLayoutState) { if (mScrolling) aBoxLayoutState.SetPaintingDisabled(true); nsresult rv = nsBoxFrame::DoXULLayout(aBoxLayoutState); // determine the real height for the scrollable area from the total number // of rows, since non-visible rows don't yet have frames nsRect rect(nsPoint(0, 0), GetSize()); nsOverflowAreas overflow(rect, rect); if (mLayoutManager) { nsIFrame* childFrame = mFrames.FirstChild(); while (childFrame) { ConsiderChildOverflow(overflow, childFrame); childFrame = childFrame->GetNextSibling(); } nsSize prefSize = mLayoutManager->GetXULPrefSize(this, aBoxLayoutState); NS_FOR_FRAME_OVERFLOW_TYPES(otype) { nsRect& o = overflow.Overflow(otype); o.height = std::max(o.height, prefSize.height); } } FinishAndStoreOverflow(overflow, GetSize()); if (mScrolling) aBoxLayoutState.SetPaintingDisabled(false); // if we are scrolled and the row height changed // make sure we are scrolled to a correct index. if (mAdjustScroll) PostReflowCallback(); return rv; }
nsSize nsBox::GetMinSize(nsBoxLayoutState& aState) { NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context"); nsSize min(0,0); DISPLAY_MIN_SIZE(this, min); if (IsCollapsed(aState)) return min; AddBorderAndPadding(min); nsIBox::AddCSSMinSize(aState, this, min); return min; }
nsSize nsBox::GetMaxSize(nsBoxLayoutState& aState) { NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context"); nsSize maxSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE); DISPLAY_MAX_SIZE(this, maxSize); if (IsCollapsed(aState)) return maxSize; AddBorderAndPadding(maxSize); nsIBox::AddCSSMaxSize(aState, this, maxSize); return maxSize; }
nsresult nsIFrame::Layout(nsBoxLayoutState& aState) { NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context"); nsBox *box = static_cast<nsBox*>(this); DISPLAY_LAYOUT(box); box->BeginLayout(aState); box->DoLayout(aState); box->EndLayout(aState); return NS_OK; }
nsSize nsBox::GetXULMinSize(nsBoxLayoutState& aState) { NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context"); nsSize min(0,0); DISPLAY_MIN_SIZE(this, min); if (IsXULCollapsed()) return min; AddBorderAndPadding(min); bool widthSet, heightSet; nsIFrame::AddXULMinSize(aState, this, min, widthSet, heightSet); return min; }
nsSize nsBox::GetXULMaxSize(nsBoxLayoutState& aState) { NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context"); nsSize maxSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE); DISPLAY_MAX_SIZE(this, maxSize); if (IsXULCollapsed()) return maxSize; AddBorderAndPadding(maxSize); bool widthSet, heightSet; nsIFrame::AddXULMaxSize(this, maxSize, widthSet, heightSet); return maxSize; }
void nsBox::SetBounds(nsBoxLayoutState& aState, const nsRect& aRect, PRBool aRemoveOverflowAreas) { NS_BOX_ASSERTION(this, aRect.width >=0 && aRect.height >= 0, "SetBounds Size < 0"); nsRect rect(mRect); PRUint32 flags = 0; GetLayoutFlags(flags); PRUint32 stateFlags = aState.LayoutFlags(); flags |= stateFlags; if ((flags & NS_FRAME_NO_MOVE_FRAME) == NS_FRAME_NO_MOVE_FRAME) SetSize(nsSize(aRect.width, aRect.height)); else SetRect(aRect); // Nuke the overflow area. The caller is responsible for restoring // it if necessary. if (aRemoveOverflowAreas) { // remove the previously stored overflow area ClearOverflowRects(); } if (!(flags & NS_FRAME_NO_MOVE_VIEW)) { nsContainerFrame::PositionFrameView(this); if ((rect.x != aRect.x) || (rect.y != aRect.y)) nsContainerFrame::PositionChildViews(this); } /* // only if the origin changed if ((rect.x != aRect.x) || (rect.y != aRect.y)) { if (frame->HasView()) { nsContainerFrame::PositionFrameView(presContext, frame, frame->GetView()); } else { nsContainerFrame::PositionChildViews(presContext, frame); } } */ }
nsresult nsIFrame::Redraw(nsBoxLayoutState& aState, const nsRect* aDamageRect, PRBool aImmediate) { if (aState.PaintingDisabled()) return NS_OK; nsRect damageRect(0,0,0,0); if (aDamageRect) damageRect = *aDamageRect; else damageRect = GetOverflowRect(); InvalidateWithFlags(damageRect, aImmediate ? INVALIDATE_IMMEDIATE : 0); return NS_OK; }
nsSize nsBox::GetPrefSize(nsBoxLayoutState& aState) { NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context"); nsSize pref(0,0); DISPLAY_PREF_SIZE(this, pref); if (IsCollapsed(aState)) return pref; AddBorderAndPadding(pref); nsIBox::AddCSSPrefSize(aState, this, pref); nsSize minSize = GetMinSize(aState); nsSize maxSize = GetMaxSize(aState); return BoundsCheck(minSize, pref, maxSize); }
nsSize nsBox::GetXULPrefSize(nsBoxLayoutState& aState) { NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context"); nsSize pref(0,0); DISPLAY_PREF_SIZE(this, pref); if (IsXULCollapsed()) return pref; AddBorderAndPadding(pref); bool widthSet, heightSet; nsIFrame::AddXULPrefSize(this, pref, widthSet, heightSet); nsSize minSize = GetXULMinSize(aState); nsSize maxSize = GetXULMaxSize(aState); return BoundsCheck(minSize, pref, maxSize); }
nsresult nsIFrame::Redraw(nsBoxLayoutState& aState, const nsRect* aDamageRect) { if (aState.PaintingDisabled()) return NS_OK; nsRect damageRect(0,0,0,0); if (aDamageRect) damageRect = *aDamageRect; else damageRect = GetVisualOverflowRect(); Invalidate(damageRect); // nsStackLayout, at least, expects us to repaint descendants even // if a damage rect is provided FrameLayerBuilder::InvalidateThebesLayersInSubtree(this); return NS_OK; }
nsSize nsTextControlFrame::GetPrefSize(nsBoxLayoutState& aState) { if (!DoesNeedRecalc(mPrefSize)) return mPrefSize; #ifdef DEBUG_LAYOUT PropagateDebug(aState); #endif nsSize pref(0,0); // FIXME: This inflation parameter isn't correct; we should fix it if // we want font size inflation to work well in XUL. If we do, we can // also re-enable the assertion in ComputeAutoSize when inflation is // enabled. nsresult rv = CalcIntrinsicSize(aState.GetRenderingContext(), pref, 1.0f); NS_ENSURE_SUCCESS(rv, pref); AddBorderAndPadding(pref); bool widthSet, heightSet; nsIBox::AddCSSPrefSize(this, pref, widthSet, heightSet); nsSize minSize = GetMinSize(aState); nsSize maxSize = GetMaxSize(aState); mPrefSize = BoundsCheck(minSize, pref, maxSize); #ifdef DEBUG_rods { nsMargin borderPadding(0,0,0,0); GetBorderAndPadding(borderPadding); nsSize size(169, 24); nsSize actual(pref.width/15, pref.height/15); printf("nsGfxText(field) %d,%d %d,%d %d,%d\n", size.width, size.height, actual.width, actual.height, actual.width-size.width, actual.height-size.height); // text field } #endif return mPrefSize; }
nsSize nsTextControlFrame::GetPrefSize(nsBoxLayoutState& aState) { if (!DoesNeedRecalc(mPrefSize)) return mPrefSize; #ifdef DEBUG_LAYOUT PropagateDebug(aState); #endif nsSize pref(0,0); nsresult rv = CalcIntrinsicSize(aState.GetRenderingContext(), pref); NS_ENSURE_SUCCESS(rv, pref); AddBorderAndPadding(pref); PRBool widthSet, heightSet; nsIBox::AddCSSPrefSize(this, pref, widthSet, heightSet); nsSize minSize = GetMinSize(aState); nsSize maxSize = GetMaxSize(aState); mPrefSize = BoundsCheck(minSize, pref, maxSize); #ifdef DEBUG_rods { nsMargin borderPadding(0,0,0,0); GetBorderAndPadding(borderPadding); nsSize size(169, 24); nsSize actual(pref.width/15, pref.height/15); printf("nsGfxText(field) %d,%d %d,%d %d,%d\n", size.width, size.height, actual.width, actual.height, actual.width-size.width, actual.height-size.height); // text field } #endif return mPrefSize; }
nscoord nsListBoxBodyFrame::ComputeIntrinsicISize(nsBoxLayoutState& aBoxLayoutState) { if (mStringWidth != -1) return mStringWidth; nscoord largestWidth = 0; int32_t index = 0; nsCOMPtr<nsIDOMElement> firstRowEl; GetItemAtIndex(index, getter_AddRefs(firstRowEl)); nsCOMPtr<nsIContent> firstRowContent(do_QueryInterface(firstRowEl)); if (firstRowContent) { RefPtr<nsStyleContext> styleContext; nsPresContext *presContext = aBoxLayoutState.PresContext(); styleContext = presContext->StyleSet()-> ResolveStyleFor(firstRowContent->AsElement(), nullptr, ConsumeStyleBehavior::DontConsume, LazyComputeBehavior::Allow); nscoord width = 0; nsMargin margin(0,0,0,0); if (styleContext->StylePadding()->GetPadding(margin)) width += margin.LeftRight(); width += styleContext->StyleBorder()->GetComputedBorder().LeftRight(); if (styleContext->StyleMargin()->GetMargin(margin)) width += margin.LeftRight(); FlattenedChildIterator iter(mContent); for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) { if (child->IsXULElement(nsGkAtoms::listitem)) { nsRenderingContext* rendContext = aBoxLayoutState.GetRenderingContext(); if (rendContext) { nsAutoString value; uint32_t textCount = child->GetChildCount(); for (uint32_t j = 0; j < textCount; ++j) { nsIContent* text = child->GetChildAt(j); if (text && text->IsNodeOfType(nsINode::eTEXT)) { text->AppendTextTo(value); } } RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetFontMetricsForStyleContext(styleContext); nscoord textWidth = nsLayoutUtils::AppUnitWidthOfStringBidi(value, this, *fm, *rendContext); textWidth += width; if (textWidth > largestWidth) largestWidth = textWidth; } } } } mStringWidth = largestWidth; return mStringWidth; }
PRBool nsIBox::AddCSSMinSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) { PRBool widthSet = PR_FALSE; PRBool heightSet = PR_FALSE; PRBool canOverride = PR_TRUE; // See if a native theme wants to supply a minimum size. const nsStyleDisplay* display = aBox->GetStyleDisplay(); if (display->mAppearance) { nsITheme *theme = aState.PresContext()->GetTheme(); if (theme && theme->ThemeSupportsWidget(aState.PresContext(), aBox, display->mAppearance)) { nsIntSize size; nsIRenderingContext* rendContext = aState.GetRenderingContext(); if (rendContext) { theme->GetMinimumWidgetSize(rendContext, aBox, display->mAppearance, &size, &canOverride); if (size.width) { aSize.width = aState.PresContext()->DevPixelsToAppUnits(size.width); widthSet = PR_TRUE; } if (size.height) { aSize.height = aState.PresContext()->DevPixelsToAppUnits(size.height); heightSet = PR_TRUE; } } } } // add in the css min, max, pref const nsStylePosition* position = aBox->GetStylePosition(); // same for min size. Unfortunately min size is always set to 0. So for now // we will assume 0 means not set. if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { nscoord min = position->mMinWidth.GetCoordValue(); if (min && (!widthSet || (min > aSize.width && canOverride))) { aSize.width = min; widthSet = PR_TRUE; } } else if (position->mMinWidth.GetUnit() == eStyleUnit_Percent) { NS_ASSERTION(position->mMinWidth.GetPercentValue() == 0.0f, "Non-zero percentage values not currently supported"); aSize.width = 0; widthSet = PR_TRUE; } // XXX Handle eStyleUnit_Enumerated? // (Handling the eStyleUnit_Enumerated types requires // GetPrefSize/GetMinSize methods that don't consider // (min-/max-/)(width/height) properties. if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) { nscoord min = position->mMinHeight.GetCoordValue(); if (min && (!heightSet || (min > aSize.height && canOverride))) { aSize.height = min; heightSet = PR_TRUE; } } else if (position->mMinHeight.GetUnit() == eStyleUnit_Percent) { NS_ASSERTION(position->mMinHeight.GetPercentValue() == 0.0f, "Non-zero percentage values not currently supported"); aSize.height = 0; heightSet = PR_TRUE; } nsIContent* content = aBox->GetContent(); if (content) { nsAutoString value; PRInt32 error; content->GetAttr(kNameSpaceID_None, nsGkAtoms::minwidth, value); if (!value.IsEmpty()) { value.Trim("%"); nscoord val = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error)); if (val > aSize.width) aSize.width = val; widthSet = PR_TRUE; } content->GetAttr(kNameSpaceID_None, nsGkAtoms::minheight, value); if (!value.IsEmpty()) { value.Trim("%"); nscoord val = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error)); if (val > aSize.height) aSize.height = val; heightSet = PR_TRUE; } } return (widthSet && heightSet); }
nsresult nsBox::SyncLayout(nsBoxLayoutState& aState) { /* PRBool collapsed = PR_FALSE; IsCollapsed(aState, collapsed); if (collapsed) { CollapseChild(aState, this, PR_TRUE); return NS_OK; } */ if (GetStateBits() & NS_FRAME_IS_DIRTY) Redraw(aState); RemoveStateBits(NS_FRAME_HAS_DIRTY_CHILDREN | NS_FRAME_IS_DIRTY | NS_FRAME_FIRST_REFLOW | NS_FRAME_IN_REFLOW); nsPresContext* presContext = aState.PresContext(); PRUint32 flags = 0; GetLayoutFlags(flags); PRUint32 stateFlags = aState.LayoutFlags(); flags |= stateFlags; nsRect rect(nsPoint(0, 0), GetSize()); if (ComputesOwnOverflowArea()) { rect = GetOverflowRect(); } else { if (!DoesClipChildren() && !IsCollapsed(aState)) { // See if our child frames caused us to overflow after being laid // out. If so, store the overflow area. This normally can't happen // in XUL, but it can happen with the CSS 'outline' property and // possibly with other exotic stuff (e.g. relatively positioned // frames in HTML inside XUL). nsIFrame* box = GetChildBox(); while (box) { nsRect bounds = box->GetOverflowRect() + box->GetPosition(); rect.UnionRect(rect, bounds); box = box->GetNextBox(); } } FinishAndStoreOverflow(&rect, GetSize()); } nsIView* view = GetView(); if (view) { // Make sure the frame's view is properly sized and positioned and has // things like opacity correct nsHTMLContainerFrame::SyncFrameViewAfterReflow( presContext, this, view, &rect, flags); } return NS_OK; }
nscoord nsListBoxBodyFrame::ComputeIntrinsicWidth(nsBoxLayoutState& aBoxLayoutState) { if (mStringWidth != -1) return mStringWidth; nscoord largestWidth = 0; PRInt32 index = 0; nsCOMPtr<nsIDOMElement> firstRowEl; GetItemAtIndex(index, getter_AddRefs(firstRowEl)); nsCOMPtr<nsIContent> firstRowContent(do_QueryInterface(firstRowEl)); if (firstRowContent) { nsRefPtr<nsStyleContext> styleContext; nsPresContext *presContext = aBoxLayoutState.PresContext(); styleContext = presContext->StyleSet()-> ResolveStyleFor(firstRowContent, nsnull); nscoord width = 0; nsMargin margin(0,0,0,0); if (styleContext->GetStylePadding()->GetPadding(margin)) width += margin.LeftRight(); width += styleContext->GetStyleBorder()->GetBorder().LeftRight(); if (styleContext->GetStyleMargin()->GetMargin(margin)) width += margin.LeftRight(); nsIContent* listbox = mContent->GetBindingParent(); NS_ENSURE_TRUE(listbox, largestWidth); PRUint32 childCount = listbox->GetChildCount(); for (PRUint32 i = 0; i < childCount && i < 100; ++i) { nsIContent *child = listbox->GetChildAt(i); if (child->Tag() == nsGkAtoms::listitem) { nsIRenderingContext* rendContext = aBoxLayoutState.GetRenderingContext(); if (rendContext) { nsAutoString value; PRUint32 textCount = child->GetChildCount(); for (PRUint32 j = 0; j < textCount; ++j) { nsIContent* text = child->GetChildAt(j); if (text && text->IsNodeOfType(nsINode::eTEXT)) { text->AppendTextTo(value); } } nsLayoutUtils::SetFontFromStyle(rendContext, styleContext); nscoord textWidth = nsLayoutUtils::GetStringWidth(this, rendContext, value.get(), value.Length()); textWidth += width; if (textWidth > largestWidth) largestWidth = textWidth; } } } } mStringWidth = largestWidth; return mStringWidth; }
PRBool nsIBox::AddCSSMinSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize, PRBool &aWidthSet, PRBool &aHeightSet) { aWidthSet = PR_FALSE; aHeightSet = PR_FALSE; PRBool canOverride = PR_TRUE; // See if a native theme wants to supply a minimum size. const nsStyleDisplay* display = aBox->GetStyleDisplay(); if (display->mAppearance) { nsITheme *theme = aState.PresContext()->GetTheme(); if (theme && theme->ThemeSupportsWidget(aState.PresContext(), aBox, display->mAppearance)) { nsIntSize size; nsRenderingContext* rendContext = aState.GetRenderingContext(); if (rendContext) { theme->GetMinimumWidgetSize(rendContext, aBox, display->mAppearance, &size, &canOverride); if (size.width) { aSize.width = aState.PresContext()->DevPixelsToAppUnits(size.width); aWidthSet = PR_TRUE; } if (size.height) { aSize.height = aState.PresContext()->DevPixelsToAppUnits(size.height); aHeightSet = PR_TRUE; } } } } // add in the css min, max, pref const nsStylePosition* position = aBox->GetStylePosition(); // same for min size. Unfortunately min size is always set to 0. So for now // we will assume 0 (as a coord) means not set. const nsStyleCoord &minWidth = position->mMinWidth; if ((minWidth.GetUnit() == eStyleUnit_Coord && minWidth.GetCoordValue() != 0) || (minWidth.IsCalcUnit() && !minWidth.CalcHasPercent())) { nscoord min = nsRuleNode::ComputeCoordPercentCalc(minWidth, 0); if (!aWidthSet || (min > aSize.width && canOverride)) { aSize.width = min; aWidthSet = PR_TRUE; } } else if (minWidth.GetUnit() == eStyleUnit_Percent) { NS_ASSERTION(minWidth.GetPercentValue() == 0.0f, "Non-zero percentage values not currently supported"); aSize.width = 0; aWidthSet = PR_TRUE; // FIXME: should we really do this for // nonzero values? } // XXX Handle eStyleUnit_Enumerated? // (Handling the eStyleUnit_Enumerated types requires // GetPrefSize/GetMinSize methods that don't consider // (min-/max-/)(width/height) properties. // calc() with percentage is treated like '0' (unset) const nsStyleCoord &minHeight = position->mMinHeight; if ((minHeight.GetUnit() == eStyleUnit_Coord && minHeight.GetCoordValue() != 0) || (minHeight.IsCalcUnit() && !minHeight.CalcHasPercent())) { nscoord min = nsRuleNode::ComputeCoordPercentCalc(minHeight, 0); if (!aHeightSet || (min > aSize.height && canOverride)) { aSize.height = min; aHeightSet = PR_TRUE; } } else if (minHeight.GetUnit() == eStyleUnit_Percent) { NS_ASSERTION(position->mMinHeight.GetPercentValue() == 0.0f, "Non-zero percentage values not currently supported"); aSize.height = 0; aHeightSet = PR_TRUE; // FIXME: should we really do this for // nonzero values? } // calc() with percentage is treated like '0' (unset) nsIContent* content = aBox->GetContent(); if (content) { nsAutoString value; PRInt32 error; content->GetAttr(kNameSpaceID_None, nsGkAtoms::minwidth, value); if (!value.IsEmpty()) { value.Trim("%"); nscoord val = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error)); if (val > aSize.width) aSize.width = val; aWidthSet = PR_TRUE; } content->GetAttr(kNameSpaceID_None, nsGkAtoms::minheight, value); if (!value.IsEmpty()) { value.Trim("%"); nscoord val = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error)); if (val > aSize.height) aSize.height = val; aHeightSet = PR_TRUE; } } return (aWidthSet && aHeightSet); }
nscoord nsListBoxBodyFrame::ComputeIntrinsicWidth(nsBoxLayoutState& aBoxLayoutState) { if (mStringWidth != -1) return mStringWidth; nscoord largestWidth = 0; PRInt32 index = 0; nsCOMPtr<nsIDOMElement> firstRowEl; GetItemAtIndex(index, getter_AddRefs(firstRowEl)); nsCOMPtr<nsIContent> firstRowContent(do_QueryInterface(firstRowEl)); if (firstRowContent) { nsRefPtr<nsStyleContext> styleContext; nsPresContext *presContext = aBoxLayoutState.PresContext(); styleContext = presContext->StyleSet()-> ResolveStyleFor(firstRowContent->AsElement(), nsnull); nscoord width = 0; nsMargin margin(0,0,0,0); if (styleContext->GetStylePadding()->GetPadding(margin)) width += margin.LeftRight(); width += styleContext->GetStyleBorder()->GetActualBorder().LeftRight(); if (styleContext->GetStyleMargin()->GetMargin(margin)) width += margin.LeftRight(); ChildIterator iter, last; PRUint32 i = 0; for (ChildIterator::Init(mContent, &iter, &last); iter != last && i < 100; ++iter, ++i) { nsIContent *child = (*iter); if (child->Tag() == nsGkAtoms::listitem) { nsRenderingContext* rendContext = aBoxLayoutState.GetRenderingContext(); if (rendContext) { nsAutoString value; PRUint32 textCount = child->GetChildCount(); for (PRUint32 j = 0; j < textCount; ++j) { nsIContent* text = child->GetChildAt(j); if (text && text->IsNodeOfType(nsINode::eTEXT)) { text->AppendTextTo(value); } } nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForStyleContext(styleContext, getter_AddRefs(fm)); rendContext->SetFont(fm); nscoord textWidth = nsLayoutUtils::GetStringWidth(this, rendContext, value.get(), value.Length()); textWidth += width; if (textWidth > largestWidth) largestWidth = textWidth; } } } } mStringWidth = largestWidth; return mStringWidth; }