📄 render_frames.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) * (C) 2003 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. * *///#define DEBUG_LAYOUT#include "rendering/render_frames.h"#include "rendering/render_canvas.h"#include "html/html_baseimpl.h"#include "html/html_objectimpl.h"#include "html/htmltokenizer.h"#include "misc/htmlattrs.h"#include "xml/dom2_eventsimpl.h"#include "xml/dom_docimpl.h"#include "misc/htmltags.h"#include "khtmlview.h"#include "khtml_part.h"#include <kapplication.h>#include <kmessagebox.h>#include <kmimetype.h>#include <klocale.h>#include <kdebug.h>#include <qtimer.h>#include <qpainter.h>#include <qcursor.h>#include <assert.h>using namespace khtml;using namespace DOM;RenderFrameSet::RenderFrameSet( HTMLFrameSetElementImpl *frameSet) : RenderBox(frameSet){ // init RenderObject attributes setInline(false); for (int k = 0; k < 2; ++k) { m_gridLen[k] = -1; m_gridDelta[k] = 0; m_gridLayout[k] = 0; } m_resizing = m_clientresizing= false; m_cursor = Qt::ArrowCursor; m_hSplit = -1; m_vSplit = -1; m_hSplitVar = 0; m_vSplitVar = 0;}RenderFrameSet::~RenderFrameSet(){ for (int k = 0; k < 2; ++k) { delete [] m_gridLayout[k]; delete [] m_gridDelta[k]; } delete [] m_hSplitVar; delete [] m_vSplitVar;}bool RenderFrameSet::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inBox){ RenderBox::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox); bool inside = m_resizing || canResize(_x, _y); if ( inside && element() && !element()->noResize() && !info.readonly()) { info.setInnerNode(element()); info.setInnerNonSharedNode(element()); } return inside || m_clientresizing;}void RenderFrameSet::layout( ){ KHTMLAssert( needsLayout() ); KHTMLAssert( minMaxKnown() ); if ( !parent()->isFrameSet() ) { KHTMLView* view = canvas()->view(); m_width = view ? view->visibleWidth() : 0; m_height = view ? view->visibleHeight() : 0; }#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << renderName() << "(FrameSet)::layout( ) width=" << width() << ", height=" << height() << endl;#endif int remainingLen[2]; remainingLen[1] = m_width - (element()->totalCols()-1)*element()->border(); if(remainingLen[1]<0) remainingLen[1]=0; remainingLen[0] = m_height - (element()->totalRows()-1)*element()->border(); if(remainingLen[0]<0) remainingLen[0]=0; int availableLen[2]; availableLen[0] = remainingLen[0]; availableLen[1] = remainingLen[1]; if (m_gridLen[0] != element()->totalRows() || m_gridLen[1] != element()->totalCols()) { // number of rows or cols changed // need to zero out the deltas m_gridLen[0] = element()->totalRows(); m_gridLen[1] = element()->totalCols(); for (int k = 0; k < 2; ++k) { delete [] m_gridDelta[k]; m_gridDelta[k] = new int[m_gridLen[k]]; delete [] m_gridLayout[k]; m_gridLayout[k] = new int[m_gridLen[k]]; for (int i = 0; i < m_gridLen[k]; ++i) m_gridDelta[k][i] = 0; } } for (int k = 0; k < 2; ++k) { int totalRelative = 0; int totalFixed = 0; int totalPercent = 0; int countRelative = 0; int countPercent = 0; int gridLen = m_gridLen[k]; int* gridDelta = m_gridDelta[k]; khtml::Length* grid = k ? element()->m_cols : element()->m_rows; int* gridLayout = m_gridLayout[k]; if (grid) { // first distribute the available width for fixed rows, then handle the // percentage ones and distribute remaining over relative for(int i = 0; i< gridLen; ++i) if (grid[i].isFixed()) { gridLayout[i] = kMin(grid[i].value() > 0 ? grid[i].value() : 0, remainingLen[k]); remainingLen[k] -= gridLayout[i]; totalFixed += gridLayout[i]; } else if(grid[i].isRelative()) { totalRelative += grid[i].value() > 1 ? grid[i].value() : 1; countRelative++; } for(int i = 0; i < gridLen; i++) if(grid[i].isPercent()) { gridLayout[i] = kMin(kMax(grid[i].width(availableLen[k]), 0), remainingLen[k]); remainingLen[k] -= gridLayout[i]; totalPercent += grid[i].value(); countPercent++; } assert(remainingLen[k] >= 0); if (countRelative) { int remaining = remainingLen[k]; for (int i = 0; i < gridLen; ++i) if (grid[i].isRelative()) { gridLayout[i] = ((grid[i].value() > 1 ? grid[i].value() : 1) * remaining) / totalRelative; remainingLen[k] -= gridLayout[i]; } } // distribute the rest if (remainingLen[k]) { LengthType distributeType = countPercent ? Percent : Fixed; int total = countPercent ? totalPercent : totalFixed; if (!total) total = 1; for (int i = 0; i < gridLen; ++i) if (grid[i].type() == distributeType) { int toAdd = (remainingLen[k] * grid[i].value()) / total; gridLayout[i] += toAdd; } } // now we have the final layout, distribute the delta over it bool worked = true; for (int i = 0; i < gridLen; ++i) { if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0) worked = false; gridLayout[i] += gridDelta[i]; } // now the delta's broke something, undo it and reset deltas if (!worked) for (int i = 0; i < gridLen; ++i) { gridLayout[i] -= gridDelta[i]; gridDelta[i] = 0; } } else gridLayout[0] = remainingLen[k]; } positionFrames(); RenderObject *child = firstChild(); if ( !child ) return; if(!m_hSplitVar && !m_vSplitVar) {#ifdef DEBUG_LAYOUT kdDebug( 6031 ) << "calculationg fixed Splitters" << endl;#endif if(!m_vSplitVar && element()->totalCols() > 1) { m_vSplitVar = new bool[element()->totalCols()]; for(int i = 0; i < element()->totalCols(); i++) m_vSplitVar[i] = true; } if(!m_hSplitVar && element()->totalRows() > 1) { m_hSplitVar = new bool[element()->totalRows()]; for(int i = 0; i < element()->totalRows(); i++) m_hSplitVar[i] = true; } for(int r = 0; r < element()->totalRows(); r++) { for(int c = 0; c < element()->totalCols(); c++) { bool fixed = false; if ( child->isFrameSet() ) fixed = static_cast<RenderFrameSet *>(child)->element()->noResize(); else fixed = static_cast<RenderFrame *>(child)->element()->noResize(); if(fixed) {#ifdef DEBUG_LAYOUT kdDebug( 6031 ) << "found fixed cell " << r << "/" << c << "!" << endl;#endif if( element()->totalCols() > 1) { if(c>0) m_vSplitVar[c-1] = false; m_vSplitVar[c] = false; } if( element()->totalRows() > 1) { if(r>0) m_hSplitVar[r-1] = false; m_hSplitVar[r] = false; } child = child->nextSibling(); if(!child) goto end2; }#ifdef DEBUG_LAYOUT else kdDebug( 6031 ) << "not fixed: " << r << "/" << c << "!" << endl;#endif } } } RenderContainer::layout(); end2: setNeedsLayout(false);}void RenderFrameSet::positionFrames(){ int r; int c; RenderObject *child = firstChild(); if ( !child ) return; // NodeImpl *child = _first; // if(!child) return; int yPos = 0; for(r = 0; r < element()->totalRows(); r++) { int xPos = 0; for(c = 0; c < element()->totalCols(); c++) { child->setPos( xPos, yPos );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -