File indexing completed on 2024-05-12 16:34:58

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2011 C. Boemann <cbo@boemann.dk>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Library General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2 of the License, or (at your option) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Library General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Library General Public License
0015  * along with this library; see the file COPYING.LIB.  If not, write to
0016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018  */
0019 
0020 #include "SimpleRootAreaProvider.h"
0021 
0022 #include "TextShape.h"
0023 
0024 #include <KoBorder.h>
0025 #include <KoTextLayoutRootArea.h>
0026 #include <KoTextLayoutObstruction.h>
0027 #include <KoInsets.h>
0028 
0029 SimpleRootAreaProvider::SimpleRootAreaProvider(KoTextShapeData *data, TextShape *textshape)
0030     : m_textShape(textshape)
0031     , m_area(0)
0032     , m_textShapeData(data)
0033     , m_fixAutogrow(false)
0034 
0035 {
0036 }
0037 
0038 KoTextLayoutRootArea *SimpleRootAreaProvider::provide(KoTextDocumentLayout *documentLayout, const RootAreaConstraint &, int requestedPosition, bool *isNewRootArea)
0039 {
0040     if(m_area == 0) {
0041         *isNewRootArea = true;
0042         m_area = new KoTextLayoutRootArea(documentLayout);
0043         m_area->setAssociatedShape(m_textShape);
0044         m_textShapeData->setRootArea(m_area);
0045 
0046         return m_area;
0047     }
0048     if (requestedPosition == 0) {
0049         *isNewRootArea = false;
0050         return m_area;
0051     }
0052     return 0;
0053 }
0054 
0055 void SimpleRootAreaProvider::releaseAllAfter(KoTextLayoutRootArea *afterThis)
0056 {
0057     Q_UNUSED(afterThis);
0058 }
0059 
0060 void SimpleRootAreaProvider::doPostLayout(KoTextLayoutRootArea *rootArea, bool isNewRootArea)
0061 {
0062     Q_UNUSED(isNewRootArea);
0063 
0064     m_textShape->update(m_textShape->outlineRect());
0065 
0066     QSizeF newSize = m_textShape->size()
0067                     - QSizeF(m_textShapeData->leftPadding() + m_textShapeData->rightPadding(),
0068                              m_textShapeData->topPadding() + m_textShapeData->bottomPadding());
0069 
0070     KoBorder *border = m_textShape->border();
0071     if (border) {
0072         newSize -= QSizeF(border->borderWidth(KoBorder::LeftBorder) + border->borderWidth(KoBorder::RightBorder), border->borderWidth(KoBorder::TopBorder) + border->borderWidth(KoBorder::BottomBorder));
0073     } else {
0074         KoInsets inset = m_textShape->strokeInsets();
0075         newSize -= QSizeF((inset.right+inset.left), (inset.bottom+inset.top));
0076     }
0077 
0078 
0079     if (m_textShapeData->verticalAlignment() & Qt::AlignBottom) {
0080     }
0081     if (m_textShapeData->verticalAlignment() & Qt::AlignVCenter) {
0082     }
0083 
0084     if (m_textShapeData->resizeMethod() == KoTextShapeData::AutoResize) {
0085         newSize = QSizeF(rootArea->right() - rootArea->left(), rootArea->bottom() - rootArea->top());
0086         // HACK: The size we get from the shape will cut descents,
0087         // so we add some reasonable (approximate) value that works ok in normal cases
0088         QSizeF s(0.0, 0.0);
0089         int lines = m_textShapeData->document()->lineCount();
0090         if (lines > 0) {
0091             s.setHeight(newSize.height() / lines * 0.2);
0092         }
0093         newSize += s;
0094     } else {
0095         if (m_textShapeData->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight
0096             ||m_textShapeData->resizeMethod() == KoTextShapeData::AutoGrowHeight) {
0097             qreal height = rootArea->bottom() - rootArea->top();
0098             if (height > newSize.height()) {
0099                 newSize.setHeight(height);
0100             }
0101             if (m_textShape->shapeId() == "AnnotationTextShapeID") {
0102                 if (height < newSize.height()) {
0103                     newSize.setHeight(rootArea->bottom() - rootArea->top());
0104                 }
0105             }
0106         }
0107         if (m_textShapeData->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight
0108             ||m_textShapeData->resizeMethod() == KoTextShapeData::AutoGrowWidth) {
0109             qreal width = rootArea->right() - rootArea->left();
0110             if (width > newSize.width()) {
0111                 newSize.setWidth(rootArea->right() - rootArea->left());
0112             }
0113         }
0114     }
0115 
0116     qreal newBottom = rootArea->top() + newSize.height();
0117     KoFlake::Position sizeAnchor= KoFlake::TopLeftCorner;
0118 
0119     if (m_textShapeData->verticalAlignment() & Qt::AlignBottom) {
0120         if (true /*FIXME test no page based shapes interfering*/) {
0121             rootArea->setVerticalAlignOffset(newBottom - rootArea->bottom());
0122             sizeAnchor= KoFlake::BottomLeftCorner;
0123         }
0124     }
0125     if (m_textShapeData->verticalAlignment() & Qt::AlignVCenter) {
0126         if (true /*FIXME test no page based shapes interfering*/) {
0127             rootArea->setVerticalAlignOffset((newBottom - rootArea->bottom()) / 2);
0128             sizeAnchor = KoFlake::CenteredPosition;
0129         }
0130     }
0131     newSize += QSizeF(m_textShapeData->leftPadding() + m_textShapeData->rightPadding(),
0132                       m_textShapeData->topPadding() + m_textShapeData->bottomPadding());
0133     if (border) {
0134         newSize += QSizeF(border->borderWidth(KoBorder::LeftBorder) + border->borderWidth(KoBorder::RightBorder), border->borderWidth(KoBorder::TopBorder) + border->borderWidth(KoBorder::BottomBorder));
0135     } else {
0136         KoInsets inset = m_textShape->strokeInsets();
0137         newSize += QSizeF((inset.right+inset.left), (inset.bottom+inset.top));
0138     }
0139 
0140     if (newSize != m_textShape->size()) {
0141         // OO grows to both sides so when to small the initial layouting needs
0142         // to keep that into account.
0143         if (m_fixAutogrow) {
0144             m_fixAutogrow = false;
0145             QSizeF tmpSize = m_textShape->size();
0146             tmpSize.setWidth(newSize.width());
0147             QPointF centerpos = rootArea->associatedShape()->absolutePosition(KoFlake::CenteredPosition);
0148             m_textShape->setSize(tmpSize);
0149             m_textShape->setAbsolutePosition(centerpos, KoFlake::CenteredPosition);
0150             centerpos = rootArea->associatedShape()->absolutePosition(sizeAnchor);
0151             m_textShape->setSize(newSize);
0152             m_textShape->setAbsolutePosition(centerpos, sizeAnchor);
0153         }
0154         m_textShape->setSize(newSize);
0155     }
0156 
0157     m_textShape->update(m_textShape->outlineRect());
0158 }
0159 
0160 void SimpleRootAreaProvider::updateAll()
0161 {
0162     if (m_area && m_area->associatedShape()) {
0163         m_area->associatedShape()->update();
0164     }
0165 }
0166 
0167 QRectF SimpleRootAreaProvider::suggestRect(KoTextLayoutRootArea *rootArea)
0168 {
0169     //Come up with a rect, but actually we don't need the height, as we set it to infinite below
0170     // Still better keep it for completeness sake
0171     QRectF rect(QPointF(), m_textShape->size());
0172     rect.adjust(m_textShapeData->leftPadding(), m_textShapeData->topPadding(), -m_textShapeData->rightPadding(), - m_textShapeData->bottomPadding());
0173 
0174     KoBorder *border = m_textShape->border();
0175     if (border) {
0176         rect.adjust(border->borderWidth(KoBorder::LeftBorder),  border->borderWidth(KoBorder::TopBorder),
0177               -border->borderWidth(KoBorder::RightBorder), - border->borderWidth(KoBorder::BottomBorder));
0178     } else {
0179         KoInsets inset = m_textShape->strokeInsets();
0180         rect.adjust(inset.left, inset.top, -inset.right, -inset.bottom);
0181     }
0182 
0183     // In simple cases we always set height way too high so that we have no breaking
0184     // If the shape grows afterwards or not is handled in doPostLayout()
0185     rect.setHeight(1E6);
0186 
0187     if (m_textShapeData->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight
0188         ||m_textShapeData->resizeMethod() == KoTextShapeData::AutoGrowWidth
0189         ||m_textShapeData->resizeMethod() == KoTextShapeData::AutoResize) {
0190         rootArea->setNoWrap(1E6);
0191     }
0192 
0193     // Make sure the size is not negative due to padding and border width
0194     // This can happen on vertical lines containing text on shape.
0195     if (rect.width() < 0) {
0196         rect.setWidth(0);
0197     }
0198     return rect;
0199 }
0200 
0201 QList<KoTextLayoutObstruction *> SimpleRootAreaProvider::relevantObstructions(KoTextLayoutRootArea *rootArea)
0202 {
0203     Q_UNUSED(rootArea);
0204 
0205     QList<KoTextLayoutObstruction*> obstructions;
0206 /*
0207     m_textShape->boundingRect();
0208     QList<KoShape *> shapes;
0209     shapes = manager->shapesAt(canvasRect):
0210 */
0211     return obstructions;
0212 }