diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /layout/forms/nsDateTimeControlFrame.cpp | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/forms/nsDateTimeControlFrame.cpp')
-rw-r--r-- | layout/forms/nsDateTimeControlFrame.cpp | 201 |
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())); +} |