mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-10 09:19:28 +00:00
Bug 1106667 - Vertical writing-mode support for HTML button elements. r=smontagu
This commit is contained in:
parent
a93db66c49
commit
a65c19199c
@ -142,7 +142,9 @@ nsHTMLButtonControlFrame::GetMinISize(nsRenderingContext* aRenderingContext)
|
||||
kid,
|
||||
nsLayoutUtils::MIN_ISIZE);
|
||||
|
||||
result += mRenderer.GetAddedButtonBorderAndPadding().LeftRight();
|
||||
result += GetWritingMode().IsVertical()
|
||||
? mRenderer.GetAddedButtonBorderAndPadding().TopBottom()
|
||||
: mRenderer.GetAddedButtonBorderAndPadding().LeftRight();
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -157,7 +159,11 @@ nsHTMLButtonControlFrame::GetPrefISize(nsRenderingContext* aRenderingContext)
|
||||
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
||||
kid,
|
||||
nsLayoutUtils::PREF_ISIZE);
|
||||
result += mRenderer.GetAddedButtonBorderAndPadding().LeftRight();
|
||||
|
||||
result += GetWritingMode().IsVertical()
|
||||
? mRenderer.GetAddedButtonBorderAndPadding().TopBottom()
|
||||
: mRenderer.GetAddedButtonBorderAndPadding().LeftRight();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -170,8 +176,8 @@ nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLButtonControlFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
NS_PRECONDITION(aReflowState.ComputedWidth() != NS_INTRINSICSIZE,
|
||||
"Should have real computed width by now");
|
||||
NS_PRECONDITION(aReflowState.ComputedISize() != NS_INTRINSICSIZE,
|
||||
"Should have real computed inline-size by now");
|
||||
|
||||
if (mState & NS_FRAME_FIRST_REFLOW) {
|
||||
nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
|
||||
@ -245,43 +251,49 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aButtonReflowState,
|
||||
nsIFrame* aFirstKid)
|
||||
{
|
||||
WritingMode wm = GetWritingMode();
|
||||
bool isVertical = wm.IsVertical();
|
||||
LogicalSize availSize = aButtonReflowState.ComputedSize(wm);
|
||||
availSize.BSize(wm) = NS_INTRINSICSIZE;
|
||||
|
||||
// Buttons have some bonus renderer-determined border/padding,
|
||||
// which occupies part of the button's content-box area:
|
||||
const nsMargin focusPadding = mRenderer.GetAddedButtonBorderAndPadding();
|
||||
const LogicalMargin focusPadding =
|
||||
LogicalMargin(wm, mRenderer.GetAddedButtonBorderAndPadding());
|
||||
|
||||
WritingMode wm = aFirstKid->GetWritingMode();
|
||||
LogicalSize availSize = aButtonReflowState.ComputedSize(GetWritingMode());
|
||||
availSize.BSize(wm) = NS_INTRINSICSIZE;
|
||||
// shorthand for a value we need to use in a bunch of places
|
||||
const LogicalMargin& clbp = aButtonReflowState.ComputedLogicalBorderPadding();
|
||||
|
||||
// Indent the child inside us by the focus border. We must do this separate
|
||||
// from the regular border.
|
||||
availSize.ISize(wm) -= LogicalMargin(wm, focusPadding).IStartEnd(wm);
|
||||
availSize.ISize(wm) -= focusPadding.IStartEnd(wm);
|
||||
|
||||
// See whether out availSize's width is big enough. If it's smaller than our
|
||||
// intrinsic min width, that means that the kid wouldn't really fit; for a
|
||||
// better look in such cases we adjust the available width and our left
|
||||
// offset to allow the kid to spill left into our padding.
|
||||
nscoord xoffset = focusPadding.left +
|
||||
aButtonReflowState.ComputedPhysicalBorderPadding().left;
|
||||
nscoord extrawidth = GetMinISize(aButtonReflowState.rendContext) -
|
||||
aButtonReflowState.ComputedWidth();
|
||||
if (extrawidth > 0) {
|
||||
nscoord extraleft = extrawidth / 2;
|
||||
nscoord extraright = extrawidth - extraleft;
|
||||
NS_ASSERTION(extraright >=0, "How'd that happen?");
|
||||
// See whether out availSize's inline-size is big enough. If it's smaller than
|
||||
// our intrinsic min iSize, that means that the kid wouldn't really fit; for a
|
||||
// better look in such cases we adjust the available iSize and our inline-start
|
||||
// offset to allow the kid to spill start-wards into our padding.
|
||||
nscoord ioffset = focusPadding.IStart(wm) + clbp.IStart(wm);
|
||||
nscoord extraISize = GetMinISize(aButtonReflowState.rendContext) -
|
||||
aButtonReflowState.ComputedISize();
|
||||
if (extraISize > 0) {
|
||||
nscoord extraIStart = extraISize / 2;
|
||||
nscoord extraIEnd = extraISize - extraIStart;
|
||||
NS_ASSERTION(extraIEnd >=0, "How'd that happen?");
|
||||
|
||||
// Do not allow the extras to be bigger than the relevant padding
|
||||
extraleft = std::min(extraleft, aButtonReflowState.ComputedPhysicalPadding().left);
|
||||
extraright = std::min(extraright, aButtonReflowState.ComputedPhysicalPadding().right);
|
||||
xoffset -= extraleft;
|
||||
availSize.Width(wm) = availSize.Width(wm) + extraleft + extraright;
|
||||
const LogicalMargin& padding = aButtonReflowState.ComputedLogicalPadding();
|
||||
extraIStart = std::min(extraIStart, padding.IStart(wm));
|
||||
extraIEnd = std::min(extraIEnd, padding.IEnd(wm));
|
||||
ioffset -= extraIStart;
|
||||
availSize.ISize(wm) = availSize.ISize(wm) + extraIStart + extraIEnd;
|
||||
}
|
||||
availSize.Width(wm) = std::max(availSize.Width(wm), 0);
|
||||
availSize.ISize(wm) = std::max(availSize.ISize(wm), 0);
|
||||
|
||||
// Give child a clone of the button's reflow state, with height/width reduced
|
||||
// by focusPadding, so that descendants with height:100% don't protrude.
|
||||
nsHTMLReflowState adjustedButtonReflowState =
|
||||
CloneReflowStateWithReducedContentBox(aButtonReflowState, focusPadding);
|
||||
CloneReflowStateWithReducedContentBox(aButtonReflowState,
|
||||
focusPadding.GetPhysicalMargin(wm));
|
||||
|
||||
nsHTMLReflowState contentsReflowState(aPresContext,
|
||||
adjustedButtonReflowState,
|
||||
@ -289,53 +301,56 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
|
||||
|
||||
nsReflowStatus contentsReflowStatus;
|
||||
nsHTMLReflowMetrics contentsDesiredSize(aButtonReflowState);
|
||||
nscoord boffset = focusPadding.BStart(wm) + clbp.BStart(wm);
|
||||
ReflowChild(aFirstKid, aPresContext,
|
||||
contentsDesiredSize, contentsReflowState,
|
||||
xoffset,
|
||||
focusPadding.top + aButtonReflowState.ComputedPhysicalBorderPadding().top,
|
||||
isVertical ? boffset : ioffset,
|
||||
isVertical ? ioffset : boffset,
|
||||
0, contentsReflowStatus);
|
||||
MOZ_ASSERT(NS_FRAME_IS_COMPLETE(contentsReflowStatus),
|
||||
"We gave button-contents frame unconstrained available height, "
|
||||
"so it should be complete");
|
||||
|
||||
// Compute the button's content-box height:
|
||||
nscoord buttonContentBoxHeight = 0;
|
||||
if (aButtonReflowState.ComputedHeight() != NS_INTRINSICSIZE) {
|
||||
// Button has a fixed height -- that's its content-box height.
|
||||
buttonContentBoxHeight = aButtonReflowState.ComputedHeight();
|
||||
nscoord buttonContentBoxBSize = 0;
|
||||
if (aButtonReflowState.ComputedBSize() != NS_INTRINSICSIZE) {
|
||||
// Button has a fixed block-size -- that's its content-box bSize.
|
||||
buttonContentBoxBSize = aButtonReflowState.ComputedBSize();
|
||||
} else {
|
||||
// Button is intrinsically sized -- it should shrinkwrap the
|
||||
// button-contents' height, plus any focus-padding space:
|
||||
buttonContentBoxHeight =
|
||||
contentsDesiredSize.Height() + focusPadding.TopBottom();
|
||||
// button-contents' bSize, plus any focus-padding space:
|
||||
buttonContentBoxBSize =
|
||||
contentsDesiredSize.BSize(wm) + focusPadding.BStartEnd(wm);
|
||||
|
||||
// Make sure we obey min/max-height in the case when we're doing intrinsic
|
||||
// Make sure we obey min/max-bSize in the case when we're doing intrinsic
|
||||
// sizing (we get it for free when we have a non-intrinsic
|
||||
// aButtonReflowState.ComputedHeight()). Note that we do this before
|
||||
// adjusting for borderpadding, since mComputedMaxHeight and
|
||||
// mComputedMinHeight are content heights.
|
||||
buttonContentBoxHeight =
|
||||
NS_CSS_MINMAX(buttonContentBoxHeight,
|
||||
aButtonReflowState.ComputedMinHeight(),
|
||||
aButtonReflowState.ComputedMaxHeight());
|
||||
// aButtonReflowState.ComputedBSize()). Note that we do this before
|
||||
// adjusting for borderpadding, since mComputedMaxBSize and
|
||||
// mComputedMinBSize are content bSizes.
|
||||
buttonContentBoxBSize =
|
||||
NS_CSS_MINMAX(buttonContentBoxBSize,
|
||||
aButtonReflowState.ComputedMinBSize(),
|
||||
aButtonReflowState.ComputedMaxBSize());
|
||||
}
|
||||
|
||||
// Center child vertically in the button
|
||||
// Center child in the block-direction in the button
|
||||
// (technically, inside of the button's focus-padding area)
|
||||
nscoord extraSpace =
|
||||
buttonContentBoxHeight - focusPadding.TopBottom() -
|
||||
contentsDesiredSize.Height();
|
||||
buttonContentBoxBSize - focusPadding.BStartEnd(wm) -
|
||||
contentsDesiredSize.BSize(wm);
|
||||
|
||||
nscoord yoffset = std::max(0, extraSpace / 2);
|
||||
boffset = std::max(0, extraSpace / 2);
|
||||
|
||||
// Adjust yoffset to be in terms of the button's frame-rect, instead of
|
||||
// Adjust boffset to be in terms of the button's frame-rect, instead of
|
||||
// its focus-padding rect:
|
||||
yoffset += focusPadding.top + aButtonReflowState.ComputedPhysicalBorderPadding().top;
|
||||
boffset += focusPadding.BStart(wm) + clbp.BStart(wm);
|
||||
|
||||
// Place the child
|
||||
FinishReflowChild(aFirstKid, aPresContext,
|
||||
contentsDesiredSize, &contentsReflowState,
|
||||
xoffset, yoffset, 0);
|
||||
isVertical ? boffset : ioffset,
|
||||
isVertical ? ioffset : boffset,
|
||||
0);
|
||||
|
||||
// Make sure we have a useful 'ascent' value for the child
|
||||
if (contentsDesiredSize.BlockStartAscent() ==
|
||||
@ -347,16 +362,20 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
|
||||
// OK, we're done with the child frame.
|
||||
// Use what we learned to populate the button frame's reflow metrics.
|
||||
// * Button's height & width are content-box size + border-box contribution:
|
||||
aButtonDesiredSize.Width() = aButtonReflowState.ComputedWidth() +
|
||||
aButtonReflowState.ComputedPhysicalBorderPadding().LeftRight();
|
||||
aButtonDesiredSize.SetSize(wm,
|
||||
LogicalSize(wm, aButtonReflowState.ComputedISize() + clbp.IStartEnd(wm),
|
||||
buttonContentBoxBSize + clbp.BStartEnd(wm)));
|
||||
|
||||
aButtonDesiredSize.Height() = buttonContentBoxHeight +
|
||||
aButtonReflowState.ComputedPhysicalBorderPadding().TopBottom();
|
||||
|
||||
// * Button's ascent is its child's ascent, plus the child's y-offset
|
||||
// within our frame:
|
||||
aButtonDesiredSize.SetBlockStartAscent(contentsDesiredSize.BlockStartAscent() +
|
||||
yoffset);
|
||||
// * Button's ascent is its child's ascent, plus the child's block-offset
|
||||
// within our frame... unless it's orthogonal, in which case we'll use the
|
||||
// contents inline-size as an approximation for now.
|
||||
// XXX is there a better strategy? should we include border-padding?
|
||||
if (aButtonDesiredSize.GetWritingMode().IsOrthogonalTo(wm)) {
|
||||
aButtonDesiredSize.SetBlockStartAscent(contentsDesiredSize.ISize(wm));
|
||||
} else {
|
||||
aButtonDesiredSize.SetBlockStartAscent(contentsDesiredSize.BlockStartAscent() +
|
||||
boffset);
|
||||
}
|
||||
|
||||
aButtonDesiredSize.SetOverflowAreasToDesiredBounds();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user