1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : //
39 : // Eric Vaughan
40 : // Netscape Communications
41 : //
42 : // See documentation in associated header file
43 : //
44 :
45 : #include "nsGridRowLayout.h"
46 : #include "nsBoxLayoutState.h"
47 : #include "nsIScrollableFrame.h"
48 : #include "nsBox.h"
49 : #include "nsStackLayout.h"
50 : #include "nsGrid.h"
51 :
52 0 : nsGridRowLayout::nsGridRowLayout():nsSprocketLayout()
53 : {
54 0 : }
55 :
56 : void
57 0 : nsGridRowLayout::ChildrenInserted(nsIBox* aBox, nsBoxLayoutState& aState,
58 : nsIBox* aPrevBox,
59 : const nsFrameList::Slice& aNewChildren)
60 : {
61 0 : ChildAddedOrRemoved(aBox, aState);
62 0 : }
63 :
64 : void
65 0 : nsGridRowLayout::ChildrenAppended(nsIBox* aBox, nsBoxLayoutState& aState,
66 : const nsFrameList::Slice& aNewChildren)
67 : {
68 0 : ChildAddedOrRemoved(aBox, aState);
69 0 : }
70 :
71 : void
72 0 : nsGridRowLayout::ChildrenRemoved(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList)
73 : {
74 0 : ChildAddedOrRemoved(aBox, aState);
75 0 : }
76 :
77 : void
78 0 : nsGridRowLayout::ChildrenSet(nsIBox* aBox, nsBoxLayoutState& aState, nsIBox* aChildList)
79 : {
80 0 : ChildAddedOrRemoved(aBox, aState);
81 0 : }
82 :
83 : nsIGridPart*
84 0 : nsGridRowLayout::GetParentGridPart(nsIBox* aBox, nsIBox** aParentBox)
85 : {
86 : // go up and find our parent gridRow. Skip and non gridRow
87 : // parents.
88 0 : *aParentBox = nsnull;
89 :
90 : // walk up through any scrollboxes
91 0 : aBox = nsGrid::GetScrollBox(aBox);
92 :
93 : // get the parent
94 0 : if (aBox)
95 0 : aBox = aBox->GetParentBox();
96 :
97 0 : if (aBox)
98 : {
99 0 : nsIGridPart* parentGridRow = nsGrid::GetPartFromBox(aBox);
100 0 : if (parentGridRow && parentGridRow->CanContain(this)) {
101 0 : *aParentBox = aBox;
102 0 : return parentGridRow;
103 : }
104 : }
105 :
106 0 : return nsnull;
107 : }
108 :
109 :
110 : nsGrid*
111 0 : nsGridRowLayout::GetGrid(nsIBox* aBox, PRInt32* aIndex, nsGridRowLayout* aRequestor)
112 : {
113 :
114 0 : if (aRequestor == nsnull)
115 : {
116 : nsIBox* parentBox; // nsIBox is implemented by nsIFrame and is not refcounted.
117 0 : nsIGridPart* parent = GetParentGridPart(aBox, &parentBox);
118 0 : if (parent)
119 0 : return parent->GetGrid(parentBox, aIndex, this);
120 0 : return nsnull;
121 : }
122 :
123 0 : PRInt32 index = -1;
124 0 : nsIBox* child = aBox->GetChildBox();
125 0 : PRInt32 count = 0;
126 0 : while(child)
127 : {
128 : // if there is a scrollframe walk inside it to its child
129 0 : nsIBox* childBox = nsGrid::GetScrolledBox(child);
130 :
131 0 : nsBoxLayout* layout = childBox->GetLayoutManager();
132 0 : nsIGridPart* gridRow = nsGrid::GetPartFromBox(childBox);
133 0 : if (gridRow)
134 : {
135 0 : if (layout == aRequestor) {
136 0 : index = count;
137 0 : break;
138 : }
139 0 : count += gridRow->GetRowCount();
140 : } else
141 0 : count++;
142 :
143 0 : child = child->GetNextBox();
144 : }
145 :
146 : // if we didn't find ourselves then the tree isn't properly formed yet
147 : // this could happen during initial construction so lets just
148 : // fail.
149 0 : if (index == -1) {
150 0 : *aIndex = -1;
151 0 : return nsnull;
152 : }
153 :
154 0 : (*aIndex) += index;
155 :
156 : nsIBox* parentBox; // nsIBox is implemented by nsIFrame and is not refcounted.
157 0 : nsIGridPart* parent = GetParentGridPart(aBox, &parentBox);
158 0 : if (parent)
159 0 : return parent->GetGrid(parentBox, aIndex, this);
160 :
161 0 : return nsnull;
162 : }
163 :
164 : nsMargin
165 0 : nsGridRowLayout::GetTotalMargin(nsIBox* aBox, bool aIsHorizontal)
166 : {
167 : // get our parents margin
168 0 : nsMargin margin(0,0,0,0);
169 0 : nsIBox* parent = nsnull;
170 0 : nsIGridPart* part = GetParentGridPart(aBox, &parent);
171 0 : if (part && parent) {
172 : // if we are the first or last child walk upward and add margins.
173 :
174 : // make sure we check for a scrollbox
175 0 : aBox = nsGrid::GetScrollBox(aBox);
176 :
177 : // see if we have a next to see if we are last
178 0 : nsIBox* next = aBox->GetNextBox();
179 :
180 : // get the parent first child to see if we are first
181 0 : nsIBox* child = parent->GetChildBox();
182 :
183 0 : margin = part->GetTotalMargin(parent, aIsHorizontal);
184 :
185 : // if first or last
186 0 : if (child == aBox || next == nsnull) {
187 :
188 : // if it's not the first child remove the top margin
189 : // we don't need it.
190 0 : if (child != aBox)
191 : {
192 0 : if (aIsHorizontal)
193 0 : margin.top = 0;
194 : else
195 0 : margin.left = 0;
196 : }
197 :
198 : // if it's not the last child remove the bottom margin
199 : // we don't need it.
200 0 : if (next != nsnull)
201 : {
202 0 : if (aIsHorizontal)
203 0 : margin.bottom = 0;
204 : else
205 0 : margin.right = 0;
206 : }
207 :
208 : }
209 : }
210 :
211 : // add ours to it.
212 0 : nsMargin ourMargin;
213 0 : aBox->GetMargin(ourMargin);
214 0 : margin += ourMargin;
215 :
216 : return margin;
217 : }
218 :
219 0 : NS_IMPL_ADDREF_INHERITED(nsGridRowLayout, nsBoxLayout)
220 0 : NS_IMPL_RELEASE_INHERITED(nsGridRowLayout, nsBoxLayout)
221 :
222 0 : NS_INTERFACE_MAP_BEGIN(nsGridRowLayout)
223 0 : NS_INTERFACE_MAP_ENTRY(nsIGridPart)
224 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGridPart)
225 0 : NS_INTERFACE_MAP_END_INHERITING(nsBoxLayout)
|