File indexing completed on 2024-05-12 16:37:13
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2010-2015 C. Boemann <cbo@boemann.dk> 0003 * Copyright (C) 2006,2011 Sebastian Sauer <mail@dipe.org> 0004 * Copyright (C) 2006-2007, 2010 Thomas Zander <zander@kde.org> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KWRootAreaProviderBase.h" 0023 #include "KWPageManager.h" 0024 #include "KWDocument.h" 0025 #include "KWView.h" 0026 #include "frames/KWTextFrameSet.h" 0027 #include "frames/KWCopyShape.h" 0028 0029 #include <KoTextLayoutRootArea.h> 0030 #include <KoShape.h> 0031 #include <KoShapeContainer.h> 0032 #include <KoShapeFactoryBase.h> 0033 #include <KoTextShapeData.h> 0034 #include <KoTextDocumentLayout.h> 0035 #include <KoTextLayoutObstruction.h> 0036 #include <KoShapeAnchor.h> 0037 0038 0039 KWRootAreaProviderBase::KWRootAreaProviderBase(KWTextFrameSet *textFrameSet) 0040 : KoTextLayoutRootAreaProvider() 0041 , m_textFrameSet(textFrameSet) 0042 { 0043 } 0044 0045 void KWRootAreaProviderBase::doPostLayout(KoTextLayoutRootArea *rootArea, bool /*isNewRootArea*/) 0046 { 0047 KoShape *shape = rootArea->associatedShape(); 0048 if (!shape) { 0049 return; 0050 } 0051 0052 KoTextShapeData *data = qobject_cast<KoTextShapeData*>(shape->userData()); 0053 Q_ASSERT(data); 0054 0055 QRectF updateRect = shape->outlineRect(); 0056 0057 QSizeF newSize = shape->size() 0058 - QSizeF(data->leftPadding() + data->rightPadding(), 0059 data->topPadding() + data->bottomPadding()); 0060 0061 KoBorder *border = shape->border(); 0062 0063 if (border) { 0064 newSize -= QSizeF(border->borderWidth(KoBorder::LeftBorder) + border->borderWidth(KoBorder::RightBorder), border->borderWidth(KoBorder::TopBorder) + border->borderWidth(KoBorder::BottomBorder)); 0065 } 0066 0067 if (data->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight 0068 ||data->resizeMethod() == KoTextShapeData::AutoGrowHeight) { 0069 0070 newSize.setHeight(rootArea->bottom() - rootArea->top()); 0071 0072 // adjust size to have at least the defined minimum height 0073 Q_ASSERT(frameSet()->shapeCount() > 0); 0074 KoShape *firstShape = frameSet()->shapes().first(); 0075 if (firstShape->minimumHeight() > newSize.height()) 0076 newSize.setHeight(firstShape->minimumHeight()); 0077 } 0078 if (data->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight 0079 ||data->resizeMethod() == KoTextShapeData::AutoGrowWidth) { 0080 newSize.setWidth(rootArea->right() - rootArea->left()); 0081 } 0082 0083 newSize += QSizeF(data->leftPadding() + data->rightPadding(), 0084 data->topPadding() + data->bottomPadding()); 0085 if (border) { 0086 newSize += QSizeF(border->borderWidth(KoBorder::LeftBorder) + border->borderWidth(KoBorder::RightBorder), border->borderWidth(KoBorder::TopBorder) + border->borderWidth(KoBorder::BottomBorder)); 0087 } 0088 0089 if (newSize != rootArea->associatedShape()->size()) { 0090 rootArea->associatedShape()->setSize(newSize); 0091 0092 // transfer the new size to the copy-shapes 0093 foreach(KWCopyShape *cs, frameSet()->copyShapes()) { 0094 cs->setSize(newSize); 0095 } 0096 } 0097 0098 updateRect |= rootArea->associatedShape()->outlineRect(); 0099 rootArea->associatedShape()->update(updateRect); 0100 } 0101 0102 void KWRootAreaProviderBase::updateAll() 0103 { 0104 foreach (KoShape *shape, frameSet()->shapes()) { 0105 shape->update(); 0106 } 0107 } 0108 0109 QRectF KWRootAreaProviderBase::suggestRect(KoTextLayoutRootArea *rootArea) 0110 { 0111 KoShape *shape = rootArea->associatedShape(); 0112 if (!shape) { // no shape => nothing to draw => no space needed 0113 return QRectF(0., 0., 0.,0.); 0114 } 0115 0116 KoTextShapeData *data = qobject_cast<KoTextShapeData*>(shape->userData()); 0117 Q_ASSERT(data); 0118 0119 QRectF rect(QPointF(), shape->size()); 0120 rect.adjust(data->leftPadding(), data->topPadding(), -data->rightPadding(), - data->bottomPadding()); 0121 0122 KoBorder *border = shape->border(); 0123 if (border) { 0124 rect.adjust(border->borderWidth(KoBorder::LeftBorder), border->borderWidth(KoBorder::TopBorder), 0125 -border->borderWidth(KoBorder::RightBorder), - border->borderWidth(KoBorder::BottomBorder)); 0126 } 0127 0128 rect.setWidth(qMax(rect.width(), qreal(1.0))); 0129 rect.setHeight(qMax(rect.height(), qreal(1.0))); 0130 if (data->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight || data->resizeMethod() == KoTextShapeData::AutoGrowHeight) { 0131 rect.setHeight(1E6); 0132 } 0133 0134 if (data->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight 0135 || data->resizeMethod() == KoTextShapeData::AutoGrowWidth) { 0136 // By setting this we make sure the textlayout librar does 2 internal runs. Once to 0137 // figure out how much width is needed, second to do a normal layout using that calculated width 0138 rootArea->setNoWrap(1E6); 0139 } 0140 0141 return rect; 0142 } 0143 0144 QList<KoTextLayoutObstruction *> KWRootAreaProviderBase::relevantObstructions(KoTextLayoutRootArea *rootArea) 0145 { 0146 QList<KoTextLayoutObstruction*> obstructions; 0147 Q_ASSERT(rootArea); 0148 0149 KoShape *currentShape = rootArea->associatedShape(); 0150 0151 if(!currentShape) { 0152 return obstructions; 0153 } 0154 0155 // let's convert into canvas/KWDocument coords 0156 QRectF rect = currentShape->boundingRect(); 0157 0158 //TODO would probably be faster if we could use the RTree of the shape manager 0159 foreach (KWFrameSet *fs, frameSet()->wordsDocument()->frameSets()) { 0160 if (fs == frameSet()) { 0161 continue; // we don't collide with ourselves 0162 } 0163 0164 if (KWTextFrameSet *tfs = dynamic_cast<KWTextFrameSet*>(fs)) { 0165 if (tfs->textFrameSetType() != Words::OtherTextFrameSet) { 0166 continue; // we don't collide with headers, footers and main-text. 0167 } 0168 } 0169 0170 foreach (KoShape *shape, fs->shapes()) { 0171 if (shape == currentShape) { 0172 continue; 0173 } 0174 if (! shape->isVisible(true)) { 0175 continue; 0176 } 0177 if (shape->anchor() && shape->anchor()->anchorType() != KoShapeAnchor::AnchorPage) { 0178 continue; 0179 } 0180 if (shape->textRunAroundSide() == KoShape::RunThrough) { 0181 continue; 0182 } 0183 if (shape->zIndex() <= currentShape->zIndex()) { 0184 continue; 0185 } 0186 if (! rect.intersects(shape->boundingRect())) { 0187 continue; 0188 } 0189 bool isChild = false; 0190 KoShape *parent = shape->parent(); 0191 while (parent && !isChild) { 0192 if (parent == currentShape) { 0193 isChild = true; 0194 } 0195 parent = parent->parent(); 0196 } 0197 if (isChild) { 0198 continue; 0199 } 0200 QTransform matrix = shape->absoluteTransformation(0); 0201 matrix = matrix * currentShape->absoluteTransformation(0).inverted(); 0202 matrix.translate(0, rootArea->top()); 0203 KoTextLayoutObstruction *obstruction = new KoTextLayoutObstruction(shape, matrix); 0204 obstructions.append(obstruction); 0205 } 0206 } 0207 0208 return obstructions; 0209 }