mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	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()));
 | 
						|
}
 |