summaryrefslogtreecommitdiffstats
path: root/layout/xul/grid
diff options
context:
space:
mode:
Diffstat (limited to 'layout/xul/grid')
-rw-r--r--layout/xul/grid/crashtests/306911-crash.xul4
-rw-r--r--layout/xul/grid/crashtests/306911-grid-testcases.xul99
-rw-r--r--layout/xul/grid/crashtests/306911-grid-testcases2.xul98
-rw-r--r--layout/xul/grid/crashtests/311710-1.xul22
-rw-r--r--layout/xul/grid/crashtests/312784-1.xul29
-rw-r--r--layout/xul/grid/crashtests/313173-1-inner.xul41
-rw-r--r--layout/xul/grid/crashtests/313173-1.html9
-rw-r--r--layout/xul/grid/crashtests/321066-1.xul8
-rw-r--r--layout/xul/grid/crashtests/321073-1.xul7
-rw-r--r--layout/xul/grid/crashtests/382750-1.xul5
-rw-r--r--layout/xul/grid/crashtests/400790-1.xul20
-rw-r--r--layout/xul/grid/crashtests/423802-crash.xul13
-rw-r--r--layout/xul/grid/crashtests/crashtests.list11
-rw-r--r--layout/xul/grid/examples/borderedcolumns.xul43
-rw-r--r--layout/xul/grid/examples/borderedrowscolumns.xul55
-rw-r--r--layout/xul/grid/examples/borderedrowscolumns2.xul44
-rw-r--r--layout/xul/grid/examples/borderedrowscolumns3.xul57
-rw-r--r--layout/xul/grid/examples/bordermargincolumns1.xul44
-rw-r--r--layout/xul/grid/examples/collapsetest.xul67
-rw-r--r--layout/xul/grid/examples/divcolumngrid.xul33
-rw-r--r--layout/xul/grid/examples/divrowgrid.xul36
-rw-r--r--layout/xul/grid/examples/dynamicgrid.xul370
-rw-r--r--layout/xul/grid/examples/flexgroupgrid.xul47
-rw-r--r--layout/xul/grid/examples/javascriptappend.xul42
-rw-r--r--layout/xul/grid/examples/jumpygrid.xul82
-rw-r--r--layout/xul/grid/examples/nestedrows.xul48
-rw-r--r--layout/xul/grid/examples/rowspan.xul41
-rw-r--r--layout/xul/grid/examples/scrollingcolumns.xul80
-rw-r--r--layout/xul/grid/examples/scrollingrows.xul80
-rw-r--r--layout/xul/grid/examples/splitter.xul40
-rw-r--r--layout/xul/grid/moz.build43
-rw-r--r--layout/xul/grid/nsGrid.cpp1276
-rw-r--r--layout/xul/grid/nsGrid.h132
-rw-r--r--layout/xul/grid/nsGridCell.cpp127
-rw-r--r--layout/xul/grid/nsGridCell.h53
-rw-r--r--layout/xul/grid/nsGridLayout2.cpp266
-rw-r--r--layout/xul/grid/nsGridLayout2.h78
-rw-r--r--layout/xul/grid/nsGridRow.cpp57
-rw-r--r--layout/xul/grid/nsGridRow.h57
-rw-r--r--layout/xul/grid/nsGridRowGroupFrame.cpp63
-rw-r--r--layout/xul/grid/nsGridRowGroupFrame.h49
-rw-r--r--layout/xul/grid/nsGridRowGroupLayout.cpp265
-rw-r--r--layout/xul/grid/nsGridRowGroupLayout.h51
-rw-r--r--layout/xul/grid/nsGridRowLayout.cpp197
-rw-r--r--layout/xul/grid/nsGridRowLayout.h60
-rw-r--r--layout/xul/grid/nsGridRowLeafFrame.cpp94
-rw-r--r--layout/xul/grid/nsGridRowLeafFrame.h54
-rw-r--r--layout/xul/grid/nsGridRowLeafLayout.cpp328
-rw-r--r--layout/xul/grid/nsGridRowLeafLayout.h62
-rw-r--r--layout/xul/grid/nsIGridPart.h95
-rw-r--r--layout/xul/grid/reftests/column-sizing-1-ref.xul13
-rw-r--r--layout/xul/grid/reftests/column-sizing-1.xul15
-rw-r--r--layout/xul/grid/reftests/not-full-basic-ref.xhtml27
-rw-r--r--layout/xul/grid/reftests/not-full-basic.xul45
-rw-r--r--layout/xul/grid/reftests/not-full-grid-pack-align.xul46
-rw-r--r--layout/xul/grid/reftests/not-full-row-group-align-ref.xhtml27
-rw-r--r--layout/xul/grid/reftests/not-full-row-group-align.xul46
-rw-r--r--layout/xul/grid/reftests/not-full-row-group-direction-ref.xhtml27
-rw-r--r--layout/xul/grid/reftests/not-full-row-group-direction.xul46
-rw-r--r--layout/xul/grid/reftests/not-full-row-group-pack-ref.xhtml31
-rw-r--r--layout/xul/grid/reftests/not-full-row-group-pack.xul46
-rw-r--r--layout/xul/grid/reftests/not-full-row-leaf-align.xul46
-rw-r--r--layout/xul/grid/reftests/not-full-row-leaf-direction.xul46
-rw-r--r--layout/xul/grid/reftests/not-full-row-leaf-pack-ref.xhtml27
-rw-r--r--layout/xul/grid/reftests/not-full-row-leaf-pack.xul46
-rw-r--r--layout/xul/grid/reftests/reftest-stylo.list38
-rw-r--r--layout/xul/grid/reftests/reftest.list18
-rw-r--r--layout/xul/grid/reftests/row-or-column-sizing-1.xul21
-rw-r--r--layout/xul/grid/reftests/row-or-column-sizing-2.xul21
-rw-r--r--layout/xul/grid/reftests/row-or-column-sizing-3.xul27
-rw-r--r--layout/xul/grid/reftests/row-or-column-sizing-4.xul27
-rw-r--r--layout/xul/grid/reftests/row-sizing-1-ref.xul14
-rw-r--r--layout/xul/grid/reftests/row-sizing-1.xul16
-rw-r--r--layout/xul/grid/reftests/scrollable-columns-ref.xhtml25
-rw-r--r--layout/xul/grid/reftests/scrollable-columns.xul49
-rw-r--r--layout/xul/grid/reftests/scrollable-rows-ref.xhtml25
-rw-r--r--layout/xul/grid/reftests/scrollable-rows.xul49
-rw-r--r--layout/xul/grid/reftests/sizing-2d-ref.xul12
-rw-r--r--layout/xul/grid/reftests/sizing-2d.xul26
-rw-r--r--layout/xul/grid/reftests/z-order-1-ref.xul30
-rw-r--r--layout/xul/grid/reftests/z-order-1.xul47
-rw-r--r--layout/xul/grid/reftests/z-order-2-ref.xul30
-rw-r--r--layout/xul/grid/reftests/z-order-2.xul47
83 files changed, 6038 insertions, 0 deletions
diff --git a/layout/xul/grid/crashtests/306911-crash.xul b/layout/xul/grid/crashtests/306911-crash.xul
new file mode 100644
index 000000000..cf55dfdf8
--- /dev/null
+++ b/layout/xul/grid/crashtests/306911-crash.xul
@@ -0,0 +1,4 @@
+<?xml version="1.0"?> <?xml-stylesheet href="chrome://global/skin/" type="text/css"?> <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <listbox id="thelist" flex="1"> <listitem label="Item1" value="item1">
+ <listitem label="Item2" value="item2"/>
+ </listitem> </listbox>
+</window> \ No newline at end of file
diff --git a/layout/xul/grid/crashtests/306911-grid-testcases.xul b/layout/xul/grid/crashtests/306911-grid-testcases.xul
new file mode 100644
index 000000000..bb69f5bcd
--- /dev/null
+++ b/layout/xul/grid/crashtests/306911-grid-testcases.xul
@@ -0,0 +1,99 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <tabbox>
+ <tabs>
+ <tab label="full grid" />
+ <tab label="grid alone" />
+ <tab label="columns alone" />
+ <tab label="rows alone" />
+ <tab label="column alone" />
+ <tab label="row alone" />
+ <tab label="wacky" />
+ </tabs>
+ <tabpanels>
+ <tabpanel>
+ <grid>
+ <rows style="color: blue">
+ <row>
+ <label value="row 1,1" />
+ <label value="row 1,2" />
+ </row>
+ <row>
+ <label value="row 2,1" />
+ <label value="row 2,2" />
+ </row>
+ </rows>
+ <columns style="color: fuchsia; opacity: 0.7">
+ <column>
+ <label value="column 1,1" />
+ <label value="column 1,2" />
+ </column>
+ <column>
+ <label value="column 2,1" />
+ <label value="column 2,2" />
+ </column>
+ </columns>
+ </grid>
+ </tabpanel>
+ <tabpanel>
+ <grid>
+ <label value="Text inside grid" />
+ </grid>
+ </tabpanel>
+ <tabpanel>
+ <columns>
+ <label value="Text inside columns" />
+ </columns>
+ </tabpanel>
+ <tabpanel>
+ <rows>
+ <label value="Text inside rows" />
+ </rows>
+ </tabpanel>
+ <tabpanel>
+ <column>
+ <label value="Text inside column" />
+ </column>
+ </tabpanel>
+ <tabpanel>
+ <row>
+ <label value="Text inside row" />
+ </row>
+ </tabpanel>
+ <tabpanel>
+ <grid>
+ <label value="Text inside grid one" />
+ <rows style="color: blue">
+ <label value="Text inside rows #1" />
+ <row>
+ <label value="row 1,1" />
+ <label value="row 1,2" />
+ </row>
+ <label value="Text inside rows #2" />
+ <row>
+ <label value="row 2,1" />
+ <label value="row 2,2" />
+ </row>
+ <label value="Text inside rows #3" />
+ </rows>
+ <label value="Text inside grid two" style="opacity: 0.7" />
+ <columns style="color: fuchsia; opacity: 0.7">
+ <label value="Text inside columns #1" />
+ <column>
+ <label value="column 1,1" />
+ <label value="column 1,2" />
+ </column>
+ <label value="Text inside columns #2" />
+ <column>
+ <label value="column 2,1" />
+ <label value="column 2,2" />
+ </column>
+ <label value="Text inside columns #3" />
+ </columns>
+ <label value="Text inside grid three" style="opacity: 0.4" />
+ </grid>
+ </tabpanel>
+ </tabpanels>
+ </tabbox>
+</window>
diff --git a/layout/xul/grid/crashtests/306911-grid-testcases2.xul b/layout/xul/grid/crashtests/306911-grid-testcases2.xul
new file mode 100644
index 000000000..c6b4e3849
--- /dev/null
+++ b/layout/xul/grid/crashtests/306911-grid-testcases2.xul
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+<!-- vim:sw=4:ts=4:noet:
+ -->
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <tabbox>
+ <tabs>
+ <tab label="no group" />
+ <tab label="wacky orientations" />
+ </tabs>
+ <tabpanels>
+ <tabpanel>
+ <grid>
+ <row>
+ <label value="row 1,1" />
+ <label value="row 1,2" />
+ </row>
+ <row>
+ <label value="row 2,1" />
+ <label value="row 2,2" />
+ </row>
+ <column>
+ <label value="column 1,1" />
+ <label value="column 1,2" />
+ </column>
+ <column>
+ <label value="column 2,1" />
+ <label value="column 2,2" />
+ </column>
+ </grid>
+ </tabpanel>
+ <tabpanel>
+ <grid>
+ <rows style="color: green">
+ <row>
+ <label value="rows+row 1" />
+ <label value="rows+row 2" />
+ </row>
+ <column>
+ <label value="rows+column 1" />
+ <label value="rows+column 2" />
+ </column>
+ <rows style="color: purple">
+ <row>
+ <label value="rows+rows+row 1" />
+ <label value="rows+rows+row 2" />
+ </row>
+ <column>
+ <label value="rows+rows+column 1" />
+ <label value="rows+rows+column 2" />
+ </column>
+ </rows>
+ <columns style="color: blue">
+ <row>
+ <label value="rows+columns+row 1" />
+ <label value="rows+columns+row 2" />
+ </row>
+ <column>
+ <label value="rows+columns+column 1" />
+ <label value="rows+columns+column 2" />
+ </column>
+ </columns>
+ </rows>
+ <columns style="opacity: 0.7; color: lime">
+ <row>
+ <label value="columns+row 1" />
+ <label value="columns+row 2" />
+ </row>
+ <column>
+ <label value="columns+column 1" />
+ <label value="columns+column 2" />
+ </column>
+ <rows style="color: fuchsia">
+ <row>
+ <label value="columns+rows+row 1" />
+ <label value="columns+rows+row 2" />
+ </row>
+ <column>
+ <label value="columns+rows+column 1" />
+ <label value="columns+rows+column 2" />
+ </column>
+ </rows>
+ <columns style="color: aqua">
+ <row>
+ <label value="columns+columns+row 1" />
+ <label value="columns+columns+row 2" />
+ </row>
+ <column>
+ <label value="columns+columns+column 1" />
+ <label value="columns+columns+column 2" />
+ </column>
+ </columns>
+ </columns>
+ </grid>
+ </tabpanel>
+ </tabpanels>
+ </tabbox>
+</window>
diff --git a/layout/xul/grid/crashtests/311710-1.xul b/layout/xul/grid/crashtests/311710-1.xul
new file mode 100644
index 000000000..403b267e9
--- /dev/null
+++ b/layout/xul/grid/crashtests/311710-1.xul
@@ -0,0 +1,22 @@
+<window title="Testcase bug 311710 - Evil xul testcase, using display:-moz-grid-group causes crash [@ nsGridRow::IsCollapsed]"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml">
+<script type="application/x-javascript">
+function clickit() {
+ var button = document.getElementById('button');
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ button.dispatchEvent(evt);
+}
+window.addEventListener('load', clickit, false);
+</script>
+
+ <grid>
+ <rows>
+ <row>
+ <separator/>
+ </row>
+ </rows>
+ </grid>
+<button id="button" onclick="document.getElementsByTagName('row')[0].style.display='-moz-grid-group'" label="Mozilla should not crash, when clicking this button"/>
+</window>
diff --git a/layout/xul/grid/crashtests/312784-1.xul b/layout/xul/grid/crashtests/312784-1.xul
new file mode 100644
index 000000000..ee4054d80
--- /dev/null
+++ b/layout/xul/grid/crashtests/312784-1.xul
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script type="application/x-JavaScript">
+function crash() {
+ document.getElementById("test").style.display = "none";
+}
+
+function clickit() {
+ var button = document.getElementById('button');
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ button.dispatchEvent(evt);
+}
+
+window.onload = clickit;
+
+</script>
+
+ <grid>
+ <columns>
+ <column/>
+ </columns>
+ <rows id="test">
+ <row><button label="placeholder"/></row>
+ </rows>
+ </grid>
+<button id="button" label="Crash me" onclick="crash()"/>
+</window>
diff --git a/layout/xul/grid/crashtests/313173-1-inner.xul b/layout/xul/grid/crashtests/313173-1-inner.xul
new file mode 100644
index 000000000..284d6c1f1
--- /dev/null
+++ b/layout/xul/grid/crashtests/313173-1-inner.xul
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window title="Testcase bug - Crash with evil xul testcase, using -moz-grid/table-caption"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<grid flex="1">
+ <columns>
+ <column flex="1"/>
+ </columns>
+
+ <rows>
+ <row>
+ </row>
+ </rows>
+</grid>
+
+<html:script>
+function doe(){
+document.getElementsByTagName('columns')[0].style.display='table-caption';
+setTimeout(doe2,20);
+}
+function doe2(){
+document.getElementsByTagName('columns')[0].style.display='-moz-grid';
+}
+
+function clickit() {
+ var button = document.getElementById('button');
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ button.dispatchEvent(evt);
+setTimeout('clickit();', 20);
+}
+window.addEventListener('load', clickit, false);
+
+</html:script>
+ <html:button id="button" onclick="doe()" label="click">Clicking this should not crash Mozilla</html:button>
+</window>
+
diff --git a/layout/xul/grid/crashtests/313173-1.html b/layout/xul/grid/crashtests/313173-1.html
new file mode 100644
index 000000000..8b45339ab
--- /dev/null
+++ b/layout/xul/grid/crashtests/313173-1.html
@@ -0,0 +1,9 @@
+<html class="reftest-wait">
+<head>
+<script>
+setTimeout('document.documentElement.className = ""', 500);
+</script>
+<body>
+<iframe src="313173-1-inner.xul"></iframe>
+</body>
+</html>
diff --git a/layout/xul/grid/crashtests/321066-1.xul b/layout/xul/grid/crashtests/321066-1.xul
new file mode 100644
index 000000000..789c2582c
--- /dev/null
+++ b/layout/xul/grid/crashtests/321066-1.xul
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <grid>
+ <rows>
+ <column/>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/crashtests/321073-1.xul b/layout/xul/grid/crashtests/321073-1.xul
new file mode 100644
index 000000000..b92098b62
--- /dev/null
+++ b/layout/xul/grid/crashtests/321073-1.xul
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <listcols>
+ <grid/>
+ <listitem/>
+ </listcols>
+</window> \ No newline at end of file
diff --git a/layout/xul/grid/crashtests/382750-1.xul b/layout/xul/grid/crashtests/382750-1.xul
new file mode 100644
index 000000000..7a9da73ec
--- /dev/null
+++ b/layout/xul/grid/crashtests/382750-1.xul
@@ -0,0 +1,5 @@
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<grid><rows><listbox/></rows></grid>
+
+</window>
diff --git a/layout/xul/grid/crashtests/400790-1.xul b/layout/xul/grid/crashtests/400790-1.xul
new file mode 100644
index 000000000..4de709428
--- /dev/null
+++ b/layout/xul/grid/crashtests/400790-1.xul
@@ -0,0 +1,20 @@
+<xul xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="boom();">
+
+<script>
+
+function boom()
+{
+ var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+ var newListbox = document.createElementNS(XUL_NS, "listbox");
+ document.getElementById("listbox").appendChild(newListbox);
+
+ var newHbox = document.createElementNS(XUL_NS, "hbox");
+ document.getElementById("listitem").appendChild(newHbox);
+}
+
+</script>
+
+<listbox id="listbox"><listitem id="listitem" /></listbox>
+
+</xul>
diff --git a/layout/xul/grid/crashtests/423802-crash.xul b/layout/xul/grid/crashtests/423802-crash.xul
new file mode 100644
index 000000000..0ae4eab8f
--- /dev/null
+++ b/layout/xul/grid/crashtests/423802-crash.xul
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+
+<window xmlns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<grid>
+ <columns>
+ <column id="col1" flex="1"/>
+ <column id="col2" flex="1"/>
+ <column id="col3" flex="P-2"/>
+ </columns>
+</grid>
+
+</window>
diff --git a/layout/xul/grid/crashtests/crashtests.list b/layout/xul/grid/crashtests/crashtests.list
new file mode 100644
index 000000000..afe8e1002
--- /dev/null
+++ b/layout/xul/grid/crashtests/crashtests.list
@@ -0,0 +1,11 @@
+load 306911-crash.xul
+load 306911-grid-testcases.xul
+load 306911-grid-testcases2.xul
+load 311710-1.xul
+load 312784-1.xul
+load 313173-1.html
+load 321066-1.xul
+load 321073-1.xul
+load 382750-1.xul
+load 400790-1.xul
+load 423802-crash.xul
diff --git a/layout/xul/grid/examples/borderedcolumns.xul b/layout/xul/grid/examples/borderedcolumns.xul
new file mode 100644
index 000000000..15ee06911
--- /dev/null
+++ b/layout/xul/grid/examples/borderedcolumns.xul
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <grid style="border: 2px inset gray;" id="grid">
+ <columns>
+ <column style="border: 10px inset red;"/>
+ <column/>
+ <column style="border: 10px inset red;"/>
+ </columns>
+
+ <rows style="font-size: 20pt;">
+ <row>
+ <text value="Cell 1 "/>
+ <text value="Cell 2 "/>
+ <text value="Cell 3 "/>
+ </row>
+ <row>
+ <text value="Cell 4 "/>
+ <text value="Cell 5 " style="border: 10px inset red;"/>
+ <text value="Cell 6 "/>
+ </row>
+ <row>
+ <text value="Cell 7 "/>
+ <text value="Cell 8 "/>
+ <text value="Cell 9 "/>
+ </row>
+
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/examples/borderedrowscolumns.xul b/layout/xul/grid/examples/borderedrowscolumns.xul
new file mode 100644
index 000000000..94d3d8d99
--- /dev/null
+++ b/layout/xul/grid/examples/borderedrowscolumns.xul
@@ -0,0 +1,55 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <grid style="border: 2px inset gray;" id="grid">
+ <columns style="border: 0px solid blue">
+ <column/>
+ <column/>
+ <column/>
+ </columns>
+
+ <rows style="font-size: 40pt; border: 15px inset blue">
+ <row>
+ <text value="Cell(1)"/>
+ <text value="Cell(2)"/>
+ <text value="Cell(3)"/>
+ </row>
+ <rows style="border: 10px inset green">
+ <row>
+ <text value="Cell(1)"/>
+ <text value="Cell(2)"/>
+ <text value="Cell(3)"/>
+ </row>
+ <row>
+ <text value="Cell(4)"/>
+ <text value="Cell(5)"/>
+ <text value="Cell(6)"/>
+ </row>
+ <row>
+ <text value="Cell(7)"/>
+ <text value="Cell(8)"/>
+ <text value="Cell(9)"/>
+ </row>
+
+ </rows>
+ <row>
+ <text value="Cell(7)"/>
+ <text value="Cell(8)"/>
+ <text value="Cell(9)"/>
+ </row>
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/examples/borderedrowscolumns2.xul b/layout/xul/grid/examples/borderedrowscolumns2.xul
new file mode 100644
index 000000000..96b6ca9e5
--- /dev/null
+++ b/layout/xul/grid/examples/borderedrowscolumns2.xul
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="gridsample.css" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <grid style="border: 2px inset gray;" id="grid">
+ <columns>
+ <column style="border: 10px solid red;"/>
+ <column/>
+ <column/>
+ </columns>
+
+ <rows style="font-size: 40pt;">
+ <row style="border: 10px solid red;">
+ <text value="Cell 1 "/>
+ <text value="Cell 2 "/>
+ <text value="Cell 3 "/>
+ </row>
+ <row>
+ <text value="Cell 4 "/>
+ <text value="Cell 5 "/>
+ <text value="Cell 6 "/>
+ </row>
+ <row>
+ <text value="Cell 7 "/>
+ <text value="Cell 8 "/>
+ <text value="Cell 9 "/>
+ </row>
+
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/examples/borderedrowscolumns3.xul b/layout/xul/grid/examples/borderedrowscolumns3.xul
new file mode 100644
index 000000000..30a6fcc1b
--- /dev/null
+++ b/layout/xul/grid/examples/borderedrowscolumns3.xul
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <grid style="border: 2px inset gray;" id="grid">
+ <columns>
+ <column/>
+ <columns style="border: 10px solid red">
+ <column/>
+ </columns>
+ <column/>
+ </columns>
+
+ <rows style="font-size: 24pt">
+ <row>
+ <text value="Cell(1)"/>
+ <text value="Cell(2)"/>
+ <text value="Cell(3)"/>
+ </row>
+ <rows style="border: 10px solid green">
+ <row>
+ <text value="Cell(1)"/>
+ <text value="Cell(2)"/>
+ <text value="Cell(3)"/>
+ </row>
+ <row>
+ <text value="Cell(4)"/>
+ <text value="Cell(5)"/>
+ <text value="Cell(6)"/>
+ </row>
+ <row>
+ <text value="Cell(7)"/>
+ <text value="Cell(8)"/>
+ <text value="Cell(9)"/>
+ </row>
+
+ </rows>
+ <row>
+ <text value="Cell(7)"/>
+ <text value="Cell(8)"/>
+ <text value="Cell(9)"/>
+ </row>
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/examples/bordermargincolumns1.xul b/layout/xul/grid/examples/bordermargincolumns1.xul
new file mode 100644
index 000000000..009f932a8
--- /dev/null
+++ b/layout/xul/grid/examples/bordermargincolumns1.xul
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="gridsample.css" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <grid style="border: 2px inset gray;" id="grid">
+ <columns>
+ <column style="border: 10px inset red; margin: 10px; "/>
+ <column/>
+ <column/>
+ </columns>
+
+ <rows style="font-size: 40pt;">
+ <row style="border: 5px solid green">
+ <text value="Cell 1"/>
+ <text value="Cell 2"/>
+ <text value="Cell 3"/>
+ </row>
+ <row>
+ <text value="Cell 4"/>
+ <text value="Cell 5"/>
+ <text value="Cell 6"/>
+ </row>
+ <row>
+ <text value="Cell 7"/>
+ <text value="Cell 8"/>
+ <text value="Cell 9"/>
+ </row>
+
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/examples/collapsetest.xul b/layout/xul/grid/examples/collapsetest.xul
new file mode 100644
index 000000000..5e1a042f6
--- /dev/null
+++ b/layout/xul/grid/examples/collapsetest.xul
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical" style="border: 2px solid green"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script>
+
+ function collapseTag(id)
+ {
+ var row = window.document.getElementById(id);
+ row.setAttribute("collapsed","true");
+ }
+
+ function uncollapseTag(id)
+ {
+ var row = window.document.getElementById(id);
+ row.setAttribute("collapsed","false");
+ }
+
+
+</script>
+
+ <hbox>
+ <grid style="border: 2px solid red;" id="grid">
+ <columns id="columns1">
+ <column id="column1"/>
+ <column id="column2"/>
+ <column id="column3"/>
+ </columns>
+
+ <rows id="rows1" style="font-size: 24pt">
+ <row id="row1">
+ <text value="cell1"/>
+ <text value="cell2"/>
+ <text value="cell3"/>
+ </row>
+ <row id="row2">
+ <text value="cell4"/>
+ <text value="cell5"/>
+ <text value="cell6"/>
+ </row>
+ <row id="row3">
+ <text value="cell7"/>
+ <text value="cell8"/>
+ <text value="cell9"/>
+ </row>
+ </rows>
+ </grid>
+ </hbox>
+ <hbox>
+ <button label="collapse row 2" oncommand="collapseTag('row2');"/>
+ <button label="uncollapse row 2" oncommand="uncollapseTag('row2');"/>
+ <button label="collapse column 2" oncommand="collapseTag('column2');"/>
+ <button label="uncollapse column 2" oncommand="uncollapseTag('column2');"/>
+
+ </hbox>
+
+</window>
diff --git a/layout/xul/grid/examples/divcolumngrid.xul b/layout/xul/grid/examples/divcolumngrid.xul
new file mode 100644
index 000000000..2268c302c
--- /dev/null
+++ b/layout/xul/grid/examples/divcolumngrid.xul
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical" style="border: 2px solid green"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <hbox>
+ <grid style="border: 2px solid red;">
+ <columns>
+ <column/>
+ <description style="border: 10px inset gray">
+ hello
+ </description>
+ <column/>
+ </columns>
+
+ <rows>
+ <row>
+ <text style="font-size: 40px" value="foo1"/>
+ <text style="font-size: 40px" value="foo2"/>
+ </row>
+ </rows>
+ </grid>
+ <spacer flex="1" style="background-color: white"/>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/examples/divrowgrid.xul b/layout/xul/grid/examples/divrowgrid.xul
new file mode 100644
index 000000000..657553aab
--- /dev/null
+++ b/layout/xul/grid/examples/divrowgrid.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical" style="border: 2px solid green"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <grid style="width: 100px; border: 2px solid red;">
+ <rows>
+ <row style="font-size: 40px">
+ <text value="foo1"/>
+ <text value="foo2"/>
+ </row>
+ <description>
+ this is some html in the row this should wrap if it is big enough.
+ </description>
+ <row style="font-size: 40px">
+ <text value="foo3"/>
+ <text value="foo4"/>
+ </row>
+
+ </rows>
+ </grid>
+ <spacer flex="1" style="background-color: white"/>
+ </hbox>
+
+
+</window>
diff --git a/layout/xul/grid/examples/dynamicgrid.xul b/layout/xul/grid/examples/dynamicgrid.xul
new file mode 100644
index 000000000..d718df5f9
--- /dev/null
+++ b/layout/xul/grid/examples/dynamicgrid.xul
@@ -0,0 +1,370 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="gridsample.css" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="start()">
+
+<script>
+
+ var selected;
+ var count = 0;
+
+ function isCell(box)
+ {
+ if (box.localName == "row" ||
+ box.localName == "column" ||
+ box.localName == "rows" ||
+ box.localName == "columns" ||
+ box.localName == "grid")
+ return false;
+
+ return true;
+ }
+
+ function start()
+ {
+ selectIt(window.document.getElementById("rows"));
+ }
+
+ function selectIt(box)
+ {
+ if (!box)
+ return;
+
+ var a = box.getAttribute("selected");
+ if (a != "true") {
+ box.setAttribute("selected","true");
+ if (selected)
+ selected.setAttribute("selected","false");
+
+ selected = box;
+ }
+ }
+
+ function addCellSelectionHandle(box)
+ {
+ box.setAttribute("oncommand", "selectIt(this);");
+ }
+
+ function addRowColumnSelectionHandle(box)
+ {
+ box.setAttribute("onclick", "selectIt(this);");
+ }
+
+ function createButton(str)
+ {
+ var b = document.createElement("button");
+ b.setAttribute("label", str+count);
+ count++;
+ addCellSelectionHandle(b);
+ return b;
+ }
+
+ function createRow()
+ {
+ var b = document.createElement("row");
+ b.setAttribute("dynamic","true");
+
+ addRowColumnSelectionHandle(b);
+ return b;
+ }
+
+ function createColumn()
+ {
+ var b = document.createElement("column");
+ b.setAttribute("dynamic","true");
+ addRowColumnSelectionHandle(b);
+ return b;
+ }
+
+ function createText(str)
+ {
+ var text = document.createElement("text");
+ text.setAttribute("value", str+count);
+ count++;
+ text.setAttribute("style", "font-size: 40pt");
+ addCellSelectionHandle(text);
+ return text;
+ }
+
+ function appendElement(element, prepend)
+ {
+ if (!selected)
+ return;
+
+ setUserAttribute(element);
+
+ if (selected.localName == "rows")
+ appendRow(false);
+ else if (selected.localName == "columns")
+ appendColumn(false);
+
+ if (selected.localName == "row" || selected.localName == "column" ) { // is row or column
+ selected.appendChild(element);
+ } else {
+ var parent = selected.parentNode;
+ if (prepend)
+ parent.insertBefore(element, selected);
+ else {
+ var next = selected.nextSibling;
+ if (next)
+ parent.insertBefore(element,next);
+ else
+ parent.appendChild(element);
+ }
+ }
+
+ selectIt(element);
+ }
+
+ function getRows(box)
+ {
+ return window.document.getElementById("rows");
+ }
+
+ function getColumns(box)
+ {
+ return window.document.getElementById("columns");
+ }
+
+ function setUserAttribute(element)
+ {
+ var attributeBox = document.getElementById("attributebox");
+ var valueBox = document.getElementById("valuebox");
+ var attribute = attributeBox.value;
+ var value = valueBox.value;
+ if (attribute != "")
+ element.setAttribute(attribute,value);
+ }
+
+ function appendRowColumn(rowColumn, prepend)
+ {
+ if (!selected)
+ return;
+
+ setUserAttribute(rowColumn);
+
+ var row = rowColumn;
+
+ // first see what we are adding.
+
+ if (isCell(selected)) { // if cell then select row/column
+ selectIt(selected.parentNode);
+ }
+
+ if (selected.localName == "row" || selected.localName == "rows")
+ if (row.localName == "column") {
+ selectIt(getColumns(selected));
+ dump("Selecting the column")
+ dump("Selected="+selected.localName);
+ }
+
+ if (selected.localName == "column" || selected.localName == "columns")
+ if (row.localName == "row")
+ selectIt(getRows(selected));
+
+ if (selected.localName == "rows" || selected.localName == "columns" )
+ { // if rows its easy
+ selected.appendChild(row);
+ } else {
+ var parent = selected.parentNode;
+ if (prepend)
+ parent.insertBefore(row, selected);
+ else {
+ var next = selected.nextSibling;
+ if (next)
+ parent.insertBefore(row,next);
+ else
+ parent.appendChild(row);
+ }
+ }
+
+ selectIt(row);
+ }
+
+ function appendRow(prepend)
+ {
+ var row = createRow();
+ appendRowColumn(row,prepend);
+ }
+
+
+ function appendColumn(prepend)
+ {
+ var column = createColumn();
+ appendRowColumn(column,prepend);
+ }
+
+
+ function selectRows()
+ {
+ var rows = getRows();
+ if (rows.firstChild)
+ selectIt(rows.firstChild);
+ else
+ selectIt(rows);
+ }
+
+
+ function selectColumns()
+ {
+ var columns = getColumns();
+ if (columns.firstChild)
+ selectIt(columns.firstChild);
+ else
+ selectIt(columns);
+ }
+
+ function nextElement()
+ {
+ if (!selected)
+ return;
+
+ selectIt(selected.nextSibling);
+ }
+
+ function previousElement()
+ {
+ if (!selected)
+ return;
+
+ selectIt(selected.previousSibling);
+ }
+
+ function selectRow()
+ {
+ if (!selected)
+ return;
+
+ if (selected.localName == "row")
+ return;
+
+ if (isCell(selected)) {
+ if (selected.parentNode.localName == "row")
+ selectIt(selected.parentNode);
+ }
+ }
+
+ function selectColumn()
+ {
+ if (!selected)
+ return;
+
+ if (selected.localName == "column")
+ return;
+
+ if (isCell(selected)) {
+ if (selected.parentNode.localName == "column")
+ selectIt(selected.parentNode);
+ }
+ }
+
+ function collapseGrid()
+ {
+ var grid = document.getElementById("grid");
+ var collapsed = grid.getAttribute("collapsed");
+
+ if (collapsed == "")
+ grid.setAttribute("collapsed","true");
+ else
+ grid.setAttribute("collapsed","");
+
+ }
+
+ function collapseElement()
+ {
+ if (selected) {
+ var collapsed = selected.getAttribute("collapsed");
+
+ if (collapsed == "")
+ selected.setAttribute("collapsed","true");
+ else
+ selected.setAttribute("collapsed","");
+ }
+ }
+
+</script>
+
+ <hbox flex="1" style="border: 2px inset gray; overflow: auto">
+ <vbox flex="1">
+ <hbox>
+ <grid id="grid" style="border: 2px solid red;">
+ <columns id="columns">
+ </columns>
+
+ <rows start="true" id="rows">
+ </rows>
+ </grid>
+ <spacer flex="1"/>
+ </hbox>
+ <spacer flex="1"/>
+ </vbox>
+ </hbox>
+
+ <grid style="background-color: blue">
+ <columns>
+ <column flex="1"/>
+ <column flex="1"/>
+ <column flex="1"/>
+ <column flex="1"/>
+ </columns>
+ <rows>
+
+ <row>
+ <button label="append row" oncommand="appendRow(false);"/>
+ <button label="prepend row" oncommand="appendRow(true);"/>
+
+ <button label="append column" oncommand="appendColumn(false);"/>
+ <button label="prepend column" oncommand="appendColumn(true);"/>
+ </row>
+
+ <row>
+
+ <button label="append button" oncommand="appendElement(createButton('button'),false);"/>
+ <button label="prepend button" oncommand="appendElement(createButton('button'),true);"/>
+
+ <button label="append text" oncommand="appendElement(createText('text'),false);"/>
+ <button label="prepend text" oncommand="appendElement(createText('text'),true);"/>
+
+ </row>
+
+ <row>
+
+ <button label="select rows" oncommand="selectRows()"/>
+ <button label="select columns" oncommand="selectColumns()"/>
+
+ <button label="next" oncommand="nextElement()"/>
+ <button label="previous" oncommand="previousElement()"/>
+
+ </row>
+
+ <hbox align="center">
+ <button label="collapse/uncollapse grid" flex="1" oncommand="collapseGrid()"/>
+ <button label="collapse/uncollapse element" flex="1" oncommand="collapseElement()"/>
+ </hbox>
+
+
+
+ <hbox>
+
+ <text value="attribute"/>
+ <textbox id="attributebox" value="" flex="1"/>
+ <text value="value"/>
+ <textbox id="valuebox" value="" flex="2"/>
+ </hbox>
+
+
+ </rows>
+ </grid>
+
+</window>
diff --git a/layout/xul/grid/examples/flexgroupgrid.xul b/layout/xul/grid/examples/flexgroupgrid.xul
new file mode 100644
index 000000000..f4cd6622c
--- /dev/null
+++ b/layout/xul/grid/examples/flexgroupgrid.xul
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="gridsample.css" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <grid style="border: 2px inset gray;" flex="1">
+ <columns>
+ <columns style="border: 10px solid red" flex="1">
+ <column flex="2"/>
+ <column flex="1"/>
+ </columns>
+ <column flex="1"/>
+ </columns>
+
+ <rows style="font-size: 20pt">
+ <rows>
+ <row>
+ <text class="yellow" value="CellA"/>
+ <text class="yellow" value="CellAB"/>
+ <text class="yellow" value="CellABC"/>
+ </row>
+ <row>
+ <text class="yellow" value="CellA"/>
+ <text class="yellow" value="CellAB"/>
+ <text class="yellow" value="CellABC"/>
+ </row>
+ </rows>
+ <row>
+ <text class="yellow" value="CellA"/>
+ <text class="yellow" value="CellAB"/>
+ <text class="yellow" value="CellABC"/>
+ </row>
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/examples/javascriptappend.xul b/layout/xul/grid/examples/javascriptappend.xul
new file mode 100644
index 000000000..f2a415cae
--- /dev/null
+++ b/layout/xul/grid/examples/javascriptappend.xul
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical" style="border: 2px solid green"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script>
+ function start()
+ {
+ var row = document.getElementById("row");
+ var text = document.createElement("text");
+ text.setAttribute("value", "foo");
+ row.appendChild(text);
+ }
+
+ </script>
+
+ <hbox>
+ <grid style="border: 2px solid red;" id="grid">
+ <columns>
+ </columns>
+
+ <rows>
+ <row id="row">
+ <button label="value"/>
+ </row>
+ </rows>
+ </grid>
+ <spacer flex="1" style="background-color: white"/>
+ </hbox>
+
+ <button label="insert" oncommand="start()"/>
+
+</window>
diff --git a/layout/xul/grid/examples/jumpygrid.xul b/layout/xul/grid/examples/jumpygrid.xul
new file mode 100644
index 000000000..8bbeb5806
--- /dev/null
+++ b/layout/xul/grid/examples/jumpygrid.xul
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="gridsample.css" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical" style="border: 2px solid green"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script>
+ function flip(child)
+ {
+ var jump = child.getAttribute("jumpy");
+ if (jump != "true")
+ child.setAttribute("jumpy","true");
+ else
+ child.setAttribute("jumpy","false");
+ }
+
+ </script>
+ <hbox>
+ <grid style="border: 2px solid yellow;">
+ <columns>
+ </columns>
+
+ <rows>
+ <row>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ </row>
+ <row>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ </row>
+ <row>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ </row>
+ <row>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ </row>
+ <row>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ </row>
+ <row>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ <button label="button" class="jumpy"/>
+ </row>
+
+ </rows>
+ </grid>
+ <spacer style="border: 2px solid white;" flex="1"/>
+ </hbox>
+ <spacer style="border: 2px solid white;" flex="1"/>
+
+</window>
diff --git a/layout/xul/grid/examples/nestedrows.xul b/layout/xul/grid/examples/nestedrows.xul
new file mode 100644
index 000000000..700f785b3
--- /dev/null
+++ b/layout/xul/grid/examples/nestedrows.xul
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox flex="1">
+ <grid style="border: 2px solid red" flex="1">
+
+ <columns>
+ <column flex="1"/>
+ <column flex="1"/>
+ <column flex="1"/>
+ </columns>
+
+ <rows>
+ <row>
+ <text value="out1"/>
+ <text value="out2"/>
+ <text value="out3"/>
+ </row>
+
+ <rows flex="1" style="border: 10px inset yellow; font-size: 20pt">
+ <row>
+ <text value="in1"/>
+ <text value="in2"/>
+ <text value="in3"/>
+ </row>
+ <row>
+ <text value="in4"/>
+ <text value="in5"/>
+ <text value="in5"/>
+ </row>
+ </rows>
+
+ </rows>
+
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/examples/rowspan.xul b/layout/xul/grid/examples/rowspan.xul
new file mode 100644
index 000000000..266a32229
--- /dev/null
+++ b/layout/xul/grid/examples/rowspan.xul
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical" style="border: 2px solid green"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <grid style="border: 2px solid red;">
+ <columns>
+ <column/>
+ <column/>
+ </columns>
+
+ <rows>
+ <row style="font-size: 40px">
+ <text value="foo1"/>
+ <text value="foo2"/>
+ </row>
+ <box width="50" style="border:5px inset grey">
+ <text value="hello there. This spans"/>
+ </box>
+ <row style="font-size: 40px" >
+ <text value="foo1"/>
+ <text value="foo2"/>
+ </row>
+
+ </rows>
+ </grid>
+ <spacer flex="1" style="background-color: white"/>
+ </hbox>
+
+
+</window>
diff --git a/layout/xul/grid/examples/scrollingcolumns.xul b/layout/xul/grid/examples/scrollingcolumns.xul
new file mode 100644
index 000000000..f29909624
--- /dev/null
+++ b/layout/xul/grid/examples/scrollingcolumns.xul
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox flex="1">
+ <grid style="border: 2px solid red" flex="1">
+
+ <rows>
+ <row flex="1"/>
+ <row flex="1"/>
+ <row flex="1"/>
+ </rows>
+ <columns>
+
+ <column>
+ <button label="left"/>
+ <button label="left"/>
+ <button label="left"/>
+ </column>
+
+ <columns flex="1" style="min-width: 1px; overflow: auto; background-color: green">
+ <column>
+ <button label="cell1"/>
+ <button label="cell1"/>
+ <button label="cell1"/>
+ </column>
+ <column>
+ <button label="cell2"/>
+ <button label="cell2"/>
+ <button label="cell2"/>
+ </column>
+ <column>
+ <button label="cell3"/>
+ <button label="cell3"/>
+ <button label="cell3"/>
+ </column>
+ <column>
+ <button label="cell4"/>
+ <button label="cell4"/>
+ <button label="cell4"/>
+ </column>
+ <column>
+ <button label="cell5"/>
+ <button label="cell5"/>
+ <button label="cell5"/>
+ </column>
+ <column>
+ <button label="cell6"/>
+ <button label="cell6"/>
+ <button label="cell6"/>
+ </column>
+ <column>
+ <button label="cell7"/>
+ <button label="cell7"/>
+ <button label="cell7"/>
+ </column>
+ </columns>
+ <column>
+ <button label="right"/>
+ <button label="right"/>
+ <button label="right"/>
+ </column>
+
+ </columns>
+
+ </grid>
+ <spacer width="100"/>
+ </hbox>
+ <spacer height="100"/>
+</window>
diff --git a/layout/xul/grid/examples/scrollingrows.xul b/layout/xul/grid/examples/scrollingrows.xul
new file mode 100644
index 000000000..fd5077cde
--- /dev/null
+++ b/layout/xul/grid/examples/scrollingrows.xul
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox flex="1">
+ <grid style="border: 2px solid red" flex="1">
+
+ <columns>
+ <column flex="1"/>
+ <column flex="1"/>
+ <column flex="1"/>
+ </columns>
+
+ <rows>
+ <row>
+ <button label="left"/>
+ <button label="left"/>
+ <button label="left"/>
+ </row>
+
+ <rows flex="1" style="border: 10px inset gray; overflow: auto; background-color: green">
+ <row>
+ <button label="cell1"/>
+ <button label="cell1"/>
+ <button label="cell1"/>
+ </row>
+ <row>
+ <button label="cell2"/>
+ <button label="cell2"/>
+ <button label="cell2"/>
+ </row>
+ <row>
+ <button label="cell3"/>
+ <button label="cell3"/>
+ <button label="cell3"/>
+ </row>
+ <row>
+ <button label="cell4"/>
+ <button label="cell4"/>
+ <button label="cell4"/>
+ </row>
+ <row>
+ <button label="cell5"/>
+ <button label="cell5"/>
+ <button label="cell5"/>
+ </row>
+ <row>
+ <button label="cell6"/>
+ <button label="cell6"/>
+ <button label="cell6"/>
+ </row>
+ <row>
+ <button label="cell7"/>
+ <button label="cell7"/>
+ <button label="cell7"/>
+ </row>
+ </rows>
+ <row>
+ <button label="right"/>
+ <button label="right"/>
+ <button label="right"/>
+ </row>
+
+ </rows>
+
+ </grid>
+ <spacer width="100"/>
+ </hbox>
+ <spacer height="100"/>
+</window>
diff --git a/layout/xul/grid/examples/splitter.xul b/layout/xul/grid/examples/splitter.xul
new file mode 100644
index 000000000..67946d487
--- /dev/null
+++ b/layout/xul/grid/examples/splitter.xul
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE window>
+
+
+<window orient="vertical" style="border: 2px solid green"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <grid style="border: 2px solid red;">
+ <columns>
+ <column style="min-width: 1px"/>
+ <splitter/>
+ <column style="min-width: 1px"/>
+ </columns>
+
+ <rows>
+ <row>
+ <text style="font-size: 40px" value="foo1"/>
+ <text style="font-size: 40px" value="foo2"/>
+ </row>
+ <label value="this is some text. This is longer"/>
+ <row>
+ <text style="font-size: 40px" value="foo1"/>
+ <text style="font-size: 40px" value="foo2"/>
+ </row>
+
+ </rows>
+ </grid>
+ <spacer flex="1" style="background-color: white"/>
+ </hbox>
+
+
+</window>
diff --git a/layout/xul/grid/moz.build b/layout/xul/grid/moz.build
new file mode 100644
index 000000000..074985aaf
--- /dev/null
+++ b/layout/xul/grid/moz.build
@@ -0,0 +1,43 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files('**'):
+ BUG_COMPONENT = ('Core', 'XP Toolkit/Widgets: XUL')
+
+EXPORTS += [
+ 'nsGrid.h',
+ 'nsGridCell.h',
+ 'nsGridLayout2.h',
+ 'nsGridRow.h',
+ 'nsGridRowGroupLayout.h',
+ 'nsGridRowLayout.h',
+ 'nsGridRowLeafFrame.h',
+ 'nsGridRowLeafLayout.h',
+ 'nsIGridPart.h',
+]
+
+UNIFIED_SOURCES += [
+ 'nsGrid.cpp',
+ 'nsGridCell.cpp',
+ 'nsGridLayout2.cpp',
+ 'nsGridRow.cpp',
+ 'nsGridRowGroupFrame.cpp',
+ 'nsGridRowGroupLayout.cpp',
+ 'nsGridRowLayout.cpp',
+ 'nsGridRowLeafFrame.cpp',
+ 'nsGridRowLeafLayout.cpp',
+]
+
+FINAL_LIBRARY = 'xul'
+LOCAL_INCLUDES += [
+ '..',
+ '../../forms',
+ '../../generic',
+ '../../style',
+]
+
+if CONFIG['GNU_CXX']:
+ CXXFLAGS += ['-Wno-error=shadow']
diff --git a/layout/xul/grid/nsGrid.cpp b/layout/xul/grid/nsGrid.cpp
new file mode 100644
index 000000000..762bbfcd7
--- /dev/null
+++ b/layout/xul/grid/nsGrid.cpp
@@ -0,0 +1,1276 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+#include "nsGrid.h"
+#include "nsGridRowGroupLayout.h"
+#include "nsBox.h"
+#include "nsIScrollableFrame.h"
+#include "nsSprocketLayout.h"
+#include "nsGridLayout2.h"
+#include "nsGridRow.h"
+#include "nsGridCell.h"
+#include "mozilla/ReflowInput.h"
+
+/*
+The grid control expands the idea of boxes from 1 dimension to 2 dimensions.
+It works by allowing the XUL to define a collection of rows and columns and then
+stacking them on top of each other. Here is and example.
+
+Example 1:
+
+<grid>
+ <columns>
+ <column/>
+ <column/>
+ </columns>
+
+ <rows>
+ <row/>
+ <row/>
+ </rows>
+</grid>
+
+example 2:
+
+<grid>
+ <columns>
+ <column flex="1"/>
+ <column flex="1"/>
+ </columns>
+
+ <rows>
+ <row>
+ <text value="hello"/>
+ <text value="there"/>
+ </row>
+ </rows>
+</grid>
+
+example 3:
+
+<grid>
+
+<rows>
+ <row>
+ <text value="hello"/>
+ <text value="there"/>
+ </row>
+ </rows>
+
+ <columns>
+ <column>
+ <text value="Hey I'm in the column and I'm on top!"/>
+ </column>
+ <column/>
+ </columns>
+
+</grid>
+
+Usually the columns are first and the rows are second, so the rows will be drawn on top of the columns.
+You can reverse this by defining the rows first.
+Other tags are then placed in the <row> or <column> tags causing the grid to accommodate everyone.
+It does this by creating 3 things: A cellmap, a row list, and a column list. The cellmap is a 2
+dimensional array of nsGridCells. Each cell contains 2 boxes. One cell from the column list
+and one from the row list. When a cell is asked for its size it returns that smallest size it can
+be to accommodate the 2 cells. Row lists and Column lists use the same data structure: nsGridRow.
+Essentially a row and column are the same except a row goes alone the x axis and a column the y.
+To make things easier and save code everything is written in terms of the x dimension. A flag is
+passed in called "isHorizontal" that can flip the calculations to the y axis.
+
+Usually the number of cells in a row match the number of columns, but not always.
+It is possible to define 5 columns for a grid but have 10 cells in one of the rows.
+In this case 5 extra columns will be added to the column list to handle the situation.
+These are called extraColumns/Rows.
+*/
+
+using namespace mozilla;
+
+nsGrid::nsGrid():mBox(nullptr),
+ mRowsBox(nullptr),
+ mColumnsBox(nullptr),
+ mNeedsRebuild(true),
+ mRowCount(0),
+ mColumnCount(0),
+ mExtraRowCount(0),
+ mExtraColumnCount(0),
+ mMarkingDirty(false)
+{
+ MOZ_COUNT_CTOR(nsGrid);
+}
+
+nsGrid::~nsGrid()
+{
+ FreeMap();
+ MOZ_COUNT_DTOR(nsGrid);
+}
+
+/*
+ * This is called whenever something major happens in the grid. And example
+ * might be when many cells or row are added. It sets a flag signaling that
+ * all the grids caches information should be recalculated.
+ */
+void
+nsGrid::NeedsRebuild(nsBoxLayoutState& aState)
+{
+ if (mNeedsRebuild)
+ return;
+
+ // iterate through columns and rows and dirty them
+ mNeedsRebuild = true;
+
+ // find the new row and column box. They could have
+ // been changed.
+ mRowsBox = nullptr;
+ mColumnsBox = nullptr;
+ FindRowsAndColumns(&mRowsBox, &mColumnsBox);
+
+ // tell all the rows and columns they are dirty
+ DirtyRows(mRowsBox, aState);
+ DirtyRows(mColumnsBox, aState);
+}
+
+
+
+/**
+ * If we are marked for rebuild. Then build everything
+ */
+void
+nsGrid::RebuildIfNeeded()
+{
+ if (!mNeedsRebuild)
+ return;
+
+ mNeedsRebuild = false;
+
+ // find the row and columns frames
+ FindRowsAndColumns(&mRowsBox, &mColumnsBox);
+
+ // count the rows and columns
+ int32_t computedRowCount = 0;
+ int32_t computedColumnCount = 0;
+ int32_t rowCount = 0;
+ int32_t columnCount = 0;
+
+ CountRowsColumns(mRowsBox, rowCount, computedColumnCount);
+ CountRowsColumns(mColumnsBox, columnCount, computedRowCount);
+
+ // computedRowCount are the actual number of rows as determined by the
+ // columns children.
+ // computedColumnCount are the number of columns as determined by the number
+ // of rows children.
+ // We can use this information to see how many extra columns or rows we need.
+ // This can happen if there are are more children in a row that number of columns
+ // defined. Example:
+ //
+ // <columns>
+ // <column/>
+ // </columns>
+ //
+ // <rows>
+ // <row>
+ // <button/><button/>
+ // </row>
+ // </rows>
+ //
+ // computedColumnCount = 2 // for the 2 buttons in the row tag
+ // computedRowCount = 0 // there is nothing in the column tag
+ // mColumnCount = 1 // one column defined
+ // mRowCount = 1 // one row defined
+ //
+ // So in this case we need to make 1 extra column.
+ //
+
+ // Make sure to update mExtraColumnCount no matter what, since it might
+ // happen that we now have as many columns as are defined, and we wouldn't
+ // want to have a positive mExtraColumnCount hanging about in that case!
+ mExtraColumnCount = computedColumnCount - columnCount;
+ if (computedColumnCount > columnCount) {
+ columnCount = computedColumnCount;
+ }
+
+ // Same for rows.
+ mExtraRowCount = computedRowCount - rowCount;
+ if (computedRowCount > rowCount) {
+ rowCount = computedRowCount;
+ }
+
+ // build and poplulate row and columns arrays
+ mRows = BuildRows(mRowsBox, rowCount, true);
+ mColumns = BuildRows(mColumnsBox, columnCount, false);
+
+ // build and populate the cell map
+ mCellMap = BuildCellMap(rowCount, columnCount);
+
+ mRowCount = rowCount;
+ mColumnCount = columnCount;
+
+ // populate the cell map from column and row children
+ PopulateCellMap(mRows.get(), mColumns.get(), mRowCount, mColumnCount, true);
+ PopulateCellMap(mColumns.get(), mRows.get(), mColumnCount, mRowCount, false);
+}
+
+void
+nsGrid::FreeMap()
+{
+ mRows = nullptr;
+ mColumns = nullptr;
+ mCellMap = nullptr;
+ mColumnCount = 0;
+ mRowCount = 0;
+ mExtraColumnCount = 0;
+ mExtraRowCount = 0;
+ mRowsBox = nullptr;
+ mColumnsBox = nullptr;
+}
+
+/**
+ * finds the first <rows> and <columns> tags in the <grid> tag
+ */
+void
+nsGrid::FindRowsAndColumns(nsIFrame** aRows, nsIFrame** aColumns)
+{
+ *aRows = nullptr;
+ *aColumns = nullptr;
+
+ // find the boxes that contain our rows and columns
+ nsIFrame* child = nullptr;
+ // if we have <grid></grid> then mBox will be null (bug 125689)
+ if (mBox)
+ child = nsBox::GetChildXULBox(mBox);
+
+ while(child)
+ {
+ nsIFrame* oldBox = child;
+ nsIScrollableFrame *scrollFrame = do_QueryFrame(child);
+ if (scrollFrame) {
+ nsIFrame* scrolledFrame = scrollFrame->GetScrolledFrame();
+ NS_ASSERTION(scrolledFrame,"Error no scroll frame!!");
+ child = do_QueryFrame(scrolledFrame);
+ }
+
+ nsCOMPtr<nsIGridPart> monument = GetPartFromBox(child);
+ if (monument)
+ {
+ nsGridRowGroupLayout* rowGroup = monument->CastToRowGroupLayout();
+ if (rowGroup) {
+ bool isHorizontal = !nsSprocketLayout::IsXULHorizontal(child);
+ if (isHorizontal)
+ *aRows = child;
+ else
+ *aColumns = child;
+
+ if (*aRows && *aColumns)
+ return;
+ }
+ }
+
+ if (scrollFrame) {
+ child = oldBox;
+ }
+
+ child = nsBox::GetNextXULBox(child);
+ }
+}
+
+/**
+ * Count the number of rows and columns in the given box. aRowCount well become the actual number
+ * rows defined in the xul. aComputedColumnCount will become the number of columns by counting the number
+ * of cells in each row.
+ */
+void
+nsGrid::CountRowsColumns(nsIFrame* aRowBox, int32_t& aRowCount, int32_t& aComputedColumnCount)
+{
+ aRowCount = 0;
+ aComputedColumnCount = 0;
+ // get the rowboxes layout manager. Then ask it to do the work for us
+ if (aRowBox) {
+ nsCOMPtr<nsIGridPart> monument = GetPartFromBox(aRowBox);
+ if (monument)
+ monument->CountRowsColumns(aRowBox, aRowCount, aComputedColumnCount);
+ }
+}
+
+
+/**
+ * Given the number of rows create nsGridRow objects for them and full them out.
+ */
+UniquePtr<nsGridRow[]>
+nsGrid::BuildRows(nsIFrame* aBox, int32_t aRowCount, bool aIsHorizontal)
+{
+ // if no rows then return null
+ if (aRowCount == 0) {
+ return nullptr;
+ }
+
+ // create the array
+ UniquePtr<nsGridRow[]> row;
+
+ // only create new rows if we have to. Reuse old rows.
+ if (aIsHorizontal)
+ {
+ if (aRowCount > mRowCount) {
+ row = MakeUnique<nsGridRow[]>(aRowCount);
+ } else {
+ for (int32_t i=0; i < mRowCount; i++)
+ mRows[i].Init(nullptr, false);
+
+ row = Move(mRows);
+ }
+ } else {
+ if (aRowCount > mColumnCount) {
+ row = MakeUnique<nsGridRow[]>(aRowCount);
+ } else {
+ for (int32_t i=0; i < mColumnCount; i++)
+ mColumns[i].Init(nullptr, false);
+
+ row = Move(mColumns);
+ }
+ }
+
+ // populate it if we can. If not it will contain only dynamic columns
+ if (aBox)
+ {
+ nsCOMPtr<nsIGridPart> monument = GetPartFromBox(aBox);
+ if (monument) {
+ monument->BuildRows(aBox, row.get());
+ }
+ }
+
+ return row;
+}
+
+
+/**
+ * Given the number of rows and columns. Build a cellmap
+ */
+UniquePtr<nsGridCell[]>
+nsGrid::BuildCellMap(int32_t aRows, int32_t aColumns)
+{
+ int32_t size = aRows*aColumns;
+ int32_t oldsize = mRowCount*mColumnCount;
+ if (size == 0) {
+ return nullptr;
+ }
+
+ if (size > oldsize) {
+ return MakeUnique<nsGridCell[]>(size);
+ }
+
+ // clear out cellmap
+ for (int32_t i=0; i < oldsize; i++) {
+ mCellMap[i].SetBoxInRow(nullptr);
+ mCellMap[i].SetBoxInColumn(nullptr);
+ }
+ return Move(mCellMap);
+}
+
+/**
+ * Run through all the cells in the rows and columns and populate then with 2 cells. One from the row and one
+ * from the column
+ */
+void
+nsGrid::PopulateCellMap(nsGridRow* aRows, nsGridRow* aColumns, int32_t aRowCount, int32_t aColumnCount, bool aIsHorizontal)
+{
+ if (!aRows)
+ return;
+
+ // look through the columns
+ int32_t j = 0;
+
+ for(int32_t i=0; i < aRowCount; i++)
+ {
+ nsIFrame* child = nullptr;
+ nsGridRow* row = &aRows[i];
+
+ // skip bogus rows. They have no cells
+ if (row->mIsBogus)
+ continue;
+
+ child = row->mBox;
+ if (child) {
+ child = nsBox::GetChildXULBox(child);
+
+ j = 0;
+
+ while(child && j < aColumnCount)
+ {
+ // skip bogus column. They have no cells
+ nsGridRow* column = &aColumns[j];
+ if (column->mIsBogus)
+ {
+ j++;
+ continue;
+ }
+
+ if (aIsHorizontal)
+ GetCellAt(j,i)->SetBoxInRow(child);
+ else
+ GetCellAt(i,j)->SetBoxInColumn(child);
+
+ child = nsBox::GetNextXULBox(child);
+
+ j++;
+ }
+ }
+ }
+}
+
+/**
+ * Run through the rows in the given box and mark them dirty so they
+ * will get recalculated and get a layout.
+ */
+void
+nsGrid::DirtyRows(nsIFrame* aRowBox, nsBoxLayoutState& aState)
+{
+ // make sure we prevent others from dirtying things.
+ mMarkingDirty = true;
+
+ // if the box is a grid part have it recursively hand it.
+ if (aRowBox) {
+ nsCOMPtr<nsIGridPart> part = GetPartFromBox(aRowBox);
+ if (part)
+ part->DirtyRows(aRowBox, aState);
+ }
+
+ mMarkingDirty = false;
+}
+
+nsGridRow*
+nsGrid::GetColumnAt(int32_t aIndex, bool aIsHorizontal)
+{
+ return GetRowAt(aIndex, !aIsHorizontal);
+}
+
+nsGridRow*
+nsGrid::GetRowAt(int32_t aIndex, bool aIsHorizontal)
+{
+ RebuildIfNeeded();
+
+ if (aIsHorizontal) {
+ NS_ASSERTION(aIndex < mRowCount && aIndex >= 0, "Index out of range");
+ return &mRows[aIndex];
+ } else {
+ NS_ASSERTION(aIndex < mColumnCount && aIndex >= 0, "Index out of range");
+ return &mColumns[aIndex];
+ }
+}
+
+nsGridCell*
+nsGrid::GetCellAt(int32_t aX, int32_t aY)
+{
+ RebuildIfNeeded();
+
+ NS_ASSERTION(aY < mRowCount && aY >= 0, "Index out of range");
+ NS_ASSERTION(aX < mColumnCount && aX >= 0, "Index out of range");
+ return &mCellMap[aY*mColumnCount+aX];
+}
+
+int32_t
+nsGrid::GetExtraColumnCount(bool aIsHorizontal)
+{
+ return GetExtraRowCount(!aIsHorizontal);
+}
+
+int32_t
+nsGrid::GetExtraRowCount(bool aIsHorizontal)
+{
+ RebuildIfNeeded();
+
+ if (aIsHorizontal)
+ return mExtraRowCount;
+ else
+ return mExtraColumnCount;
+}
+
+
+/**
+ * These methods return the preferred, min, max sizes for a given row index.
+ * aIsHorizontal if aIsHorizontal is true. If you pass false you will get the inverse.
+ * As if you called GetPrefColumnSize(aState, index, aPref)
+ */
+nsSize
+nsGrid::GetPrefRowSize(nsBoxLayoutState& aState, int32_t aRowIndex, bool aIsHorizontal)
+{
+ nsSize size(0,0);
+ if (!(aRowIndex >=0 && aRowIndex < GetRowCount(aIsHorizontal)))
+ return size;
+
+ nscoord height = GetPrefRowHeight(aState, aRowIndex, aIsHorizontal);
+ SetLargestSize(size, height, aIsHorizontal);
+
+ return size;
+}
+
+nsSize
+nsGrid::GetMinRowSize(nsBoxLayoutState& aState, int32_t aRowIndex, bool aIsHorizontal)
+{
+ nsSize size(0,0);
+ if (!(aRowIndex >=0 && aRowIndex < GetRowCount(aIsHorizontal)))
+ return size;
+
+ nscoord height = GetMinRowHeight(aState, aRowIndex, aIsHorizontal);
+ SetLargestSize(size, height, aIsHorizontal);
+
+ return size;
+}
+
+nsSize
+nsGrid::GetMaxRowSize(nsBoxLayoutState& aState, int32_t aRowIndex, bool aIsHorizontal)
+{
+ nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
+ if (!(aRowIndex >=0 && aRowIndex < GetRowCount(aIsHorizontal)))
+ return size;
+
+ nscoord height = GetMaxRowHeight(aState, aRowIndex, aIsHorizontal);
+ SetSmallestSize(size, height, aIsHorizontal);
+
+ return size;
+}
+
+// static
+nsIGridPart*
+nsGrid::GetPartFromBox(nsIFrame* aBox)
+{
+ if (!aBox)
+ return nullptr;
+
+ nsBoxLayout* layout = aBox->GetXULLayoutManager();
+ return layout ? layout->AsGridPart() : nullptr;
+}
+
+nsMargin
+nsGrid::GetBoxTotalMargin(nsIFrame* aBox, bool aIsHorizontal)
+{
+ nsMargin margin(0,0,0,0);
+ // walk the boxes parent chain getting the border/padding/margin of our parent rows
+
+ // first get the layour manager
+ nsIGridPart* part = GetPartFromBox(aBox);
+ if (part)
+ margin = part->GetTotalMargin(aBox, aIsHorizontal);
+
+ return margin;
+}
+
+/**
+ * The first and last rows can be affected by <rows> tags with borders or margin
+ * gets first and last rows and their indexes.
+ * If it fails because there are no rows then:
+ * FirstRow is nullptr
+ * LastRow is nullptr
+ * aFirstIndex = -1
+ * aLastIndex = -1
+ */
+void
+nsGrid::GetFirstAndLastRow(int32_t& aFirstIndex,
+ int32_t& aLastIndex,
+ nsGridRow*& aFirstRow,
+ nsGridRow*& aLastRow,
+ bool aIsHorizontal)
+{
+ aFirstRow = nullptr;
+ aLastRow = nullptr;
+ aFirstIndex = -1;
+ aLastIndex = -1;
+
+ int32_t count = GetRowCount(aIsHorizontal);
+
+ if (count == 0)
+ return;
+
+
+ // We could have collapsed columns either before or after our index.
+ // they should not count. So if we are the 5th row and the first 4 are
+ // collaped we become the first row. Or if we are the 9th row and
+ // 10 up to the last row are collapsed we then become the last.
+
+ // see if we are first
+ int32_t i;
+ for (i=0; i < count; i++)
+ {
+ nsGridRow* row = GetRowAt(i,aIsHorizontal);
+ if (!row->IsXULCollapsed()) {
+ aFirstIndex = i;
+ aFirstRow = row;
+ break;
+ }
+ }
+
+ // see if we are last
+ for (i=count-1; i >= 0; i--)
+ {
+ nsGridRow* row = GetRowAt(i,aIsHorizontal);
+ if (!row->IsXULCollapsed()) {
+ aLastIndex = i;
+ aLastRow = row;
+ break;
+ }
+
+ }
+}
+
+/**
+ * A row can have a top and bottom offset. Usually this is just the top and bottom border/padding.
+ * However if the row is the first or last it could be affected by the fact a column or columns could
+ * have a top or bottom margin.
+ */
+void
+nsGrid::GetRowOffsets(int32_t aIndex, nscoord& aTop, nscoord& aBottom, bool aIsHorizontal)
+{
+
+ RebuildIfNeeded();
+
+ nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
+
+ if (row->IsOffsetSet())
+ {
+ aTop = row->mTop;
+ aBottom = row->mBottom;
+ return;
+ }
+
+ // first get the rows top and bottom border and padding
+ nsIFrame* box = row->GetBox();
+
+ // add up all the padding
+ nsMargin margin(0,0,0,0);
+ nsMargin border(0,0,0,0);
+ nsMargin padding(0,0,0,0);
+ nsMargin totalBorderPadding(0,0,0,0);
+ nsMargin totalMargin(0,0,0,0);
+
+ // if there is a box and it's not bogus take its
+ // borders padding into account
+ if (box && !row->mIsBogus)
+ {
+ if (!box->IsXULCollapsed())
+ {
+ // get real border and padding. GetXULBorderAndPadding
+ // is redefined on nsGridRowLeafFrame. If we called it here
+ // we would be in finite recurson.
+ box->GetXULBorder(border);
+ box->GetXULPadding(padding);
+
+ totalBorderPadding += border;
+ totalBorderPadding += padding;
+ }
+
+ // if we are the first or last row
+ // take into account <rows> tags around us
+ // that could have borders or margins.
+ // fortunately they only affect the first
+ // and last row inside the <rows> tag
+
+ totalMargin = GetBoxTotalMargin(box, aIsHorizontal);
+ }
+
+ if (aIsHorizontal) {
+ row->mTop = totalBorderPadding.top;
+ row->mBottom = totalBorderPadding.bottom;
+ row->mTopMargin = totalMargin.top;
+ row->mBottomMargin = totalMargin.bottom;
+ } else {
+ row->mTop = totalBorderPadding.left;
+ row->mBottom = totalBorderPadding.right;
+ row->mTopMargin = totalMargin.left;
+ row->mBottomMargin = totalMargin.right;
+ }
+
+ // if we are the first or last row take into account the top and bottom borders
+ // of each columns.
+
+ // If we are the first row then get the largest top border/padding in
+ // our columns. If that's larger than the rows top border/padding use it.
+
+ // If we are the last row then get the largest bottom border/padding in
+ // our columns. If that's larger than the rows bottom border/padding use it.
+ int32_t firstIndex = 0;
+ int32_t lastIndex = 0;
+ nsGridRow* firstRow = nullptr;
+ nsGridRow* lastRow = nullptr;
+ GetFirstAndLastRow(firstIndex, lastIndex, firstRow, lastRow, aIsHorizontal);
+
+ if (aIndex == firstIndex || aIndex == lastIndex) {
+ nscoord maxTop = 0;
+ nscoord maxBottom = 0;
+
+ // run through the columns. Look at each column
+ // pick the largest top border or bottom border
+ int32_t count = GetColumnCount(aIsHorizontal);
+
+ for (int32_t i=0; i < count; i++)
+ {
+ nsMargin totalChildBorderPadding(0,0,0,0);
+
+ nsGridRow* column = GetColumnAt(i,aIsHorizontal);
+ nsIFrame* box = column->GetBox();
+
+ if (box)
+ {
+ // ignore collapsed children
+ if (!box->IsXULCollapsed())
+ {
+ // include the margin of the columns. To the row
+ // at this point border/padding and margins all added
+ // up to more needed space.
+ margin = GetBoxTotalMargin(box, !aIsHorizontal);
+ // get real border and padding. GetXULBorderAndPadding
+ // is redefined on nsGridRowLeafFrame. If we called it here
+ // we would be in finite recurson.
+ box->GetXULBorder(border);
+ box->GetXULPadding(padding);
+ totalChildBorderPadding += border;
+ totalChildBorderPadding += padding;
+ totalChildBorderPadding += margin;
+ }
+
+ nscoord top;
+ nscoord bottom;
+
+ // pick the largest top margin
+ if (aIndex == firstIndex) {
+ if (aIsHorizontal) {
+ top = totalChildBorderPadding.top;
+ } else {
+ top = totalChildBorderPadding.left;
+ }
+ if (top > maxTop)
+ maxTop = top;
+ }
+
+ // pick the largest bottom margin
+ if (aIndex == lastIndex) {
+ if (aIsHorizontal) {
+ bottom = totalChildBorderPadding.bottom;
+ } else {
+ bottom = totalChildBorderPadding.right;
+ }
+ if (bottom > maxBottom)
+ maxBottom = bottom;
+ }
+
+ }
+
+ // If the biggest top border/padding the columns is larger than this rows top border/padding
+ // the use it.
+ if (aIndex == firstIndex) {
+ if (maxTop > (row->mTop + row->mTopMargin))
+ row->mTop = maxTop - row->mTopMargin;
+ }
+
+ // If the biggest bottom border/padding the columns is larger than this rows bottom border/padding
+ // the use it.
+ if (aIndex == lastIndex) {
+ if (maxBottom > (row->mBottom + row->mBottomMargin))
+ row->mBottom = maxBottom - row->mBottomMargin;
+ }
+ }
+ }
+
+ aTop = row->mTop;
+ aBottom = row->mBottom;
+}
+
+/**
+ * These methods return the preferred, min, max coord for a given row index if
+ * aIsHorizontal is true. If you pass false you will get the inverse.
+ * As if you called GetPrefColumnHeight(aState, index, aPref).
+ */
+nscoord
+nsGrid::GetPrefRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
+{
+ RebuildIfNeeded();
+
+ nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
+
+ if (row->IsXULCollapsed())
+ return 0;
+
+ if (row->IsPrefSet())
+ return row->mPref;
+
+ nsIFrame* box = row->mBox;
+
+ // set in CSS?
+ if (box)
+ {
+ bool widthSet, heightSet;
+ nsSize cssSize(-1, -1);
+ nsIFrame::AddXULPrefSize(box, cssSize, widthSet, heightSet);
+
+ row->mPref = GET_HEIGHT(cssSize, aIsHorizontal);
+
+ // yep do nothing.
+ if (row->mPref != -1)
+ return row->mPref;
+ }
+
+ // get the offsets so they are cached.
+ nscoord top;
+ nscoord bottom;
+ GetRowOffsets(aIndex, top, bottom, aIsHorizontal);
+
+ // is the row bogus? If so then just ask it for its size
+ // it should not be affected by cells in the grid.
+ if (row->mIsBogus)
+ {
+ nsSize size(0,0);
+ if (box)
+ {
+ size = box->GetXULPrefSize(aState);
+ nsBox::AddMargin(box, size);
+ nsGridLayout2::AddOffset(box, size);
+ }
+
+ row->mPref = GET_HEIGHT(size, aIsHorizontal);
+ return row->mPref;
+ }
+
+ nsSize size(0,0);
+
+ nsGridCell* child;
+
+ int32_t count = GetColumnCount(aIsHorizontal);
+
+ for (int32_t i=0; i < count; i++)
+ {
+ if (aIsHorizontal)
+ child = GetCellAt(i,aIndex);
+ else
+ child = GetCellAt(aIndex,i);
+
+ // ignore collapsed children
+ if (!child->IsXULCollapsed())
+ {
+ nsSize childSize = child->GetXULPrefSize(aState);
+
+ nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal);
+ }
+ }
+
+ row->mPref = GET_HEIGHT(size, aIsHorizontal) + top + bottom;
+
+ return row->mPref;
+}
+
+nscoord
+nsGrid::GetMinRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
+{
+ RebuildIfNeeded();
+
+ nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
+
+ if (row->IsXULCollapsed())
+ return 0;
+
+ if (row->IsMinSet())
+ return row->mMin;
+
+ nsIFrame* box = row->mBox;
+
+ // set in CSS?
+ if (box) {
+ bool widthSet, heightSet;
+ nsSize cssSize(-1, -1);
+ nsIFrame::AddXULMinSize(aState, box, cssSize, widthSet, heightSet);
+
+ row->mMin = GET_HEIGHT(cssSize, aIsHorizontal);
+
+ // yep do nothing.
+ if (row->mMin != -1)
+ return row->mMin;
+ }
+
+ // get the offsets so they are cached.
+ nscoord top;
+ nscoord bottom;
+ GetRowOffsets(aIndex, top, bottom, aIsHorizontal);
+
+ // is the row bogus? If so then just ask it for its size
+ // it should not be affected by cells in the grid.
+ if (row->mIsBogus)
+ {
+ nsSize size(0,0);
+ if (box) {
+ size = box->GetXULPrefSize(aState);
+ nsBox::AddMargin(box, size);
+ nsGridLayout2::AddOffset(box, size);
+ }
+
+ row->mMin = GET_HEIGHT(size, aIsHorizontal) + top + bottom;
+ return row->mMin;
+ }
+
+ nsSize size(0,0);
+
+ nsGridCell* child;
+
+ int32_t count = GetColumnCount(aIsHorizontal);
+
+ for (int32_t i=0; i < count; i++)
+ {
+ if (aIsHorizontal)
+ child = GetCellAt(i,aIndex);
+ else
+ child = GetCellAt(aIndex,i);
+
+ // ignore collapsed children
+ if (!child->IsXULCollapsed())
+ {
+ nsSize childSize = child->GetXULMinSize(aState);
+
+ nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal);
+ }
+ }
+
+ row->mMin = GET_HEIGHT(size, aIsHorizontal);
+
+ return row->mMin;
+}
+
+nscoord
+nsGrid::GetMaxRowHeight(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
+{
+ RebuildIfNeeded();
+
+ nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
+
+ if (row->IsXULCollapsed())
+ return 0;
+
+ if (row->IsMaxSet())
+ return row->mMax;
+
+ nsIFrame* box = row->mBox;
+
+ // set in CSS?
+ if (box) {
+ bool widthSet, heightSet;
+ nsSize cssSize(-1, -1);
+ nsIFrame::AddXULMaxSize(box, cssSize, widthSet, heightSet);
+
+ row->mMax = GET_HEIGHT(cssSize, aIsHorizontal);
+
+ // yep do nothing.
+ if (row->mMax != -1)
+ return row->mMax;
+ }
+
+ // get the offsets so they are cached.
+ nscoord top;
+ nscoord bottom;
+ GetRowOffsets(aIndex, top, bottom, aIsHorizontal);
+
+ // is the row bogus? If so then just ask it for its size
+ // it should not be affected by cells in the grid.
+ if (row->mIsBogus)
+ {
+ nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
+ if (box) {
+ size = box->GetXULPrefSize(aState);
+ nsBox::AddMargin(box, size);
+ nsGridLayout2::AddOffset(box, size);
+ }
+
+ row->mMax = GET_HEIGHT(size, aIsHorizontal);
+ return row->mMax;
+ }
+
+ nsSize size(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
+
+ nsGridCell* child;
+
+ int32_t count = GetColumnCount(aIsHorizontal);
+
+ for (int32_t i=0; i < count; i++)
+ {
+ if (aIsHorizontal)
+ child = GetCellAt(i,aIndex);
+ else
+ child = GetCellAt(aIndex,i);
+
+ // ignore collapsed children
+ if (!child->IsXULCollapsed())
+ {
+ nsSize min = child->GetXULMinSize(aState);
+ nsSize childSize = nsBox::BoundsCheckMinMax(min, child->GetXULMaxSize(aState));
+ nsSprocketLayout::AddLargestSize(size, childSize, aIsHorizontal);
+ }
+ }
+
+ row->mMax = GET_HEIGHT(size, aIsHorizontal) + top + bottom;
+
+ return row->mMax;
+}
+
+bool
+nsGrid::IsGrid(nsIFrame* aBox)
+{
+ nsIGridPart* part = GetPartFromBox(aBox);
+ if (!part)
+ return false;
+
+ nsGridLayout2* grid = part->CastToGridLayout();
+
+ if (grid)
+ return true;
+
+ return false;
+}
+
+/**
+ * This get the flexibilty of the row at aIndex. It's not trivial. There are a few
+ * things we need to look at. Specifically we need to see if any <rows> or <columns>
+ * tags are around us. Their flexibilty will affect ours.
+ */
+nscoord
+nsGrid::GetRowFlex(int32_t aIndex, bool aIsHorizontal)
+{
+ RebuildIfNeeded();
+
+ nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
+
+ if (row->IsFlexSet())
+ return row->mFlex;
+
+ nsIFrame* box = row->mBox;
+ row->mFlex = 0;
+
+ if (box) {
+
+ // We need our flex but a inflexible row could be around us. If so
+ // neither are we. However if its the row tag just inside the grid it won't
+ // affect us. We need to do this for this case:
+ // <grid>
+ // <rows>
+ // <rows> // this is not flexible. So our children should not be flexible
+ // <row flex="1"/>
+ // <row flex="1"/>
+ // </rows>
+ // <row/>
+ // </rows>
+ // </grid>
+ //
+ // or..
+ //
+ // <grid>
+ // <rows>
+ // <rows> // this is not flexible. So our children should not be flexible
+ // <rows flex="1">
+ // <row flex="1"/>
+ // <row flex="1"/>
+ // </rows>
+ // <row/>
+ // </rows>
+ // </row>
+ // </grid>
+
+
+ // So here is how it looks
+ //
+ // <grid>
+ // <rows> // parentsParent
+ // <rows> // parent
+ // <row flex="1"/>
+ // <row flex="1"/>
+ // </rows>
+ // <row/>
+ // </rows>
+ // </grid>
+
+ // so the answer is simple: 1) Walk our parent chain. 2) If we find
+ // someone who is not flexible and they aren't the rows immediately in
+ // the grid. 3) Then we are not flexible
+
+ box = GetScrollBox(box);
+ nsIFrame* parent = nsBox::GetParentXULBox(box);
+ nsIFrame* parentsParent=nullptr;
+
+ while(parent)
+ {
+ parent = GetScrollBox(parent);
+ parentsParent = nsBox::GetParentXULBox(parent);
+
+ // if our parents parent is not a grid
+ // the get its flex. If its 0 then we are
+ // not flexible.
+ if (parentsParent) {
+ if (!IsGrid(parentsParent)) {
+ nscoord flex = parent->GetXULFlex();
+ nsIFrame::AddXULFlex(parent, flex);
+ if (flex == 0) {
+ row->mFlex = 0;
+ return row->mFlex;
+ }
+ } else
+ break;
+ }
+
+ parent = parentsParent;
+ }
+
+ // get the row flex.
+ row->mFlex = box->GetXULFlex();
+ nsIFrame::AddXULFlex(box, row->mFlex);
+ }
+
+ return row->mFlex;
+}
+
+void
+nsGrid::SetLargestSize(nsSize& aSize, nscoord aHeight, bool aIsHorizontal)
+{
+ if (aIsHorizontal) {
+ if (aSize.height < aHeight)
+ aSize.height = aHeight;
+ } else {
+ if (aSize.width < aHeight)
+ aSize.width = aHeight;
+ }
+}
+
+void
+nsGrid::SetSmallestSize(nsSize& aSize, nscoord aHeight, bool aIsHorizontal)
+{
+ if (aIsHorizontal) {
+ if (aSize.height > aHeight)
+ aSize.height = aHeight;
+ } else {
+ if (aSize.width < aHeight)
+ aSize.width = aHeight;
+ }
+}
+
+int32_t
+nsGrid::GetRowCount(int32_t aIsHorizontal)
+{
+ RebuildIfNeeded();
+
+ if (aIsHorizontal)
+ return mRowCount;
+ else
+ return mColumnCount;
+}
+
+int32_t
+nsGrid::GetColumnCount(int32_t aIsHorizontal)
+{
+ return GetRowCount(!aIsHorizontal);
+}
+
+/*
+ * A cell in the given row or columns at the given index has had a child added or removed
+ */
+void
+nsGrid::CellAddedOrRemoved(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
+{
+ // TBD see if the cell will fit in our current row. If it will
+ // just add it in.
+ // but for now rebuild everything.
+ if (mMarkingDirty)
+ return;
+
+ NeedsRebuild(aState);
+}
+
+/**
+ * A row or columns at the given index had been added or removed
+ */
+void
+nsGrid::RowAddedOrRemoved(nsBoxLayoutState& aState, int32_t aIndex, bool aIsHorizontal)
+{
+ // TBD see if we have extra room in the table and just add the new row in
+ // for now rebuild the world
+ if (mMarkingDirty)
+ return;
+
+ NeedsRebuild(aState);
+}
+
+/*
+ * Scrollframes are tranparent. If this is given a scrollframe is will return the
+ * frame inside. If there is no scrollframe it does nothing.
+ */
+nsIFrame*
+nsGrid::GetScrolledBox(nsIFrame* aChild)
+{
+ // first see if it is a scrollframe. If so walk down into it and get the scrolled child
+ nsIScrollableFrame *scrollFrame = do_QueryFrame(aChild);
+ if (scrollFrame) {
+ nsIFrame* scrolledFrame = scrollFrame->GetScrolledFrame();
+ NS_ASSERTION(scrolledFrame,"Error no scroll frame!!");
+ return scrolledFrame;
+ }
+
+ return aChild;
+}
+
+/*
+ * Scrollframes are tranparent. If this is given a child in a scrollframe is will return the
+ * scrollframe ourside it. If there is no scrollframe it does nothing.
+ */
+nsIFrame*
+nsGrid::GetScrollBox(nsIFrame* aChild)
+{
+ if (!aChild)
+ return nullptr;
+
+ // get parent
+ nsIFrame* parent = nsBox::GetParentXULBox(aChild);
+
+ // walk up until we find a scrollframe or a part
+ // if it's a scrollframe return it.
+ // if it's a parent then the child passed does not
+ // have a scroll frame immediately wrapped around it.
+ while (parent) {
+ nsIScrollableFrame *scrollFrame = do_QueryFrame(parent);
+ // scrollframe? Yep return it.
+ if (scrollFrame)
+ return parent;
+
+ nsCOMPtr<nsIGridPart> parentGridRow = GetPartFromBox(parent);
+ // if a part then just return the child
+ if (parentGridRow)
+ break;
+
+ parent = nsBox::GetParentXULBox(parent);
+ }
+
+ return aChild;
+}
+
+
+
+#ifdef DEBUG_grid
+void
+nsGrid::PrintCellMap()
+{
+
+ printf("-----Columns------\n");
+ for (int x=0; x < mColumnCount; x++)
+ {
+
+ nsGridRow* column = GetColumnAt(x);
+ printf("%d(pf=%d, mn=%d, mx=%d) ", x, column->mPref, column->mMin, column->mMax);
+ }
+
+ printf("\n-----Rows------\n");
+ for (x=0; x < mRowCount; x++)
+ {
+ nsGridRow* column = GetRowAt(x);
+ printf("%d(pf=%d, mn=%d, mx=%d) ", x, column->mPref, column->mMin, column->mMax);
+ }
+
+ printf("\n");
+
+}
+#endif
diff --git a/layout/xul/grid/nsGrid.h b/layout/xul/grid/nsGrid.h
new file mode 100644
index 000000000..d8726a946
--- /dev/null
+++ b/layout/xul/grid/nsGrid.h
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsGrid_h___
+#define nsGrid_h___
+
+#include "nsStackLayout.h"
+#include "nsIGridPart.h"
+#include "nsCOMPtr.h"
+#include "mozilla/UniquePtr.h"
+
+class nsBoxLayoutState;
+class nsGridCell;
+
+//#define DEBUG_grid 1
+
+/**
+ * The grid data structure, i.e., the grid cellmap.
+ */
+class nsGrid
+{
+public:
+ nsGrid();
+ ~nsGrid();
+
+ nsGridRow* GetColumnAt(int32_t aIndex, bool aIsHorizontal = true);
+ nsGridRow* GetRowAt(int32_t aIndex, bool aIsHorizontal = true);
+ nsGridCell* GetCellAt(int32_t aX, int32_t aY);
+
+ void NeedsRebuild(nsBoxLayoutState& aBoxLayoutState);
+ void RebuildIfNeeded();
+
+ // For all the methods taking an aIsHorizontal parameter:
+ // * When aIsHorizontal is true, the words "rows" and (for
+ // GetColumnCount) "columns" refer to their normal meanings.
+ // * When aIsHorizontal is false, the meanings are flipped.
+ // FIXME: Maybe eliminate GetColumnCount and change aIsHorizontal to
+ // aIsRows? (Calling it horizontal doesn't really make sense because
+ // row groups and columns have vertical orientation, whereas column
+ // groups and rows are horizontal.)
+
+ nsSize GetPrefRowSize(nsBoxLayoutState& aBoxLayoutState, int32_t aRowIndex, bool aIsHorizontal = true);
+ nsSize GetMinRowSize(nsBoxLayoutState& aBoxLayoutState, int32_t aRowIndex, bool aIsHorizontal = true);
+ nsSize GetMaxRowSize(nsBoxLayoutState& aBoxLayoutState, int32_t aRowIndex, bool aIsHorizontal = true);
+ nscoord GetRowFlex(int32_t aRowIndex, bool aIsHorizontal = true);
+
+ nscoord GetPrefRowHeight(nsBoxLayoutState& aBoxLayoutState, int32_t aRowIndex, bool aIsHorizontal = true);
+ nscoord GetMinRowHeight(nsBoxLayoutState& aBoxLayoutState, int32_t aRowIndex, bool aIsHorizontal = true);
+ nscoord GetMaxRowHeight(nsBoxLayoutState& aBoxLayoutState, int32_t aRowIndex, bool aIsHorizontal = true);
+ void GetRowOffsets(int32_t aIndex, nscoord& aTop, nscoord& aBottom, bool aIsHorizontal = true);
+
+ void RowAddedOrRemoved(nsBoxLayoutState& aBoxLayoutState, int32_t aIndex, bool aIsHorizontal = true);
+ void CellAddedOrRemoved(nsBoxLayoutState& aBoxLayoutState, int32_t aIndex, bool aIsHorizontal = true);
+ void DirtyRows(nsIFrame* aRowBox, nsBoxLayoutState& aState);
+#ifdef DEBUG_grid
+ void PrintCellMap();
+#endif
+ int32_t GetExtraColumnCount(bool aIsHorizontal = true);
+ int32_t GetExtraRowCount(bool aIsHorizontal = true);
+
+// accessors
+ void SetBox(nsIFrame* aBox) { mBox = aBox; }
+ nsIFrame* GetBox() { return mBox; }
+ nsIFrame* GetRowsBox() { return mRowsBox; }
+ nsIFrame* GetColumnsBox() { return mColumnsBox; }
+ int32_t GetRowCount(int32_t aIsHorizontal = true);
+ int32_t GetColumnCount(int32_t aIsHorizontal = true);
+
+ static nsIFrame* GetScrolledBox(nsIFrame* aChild);
+ static nsIFrame* GetScrollBox(nsIFrame* aChild);
+ static nsIGridPart* GetPartFromBox(nsIFrame* aBox);
+ void GetFirstAndLastRow(int32_t& aFirstIndex,
+ int32_t& aLastIndex,
+ nsGridRow*& aFirstRow,
+ nsGridRow*& aLastRow,
+ bool aIsHorizontal);
+
+private:
+
+ nsMargin GetBoxTotalMargin(nsIFrame* aBox, bool aIsHorizontal = true);
+
+ void FreeMap();
+ void FindRowsAndColumns(nsIFrame** aRows, nsIFrame** aColumns);
+ mozilla::UniquePtr<nsGridRow[]> BuildRows(nsIFrame* aBox, int32_t aSize,
+ bool aIsHorizontal = true);
+ mozilla::UniquePtr<nsGridCell[]> BuildCellMap(int32_t aRows, int32_t aColumns);
+ void PopulateCellMap(nsGridRow* aRows, nsGridRow* aColumns, int32_t aRowCount, int32_t aColumnCount, bool aIsHorizontal = true);
+ void CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount);
+ void SetLargestSize(nsSize& aSize, nscoord aHeight, bool aIsHorizontal = true);
+ void SetSmallestSize(nsSize& aSize, nscoord aHeight, bool aIsHorizontal = true);
+ bool IsGrid(nsIFrame* aBox);
+
+ // the box that implement the <grid> tag
+ nsIFrame* mBox;
+
+ // an array of row object
+ mozilla::UniquePtr<nsGridRow[]> mRows;
+
+ // an array of columns objects.
+ mozilla::UniquePtr<nsGridRow[]> mColumns;
+
+ // the first in the <grid> that implements the <rows> tag.
+ nsIFrame* mRowsBox;
+
+ // the first in the <grid> that implements the <columns> tag.
+ nsIFrame* mColumnsBox;
+
+ // a flag that is false tells us to rebuild the who grid
+ bool mNeedsRebuild;
+
+ // number of rows and columns as defined by the XUL
+ int32_t mRowCount;
+ int32_t mColumnCount;
+
+ // number of rows and columns that are implied but not
+ // explicitly defined int he XUL
+ int32_t mExtraRowCount;
+ int32_t mExtraColumnCount;
+
+ // x,y array of cells in the rows and columns
+ mozilla::UniquePtr<nsGridCell[]> mCellMap;
+
+ // a flag that when true suppresses all other MarkDirties. This
+ // prevents lots of extra work being done.
+ bool mMarkingDirty;
+};
+
+#endif
+
diff --git a/layout/xul/grid/nsGridCell.cpp b/layout/xul/grid/nsGridCell.cpp
new file mode 100644
index 000000000..c54256297
--- /dev/null
+++ b/layout/xul/grid/nsGridCell.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+#include "nsGridCell.h"
+#include "nsFrame.h"
+#include "nsBox.h"
+#include "nsGridLayout2.h"
+
+
+nsGridCell::nsGridCell():mBoxInColumn(nullptr),mBoxInRow(nullptr)
+{
+ MOZ_COUNT_CTOR(nsGridCell);
+}
+
+nsGridCell::~nsGridCell()
+{
+ MOZ_COUNT_DTOR(nsGridCell);
+}
+
+nsSize
+nsGridCell::GetXULPrefSize(nsBoxLayoutState& aState)
+{
+ nsSize sum(0,0);
+
+ // take our 2 children and add them up.
+ // we are as wide as the widest child plus its left offset
+ // we are tall as the tallest child plus its top offset
+
+ if (mBoxInColumn) {
+ nsSize pref = mBoxInColumn->GetXULPrefSize(aState);
+
+ nsBox::AddMargin(mBoxInColumn, pref);
+ nsGridLayout2::AddOffset(mBoxInColumn, pref);
+
+ nsBoxLayout::AddLargestSize(sum, pref);
+ }
+
+ if (mBoxInRow) {
+ nsSize pref = mBoxInRow->GetXULPrefSize(aState);
+
+ nsBox::AddMargin(mBoxInRow, pref);
+ nsGridLayout2::AddOffset(mBoxInRow, pref);
+
+ nsBoxLayout::AddLargestSize(sum, pref);
+ }
+
+ return sum;
+}
+
+nsSize
+nsGridCell::GetXULMinSize(nsBoxLayoutState& aState)
+{
+ nsSize sum(0, 0);
+
+ // take our 2 children and add them up.
+ // we are as wide as the widest child plus its left offset
+ // we are tall as the tallest child plus its top offset
+
+ if (mBoxInColumn) {
+ nsSize min = mBoxInColumn->GetXULMinSize(aState);
+
+ nsBox::AddMargin(mBoxInColumn, min);
+ nsGridLayout2::AddOffset(mBoxInColumn, min);
+
+ nsBoxLayout::AddLargestSize(sum, min);
+ }
+
+ if (mBoxInRow) {
+ nsSize min = mBoxInRow->GetXULMinSize(aState);
+
+ nsBox::AddMargin(mBoxInRow, min);
+ nsGridLayout2::AddOffset(mBoxInRow, min);
+
+ nsBoxLayout::AddLargestSize(sum, min);
+ }
+
+ return sum;
+}
+
+nsSize
+nsGridCell::GetXULMaxSize(nsBoxLayoutState& aState)
+{
+ nsSize sum(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
+
+ // take our 2 children and add them up.
+ // we are as wide as the smallest child plus its left offset
+ // we are tall as the shortest child plus its top offset
+
+ if (mBoxInColumn) {
+ nsSize max = mBoxInColumn->GetXULMaxSize(aState);
+
+ nsBox::AddMargin(mBoxInColumn, max);
+ nsGridLayout2::AddOffset(mBoxInColumn, max);
+
+ nsBoxLayout::AddSmallestSize(sum, max);
+ }
+
+ if (mBoxInRow) {
+ nsSize max = mBoxInRow->GetXULMaxSize(aState);
+
+ nsBox::AddMargin(mBoxInRow, max);
+ nsGridLayout2::AddOffset(mBoxInRow, max);
+
+ nsBoxLayout::AddSmallestSize(sum, max);
+ }
+
+ return sum;
+}
+
+
+bool
+nsGridCell::IsXULCollapsed()
+{
+ return ((mBoxInColumn && mBoxInColumn->IsXULCollapsed()) ||
+ (mBoxInRow && mBoxInRow->IsXULCollapsed()));
+}
+
+
diff --git a/layout/xul/grid/nsGridCell.h b/layout/xul/grid/nsGridCell.h
new file mode 100644
index 000000000..eca652776
--- /dev/null
+++ b/layout/xul/grid/nsGridCell.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+
+ Author:
+ Eric D Vaughan
+
+**/
+
+#ifndef nsGridCell_h___
+#define nsGridCell_h___
+
+#include "mozilla/Attributes.h"
+
+class nsBoxLayoutState;
+struct nsSize;
+class nsIFrame;
+
+/*
+ * Grid cell is what makes up the cellmap in the grid. Each GridCell contains
+ * 2 pointers. One to the matching box in the columns and one to the matching box
+ * in the rows. Remember that you can put content in both rows and columns.
+ * When asked for preferred/min/max sizes it works like a stack and takes the
+ * biggest sizes.
+ */
+
+class nsGridCell final
+{
+public:
+ nsGridCell();
+ ~nsGridCell();
+
+ nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState);
+ nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState);
+ nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState);
+ bool IsXULCollapsed();
+
+// accessors
+ nsIFrame* GetBoxInColumn() { return mBoxInColumn; }
+ nsIFrame* GetBoxInRow() { return mBoxInRow; }
+ void SetBoxInRow(nsIFrame* aBox) { mBoxInRow = aBox; }
+ void SetBoxInColumn(nsIFrame* aBox) { mBoxInColumn = aBox; }
+
+private:
+ nsIFrame* mBoxInColumn;
+ nsIFrame* mBoxInRow;
+};
+
+#endif
+
diff --git a/layout/xul/grid/nsGridLayout2.cpp b/layout/xul/grid/nsGridLayout2.cpp
new file mode 100644
index 000000000..75408dce3
--- /dev/null
+++ b/layout/xul/grid/nsGridLayout2.cpp
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+#include "nsGridLayout2.h"
+#include "nsGridRowGroupLayout.h"
+#include "nsGridRow.h"
+#include "nsBox.h"
+#include "nsIScrollableFrame.h"
+#include "nsSprocketLayout.h"
+#include "mozilla/ReflowInput.h"
+
+nsresult
+NS_NewGridLayout2( nsIPresShell* aPresShell, nsBoxLayout** aNewLayout)
+{
+ *aNewLayout = new nsGridLayout2(aPresShell);
+ NS_IF_ADDREF(*aNewLayout);
+
+ return NS_OK;
+
+}
+
+nsGridLayout2::nsGridLayout2(nsIPresShell* aPresShell):nsStackLayout()
+{
+}
+
+nsGridLayout2::~nsGridLayout2()
+{
+}
+
+// static
+void
+nsGridLayout2::AddOffset(nsIFrame* aChild, nsSize& aSize)
+{
+ nsMargin offset;
+ GetOffset(aChild, offset);
+ aSize.width += offset.left;
+ aSize.height += offset.top;
+}
+
+NS_IMETHODIMP
+nsGridLayout2::XULLayout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
+{
+ // XXX This should be set a better way!
+ mGrid.SetBox(aBox);
+ NS_ASSERTION(aBox->GetXULLayoutManager() == this, "setting incorrect box");
+
+ nsresult rv = nsStackLayout::XULLayout(aBox, aBoxLayoutState);
+#ifdef DEBUG_grid
+ mGrid.PrintCellMap();
+#endif
+ return rv;
+}
+
+void
+nsGridLayout2::IntrinsicISizesDirty(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
+{
+ nsStackLayout::IntrinsicISizesDirty(aBox, aBoxLayoutState);
+ // XXXldb We really don't need to do all the work that NeedsRebuild
+ // does; we just need to mark intrinsic widths dirty on the
+ // (row/column)(s/-groups).
+ mGrid.NeedsRebuild(aBoxLayoutState);
+}
+
+nsGrid*
+nsGridLayout2::GetGrid(nsIFrame* aBox, int32_t* aIndex, nsGridRowLayout* aRequestor)
+{
+ // XXX This should be set a better way!
+ mGrid.SetBox(aBox);
+ NS_ASSERTION(aBox->GetXULLayoutManager() == this, "setting incorrect box");
+ return &mGrid;
+}
+
+void
+nsGridLayout2::AddWidth(nsSize& aSize, nscoord aSize2, bool aIsHorizontal)
+{
+ nscoord& size = GET_WIDTH(aSize, aIsHorizontal);
+
+ if (size != NS_INTRINSICSIZE) {
+ if (aSize2 == NS_INTRINSICSIZE)
+ size = NS_INTRINSICSIZE;
+ else
+ size += aSize2;
+ }
+}
+
+nsSize
+nsGridLayout2::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ nsSize minSize = nsStackLayout::GetXULMinSize(aBox, aState);
+
+ // if there are no <rows> tags that will sum up our columns,
+ // sum up our columns here.
+ nsSize total(0,0);
+ nsIFrame* rowsBox = mGrid.GetRowsBox();
+ nsIFrame* columnsBox = mGrid.GetColumnsBox();
+ if (!rowsBox || !columnsBox) {
+ if (!rowsBox) {
+ // max height is the sum of our rows
+ int32_t rows = mGrid.GetRowCount();
+ for (int32_t i=0; i < rows; i++)
+ {
+ nscoord height = mGrid.GetMinRowHeight(aState, i, true);
+ AddWidth(total, height, false); // AddHeight
+ }
+ }
+
+ if (!columnsBox) {
+ // max height is the sum of our rows
+ int32_t columns = mGrid.GetColumnCount();
+ for (int32_t i=0; i < columns; i++)
+ {
+ nscoord width = mGrid.GetMinRowHeight(aState, i, false);
+ AddWidth(total, width, true); // AddWidth
+ }
+ }
+
+ AddMargin(aBox, total);
+ AddOffset(aBox, total);
+ AddLargestSize(minSize, total);
+ }
+
+ return minSize;
+}
+
+nsSize
+nsGridLayout2::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ nsSize pref = nsStackLayout::GetXULPrefSize(aBox, aState);
+
+ // if there are no <rows> tags that will sum up our columns,
+ // sum up our columns here.
+ nsSize total(0,0);
+ nsIFrame* rowsBox = mGrid.GetRowsBox();
+ nsIFrame* columnsBox = mGrid.GetColumnsBox();
+ if (!rowsBox || !columnsBox) {
+ if (!rowsBox) {
+ // max height is the sum of our rows
+ int32_t rows = mGrid.GetRowCount();
+ for (int32_t i=0; i < rows; i++)
+ {
+ nscoord height = mGrid.GetPrefRowHeight(aState, i, true);
+ AddWidth(total, height, false); // AddHeight
+ }
+ }
+
+ if (!columnsBox) {
+ // max height is the sum of our rows
+ int32_t columns = mGrid.GetColumnCount();
+ for (int32_t i=0; i < columns; i++)
+ {
+ nscoord width = mGrid.GetPrefRowHeight(aState, i, false);
+ AddWidth(total, width, true); // AddWidth
+ }
+ }
+
+ AddMargin(aBox, total);
+ AddOffset(aBox, total);
+ AddLargestSize(pref, total);
+ }
+
+ return pref;
+}
+
+nsSize
+nsGridLayout2::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ nsSize maxSize = nsStackLayout::GetXULMaxSize(aBox, aState);
+
+ // if there are no <rows> tags that will sum up our columns,
+ // sum up our columns here.
+ nsSize total(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
+ nsIFrame* rowsBox = mGrid.GetRowsBox();
+ nsIFrame* columnsBox = mGrid.GetColumnsBox();
+ if (!rowsBox || !columnsBox) {
+ if (!rowsBox) {
+ total.height = 0;
+ // max height is the sum of our rows
+ int32_t rows = mGrid.GetRowCount();
+ for (int32_t i=0; i < rows; i++)
+ {
+ nscoord height = mGrid.GetMaxRowHeight(aState, i, true);
+ AddWidth(total, height, false); // AddHeight
+ }
+ }
+
+ if (!columnsBox) {
+ total.width = 0;
+ // max height is the sum of our rows
+ int32_t columns = mGrid.GetColumnCount();
+ for (int32_t i=0; i < columns; i++)
+ {
+ nscoord width = mGrid.GetMaxRowHeight(aState, i, false);
+ AddWidth(total, width, true); // AddWidth
+ }
+ }
+
+ AddMargin(aBox, total);
+ AddOffset(aBox, total);
+ AddSmallestSize(maxSize, total);
+ }
+
+ return maxSize;
+}
+
+int32_t
+nsGridLayout2::BuildRows(nsIFrame* aBox, nsGridRow* aRows)
+{
+ if (aBox) {
+ aRows[0].Init(aBox, true);
+ return 1;
+ }
+ return 0;
+}
+
+nsMargin
+nsGridLayout2::GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal)
+{
+ nsMargin margin(0,0,0,0);
+ return margin;
+}
+
+void
+nsGridLayout2::ChildrenInserted(nsIFrame* aBox, nsBoxLayoutState& aState,
+ nsIFrame* aPrevBox,
+ const nsFrameList::Slice& aNewChildren)
+{
+ mGrid.NeedsRebuild(aState);
+}
+
+void
+nsGridLayout2::ChildrenAppended(nsIFrame* aBox, nsBoxLayoutState& aState,
+ const nsFrameList::Slice& aNewChildren)
+{
+ mGrid.NeedsRebuild(aState);
+}
+
+void
+nsGridLayout2::ChildrenRemoved(nsIFrame* aBox, nsBoxLayoutState& aState,
+ nsIFrame* aChildList)
+{
+ mGrid.NeedsRebuild(aState);
+}
+
+void
+nsGridLayout2::ChildrenSet(nsIFrame* aBox, nsBoxLayoutState& aState,
+ nsIFrame* aChildList)
+{
+ mGrid.NeedsRebuild(aState);
+}
+
+NS_IMPL_ADDREF_INHERITED(nsGridLayout2, nsStackLayout)
+NS_IMPL_RELEASE_INHERITED(nsGridLayout2, nsStackLayout)
+
+NS_INTERFACE_MAP_BEGIN(nsGridLayout2)
+ NS_INTERFACE_MAP_ENTRY(nsIGridPart)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGridPart)
+NS_INTERFACE_MAP_END_INHERITING(nsStackLayout)
diff --git a/layout/xul/grid/nsGridLayout2.h b/layout/xul/grid/nsGridLayout2.h
new file mode 100644
index 000000000..eb696faf8
--- /dev/null
+++ b/layout/xul/grid/nsGridLayout2.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsGridLayout2_h___
+#define nsGridLayout2_h___
+
+#include "mozilla/Attributes.h"
+#include "nsStackLayout.h"
+#include "nsIGridPart.h"
+#include "nsCoord.h"
+#include "nsGrid.h"
+
+class nsGridRowGroupLayout;
+class nsGridRowLayout;
+class nsGridRow;
+class nsBoxLayoutState;
+
+/**
+ * The nsBoxLayout implementation for a grid.
+ */
+class nsGridLayout2 final : public nsStackLayout,
+ public nsIGridPart
+{
+public:
+
+ friend nsresult NS_NewGridLayout2(nsIPresShell* aPresShell, nsBoxLayout** aNewLayout);
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_IMETHOD XULLayout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual void IntrinsicISizesDirty(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+
+ virtual nsGridRowGroupLayout* CastToRowGroupLayout() override { return nullptr; }
+ virtual nsGridLayout2* CastToGridLayout() override { return this; }
+ virtual nsGrid* GetGrid(nsIFrame* aBox, int32_t* aIndex, nsGridRowLayout* aRequestor=nullptr) override;
+ virtual nsIGridPart* GetParentGridPart(nsIFrame* aBox, nsIFrame** aParentBox) override {
+ NS_NOTREACHED("Should not be called"); return nullptr;
+ }
+ virtual nsSize GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual nsSize GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual nsSize GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual void CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount) override { aRowCount++; }
+ virtual void DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState) override { }
+ virtual int32_t BuildRows(nsIFrame* aBox, nsGridRow* aRows) override;
+ virtual nsMargin GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal) override;
+ virtual Type GetType() override { return eGrid; }
+ virtual void ChildrenInserted(nsIFrame* aBox, nsBoxLayoutState& aState,
+ nsIFrame* aPrevBox,
+ const nsFrameList::Slice& aNewChildren) override;
+ virtual void ChildrenAppended(nsIFrame* aBox, nsBoxLayoutState& aState,
+ const nsFrameList::Slice& aNewChildren) override;
+ virtual void ChildrenRemoved(nsIFrame* aBox, nsBoxLayoutState& aState,
+ nsIFrame* aChildList) override;
+ virtual void ChildrenSet(nsIFrame* aBox, nsBoxLayoutState& aState,
+ nsIFrame* aChildList) override;
+
+ virtual nsIGridPart* AsGridPart() override { return this; }
+
+ static void AddOffset(nsIFrame* aChild, nsSize& aSize);
+
+protected:
+
+ explicit nsGridLayout2(nsIPresShell* aShell);
+ virtual ~nsGridLayout2();
+ nsGrid mGrid;
+
+private:
+ void AddWidth(nsSize& aSize, nscoord aSize2, bool aIsHorizontal);
+
+
+}; // class nsGridLayout2
+
+
+#endif
+
diff --git a/layout/xul/grid/nsGridRow.cpp b/layout/xul/grid/nsGridRow.cpp
new file mode 100644
index 000000000..2a2a64016
--- /dev/null
+++ b/layout/xul/grid/nsGridRow.cpp
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+#include "nsGridRow.h"
+#include "nsBoxLayoutState.h"
+#include "nsIFrame.h"
+
+nsGridRow::nsGridRow():mIsBogus(false),
+ mBox(nullptr),
+ mFlex(-1),
+ mPref(-1),
+ mMin(-1),
+ mMax(-1),
+ mTop(-1),
+ mBottom(-1),
+ mTopMargin(0),
+ mBottomMargin(0)
+
+{
+ MOZ_COUNT_CTOR(nsGridRow);
+}
+
+void
+nsGridRow::Init(nsIFrame* aBox, bool aIsBogus)
+{
+ mBox = aBox;
+ mIsBogus = aIsBogus;
+ mFlex = -1;
+ mPref = -1;
+ mMin = -1;
+ mMax = -1;
+ mTop = -1;
+ mBottom = -1;
+ mTopMargin = 0;
+ mBottomMargin = 0;
+}
+
+nsGridRow::~nsGridRow()
+{
+ MOZ_COUNT_DTOR(nsGridRow);
+}
+
+bool
+nsGridRow::IsXULCollapsed()
+{
+ return mBox && mBox->IsXULCollapsed();
+}
+
diff --git a/layout/xul/grid/nsGridRow.h b/layout/xul/grid/nsGridRow.h
new file mode 100644
index 000000000..a5bc39158
--- /dev/null
+++ b/layout/xul/grid/nsGridRow.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+
+ Author:
+ Eric D Vaughan
+
+**/
+
+#ifndef nsGridRow_h___
+#define nsGridRow_h___
+
+#include "nsCoord.h"
+
+class nsIFrame;
+
+/**
+ * The row (or column) data structure in the grid cellmap.
+ */
+class nsGridRow
+{
+public:
+ nsGridRow();
+ ~nsGridRow();
+
+ void Init(nsIFrame* aBox, bool aIsBogus);
+
+// accessors
+ nsIFrame* GetBox() { return mBox; }
+ bool IsPrefSet() { return (mPref != -1); }
+ bool IsMinSet() { return (mMin != -1); }
+ bool IsMaxSet() { return (mMax != -1); }
+ bool IsFlexSet() { return (mFlex != -1); }
+ bool IsOffsetSet() { return (mTop != -1 && mBottom != -1); }
+ bool IsXULCollapsed();
+
+public:
+
+ bool mIsBogus;
+ nsIFrame* mBox;
+ nscoord mFlex;
+ nscoord mPref;
+ nscoord mMin;
+ nscoord mMax;
+ nscoord mTop;
+ nscoord mBottom;
+ nscoord mTopMargin;
+ nscoord mBottomMargin;
+
+};
+
+
+#endif
+
diff --git a/layout/xul/grid/nsGridRowGroupFrame.cpp b/layout/xul/grid/nsGridRowGroupFrame.cpp
new file mode 100644
index 000000000..5b72d3753
--- /dev/null
+++ b/layout/xul/grid/nsGridRowGroupFrame.cpp
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+#include "nsGridRowGroupFrame.h"
+#include "nsGridRowLeafLayout.h"
+#include "nsGridRow.h"
+#include "nsBoxLayoutState.h"
+#include "nsGridLayout2.h"
+
+already_AddRefed<nsBoxLayout> NS_NewGridRowGroupLayout();
+
+nsIFrame*
+NS_NewGridRowGroupFrame(nsIPresShell* aPresShell,
+ nsStyleContext* aContext)
+{
+ nsCOMPtr<nsBoxLayout> layout = NS_NewGridRowGroupLayout();
+ return new (aPresShell) nsGridRowGroupFrame(aContext, layout);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(nsGridRowGroupFrame)
+
+
+/**
+ * This is redefined because row groups have a funny property. If they are flexible
+ * then their flex must be equal to the sum of their children's flexes.
+ */
+nscoord
+nsGridRowGroupFrame::GetXULFlex()
+{
+ // if we are flexible out flexibility is determined by our columns.
+ // so first get the our flex. If not 0 then our flex is the sum of
+ // our columns flexes.
+
+ if (!DoesNeedRecalc(mFlex))
+ return mFlex;
+
+ if (nsBoxFrame::GetXULFlex() == 0)
+ return 0;
+
+ // ok we are flexible add up our children
+ nscoord totalFlex = 0;
+ nsIFrame* child = nsBox::GetChildXULBox(this);
+ while (child)
+ {
+ totalFlex += child->GetXULFlex();
+ child = GetNextXULBox(child);
+ }
+
+ mFlex = totalFlex;
+
+ return totalFlex;
+}
+
+
diff --git a/layout/xul/grid/nsGridRowGroupFrame.h b/layout/xul/grid/nsGridRowGroupFrame.h
new file mode 100644
index 000000000..f367e2121
--- /dev/null
+++ b/layout/xul/grid/nsGridRowGroupFrame.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+
+ Eric D Vaughan
+ A frame that can have multiple children. Only one child may be displayed at one time. So the
+ can be flipped though like a deck of cards.
+
+**/
+
+#ifndef nsGridRowGroupFrame_h___
+#define nsGridRowGroupFrame_h___
+
+#include "mozilla/Attributes.h"
+#include "nsBoxFrame.h"
+
+/**
+ * A frame representing a grid row (or column) group, which is usually
+ * an element that is a child of a grid and contains all the rows (or
+ * all the columns). However, multiple levels of groups are allowed, so
+ * the parent or child could instead be another group.
+ */
+class nsGridRowGroupFrame : public nsBoxFrame
+{
+public:
+ NS_DECL_FRAMEARENA_HELPERS
+
+#ifdef DEBUG_FRAME_DUMP
+ virtual nsresult GetFrameName(nsAString& aResult) const override
+ {
+ return MakeFrameName(NS_LITERAL_STRING("nsGridRowGroup"), aResult);
+ }
+#endif
+
+ nsGridRowGroupFrame(nsStyleContext* aContext,
+ nsBoxLayout* aLayoutManager):
+ nsBoxFrame(aContext, false, aLayoutManager) {}
+
+ virtual nscoord GetXULFlex() override;
+
+}; // class nsGridRowGroupFrame
+
+
+
+#endif
+
diff --git a/layout/xul/grid/nsGridRowGroupLayout.cpp b/layout/xul/grid/nsGridRowGroupLayout.cpp
new file mode 100644
index 000000000..1c600cef5
--- /dev/null
+++ b/layout/xul/grid/nsGridRowGroupLayout.cpp
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+
+/*
+ * The nsGridRowGroupLayout implements the <rows> or <columns> tag in a grid.
+ */
+
+#include "nsGridRowGroupLayout.h"
+#include "nsCOMPtr.h"
+#include "nsIScrollableFrame.h"
+#include "nsBox.h"
+#include "nsBoxLayoutState.h"
+#include "nsGridLayout2.h"
+#include "nsGridRow.h"
+#include "mozilla/ReflowInput.h"
+
+already_AddRefed<nsBoxLayout> NS_NewGridRowGroupLayout()
+{
+ RefPtr<nsBoxLayout> layout = new nsGridRowGroupLayout();
+ return layout.forget();
+}
+
+nsGridRowGroupLayout::nsGridRowGroupLayout():nsGridRowLayout(), mRowCount(0)
+{
+}
+
+nsGridRowGroupLayout::~nsGridRowGroupLayout()
+{
+}
+
+void
+nsGridRowGroupLayout::ChildAddedOrRemoved(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ int32_t index = 0;
+ nsGrid* grid = GetGrid(aBox, &index);
+ bool isHorizontal = IsXULHorizontal(aBox);
+
+ if (grid)
+ grid->RowAddedOrRemoved(aState, index, isHorizontal);
+}
+
+void
+nsGridRowGroupLayout::AddWidth(nsSize& aSize, nscoord aSize2, bool aIsHorizontal)
+{
+ nscoord& size = GET_WIDTH(aSize, aIsHorizontal);
+
+ if (size == NS_INTRINSICSIZE || aSize2 == NS_INTRINSICSIZE)
+ size = NS_INTRINSICSIZE;
+ else
+ size += aSize2;
+}
+
+nsSize
+nsGridRowGroupLayout::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ nsSize vpref = nsGridRowLayout::GetXULPrefSize(aBox, aState);
+
+
+ /* It is possible that we could have some extra columns. This is when less columns in XUL were
+ * defined that needed. And example might be a grid with 3 defined columns but a row with 4 cells in
+ * it. We would need an extra column to make the grid work. But because that extra column does not
+ * have a box associated with it we must add its size in manually. Remember we could have extra rows
+ * as well.
+ */
+
+ int32_t index = 0;
+ nsGrid* grid = GetGrid(aBox, &index);
+
+ if (grid)
+ {
+ // make sure we add in extra columns sizes as well
+ bool isHorizontal = IsXULHorizontal(aBox);
+ int32_t extraColumns = grid->GetExtraColumnCount(isHorizontal);
+ int32_t start = grid->GetColumnCount(isHorizontal) - grid->GetExtraColumnCount(isHorizontal);
+ for (int32_t i=0; i < extraColumns; i++)
+ {
+ nscoord pref =
+ grid->GetPrefRowHeight(aState, i+start, !isHorizontal); // GetPrefColumnWidth
+
+ AddWidth(vpref, pref, isHorizontal);
+ }
+ }
+
+ return vpref;
+}
+
+nsSize
+nsGridRowGroupLayout::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ nsSize maxSize = nsGridRowLayout::GetXULMaxSize(aBox, aState);
+
+ int32_t index = 0;
+ nsGrid* grid = GetGrid(aBox, &index);
+
+ if (grid)
+ {
+ // make sure we add in extra columns sizes as well
+ bool isHorizontal = IsXULHorizontal(aBox);
+ int32_t extraColumns = grid->GetExtraColumnCount(isHorizontal);
+ int32_t start = grid->GetColumnCount(isHorizontal) - grid->GetExtraColumnCount(isHorizontal);
+ for (int32_t i=0; i < extraColumns; i++)
+ {
+ nscoord max =
+ grid->GetMaxRowHeight(aState, i+start, !isHorizontal); // GetMaxColumnWidth
+
+ AddWidth(maxSize, max, isHorizontal);
+ }
+ }
+
+ return maxSize;
+}
+
+nsSize
+nsGridRowGroupLayout::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ nsSize minSize = nsGridRowLayout::GetXULMinSize(aBox, aState);
+
+ int32_t index = 0;
+ nsGrid* grid = GetGrid(aBox, &index);
+
+ if (grid)
+ {
+ // make sure we add in extra columns sizes as well
+ bool isHorizontal = IsXULHorizontal(aBox);
+ int32_t extraColumns = grid->GetExtraColumnCount(isHorizontal);
+ int32_t start = grid->GetColumnCount(isHorizontal) - grid->GetExtraColumnCount(isHorizontal);
+ for (int32_t i=0; i < extraColumns; i++)
+ {
+ nscoord min =
+ grid->GetMinRowHeight(aState, i+start, !isHorizontal); // GetMinColumnWidth
+ AddWidth(minSize, min, isHorizontal);
+ }
+ }
+
+ return minSize;
+}
+
+/*
+ * Run down through our children dirtying them recursively.
+ */
+void
+nsGridRowGroupLayout::DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ if (aBox) {
+ // mark us dirty
+ // XXXldb We probably don't want to walk up the ancestor chain
+ // calling MarkIntrinsicISizesDirty for every row group.
+ aState.PresShell()->FrameNeedsReflow(aBox, nsIPresShell::eTreeChange,
+ NS_FRAME_IS_DIRTY);
+ nsIFrame* child = nsBox::GetChildXULBox(aBox);
+
+ while(child) {
+
+ // walk into scrollframes
+ nsIFrame* deepChild = nsGrid::GetScrolledBox(child);
+
+ // walk into other monuments
+ nsIGridPart* monument = nsGrid::GetPartFromBox(deepChild);
+ if (monument)
+ monument->DirtyRows(deepChild, aState);
+
+ child = nsBox::GetNextXULBox(child);
+ }
+ }
+}
+
+
+void
+nsGridRowGroupLayout::CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount)
+{
+ if (aBox) {
+ int32_t startCount = aRowCount;
+
+ nsIFrame* child = nsBox::GetChildXULBox(aBox);
+
+ while(child) {
+
+ // first see if it is a scrollframe. If so walk down into it and get the scrolled child
+ nsIFrame* deepChild = nsGrid::GetScrolledBox(child);
+
+ nsIGridPart* monument = nsGrid::GetPartFromBox(deepChild);
+ if (monument) {
+ monument->CountRowsColumns(deepChild, aRowCount, aComputedColumnCount);
+ child = nsBox::GetNextXULBox(child);
+ deepChild = child;
+ continue;
+ }
+
+ child = nsBox::GetNextXULBox(child);
+
+ // if not a monument. Then count it. It will be a bogus row
+ aRowCount++;
+ }
+
+ mRowCount = aRowCount - startCount;
+ }
+}
+
+
+/**
+ * Fill out the given row structure recursively
+ */
+int32_t
+nsGridRowGroupLayout::BuildRows(nsIFrame* aBox, nsGridRow* aRows)
+{
+ int32_t rowCount = 0;
+
+ if (aBox) {
+ nsIFrame* child = nsBox::GetChildXULBox(aBox);
+
+ while(child) {
+
+ // first see if it is a scrollframe. If so walk down into it and get the scrolled child
+ nsIFrame* deepChild = nsGrid::GetScrolledBox(child);
+
+ nsIGridPart* monument = nsGrid::GetPartFromBox(deepChild);
+ if (monument) {
+ rowCount += monument->BuildRows(deepChild, &aRows[rowCount]);
+ child = nsBox::GetNextXULBox(child);
+ deepChild = child;
+ continue;
+ }
+
+ aRows[rowCount].Init(child, true);
+
+ child = nsBox::GetNextXULBox(child);
+
+ // if not a monument. Then count it. It will be a bogus row
+ rowCount++;
+ }
+ }
+
+ return rowCount;
+}
+
+nsMargin
+nsGridRowGroupLayout::GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal)
+{
+ // group have border and padding added to the total margin
+
+ nsMargin margin = nsGridRowLayout::GetTotalMargin(aBox, aIsHorizontal);
+
+ // make sure we have the scrollframe on the outside if it has one.
+ // that's where the border is.
+ aBox = nsGrid::GetScrollBox(aBox);
+
+ // add our border/padding to it
+ nsMargin borderPadding(0,0,0,0);
+ aBox->GetXULBorderAndPadding(borderPadding);
+ margin += borderPadding;
+
+ return margin;
+}
+
+
diff --git a/layout/xul/grid/nsGridRowGroupLayout.h b/layout/xul/grid/nsGridRowGroupLayout.h
new file mode 100644
index 000000000..07f2aa1eb
--- /dev/null
+++ b/layout/xul/grid/nsGridRowGroupLayout.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+
+ Author:
+ Eric D Vaughan
+
+**/
+
+#ifndef nsGridRowGroupLayout_h___
+#define nsGridRowGroupLayout_h___
+
+#include "mozilla/Attributes.h"
+#include "nsGridRowLayout.h"
+
+/**
+ * The nsBoxLayout implementation for nsGridRowGroupFrame.
+ */
+class nsGridRowGroupLayout : public nsGridRowLayout
+{
+public:
+
+ friend already_AddRefed<nsBoxLayout> NS_NewGridRowGroupLayout();
+
+ virtual nsGridRowGroupLayout* CastToRowGroupLayout() override { return this; }
+ virtual nsSize GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual nsSize GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual nsSize GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual void CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount) override;
+ virtual void DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState) override;
+ virtual int32_t BuildRows(nsIFrame* aBox, nsGridRow* aRows) override;
+ virtual nsMargin GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal) override;
+ virtual int32_t GetRowCount() override { return mRowCount; }
+ virtual Type GetType() override { return eRowGroup; }
+
+protected:
+ nsGridRowGroupLayout();
+ virtual ~nsGridRowGroupLayout();
+
+ virtual void ChildAddedOrRemoved(nsIFrame* aBox, nsBoxLayoutState& aState) override;
+ static void AddWidth(nsSize& aSize, nscoord aSize2, bool aIsHorizontal);
+
+private:
+ int32_t mRowCount;
+};
+
+#endif
+
diff --git a/layout/xul/grid/nsGridRowLayout.cpp b/layout/xul/grid/nsGridRowLayout.cpp
new file mode 100644
index 000000000..a658e088e
--- /dev/null
+++ b/layout/xul/grid/nsGridRowLayout.cpp
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+#include "nsGridRowLayout.h"
+#include "nsBoxLayoutState.h"
+#include "nsIScrollableFrame.h"
+#include "nsBox.h"
+#include "nsStackLayout.h"
+#include "nsGrid.h"
+
+nsGridRowLayout::nsGridRowLayout():nsSprocketLayout()
+{
+}
+
+nsGridRowLayout::~nsGridRowLayout()
+{
+}
+
+void
+nsGridRowLayout::ChildrenInserted(nsIFrame* aBox, nsBoxLayoutState& aState,
+ nsIFrame* aPrevBox,
+ const nsFrameList::Slice& aNewChildren)
+{
+ ChildAddedOrRemoved(aBox, aState);
+}
+
+void
+nsGridRowLayout::ChildrenAppended(nsIFrame* aBox, nsBoxLayoutState& aState,
+ const nsFrameList::Slice& aNewChildren)
+{
+ ChildAddedOrRemoved(aBox, aState);
+}
+
+void
+nsGridRowLayout::ChildrenRemoved(nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChildList)
+{
+ ChildAddedOrRemoved(aBox, aState);
+}
+
+void
+nsGridRowLayout::ChildrenSet(nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChildList)
+{
+ ChildAddedOrRemoved(aBox, aState);
+}
+
+nsIGridPart*
+nsGridRowLayout::GetParentGridPart(nsIFrame* aBox, nsIFrame** aParentBox)
+{
+ // go up and find our parent gridRow. Skip and non gridRow
+ // parents.
+ *aParentBox = nullptr;
+
+ // walk up through any scrollboxes
+ aBox = nsGrid::GetScrollBox(aBox);
+
+ // get the parent
+ if (aBox)
+ aBox = nsBox::GetParentXULBox(aBox);
+
+ if (aBox)
+ {
+ nsIGridPart* parentGridRow = nsGrid::GetPartFromBox(aBox);
+ if (parentGridRow && parentGridRow->CanContain(this)) {
+ *aParentBox = aBox;
+ return parentGridRow;
+ }
+ }
+
+ return nullptr;
+}
+
+
+nsGrid*
+nsGridRowLayout::GetGrid(nsIFrame* aBox, int32_t* aIndex, nsGridRowLayout* aRequestor)
+{
+
+ if (aRequestor == nullptr)
+ {
+ nsIFrame* parentBox; // nsIFrame is implemented by nsIFrame and is not refcounted.
+ nsIGridPart* parent = GetParentGridPart(aBox, &parentBox);
+ if (parent)
+ return parent->GetGrid(parentBox, aIndex, this);
+ return nullptr;
+ }
+
+ int32_t index = -1;
+ nsIFrame* child = nsBox::GetChildXULBox(aBox);
+ int32_t count = 0;
+ while(child)
+ {
+ // if there is a scrollframe walk inside it to its child
+ nsIFrame* childBox = nsGrid::GetScrolledBox(child);
+
+ nsBoxLayout* layout = childBox->GetXULLayoutManager();
+ nsIGridPart* gridRow = nsGrid::GetPartFromBox(childBox);
+ if (gridRow)
+ {
+ if (layout == aRequestor) {
+ index = count;
+ break;
+ }
+ count += gridRow->GetRowCount();
+ } else
+ count++;
+
+ child = nsBox::GetNextXULBox(child);
+ }
+
+ // if we didn't find ourselves then the tree isn't properly formed yet
+ // this could happen during initial construction so lets just
+ // fail.
+ if (index == -1) {
+ *aIndex = -1;
+ return nullptr;
+ }
+
+ (*aIndex) += index;
+
+ nsIFrame* parentBox; // nsIFrame is implemented by nsIFrame and is not refcounted.
+ nsIGridPart* parent = GetParentGridPart(aBox, &parentBox);
+ if (parent)
+ return parent->GetGrid(parentBox, aIndex, this);
+
+ return nullptr;
+}
+
+nsMargin
+nsGridRowLayout::GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal)
+{
+ // get our parents margin
+ nsMargin margin(0,0,0,0);
+ nsIFrame* parent = nullptr;
+ nsIGridPart* part = GetParentGridPart(aBox, &parent);
+ if (part && parent) {
+ // if we are the first or last child walk upward and add margins.
+
+ // make sure we check for a scrollbox
+ aBox = nsGrid::GetScrollBox(aBox);
+
+ // see if we have a next to see if we are last
+ nsIFrame* next = nsBox::GetNextXULBox(aBox);
+
+ // get the parent first child to see if we are first
+ nsIFrame* child = nsBox::GetChildXULBox(parent);
+
+ margin = part->GetTotalMargin(parent, aIsHorizontal);
+
+ // if first or last
+ if (child == aBox || next == nullptr) {
+
+ // if it's not the first child remove the top margin
+ // we don't need it.
+ if (child != aBox)
+ {
+ if (aIsHorizontal)
+ margin.top = 0;
+ else
+ margin.left = 0;
+ }
+
+ // if it's not the last child remove the bottom margin
+ // we don't need it.
+ if (next != nullptr)
+ {
+ if (aIsHorizontal)
+ margin.bottom = 0;
+ else
+ margin.right = 0;
+ }
+
+ }
+ }
+
+ // add ours to it.
+ nsMargin ourMargin;
+ aBox->GetXULMargin(ourMargin);
+ margin += ourMargin;
+
+ return margin;
+}
+
+NS_IMPL_ADDREF_INHERITED(nsGridRowLayout, nsBoxLayout)
+NS_IMPL_RELEASE_INHERITED(nsGridRowLayout, nsBoxLayout)
+
+NS_INTERFACE_MAP_BEGIN(nsGridRowLayout)
+ NS_INTERFACE_MAP_ENTRY(nsIGridPart)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGridPart)
+NS_INTERFACE_MAP_END_INHERITING(nsBoxLayout)
diff --git a/layout/xul/grid/nsGridRowLayout.h b/layout/xul/grid/nsGridRowLayout.h
new file mode 100644
index 000000000..22a6f12c9
--- /dev/null
+++ b/layout/xul/grid/nsGridRowLayout.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+
+ Author:
+ Eric D Vaughan
+
+**/
+
+#ifndef nsGridRowLayout_h___
+#define nsGridRowLayout_h___
+
+#include "mozilla/Attributes.h"
+#include "nsSprocketLayout.h"
+#include "nsIGridPart.h"
+class nsGridRowGroupLayout;
+class nsGridLayout2;
+class nsBoxLayoutState;
+class nsGrid;
+
+/**
+ * A common base class for nsGridRowLeafLayout (the nsBoxLayout object
+ * for a grid row or column) and nsGridRowGroupLayout (the nsBoxLayout
+ * object for a grid row group or column group).
+ */
+// XXXldb This needs a name that indicates that it's a base class for
+// both row and rows (row-group).
+class nsGridRowLayout : public nsSprocketLayout,
+ public nsIGridPart
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+
+ virtual nsGridRowGroupLayout* CastToRowGroupLayout() override { return nullptr; }
+ virtual nsGridLayout2* CastToGridLayout() override { return nullptr; }
+ virtual nsGrid* GetGrid(nsIFrame* aBox, int32_t* aIndex, nsGridRowLayout* aRequestor=nullptr) override;
+ virtual nsIGridPart* GetParentGridPart(nsIFrame* aBox, nsIFrame** aParentBox) override;
+ virtual void ChildrenInserted(nsIFrame* aBox, nsBoxLayoutState& aState,
+ nsIFrame* aPrevBox,
+ const nsFrameList::Slice& aNewChildren) override;
+ virtual void ChildrenAppended(nsIFrame* aBox, nsBoxLayoutState& aState,
+ const nsFrameList::Slice& aNewChildren) override;
+ virtual void ChildrenRemoved(nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChildList) override;
+ virtual void ChildrenSet(nsIFrame* aBox, nsBoxLayoutState& aState, nsIFrame* aChildList) override;
+ virtual nsMargin GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal) override;
+
+ virtual nsIGridPart* AsGridPart() override { return this; }
+
+protected:
+ virtual void ChildAddedOrRemoved(nsIFrame* aBox, nsBoxLayoutState& aState)=0;
+
+ nsGridRowLayout();
+ virtual ~nsGridRowLayout();
+};
+
+#endif
+
diff --git a/layout/xul/grid/nsGridRowLeafFrame.cpp b/layout/xul/grid/nsGridRowLeafFrame.cpp
new file mode 100644
index 000000000..e973877a4
--- /dev/null
+++ b/layout/xul/grid/nsGridRowLeafFrame.cpp
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+#include "nsGridRowLeafFrame.h"
+#include "nsGridRowLeafLayout.h"
+#include "nsGridRow.h"
+#include "nsBoxLayoutState.h"
+#include "nsGridLayout2.h"
+
+already_AddRefed<nsBoxLayout> NS_NewGridRowLeafLayout();
+
+nsIFrame*
+NS_NewGridRowLeafFrame(nsIPresShell* aPresShell,
+ nsStyleContext* aContext)
+{
+ nsCOMPtr<nsBoxLayout> layout = NS_NewGridRowLeafLayout();
+ return new (aPresShell) nsGridRowLeafFrame(aContext, false, layout);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(nsGridRowLeafFrame)
+
+/*
+ * Our border and padding could be affected by our columns or rows.
+ * Let's go check it out.
+ */
+nsresult
+nsGridRowLeafFrame::GetXULBorderAndPadding(nsMargin& aBorderAndPadding)
+{
+ // if our columns have made our padding larger add it in.
+ nsresult rv = nsBoxFrame::GetXULBorderAndPadding(aBorderAndPadding);
+
+ nsIGridPart* part = nsGrid::GetPartFromBox(this);
+ if (!part)
+ return rv;
+
+ int32_t index = 0;
+ nsGrid* grid = part->GetGrid(this, &index);
+
+ if (!grid)
+ return rv;
+
+ bool isHorizontal = IsXULHorizontal();
+
+ int32_t firstIndex = 0;
+ int32_t lastIndex = 0;
+ nsGridRow* firstRow = nullptr;
+ nsGridRow* lastRow = nullptr;
+ grid->GetFirstAndLastRow(firstIndex, lastIndex, firstRow, lastRow, isHorizontal);
+
+ // only the first and last rows can be affected.
+ if (firstRow && firstRow->GetBox() == this) {
+
+ nscoord top = 0;
+ nscoord bottom = 0;
+ grid->GetRowOffsets(firstIndex, top, bottom, isHorizontal);
+
+ if (isHorizontal) {
+ if (top > aBorderAndPadding.top)
+ aBorderAndPadding.top = top;
+ } else {
+ if (top > aBorderAndPadding.left)
+ aBorderAndPadding.left = top;
+ }
+ }
+
+ if (lastRow && lastRow->GetBox() == this) {
+
+ nscoord top = 0;
+ nscoord bottom = 0;
+ grid->GetRowOffsets(lastIndex, top, bottom, isHorizontal);
+
+ if (isHorizontal) {
+ if (bottom > aBorderAndPadding.bottom)
+ aBorderAndPadding.bottom = bottom;
+ } else {
+ if (bottom > aBorderAndPadding.right)
+ aBorderAndPadding.right = bottom;
+ }
+
+ }
+
+ return rv;
+}
+
+
diff --git a/layout/xul/grid/nsGridRowLeafFrame.h b/layout/xul/grid/nsGridRowLeafFrame.h
new file mode 100644
index 000000000..dd4ee6835
--- /dev/null
+++ b/layout/xul/grid/nsGridRowLeafFrame.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+
+ Eric D Vaughan
+ A frame that can have multiple children. Only one child may be displayed at one time. So the
+ can be flipped though like a deck of cards.
+
+**/
+
+#ifndef nsGridRowLeafFrame_h___
+#define nsGridRowLeafFrame_h___
+
+#include "mozilla/Attributes.h"
+#include "nsBoxFrame.h"
+
+/**
+ * A frame representing a grid row (or column). Grid row (and column)
+ * elements are the children of row group (or column group) elements,
+ * and their children are placed one to a cell.
+ */
+// XXXldb This needs a better name that indicates that it's for any grid
+// row.
+class nsGridRowLeafFrame : public nsBoxFrame
+{
+public:
+ NS_DECL_FRAMEARENA_HELPERS
+
+ friend nsIFrame* NS_NewGridRowLeafFrame(nsIPresShell* aPresShell,
+ nsStyleContext* aContext);
+
+#ifdef DEBUG_FRAME_DUMP
+ virtual nsresult GetFrameName(nsAString& aResult) const override
+ {
+ return MakeFrameName(NS_LITERAL_STRING("nsGridRowLeaf"), aResult);
+ }
+#endif
+
+ nsGridRowLeafFrame(nsStyleContext* aContext,
+ bool aIsRoot,
+ nsBoxLayout* aLayoutManager):
+ nsBoxFrame(aContext, aIsRoot, aLayoutManager) {}
+
+ virtual nsresult GetXULBorderAndPadding(nsMargin& aBorderAndPadding) override;
+
+}; // class nsGridRowLeafFrame
+
+
+
+#endif
+
diff --git a/layout/xul/grid/nsGridRowLeafLayout.cpp b/layout/xul/grid/nsGridRowLeafLayout.cpp
new file mode 100644
index 000000000..2a089af0c
--- /dev/null
+++ b/layout/xul/grid/nsGridRowLeafLayout.cpp
@@ -0,0 +1,328 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//
+// Eric Vaughan
+// Netscape Communications
+//
+// See documentation in associated header file
+//
+
+#include "nsGridRowLeafLayout.h"
+#include "nsGridRowGroupLayout.h"
+#include "nsGridRow.h"
+#include "nsBoxLayoutState.h"
+#include "nsBox.h"
+#include "nsIScrollableFrame.h"
+#include "nsBoxFrame.h"
+#include "nsGridLayout2.h"
+#include <algorithm>
+
+already_AddRefed<nsBoxLayout> NS_NewGridRowLeafLayout()
+{
+ RefPtr<nsBoxLayout> layout = new nsGridRowLeafLayout();
+ return layout.forget();
+}
+
+nsGridRowLeafLayout::nsGridRowLeafLayout():nsGridRowLayout()
+{
+}
+
+nsGridRowLeafLayout::~nsGridRowLeafLayout()
+{
+}
+
+nsSize
+nsGridRowLeafLayout::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ int32_t index = 0;
+ nsGrid* grid = GetGrid(aBox, &index);
+ bool isHorizontal = IsXULHorizontal(aBox);
+
+ // If we are not in a grid. Then we just work like a box. But if we are in a grid
+ // ask the grid for our size.
+ if (!grid) {
+ return nsGridRowLayout::GetXULPrefSize(aBox, aState);
+ }
+ else {
+ return grid->GetPrefRowSize(aState, index, isHorizontal);
+ //AddBorderAndPadding(aBox, pref);
+ }
+}
+
+nsSize
+nsGridRowLeafLayout::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ int32_t index = 0;
+ nsGrid* grid = GetGrid(aBox, &index);
+ bool isHorizontal = IsXULHorizontal(aBox);
+
+ if (!grid)
+ return nsGridRowLayout::GetXULMinSize(aBox, aState);
+ else {
+ nsSize minSize = grid->GetMinRowSize(aState, index, isHorizontal);
+ AddBorderAndPadding(aBox, minSize);
+ return minSize;
+ }
+}
+
+nsSize
+nsGridRowLeafLayout::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ int32_t index = 0;
+ nsGrid* grid = GetGrid(aBox, &index);
+ bool isHorizontal = IsXULHorizontal(aBox);
+
+ if (!grid)
+ return nsGridRowLayout::GetXULMaxSize(aBox, aState);
+ else {
+ nsSize maxSize;
+ maxSize = grid->GetMaxRowSize(aState, index, isHorizontal);
+ AddBorderAndPadding(aBox, maxSize);
+ return maxSize;
+ }
+}
+
+/** If a child is added or removed or changes size
+ */
+void
+nsGridRowLeafLayout::ChildAddedOrRemoved(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ int32_t index = 0;
+ nsGrid* grid = GetGrid(aBox, &index);
+ bool isHorizontal = IsXULHorizontal(aBox);
+
+ if (grid)
+ grid->CellAddedOrRemoved(aState, index, isHorizontal);
+}
+
+void
+nsGridRowLeafLayout::PopulateBoxSizes(nsIFrame* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, int32_t& aFlexes)
+{
+ int32_t index = 0;
+ nsGrid* grid = GetGrid(aBox, &index);
+ bool isHorizontal = IsXULHorizontal(aBox);
+
+ // Our base class SprocketLayout is giving us a chance to change the box sizes before layout
+ // If we are a row lets change the sizes to match our columns. If we are a column then do the opposite
+ // and make them match or rows.
+ if (grid) {
+ nsGridRow* column;
+ int32_t count = grid->GetColumnCount(isHorizontal);
+ nsBoxSize* start = nullptr;
+ nsBoxSize* last = nullptr;
+ nsBoxSize* current = nullptr;
+ nsIFrame* child = nsBox::GetChildXULBox(aBox);
+ for (int i=0; i < count; i++)
+ {
+ column = grid->GetColumnAt(i,isHorizontal);
+
+ // make sure the value was computed before we use it.
+ // !isHorizontal is passed in to invert the behavior of these methods.
+ nscoord pref =
+ grid->GetPrefRowHeight(aState, i, !isHorizontal); // GetPrefColumnWidth
+ nscoord min =
+ grid->GetMinRowHeight(aState, i, !isHorizontal); // GetMinColumnWidth
+ nscoord max =
+ grid->GetMaxRowHeight(aState, i, !isHorizontal); // GetMaxColumnWidth
+ nscoord flex = grid->GetRowFlex(i, !isHorizontal); // GetColumnFlex
+ nscoord left = 0;
+ nscoord right = 0;
+ grid->GetRowOffsets(i, left, right, !isHorizontal); // GetColumnOffsets
+ nsIFrame* box = column->GetBox();
+ bool collapsed = false;
+ nscoord topMargin = column->mTopMargin;
+ nscoord bottomMargin = column->mBottomMargin;
+
+ if (box)
+ collapsed = box->IsXULCollapsed();
+
+ pref = pref - (left + right);
+ if (pref < 0)
+ pref = 0;
+
+ // if this is the first or last column. Take into account that
+ // our row could have a border that could affect our left or right
+ // padding from our columns. If the row has padding subtract it.
+ // would should always be able to garentee that our margin is smaller
+ // or equal to our left or right
+ int32_t firstIndex = 0;
+ int32_t lastIndex = 0;
+ nsGridRow* firstRow = nullptr;
+ nsGridRow* lastRow = nullptr;
+ grid->GetFirstAndLastRow(firstIndex, lastIndex, firstRow, lastRow, !isHorizontal);
+
+ if (i == firstIndex || i == lastIndex) {
+ nsMargin offset = GetTotalMargin(aBox, isHorizontal);
+
+ nsMargin border(0,0,0,0);
+ // can't call GetBorderPadding we will get into recursion
+ aBox->GetXULBorder(border);
+ offset += border;
+ aBox->GetXULPadding(border);
+ offset += border;
+
+ // subtract from out left and right
+ if (i == firstIndex)
+ {
+ if (isHorizontal)
+ left -= offset.left;
+ else
+ left -= offset.top;
+ }
+
+ if (i == lastIndex)
+ {
+ if (isHorizontal)
+ right -= offset.right;
+ else
+ right -= offset.bottom;
+ }
+ }
+
+ // initialize the box size here
+ max = std::max(min, max);
+ pref = nsBox::BoundsCheck(min, pref, max);
+
+ current = new (aState) nsBoxSize();
+ current->pref = pref;
+ current->min = min;
+ current->max = max;
+ current->flex = flex;
+ current->bogus = column->mIsBogus;
+ current->left = left + topMargin;
+ current->right = right + bottomMargin;
+ current->collapsed = collapsed;
+
+ if (!start) {
+ start = current;
+ last = start;
+ } else {
+ last->next = current;
+ last = current;
+ }
+
+ if (child && !column->mIsBogus)
+ child = nsBox::GetNextXULBox(child);
+
+ }
+ aBoxSizes = start;
+ }
+
+ nsSprocketLayout::PopulateBoxSizes(aBox, aState, aBoxSizes, aMinSize, aMaxSize, aFlexes);
+}
+
+void
+nsGridRowLeafLayout::ComputeChildSizes(nsIFrame* aBox,
+ nsBoxLayoutState& aState,
+ nscoord& aGivenSize,
+ nsBoxSize* aBoxSizes,
+ nsComputedBoxSize*& aComputedBoxSizes)
+{
+ // see if we are in a scrollable frame. If we are then there could be scrollbars present
+ // if so we need to subtract them out to make sure our columns line up.
+ if (aBox) {
+ bool isHorizontal = aBox->IsXULHorizontal();
+
+ // go up the parent chain looking for scrollframes
+ nscoord diff = 0;
+ nsIFrame* parentBox;
+ (void)GetParentGridPart(aBox, &parentBox);
+ while (parentBox) {
+ nsIFrame* scrollbox = nsGrid::GetScrollBox(parentBox);
+ nsIScrollableFrame *scrollable = do_QueryFrame(scrollbox);
+ if (scrollable) {
+ // Don't call GetActualScrollbarSizes here because it's not safe
+ // to call that while we're reflowing the contents of the scrollframe,
+ // which we are here.
+ nsMargin scrollbarSizes = scrollable->GetDesiredScrollbarSizes(&aState);
+ uint32_t visible = scrollable->GetScrollbarVisibility();
+
+ if (isHorizontal && (visible & nsIScrollableFrame::VERTICAL)) {
+ diff += scrollbarSizes.left + scrollbarSizes.right;
+ } else if (!isHorizontal && (visible & nsIScrollableFrame::HORIZONTAL)) {
+ diff += scrollbarSizes.top + scrollbarSizes.bottom;
+ }
+ }
+
+ (void)GetParentGridPart(parentBox, &parentBox);
+ }
+
+ if (diff > 0) {
+ aGivenSize += diff;
+
+ nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes);
+
+ aGivenSize -= diff;
+
+ nsComputedBoxSize* s = aComputedBoxSizes;
+ nsComputedBoxSize* last = aComputedBoxSizes;
+ while(s)
+ {
+ last = s;
+ s = s->next;
+ }
+
+ if (last)
+ last->size -= diff;
+
+ return;
+ }
+ }
+
+ nsSprocketLayout::ComputeChildSizes(aBox, aState, aGivenSize, aBoxSizes, aComputedBoxSizes);
+
+}
+
+NS_IMETHODIMP
+nsGridRowLeafLayout::XULLayout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState)
+{
+ return nsGridRowLayout::XULLayout(aBox, aBoxLayoutState);
+}
+
+void
+nsGridRowLeafLayout::DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState)
+{
+ if (aBox) {
+ // mark us dirty
+ // XXXldb We probably don't want to walk up the ancestor chain
+ // calling MarkIntrinsicISizesDirty for every row.
+ aState.PresShell()->FrameNeedsReflow(aBox, nsIPresShell::eTreeChange,
+ NS_FRAME_IS_DIRTY);
+ }
+}
+
+void
+nsGridRowLeafLayout::CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount)
+{
+ if (aBox) {
+ nsIFrame* child = nsBox::GetChildXULBox(aBox);
+
+ // count the children
+ int32_t columnCount = 0;
+ while(child) {
+ child = nsBox::GetNextXULBox(child);
+ columnCount++;
+ }
+
+ // if our count is greater than the current column count
+ if (columnCount > aComputedColumnCount)
+ aComputedColumnCount = columnCount;
+
+ aRowCount++;
+ }
+}
+
+int32_t
+nsGridRowLeafLayout::BuildRows(nsIFrame* aBox, nsGridRow* aRows)
+{
+ if (aBox) {
+ aRows[0].Init(aBox, false);
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/layout/xul/grid/nsGridRowLeafLayout.h b/layout/xul/grid/nsGridRowLeafLayout.h
new file mode 100644
index 000000000..b103ab176
--- /dev/null
+++ b/layout/xul/grid/nsGridRowLeafLayout.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+
+ Author:
+ Eric D Vaughan
+
+**/
+
+#ifndef nsGridRowLeafLayout_h___
+#define nsGridRowLeafLayout_h___
+
+#include "mozilla/Attributes.h"
+#include "nsGridRowLayout.h"
+#include "nsCOMPtr.h"
+
+/**
+ * The nsBoxLayout implementation for nsGridRowLeafFrame.
+ */
+// XXXldb This needs a better name that indicates that it's for any grid
+// row.
+class nsGridRowLeafLayout final : public nsGridRowLayout
+{
+public:
+
+ friend already_AddRefed<nsBoxLayout> NS_NewGridRowLeafLayout();
+
+ virtual nsSize GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual nsSize GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual nsSize GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual void ChildAddedOrRemoved(nsIFrame* aBox, nsBoxLayoutState& aState) override;
+ NS_IMETHOD XULLayout(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState) override;
+ virtual void CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount) override;
+ virtual void DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState) override;
+ virtual int32_t BuildRows(nsIFrame* aBox, nsGridRow* aRows) override;
+ virtual Type GetType() override { return eRowLeaf; }
+
+protected:
+
+ virtual void PopulateBoxSizes(nsIFrame* aBox, nsBoxLayoutState& aBoxLayoutState,
+ nsBoxSize*& aBoxSizes, nscoord& aMinSize,
+ nscoord& aMaxSize, int32_t& aFlexes) override;
+ virtual void ComputeChildSizes(nsIFrame* aBox,
+ nsBoxLayoutState& aState,
+ nscoord& aGivenSize,
+ nsBoxSize* aBoxSizes,
+ nsComputedBoxSize*& aComputedBoxSizes) override;
+
+
+ nsGridRowLeafLayout();
+ virtual ~nsGridRowLeafLayout();
+ //virtual void AddBorderAndPadding(nsIFrame* aBox, nsSize& aSize);
+
+private:
+
+}; // class nsGridRowLeafLayout
+
+#endif
+
diff --git a/layout/xul/grid/nsIGridPart.h b/layout/xul/grid/nsIGridPart.h
new file mode 100644
index 000000000..202429de6
--- /dev/null
+++ b/layout/xul/grid/nsIGridPart.h
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsIGridPart_h___
+#define nsIGridPart_h___
+
+#include "nsISupports.h"
+
+class nsGridRowGroupLayout;
+class nsGrid;
+class nsGridRowLayout;
+class nsGridRow;
+class nsGridLayout2;
+
+// 07373ed7-e947-4a5e-b36c-69f7c195677b
+#define NS_IGRIDPART_IID \
+{ 0x07373ed7, 0xe947, 0x4a5e, \
+ { 0xb3, 0x6c, 0x69, 0xf7, 0xc1, 0x95, 0x67, 0x7b } }
+
+/**
+ * An additional interface implemented by nsBoxLayout implementations
+ * for parts of a grid (excluding cells, which are not special).
+ */
+class nsIGridPart : public nsISupports {
+
+public:
+
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGRIDPART_IID)
+
+ virtual nsGridRowGroupLayout* CastToRowGroupLayout()=0;
+ virtual nsGridLayout2* CastToGridLayout()=0;
+
+ /**
+ * @param aBox [IN] The other half of the |this| parameter, i.e., the box
+ * whose layout manager is |this|.
+ * @param aIndex [INOUT] For callers not setting aRequestor, the value
+ * pointed to by aIndex is incremented by the index
+ * of the row (aBox) within its row group; if aBox
+ * is not a row/column, it is untouched.
+ * The implementation does this by doing the aIndex
+ * incrementing in the call to the parent row group
+ * when aRequestor is non-null.
+ * @param aRequestor [IN] Non-null if and only if this is a recursive
+ * call from the GetGrid method on a child grid part,
+ * in which case it is a pointer to that grid part.
+ * (This may only be non-null for row groups and
+ * grids.)
+ * @return The grid of which aBox (a row, row group, or grid) is a part.
+ */
+ virtual nsGrid* GetGrid(nsIFrame* aBox, int32_t* aIndex, nsGridRowLayout* aRequestor=nullptr)=0;
+
+ /**
+ * @param aBox [IN] The other half of the |this| parameter, i.e., the box
+ * whose layout manager is |this|.
+ * @param aParentBox [OUT] The box representing the next level up in
+ * the grid (i.e., row group for a row, grid for a
+ * row group).
+ * @returns The layout manager for aParentBox.
+ */
+ virtual nsIGridPart* GetParentGridPart(nsIFrame* aBox, nsIFrame** aParentBox) = 0;
+
+ /**
+ * @param aBox [IN] The other half of the |this| parameter, i.e., the box
+ * whose layout manager is |this|.
+ * @param aRowCount [INOUT] Row count
+ * @param aComputedColumnCount [INOUT] Column count
+ */
+ virtual void CountRowsColumns(nsIFrame* aBox, int32_t& aRowCount, int32_t& aComputedColumnCount)=0;
+ virtual void DirtyRows(nsIFrame* aBox, nsBoxLayoutState& aState)=0;
+ virtual int32_t BuildRows(nsIFrame* aBox, nsGridRow* aRows)=0;
+ virtual nsMargin GetTotalMargin(nsIFrame* aBox, bool aIsHorizontal)=0;
+ virtual int32_t GetRowCount() { return 1; }
+
+ /**
+ * Return the level of the grid hierarchy this grid part represents.
+ */
+ enum Type { eGrid, eRowGroup, eRowLeaf };
+ virtual Type GetType()=0;
+
+ /**
+ * Return whether this grid part is an appropriate parent for the argument.
+ */
+ bool CanContain(nsIGridPart* aPossibleChild) {
+ Type thisType = GetType(), childType = aPossibleChild->GetType();
+ return thisType + 1 == childType || (thisType == eRowGroup && childType == eRowGroup);
+ }
+
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIGridPart, NS_IGRIDPART_IID)
+
+#endif
+
diff --git a/layout/xul/grid/reftests/column-sizing-1-ref.xul b/layout/xul/grid/reftests/column-sizing-1-ref.xul
new file mode 100644
index 000000000..df0113083
--- /dev/null
+++ b/layout/xul/grid/reftests/column-sizing-1-ref.xul
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <hbox>
+ <vbox style="background:aqua">
+ <label value="Left" />
+ </vbox>
+ <vbox style="background:yellow">
+ <textbox value="Right" />
+ </vbox>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/reftests/column-sizing-1.xul b/layout/xul/grid/reftests/column-sizing-1.xul
new file mode 100644
index 000000000..2a94569ba
--- /dev/null
+++ b/layout/xul/grid/reftests/column-sizing-1.xul
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <grid>
+ <columns>
+ <column style="background:aqua">
+ <label value="Left" />
+ </column>
+ <column style="background:yellow">
+ <textbox value="Right" />
+ </column>
+ </columns>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/not-full-basic-ref.xhtml b/layout/xul/grid/reftests/not-full-basic-ref.xhtml
new file mode 100644
index 000000000..cd233585a
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-basic-ref.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>XUL Grid Test</title>
+ <style type="text/css">
+ html { background: black; }
+ html, body { margin: 0; padding: 0; height: 100%; }
+ div { position: absolute; }
+ </style>
+</head>
+<body>
+
+<div style="background: rgb(0, 102, 153);
+ top: 0px; height: 200px; left: 0px; width: 200px;" />
+<div style="background: rgb(0, 255, 0);
+ top: 200px; bottom: 0px; left: 0px; width: 100px;" />
+<div style="background: rgb(0, 255, 0);
+ top: 200px; height: 100px; left: 100px; width: 100px;" />
+<div style="background: rgb(0, 0, 153);
+ top: 0px; height: 100px; left: 200px; right: 0px;" />
+<div style="background: rgb(0, 0, 153);
+ top: 100px; height: 100px; left: 200px; width: 100px;" />
+
+</body>
+</html>
diff --git a/layout/xul/grid/reftests/not-full-basic.xul b/layout/xul/grid/reftests/not-full-basic.xul
new file mode 100644
index 000000000..5c7fa9123
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-basic.xul
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ ]]></style>
+ <grid flex="1">
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/not-full-grid-pack-align.xul b/layout/xul/grid/reftests/not-full-grid-pack-align.xul
new file mode 100644
index 000000000..3fe6a95cb
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-grid-pack-align.xul
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ ]]></style>
+ <!-- align and pack should be no-ops on grid element (not on columns/rows) -->
+ <grid flex="1" align="start" pack="end">
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/not-full-row-group-align-ref.xhtml b/layout/xul/grid/reftests/not-full-row-group-align-ref.xhtml
new file mode 100644
index 000000000..abef67f87
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-group-align-ref.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>XUL Grid Test</title>
+ <style type="text/css">
+ html { background: black; }
+ html, body { margin: 0; padding: 0; height: 100%; }
+ div { position: absolute; }
+ </style>
+</head>
+<body>
+
+<div style="background: rgb(0, 102, 153);
+ top: 100px; height: 100px; left: 100px; width: 100px;" />
+<div style="background: rgb(0, 255, 0);
+ top: 0px; height: 100px; left: 100px; width: 100px;" />
+<div style="background: rgb(0, 255, 0);
+ top: 200px; height: 100px; left: 100px; width: 100px;" />
+<div style="background: rgb(0, 0, 153);
+ top: 100px; height: 100px; left: 0px; width: 100px;" />
+<div style="background: rgb(0, 0, 153);
+ top: 100px; height: 100px; left: 200px; width: 100px;" />
+
+</body>
+</html>
diff --git a/layout/xul/grid/reftests/not-full-row-group-align.xul b/layout/xul/grid/reftests/not-full-row-group-align.xul
new file mode 100644
index 000000000..0037d9fb8
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-group-align.xul
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ ]]></style>
+ <grid flex="1">
+ <!-- does anybody actually *want* the way columns align="start" behaves here? -->
+ <columns align="start">
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows align="start">
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/not-full-row-group-direction-ref.xhtml b/layout/xul/grid/reftests/not-full-row-group-direction-ref.xhtml
new file mode 100644
index 000000000..b2a92b07b
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-group-direction-ref.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>XUL Grid Test</title>
+ <style type="text/css">
+ html { background: black; }
+ html, body { margin: 0; padding: 0; height: 100%; }
+ div { position: absolute; }
+ </style>
+</head>
+<body>
+
+<div style="background: rgb(0, 102, 153);
+ bottom: 0px; height: 100px; right: 0px; width: 100px;" />
+<div style="background: rgb(0, 0, 153);
+ bottom: 0px; height: 100px; left: 0px; right: 100px;" />
+<div style="background: rgb(0, 0, 153);
+ bottom: 100px; height: 100px; left: 0px; width: 300px;" />
+<div style="background: rgb(0, 255, 0);
+ top: 0px; bottom: 100px; right: 0px; width: 100px;" />
+<div style="background: rgb(0, 255, 0);
+ top: 0px; height: 300px; right: 100px; width: 100px;" />
+
+</body>
+</html>
diff --git a/layout/xul/grid/reftests/not-full-row-group-direction.xul b/layout/xul/grid/reftests/not-full-row-group-direction.xul
new file mode 100644
index 000000000..c38db40a5
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-group-direction.xul
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ rows, columns { -moz-box-direction: reverse; }
+ ]]></style>
+ <grid flex="1">
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/not-full-row-group-pack-ref.xhtml b/layout/xul/grid/reftests/not-full-row-group-pack-ref.xhtml
new file mode 100644
index 000000000..9232f6ba4
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-group-pack-ref.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>XUL Grid Test</title>
+ <style type="text/css">
+ html { background: black; }
+ html, body { margin: 0; padding: 0; height: 100%; }
+ div { position: absolute; }
+ </style>
+</head>
+<body>
+
+<div style="background: rgb(0, 102, 153);
+ bottom: 200px; height: 100px; right: 200px; width: 100px;" />
+<div style="background: rgb(0, 0, 153);
+ bottom: 200px; height: 100px; left: 0px; right: 300px;" />
+<div style="background: rgb(0, 0, 153);
+ bottom: 100px; height: 100px; left: 0px; width: 300px;" />
+<div style="background: rgb(0, 0, 153);
+ bottom: 200px; height: 100px; right: 0px; width: 200px;" />
+<div style="background: rgb(0, 255, 0);
+ top: 0px; bottom: 300px; right: 200px; width: 100px;" />
+<div style="background: rgb(0, 255, 0);
+ top: 0px; height: 300px; right: 100px; width: 100px;" />
+<div style="background: rgb(0, 255, 0);
+ bottom: 0px; height: 200px; right: 200px; width: 100px;" />
+
+</body>
+</html>
diff --git a/layout/xul/grid/reftests/not-full-row-group-pack.xul b/layout/xul/grid/reftests/not-full-row-group-pack.xul
new file mode 100644
index 000000000..bb8f650ae
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-group-pack.xul
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ rows, columns { -moz-box-pack: end; }
+ ]]></style>
+ <grid flex="1">
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/not-full-row-leaf-align.xul b/layout/xul/grid/reftests/not-full-row-leaf-align.xul
new file mode 100644
index 000000000..806514ebd
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-leaf-align.xul
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ row, column { -moz-box-align: start; }
+ ]]></style>
+ <grid flex="1">
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/not-full-row-leaf-direction.xul b/layout/xul/grid/reftests/not-full-row-leaf-direction.xul
new file mode 100644
index 000000000..17c3a6585
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-leaf-direction.xul
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ row, column { -moz-box-direction: reverse; }
+ ]]></style>
+ <grid flex="1">
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/not-full-row-leaf-pack-ref.xhtml b/layout/xul/grid/reftests/not-full-row-leaf-pack-ref.xhtml
new file mode 100644
index 000000000..30635313a
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-leaf-pack-ref.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>XUL Grid Test</title>
+ <style type="text/css">
+ html { background: black; }
+ html, body { margin: 0; padding: 0; height: 100%; }
+ div { position: absolute; }
+ </style>
+</head>
+<body>
+
+<div style="background: rgb(0, 102, 153);
+ top: 0px; height: 100px; left: 0px; width: 100px;" />
+<div style="background: rgb(0, 255, 0);
+ top: 100px; bottom: 0px; left: 0px; width: 100px;" />
+<div style="background: rgb(0, 255, 0);
+ bottom: 0px; height: 300px; left: 100px; width: 100px;" />
+<div style="background: rgb(0, 0, 153);
+ top: 0px; height: 100px; left: 100px; right: 0px;" />
+<div style="background: rgb(0, 0, 153);
+ top: 100px; height: 100px; right: 0px; width: 300px;" />
+
+</body>
+</html>
diff --git a/layout/xul/grid/reftests/not-full-row-leaf-pack.xul b/layout/xul/grid/reftests/not-full-row-leaf-pack.xul
new file mode 100644
index 000000000..8f353c764
--- /dev/null
+++ b/layout/xul/grid/reftests/not-full-row-leaf-pack.xul
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ row, column { -moz-box-pack: end; }
+ ]]></style>
+ <grid flex="1">
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/reftest-stylo.list b/layout/xul/grid/reftests/reftest-stylo.list
new file mode 100644
index 000000000..eb73955c9
--- /dev/null
+++ b/layout/xul/grid/reftests/reftest-stylo.list
@@ -0,0 +1,38 @@
+# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
+skip-if((B2G&&browserIsRemote)||Mulet) == row-sizing-1.xul row-sizing-1.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) == column-sizing-1.xul column-sizing-1.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) == row-or-column-sizing-1.xul row-or-column-sizing-1.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) == row-or-column-sizing-1.xul row-or-column-sizing-1.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) == row-or-column-sizing-1.xul row-or-column-sizing-1.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,60000) == z-order-1.xul z-order-1.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,60000) == z-order-2.xul z-order-2.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,60000) == not-full-basic.xul not-full-basic.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,110000) == not-full-grid-pack-align.xul not-full-grid-pack-align.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,30000) == not-full-row-group-align.xul not-full-row-group-align.xul
+# does anyone want/need this behavior?
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,10000) == not-full-row-group-pack.xul not-full-row-group-pack.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,50000) == not-full-row-group-direction.xul not-full-row-group-direction.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,60000) == not-full-row-leaf-align.xul not-full-row-leaf-align.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,50000) == not-full-row-leaf-pack.xul not-full-row-leaf-pack.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(skiaContent,1,80000) == not-full-row-leaf-direction.xul not-full-row-leaf-direction.xul
+skip-if(B2G||Mulet) random-if(transparentScrollbars) fuzzy-if(OSX==1010,1,565) == scrollable-columns.xul scrollable-columns.xul
+# bug 650597
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) == scrollable-rows.xul scrollable-rows.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) == sizing-2d.xul sizing-2d.xul
+# Initial mulet triage: parity with B2G/B2G Desktop
diff --git a/layout/xul/grid/reftests/reftest.list b/layout/xul/grid/reftests/reftest.list
new file mode 100644
index 000000000..eb414f906
--- /dev/null
+++ b/layout/xul/grid/reftests/reftest.list
@@ -0,0 +1,18 @@
+== row-sizing-1.xul row-sizing-1-ref.xul
+== column-sizing-1.xul column-sizing-1-ref.xul
+== row-or-column-sizing-1.xul row-or-column-sizing-2.xul
+== row-or-column-sizing-1.xul row-or-column-sizing-3.xul
+== row-or-column-sizing-1.xul row-or-column-sizing-4.xul
+fuzzy-if(skiaContent,1,60000) == z-order-1.xul z-order-1-ref.xul
+fuzzy-if(skiaContent,1,60000) == z-order-2.xul z-order-2-ref.xul
+fuzzy-if(skiaContent,1,60000) == not-full-basic.xul not-full-basic-ref.xhtml
+fuzzy-if(skiaContent,1,110000) == not-full-grid-pack-align.xul not-full-basic-ref.xhtml
+fuzzy-if(skiaContent,1,30000) == not-full-row-group-align.xul not-full-row-group-align-ref.xhtml # does anyone want/need this behavior?
+fuzzy-if(skiaContent,1,10000) == not-full-row-group-pack.xul not-full-row-group-pack-ref.xhtml
+fuzzy-if(skiaContent,1,50000) == not-full-row-group-direction.xul not-full-row-group-direction-ref.xhtml
+fuzzy-if(skiaContent,1,60000) == not-full-row-leaf-align.xul not-full-basic-ref.xhtml
+fuzzy-if(skiaContent,1,50000) == not-full-row-leaf-pack.xul not-full-row-leaf-pack-ref.xhtml
+fuzzy-if(skiaContent,1,80000) == not-full-row-leaf-direction.xul not-full-row-leaf-pack-ref.xhtml
+random-if(transparentScrollbars) fuzzy-if(OSX==1010,1,565) == scrollable-columns.xul scrollable-columns-ref.xhtml # bug 650597
+fails == scrollable-rows.xul scrollable-rows-ref.xhtml
+== sizing-2d.xul sizing-2d-ref.xul
diff --git a/layout/xul/grid/reftests/row-or-column-sizing-1.xul b/layout/xul/grid/reftests/row-or-column-sizing-1.xul
new file mode 100644
index 000000000..6c64eef18
--- /dev/null
+++ b/layout/xul/grid/reftests/row-or-column-sizing-1.xul
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <grid>
+ <columns>
+ <column />
+ <column />
+ </columns>
+ <rows>
+ <row>
+ <hbox />
+ <label value="Upper right" />
+ </row>
+ <row>
+ <textbox value="Lower left" />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/row-or-column-sizing-2.xul b/layout/xul/grid/reftests/row-or-column-sizing-2.xul
new file mode 100644
index 000000000..008f82fd5
--- /dev/null
+++ b/layout/xul/grid/reftests/row-or-column-sizing-2.xul
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <grid>
+ <columns>
+ <column>
+ <hbox />
+ <textbox value="Lower left" />
+ </column>
+ <column>
+ <label value="Upper right" />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row />
+ <row />
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/row-or-column-sizing-3.xul b/layout/xul/grid/reftests/row-or-column-sizing-3.xul
new file mode 100644
index 000000000..1e8e55c29
--- /dev/null
+++ b/layout/xul/grid/reftests/row-or-column-sizing-3.xul
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <grid>
+ <columns>
+ <column>
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <label value="Upper right" />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row>
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <textbox value="Lower left" />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/row-or-column-sizing-4.xul b/layout/xul/grid/reftests/row-or-column-sizing-4.xul
new file mode 100644
index 000000000..5a826fd84
--- /dev/null
+++ b/layout/xul/grid/reftests/row-or-column-sizing-4.xul
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <grid>
+ <columns>
+ <column>
+ <hbox />
+ <textbox value="Lower left" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row>
+ <hbox />
+ <label value="Upper right" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/row-sizing-1-ref.xul b/layout/xul/grid/reftests/row-sizing-1-ref.xul
new file mode 100644
index 000000000..b35719052
--- /dev/null
+++ b/layout/xul/grid/reftests/row-sizing-1-ref.xul
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ orient="horizontal"
+ title="XUL Grid Test">
+ <vbox>
+ <hbox style="background:aqua">
+ <label value="Top" />
+ </hbox>
+ <hbox style="background:yellow">
+ <textbox value="Bottom" />
+ </hbox>
+ </vbox>
+</window>
diff --git a/layout/xul/grid/reftests/row-sizing-1.xul b/layout/xul/grid/reftests/row-sizing-1.xul
new file mode 100644
index 000000000..0455b8da4
--- /dev/null
+++ b/layout/xul/grid/reftests/row-sizing-1.xul
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ orient="horizontal"
+ title="XUL Grid Test">
+ <grid>
+ <rows>
+ <row style="background:aqua">
+ <label value="Top" />
+ </row>
+ <row style="background:yellow">
+ <textbox value="Bottom" />
+ </row>
+ </rows>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/scrollable-columns-ref.xhtml b/layout/xul/grid/reftests/scrollable-columns-ref.xhtml
new file mode 100644
index 000000000..698c5a036
--- /dev/null
+++ b/layout/xul/grid/reftests/scrollable-columns-ref.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>XUL Grid Test</title>
+ <style type="text/css">
+ html { background: black; }
+ html, body { margin: 0; padding: 0; height: 100%; }
+ div { position: absolute; }
+ </style>
+</head>
+<body>
+
+<div style="background: rgb(0, 102, 153);
+ top: 0px; height: 200px; left: 0px; width: 200px;" />
+<div style="background: rgb(0, 255, 0); overflow: auto;
+ top: 200px; height: 100px; left: 0px; width: 200px;">
+ <div style="width: 300px; height: 50px" />
+</div>
+<div style="background: rgb(0, 0, 153);
+ top: 100px; height: 100px; left: 200px; width: 100px;" />
+
+</body>
+</html>
diff --git a/layout/xul/grid/reftests/scrollable-columns.xul b/layout/xul/grid/reftests/scrollable-columns.xul
new file mode 100644
index 000000000..661c4412f
--- /dev/null
+++ b/layout/xul/grid/reftests/scrollable-columns.xul
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ grid { width: 200px; height: 200px; }
+ columns { overflow: auto; }
+ ]]></style>
+ <hbox>
+ <grid>
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/reftests/scrollable-rows-ref.xhtml b/layout/xul/grid/reftests/scrollable-rows-ref.xhtml
new file mode 100644
index 000000000..6b5b95f02
--- /dev/null
+++ b/layout/xul/grid/reftests/scrollable-rows-ref.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>XUL Grid Test</title>
+ <style type="text/css">
+ html { background: black; }
+ html, body { margin: 0; padding: 0; height: 100%; }
+ div { position: absolute; }
+ </style>
+</head>
+<body>
+
+<div style="background: rgb(0, 102, 153);
+ top: 0px; height: 200px; left: 0px; width: 200px;" />
+<div style="background: rgb(0, 0, 153); overflow: auto;
+ top: 0px; height: 200px; left: 200px; width: 100px;">
+ <div style="width: 50px; height: 300px" />
+</div>
+<div style="background: rgb(0, 255, 0);
+ top: 200px; height: 100px; left: 100px; width: 100px;" />
+
+</body>
+</html>
diff --git a/layout/xul/grid/reftests/scrollable-rows.xul b/layout/xul/grid/reftests/scrollable-rows.xul
new file mode 100644
index 000000000..9fa1f82c5
--- /dev/null
+++ b/layout/xul/grid/reftests/scrollable-rows.xul
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ grid { width: 200px; height: 200px; }
+ rows { overflow: auto; }
+ ]]></style>
+ <hbox>
+ <grid>
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/reftests/sizing-2d-ref.xul b/layout/xul/grid/reftests/sizing-2d-ref.xul
new file mode 100644
index 000000000..a3bc4ca73
--- /dev/null
+++ b/layout/xul/grid/reftests/sizing-2d-ref.xul
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" align="start">
+ <hbox>
+ <box style="background:aqua; width: 50px; height: 100px" />
+ <box style="background:fuchsia; width: 100px; height: 100px" />
+ </hbox>
+ <hbox>
+ <box style="background:yellow; width: 50px; height: 75px" />
+ <box style="background:blue; width: 100px; height: 75px" />
+ </hbox>
+</window>
diff --git a/layout/xul/grid/reftests/sizing-2d.xul b/layout/xul/grid/reftests/sizing-2d.xul
new file mode 100644
index 000000000..7868f9eca
--- /dev/null
+++ b/layout/xul/grid/reftests/sizing-2d.xul
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" align="start">
+ <grid>
+ <rows>
+ <row>
+ <box style="width: 25px; height: 25px" />
+ <box />
+ </row>
+ <row>
+ <box />
+ <box style="width: 75px; height: 75px" />
+ </row>
+ </rows>
+ <columns>
+ <column>
+ <box style="background: aqua" />
+ <box style="background: yellow; width: 50px; height: 50px" />
+ </column>
+ <column>
+ <box style="background: fuchsia; width: 100px; height: 100px" />
+ <box style="background: blue" />
+ </column>
+ </columns>
+ </grid>
+</window>
diff --git a/layout/xul/grid/reftests/z-order-1-ref.xul b/layout/xul/grid/reftests/z-order-1-ref.xul
new file mode 100644
index 000000000..198c4e6c6
--- /dev/null
+++ b/layout/xul/grid/reftests/z-order-1-ref.xul
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ ]]></style>
+ <hbox>
+ <grid>
+ <rows>
+ <row>
+ <hbox style="background: rgb(0, 102, 153)" />
+ <hbox style="background: rgb(0, 102, 153)" />
+ <hbox style="background: rgb(0, 0, 153)" />
+ </row>
+ <row>
+ <hbox style="background: rgb(0, 102, 153)" />
+ <hbox style="background: rgb(0, 102, 153)" />
+ <hbox style="background: rgb(0, 0, 153)" />
+ </row>
+ <row>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 0, 0)" />
+ </row>
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/reftests/z-order-1.xul b/layout/xul/grid/reftests/z-order-1.xul
new file mode 100644
index 000000000..d38ef9f4a
--- /dev/null
+++ b/layout/xul/grid/reftests/z-order-1.xul
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ ]]></style>
+ <hbox>
+ <grid>
+ <columns>
+ <column style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ <rows>
+ <row style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/reftests/z-order-2-ref.xul b/layout/xul/grid/reftests/z-order-2-ref.xul
new file mode 100644
index 000000000..5b0793d6d
--- /dev/null
+++ b/layout/xul/grid/reftests/z-order-2-ref.xul
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ ]]></style>
+ <hbox>
+ <grid>
+ <rows>
+ <row>
+ <hbox style="background: rgb(0, 102, 153)" />
+ <hbox style="background: rgb(0, 102, 153)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </row>
+ <row>
+ <hbox style="background: rgb(0, 102, 153)" />
+ <hbox style="background: rgb(0, 102, 153)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </row>
+ <row>
+ <hbox style="background: rgb(0, 0, 153)" />
+ <hbox style="background: rgb(0, 0, 153)" />
+ <hbox style="background: rgb(0, 0, 0)" />
+ </row>
+ </rows>
+ </grid>
+ </hbox>
+</window>
diff --git a/layout/xul/grid/reftests/z-order-2.xul b/layout/xul/grid/reftests/z-order-2.xul
new file mode 100644
index 000000000..b2c270d6b
--- /dev/null
+++ b/layout/xul/grid/reftests/z-order-2.xul
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!DOCTYPE window>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ title="XUL Grid Test">
+ <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
+ window { background: black; }
+ hbox { height: 100px; width: 100px; }
+ ]]></style>
+ <hbox>
+ <grid>
+ <rows>
+ <row style="background: rgb(0, 255, 0)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ <row>
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ <hbox style="background: rgb(0, 255, 0)" />
+ </row>
+ <row>
+ <hbox />
+ <hbox />
+ <hbox />
+ </row>
+ </rows>
+ <columns>
+ <column style="background: rgba(0, 0, 255, 0.6)">
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ <column>
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ <hbox style="background: rgba(0, 0, 255, 0.6)" />
+ </column>
+ <column>
+ <hbox />
+ <hbox />
+ <hbox />
+ </column>
+ </columns>
+ </grid>
+ </hbox>
+</window>