Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: Source/core/rendering/RenderFrameSet.cpp

Issue 929223003: Move and rename RenderFrame and RenderFrameSet. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/rendering/RenderFrameSet.h ('k') | Source/web/WebLocalFrameImpl.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /**
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2000 Simon Hausmann <hausmann@kde.org>
4 * (C) 2000 Stefan Schimanski (1Stein@gmx.de)
5 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24 #include "config.h"
25 #include "core/rendering/RenderFrameSet.h"
26
27 #include "core/dom/Document.h"
28 #include "core/events/MouseEvent.h"
29 #include "core/frame/LocalFrame.h"
30 #include "core/html/HTMLDimension.h"
31 #include "core/html/HTMLFrameSetElement.h"
32 #include "core/layout/PaintInfo.h"
33 #include "core/page/EventHandler.h"
34 #include "core/paint/FrameSetPainter.h"
35 #include "core/rendering/RenderFrame.h"
36 #include "core/rendering/RenderView.h"
37 #include "platform/Cursor.h"
38 #include "platform/graphics/GraphicsContext.h"
39
40 namespace blink {
41
42 RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet)
43 : RenderBox(frameSet)
44 , m_isResizing(false)
45 , m_isChildResizing(false)
46 {
47 setInline(false);
48 }
49
50 RenderFrameSet::~RenderFrameSet()
51 {
52 }
53
54 RenderFrameSet::GridAxis::GridAxis()
55 : m_splitBeingResized(noSplit)
56 {
57 }
58
59 HTMLFrameSetElement* RenderFrameSet::frameSet() const
60 {
61 return toHTMLFrameSetElement(node());
62 }
63
64 void RenderFrameSet::paint(const PaintInfo& paintInfo, const LayoutPoint& paintO ffset)
65 {
66 FrameSetPainter(*this).paint(paintInfo, paintOffset);
67 }
68
69 void RenderFrameSet::computePreferredLogicalWidths()
70 {
71 m_minPreferredLogicalWidth = 0;
72 m_maxPreferredLogicalWidth = 0;
73 clearPreferredLogicalWidthsDirty();
74 }
75
76 void RenderFrameSet::GridAxis::resize(int size)
77 {
78 m_sizes.resize(size);
79 m_deltas.resize(size);
80 m_deltas.fill(0);
81
82 // To track edges for resizability and borders, we need to be (size + 1). Th is is because a parent frameset
83 // may ask us for information about our left/top/right/bottom edges in order to make its own decisions about
84 // what to do. We are capable of tainting that parent frameset's borders, so we have to cache this info.
85 m_preventResize.resize(size + 1);
86 m_allowBorder.resize(size + 1);
87 }
88
89 void RenderFrameSet::layOutAxis(GridAxis& axis, const Vector<HTMLDimension>& gri d, int availableLen)
90 {
91 availableLen = max(availableLen, 0);
92
93 int* gridLayout = axis.m_sizes.data();
94
95 if (grid.isEmpty()) {
96 gridLayout[0] = availableLen;
97 return;
98 }
99
100 int gridLen = axis.m_sizes.size();
101 ASSERT(gridLen);
102
103 int totalRelative = 0;
104 int totalFixed = 0;
105 int totalPercent = 0;
106 int countRelative = 0;
107 int countFixed = 0;
108 int countPercent = 0;
109
110 // First we need to investigate how many columns of each type we have and
111 // how much space these columns are going to require.
112 for (int i = 0; i < gridLen; ++i) {
113 // Count the total length of all of the fixed columns/rows -> totalFixed
114 // Count the number of columns/rows which are fixed -> countFixed
115 if (grid[i].isAbsolute()) {
116 gridLayout[i] = max<int>(grid[i].value(), 0);
117 totalFixed += gridLayout[i];
118 countFixed++;
119 }
120
121 // Count the total percentage of all of the percentage columns/rows -> t otalPercent
122 // Count the number of columns/rows which are percentages -> countPercen t
123 if (grid[i].isPercentage()) {
124 gridLayout[i] = max<int>(grid[i].value() * availableLen / 100., 0);
125 totalPercent += gridLayout[i];
126 countPercent++;
127 }
128
129 // Count the total relative of all the relative columns/rows -> totalRel ative
130 // Count the number of columns/rows which are relative -> countRelative
131 if (grid[i].isRelative()) {
132 totalRelative += max<int>(grid[i].value(), 1);
133 countRelative++;
134 }
135 }
136
137 int remainingLen = availableLen;
138
139 // Fixed columns/rows are our first priority. If there is not enough space t o fit all fixed
140 // columns/rows we need to proportionally adjust their size.
141 if (totalFixed > remainingLen) {
142 int remainingFixed = remainingLen;
143
144 for (int i = 0; i < gridLen; ++i) {
145 if (grid[i].isAbsolute()) {
146 gridLayout[i] = (gridLayout[i] * remainingFixed) / totalFixed;
147 remainingLen -= gridLayout[i];
148 }
149 }
150 } else
151 remainingLen -= totalFixed;
152
153 // Percentage columns/rows are our second priority. Divide the remaining spa ce proportionally
154 // over all percentage columns/rows. IMPORTANT: the size of each column/row is not relative
155 // to 100%, but to the total percentage. For example, if there are three col umns, each of 75%,
156 // and the available space is 300px, each column will become 100px in width.
157 if (totalPercent > remainingLen) {
158 int remainingPercent = remainingLen;
159
160 for (int i = 0; i < gridLen; ++i) {
161 if (grid[i].isPercentage()) {
162 gridLayout[i] = (gridLayout[i] * remainingPercent) / totalPercen t;
163 remainingLen -= gridLayout[i];
164 }
165 }
166 } else
167 remainingLen -= totalPercent;
168
169 // Relative columns/rows are our last priority. Divide the remaining space p roportionally
170 // over all relative columns/rows. IMPORTANT: the relative value of 0* is tr eated as 1*.
171 if (countRelative) {
172 int lastRelative = 0;
173 int remainingRelative = remainingLen;
174
175 for (int i = 0; i < gridLen; ++i) {
176 if (grid[i].isRelative()) {
177 gridLayout[i] = (max(grid[i].value(), 1.) * remainingRelative) / totalRelative;
178 remainingLen -= gridLayout[i];
179 lastRelative = i;
180 }
181 }
182
183 // If we could not evenly distribute the available space of all of the r elative
184 // columns/rows, the remainder will be added to the last column/row.
185 // For example: if we have a space of 100px and three columns (*,*,*), t he remainder will
186 // be 1px and will be added to the last column: 33px, 33px, 34px.
187 if (remainingLen) {
188 gridLayout[lastRelative] += remainingLen;
189 remainingLen = 0;
190 }
191 }
192
193 // If we still have some left over space we need to divide it over the alrea dy existing
194 // columns/rows
195 if (remainingLen) {
196 // Our first priority is to spread if over the percentage columns. The r emaining
197 // space is spread evenly, for example: if we have a space of 100px, the columns
198 // definition of 25%,25% used to result in two columns of 25px. After th is the
199 // columns will each be 50px in width.
200 if (countPercent && totalPercent) {
201 int remainingPercent = remainingLen;
202 int changePercent = 0;
203
204 for (int i = 0; i < gridLen; ++i) {
205 if (grid[i].isPercentage()) {
206 changePercent = (remainingPercent * gridLayout[i]) / totalPe rcent;
207 gridLayout[i] += changePercent;
208 remainingLen -= changePercent;
209 }
210 }
211 } else if (totalFixed) {
212 // Our last priority is to spread the remaining space over the fixed columns.
213 // For example if we have 100px of space and two column of each 40px , both
214 // columns will become exactly 50px.
215 int remainingFixed = remainingLen;
216 int changeFixed = 0;
217
218 for (int i = 0; i < gridLen; ++i) {
219 if (grid[i].isAbsolute()) {
220 changeFixed = (remainingFixed * gridLayout[i]) / totalFixed;
221 gridLayout[i] += changeFixed;
222 remainingLen -= changeFixed;
223 }
224 }
225 }
226 }
227
228 // If we still have some left over space we probably ended up with a remaind er of
229 // a division. We cannot spread it evenly anymore. If we have any percentage
230 // columns/rows simply spread the remainder equally over all available perce ntage columns,
231 // regardless of their size.
232 if (remainingLen && countPercent) {
233 int remainingPercent = remainingLen;
234 int changePercent = 0;
235
236 for (int i = 0; i < gridLen; ++i) {
237 if (grid[i].isPercentage()) {
238 changePercent = remainingPercent / countPercent;
239 gridLayout[i] += changePercent;
240 remainingLen -= changePercent;
241 }
242 }
243 } else if (remainingLen && countFixed) {
244 // If we don't have any percentage columns/rows we only have
245 // fixed columns. Spread the remainder equally over all fixed
246 // columns/rows.
247 int remainingFixed = remainingLen;
248 int changeFixed = 0;
249
250 for (int i = 0; i < gridLen; ++i) {
251 if (grid[i].isAbsolute()) {
252 changeFixed = remainingFixed / countFixed;
253 gridLayout[i] += changeFixed;
254 remainingLen -= changeFixed;
255 }
256 }
257 }
258
259 // Still some left over. Add it to the last column, because it is impossible
260 // spread it evenly or equally.
261 if (remainingLen)
262 gridLayout[gridLen - 1] += remainingLen;
263
264 // now we have the final layout, distribute the delta over it
265 bool worked = true;
266 int* gridDelta = axis.m_deltas.data();
267 for (int i = 0; i < gridLen; ++i) {
268 if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0)
269 worked = false;
270 gridLayout[i] += gridDelta[i];
271 }
272 // if the deltas broke something, undo them
273 if (!worked) {
274 for (int i = 0; i < gridLen; ++i)
275 gridLayout[i] -= gridDelta[i];
276 axis.m_deltas.fill(0);
277 }
278 }
279
280 void RenderFrameSet::notifyFrameEdgeInfoChanged()
281 {
282 if (needsLayout())
283 return;
284 // FIXME: We should only recompute the edge info with respect to the frame t hat changed
285 // and its adjacent frame(s) instead of recomputing the edge info for the en tire frameset.
286 computeEdgeInfo();
287 }
288
289 void RenderFrameSet::fillFromEdgeInfo(const FrameEdgeInfo& edgeInfo, int r, int c)
290 {
291 if (edgeInfo.allowBorder(LeftFrameEdge))
292 m_cols.m_allowBorder[c] = true;
293 if (edgeInfo.allowBorder(RightFrameEdge))
294 m_cols.m_allowBorder[c + 1] = true;
295 if (edgeInfo.preventResize(LeftFrameEdge))
296 m_cols.m_preventResize[c] = true;
297 if (edgeInfo.preventResize(RightFrameEdge))
298 m_cols.m_preventResize[c + 1] = true;
299
300 if (edgeInfo.allowBorder(TopFrameEdge))
301 m_rows.m_allowBorder[r] = true;
302 if (edgeInfo.allowBorder(BottomFrameEdge))
303 m_rows.m_allowBorder[r + 1] = true;
304 if (edgeInfo.preventResize(TopFrameEdge))
305 m_rows.m_preventResize[r] = true;
306 if (edgeInfo.preventResize(BottomFrameEdge))
307 m_rows.m_preventResize[r + 1] = true;
308 }
309
310 void RenderFrameSet::computeEdgeInfo()
311 {
312 m_rows.m_preventResize.fill(frameSet()->noResize());
313 m_rows.m_allowBorder.fill(false);
314 m_cols.m_preventResize.fill(frameSet()->noResize());
315 m_cols.m_allowBorder.fill(false);
316
317 LayoutObject* child = firstChild();
318 if (!child)
319 return;
320
321 size_t rows = m_rows.m_sizes.size();
322 size_t cols = m_cols.m_sizes.size();
323 for (size_t r = 0; r < rows; ++r) {
324 for (size_t c = 0; c < cols; ++c) {
325 FrameEdgeInfo edgeInfo;
326 if (child->isFrameSet())
327 edgeInfo = toRenderFrameSet(child)->edgeInfo();
328 else
329 edgeInfo = toRenderFrame(child)->edgeInfo();
330 fillFromEdgeInfo(edgeInfo, r, c);
331 child = child->nextSibling();
332 if (!child)
333 return;
334 }
335 }
336 }
337
338 FrameEdgeInfo RenderFrameSet::edgeInfo() const
339 {
340 FrameEdgeInfo result(frameSet()->noResize(), true);
341
342 int rows = frameSet()->totalRows();
343 int cols = frameSet()->totalCols();
344 if (rows && cols) {
345 result.setPreventResize(LeftFrameEdge, m_cols.m_preventResize[0]);
346 result.setAllowBorder(LeftFrameEdge, m_cols.m_allowBorder[0]);
347 result.setPreventResize(RightFrameEdge, m_cols.m_preventResize[cols]);
348 result.setAllowBorder(RightFrameEdge, m_cols.m_allowBorder[cols]);
349 result.setPreventResize(TopFrameEdge, m_rows.m_preventResize[0]);
350 result.setAllowBorder(TopFrameEdge, m_rows.m_allowBorder[0]);
351 result.setPreventResize(BottomFrameEdge, m_rows.m_preventResize[rows]);
352 result.setAllowBorder(BottomFrameEdge, m_rows.m_allowBorder[rows]);
353 }
354
355 return result;
356 }
357
358 void RenderFrameSet::layout()
359 {
360 ASSERT(needsLayout());
361
362 if (!parent()->isFrameSet() && !document().printing()) {
363 setWidth(view()->viewWidth());
364 setHeight(view()->viewHeight());
365 }
366
367 unsigned cols = frameSet()->totalCols();
368 unsigned rows = frameSet()->totalRows();
369
370 if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) {
371 m_rows.resize(rows);
372 m_cols.resize(cols);
373 }
374
375 LayoutUnit borderThickness = frameSet()->border();
376 layOutAxis(m_rows, frameSet()->rowLengths(), size().height() - (rows - 1) * borderThickness);
377 layOutAxis(m_cols, frameSet()->colLengths(), size().width() - (cols - 1) * b orderThickness);
378
379 positionFrames();
380
381 RenderBox::layout();
382
383 computeEdgeInfo();
384
385 updateLayerTransformAfterLayout();
386
387 clearNeedsLayout();
388 }
389
390 static void clearNeedsLayoutOnHiddenFrames(RenderBox* frame)
391 {
392 for (; frame; frame = frame->nextSiblingBox()) {
393 frame->setWidth(0);
394 frame->setHeight(0);
395 frame->clearNeedsLayout();
396 clearNeedsLayoutOnHiddenFrames(frame->firstChildBox());
397 }
398 }
399
400 void RenderFrameSet::positionFrames()
401 {
402 RenderBox* child = firstChildBox();
403 if (!child)
404 return;
405
406 int rows = frameSet()->totalRows();
407 int cols = frameSet()->totalCols();
408
409 int borderThickness = frameSet()->border();
410 LayoutSize size;
411 LayoutPoint position;
412 for (int r = 0; r < rows; r++) {
413 position.setX(0);
414 size.setHeight(m_rows.m_sizes[r]);
415 for (int c = 0; c < cols; c++) {
416 child->setLocation(position);
417 size.setWidth(m_cols.m_sizes[c]);
418
419 // has to be resized and itself resize its contents
420 if (size != child->size()) {
421 child->setSize(size);
422 child->setNeedsLayoutAndFullPaintInvalidation();
423 child->layout();
424 }
425
426 position.setX(position.x() + size.width() + borderThickness);
427
428 child = child->nextSiblingBox();
429 if (!child)
430 return;
431 }
432 position.setY(position.y() + size.height() + borderThickness);
433 }
434
435 // All the remaining frames are hidden to avoid ugly spurious unflowed frame s.
436 clearNeedsLayoutOnHiddenFrames(child);
437 }
438
439 void RenderFrameSet::startResizing(GridAxis& axis, int position)
440 {
441 int split = hitTestSplit(axis, position);
442 if (split == noSplit || axis.m_preventResize[split]) {
443 axis.m_splitBeingResized = noSplit;
444 return;
445 }
446 axis.m_splitBeingResized = split;
447 axis.m_splitResizeOffset = position - splitPosition(axis, split);
448 }
449
450 void RenderFrameSet::continueResizing(GridAxis& axis, int position)
451 {
452 if (needsLayout())
453 return;
454 if (axis.m_splitBeingResized == noSplit)
455 return;
456 int currentSplitPosition = splitPosition(axis, axis.m_splitBeingResized);
457 int delta = (position - currentSplitPosition) - axis.m_splitResizeOffset;
458 if (!delta)
459 return;
460 axis.m_deltas[axis.m_splitBeingResized - 1] += delta;
461 axis.m_deltas[axis.m_splitBeingResized] -= delta;
462 setNeedsLayoutAndFullPaintInvalidation();
463 }
464
465 bool RenderFrameSet::userResize(MouseEvent* evt)
466 {
467 if (!m_isResizing) {
468 if (needsLayout())
469 return false;
470 if (evt->type() == EventTypeNames::mousedown && evt->button() == LeftBut ton) {
471 FloatPoint localPos = absoluteToLocal(FloatPoint(evt->absoluteLocati on()), UseTransforms);
472 startResizing(m_cols, localPos.x());
473 startResizing(m_rows, localPos.y());
474 if (m_cols.m_splitBeingResized != noSplit || m_rows.m_splitBeingResi zed != noSplit) {
475 setIsResizing(true);
476 return true;
477 }
478 }
479 } else {
480 if (evt->type() == EventTypeNames::mousemove || (evt->type() == EventTyp eNames::mouseup && evt->button() == LeftButton)) {
481 FloatPoint localPos = absoluteToLocal(FloatPoint(evt->absoluteLocati on()), UseTransforms);
482 continueResizing(m_cols, localPos.x());
483 continueResizing(m_rows, localPos.y());
484 if (evt->type() == EventTypeNames::mouseup && evt->button() == LeftB utton) {
485 setIsResizing(false);
486 return true;
487 }
488 }
489 }
490
491 return false;
492 }
493
494 void RenderFrameSet::setIsResizing(bool isResizing)
495 {
496 m_isResizing = isResizing;
497 for (LayoutObject* ancestor = parent(); ancestor; ancestor = ancestor->paren t()) {
498 if (ancestor->isFrameSet())
499 toRenderFrameSet(ancestor)->m_isChildResizing = isResizing;
500 }
501 if (LocalFrame* frame = this->frame())
502 frame->eventHandler().setResizingFrameSet(isResizing ? frameSet() : 0);
503 }
504
505 bool RenderFrameSet::canResizeRow(const IntPoint& p) const
506 {
507 int r = hitTestSplit(m_rows, p.y());
508 return r != noSplit && !m_rows.m_preventResize[r];
509 }
510
511 bool RenderFrameSet::canResizeColumn(const IntPoint& p) const
512 {
513 int c = hitTestSplit(m_cols, p.x());
514 return c != noSplit && !m_cols.m_preventResize[c];
515 }
516
517 int RenderFrameSet::splitPosition(const GridAxis& axis, int split) const
518 {
519 if (needsLayout())
520 return 0;
521
522 int borderThickness = frameSet()->border();
523
524 int size = axis.m_sizes.size();
525 if (!size)
526 return 0;
527
528 int position = 0;
529 for (int i = 0; i < split && i < size; ++i)
530 position += axis.m_sizes[i] + borderThickness;
531 return position - borderThickness;
532 }
533
534 int RenderFrameSet::hitTestSplit(const GridAxis& axis, int position) const
535 {
536 if (needsLayout())
537 return noSplit;
538
539 int borderThickness = frameSet()->border();
540 if (borderThickness <= 0)
541 return noSplit;
542
543 size_t size = axis.m_sizes.size();
544 if (!size)
545 return noSplit;
546
547 int splitPosition = axis.m_sizes[0];
548 for (size_t i = 1; i < size; ++i) {
549 if (position >= splitPosition && position < splitPosition + borderThickn ess)
550 return i;
551 splitPosition += borderThickness + axis.m_sizes[i];
552 }
553 return noSplit;
554 }
555
556 bool RenderFrameSet::isChildAllowed(LayoutObject* child, const LayoutStyle&) con st
557 {
558 return child->isFrame() || child->isFrameSet();
559 }
560
561 CursorDirective RenderFrameSet::getCursor(const LayoutPoint& point, Cursor& curs or) const
562 {
563 IntPoint roundedPoint = roundedIntPoint(point);
564 if (canResizeRow(roundedPoint)) {
565 cursor = rowResizeCursor();
566 return SetCursor;
567 }
568 if (canResizeColumn(roundedPoint)) {
569 cursor = columnResizeCursor();
570 return SetCursor;
571 }
572 return RenderBox::getCursor(point, cursor);
573 }
574
575 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderFrameSet.h ('k') | Source/web/WebLocalFrameImpl.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698