summaryrefslogtreecommitdiffstats
path: root/karbon/widgets/vcanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'karbon/widgets/vcanvas.cpp')
-rw-r--r--karbon/widgets/vcanvas.cpp380
1 files changed, 380 insertions, 0 deletions
diff --git a/karbon/widgets/vcanvas.cpp b/karbon/widgets/vcanvas.cpp
new file mode 100644
index 000000000..d4cd64972
--- /dev/null
+++ b/karbon/widgets/vcanvas.cpp
@@ -0,0 +1,380 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <tqcursor.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+
+#include "karbon_view.h"
+#include "karbon_part.h"
+#include "karbon_drag.h"
+#include "vcanvas.h"
+#include "vdocument.h"
+#include "vpainter.h"
+#include "vqpainter.h"
+#include "vpainterfactory.h"
+#include "vselection.h"
+#include "vtoolcontroller.h"
+#include "vtool.h"
+
+#include <kdebug.h>
+#include <tdelocale.h>
+#include <kcolordrag.h>
+
+int
+VCanvas::pageOffsetX() const
+{
+ double zoomedWidth = m_part->document().width() * m_view->zoom();
+ if( contentsWidth() < visibleWidth() )
+ return int( 0.5 * ( visibleWidth() - zoomedWidth ) );
+ else
+ return int( 0.5 * ( contentsWidth() - zoomedWidth ) );
+}
+
+int
+VCanvas::pageOffsetY() const
+{
+ double zoomedHeight = m_part->document().height() * m_view->zoom();
+ if( contentsHeight() < visibleHeight() )
+ return int( 0.5 * ( visibleHeight() - zoomedHeight ) );
+ else
+ return int( 0.5 * ( contentsHeight() - zoomedHeight ) );
+}
+
+KoPoint VCanvas::snapToGrid( const KoPoint &point )
+{
+ if( !m_part->document().grid().isSnap )
+ return point;
+
+ KoPoint p = point;
+
+ KoSize dist = m_part->document().grid().snap;
+ KoSize dxy = m_part->document().grid().freq;
+
+ int dx = tqRound( p.x() / dxy.width() );
+ int dy = tqRound( p.y() / dxy.height() );
+
+ float distx = TQMIN( TQABS( p.x() - dxy.width() * dx ), TQABS( p.x() - dxy.width() * ( dx + 1 ) ) );
+ float disty = TQMIN( TQABS( p.y() - dxy.height() * dy ), TQABS( p.y() - dxy.height() * ( dy + 1 ) ) );
+
+ if( distx < dist.width() )
+ {
+ if( TQABS(p.x() - dxy.width() * dx ) < TQABS( p.x() - dxy.width() * ( dx + 1 ) ) )
+ p.rx() = dxy.width() * dx;
+ else
+ p.rx() = dxy.width() * ( dx + 1 );
+ }
+
+ if( disty < dist.height() )
+ {
+ if( TQABS( p.y() - dxy.height() * dy ) < TQABS( p.y() - dxy.height() * ( dy + 1 ) ) )
+ p.ry() = dxy.height() * dy;
+ else
+ p.ry() = dxy.height() * ( dy + 1 );
+ }
+
+ return p;
+}
+
+
+VCanvas::VCanvas( TQWidget *parent, KarbonView* view, KarbonPart* part )
+ : TQScrollView( parent, "canvas", WStaticContents/*WNorthWestGravity*/ | WResizeNoErase |
+ WRepaintNoErase ), m_part( part ), m_view( view )
+{
+ connect(this, TQT_SIGNAL( contentsMoving( int, int ) ), this, TQT_SLOT( slotContentsMoving( int, int ) ) );
+ viewport()->setFocusPolicy( TQ_StrongFocus );
+
+ viewport()->setMouseTracking( true );
+ setMouseTracking( true );
+
+ viewport()->setBackgroundColor( TQt::white );
+ viewport()->setBackgroundMode( TQWidget::NoBackground );
+ viewport()->installEventFilter( this );
+
+ resizeContents( 800, 600 );
+ m_pixmap = new TQPixmap( 800, 600 );
+
+ setFocus();
+
+ setAcceptDrops( true );
+}
+
+VCanvas::~VCanvas()
+{
+ delete m_pixmap;
+ m_view = 0L;
+ m_part = 0L;
+}
+
+void
+VCanvas::setPos( const KoPoint& p )
+{
+ KoPoint p2 = toViewport( p );
+ TQCursor::setPos( mapToGlobal( TQPoint( int(p2.x()), int(p2.y()) ) ) );
+}
+
+bool
+VCanvas::eventFilter( TQObject* object, TQEvent* event )
+{
+ TQScrollView::eventFilter( object, event );
+
+ if( event->type() == TQEvent::AccelOverride || event->type() == TQEvent::Accel )
+ return TQScrollView::eventFilter( object, event );
+
+ if( event->type() == TQEvent::KeyPress || event->type() == TQEvent::KeyRelease )
+ return m_view->keyEvent( event );
+
+ TQMouseEvent* mouseEvent = dynamic_cast<TQMouseEvent*>( event );
+
+ if( mouseEvent && m_view )
+ {
+ KoPoint canvasCoordinate = toContents( KoPoint( mouseEvent->pos() ) );
+ return m_view->mouseEvent( mouseEvent, canvasCoordinate );
+ }
+
+ return false;
+}
+
+
+// This causes a repaint normally, so just overwriting it omits the repainting
+void
+VCanvas::focusInEvent( TQFocusEvent * )
+{
+}
+
+KoPoint
+VCanvas::toViewport( const KoPoint &p ) const
+{
+ KoPoint p2 = p;
+ p2.setX( ( p.x() * m_view->zoom() ) - contentsX() + pageOffsetX() );
+ if( contentsHeight() > height() )
+ p2.setY( ( contentsHeight() - ( p.y() * m_view->zoom() + contentsY() + pageOffsetY() ) ) );
+ else
+ p2.setY( ( height() - p.y() * m_view->zoom() + pageOffsetY() ) );
+ return p2;
+}
+
+KoPoint
+VCanvas::toContents( const KoPoint &p ) const
+{
+ KoPoint p2 = p;
+ p2.setX( ( p.x() + contentsX() - pageOffsetX() ) / m_view->zoom() );
+ if( contentsHeight() > height() )
+ p2.setY( ( contentsHeight() - ( p.y() + contentsY() + pageOffsetY()) ) / m_view->zoom() );
+ else
+ p2.setY( ( height() - p.y() - pageOffsetY() ) / m_view->zoom() );
+ return p2;
+}
+
+KoRect
+VCanvas::boundingBox() const
+{
+ KoPoint p1( 0, 0 );
+ KoPoint p2( width(), height() );
+ if( !m_view->documentDeleted() )
+ {
+ p1 = toContents( p1 );
+ p2 = toContents( p2 );
+ }
+ return KoRect( p1, p2 ).normalize();
+}
+
+void
+VCanvas::setYMirroring( VPainter *p )
+{
+ TQWMatrix mat;
+
+ mat.scale( 1, -1 );
+ mat.translate( pageOffsetX(), pageOffsetY() );
+
+ if( contentsHeight() > visibleHeight() )
+ mat.translate( -contentsX(), contentsY() - contentsHeight() );
+ else
+ mat.translate( 0, -visibleHeight() );
+
+ p->setWorldMatrix( mat );
+}
+
+void
+VCanvas::viewportPaintEvent( TQPaintEvent *e )
+{
+ TQRect eventRect = e->rect();
+ KoRect rect = KoRect::fromTQRect( eventRect );
+
+ setYMirroring( m_view->painterFactory()->editpainter() );
+ viewport()->setUpdatesEnabled( false );
+ VPainter *p = m_view->painterFactory()->painter();
+
+ // TODO : only update ROIs
+ p->begin();
+ p->clear( rect, TQColor( 195, 194, 193 ) );
+ p->setZoomFactor( m_view->zoom() );
+ setYMirroring( p );
+
+ // TRICK : slightly adjust the matrix so libart AA looks better
+ TQWMatrix mat = p->worldMatrix();
+ p->setWorldMatrix( mat.translate( -.5, -.5 ) );
+
+ // set up clippath
+ p->newPath();
+ p->moveTo( rect.topLeft() );
+ p->lineTo( rect.topRight() );
+ p->lineTo( rect.bottomRight() );
+ p->lineTo( rect.bottomLeft() );
+ p->lineTo( rect.topLeft() );
+ p->setClipPath();
+
+ m_part->document().drawPage( p, m_part->pageLayout(), m_view->showPageMargins() );
+ KoRect bbox = boundingBox();
+ m_part->document().draw( p, &bbox );
+
+ p->resetClipPath();
+ p->end();
+
+ // draw handle:
+ VTQPainter qpainter( p->device() );
+ setYMirroring( &qpainter );
+ qpainter.setZoomFactor( m_view->zoom() );
+ m_part->document().selection()->draw( &qpainter, m_view->zoom() );
+
+ if( m_view->toolController()->currentTool() )
+ m_view->toolController()->currentTool()->draw( &qpainter );
+
+ bitBlt( viewport(), eventRect.topLeft(), p->device(), eventRect );
+ viewport()->setUpdatesEnabled( true );
+}
+
+void
+VCanvas::setViewport( double centerX, double centerY )
+{
+ setContentsPos( int( centerX * contentsWidth() - 0.5 * visibleWidth() ),
+ int( centerY * contentsHeight() - 0.5 * visibleHeight() ) );
+}
+
+void
+VCanvas::setViewportRect( const KoRect &r )
+{
+ viewport()->setUpdatesEnabled( false );
+ double zoomX = m_view->zoom() * ( ( visibleWidth() / m_view->zoom() ) / r.width() );
+ double zoomY = m_view->zoom() * ( ( visibleHeight() / m_view->zoom() ) / r.height() );
+ double pageOffX = ( contentsWidth() - ( m_part->document().width() * m_view->zoom() ) ) / 2.0;
+ double centerX = double( ( r.center().x() ) * m_view->zoom() + pageOffX ) / double( contentsWidth() );
+ double pageOffY = ( contentsHeight() - ( m_part->document().height() * m_view->zoom() ) ) / 2.0;
+ double centerY = double( ( r.center().y() ) * m_view->zoom() + pageOffY ) / double( contentsHeight() );
+ double zoom = zoomX < zoomY ? zoomX : zoomY;
+ resizeContents( int( ( zoom / m_view->zoom() ) * contentsWidth() ),
+ int( ( zoom / m_view->zoom() ) * contentsHeight() ) );
+ setViewport( centerX, 1.0 - centerY );
+ m_view->setZoomAt( zoom );
+ viewport()->setUpdatesEnabled( true );
+}
+
+void
+VCanvas::drawContents( TQPainter* painter, int clipx, int clipy,
+ int clipw, int cliph )
+{
+ drawDocument( painter, KoRect( clipx, clipy, clipw, cliph ) );
+}
+
+void
+VCanvas::drawDocument( TQPainter* /*painter*/, const KoRect&, bool drawVObjects )
+{
+ setYMirroring( m_view->painterFactory()->editpainter() );
+
+ VPainter* p = m_view->painterFactory()->painter();
+ if( drawVObjects )
+ {
+ p->begin();
+ p->clear( TQColor( 195, 194, 193 ) );
+ p->setZoomFactor( m_view->zoom() );
+ setYMirroring( p );
+ // TRICK : slightly adjust the matrix so libart AA looks better
+ TQWMatrix mat = p->worldMatrix();
+ p->setWorldMatrix( mat.translate( -.5, -.5 ) );
+
+ m_part->document().drawPage( p, m_part->pageLayout(), m_view->showPageMargins() );
+ KoRect r2 = boundingBox();
+ m_part->document().draw( p, &r2 );
+
+ p->end();
+ }
+
+ // draw handle:
+ VTQPainter qpainter( p->device() );
+ setYMirroring( &qpainter );
+ qpainter.setZoomFactor( m_view->zoom() );
+ m_part->document().selection()->draw( &qpainter, m_view->zoom() );
+
+ if( m_view->toolController()->currentTool() )
+ m_view->toolController()->currentTool()->draw( &qpainter );
+
+ bitBlt( viewport(), 0, 0, p->device(), 0, 0, width(), height() );
+}
+
+void
+VCanvas::repaintAll( bool drawVObjects )
+{
+ drawDocument( 0, KoRect( 0, 0, width(), height() ), drawVObjects );
+}
+
+/// repaints just a rect area (no scrolling)
+void
+VCanvas::repaintAll( const KoRect &r )
+{
+ drawDocument( 0, r );
+}
+
+void
+VCanvas::resizeEvent( TQResizeEvent* event )
+{
+ double centerX = double( contentsX() + 0.5 * visibleWidth() ) / double( contentsWidth() );
+ double centerY = double( contentsY() + 0.5 * visibleHeight() ) / double( contentsHeight() );
+
+ TQScrollView::resizeEvent( event );
+ if( !m_pixmap )
+ m_pixmap = new TQPixmap( width(), height() );
+ else
+ m_pixmap->resize( width(), height() );
+
+ VPainter *p = m_view->painterFactory()->painter();
+ p->resize( width(), height() );
+ p->clear( TQColor( 195, 194, 193 ) );
+ setViewport( centerX, centerY );
+}
+
+void
+VCanvas::slotContentsMoving( int /*x*/, int /*y*/ )
+{
+ emit viewportChanged();
+}
+
+void
+VCanvas::dragEnterEvent( TQDragEnterEvent *e )
+{
+ e->accept( KarbonDrag::canDecode( e ) || KColorDrag::canDecode( e ) );
+}
+
+void
+VCanvas::dropEvent( TQDropEvent *e )
+{
+ m_view->dropEvent( e );
+}
+
+#include "vcanvas.moc"
+