karbon

vcanvas.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001, 2002, 2003 The Karbon Developers
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include <qcursor.h>
00021 #include <qpainter.h>
00022 #include <qpixmap.h>
00023 
00024 #include "karbon_view.h"
00025 #include "karbon_part.h"
00026 #include "karbon_drag.h"
00027 #include "vcanvas.h"
00028 #include "vdocument.h"
00029 #include "vpainter.h"
00030 #include "vqpainter.h"
00031 #include "vpainterfactory.h"
00032 #include "vselection.h"
00033 #include "vtoolcontroller.h"
00034 #include "vtool.h"
00035 
00036 #include <kdebug.h>
00037 #include <klocale.h>
00038 #include <kcolordrag.h>
00039 
00040 int
00041 VCanvas::pageOffsetX() const
00042 {
00043     double zoomedWidth = m_part->document().width() * m_view->zoom();
00044     if( contentsWidth() < visibleWidth() )
00045         return int( 0.5 * ( visibleWidth() - zoomedWidth ) );
00046     else
00047         return int( 0.5 * ( contentsWidth() - zoomedWidth ) );
00048 }
00049 
00050 int
00051 VCanvas::pageOffsetY() const
00052 {
00053     double zoomedHeight = m_part->document().height() * m_view->zoom();
00054     if( contentsHeight() < visibleHeight() )
00055         return int( 0.5 * ( visibleHeight() - zoomedHeight ) );
00056     else
00057         return int( 0.5 * ( contentsHeight() - zoomedHeight ) );
00058 }
00059 
00060 KoPoint VCanvas::snapToGrid( const KoPoint &point )
00061 {
00062     if( !m_part->document().grid().isSnap )
00063         return point;
00064 
00065     KoPoint p = point;
00066 
00067     KoSize dist = m_part->document().grid().snap;
00068     KoSize dxy = m_part->document().grid().freq;
00069 
00070     int dx = qRound( p.x() / dxy.width() );
00071     int dy = qRound( p.y() / dxy.height() );
00072 
00073     float distx = QMIN( QABS( p.x() - dxy.width() * dx ), QABS( p.x() - dxy.width() * ( dx + 1 ) ) );
00074     float disty = QMIN( QABS( p.y() - dxy.height() * dy ), QABS( p.y() - dxy.height() * ( dy + 1 ) ) );
00075 
00076     if( distx < dist.width() )
00077     {
00078         if( QABS(p.x() - dxy.width() * dx ) < QABS( p.x() - dxy.width() * ( dx + 1 ) ) )
00079             p.rx() = dxy.width() * dx;
00080         else
00081             p.rx() = dxy.width() * ( dx + 1 );
00082     }
00083 
00084     if( disty < dist.height() )
00085     {
00086         if( QABS( p.y() - dxy.height() * dy ) < QABS( p.y() - dxy.height() * ( dy + 1 ) ) )
00087             p.ry() = dxy.height() * dy;
00088         else
00089             p.ry() = dxy.height() * ( dy + 1 );
00090     }
00091 
00092     return p;
00093 }
00094 
00095 
00096 VCanvas::VCanvas( QWidget *parent, KarbonView* view, KarbonPart* part )
00097     : QScrollView( parent, "canvas", WStaticContents/*WNorthWestGravity*/ | WResizeNoErase  |
00098       WRepaintNoErase ), m_part( part ), m_view( view )
00099 {
00100     connect(this, SIGNAL( contentsMoving( int, int ) ), this, SLOT( slotContentsMoving( int, int ) ) );
00101     viewport()->setFocusPolicy( QWidget::StrongFocus );
00102 
00103     viewport()->setMouseTracking( true );
00104     setMouseTracking( true );
00105 
00106     viewport()->setBackgroundColor( Qt::white );
00107     viewport()->setBackgroundMode( QWidget::NoBackground );
00108     viewport()->installEventFilter( this );
00109 
00110     resizeContents( 800, 600 );
00111     m_pixmap = new QPixmap( 800, 600 );
00112 
00113     setFocus();
00114 
00115     setAcceptDrops( true );
00116 }
00117 
00118 VCanvas::~VCanvas()
00119 {
00120     delete m_pixmap;
00121     m_view = 0L;
00122     m_part = 0L;
00123 }
00124 
00125 void
00126 VCanvas::setPos( const KoPoint& p )
00127 {
00128     KoPoint p2 = toViewport( p );
00129     QCursor::setPos( mapToGlobal( QPoint( int(p2.x()), int(p2.y()) ) ) );
00130 }
00131 
00132 bool
00133 VCanvas::eventFilter( QObject* object, QEvent* event )
00134 {
00135     QScrollView::eventFilter( object, event );
00136 
00137     if( event->type() == QEvent::AccelOverride || event->type() == QEvent::Accel )
00138         return QScrollView::eventFilter( object, event );
00139 
00140     if( event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease )
00141         return m_view->keyEvent( event );
00142 
00143     QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>( event );
00144 
00145     if( mouseEvent && m_view )
00146     {
00147         KoPoint canvasCoordinate = toContents( KoPoint( mouseEvent->pos() ) );
00148         return m_view->mouseEvent( mouseEvent, canvasCoordinate );
00149     }
00150 
00151     return false;
00152 }
00153 
00154 
00155 // This causes a repaint normally, so just overwriting it omits the repainting
00156 void
00157 VCanvas::focusInEvent( QFocusEvent * )
00158 {
00159 }
00160 
00161 KoPoint
00162 VCanvas::toViewport( const KoPoint &p ) const
00163 {
00164     KoPoint p2 = p;
00165     p2.setX( ( p.x() * m_view->zoom() ) - contentsX() + pageOffsetX() );
00166     if( contentsHeight() > height() )
00167         p2.setY( ( contentsHeight() - ( p.y() * m_view->zoom() + contentsY() + pageOffsetY() ) ) );
00168     else
00169         p2.setY( ( height() - p.y() * m_view->zoom() + pageOffsetY() ) );
00170     return p2;
00171 }
00172 
00173 KoPoint
00174 VCanvas::toContents( const KoPoint &p ) const
00175 {
00176     KoPoint p2 = p;
00177     p2.setX( ( p.x() + contentsX() - pageOffsetX() ) / m_view->zoom() );
00178     if( contentsHeight() > height() )
00179         p2.setY( ( contentsHeight() - ( p.y() + contentsY() + pageOffsetY()) ) / m_view->zoom() );
00180     else
00181         p2.setY( ( height() - p.y() - pageOffsetY() ) / m_view->zoom() );
00182     return p2;
00183 }
00184 
00185 KoRect
00186 VCanvas::boundingBox() const
00187 {
00188     KoPoint p1( 0, 0 );
00189     KoPoint p2( width(), height() );
00190     if( !m_view->documentDeleted() )
00191     {
00192         p1 = toContents( p1 );
00193         p2 = toContents( p2 );
00194     }
00195     return KoRect( p1, p2 ).normalize();
00196 }
00197 
00198 void
00199 VCanvas::setYMirroring( VPainter *p )
00200 {
00201     QWMatrix mat;
00202 
00203     mat.scale( 1, -1 );
00204     mat.translate( pageOffsetX(), pageOffsetY() );
00205 
00206     if( contentsHeight() > visibleHeight() )
00207         mat.translate( -contentsX(), contentsY() - contentsHeight() );
00208     else
00209         mat.translate( 0, -visibleHeight() );
00210 
00211     p->setWorldMatrix( mat );
00212 }
00213 
00214 void
00215 VCanvas::viewportPaintEvent( QPaintEvent *e )
00216 {
00217     QRect eventRect = e->rect();
00218     KoRect rect = KoRect::fromQRect( eventRect );
00219     
00220     setYMirroring( m_view->painterFactory()->editpainter() );
00221     viewport()->setUpdatesEnabled( false );
00222     VPainter *p = m_view->painterFactory()->painter();
00223 
00224     // TODO : only update ROIs
00225     p->begin();
00226     p->clear( rect, QColor( 195, 194, 193 ) );
00227     p->setZoomFactor( m_view->zoom() );
00228     setYMirroring( p );
00229     
00230     // TRICK : slightly adjust the matrix so libart AA looks better
00231     QWMatrix mat = p->worldMatrix();
00232     p->setWorldMatrix( mat.translate( -.5, -.5 ) );
00233 
00234     // set up clippath
00235     p->newPath();
00236     p->moveTo( rect.topLeft() );
00237     p->lineTo( rect.topRight() );
00238     p->lineTo( rect.bottomRight() );
00239     p->lineTo( rect.bottomLeft() );
00240     p->lineTo( rect.topLeft() );
00241     p->setClipPath();
00242 
00243     m_part->document().drawPage( p, m_part->pageLayout(), m_view->showPageMargins() );
00244     KoRect bbox = boundingBox();
00245     m_part->document().draw( p, &bbox );
00246 
00247     p->resetClipPath();
00248     p->end();
00249 
00250     // draw handle:
00251     VQPainter qpainter( p->device() );
00252     setYMirroring( &qpainter );
00253     qpainter.setZoomFactor( m_view->zoom() );
00254     m_part->document().selection()->draw( &qpainter, m_view->zoom() );
00255 
00256     if( m_view->toolController()->currentTool() )
00257         m_view->toolController()->currentTool()->draw( &qpainter );
00258 
00259     bitBlt( viewport(), eventRect.topLeft(), p->device(), eventRect );
00260     viewport()->setUpdatesEnabled( true );
00261 }
00262 
00263 void
00264 VCanvas::setViewport( double centerX, double centerY )
00265 {
00266     setContentsPos( int( centerX * contentsWidth() - 0.5 * visibleWidth() ),
00267                     int( centerY * contentsHeight() - 0.5 * visibleHeight() ) );
00268 }
00269 
00270 void
00271 VCanvas::setViewportRect( const KoRect &r )
00272 {
00273     viewport()->setUpdatesEnabled( false );
00274     double zoomX = m_view->zoom() * ( ( visibleWidth() / m_view->zoom() ) / r.width() );
00275     double zoomY = m_view->zoom() * ( ( visibleHeight() / m_view->zoom() ) / r.height() );
00276     double pageOffX = ( contentsWidth() - ( m_part->document().width() * m_view->zoom() ) ) / 2.0;
00277     double centerX = double( ( r.center().x() ) * m_view->zoom() + pageOffX ) / double( contentsWidth() );
00278     double pageOffY = ( contentsHeight() - ( m_part->document().height() * m_view->zoom() ) ) / 2.0;
00279     double centerY = double( ( r.center().y() ) * m_view->zoom() + pageOffY ) / double( contentsHeight() );
00280     double zoom = zoomX < zoomY ? zoomX : zoomY;
00281     resizeContents( int( ( zoom / m_view->zoom() ) * contentsWidth() ),
00282                     int( ( zoom / m_view->zoom() ) * contentsHeight() ) );
00283     setViewport( centerX, 1.0 - centerY );
00284     m_view->setZoomAt( zoom );
00285     viewport()->setUpdatesEnabled( true );
00286 }
00287 
00288 void
00289 VCanvas::drawContents( QPainter* painter, int clipx, int clipy,
00290     int clipw, int cliph  )
00291 {
00292     drawDocument( painter, KoRect( clipx, clipy, clipw, cliph ) );
00293 }
00294 
00295 void
00296 VCanvas::drawDocument( QPainter* /*painter*/, const KoRect&, bool drawVObjects )
00297 {
00298     setYMirroring( m_view->painterFactory()->editpainter() );
00299 
00300     VPainter* p = m_view->painterFactory()->painter();
00301     if( drawVObjects )
00302     {
00303         p->begin();
00304         p->clear( QColor( 195, 194, 193 ) );
00305         p->setZoomFactor( m_view->zoom() );
00306         setYMirroring( p );
00307         // TRICK : slightly adjust the matrix so libart AA looks better
00308         QWMatrix mat = p->worldMatrix();
00309         p->setWorldMatrix( mat.translate( -.5, -.5 ) );
00310 
00311         m_part->document().drawPage( p, m_part->pageLayout(), m_view->showPageMargins() );
00312         KoRect r2 = boundingBox();
00313         m_part->document().draw( p, &r2 );
00314 
00315         p->end();
00316     }
00317 
00318     // draw handle:
00319     VQPainter qpainter( p->device() );
00320     setYMirroring( &qpainter );
00321     qpainter.setZoomFactor( m_view->zoom() );
00322     m_part->document().selection()->draw( &qpainter, m_view->zoom() );
00323 
00324     if( m_view->toolController()->currentTool() )
00325         m_view->toolController()->currentTool()->draw( &qpainter );
00326 
00327     bitBlt( viewport(), 0, 0, p->device(), 0, 0, width(), height() );
00328 }
00329 
00330 void
00331 VCanvas::repaintAll( bool drawVObjects )
00332 {
00333     drawDocument( 0, KoRect( 0, 0, width(), height() ), drawVObjects );
00334 }
00335 
00337 void
00338 VCanvas::repaintAll( const KoRect &r )
00339 {
00340     drawDocument( 0, r );
00341 }
00342 
00343 void
00344 VCanvas::resizeEvent( QResizeEvent* event )
00345 {
00346     double centerX = double( contentsX() + 0.5 * visibleWidth() ) / double( contentsWidth() );
00347     double centerY = double( contentsY() + 0.5 * visibleHeight() ) / double( contentsHeight() );
00348 
00349     QScrollView::resizeEvent( event );
00350     if( !m_pixmap )
00351         m_pixmap = new QPixmap( width(), height() );
00352     else
00353         m_pixmap->resize( width(), height() );
00354 
00355     VPainter *p = m_view->painterFactory()->painter();
00356     p->resize( width(), height() );
00357     p->clear( QColor( 195, 194, 193 ) );
00358     setViewport( centerX, centerY );
00359 }
00360 
00361 void
00362 VCanvas::slotContentsMoving( int /*x*/, int /*y*/ )
00363 {
00364     emit viewportChanged();
00365 }
00366 
00367 void
00368 VCanvas::dragEnterEvent( QDragEnterEvent *e )
00369 {
00370     e->accept( KarbonDrag::canDecode( e ) || KColorDrag::canDecode( e ) );
00371 }
00372 
00373 void
00374 VCanvas::dropEvent( QDropEvent *e )
00375 {
00376     m_view->dropEvent( e );
00377 }
00378 
00379 #include "vcanvas.moc"
00380 
KDE Home | KDE Accessibility Home | Description of Access Keys