F:/KPlato/koffice/libs/flake/KoShape.cpp

Aller à la documentation de ce fichier.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2006 Thorsten Zachmann <zachmann@kde.org>
00003    Copyright (C) 2006 Casper Boemann Rasmussen <cbr@boemann.dk>
00004    Copyright (C) 2006 Thomas Zander <zander@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "KoShape.h"
00023 #include "KoShapeContainer.h"
00024 #include "KoSelection.h"
00025 #include "KoPointerEvent.h"
00026 #include "KoInsets.h"
00027 #include "KoShapeBorderModel.h"
00028 #include "KoShapeManager.h"
00029 #include "KoShapeUserData.h"
00030 #include "KoViewConverter.h"
00031 
00032 #include <QPainter>
00033 #include <QtDebug>
00034 #include <QVariant>
00035 #include <QPainterPath>
00036 
00037 KoShape::KoShape()
00038 : m_backgroundBrush(Qt::NoBrush)
00039 , m_border(0)
00040 , m_scaleX( 1 )
00041 , m_scaleY( 1 )
00042 , m_angle( 0 )
00043 , m_shearX( 0 )
00044 , m_shearY( 0 )
00045 , m_size( 50, 50 )
00046 , m_pos( 0, 0 )
00047 , m_zIndex( 0 )
00048 , m_parent( 0 )
00049 , m_visible( true )
00050 , m_locked( false )
00051 , m_keepAspect( false )
00052 , m_selectable( true )
00053 , m_userData(0)
00054 {
00055     recalcMatrix();
00056 }
00057 
00058 KoShape::~KoShape()
00059 {
00060     delete m_userData;
00061 }
00062 
00063 void KoShape::paintDecorations(QPainter &painter, const KoViewConverter &converter, bool selected) {
00064     if ( selected )
00065     {
00066         // draw connectors
00067         QPen pen( Qt::blue );
00068         pen.setWidth( 0 );
00069         painter.setPen( pen );
00070         painter.setBrush( Qt::NoBrush );
00071         for ( int i = 0; i < m_connectors.size(); ++i )
00072         {
00073             QPointF p = converter.documentToView(m_connectors[ i ]);
00074             painter.drawLine( QPointF( p.x() - 2, p.y() + 2 ), QPointF( p.x() + 2, p.y() - 2 ) );
00075             painter.drawLine( QPointF( p.x() + 2, p.y() + 2 ), QPointF( p.x() - 2, p.y() - 2 ) );
00076         }
00077     }
00078 }
00079 
00080 void KoShape::scale( double sx, double sy )
00081 {
00082     if(m_scaleX == sx && m_scaleY == sy)
00083         return;
00084     m_scaleX = sx;
00085     m_scaleY = sy;
00086     recalcMatrix();
00087     shapeChanged(ScaleChanged);
00088 }
00089 
00090 void KoShape::rotate( double angle )
00091 {
00092     if(m_angle == angle)
00093         return;
00094     m_angle = angle;
00095     while(m_angle >= 360) m_angle -= 360;
00096     while(m_angle <= -360) m_angle += 360;
00097     recalcMatrix();
00098     shapeChanged(RotationChanged);
00099 }
00100 
00101 void KoShape::shear( double sx, double sy )
00102 {
00103     if(m_shearX == sx && m_shearY == sy)
00104         return;
00105     m_shearX = sx;
00106     m_shearY = sy;
00107     recalcMatrix();
00108     shapeChanged(ShearChanged);
00109 }
00110 
00111 void KoShape::resize( const QSizeF &newSize )
00112 {
00113     QSizeF s( size() );
00114     if(s == newSize)
00115         return;
00116 
00117     double fx = newSize.width() / s.width();
00118     double fy = newSize.height() / s.height();
00119 
00120     m_size = newSize;
00121 
00122     for ( int i = 0; i < m_connectors.size(); ++i )
00123     {
00124         QPointF &point = m_connectors[i];
00125         point.setX(point.x() * fx);
00126         point.setY(point.y() * fy);
00127     }
00128     recalcMatrix();
00129     shapeChanged(SizeChanged);
00130 }
00131 
00132 void KoShape::setPosition( const QPointF &position )
00133 {
00134     if(m_pos == position)
00135         return;
00136     m_pos = position;
00137     recalcMatrix();
00138     shapeChanged(PositionChanged);
00139 }
00140 
00141 bool KoShape::hitTest( const QPointF &position ) const
00142 {
00143     if(m_parent && m_parent->childClipped(this) && !m_parent->hitTest(position))
00144         return false;
00145 
00146     QPointF point( position * m_invMatrix );
00147     KoInsets insets(0, 0, 0, 0);
00148     if(m_border)
00149         m_border->borderInsets(this, insets);
00150 
00151     QSizeF s( size() );
00152     return point.x() >= -insets.left && point.x() <= s.width() + insets.right &&
00153              point.y() >= -insets.top && point.y() <= s.height() + insets.bottom;
00154 }
00155 
00156 QRectF KoShape::boundingRect() const
00157 {
00158     QRectF bb( QPointF(0, 0), size() );
00159     return m_matrix.mapRect( bb );
00160 }
00161 
00162 void KoShape::recalcMatrix()
00163 {
00164     m_matrix = transformationMatrix(0);
00165     m_invMatrix = m_matrix.inverted();
00166     updateTree();
00167 }
00168 
00169 QMatrix KoShape::transformationMatrix(const KoViewConverter *converter) const {
00170     QMatrix matrix;
00171     QRectF zoomedRect = QRectF(position(), size());
00172     if(converter)
00173         zoomedRect = converter->documentToView(zoomedRect);
00174     matrix.translate( zoomedRect.x(), zoomedRect.y() );
00175 
00176     // apply parents matrix to inherit any transformations done there.
00177     KoShapeContainer *container = m_parent;
00178     KoShape const *child = this;
00179     while(container) {
00180         if(container->childClipped(child))
00181             matrix *= container->transformationMatrix(0);
00182         else {
00183             QPointF containerPos =container->position();
00184             if(converter)
00185                 containerPos = converter->documentToView(containerPos);
00186             matrix.translate(containerPos.x(), containerPos.y());
00187         }
00188         container = dynamic_cast<KoShapeContainer*>(container->parent());
00189         child = child->parent();
00190     }
00191 
00192     if ( m_angle != 0 )
00193     {
00194         matrix.translate( zoomedRect.width() / 2.0 * m_scaleX, zoomedRect.height() / 2.0 * m_scaleY );
00195         matrix.translate( zoomedRect.height() / 2.0 * m_shearX, zoomedRect.width() / 2.0 * m_shearY );
00196         matrix.rotate( m_angle );
00197         matrix.translate( -zoomedRect.width() / 2.0 * m_scaleX, -zoomedRect.height() / 2.0 * m_scaleY );
00198         matrix.translate( -zoomedRect.height() / 2.0 * m_shearX, -zoomedRect.width() / 2.0 * m_shearY );
00199     }
00200     matrix.shear( m_shearX, m_shearY );
00201     matrix.scale( m_scaleX, m_scaleY );
00202     return matrix;
00203 }
00204 
00205 
00206 bool KoShape::compareShapeZIndex(KoShape *g1, KoShape *g2) {
00207     return g1->zIndex() < g2->zIndex();
00208 }
00209 
00210 void KoShape::setParent(KoShapeContainer *parent) {
00211     if(dynamic_cast<KoShape*>(parent) != this)
00212         m_parent = parent;
00213     else
00214         m_parent = 0;
00215     recalcMatrix();
00216     shapeChanged(ParentChanged);
00217 }
00218 
00219 int KoShape::zIndex() const {
00220     if(parent()) // we can't be under our parent...
00221         return qMax(m_zIndex, parent()->zIndex());
00222     return m_zIndex;
00223 }
00224 
00225 void KoShape::repaint() const {
00226     if ( !m_shapeManagers.empty() )
00227     {
00228         foreach( KoShapeManager * manager, m_shapeManagers )
00229         {
00230             QRectF rect(QPointF(0, 0), size() );
00231             if(m_border) {
00232                 KoInsets insets(0, 0, 0, 0);
00233                 m_border->borderInsets(this, insets);
00234                 rect.adjust(-insets.left, -insets.top, insets.right, insets.bottom);
00235             }
00236             rect = m_matrix.mapRect(rect);
00237             manager->repaint( rect, this, true );
00238         }
00239     }
00240 }
00241 
00242 void KoShape::repaint(const QRectF &shape) const {
00243     if ( !m_shapeManagers.empty() && isVisible() )
00244     {
00245         foreach( KoShapeManager * manager, m_shapeManagers )
00246         {
00247             QRectF rect(m_matrix.mapRect(shape));
00248             manager->repaint(rect);
00249         }
00250     }
00251 }
00252 
00253 void KoShape::repaint(double x, double y, double width, double height) const {
00254     QRectF rect(x, y, width, height);
00255     repaint(rect);
00256 }
00257 
00258 const QPainterPath KoShape::outline() const {
00259     QPainterPath path;
00260     path.addRect(QRectF( QPointF(0, 0), size() ));
00261     return path;
00262 }
00263 
00264 QPointF KoShape::absolutePosition() const {
00265     return m_matrix.map(QPointF(size().width() / 2.0 , size().height() / 2.0));
00266 }
00267 
00268 void KoShape::setAbsolutePosition(QPointF newPosition) {
00269     QPointF zero(0, 0);
00270     QMatrix matrix;
00271     // apply parents matrix to inherit any transformations done there.
00272     KoShapeContainer *container = m_parent;
00273     KoShape const *child = this;
00274     while(container) {
00275         if(container->childClipped(child)) {
00276             matrix *= container->transformationMatrix(0);
00277             break;
00278         }
00279         else {
00280             QPointF containerPos =container->position();
00281             matrix.translate(containerPos.x(), containerPos.y());
00282         }
00283         container = dynamic_cast<KoShapeContainer*>(container->parent());
00284         child = child->parent();
00285     }
00286     QPointF vector1 = matrix.inverted().map(zero);
00287 
00288     matrix = QMatrix();
00289     if ( m_angle != 0 )
00290     {
00291         matrix.translate( size().width() / 2.0 * m_scaleX, size().height() / 2.0 * m_scaleY );
00292         matrix.translate( size().height() / 2.0 * m_shearX, size().width() / 2.0 * m_shearY );
00293         matrix.rotate( m_angle );
00294         matrix.translate( -size().width() / 2.0 * m_scaleX, -size().height() / 2.0 * m_scaleY );
00295         matrix.translate( -size().height() / 2.0 * m_shearX, -size().width() / 2.0 * m_shearY );
00296     }
00297     matrix.shear( m_shearX, m_shearY );
00298     matrix.scale( m_scaleX, m_scaleY );
00299 
00300     QPointF vector2 = matrix.map( QPointF(size().width() / 2.0, size().height() / 2.0) );
00301     //kDebug() << "vector1: " << vector1 << ", vector2: " << vector2 << endl;
00302 
00303     setPosition(newPosition + vector1 - vector2);
00304 }
00305 
00306 void KoShape::copySettings(const KoShape *shape) {
00307     m_pos = shape->position();
00308     m_scaleX = shape->scaleX();
00309     m_scaleY = shape->scaleY();
00310     m_angle = shape->rotation();
00311     m_shearX = shape->shearX();
00312     m_shearY = shape->shearY();
00313     m_size = shape->size();
00314     m_connectors.clear();
00315     foreach(QPointF point, shape->connectors())
00316         addConnectionPoint(point);
00317     m_zIndex = shape->zIndex();
00318     m_visible = shape->isVisible();
00319     m_locked = shape->isLocked();
00320     m_keepAspect = shape->keepAspectRatio();
00321 }
00322 
00323 void KoShape::moveBy(double distanceX, double distanceY) {
00324     QPointF p = absolutePosition();
00325     setAbsolutePosition(QPointF(p.x() + distanceX, p.y() + distanceY));
00326 }
00327 
00328 void KoShape::updateTree()
00329 {
00330     foreach( KoShapeManager * manager, m_shapeManagers )
00331     {
00332         manager->updateTree( this );
00333     }
00334 }
00335 
00336 void KoShape::setUserData(KoShapeUserData *userData) {
00337     if(m_userData)
00338         delete m_userData;
00339     m_userData = userData;
00340 }
00341 
00342 KoShapeUserData *KoShape::userData() const {
00343     return m_userData;
00344 }
00345 
00346 bool KoShape::hasTransparency() {
00347     if(m_backgroundBrush.style() == Qt::NoBrush)
00348         return true;
00349     return !m_backgroundBrush.isOpaque();
00350 }
00351 
00352 // static
00353 void KoShape::applyConversion(QPainter &painter, const KoViewConverter &converter) {
00354     double zoomX, zoomY;
00355     converter.zoom(&zoomX, &zoomY);
00356     painter.scale(zoomX, zoomY);
00357 }
00358 

Généré le Wed Nov 22 23:40:59 2006 pour KPlato par  doxygen 1.5.1-p1