forked from mirrors/gecko-dev
		
	 f5a42005e2
			
		
	
	
		f5a42005e2
		
	
	
	
	
		
			
			Changed from returning `bool` & taking an out parameter. Differential Revision: https://phabricator.services.mozilla.com/D168998
		
			
				
	
	
		
			201 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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) 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()));
 | |
| }
 |