1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef nsSprocketLayout_h___
8 #define nsSprocketLayout_h___
9 
10 #include "mozilla/Attributes.h"
11 #include "nsBoxLayout.h"
12 #include "nsCOMPtr.h"
13 #include "nsIFrame.h"
14 
15 class nsBoxSize {
16  public:
17   nsBoxSize();
18 
19   nscoord pref;
20   nscoord min;
21   nscoord max;
22   nscoord flex;
23   nscoord left;
24   nscoord right;
25   bool collapsed;
26   bool bogus;
27 
28   nsBoxSize* next;
29 
30   void* operator new(size_t sz, nsBoxLayoutState& aState) noexcept(true);
31   void operator delete(void* aPtr, size_t sz);
32 };
33 
34 class nsComputedBoxSize {
35  public:
36   nsComputedBoxSize();
37 
38   nscoord size;
39   bool valid;
40   bool resized;
41   nsComputedBoxSize* next;
42 
43   void* operator new(size_t sz, nsBoxLayoutState& aState) noexcept(true);
44   void operator delete(void* aPtr, size_t sz);
45 };
46 
47 #define GET_WIDTH(size, isHorizontal) (isHorizontal ? size.width : size.height)
48 #define GET_HEIGHT(size, isHorizontal) (isHorizontal ? size.height : size.width)
49 #define GET_X(size, isHorizontal) (isHorizontal ? size.x : size.y)
50 #define GET_Y(size, isHorizontal) (isHorizontal ? size.y : size.x)
51 #define GET_COORD(aX, aY, isHorizontal) (isHorizontal ? aX : aY)
52 
53 #define SET_WIDTH(size, coord, isHorizontal) \
54   if (isHorizontal) {                        \
55     (size).width = (coord);                  \
56   } else {                                   \
57     (size).height = (coord);                 \
58   }
59 #define SET_HEIGHT(size, coord, isHorizontal) \
60   if (isHorizontal) {                         \
61     (size).height = (coord);                  \
62   } else {                                    \
63     (size).width = (coord);                   \
64   }
65 #define SET_X(size, coord, isHorizontal) \
66   if (isHorizontal) {                    \
67     (size).x = (coord);                  \
68   } else {                               \
69     (size).y = (coord);                  \
70   }
71 #define SET_Y(size, coord, isHorizontal) \
72   if (isHorizontal) {                    \
73     (size).y = (coord);                  \
74   } else {                               \
75     (size).x = (coord);                  \
76   }
77 
78 #define SET_COORD(aX, aY, coord, isHorizontal) \
79   if (isHorizontal) {                          \
80     aX = (coord);                              \
81   } else {                                     \
82     aY = (coord);                              \
83   }
84 
85 nsresult NS_NewSprocketLayout(nsCOMPtr<nsBoxLayout>& aNewLayout);
86 
87 class nsSprocketLayout : public nsBoxLayout {
88  public:
89   friend nsresult NS_NewSprocketLayout(nsCOMPtr<nsBoxLayout>& aNewLayout);
90   static void Shutdown();
91 
92   NS_IMETHOD XULLayout(nsIFrame* aBox, nsBoxLayoutState& aState) override;
93 
94   virtual nsSize GetXULPrefSize(nsIFrame* aBox,
95                                 nsBoxLayoutState& aBoxLayoutState) override;
96   virtual nsSize GetXULMinSize(nsIFrame* aBox,
97                                nsBoxLayoutState& aBoxLayoutState) override;
98   virtual nsSize GetXULMaxSize(nsIFrame* aBox,
99                                nsBoxLayoutState& aBoxLayoutState) override;
100   virtual nscoord GetAscent(nsIFrame* aBox,
101                             nsBoxLayoutState& aBoxLayoutState) override;
102 
103   nsSprocketLayout();
104 
105   static bool IsXULHorizontal(nsIFrame* aBox);
106 
107   static void SetLargestSize(nsSize& aSize1, const nsSize& aSize2,
108                              bool aIsHorizontal);
109   static void SetSmallestSize(nsSize& aSize1, const nsSize& aSize2,
110                               bool aIsHorizontal);
111 
112   static void AddLargestSize(nsSize& aSize, const nsSize& aSizeToAdd,
113                              bool aIsHorizontal);
114   static void AddSmallestSize(nsSize& aSize, const nsSize& aSizeToAdd,
115                               bool aIsHorizontal);
116   static void AddCoord(nscoord& aCoord, nscoord aCoordToAdd);
117 
118  protected:
119   void ComputeChildsNextPosition(nsIFrame* aBox, const nscoord& aCurX,
120                                  const nscoord& aCurY, nscoord& aNextX,
121                                  nscoord& aNextY, const nsRect& aChildSize);
122 
123   void ChildResized(nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChild,
124                     nsBoxSize* aChildBoxSize,
125                     nsComputedBoxSize* aChildComputedBoxSize,
126                     nsBoxSize* aBoxSizes, nsComputedBoxSize* aComputedBoxSizes,
127                     const nsRect& aChildLayoutRect, nsRect& aChildActualRect,
128                     nsRect& aContainingRect, int32_t aFlexes, bool& aFinished);
129 
130   void AlignChildren(nsIFrame* aBox, nsBoxLayoutState& aState);
131 
132   virtual void ComputeChildSizes(nsIFrame* aBox, nsBoxLayoutState& aState,
133                                  nscoord& aGivenSize, nsBoxSize* aBoxSizes,
134                                  nsComputedBoxSize*& aComputedBoxSizes);
135 
136   virtual void PopulateBoxSizes(nsIFrame* aBox,
137                                 nsBoxLayoutState& aBoxLayoutState,
138                                 nsBoxSize*& aBoxSizes, nscoord& aMinSize,
139                                 nscoord& aMaxSize, int32_t& aFlexes);
140 
141   virtual void InvalidateComputedSizes(nsComputedBoxSize* aComputedBoxSizes);
142 
143   virtual bool GetDefaultFlex(int32_t& aFlex);
144 
145   virtual void GetFrameState(nsIFrame* aBox, nsFrameState& aState);
146 
147  private:
148   // because the sprocket layout manager has no instance variables. We
149   // can make a static one and reuse it everywhere.
150   static nsBoxLayout* gInstance;
151 };
152 
153 #endif
154