1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 // Netscape Communications
10 // See documentation in associated header file
13 #include "nsLeafBoxFrame.h"
14 #include "nsBoxFrame.h"
16 #include "nsGkAtoms.h"
17 #include "nsPresContext.h"
18 #include "nsStyleContext.h"
19 #include "nsIContent.h"
20 #include "nsNameSpaceManager.h"
21 #include "nsBoxLayoutState.h"
22 #include "nsWidgetsCID.h"
23 #include "nsViewManager.h"
24 #include "nsContainerFrame.h"
25 #include "nsDisplayList.h"
28 using namespace mozilla
;
33 // Creates a new Toolbar frame and returns it
36 NS_NewLeafBoxFrame (nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
38 return new (aPresShell
) nsLeafBoxFrame(aContext
);
41 NS_IMPL_FRAMEARENA_HELPERS(nsLeafBoxFrame
)
43 nsLeafBoxFrame::nsLeafBoxFrame(nsStyleContext
* aContext
)
44 : nsLeafFrame(aContext
)
50 nsLeafBoxFrame::GetBoxName(nsAutoString
& aName
)
58 * Initialize us. This is a good time to get the alignment of the box
61 nsLeafBoxFrame::Init(nsIContent
* aContent
,
62 nsContainerFrame
* aParent
,
63 nsIFrame
* aPrevInFlow
)
65 nsLeafFrame::Init(aContent
, aParent
, aPrevInFlow
);
67 if (GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER
) {
68 AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT
);
75 nsLeafBoxFrame::AttributeChanged(int32_t aNameSpaceID
,
79 nsresult rv
= nsLeafFrame::AttributeChanged(aNameSpaceID
, aAttribute
,
82 if (aAttribute
== nsGkAtoms::mousethrough
)
88 void nsLeafBoxFrame::UpdateMouseThrough()
91 static nsIContent::AttrValuesArray strings
[] =
92 {&nsGkAtoms::never
, &nsGkAtoms::always
, nullptr};
93 switch (mContent
->FindAttrValueIn(kNameSpaceID_None
,
94 nsGkAtoms::mousethrough
,
95 strings
, eCaseMatters
)) {
96 case 0: AddStateBits(NS_FRAME_MOUSE_THROUGH_NEVER
); break;
97 case 1: AddStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS
); break;
99 RemoveStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS
);
100 RemoveStateBits(NS_FRAME_MOUSE_THROUGH_NEVER
);
108 nsLeafBoxFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
109 const nsRect
& aDirtyRect
,
110 const nsDisplayListSet
& aLists
)
112 // REVIEW: GetFrameForPoint used to not report events for the background
113 // layer, whereas this code will put an event receiver for this frame in the
114 // BlockBorderBackground() list. But I don't see any need to preserve
115 // that anomalous behaviour. The important thing I'm preserving is that
116 // leaf boxes continue to receive events in the foreground layer.
117 DisplayBorderBackgroundOutline(aBuilder
, aLists
);
119 if (!aBuilder
->IsForEventDelivery() || !IsVisibleForPainting(aBuilder
))
122 aLists
.Content()->AppendNewToTop(new (aBuilder
)
123 nsDisplayEventReceiver(aBuilder
, this));
126 /* virtual */ nscoord
127 nsLeafBoxFrame::GetMinISize(nsRenderingContext
*aRenderingContext
)
130 DISPLAY_MIN_WIDTH(this, result
);
131 nsBoxLayoutState
state(PresContext(), aRenderingContext
);
132 nsSize minSize
= GetMinSize(state
);
134 // GetMinSize returns border-box width, and we want to return content
135 // width. Since Reflow uses the reflow state's border and padding, we
136 // actually just want to subtract what GetMinSize added, which is the
137 // result of GetBorderAndPadding.
139 GetBorderAndPadding(bp
);
141 result
= minSize
.width
- bp
.LeftRight();
146 /* virtual */ nscoord
147 nsLeafBoxFrame::GetPrefISize(nsRenderingContext
*aRenderingContext
)
150 DISPLAY_PREF_WIDTH(this, result
);
151 nsBoxLayoutState
state(PresContext(), aRenderingContext
);
152 nsSize prefSize
= GetPrefSize(state
);
154 // GetPrefSize returns border-box width, and we want to return content
155 // width. Since Reflow uses the reflow state's border and padding, we
156 // actually just want to subtract what GetPrefSize added, which is the
157 // result of GetBorderAndPadding.
159 GetBorderAndPadding(bp
);
161 result
= prefSize
.width
- bp
.LeftRight();
167 nsLeafBoxFrame::GetIntrinsicISize()
169 // No intrinsic width
174 nsLeafBoxFrame::ComputeAutoSize(nsRenderingContext
*aRenderingContext
,
176 const LogicalSize
& aCBSize
,
177 nscoord aAvailableISize
,
178 const LogicalSize
& aMargin
,
179 const LogicalSize
& aBorder
,
180 const LogicalSize
& aPadding
,
183 // Important: NOT calling our direct superclass here!
184 return nsFrame::ComputeAutoSize(aRenderingContext
, aWM
,
185 aCBSize
, aAvailableISize
,
186 aMargin
, aBorder
, aPadding
, aShrinkWrap
);
190 nsLeafBoxFrame::Reflow(nsPresContext
* aPresContext
,
191 nsHTMLReflowMetrics
& aDesiredSize
,
192 const nsHTMLReflowState
& aReflowState
,
193 nsReflowStatus
& aStatus
)
195 // This is mostly a copy of nsBoxFrame::Reflow().
196 // We aren't able to share an implementation because of the frame
197 // class hierarchy. If you make changes here, please keep
198 // nsBoxFrame::Reflow in sync.
200 DO_GLOBAL_REFLOW_COUNT("nsLeafBoxFrame");
201 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
203 NS_ASSERTION(aReflowState
.ComputedWidth() >=0 &&
204 aReflowState
.ComputedHeight() >= 0, "Computed Size < 0");
206 #ifdef DO_NOISY_REFLOW
207 printf("\n-------------Starting LeafBoxFrame Reflow ----------------------------\n");
208 printf("%p ** nsLBF::Reflow %d R: ", this, myCounter
++);
209 switch (aReflowState
.reason
) {
210 case eReflowReason_Initial
:
212 case eReflowReason_Incremental
:
214 case eReflowReason_Resize
:
216 case eReflowReason_StyleChange
:
218 case eReflowReason_Dirty
:
221 default:printf("<unknown>%d", aReflowState
.reason
);break;
224 printSize("AW", aReflowState
.AvailableWidth());
225 printSize("AH", aReflowState
.AvailableHeight());
226 printSize("CW", aReflowState
.ComputedWidth());
227 printSize("CH", aReflowState
.ComputedHeight());
233 aStatus
= NS_FRAME_COMPLETE
;
235 // create the layout state
236 nsBoxLayoutState
state(aPresContext
, aReflowState
.rendContext
);
238 nsSize
computedSize(aReflowState
.ComputedWidth(),aReflowState
.ComputedHeight());
241 m
= aReflowState
.ComputedPhysicalBorderPadding();
243 //GetBorderAndPadding(m);
245 // this happens sometimes. So lets handle it gracefully.
246 if (aReflowState
.ComputedHeight() == 0) {
247 nsSize minSize
= GetMinSize(state
);
248 computedSize
.height
= minSize
.height
- m
.top
- m
.bottom
;
251 nsSize
prefSize(0,0);
253 // if we are told to layout intrinic then get our preferred size.
254 if (computedSize
.width
== NS_INTRINSICSIZE
|| computedSize
.height
== NS_INTRINSICSIZE
) {
255 prefSize
= GetPrefSize(state
);
256 nsSize minSize
= GetMinSize(state
);
257 nsSize maxSize
= GetMaxSize(state
);
258 prefSize
= BoundsCheck(minSize
, prefSize
, maxSize
);
261 // get our desiredSize
262 if (aReflowState
.ComputedWidth() == NS_INTRINSICSIZE
) {
263 computedSize
.width
= prefSize
.width
;
265 computedSize
.width
+= m
.left
+ m
.right
;
268 if (aReflowState
.ComputedHeight() == NS_INTRINSICSIZE
) {
269 computedSize
.height
= prefSize
.height
;
271 computedSize
.height
+= m
.top
+ m
.bottom
;
274 // handle reflow state min and max sizes
275 // XXXbz the width handling here seems to be wrong, since
276 // mComputedMin/MaxWidth is a content-box size, whole
277 // computedSize.width is a border-box size...
278 if (computedSize
.width
> aReflowState
.ComputedMaxWidth())
279 computedSize
.width
= aReflowState
.ComputedMaxWidth();
281 if (computedSize
.width
< aReflowState
.ComputedMinWidth())
282 computedSize
.width
= aReflowState
.ComputedMinWidth();
284 // Now adjust computedSize.height for our min and max computed
285 // height. The only problem is that those are content-box sizes,
286 // while computedSize.height is a border-box size. So subtract off
287 // m.TopBottom() before adjusting, then readd it.
288 computedSize
.height
= std::max(0, computedSize
.height
- m
.TopBottom());
289 computedSize
.height
= NS_CSS_MINMAX(computedSize
.height
,
290 aReflowState
.ComputedMinHeight(),
291 aReflowState
.ComputedMaxHeight());
292 computedSize
.height
+= m
.TopBottom();
294 nsRect
r(mRect
.x
, mRect
.y
, computedSize
.width
, computedSize
.height
);
298 // layout our children
301 // ok our child could have gotten bigger. So lets get its bounds
302 aDesiredSize
.Width() = mRect
.width
;
303 aDesiredSize
.Height() = mRect
.height
;
304 aDesiredSize
.SetBlockStartAscent(GetBoxAscent(state
));
306 // the overflow rect is set in SetBounds() above
307 aDesiredSize
.mOverflowAreas
= GetOverflowAreas();
309 #ifdef DO_NOISY_REFLOW
311 printf("%p ** nsLBF(done) W:%d H:%d ", this, aDesiredSize
.Width(), aDesiredSize
.Height());
313 if (maxElementWidth
) {
314 printf("MW:%d\n", *maxElementWidth
);
323 #ifdef DEBUG_FRAME_DUMP
325 nsLeafBoxFrame::GetFrameName(nsAString
& aResult
) const
327 return MakeFrameName(NS_LITERAL_STRING("LeafBox"), aResult
);
332 nsLeafBoxFrame::GetType() const
334 return nsGkAtoms::leafBoxFrame
;
338 nsLeafBoxFrame::CharacterDataChanged(CharacterDataChangeInfo
* aInfo
)
340 MarkIntrinsicISizesDirty();
341 return nsLeafFrame::CharacterDataChanged(aInfo
);
345 nsLeafBoxFrame::GetPrefSize(nsBoxLayoutState
& aState
)
347 return nsBox::GetPrefSize(aState
);
351 nsLeafBoxFrame::GetMinSize(nsBoxLayoutState
& aState
)
353 return nsBox::GetMinSize(aState
);
357 nsLeafBoxFrame::GetMaxSize(nsBoxLayoutState
& aState
)
359 return nsBox::GetMaxSize(aState
);
362 /* virtual */ nscoord
363 nsLeafBoxFrame::GetFlex(nsBoxLayoutState
& aState
)
365 return nsBox::GetFlex(aState
);
368 /* virtual */ nscoord
369 nsLeafBoxFrame::GetBoxAscent(nsBoxLayoutState
& aState
)
371 return nsBox::GetBoxAscent(aState
);
375 nsLeafBoxFrame::MarkIntrinsicISizesDirty()
377 // Don't call base class method, since everything it does is within an
378 // IsBoxWrapped check.
382 nsLeafBoxFrame::DoLayout(nsBoxLayoutState
& aState
)
384 return nsBox::DoLayout(aState
);