File indexing completed on 2024-05-12 16:34:58
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2010 Thomas Zander <zander@kde.org> 0003 * Copyright (C) 2010 Sebastian Sauer <sebsauer@kdab.com> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "ShrinkToFitShapeContainer.h" 0022 0023 #include <KoShapeSavingContext.h> 0024 #include <KoTextLayoutRootArea.h> 0025 0026 ShrinkToFitShapeContainer::ShrinkToFitShapeContainer(KoShape *childShape, KoDocumentResourceManager *documentResources) 0027 : KoShapeContainer(*(new ShrinkToFitShapeContainerPrivate(this, childShape))) 0028 { 0029 Q_UNUSED(documentResources); 0030 Q_D(ShrinkToFitShapeContainer); 0031 0032 setPosition(childShape->position()); 0033 setSize(childShape->size()); 0034 setZIndex(childShape->zIndex()); 0035 setRunThrough(childShape->runThrough()); 0036 rotate(childShape->rotation()); 0037 //setTransformation(childShape->transformation()); 0038 0039 if (childShape->parent()) { 0040 childShape->parent()->addShape(this); 0041 childShape->setParent(0); 0042 } 0043 0044 childShape->setPosition(QPointF(0.0,0.0)); // since its relative to my position, this won't move it 0045 childShape->setSelectable(false); // our ShrinkToFitShapeContainer will handle that from now on 0046 0047 d->model = new ShrinkToFitShapeContainerModel(this, d); 0048 addShape(childShape); 0049 0050 QSet<KoShape*> delegates; 0051 delegates << childShape; 0052 setToolDelegates(delegates); 0053 0054 KoTextShapeData* data = dynamic_cast<KoTextShapeData*>(childShape->userData()); 0055 Q_ASSERT(data); 0056 KoTextDocumentLayout *lay = qobject_cast<KoTextDocumentLayout*>(data->document()->documentLayout()); 0057 Q_ASSERT(lay); 0058 QObject::connect(lay, SIGNAL(finishedLayout()), static_cast<ShrinkToFitShapeContainerModel*>(d->model), SLOT(finishedLayout())); 0059 } 0060 0061 ShrinkToFitShapeContainer::~ShrinkToFitShapeContainer() 0062 { 0063 } 0064 0065 void ShrinkToFitShapeContainer::paintComponent(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &) 0066 { 0067 Q_UNUSED(painter); 0068 Q_UNUSED(converter); 0069 //painter.fillRect(converter.documentToView(QRectF(QPointF(0,0),size())), QBrush(QColor("#ffcccc"))); // for testing 0070 } 0071 0072 bool ShrinkToFitShapeContainer::loadOdf(const KoXmlElement &element, KoShapeLoadingContext &context) 0073 { 0074 Q_UNUSED(element); 0075 Q_UNUSED(context); 0076 return true; 0077 } 0078 0079 void ShrinkToFitShapeContainer::saveOdf(KoShapeSavingContext &context) const 0080 { 0081 Q_D(const ShrinkToFitShapeContainer); 0082 d->childShape->saveOdf(context); 0083 } 0084 0085 ShrinkToFitShapeContainer* ShrinkToFitShapeContainer::wrapShape(KoShape *shape, KoDocumentResourceManager *documentResourceManager) 0086 { 0087 Q_ASSERT(dynamic_cast<KoTextShapeData*>(shape->userData())); 0088 Q_ASSERT(qobject_cast<KoTextDocumentLayout*>(dynamic_cast<KoTextShapeData*>(shape->userData())->document()->documentLayout())); 0089 0090 return new ShrinkToFitShapeContainer(shape, documentResourceManager); 0091 } 0092 0093 void ShrinkToFitShapeContainer::tryWrapShape(KoShape *shape, const KoXmlElement &element, KoShapeLoadingContext &context) 0094 { 0095 KoTextShapeData* data = dynamic_cast<KoTextShapeData*>(shape->userData()); 0096 if (!data || data->resizeMethod() != KoTextShapeData::ShrinkToFitResize) 0097 return; 0098 0099 KoShapeContainer *oldParent = shape->parent(); 0100 ShrinkToFitShapeContainer *tos = wrapShape(shape, context.documentResourceManager()); 0101 if (!tos->loadOdf(element, context)) { 0102 shape->setParent(oldParent); 0103 delete tos; 0104 } 0105 } 0106 0107 void ShrinkToFitShapeContainer::unwrapShape(KoShape *shape) 0108 { 0109 Q_ASSERT(shape->parent() == this); 0110 0111 removeShape(shape); 0112 shape->setParent(parent()); 0113 0114 QSet<KoShape*> delegates = toolDelegates(); 0115 delegates.remove(shape); 0116 setToolDelegates(delegates); 0117 0118 shape->setPosition(position()); 0119 shape->setSize(size()); 0120 shape->rotate(rotation()); 0121 shape->setSelectable(true); 0122 } 0123 0124 ShrinkToFitShapeContainerModel::ShrinkToFitShapeContainerModel(ShrinkToFitShapeContainer *q, ShrinkToFitShapeContainerPrivate *d) 0125 : q(q) 0126 , d(d) 0127 , m_scale(1.0) 0128 , m_dirty(10) 0129 , m_maybeUpdate(false) 0130 { 0131 } 0132 0133 void ShrinkToFitShapeContainerModel::finishedLayout() 0134 { 0135 m_maybeUpdate = true; 0136 containerChanged(q, KoShape::SizeChanged); 0137 m_maybeUpdate = false; 0138 } 0139 0140 void ShrinkToFitShapeContainerModel::containerChanged(KoShapeContainer *container, KoShape::ChangeType type) 0141 { 0142 Q_ASSERT(container == q); Q_UNUSED(container); 0143 if (type == KoShape::SizeChanged) { 0144 KoTextShapeData* data = dynamic_cast<KoTextShapeData*>(d->childShape->userData()); 0145 Q_ASSERT(data); 0146 KoTextLayoutRootArea *rootArea = data->rootArea(); 0147 Q_ASSERT(rootArea); 0148 0149 QSizeF shapeSize = q->size(); 0150 QSizeF documentSize = rootArea->boundingRect().size(); 0151 if (m_maybeUpdate &&shapeSize == m_shapeSize && documentSize == m_documentSize) { 0152 m_dirty = 0; 0153 return; // nothing to update 0154 } 0155 0156 m_shapeSize = shapeSize; 0157 m_documentSize = documentSize; 0158 0159 if ( documentSize.width() > 0.0 && documentSize.height() > 0.0 ) { 0160 if (m_dirty || !m_maybeUpdate) { 0161 qreal scaleX = qMin<qreal>(1.0, shapeSize.width() / documentSize.width()); 0162 qreal scaleY = qMin<qreal>(1.0, shapeSize.height() / documentSize.height()); 0163 m_scale = (scaleX+scaleY)/2.0 * 0.95; 0164 if (m_maybeUpdate && m_dirty) 0165 --m_dirty; 0166 } 0167 } else { 0168 m_scale = 1.0; 0169 m_dirty = 1; 0170 } 0171 0172 QSizeF newSize(shapeSize.width() / m_scale, shapeSize.height() / m_scale); 0173 d->childShape->setSize(newSize); 0174 0175 QTransform m; 0176 m.scale(m_scale, m_scale); 0177 d->childShape->setTransformation(m); 0178 } 0179 } 0180 0181 bool ShrinkToFitShapeContainerModel::inheritsTransform(const KoShape *child) const 0182 { 0183 Q_ASSERT(child == d->childShape); Q_UNUSED(child); 0184 return true; 0185 } 0186 0187 bool ShrinkToFitShapeContainerModel::isChildLocked(const KoShape *child) const 0188 { 0189 Q_ASSERT(child == d->childShape); Q_UNUSED(child); 0190 return true; 0191 } 0192 0193 bool ShrinkToFitShapeContainerModel::isClipped(const KoShape *child) const 0194 { 0195 Q_ASSERT(child == d->childShape); Q_UNUSED(child); 0196 return false; 0197 }