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 // Eric Vaughan
8 // Netscape Communications
9 //
10 // See documentation in associated header file
11 //
12
13 #include "nsGridRowLayout.h"
14 #include "nsBoxLayoutState.h"
15 #include "nsIScrollableFrame.h"
16 #include "nsBox.h"
17 #include "nsStackLayout.h"
18 #include "nsGrid.h"
19
nsGridRowLayout()20 nsGridRowLayout::nsGridRowLayout():nsSprocketLayout()
21 {
22 }
23
~nsGridRowLayout()24 nsGridRowLayout::~nsGridRowLayout()
25 {
26 }
27
28 void
ChildrenInserted(nsIFrame * aBox,nsBoxLayoutState & aState,nsIFrame * aPrevBox,const nsFrameList::Slice & aNewChildren)29 nsGridRowLayout::ChildrenInserted(nsIFrame* aBox, nsBoxLayoutState& aState,
30 nsIFrame* aPrevBox,
31 const nsFrameList::Slice& aNewChildren)
32 {
33 ChildAddedOrRemoved(aBox, aState);
34 }
35
36 void
ChildrenAppended(nsIFrame * aBox,nsBoxLayoutState & aState,const nsFrameList::Slice & aNewChildren)37 nsGridRowLayout::ChildrenAppended(nsIFrame* aBox, nsBoxLayoutState& aState,
38 const nsFrameList::Slice& aNewChildren)
39 {
40 ChildAddedOrRemoved(aBox, aState);
41 }
42
43 void
ChildrenRemoved(nsIFrame * aBox,nsBoxLayoutState & aState,nsIFrame * aChildList)44 nsGridRowLayout::ChildrenRemoved(nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChildList)
45 {
46 ChildAddedOrRemoved(aBox, aState);
47 }
48
49 void
ChildrenSet(nsIFrame * aBox,nsBoxLayoutState & aState,nsIFrame * aChildList)50 nsGridRowLayout::ChildrenSet(nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChildList)
51 {
52 ChildAddedOrRemoved(aBox, aState);
53 }
54
55 nsIGridPart*
GetParentGridPart(nsIFrame * aBox,nsIFrame ** aParentBox)56 nsGridRowLayout::GetParentGridPart(nsIFrame* aBox, nsIFrame** aParentBox)
57 {
58 // go up and find our parent gridRow. Skip and non gridRow
59 // parents.
60 *aParentBox = nullptr;
61
62 // walk up through any scrollboxes
63 aBox = nsGrid::GetScrollBox(aBox);
64
65 // get the parent
66 if (aBox)
67 aBox = nsBox::GetParentXULBox(aBox);
68
69 if (aBox)
70 {
71 nsIGridPart* parentGridRow = nsGrid::GetPartFromBox(aBox);
72 if (parentGridRow && parentGridRow->CanContain(this)) {
73 *aParentBox = aBox;
74 return parentGridRow;
75 }
76 }
77
78 return nullptr;
79 }
80
81
82 nsGrid*
GetGrid(nsIFrame * aBox,int32_t * aIndex,nsGridRowLayout * aRequestor)83 nsGridRowLayout::GetGrid(nsIFrame* aBox, int32_t* aIndex, nsGridRowLayout* aRequestor)
84 {
85
86 if (aRequestor == nullptr)
87 {
88 nsIFrame* parentBox; // nsIFrame is implemented by nsIFrame and is not refcounted.
89 nsIGridPart* parent = GetParentGridPart(aBox, &parentBox);
90 if (parent)
91 return parent->GetGrid(parentBox, aIndex, this);
92 return nullptr;
93 }
94
95 int32_t index = -1;
96 nsIFrame* child = nsBox::GetChildXULBox(aBox);
97 int32_t count = 0;
98 while(child)
99 {
100 // if there is a scrollframe walk inside it to its child
101 nsIFrame* childBox = nsGrid::GetScrolledBox(child);
102
103 nsBoxLayout* layout = childBox->GetXULLayoutManager();
104 nsIGridPart* gridRow = nsGrid::GetPartFromBox(childBox);
105 if (gridRow)
106 {
107 if (layout == aRequestor) {
108 index = count;
109 break;
110 }
111 count += gridRow->GetRowCount();
112 } else
113 count++;
114
115 child = nsBox::GetNextXULBox(child);
116 }
117
118 // if we didn't find ourselves then the tree isn't properly formed yet
119 // this could happen during initial construction so lets just
120 // fail.
121 if (index == -1) {
122 *aIndex = -1;
123 return nullptr;
124 }
125
126 (*aIndex) += index;
127
128 nsIFrame* parentBox; // nsIFrame is implemented by nsIFrame and is not refcounted.
129 nsIGridPart* parent = GetParentGridPart(aBox, &parentBox);
130 if (parent)
131 return parent->GetGrid(parentBox, aIndex, this);
132
133 return nullptr;
134 }
135
136 nsMargin
GetTotalMargin(nsIFrame * aBox,bool aIsHorizontal)137 nsGridRowLayout::GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal)
138 {
139 // get our parents margin
140 nsMargin margin(0,0,0,0);
141 nsIFrame* parent = nullptr;
142 nsIGridPart* part = GetParentGridPart(aBox, &parent);
143 if (part && parent) {
144 // if we are the first or last child walk upward and add margins.
145
146 // make sure we check for a scrollbox
147 aBox = nsGrid::GetScrollBox(aBox);
148
149 // see if we have a next to see if we are last
150 nsIFrame* next = nsBox::GetNextXULBox(aBox);
151
152 // get the parent first child to see if we are first
153 nsIFrame* child = nsBox::GetChildXULBox(parent);
154
155 margin = part->GetTotalMargin(parent, aIsHorizontal);
156
157 // if first or last
158 if (child == aBox || next == nullptr) {
159
160 // if it's not the first child remove the top margin
161 // we don't need it.
162 if (child != aBox)
163 {
164 if (aIsHorizontal)
165 margin.top = 0;
166 else
167 margin.left = 0;
168 }
169
170 // if it's not the last child remove the bottom margin
171 // we don't need it.
172 if (next != nullptr)
173 {
174 if (aIsHorizontal)
175 margin.bottom = 0;
176 else
177 margin.right = 0;
178 }
179
180 }
181 }
182
183 // add ours to it.
184 nsMargin ourMargin;
185 aBox->GetXULMargin(ourMargin);
186 margin += ourMargin;
187
188 return margin;
189 }
190
191 NS_IMPL_ADDREF_INHERITED(nsGridRowLayout, nsBoxLayout)
192 NS_IMPL_RELEASE_INHERITED(nsGridRowLayout, nsBoxLayout)
193
194 NS_INTERFACE_MAP_BEGIN(nsGridRowLayout)
195 NS_INTERFACE_MAP_ENTRY(nsIGridPart)
196 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGridPart)
197 NS_INTERFACE_MAP_END_INHERITING(nsBoxLayout)
198