|
|
|
/* 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 <klocale.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 tqrepaint 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"
|
|
|
|
|