Index: Source/core/rendering/RenderFrameSet.cpp |
diff --git a/Source/core/rendering/RenderFrameSet.cpp b/Source/core/rendering/RenderFrameSet.cpp |
deleted file mode 100644 |
index 934842a1e8455da4d61f8d882b7c4b805fd0b282..0000000000000000000000000000000000000000 |
--- a/Source/core/rendering/RenderFrameSet.cpp |
+++ /dev/null |
@@ -1,575 +0,0 @@ |
-/** |
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
- * (C) 2000 Simon Hausmann <hausmann@kde.org> |
- * (C) 2000 Stefan Schimanski (1Stein@gmx.de) |
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. |
- * |
- * This library is free software; you can redistribute it and/or |
- * modify it under the terms of the GNU Library General Public |
- * License as published by the Free Software Foundation; either |
- * version 2 of the License, or (at your option) any later version. |
- * |
- * This library is distributed in the hope that it will be useful, |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
- * Library General Public License for more details. |
- * |
- * You should have received a copy of the GNU Library General Public License |
- * along with this library; see the file COPYING.LIB. If not, write to |
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
- * Boston, MA 02110-1301, USA. |
- * |
- */ |
- |
-#include "config.h" |
-#include "core/rendering/RenderFrameSet.h" |
- |
-#include "core/dom/Document.h" |
-#include "core/events/MouseEvent.h" |
-#include "core/frame/LocalFrame.h" |
-#include "core/html/HTMLDimension.h" |
-#include "core/html/HTMLFrameSetElement.h" |
-#include "core/layout/PaintInfo.h" |
-#include "core/page/EventHandler.h" |
-#include "core/paint/FrameSetPainter.h" |
-#include "core/rendering/RenderFrame.h" |
-#include "core/rendering/RenderView.h" |
-#include "platform/Cursor.h" |
-#include "platform/graphics/GraphicsContext.h" |
- |
-namespace blink { |
- |
-RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet) |
- : RenderBox(frameSet) |
- , m_isResizing(false) |
- , m_isChildResizing(false) |
-{ |
- setInline(false); |
-} |
- |
-RenderFrameSet::~RenderFrameSet() |
-{ |
-} |
- |
-RenderFrameSet::GridAxis::GridAxis() |
- : m_splitBeingResized(noSplit) |
-{ |
-} |
- |
-HTMLFrameSetElement* RenderFrameSet::frameSet() const |
-{ |
- return toHTMLFrameSetElement(node()); |
-} |
- |
-void RenderFrameSet::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
-{ |
- FrameSetPainter(*this).paint(paintInfo, paintOffset); |
-} |
- |
-void RenderFrameSet::computePreferredLogicalWidths() |
-{ |
- m_minPreferredLogicalWidth = 0; |
- m_maxPreferredLogicalWidth = 0; |
- clearPreferredLogicalWidthsDirty(); |
-} |
- |
-void RenderFrameSet::GridAxis::resize(int size) |
-{ |
- m_sizes.resize(size); |
- m_deltas.resize(size); |
- m_deltas.fill(0); |
- |
- // To track edges for resizability and borders, we need to be (size + 1). This is because a parent frameset |
- // may ask us for information about our left/top/right/bottom edges in order to make its own decisions about |
- // what to do. We are capable of tainting that parent frameset's borders, so we have to cache this info. |
- m_preventResize.resize(size + 1); |
- m_allowBorder.resize(size + 1); |
-} |
- |
-void RenderFrameSet::layOutAxis(GridAxis& axis, const Vector<HTMLDimension>& grid, int availableLen) |
-{ |
- availableLen = max(availableLen, 0); |
- |
- int* gridLayout = axis.m_sizes.data(); |
- |
- if (grid.isEmpty()) { |
- gridLayout[0] = availableLen; |
- return; |
- } |
- |
- int gridLen = axis.m_sizes.size(); |
- ASSERT(gridLen); |
- |
- int totalRelative = 0; |
- int totalFixed = 0; |
- int totalPercent = 0; |
- int countRelative = 0; |
- int countFixed = 0; |
- int countPercent = 0; |
- |
- // First we need to investigate how many columns of each type we have and |
- // how much space these columns are going to require. |
- for (int i = 0; i < gridLen; ++i) { |
- // Count the total length of all of the fixed columns/rows -> totalFixed |
- // Count the number of columns/rows which are fixed -> countFixed |
- if (grid[i].isAbsolute()) { |
- gridLayout[i] = max<int>(grid[i].value(), 0); |
- totalFixed += gridLayout[i]; |
- countFixed++; |
- } |
- |
- // Count the total percentage of all of the percentage columns/rows -> totalPercent |
- // Count the number of columns/rows which are percentages -> countPercent |
- if (grid[i].isPercentage()) { |
- gridLayout[i] = max<int>(grid[i].value() * availableLen / 100., 0); |
- totalPercent += gridLayout[i]; |
- countPercent++; |
- } |
- |
- // Count the total relative of all the relative columns/rows -> totalRelative |
- // Count the number of columns/rows which are relative -> countRelative |
- if (grid[i].isRelative()) { |
- totalRelative += max<int>(grid[i].value(), 1); |
- countRelative++; |
- } |
- } |
- |
- int remainingLen = availableLen; |
- |
- // Fixed columns/rows are our first priority. If there is not enough space to fit all fixed |
- // columns/rows we need to proportionally adjust their size. |
- if (totalFixed > remainingLen) { |
- int remainingFixed = remainingLen; |
- |
- for (int i = 0; i < gridLen; ++i) { |
- if (grid[i].isAbsolute()) { |
- gridLayout[i] = (gridLayout[i] * remainingFixed) / totalFixed; |
- remainingLen -= gridLayout[i]; |
- } |
- } |
- } else |
- remainingLen -= totalFixed; |
- |
- // Percentage columns/rows are our second priority. Divide the remaining space proportionally |
- // over all percentage columns/rows. IMPORTANT: the size of each column/row is not relative |
- // to 100%, but to the total percentage. For example, if there are three columns, each of 75%, |
- // and the available space is 300px, each column will become 100px in width. |
- if (totalPercent > remainingLen) { |
- int remainingPercent = remainingLen; |
- |
- for (int i = 0; i < gridLen; ++i) { |
- if (grid[i].isPercentage()) { |
- gridLayout[i] = (gridLayout[i] * remainingPercent) / totalPercent; |
- remainingLen -= gridLayout[i]; |
- } |
- } |
- } else |
- remainingLen -= totalPercent; |
- |
- // Relative columns/rows are our last priority. Divide the remaining space proportionally |
- // over all relative columns/rows. IMPORTANT: the relative value of 0* is treated as 1*. |
- if (countRelative) { |
- int lastRelative = 0; |
- int remainingRelative = remainingLen; |
- |
- for (int i = 0; i < gridLen; ++i) { |
- if (grid[i].isRelative()) { |
- gridLayout[i] = (max(grid[i].value(), 1.) * remainingRelative) / totalRelative; |
- remainingLen -= gridLayout[i]; |
- lastRelative = i; |
- } |
- } |
- |
- // If we could not evenly distribute the available space of all of the relative |
- // columns/rows, the remainder will be added to the last column/row. |
- // For example: if we have a space of 100px and three columns (*,*,*), the remainder will |
- // be 1px and will be added to the last column: 33px, 33px, 34px. |
- if (remainingLen) { |
- gridLayout[lastRelative] += remainingLen; |
- remainingLen = 0; |
- } |
- } |
- |
- // If we still have some left over space we need to divide it over the already existing |
- // columns/rows |
- if (remainingLen) { |
- // Our first priority is to spread if over the percentage columns. The remaining |
- // space is spread evenly, for example: if we have a space of 100px, the columns |
- // definition of 25%,25% used to result in two columns of 25px. After this the |
- // columns will each be 50px in width. |
- if (countPercent && totalPercent) { |
- int remainingPercent = remainingLen; |
- int changePercent = 0; |
- |
- for (int i = 0; i < gridLen; ++i) { |
- if (grid[i].isPercentage()) { |
- changePercent = (remainingPercent * gridLayout[i]) / totalPercent; |
- gridLayout[i] += changePercent; |
- remainingLen -= changePercent; |
- } |
- } |
- } else if (totalFixed) { |
- // Our last priority is to spread the remaining space over the fixed columns. |
- // For example if we have 100px of space and two column of each 40px, both |
- // columns will become exactly 50px. |
- int remainingFixed = remainingLen; |
- int changeFixed = 0; |
- |
- for (int i = 0; i < gridLen; ++i) { |
- if (grid[i].isAbsolute()) { |
- changeFixed = (remainingFixed * gridLayout[i]) / totalFixed; |
- gridLayout[i] += changeFixed; |
- remainingLen -= changeFixed; |
- } |
- } |
- } |
- } |
- |
- // If we still have some left over space we probably ended up with a remainder of |
- // a division. We cannot spread it evenly anymore. If we have any percentage |
- // columns/rows simply spread the remainder equally over all available percentage columns, |
- // regardless of their size. |
- if (remainingLen && countPercent) { |
- int remainingPercent = remainingLen; |
- int changePercent = 0; |
- |
- for (int i = 0; i < gridLen; ++i) { |
- if (grid[i].isPercentage()) { |
- changePercent = remainingPercent / countPercent; |
- gridLayout[i] += changePercent; |
- remainingLen -= changePercent; |
- } |
- } |
- } else if (remainingLen && countFixed) { |
- // If we don't have any percentage columns/rows we only have |
- // fixed columns. Spread the remainder equally over all fixed |
- // columns/rows. |
- int remainingFixed = remainingLen; |
- int changeFixed = 0; |
- |
- for (int i = 0; i < gridLen; ++i) { |
- if (grid[i].isAbsolute()) { |
- changeFixed = remainingFixed / countFixed; |
- gridLayout[i] += changeFixed; |
- remainingLen -= changeFixed; |
- } |
- } |
- } |
- |
- // Still some left over. Add it to the last column, because it is impossible |
- // spread it evenly or equally. |
- if (remainingLen) |
- gridLayout[gridLen - 1] += remainingLen; |
- |
- // now we have the final layout, distribute the delta over it |
- bool worked = true; |
- int* gridDelta = axis.m_deltas.data(); |
- for (int i = 0; i < gridLen; ++i) { |
- if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0) |
- worked = false; |
- gridLayout[i] += gridDelta[i]; |
- } |
- // if the deltas broke something, undo them |
- if (!worked) { |
- for (int i = 0; i < gridLen; ++i) |
- gridLayout[i] -= gridDelta[i]; |
- axis.m_deltas.fill(0); |
- } |
-} |
- |
-void RenderFrameSet::notifyFrameEdgeInfoChanged() |
-{ |
- if (needsLayout()) |
- return; |
- // FIXME: We should only recompute the edge info with respect to the frame that changed |
- // and its adjacent frame(s) instead of recomputing the edge info for the entire frameset. |
- computeEdgeInfo(); |
-} |
- |
-void RenderFrameSet::fillFromEdgeInfo(const FrameEdgeInfo& edgeInfo, int r, int c) |
-{ |
- if (edgeInfo.allowBorder(LeftFrameEdge)) |
- m_cols.m_allowBorder[c] = true; |
- if (edgeInfo.allowBorder(RightFrameEdge)) |
- m_cols.m_allowBorder[c + 1] = true; |
- if (edgeInfo.preventResize(LeftFrameEdge)) |
- m_cols.m_preventResize[c] = true; |
- if (edgeInfo.preventResize(RightFrameEdge)) |
- m_cols.m_preventResize[c + 1] = true; |
- |
- if (edgeInfo.allowBorder(TopFrameEdge)) |
- m_rows.m_allowBorder[r] = true; |
- if (edgeInfo.allowBorder(BottomFrameEdge)) |
- m_rows.m_allowBorder[r + 1] = true; |
- if (edgeInfo.preventResize(TopFrameEdge)) |
- m_rows.m_preventResize[r] = true; |
- if (edgeInfo.preventResize(BottomFrameEdge)) |
- m_rows.m_preventResize[r + 1] = true; |
-} |
- |
-void RenderFrameSet::computeEdgeInfo() |
-{ |
- m_rows.m_preventResize.fill(frameSet()->noResize()); |
- m_rows.m_allowBorder.fill(false); |
- m_cols.m_preventResize.fill(frameSet()->noResize()); |
- m_cols.m_allowBorder.fill(false); |
- |
- LayoutObject* child = firstChild(); |
- if (!child) |
- return; |
- |
- size_t rows = m_rows.m_sizes.size(); |
- size_t cols = m_cols.m_sizes.size(); |
- for (size_t r = 0; r < rows; ++r) { |
- for (size_t c = 0; c < cols; ++c) { |
- FrameEdgeInfo edgeInfo; |
- if (child->isFrameSet()) |
- edgeInfo = toRenderFrameSet(child)->edgeInfo(); |
- else |
- edgeInfo = toRenderFrame(child)->edgeInfo(); |
- fillFromEdgeInfo(edgeInfo, r, c); |
- child = child->nextSibling(); |
- if (!child) |
- return; |
- } |
- } |
-} |
- |
-FrameEdgeInfo RenderFrameSet::edgeInfo() const |
-{ |
- FrameEdgeInfo result(frameSet()->noResize(), true); |
- |
- int rows = frameSet()->totalRows(); |
- int cols = frameSet()->totalCols(); |
- if (rows && cols) { |
- result.setPreventResize(LeftFrameEdge, m_cols.m_preventResize[0]); |
- result.setAllowBorder(LeftFrameEdge, m_cols.m_allowBorder[0]); |
- result.setPreventResize(RightFrameEdge, m_cols.m_preventResize[cols]); |
- result.setAllowBorder(RightFrameEdge, m_cols.m_allowBorder[cols]); |
- result.setPreventResize(TopFrameEdge, m_rows.m_preventResize[0]); |
- result.setAllowBorder(TopFrameEdge, m_rows.m_allowBorder[0]); |
- result.setPreventResize(BottomFrameEdge, m_rows.m_preventResize[rows]); |
- result.setAllowBorder(BottomFrameEdge, m_rows.m_allowBorder[rows]); |
- } |
- |
- return result; |
-} |
- |
-void RenderFrameSet::layout() |
-{ |
- ASSERT(needsLayout()); |
- |
- if (!parent()->isFrameSet() && !document().printing()) { |
- setWidth(view()->viewWidth()); |
- setHeight(view()->viewHeight()); |
- } |
- |
- unsigned cols = frameSet()->totalCols(); |
- unsigned rows = frameSet()->totalRows(); |
- |
- if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) { |
- m_rows.resize(rows); |
- m_cols.resize(cols); |
- } |
- |
- LayoutUnit borderThickness = frameSet()->border(); |
- layOutAxis(m_rows, frameSet()->rowLengths(), size().height() - (rows - 1) * borderThickness); |
- layOutAxis(m_cols, frameSet()->colLengths(), size().width() - (cols - 1) * borderThickness); |
- |
- positionFrames(); |
- |
- RenderBox::layout(); |
- |
- computeEdgeInfo(); |
- |
- updateLayerTransformAfterLayout(); |
- |
- clearNeedsLayout(); |
-} |
- |
-static void clearNeedsLayoutOnHiddenFrames(RenderBox* frame) |
-{ |
- for (; frame; frame = frame->nextSiblingBox()) { |
- frame->setWidth(0); |
- frame->setHeight(0); |
- frame->clearNeedsLayout(); |
- clearNeedsLayoutOnHiddenFrames(frame->firstChildBox()); |
- } |
-} |
- |
-void RenderFrameSet::positionFrames() |
-{ |
- RenderBox* child = firstChildBox(); |
- if (!child) |
- return; |
- |
- int rows = frameSet()->totalRows(); |
- int cols = frameSet()->totalCols(); |
- |
- int borderThickness = frameSet()->border(); |
- LayoutSize size; |
- LayoutPoint position; |
- for (int r = 0; r < rows; r++) { |
- position.setX(0); |
- size.setHeight(m_rows.m_sizes[r]); |
- for (int c = 0; c < cols; c++) { |
- child->setLocation(position); |
- size.setWidth(m_cols.m_sizes[c]); |
- |
- // has to be resized and itself resize its contents |
- if (size != child->size()) { |
- child->setSize(size); |
- child->setNeedsLayoutAndFullPaintInvalidation(); |
- child->layout(); |
- } |
- |
- position.setX(position.x() + size.width() + borderThickness); |
- |
- child = child->nextSiblingBox(); |
- if (!child) |
- return; |
- } |
- position.setY(position.y() + size.height() + borderThickness); |
- } |
- |
- // All the remaining frames are hidden to avoid ugly spurious unflowed frames. |
- clearNeedsLayoutOnHiddenFrames(child); |
-} |
- |
-void RenderFrameSet::startResizing(GridAxis& axis, int position) |
-{ |
- int split = hitTestSplit(axis, position); |
- if (split == noSplit || axis.m_preventResize[split]) { |
- axis.m_splitBeingResized = noSplit; |
- return; |
- } |
- axis.m_splitBeingResized = split; |
- axis.m_splitResizeOffset = position - splitPosition(axis, split); |
-} |
- |
-void RenderFrameSet::continueResizing(GridAxis& axis, int position) |
-{ |
- if (needsLayout()) |
- return; |
- if (axis.m_splitBeingResized == noSplit) |
- return; |
- int currentSplitPosition = splitPosition(axis, axis.m_splitBeingResized); |
- int delta = (position - currentSplitPosition) - axis.m_splitResizeOffset; |
- if (!delta) |
- return; |
- axis.m_deltas[axis.m_splitBeingResized - 1] += delta; |
- axis.m_deltas[axis.m_splitBeingResized] -= delta; |
- setNeedsLayoutAndFullPaintInvalidation(); |
-} |
- |
-bool RenderFrameSet::userResize(MouseEvent* evt) |
-{ |
- if (!m_isResizing) { |
- if (needsLayout()) |
- return false; |
- if (evt->type() == EventTypeNames::mousedown && evt->button() == LeftButton) { |
- FloatPoint localPos = absoluteToLocal(FloatPoint(evt->absoluteLocation()), UseTransforms); |
- startResizing(m_cols, localPos.x()); |
- startResizing(m_rows, localPos.y()); |
- if (m_cols.m_splitBeingResized != noSplit || m_rows.m_splitBeingResized != noSplit) { |
- setIsResizing(true); |
- return true; |
- } |
- } |
- } else { |
- if (evt->type() == EventTypeNames::mousemove || (evt->type() == EventTypeNames::mouseup && evt->button() == LeftButton)) { |
- FloatPoint localPos = absoluteToLocal(FloatPoint(evt->absoluteLocation()), UseTransforms); |
- continueResizing(m_cols, localPos.x()); |
- continueResizing(m_rows, localPos.y()); |
- if (evt->type() == EventTypeNames::mouseup && evt->button() == LeftButton) { |
- setIsResizing(false); |
- return true; |
- } |
- } |
- } |
- |
- return false; |
-} |
- |
-void RenderFrameSet::setIsResizing(bool isResizing) |
-{ |
- m_isResizing = isResizing; |
- for (LayoutObject* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { |
- if (ancestor->isFrameSet()) |
- toRenderFrameSet(ancestor)->m_isChildResizing = isResizing; |
- } |
- if (LocalFrame* frame = this->frame()) |
- frame->eventHandler().setResizingFrameSet(isResizing ? frameSet() : 0); |
-} |
- |
-bool RenderFrameSet::canResizeRow(const IntPoint& p) const |
-{ |
- int r = hitTestSplit(m_rows, p.y()); |
- return r != noSplit && !m_rows.m_preventResize[r]; |
-} |
- |
-bool RenderFrameSet::canResizeColumn(const IntPoint& p) const |
-{ |
- int c = hitTestSplit(m_cols, p.x()); |
- return c != noSplit && !m_cols.m_preventResize[c]; |
-} |
- |
-int RenderFrameSet::splitPosition(const GridAxis& axis, int split) const |
-{ |
- if (needsLayout()) |
- return 0; |
- |
- int borderThickness = frameSet()->border(); |
- |
- int size = axis.m_sizes.size(); |
- if (!size) |
- return 0; |
- |
- int position = 0; |
- for (int i = 0; i < split && i < size; ++i) |
- position += axis.m_sizes[i] + borderThickness; |
- return position - borderThickness; |
-} |
- |
-int RenderFrameSet::hitTestSplit(const GridAxis& axis, int position) const |
-{ |
- if (needsLayout()) |
- return noSplit; |
- |
- int borderThickness = frameSet()->border(); |
- if (borderThickness <= 0) |
- return noSplit; |
- |
- size_t size = axis.m_sizes.size(); |
- if (!size) |
- return noSplit; |
- |
- int splitPosition = axis.m_sizes[0]; |
- for (size_t i = 1; i < size; ++i) { |
- if (position >= splitPosition && position < splitPosition + borderThickness) |
- return i; |
- splitPosition += borderThickness + axis.m_sizes[i]; |
- } |
- return noSplit; |
-} |
- |
-bool RenderFrameSet::isChildAllowed(LayoutObject* child, const LayoutStyle&) const |
-{ |
- return child->isFrame() || child->isFrameSet(); |
-} |
- |
-CursorDirective RenderFrameSet::getCursor(const LayoutPoint& point, Cursor& cursor) const |
-{ |
- IntPoint roundedPoint = roundedIntPoint(point); |
- if (canResizeRow(roundedPoint)) { |
- cursor = rowResizeCursor(); |
- return SetCursor; |
- } |
- if (canResizeColumn(roundedPoint)) { |
- cursor = columnResizeCursor(); |
- return SetCursor; |
- } |
- return RenderBox::getCursor(point, cursor); |
-} |
- |
-} // namespace blink |