Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / layout / xul / nsLeafBoxFrame.cpp
blob1c373300d03bd68135eb5b55cd8b60e17bf8caf4
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/. */
6 //
7 // Eric Vaughan
8 // Netscape Communications
9 //
10 // See documentation in associated header file
13 #include "nsLeafBoxFrame.h"
14 #include "nsBoxFrame.h"
15 #include "nsCOMPtr.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"
26 #include <algorithm>
28 using namespace mozilla;
31 // NS_NewLeafBoxFrame
33 // Creates a new Toolbar frame and returns it
35 nsIFrame*
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)
48 #ifdef DEBUG_LAYOUT
49 void
50 nsLeafBoxFrame::GetBoxName(nsAutoString& aName)
52 GetFrameName(aName);
54 #endif
57 /**
58 * Initialize us. This is a good time to get the alignment of the box
60 void
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);
71 UpdateMouseThrough();
74 nsresult
75 nsLeafBoxFrame::AttributeChanged(int32_t aNameSpaceID,
76 nsIAtom* aAttribute,
77 int32_t aModType)
79 nsresult rv = nsLeafFrame::AttributeChanged(aNameSpaceID, aAttribute,
80 aModType);
82 if (aAttribute == nsGkAtoms::mousethrough)
83 UpdateMouseThrough();
85 return rv;
88 void nsLeafBoxFrame::UpdateMouseThrough()
90 if (mContent) {
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;
98 case 2: {
99 RemoveStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS);
100 RemoveStateBits(NS_FRAME_MOUSE_THROUGH_NEVER);
101 break;
107 void
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))
120 return;
122 aLists.Content()->AppendNewToTop(new (aBuilder)
123 nsDisplayEventReceiver(aBuilder, this));
126 /* virtual */ nscoord
127 nsLeafBoxFrame::GetMinISize(nsRenderingContext *aRenderingContext)
129 nscoord result;
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.
138 nsMargin bp;
139 GetBorderAndPadding(bp);
141 result = minSize.width - bp.LeftRight();
143 return result;
146 /* virtual */ nscoord
147 nsLeafBoxFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
149 nscoord result;
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.
158 nsMargin bp;
159 GetBorderAndPadding(bp);
161 result = prefSize.width - bp.LeftRight();
163 return result;
166 nscoord
167 nsLeafBoxFrame::GetIntrinsicISize()
169 // No intrinsic width
170 return 0;
173 LogicalSize
174 nsLeafBoxFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
175 WritingMode aWM,
176 const LogicalSize& aCBSize,
177 nscoord aAvailableISize,
178 const LogicalSize& aMargin,
179 const LogicalSize& aBorder,
180 const LogicalSize& aPadding,
181 bool aShrinkWrap)
183 // Important: NOT calling our direct superclass here!
184 return nsFrame::ComputeAutoSize(aRenderingContext, aWM,
185 aCBSize, aAvailableISize,
186 aMargin, aBorder, aPadding, aShrinkWrap);
189 void
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:
211 printf("Ini");break;
212 case eReflowReason_Incremental:
213 printf("Inc");break;
214 case eReflowReason_Resize:
215 printf("Rsz");break;
216 case eReflowReason_StyleChange:
217 printf("Sty");break;
218 case eReflowReason_Dirty:
219 printf("Drt ");
220 break;
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());
229 printf(" *\n");
231 #endif
233 aStatus = NS_FRAME_COMPLETE;
235 // create the layout state
236 nsBoxLayoutState state(aPresContext, aReflowState.rendContext);
238 nsSize computedSize(aReflowState.ComputedWidth(),aReflowState.ComputedHeight());
240 nsMargin m;
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;
264 } else {
265 computedSize.width += m.left + m.right;
268 if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
269 computedSize.height = prefSize.height;
270 } else {
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);
296 SetBounds(state, r);
298 // layout our children
299 Layout(state);
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);
315 } else {
316 printf("MW:?\n");
320 #endif
323 #ifdef DEBUG_FRAME_DUMP
324 nsresult
325 nsLeafBoxFrame::GetFrameName(nsAString& aResult) const
327 return MakeFrameName(NS_LITERAL_STRING("LeafBox"), aResult);
329 #endif
331 nsIAtom*
332 nsLeafBoxFrame::GetType() const
334 return nsGkAtoms::leafBoxFrame;
337 nsresult
338 nsLeafBoxFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
340 MarkIntrinsicISizesDirty();
341 return nsLeafFrame::CharacterDataChanged(aInfo);
344 /* virtual */ nsSize
345 nsLeafBoxFrame::GetPrefSize(nsBoxLayoutState& aState)
347 return nsBox::GetPrefSize(aState);
350 /* virtual */ nsSize
351 nsLeafBoxFrame::GetMinSize(nsBoxLayoutState& aState)
353 return nsBox::GetMinSize(aState);
356 /* virtual */ nsSize
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);
374 /* virtual */ void
375 nsLeafBoxFrame::MarkIntrinsicISizesDirty()
377 // Don't call base class method, since everything it does is within an
378 // IsBoxWrapped check.
381 NS_IMETHODIMP
382 nsLeafBoxFrame::DoLayout(nsBoxLayoutState& aState)
384 return nsBox::DoLayout(aState);