1 /* -*- Mode: C++; tab-width: 2; 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/. */
5 
6 /**
7 
8   Eric D Vaughan
9   nsBoxFrame is a frame that can lay its children out either vertically or horizontally.
10   It lays them out according to a min max or preferred size.
11 
12 **/
13 
14 #ifndef nsBoxFrame_h___
15 #define nsBoxFrame_h___
16 
17 #include "mozilla/Attributes.h"
18 #include "nsCOMPtr.h"
19 #include "nsContainerFrame.h"
20 #include "nsBoxLayout.h"
21 
22 class nsBoxLayoutState;
23 
24 namespace mozilla {
25 namespace gfx {
26 class DrawTarget;
27 } // namespace gfx
28 } // namespace mozilla
29 
30 nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell,
31                          nsStyleContext* aContext,
32                          bool aIsRoot,
33                          nsBoxLayout* aLayoutManager);
34 nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell,
35                          nsStyleContext* aContext);
36 
37 class nsBoxFrame : public nsContainerFrame
38 {
39 protected:
40   typedef mozilla::gfx::DrawTarget DrawTarget;
41 
42 public:
43   NS_DECL_FRAMEARENA_HELPERS
44 #ifdef DEBUG
45   NS_DECL_QUERYFRAME_TARGET(nsBoxFrame)
46   NS_DECL_QUERYFRAME
47 #endif
48 
49   friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell,
50                                   nsStyleContext* aContext,
51                                   bool aIsRoot,
52                                   nsBoxLayout* aLayoutManager);
53   friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell,
54                                   nsStyleContext* aContext);
55 
56   // gets the rect inside our border and debug border. If you wish to paint inside a box
57   // call this method to get the rect so you don't draw on the debug border or outer border.
58 
SetXULLayoutManager(nsBoxLayout * aLayout)59   virtual void SetXULLayoutManager(nsBoxLayout* aLayout) override { mLayoutManager = aLayout; }
GetXULLayoutManager()60   virtual nsBoxLayout* GetXULLayoutManager() override { return mLayoutManager; }
61 
62   virtual nsresult XULRelayoutChildAtOrdinal(nsIFrame* aChild) override;
63 
64   virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
65   virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
66   virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
67   virtual nscoord GetXULFlex() override;
68   virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) override;
69 #ifdef DEBUG_LAYOUT
70   virtual nsresult SetXULDebug(nsBoxLayoutState& aBoxLayoutState, bool aDebug) override;
71   virtual nsresult GetXULDebug(bool& aDebug) override;
72 #endif
GetXULVAlign()73   virtual Valignment GetXULVAlign() const override { return mValign; }
GetXULHAlign()74   virtual Halignment GetXULHAlign() const override { return mHalign; }
75   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
76 
ComputesOwnOverflowArea()77   virtual bool ComputesOwnOverflowArea() override { return false; }
78 
79   // ----- child and sibling operations ---
80 
81   // ----- public methods -------
82 
83   virtual void Init(nsIContent*       aContent,
84                     nsContainerFrame* aParent,
85                     nsIFrame*         aPrevInFlow) override;
86 
87 
88   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
89                                     nsIAtom*        aAttribute,
90                                     int32_t         aModType) override;
91 
92   virtual void MarkIntrinsicISizesDirty() override;
93   virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
94   virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
95 
96   virtual void Reflow(nsPresContext*           aPresContext,
97                       ReflowOutput&     aDesiredSize,
98                       const ReflowInput& aReflowInput,
99                       nsReflowStatus&          aStatus) override;
100 
101   virtual void SetInitialChildList(ChildListID  aListID,
102                                    nsFrameList& aChildList) override;
103   virtual void AppendFrames(ChildListID     aListID,
104                             nsFrameList&    aFrameList) override;
105   virtual void InsertFrames(ChildListID     aListID,
106                             nsIFrame*       aPrevFrame,
107                             nsFrameList&    aFrameList) override;
108   virtual void RemoveFrame(ChildListID     aListID,
109                            nsIFrame*       aOldFrame) override;
110 
111   virtual nsContainerFrame* GetContentInsertionFrame() override;
112 
113   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
114 
115   virtual nsIAtom* GetType() const override;
116 
IsFrameOfType(uint32_t aFlags)117   virtual bool IsFrameOfType(uint32_t aFlags) const override
118   {
119     // record that children that are ignorable whitespace should be excluded
120     // (When content was loaded via the XUL content sink, it's already
121     // been excluded, but we need this for when the XUL namespace is used
122     // in other MIME types or when the XUL CSS display types are used with
123     // non-XUL elements.)
124 
125     // This is bogus, but it's what we've always done.
126     // (Given that we're replaced, we need to say we're a replaced element
127     // that contains a block so ReflowInput doesn't tell us to be
128     // NS_INTRINSICSIZE wide.)
129     return nsContainerFrame::IsFrameOfType(aFlags &
130       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock | eXULBox |
131         nsIFrame::eExcludesIgnorableWhitespace));
132   }
133 
134 #ifdef DEBUG_FRAME_DUMP
135   virtual nsresult GetFrameName(nsAString& aResult) const override;
136 #endif
137 
138   virtual void DidReflow(nsPresContext*           aPresContext,
139                          const ReflowInput* aReflowInput,
140                          nsDidReflowStatus        aStatus) override;
141 
142   virtual bool HonorPrintBackgroundSettings() override;
143 
144   virtual ~nsBoxFrame();
145 
146   explicit nsBoxFrame(nsStyleContext* aContext, bool aIsRoot = false, nsBoxLayout* aLayoutManager = nullptr);
147 
148   // virtual so nsStackFrame, nsButtonBoxFrame, nsSliderFrame and nsMenuFrame
149   // can override it
150   virtual void BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
151                                            const nsRect&           aDirtyRect,
152                                            const nsDisplayListSet& aLists);
153 
154   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
155                                 const nsRect&           aDirtyRect,
156                                 const nsDisplayListSet& aLists) override;
157 
158 #ifdef DEBUG_LAYOUT
159     virtual void SetDebugOnChildList(nsBoxLayoutState& aState, nsIFrame* aChild, bool aDebug);
160     nsresult DisplayDebugInfoFor(nsIFrame*  aBox,
161                                  nsPoint& aPoint);
162 #endif
163 
164   static nsresult LayoutChildAt(nsBoxLayoutState& aState, nsIFrame* aBox, const nsRect& aRect);
165 
166   /**
167    * Utility method to redirect events on descendants to this frame.
168    * Supports 'allowevents' attribute on descendant elements to allow those
169    * elements and their descendants to receive events.
170    */
171   void WrapListsInRedirector(nsDisplayListBuilder*   aBuilder,
172                              const nsDisplayListSet& aIn,
173                              const nsDisplayListSet& aOut);
174 
175   /**
176    * This defaults to true, but some box frames (nsListBoxBodyFrame for
177    * example) don't support ordinals in their children.
178    */
179   virtual bool SupportsOrdinalsInChildren();
180 
181 protected:
182 #ifdef DEBUG_LAYOUT
183     virtual void GetBoxName(nsAutoString& aName) override;
184     void PaintXULDebugBackground(nsRenderingContext& aRenderingContext,
185                                  nsPoint aPt);
186     void PaintXULDebugOverlay(DrawTarget& aRenderingContext,
187                               nsPoint aPt);
188 #endif
189 
190     virtual bool GetInitialEqualSize(bool& aEqualSize);
191     virtual void GetInitialOrientation(bool& aIsHorizontal);
192     virtual void GetInitialDirection(bool& aIsNormal);
193     virtual bool GetInitialHAlignment(Halignment& aHalign);
194     virtual bool GetInitialVAlignment(Valignment& aValign);
195     virtual bool GetInitialAutoStretch(bool& aStretch);
196 
197     virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
198 
199     nsSize mPrefSize;
200     nsSize mMinSize;
201     nsSize mMaxSize;
202     nscoord mFlex;
203     nscoord mAscent;
204 
205     nsCOMPtr<nsBoxLayout> mLayoutManager;
206 
207     // Get the point associated with this event. Returns true if a single valid
208     // point was found. Otherwise false.
209     bool GetEventPoint(mozilla::WidgetGUIEvent* aEvent, nsPoint& aPoint);
210     // Gets the event coordinates relative to the widget offset associated with
211     // this frame. Return true if a single valid point was found.
212     bool GetEventPoint(mozilla::WidgetGUIEvent* aEvent,
213                        mozilla::LayoutDeviceIntPoint& aPoint);
214 
215 protected:
216     void RegUnregAccessKey(bool aDoReg);
217 
218   void CheckBoxOrder();
219 
220 private:
221 
222 #ifdef DEBUG_LAYOUT
223     nsresult SetXULDebug(nsPresContext* aPresContext, bool aDebug);
224     bool GetInitialDebug(bool& aDebug);
225     void GetDebugPref();
226 
227     void GetDebugBorder(nsMargin& aInset);
228     void GetDebugPadding(nsMargin& aInset);
229     void GetDebugMargin(nsMargin& aInset);
230 
231     nsresult GetFrameSizeWithMargin(nsIFrame* aBox, nsSize& aSize);
232 
233     void PixelMarginToTwips(nsMargin& aMarginPixels);
234 
235     void GetValue(nsPresContext* aPresContext, const nsSize& a, const nsSize& b, char* value);
236     void GetValue(nsPresContext* aPresContext, int32_t a, int32_t b, char* value);
237     void DrawSpacer(nsPresContext* aPresContext, DrawTarget& aDrawTarget, bool aHorizontal, int32_t flex, nscoord x, nscoord y, nscoord size, nscoord spacerSize);
238     void DrawLine(DrawTarget& aDrawTarget,  bool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2);
239     void FillRect(DrawTarget& aDrawTarget,  bool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height);
240 #endif
241     virtual void UpdateMouseThrough();
242 
243     void CacheAttributes();
244 
245     // instance variables.
246     Halignment mHalign;
247     Valignment mValign;
248 
249 #ifdef DEBUG_LAYOUT
250     static bool gDebug;
251     static nsIFrame* mDebugChild;
252 #endif
253 
254 }; // class nsBoxFrame
255 
256 #endif
257 
258