123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* 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/. */
- //
- // Eric Vaughan
- // Netscape Communications
- //
- // See documentation in associated header file
- //
- #include "nsLeafBoxFrame.h"
- #include "nsBoxFrame.h"
- #include "nsCOMPtr.h"
- #include "nsGkAtoms.h"
- #include "nsPresContext.h"
- #include "nsStyleContext.h"
- #include "nsIContent.h"
- #include "nsNameSpaceManager.h"
- #include "nsBoxLayoutState.h"
- #include "nsWidgetsCID.h"
- #include "nsViewManager.h"
- #include "nsContainerFrame.h"
- #include "nsDisplayList.h"
- #include <algorithm>
- using namespace mozilla;
- //
- // NS_NewLeafBoxFrame
- //
- // Creates a new Toolbar frame and returns it
- //
- nsIFrame*
- NS_NewLeafBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
- {
- return new (aPresShell) nsLeafBoxFrame(aContext);
- }
- NS_IMPL_FRAMEARENA_HELPERS(nsLeafBoxFrame)
- nsLeafBoxFrame::nsLeafBoxFrame(nsStyleContext* aContext)
- : nsLeafFrame(aContext)
- {
- }
- #ifdef DEBUG_LAYOUT
- void
- nsLeafBoxFrame::GetBoxName(nsAutoString& aName)
- {
- GetFrameName(aName);
- }
- #endif
- /**
- * Initialize us. This is a good time to get the alignment of the box
- */
- void
- nsLeafBoxFrame::Init(nsIContent* aContent,
- nsContainerFrame* aParent,
- nsIFrame* aPrevInFlow)
- {
- nsLeafFrame::Init(aContent, aParent, aPrevInFlow);
- if (GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER) {
- AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
- }
- UpdateMouseThrough();
- }
- nsresult
- nsLeafBoxFrame::AttributeChanged(int32_t aNameSpaceID,
- nsIAtom* aAttribute,
- int32_t aModType)
- {
- nsresult rv = nsLeafFrame::AttributeChanged(aNameSpaceID, aAttribute,
- aModType);
- if (aAttribute == nsGkAtoms::mousethrough)
- UpdateMouseThrough();
- return rv;
- }
- void nsLeafBoxFrame::UpdateMouseThrough()
- {
- if (mContent) {
- static nsIContent::AttrValuesArray strings[] =
- {&nsGkAtoms::never, &nsGkAtoms::always, nullptr};
- switch (mContent->FindAttrValueIn(kNameSpaceID_None,
- nsGkAtoms::mousethrough,
- strings, eCaseMatters)) {
- case 0: AddStateBits(NS_FRAME_MOUSE_THROUGH_NEVER); break;
- case 1: AddStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS); break;
- case 2: {
- RemoveStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS);
- RemoveStateBits(NS_FRAME_MOUSE_THROUGH_NEVER);
- break;
- }
- }
- }
- }
- void
- nsLeafBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists)
- {
- // REVIEW: GetFrameForPoint used to not report events for the background
- // layer, whereas this code will put an event receiver for this frame in the
- // BlockBorderBackground() list. But I don't see any need to preserve
- // that anomalous behaviour. The important thing I'm preserving is that
- // leaf boxes continue to receive events in the foreground layer.
- DisplayBorderBackgroundOutline(aBuilder, aLists);
- if (!aBuilder->IsForEventDelivery() || !IsVisibleForPainting(aBuilder))
- return;
- aLists.Content()->AppendNewToTop(new (aBuilder)
- nsDisplayEventReceiver(aBuilder, this));
- }
- /* virtual */ nscoord
- nsLeafBoxFrame::GetMinISize(nsRenderingContext *aRenderingContext)
- {
- nscoord result;
- DISPLAY_MIN_WIDTH(this, result);
- nsBoxLayoutState state(PresContext(), aRenderingContext);
- WritingMode wm = GetWritingMode();
- LogicalSize minSize(wm, GetXULMinSize(state));
- // GetXULMinSize returns border-box size, and we want to return content
- // inline-size. Since Reflow uses the reflow state's border and padding, we
- // actually just want to subtract what GetXULMinSize added, which is the
- // result of GetXULBorderAndPadding.
- nsMargin bp;
- GetXULBorderAndPadding(bp);
- result = minSize.ISize(wm) - LogicalMargin(wm, bp).IStartEnd(wm);
- return result;
- }
- /* virtual */ nscoord
- nsLeafBoxFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
- {
- nscoord result;
- DISPLAY_PREF_WIDTH(this, result);
- nsBoxLayoutState state(PresContext(), aRenderingContext);
- WritingMode wm = GetWritingMode();
- LogicalSize prefSize(wm, GetXULPrefSize(state));
- // GetXULPrefSize returns border-box size, and we want to return content
- // inline-size. Since Reflow uses the reflow state's border and padding, we
- // actually just want to subtract what GetXULPrefSize added, which is the
- // result of GetXULBorderAndPadding.
- nsMargin bp;
- GetXULBorderAndPadding(bp);
- result = prefSize.ISize(wm) - LogicalMargin(wm, bp).IStartEnd(wm);
- return result;
- }
- nscoord
- nsLeafBoxFrame::GetIntrinsicISize()
- {
- // No intrinsic width
- return 0;
- }
- LogicalSize
- nsLeafBoxFrame::ComputeAutoSize(nsRenderingContext* aRenderingContext,
- WritingMode aWM,
- const LogicalSize& aCBSize,
- nscoord aAvailableISize,
- const LogicalSize& aMargin,
- const LogicalSize& aBorder,
- const LogicalSize& aPadding,
- ComputeSizeFlags aFlags)
- {
- // Important: NOT calling our direct superclass here!
- return nsFrame::ComputeAutoSize(aRenderingContext, aWM,
- aCBSize, aAvailableISize,
- aMargin, aBorder, aPadding, aFlags);
- }
- void
- nsLeafBoxFrame::Reflow(nsPresContext* aPresContext,
- ReflowOutput& aDesiredSize,
- const ReflowInput& aReflowInput,
- nsReflowStatus& aStatus)
- {
- // This is mostly a copy of nsBoxFrame::Reflow().
- // We aren't able to share an implementation because of the frame
- // class hierarchy. If you make changes here, please keep
- // nsBoxFrame::Reflow in sync.
- MarkInReflow();
- DO_GLOBAL_REFLOW_COUNT("nsLeafBoxFrame");
- DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
- NS_ASSERTION(aReflowInput.ComputedWidth() >=0 &&
- aReflowInput.ComputedHeight() >= 0, "Computed Size < 0");
- #ifdef DO_NOISY_REFLOW
- printf("\n-------------Starting LeafBoxFrame Reflow ----------------------------\n");
- printf("%p ** nsLBF::Reflow %d R: ", this, myCounter++);
- switch (aReflowInput.reason) {
- case eReflowReason_Initial:
- printf("Ini");break;
- case eReflowReason_Incremental:
- printf("Inc");break;
- case eReflowReason_Resize:
- printf("Rsz");break;
- case eReflowReason_StyleChange:
- printf("Sty");break;
- case eReflowReason_Dirty:
- printf("Drt ");
- break;
- default:printf("<unknown>%d", aReflowInput.reason);break;
- }
-
- printSize("AW", aReflowInput.AvailableWidth());
- printSize("AH", aReflowInput.AvailableHeight());
- printSize("CW", aReflowInput.ComputedWidth());
- printSize("CH", aReflowInput.ComputedHeight());
- printf(" *\n");
- #endif
- aStatus = NS_FRAME_COMPLETE;
- // create the layout state
- nsBoxLayoutState state(aPresContext, aReflowInput.mRenderingContext);
- nsSize computedSize(aReflowInput.ComputedWidth(),aReflowInput.ComputedHeight());
- nsMargin m;
- m = aReflowInput.ComputedPhysicalBorderPadding();
- //GetXULBorderAndPadding(m);
- // this happens sometimes. So lets handle it gracefully.
- if (aReflowInput.ComputedHeight() == 0) {
- nsSize minSize = GetXULMinSize(state);
- computedSize.height = minSize.height - m.top - m.bottom;
- }
- nsSize prefSize(0,0);
- // if we are told to layout intrinic then get our preferred size.
- if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) {
- prefSize = GetXULPrefSize(state);
- nsSize minSize = GetXULMinSize(state);
- nsSize maxSize = GetXULMaxSize(state);
- prefSize = BoundsCheck(minSize, prefSize, maxSize);
- }
- // get our desiredSize
- if (aReflowInput.ComputedWidth() == NS_INTRINSICSIZE) {
- computedSize.width = prefSize.width;
- } else {
- computedSize.width += m.left + m.right;
- }
- if (aReflowInput.ComputedHeight() == NS_INTRINSICSIZE) {
- computedSize.height = prefSize.height;
- } else {
- computedSize.height += m.top + m.bottom;
- }
- // handle reflow state min and max sizes
- // XXXbz the width handling here seems to be wrong, since
- // mComputedMin/MaxWidth is a content-box size, whole
- // computedSize.width is a border-box size...
- if (computedSize.width > aReflowInput.ComputedMaxWidth())
- computedSize.width = aReflowInput.ComputedMaxWidth();
- if (computedSize.width < aReflowInput.ComputedMinWidth())
- computedSize.width = aReflowInput.ComputedMinWidth();
- // Now adjust computedSize.height for our min and max computed
- // height. The only problem is that those are content-box sizes,
- // while computedSize.height is a border-box size. So subtract off
- // m.TopBottom() before adjusting, then readd it.
- computedSize.height = std::max(0, computedSize.height - m.TopBottom());
- computedSize.height = NS_CSS_MINMAX(computedSize.height,
- aReflowInput.ComputedMinHeight(),
- aReflowInput.ComputedMaxHeight());
- computedSize.height += m.TopBottom();
- nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);
- SetXULBounds(state, r);
-
- // layout our children
- XULLayout(state);
-
- // ok our child could have gotten bigger. So lets get its bounds
- aDesiredSize.Width() = mRect.width;
- aDesiredSize.Height() = mRect.height;
- aDesiredSize.SetBlockStartAscent(GetXULBoxAscent(state));
- // the overflow rect is set in SetXULBounds() above
- aDesiredSize.mOverflowAreas = GetOverflowAreas();
- #ifdef DO_NOISY_REFLOW
- {
- printf("%p ** nsLBF(done) W:%d H:%d ", this, aDesiredSize.Width(), aDesiredSize.Height());
- if (maxElementWidth) {
- printf("MW:%d\n", *maxElementWidth);
- } else {
- printf("MW:?\n");
- }
- }
- #endif
- }
- #ifdef DEBUG_FRAME_DUMP
- nsresult
- nsLeafBoxFrame::GetFrameName(nsAString& aResult) const
- {
- return MakeFrameName(NS_LITERAL_STRING("LeafBox"), aResult);
- }
- #endif
- nsIAtom*
- nsLeafBoxFrame::GetType() const
- {
- return nsGkAtoms::leafBoxFrame;
- }
- nsresult
- nsLeafBoxFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
- {
- MarkIntrinsicISizesDirty();
- return nsLeafFrame::CharacterDataChanged(aInfo);
- }
- /* virtual */ nsSize
- nsLeafBoxFrame::GetXULPrefSize(nsBoxLayoutState& aState)
- {
- return nsBox::GetXULPrefSize(aState);
- }
- /* virtual */ nsSize
- nsLeafBoxFrame::GetXULMinSize(nsBoxLayoutState& aState)
- {
- return nsBox::GetXULMinSize(aState);
- }
- /* virtual */ nsSize
- nsLeafBoxFrame::GetXULMaxSize(nsBoxLayoutState& aState)
- {
- return nsBox::GetXULMaxSize(aState);
- }
- /* virtual */ nscoord
- nsLeafBoxFrame::GetXULFlex()
- {
- return nsBox::GetXULFlex();
- }
- /* virtual */ nscoord
- nsLeafBoxFrame::GetXULBoxAscent(nsBoxLayoutState& aState)
- {
- return nsBox::GetXULBoxAscent(aState);
- }
- /* virtual */ void
- nsLeafBoxFrame::MarkIntrinsicISizesDirty()
- {
- // Don't call base class method, since everything it does is within an
- // IsXULBoxWrapped check.
- }
- NS_IMETHODIMP
- nsLeafBoxFrame::DoXULLayout(nsBoxLayoutState& aState)
- {
- return nsBox::DoXULLayout(aState);
- }
|