summaryrefslogtreecommitdiffstats
path: root/layout/forms/nsDateTimeControlFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/forms/nsDateTimeControlFrame.cpp')
-rw-r--r--layout/forms/nsDateTimeControlFrame.cpp201
1 files changed, 201 insertions, 0 deletions
diff --git a/layout/forms/nsDateTimeControlFrame.cpp b/layout/forms/nsDateTimeControlFrame.cpp
new file mode 100644
index 0000000000..d80f4ea2ce
--- /dev/null
+++ b/layout/forms/nsDateTimeControlFrame.cpp
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * This frame type is used for input type=date, time, month, week, and
+ * datetime-local.
+ */
+
+#include "nsDateTimeControlFrame.h"
+
+#include "mozilla/PresShell.h"
+#include "nsLayoutUtils.h"
+#include "nsTextControlFrame.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+nsIFrame* NS_NewDateTimeControlFrame(PresShell* aPresShell,
+ ComputedStyle* aStyle) {
+ return new (aPresShell)
+ nsDateTimeControlFrame(aStyle, aPresShell->GetPresContext());
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(nsDateTimeControlFrame)
+
+NS_QUERYFRAME_HEAD(nsDateTimeControlFrame)
+ NS_QUERYFRAME_ENTRY(nsDateTimeControlFrame)
+NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
+
+nsDateTimeControlFrame::nsDateTimeControlFrame(ComputedStyle* aStyle,
+ nsPresContext* aPresContext)
+ : nsContainerFrame(aStyle, aPresContext, kClassID) {}
+
+nscoord nsDateTimeControlFrame::GetMinISize(gfxContext* aRenderingContext) {
+ nscoord result;
+ DISPLAY_MIN_INLINE_SIZE(this, result);
+
+ nsIFrame* kid = mFrames.FirstChild();
+ if (kid) { // display:none?
+ result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, kid,
+ IntrinsicISizeType::MinISize);
+ } else {
+ result = 0;
+ }
+
+ return result;
+}
+
+nscoord nsDateTimeControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
+ nscoord result;
+ DISPLAY_PREF_INLINE_SIZE(this, result);
+
+ nsIFrame* kid = mFrames.FirstChild();
+ if (kid) { // display:none?
+ result = nsLayoutUtils::IntrinsicForContainer(
+ aRenderingContext, kid, IntrinsicISizeType::PrefISize);
+ } else {
+ result = 0;
+ }
+
+ return result;
+}
+
+Maybe<nscoord> nsDateTimeControlFrame::GetNaturalBaselineBOffset(
+ WritingMode aWM, BaselineSharingGroup aBaselineGroup,
+ BaselineExportContext) const {
+ return nsTextControlFrame::GetSingleLineTextControlBaseline(
+ this, mFirstBaseline, aWM, aBaselineGroup);
+}
+
+void nsDateTimeControlFrame::Reflow(nsPresContext* aPresContext,
+ ReflowOutput& aDesiredSize,
+ const ReflowInput& aReflowInput,
+ nsReflowStatus& aStatus) {
+ MarkInReflow();
+
+ DO_GLOBAL_REFLOW_COUNT("nsDateTimeControlFrame");
+ DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
+ MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
+ NS_FRAME_TRACE(
+ NS_FRAME_TRACE_CALLS,
+ ("enter nsDateTimeControlFrame::Reflow: availSize=%d,%d",
+ aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
+
+ NS_ASSERTION(mFrames.GetLength() <= 1,
+ "There should be no more than 1 frames");
+
+ const WritingMode myWM = aReflowInput.GetWritingMode();
+
+ {
+ auto baseline = nsTextControlFrame::ComputeBaseline(
+ this, aReflowInput, /* aForSingleLineControl = */ true);
+ mFirstBaseline = baseline.valueOr(NS_INTRINSIC_ISIZE_UNKNOWN);
+ if (baseline) {
+ aDesiredSize.SetBlockStartAscent(*baseline);
+ }
+ }
+
+ // The ISize of our content box, which is the available ISize
+ // for our anonymous content:
+ const nscoord contentBoxISize = aReflowInput.ComputedISize();
+ nscoord contentBoxBSize = aReflowInput.ComputedBSize();
+
+ // Figure out our border-box sizes as well (by adding borderPadding to
+ // content-box sizes):
+ const auto borderPadding = aReflowInput.ComputedLogicalBorderPadding(myWM);
+ const nscoord borderBoxISize =
+ contentBoxISize + borderPadding.IStartEnd(myWM);
+
+ nscoord borderBoxBSize;
+ if (contentBoxBSize != NS_UNCONSTRAINEDSIZE) {
+ borderBoxBSize = contentBoxBSize + borderPadding.BStartEnd(myWM);
+ } // else, we'll figure out borderBoxBSize after we resolve contentBoxBSize.
+
+ nsIFrame* inputAreaFrame = mFrames.FirstChild();
+ if (!inputAreaFrame) { // display:none?
+ if (contentBoxBSize == NS_UNCONSTRAINEDSIZE) {
+ contentBoxBSize = 0;
+ borderBoxBSize = borderPadding.BStartEnd(myWM);
+ }
+ } else {
+ ReflowOutput childDesiredSize(aReflowInput);
+
+ WritingMode wm = inputAreaFrame->GetWritingMode();
+ LogicalSize availSize = aReflowInput.ComputedSize(wm);
+ availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
+
+ ReflowInput childReflowInput(aPresContext, aReflowInput, inputAreaFrame,
+ availSize);
+
+ // Convert input area margin into my own writing-mode (in case it differs):
+ LogicalMargin childMargin = childReflowInput.ComputedLogicalMargin(myWM);
+
+ // offsets of input area frame within this frame:
+ LogicalPoint childOffset(
+ myWM, borderPadding.IStart(myWM) + childMargin.IStart(myWM),
+ borderPadding.BStart(myWM) + childMargin.BStart(myWM));
+
+ nsReflowStatus childStatus;
+ // We initially reflow the child with a dummy containerSize; positioning
+ // will be fixed later.
+ const nsSize dummyContainerSize;
+ ReflowChild(inputAreaFrame, aPresContext, childDesiredSize,
+ childReflowInput, myWM, childOffset, dummyContainerSize,
+ ReflowChildFlags::Default, childStatus);
+ MOZ_ASSERT(childStatus.IsFullyComplete(),
+ "We gave our child unconstrained available block-size, "
+ "so it should be complete");
+
+ nscoord childMarginBoxBSize =
+ childDesiredSize.BSize(myWM) + childMargin.BStartEnd(myWM);
+
+ if (contentBoxBSize == NS_UNCONSTRAINEDSIZE) {
+ // We are intrinsically sized -- we should shrinkwrap the input area's
+ // block-size, or our line-height:
+ contentBoxBSize =
+ std::max(aReflowInput.GetLineHeight(), childMarginBoxBSize);
+
+ // 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
+ // aReflowInput.ComputedBSize()). Note that we do this before
+ // adjusting for borderpadding, since ComputedMaxBSize and
+ // ComputedMinBSize are content heights.
+ contentBoxBSize =
+ NS_CSS_MINMAX(contentBoxBSize, aReflowInput.ComputedMinBSize(),
+ aReflowInput.ComputedMaxBSize());
+
+ borderBoxBSize = contentBoxBSize + borderPadding.BStartEnd(myWM);
+ }
+
+ // Center child in block axis
+ nscoord extraSpace = contentBoxBSize - childMarginBoxBSize;
+ childOffset.B(myWM) += std::max(0, extraSpace / 2);
+
+ // Needed in FinishReflowChild, for logical-to-physical conversion:
+ nsSize borderBoxSize =
+ LogicalSize(myWM, borderBoxISize, borderBoxBSize).GetPhysicalSize(myWM);
+
+ // Place the child
+ FinishReflowChild(inputAreaFrame, aPresContext, childDesiredSize,
+ &childReflowInput, myWM, childOffset, borderBoxSize,
+ ReflowChildFlags::Default);
+ }
+
+ LogicalSize logicalDesiredSize(myWM, borderBoxISize, borderBoxBSize);
+ aDesiredSize.SetSize(myWM, logicalDesiredSize);
+ aDesiredSize.SetOverflowAreasToDesiredBounds();
+
+ if (inputAreaFrame) {
+ ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inputAreaFrame);
+ }
+
+ FinishAndStoreOverflow(&aDesiredSize);
+
+ NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
+ ("exit nsDateTimeControlFrame::Reflow: size=%d,%d",
+ aDesiredSize.Width(), aDesiredSize.Height()));
+}