00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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 | 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
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
00225 p->begin();
00226 p->clear( rect, QColor( 195, 194, 193 ) );
00227 p->setZoomFactor( m_view->zoom() );
00228 setYMirroring( p );
00229
00230
00231 QWMatrix mat = p->worldMatrix();
00232 p->setWorldMatrix( mat.translate( -.5, -.5 ) );
00233
00234
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
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* , 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
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
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 , int )
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