[LayoutReloaded] Remove left/right width/height setters from Layout.Box
[WebKit-https.git] / Tools / LayoutReloaded / LayoutTree / Box.js
1 /*
2  * Copyright (C) 2018 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 var Layout = { }
27
28 Layout.Box = class Box {
29     constructor(node, id) {
30         this.m_id = id;
31         this.m_rendererName = null;
32         this.m_node = node;
33         this.m_parent = null;
34         this.m_nextSibling = null;
35         this.m_previousSibling = null;
36         this.m_isAnonymous = false;
37         this.m_establishedFormattingContext = null;
38         this.m_displayBox = null;
39     }
40
41     id() {
42         return this.m_id;
43     }
44
45     setRendererName(name) {
46         this.m_rendererName = name;
47     }
48
49     name() {
50         return this.m_rendererName;
51     }
52
53     node() {
54         return this.m_node;
55     }
56
57     parent() {
58         return this.m_parent;
59     }
60
61     nextSibling() {
62         return this.m_nextSibling;
63     }
64
65     nextInFlowSibling() {
66         let nextInFlowSibling = this.nextSibling();
67         while (nextInFlowSibling) {
68             if (nextInFlowSibling.isInFlow())
69                 return nextInFlowSibling;
70             nextInFlowSibling = nextInFlowSibling.nextSibling();
71         }
72         return null;
73     }
74
75     nextInFlowOrFloatSibling() {
76         let nextInFlowSibling = this.nextSibling();
77         while (nextInFlowSibling) {
78             if (nextInFlowSibling.isInFlow() || nextInFlowSibling.isFloatingPositioned())
79                 return nextInFlowSibling;
80             nextInFlowSibling = nextInFlowSibling.nextSibling();
81         }
82         return null;
83     }
84
85     previousSibling() {
86         return this.m_previousSibling;
87     }
88
89     previousInFlowSibling() {
90         let previousInFlowSibling = this.previousSibling();
91         while (previousInFlowSibling) {
92             if (previousInFlowSibling.isInFlow())
93                 return previousInFlowSibling;
94             previousInFlowSibling = previousInFlowSibling.previousSibling();
95         }
96         return null;
97     }
98
99     setParent(parent) {
100         this.m_parent = parent;
101     }
102
103     setNextSibling(nextSibling) {
104         this.m_nextSibling = nextSibling;
105     }
106     
107     setPreviousSibling(previousSibling) {
108         this.m_previousSibling = previousSibling;
109     }
110
111     setDisplayBox(displayBox) {
112         ASSERT(!this.m_displayBox);
113         this.m_displayBox = displayBox;
114     }
115
116     displayBox() {
117         ASSERT(this.m_displayBox);
118         return this.m_displayBox;
119     }
120
121     rect() {
122         return this.displayBox().rect();
123     }
124
125     topLeft() {
126         return this.rect().topLeft();
127     }
128
129     bottomRight() {
130         return this.rect().bottomRight();
131     }
132
133     isContainer() {
134         return false;
135     }
136
137     isBlockLevelBox() {
138         return Utils.isBlockLevelElement(this.node());
139     }
140
141     isBlockContainerBox() {
142         return Utils.isBlockContainerElement(this.node());
143     }
144
145     isInlineLevelBox() {
146         return Utils.isInlineLevelElement(this.node());
147     }
148
149     setIsAnonymous() {
150         this.m_isAnonymous = true;
151     }
152
153     isAnonymous() {
154         return this.m_isAnonymous;
155     }
156
157     establishesFormattingContext() {
158         if (this.isAnonymous())
159             return false;
160         return this.establishesBlockFormattingContext() || this.establishesInlineFormattingContext();
161     }
162
163     establishedFormattingContext() {
164         if (this.establishesFormattingContext() && !this.m_establishedFormattingContext)
165             this.m_establishedFormattingContext = this.establishesBlockFormattingContext() ? new BlockFormattingContext(this) : new InlineFormattingContext(this);
166         return this.m_establishedFormattingContext;
167     }
168
169     establishesBlockFormattingContext() {
170         // 9.4.1 Block formatting contexts
171         // Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions)
172         // that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport)
173         // establish new block formatting contexts for their contents.
174         return this.isFloatingPositioned() || this.isAbsolutelyPositioned() || (this.isBlockContainerBox() && !this.isBlockLevelBox())
175             || (this.isBlockLevelBox() && !Utils.isOverflowVisible(this));
176     }
177
178     establishesInlineFormattingContext() {
179         return false;
180     }
181
182     isPositioned() {
183         return this.isOutOfFlowPositioned() || this.isRelativelyPositioned();
184     }
185
186     isRelativelyPositioned() {
187         return Utils.isRelativelyPositioned(this);
188     }
189
190     isAbsolutelyPositioned() {
191         return Utils.isAbsolutelyPositioned(this) || this.isFixedPositioned();
192     }
193
194     isFixedPositioned() {
195         return Utils.isFixedPositioned(this);
196     }
197
198     isInFlow() {
199         if (this.isAnonymous())
200             return true;
201         return !this.isFloatingOrOutOfFlowPositioned();
202     }
203
204     isOutOfFlowPositioned() {
205         return this.isAbsolutelyPositioned() || this.isFixedPositioned();
206     }
207
208     isInFlowPositioned() {
209         return this.isPositioned() && !this.isOutOfFlowPositioned();
210     }
211
212     isFloatingPositioned() {
213         return Utils.isFloatingPositioned(this);
214     }
215
216     isFloatingOrOutOfFlowPositioned() {
217         return this.isFloatingPositioned() || this.isOutOfFlowPositioned();
218     }
219
220     isRootBox() {
221         // FIXME: This should just be a simple instanceof check, but we are in the mainframe while the test document is in an iframe
222         // Let's just return root for both the RenderView and the <html> element.
223         return !this.parent() || !this.parent().parent();
224     }
225
226     containingBlock() {
227         if (!this.parent())
228             return null;
229         if (!this.isPositioned() || this.isInFlowPositioned())
230             return this.parent();
231         if (this.isAbsolutelyPositioned() && !this.isFixedPositioned()) {
232             let ascendant = this.parent();
233             while (ascendant.parent() && !ascendant.isPositioned())
234                 ascendant = ascendant.parent();
235             return ascendant;
236         }
237         if (this.isFixedPositioned()) {
238             let ascendant = this.parent();
239             while (ascendant.parent())
240                 ascendant = ascendant.parent();
241             return ascendant;
242         }
243         ASSERT_NOT_REACHED();
244         return null;
245     }
246
247     isDescendantOf(container) {
248         ASSERT(container);
249         let ascendant = this.parent();
250         while (ascendant && ascendant != container)
251             ascendant = ascendant.parent();
252         return !!ascendant;
253     }
254
255     borderBox() {
256         return this.displayBox().borderBox();
257     }
258
259     paddingBox() {
260         return this.displayBox().paddingBox();
261     }
262
263     contentBox() {
264         return this.displayBox().contentBox();
265     }
266 }