1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 * This frame type is used for input type=date, time, month, week, and
12 #include "nsDateTimeControlFrame.h"
14 #include "mozilla/PresShell.h"
15 #include "nsLayoutUtils.h"
16 #include "nsTextControlFrame.h"
18 using namespace mozilla
;
19 using namespace mozilla::dom
;
21 nsIFrame
* NS_NewDateTimeControlFrame(PresShell
* aPresShell
,
22 ComputedStyle
* aStyle
) {
23 return new (aPresShell
)
24 nsDateTimeControlFrame(aStyle
, aPresShell
->GetPresContext());
27 NS_IMPL_FRAMEARENA_HELPERS(nsDateTimeControlFrame
)
29 NS_QUERYFRAME_HEAD(nsDateTimeControlFrame
)
30 NS_QUERYFRAME_ENTRY(nsDateTimeControlFrame
)
31 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame
)
33 nsDateTimeControlFrame::nsDateTimeControlFrame(ComputedStyle
* aStyle
,
34 nsPresContext
* aPresContext
)
35 : nsContainerFrame(aStyle
, aPresContext
, kClassID
) {}
37 nscoord
nsDateTimeControlFrame::GetMinISize(gfxContext
* aRenderingContext
) {
39 DISPLAY_MIN_INLINE_SIZE(this, result
);
41 nsIFrame
* kid
= mFrames
.FirstChild();
42 if (kid
) { // display:none?
43 result
= nsLayoutUtils::IntrinsicForContainer(aRenderingContext
, kid
,
44 IntrinsicISizeType::MinISize
);
52 nscoord
nsDateTimeControlFrame::GetPrefISize(gfxContext
* aRenderingContext
) {
54 DISPLAY_PREF_INLINE_SIZE(this, result
);
56 nsIFrame
* kid
= mFrames
.FirstChild();
57 if (kid
) { // display:none?
58 result
= nsLayoutUtils::IntrinsicForContainer(
59 aRenderingContext
, kid
, IntrinsicISizeType::PrefISize
);
67 Maybe
<nscoord
> nsDateTimeControlFrame::GetNaturalBaselineBOffset(
68 WritingMode aWM
, BaselineSharingGroup aBaselineGroup
,
69 BaselineExportContext
) const {
70 return nsTextControlFrame::GetSingleLineTextControlBaseline(
71 this, mFirstBaseline
, aWM
, aBaselineGroup
);
74 void nsDateTimeControlFrame::Reflow(nsPresContext
* aPresContext
,
75 ReflowOutput
& aDesiredSize
,
76 const ReflowInput
& aReflowInput
,
77 nsReflowStatus
& aStatus
) {
80 DO_GLOBAL_REFLOW_COUNT("nsDateTimeControlFrame");
81 DISPLAY_REFLOW(aPresContext
, this, aReflowInput
, aDesiredSize
, aStatus
);
82 MOZ_ASSERT(aStatus
.IsEmpty(), "Caller should pass a fresh reflow status!");
85 ("enter nsDateTimeControlFrame::Reflow: availSize=%d,%d",
86 aReflowInput
.AvailableWidth(), aReflowInput
.AvailableHeight()));
88 NS_ASSERTION(mFrames
.GetLength() <= 1,
89 "There should be no more than 1 frames");
91 const WritingMode myWM
= aReflowInput
.GetWritingMode();
94 auto baseline
= nsTextControlFrame::ComputeBaseline(
95 this, aReflowInput
, /* aForSingleLineControl = */ true);
96 mFirstBaseline
= baseline
.valueOr(NS_INTRINSIC_ISIZE_UNKNOWN
);
98 aDesiredSize
.SetBlockStartAscent(*baseline
);
102 // The ISize of our content box, which is the available ISize
103 // for our anonymous content:
104 const nscoord contentBoxISize
= aReflowInput
.ComputedISize();
105 nscoord contentBoxBSize
= aReflowInput
.ComputedBSize();
107 // Figure out our border-box sizes as well (by adding borderPadding to
108 // content-box sizes):
109 const auto borderPadding
= aReflowInput
.ComputedLogicalBorderPadding(myWM
);
110 const nscoord borderBoxISize
=
111 contentBoxISize
+ borderPadding
.IStartEnd(myWM
);
113 nscoord borderBoxBSize
;
114 if (contentBoxBSize
!= NS_UNCONSTRAINEDSIZE
) {
115 borderBoxBSize
= contentBoxBSize
+ borderPadding
.BStartEnd(myWM
);
116 } // else, we'll figure out borderBoxBSize after we resolve contentBoxBSize.
118 nsIFrame
* inputAreaFrame
= mFrames
.FirstChild();
119 if (!inputAreaFrame
) { // display:none?
120 if (contentBoxBSize
== NS_UNCONSTRAINEDSIZE
) {
122 borderBoxBSize
= borderPadding
.BStartEnd(myWM
);
125 ReflowOutput
childDesiredSize(aReflowInput
);
127 WritingMode wm
= inputAreaFrame
->GetWritingMode();
128 LogicalSize availSize
= aReflowInput
.ComputedSize(wm
);
129 availSize
.BSize(wm
) = NS_UNCONSTRAINEDSIZE
;
131 ReflowInput
childReflowInput(aPresContext
, aReflowInput
, inputAreaFrame
,
134 // Convert input area margin into my own writing-mode (in case it differs):
135 LogicalMargin childMargin
= childReflowInput
.ComputedLogicalMargin(myWM
);
137 // offsets of input area frame within this frame:
138 LogicalPoint
childOffset(
139 myWM
, borderPadding
.IStart(myWM
) + childMargin
.IStart(myWM
),
140 borderPadding
.BStart(myWM
) + childMargin
.BStart(myWM
));
142 nsReflowStatus childStatus
;
143 // We initially reflow the child with a dummy containerSize; positioning
144 // will be fixed later.
145 const nsSize dummyContainerSize
;
146 ReflowChild(inputAreaFrame
, aPresContext
, childDesiredSize
,
147 childReflowInput
, myWM
, childOffset
, dummyContainerSize
,
148 ReflowChildFlags::Default
, childStatus
);
149 MOZ_ASSERT(childStatus
.IsFullyComplete(),
150 "We gave our child unconstrained available block-size, "
151 "so it should be complete");
153 nscoord childMarginBoxBSize
=
154 childDesiredSize
.BSize(myWM
) + childMargin
.BStartEnd(myWM
);
156 if (contentBoxBSize
== NS_UNCONSTRAINEDSIZE
) {
157 // We are intrinsically sized -- we should shrinkwrap the input area's
158 // block-size, or our line-height:
160 std::max(aReflowInput
.GetLineHeight(), childMarginBoxBSize
);
162 // Make sure we obey min/max-bsize in the case when we're doing intrinsic
163 // sizing (we get it for free when we have a non-intrinsic
164 // aReflowInput.ComputedBSize()). Note that we do this before
165 // adjusting for borderpadding, since ComputedMaxBSize and
166 // ComputedMinBSize are content heights.
168 NS_CSS_MINMAX(contentBoxBSize
, aReflowInput
.ComputedMinBSize(),
169 aReflowInput
.ComputedMaxBSize());
171 borderBoxBSize
= contentBoxBSize
+ borderPadding
.BStartEnd(myWM
);
174 // Center child in block axis
175 nscoord extraSpace
= contentBoxBSize
- childMarginBoxBSize
;
176 childOffset
.B(myWM
) += std::max(0, extraSpace
/ 2);
178 // Needed in FinishReflowChild, for logical-to-physical conversion:
179 nsSize borderBoxSize
=
180 LogicalSize(myWM
, borderBoxISize
, borderBoxBSize
).GetPhysicalSize(myWM
);
183 FinishReflowChild(inputAreaFrame
, aPresContext
, childDesiredSize
,
184 &childReflowInput
, myWM
, childOffset
, borderBoxSize
,
185 ReflowChildFlags::Default
);
188 LogicalSize
logicalDesiredSize(myWM
, borderBoxISize
, borderBoxBSize
);
189 aDesiredSize
.SetSize(myWM
, logicalDesiredSize
);
190 aDesiredSize
.SetOverflowAreasToDesiredBounds();
192 if (inputAreaFrame
) {
193 ConsiderChildOverflow(aDesiredSize
.mOverflowAreas
, inputAreaFrame
);
196 FinishAndStoreOverflow(&aDesiredSize
);
198 NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS
,
199 ("exit nsDateTimeControlFrame::Reflow: size=%d,%d",
200 aDesiredSize
.Width(), aDesiredSize
.Height()));