📄 renderframeset.cpp
字号:
/** * This file is part of the KDE project. * * 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 "RenderFrameSet.h"#include "Document.h"#include "EventHandler.h"#include "EventNames.h"#include "Frame.h"#include "FrameView.h"#include "GraphicsContext.h"#include "HTMLFrameSetElement.h"#include "HitTestRequest.h"#include "HitTestResult.h"#include "MouseEvent.h"#include "RenderFrame.h"#include "RenderView.h"namespace WebCore {RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet) : RenderBox(frameSet) , m_isResizing(false) , m_isChildResizing(false){ setInline(false);}RenderFrameSet::~RenderFrameSet(){}RenderFrameSet::GridAxis::GridAxis() : m_splitBeingResized(noSplit){}inline HTMLFrameSetElement* RenderFrameSet::frameSet() const{ return static_cast<HTMLFrameSetElement*>(node());}static Color borderStartEdgeColor(){ return Color(170,170,170);}static Color borderEndEdgeColor(){ return Color::black;}static Color borderFillColor(){ return Color(208, 208, 208);}void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const IntRect& borderRect){ if (!paintInfo.rect.intersects(borderRect)) return; // FIXME: We should do something clever when borders from distinct framesets meet at a join. // Fill first. GraphicsContext* context = paintInfo.context; context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor()); // Now stroke the edges but only if we have enough room to paint both edges with a little // bit of the fill color showing through. if (borderRect.width() >= 3) { context->fillRect(IntRect(borderRect.topLeft(), IntSize(1, height())), borderStartEdgeColor()); context->fillRect(IntRect(borderRect.topRight(), IntSize(1, height())), borderEndEdgeColor()); }}void RenderFrameSet::paintRowBorder(const PaintInfo& paintInfo, const IntRect& borderRect){ if (!paintInfo.rect.intersects(borderRect)) return; // FIXME: We should do something clever when borders from distinct framesets meet at a join. // Fill first. GraphicsContext* context = paintInfo.context; context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->borderLeftColor() : borderFillColor()); // Now stroke the edges but only if we have enough room to paint both edges with a little // bit of the fill color showing through. if (borderRect.height() >= 3) { context->fillRect(IntRect(borderRect.topLeft(), IntSize(width(), 1)), borderStartEdgeColor()); context->fillRect(IntRect(borderRect.bottomLeft(), IntSize(width(), 1)), borderEndEdgeColor()); }}void RenderFrameSet::paint(PaintInfo& paintInfo, int tx, int ty){ if (paintInfo.phase != PaintPhaseForeground) return; RenderObject* child = firstChild(); if (!child) return; // Add in our offsets. tx += x(); ty += y(); int rows = frameSet()->totalRows(); int cols = frameSet()->totalCols(); int borderThickness = frameSet()->border(); int yPos = 0; for (int r = 0; r < rows; r++) { int xPos = 0; for (int c = 0; c < cols; c++) { child->paint(paintInfo, tx, ty); xPos += m_cols.m_sizes[c]; if (borderThickness && m_cols.m_allowBorder[c + 1]) { paintColumnBorder(paintInfo, IntRect(tx + xPos, ty + yPos, borderThickness, height())); xPos += borderThickness; } child = child->nextSibling(); if (!child) return; } yPos += m_rows.m_sizes[r]; if (borderThickness && m_rows.m_allowBorder[r + 1]) { paintRowBorder(paintInfo, IntRect(tx, ty + yPos, width(), borderThickness)); yPos += borderThickness; } }}bool RenderFrameSet::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action){ if (action != HitTestForeground) return false; bool inside = RenderBox::nodeAtPoint(request, result, x, y, tx, ty, action) || m_isResizing; if (inside && frameSet()->noResize() && !request.readOnly() && !result.innerNode()) { result.setInnerNode(node()); result.setInnerNonSharedNode(node()); } return inside || m_isChildResizing;}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 Length* grid, int availableLen){ availableLen = max(availableLen, 0); int* gridLayout = axis.m_sizes.data(); if (!grid) { 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].isFixed()) { gridLayout[i] = max(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].isPercent()) { gridLayout[i] = max(grid[i].calcValue(availableLen), 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(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].isFixed()) { 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].isPercent()) { 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].isPercent()) { 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].isFixed()) { 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -