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 //
8 // Eric Vaughan
9 // Netscape Communications
10 //
11 // See documentation in associated header file
12 //
13 
14 #include "nsGridLayout2.h"
15 #include "nsGridRowGroupLayout.h"
16 #include "nsGridRow.h"
17 #include "nsBox.h"
18 #include "nsIScrollableFrame.h"
19 #include "nsSprocketLayout.h"
20 #include "mozilla/ReflowInput.h"
21 
NS_NewGridLayout2(nsIPresShell * aPresShell,nsBoxLayout ** aNewLayout)22 nsresult NS_NewGridLayout2(nsIPresShell* aPresShell, nsBoxLayout** aNewLayout) {
23   *aNewLayout = new nsGridLayout2(aPresShell);
24   NS_IF_ADDREF(*aNewLayout);
25 
26   return NS_OK;
27 }
28 
nsGridLayout2(nsIPresShell * aPresShell)29 nsGridLayout2::nsGridLayout2(nsIPresShell* aPresShell) : nsStackLayout() {}
30 
~nsGridLayout2()31 nsGridLayout2::~nsGridLayout2() {}
32 
33 // static
AddOffset(nsIFrame * aChild,nsSize & aSize)34 void nsGridLayout2::AddOffset(nsIFrame* aChild, nsSize& aSize) {
35   nsMargin offset;
36   GetOffset(aChild, offset);
37   aSize.width += offset.left;
38   aSize.height += offset.top;
39 }
40 
41 NS_IMETHODIMP
XULLayout(nsIFrame * aBox,nsBoxLayoutState & aBoxLayoutState)42 nsGridLayout2::XULLayout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) {
43   // XXX This should be set a better way!
44   mGrid.SetBox(aBox);
45   NS_ASSERTION(aBox->GetXULLayoutManager() == this, "setting incorrect box");
46 
47   nsresult rv = nsStackLayout::XULLayout(aBox, aBoxLayoutState);
48 #ifdef DEBUG_grid
49   mGrid.PrintCellMap();
50 #endif
51   return rv;
52 }
53 
IntrinsicISizesDirty(nsIFrame * aBox,nsBoxLayoutState & aBoxLayoutState)54 void nsGridLayout2::IntrinsicISizesDirty(nsIFrame* aBox,
55                                          nsBoxLayoutState& aBoxLayoutState) {
56   nsStackLayout::IntrinsicISizesDirty(aBox, aBoxLayoutState);
57   // XXXldb We really don't need to do all the work that NeedsRebuild
58   // does; we just need to mark intrinsic widths dirty on the
59   // (row/column)(s/-groups).
60   mGrid.NeedsRebuild(aBoxLayoutState);
61 }
62 
GetGrid(nsIFrame * aBox,int32_t * aIndex,nsGridRowLayout * aRequestor)63 nsGrid* nsGridLayout2::GetGrid(nsIFrame* aBox, int32_t* aIndex,
64                                nsGridRowLayout* aRequestor) {
65   // XXX This should be set a better way!
66   mGrid.SetBox(aBox);
67   NS_ASSERTION(aBox->GetXULLayoutManager() == this, "setting incorrect box");
68   return &mGrid;
69 }
70 
AddWidth(nsSize & aSize,nscoord aSize2,bool aIsHorizontal)71 void nsGridLayout2::AddWidth(nsSize& aSize, nscoord aSize2,
72                              bool aIsHorizontal) {
73   nscoord& size = GET_WIDTH(aSize, aIsHorizontal);
74 
75   if (size != NS_INTRINSICSIZE) {
76     if (aSize2 == NS_INTRINSICSIZE)
77       size = NS_INTRINSICSIZE;
78     else
79       size += aSize2;
80   }
81 }
82 
GetXULMinSize(nsIFrame * aBox,nsBoxLayoutState & aState)83 nsSize nsGridLayout2::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState) {
84   nsSize minSize = nsStackLayout::GetXULMinSize(aBox, aState);
85 
86   // if there are no <rows> tags that will sum up our columns,
87   // sum up our columns here.
88   nsSize total(0, 0);
89   nsIFrame* rowsBox = mGrid.GetRowsBox();
90   nsIFrame* columnsBox = mGrid.GetColumnsBox();
91   if (!rowsBox || !columnsBox) {
92     if (!rowsBox) {
93       // max height is the sum of our rows
94       int32_t rows = mGrid.GetRowCount();
95       for (int32_t i = 0; i < rows; i++) {
96         nscoord height = mGrid.GetMinRowHeight(aState, i, true);
97         AddWidth(total, height, false);  // AddHeight
98       }
99     }
100 
101     if (!columnsBox) {
102       // max height is the sum of our rows
103       int32_t columns = mGrid.GetColumnCount();
104       for (int32_t i = 0; i < columns; i++) {
105         nscoord width = mGrid.GetMinRowHeight(aState, i, false);
106         AddWidth(total, width, true);  // AddWidth
107       }
108     }
109 
110     AddMargin(aBox, total);
111     AddOffset(aBox, total);
112     AddLargestSize(minSize, total);
113   }
114 
115   return minSize;
116 }
117 
GetXULPrefSize(nsIFrame * aBox,nsBoxLayoutState & aState)118 nsSize nsGridLayout2::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState) {
119   nsSize pref = nsStackLayout::GetXULPrefSize(aBox, aState);
120 
121   // if there are no <rows> tags that will sum up our columns,
122   // sum up our columns here.
123   nsSize total(0, 0);
124   nsIFrame* rowsBox = mGrid.GetRowsBox();
125   nsIFrame* columnsBox = mGrid.GetColumnsBox();
126   if (!rowsBox || !columnsBox) {
127     if (!rowsBox) {
128       // max height is the sum of our rows
129       int32_t rows = mGrid.GetRowCount();
130       for (int32_t i = 0; i < rows; i++) {
131         nscoord height = mGrid.GetPrefRowHeight(aState, i, true);
132         AddWidth(total, height, false);  // AddHeight
133       }
134     }
135 
136     if (!columnsBox) {
137       // max height is the sum of our rows
138       int32_t columns = mGrid.GetColumnCount();
139       for (int32_t i = 0; i < columns; i++) {
140         nscoord width = mGrid.GetPrefRowHeight(aState, i, false);
141         AddWidth(total, width, true);  // AddWidth
142       }
143     }
144 
145     AddMargin(aBox, total);
146     AddOffset(aBox, total);
147     AddLargestSize(pref, total);
148   }
149 
150   return pref;
151 }
152 
GetXULMaxSize(nsIFrame * aBox,nsBoxLayoutState & aState)153 nsSize nsGridLayout2::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState) {
154   nsSize maxSize = nsStackLayout::GetXULMaxSize(aBox, aState);
155 
156   // if there are no <rows> tags that will sum up our columns,
157   // sum up our columns here.
158   nsSize total(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
159   nsIFrame* rowsBox = mGrid.GetRowsBox();
160   nsIFrame* columnsBox = mGrid.GetColumnsBox();
161   if (!rowsBox || !columnsBox) {
162     if (!rowsBox) {
163       total.height = 0;
164       // max height is the sum of our rows
165       int32_t rows = mGrid.GetRowCount();
166       for (int32_t i = 0; i < rows; i++) {
167         nscoord height = mGrid.GetMaxRowHeight(aState, i, true);
168         AddWidth(total, height, false);  // AddHeight
169       }
170     }
171 
172     if (!columnsBox) {
173       total.width = 0;
174       // max height is the sum of our rows
175       int32_t columns = mGrid.GetColumnCount();
176       for (int32_t i = 0; i < columns; i++) {
177         nscoord width = mGrid.GetMaxRowHeight(aState, i, false);
178         AddWidth(total, width, true);  // AddWidth
179       }
180     }
181 
182     AddMargin(aBox, total);
183     AddOffset(aBox, total);
184     AddSmallestSize(maxSize, total);
185   }
186 
187   return maxSize;
188 }
189 
BuildRows(nsIFrame * aBox,nsGridRow * aRows)190 int32_t nsGridLayout2::BuildRows(nsIFrame* aBox, nsGridRow* aRows) {
191   if (aBox) {
192     aRows[0].Init(aBox, true);
193     return 1;
194   }
195   return 0;
196 }
197 
GetTotalMargin(nsIFrame * aBox,bool aIsHorizontal)198 nsMargin nsGridLayout2::GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal) {
199   nsMargin margin(0, 0, 0, 0);
200   return margin;
201 }
202 
ChildrenInserted(nsIFrame * aBox,nsBoxLayoutState & aState,nsIFrame * aPrevBox,const nsFrameList::Slice & aNewChildren)203 void nsGridLayout2::ChildrenInserted(nsIFrame* aBox, nsBoxLayoutState& aState,
204                                      nsIFrame* aPrevBox,
205                                      const nsFrameList::Slice& aNewChildren) {
206   mGrid.NeedsRebuild(aState);
207 }
208 
ChildrenAppended(nsIFrame * aBox,nsBoxLayoutState & aState,const nsFrameList::Slice & aNewChildren)209 void nsGridLayout2::ChildrenAppended(nsIFrame* aBox, nsBoxLayoutState& aState,
210                                      const nsFrameList::Slice& aNewChildren) {
211   mGrid.NeedsRebuild(aState);
212 }
213 
ChildrenRemoved(nsIFrame * aBox,nsBoxLayoutState & aState,nsIFrame * aChildList)214 void nsGridLayout2::ChildrenRemoved(nsIFrame* aBox, nsBoxLayoutState& aState,
215                                     nsIFrame* aChildList) {
216   mGrid.NeedsRebuild(aState);
217 }
218 
ChildrenSet(nsIFrame * aBox,nsBoxLayoutState & aState,nsIFrame * aChildList)219 void nsGridLayout2::ChildrenSet(nsIFrame* aBox, nsBoxLayoutState& aState,
220                                 nsIFrame* aChildList) {
221   mGrid.NeedsRebuild(aState);
222 }
223 
224 NS_IMPL_ADDREF_INHERITED(nsGridLayout2, nsStackLayout)
225 NS_IMPL_RELEASE_INHERITED(nsGridLayout2, nsStackLayout)
226 
227 NS_INTERFACE_MAP_BEGIN(nsGridLayout2)
228   NS_INTERFACE_MAP_ENTRY(nsIGridPart)
229   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGridPart)
230 NS_INTERFACE_MAP_END_INHERITING(nsStackLayout)
231