karbon

vcanvas.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001, 2002, 2003 The Karbon Developers
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include <tqcursor.h>
21#include <tqpainter.h>
22#include <tqpixmap.h>
23
24#include "karbon_view.h"
25#include "karbon_part.h"
26#include "karbon_drag.h"
27#include "vcanvas.h"
28#include "vdocument.h"
29#include "vpainter.h"
30#include "vqpainter.h"
31#include "vpainterfactory.h"
32#include "vselection.h"
33#include "vtoolcontroller.h"
34#include "vtool.h"
35
36#include <kdebug.h>
37#include <tdelocale.h>
38#include <kcolordrag.h>
39
40int
41VCanvas::pageOffsetX() const
42{
43 double zoomedWidth = m_part->document().width() * m_view->zoom();
44 if( contentsWidth() < visibleWidth() )
45 return int( 0.5 * ( visibleWidth() - zoomedWidth ) );
46 else
47 return int( 0.5 * ( contentsWidth() - zoomedWidth ) );
48}
49
50int
51VCanvas::pageOffsetY() const
52{
53 double zoomedHeight = m_part->document().height() * m_view->zoom();
54 if( contentsHeight() < visibleHeight() )
55 return int( 0.5 * ( visibleHeight() - zoomedHeight ) );
56 else
57 return int( 0.5 * ( contentsHeight() - zoomedHeight ) );
58}
59
60KoPoint VCanvas::snapToGrid( const KoPoint &point )
61{
62 if( !m_part->document().grid().isSnap )
63 return point;
64
65 KoPoint p = point;
66
67 KoSize dist = m_part->document().grid().snap;
68 KoSize dxy = m_part->document().grid().freq;
69
70 int dx = tqRound( p.x() / dxy.width() );
71 int dy = tqRound( p.y() / dxy.height() );
72
73 float distx = TQMIN( TQABS( p.x() - dxy.width() * dx ), TQABS( p.x() - dxy.width() * ( dx + 1 ) ) );
74 float disty = TQMIN( TQABS( p.y() - dxy.height() * dy ), TQABS( p.y() - dxy.height() * ( dy + 1 ) ) );
75
76 if( distx < dist.width() )
77 {
78 if( TQABS(p.x() - dxy.width() * dx ) < TQABS( p.x() - dxy.width() * ( dx + 1 ) ) )
79 p.rx() = dxy.width() * dx;
80 else
81 p.rx() = dxy.width() * ( dx + 1 );
82 }
83
84 if( disty < dist.height() )
85 {
86 if( TQABS( p.y() - dxy.height() * dy ) < TQABS( p.y() - dxy.height() * ( dy + 1 ) ) )
87 p.ry() = dxy.height() * dy;
88 else
89 p.ry() = dxy.height() * ( dy + 1 );
90 }
91
92 return p;
93}
94
95
96VCanvas::VCanvas( TQWidget *parent, KarbonView* view, KarbonPart* part )
97 : TQScrollView( parent, "canvas", WStaticContents/*WNorthWestGravity*/ | WResizeNoErase |
98 WRepaintNoErase ), m_part( part ), m_view( view )
99{
100 connect(this, TQ_SIGNAL( contentsMoving( int, int ) ), this, TQ_SLOT( slotContentsMoving( int, int ) ) );
101 viewport()->setFocusPolicy( TQWidget::StrongFocus );
102
103 viewport()->setMouseTracking( true );
104 setMouseTracking( true );
105
106 viewport()->setBackgroundColor( TQt::white );
107 viewport()->setBackgroundMode( TQWidget::NoBackground );
108 viewport()->installEventFilter( this );
109
110 resizeContents( 800, 600 );
111 m_pixmap = new TQPixmap( 800, 600 );
112
113 setFocus();
114
115 setAcceptDrops( true );
116}
117
118VCanvas::~VCanvas()
119{
120 delete m_pixmap;
121 m_view = 0L;
122 m_part = 0L;
123}
124
125void
126VCanvas::setPos( const KoPoint& p )
127{
128 KoPoint p2 = toViewport( p );
129 TQCursor::setPos( mapToGlobal( TQPoint( int(p2.x()), int(p2.y()) ) ) );
130}
131
132bool
133VCanvas::eventFilter( TQObject* object, TQEvent* event )
134{
135 TQScrollView::eventFilter( object, event );
136
137 if( event->type() == TQEvent::AccelOverride || event->type() == TQEvent::Accel )
138 return TQScrollView::eventFilter( object, event );
139
140 if( event->type() == TQEvent::KeyPress || event->type() == TQEvent::KeyRelease )
141 return m_view->keyEvent( event );
142
143 TQMouseEvent* mouseEvent = dynamic_cast<TQMouseEvent*>( event );
144
145 if( mouseEvent && m_view )
146 {
147 KoPoint canvasCoordinate = toContents( KoPoint( mouseEvent->pos() ) );
148 return m_view->mouseEvent( mouseEvent, canvasCoordinate );
149 }
150
151 return false;
152}
153
154
155// This causes a repaint normally, so just overwriting it omits the repainting
156void
157VCanvas::focusInEvent( TQFocusEvent * )
158{
159}
160
161KoPoint
162VCanvas::toViewport( const KoPoint &p ) const
163{
164 KoPoint p2 = p;
165 p2.setX( ( p.x() * m_view->zoom() ) - contentsX() + pageOffsetX() );
166 if( contentsHeight() > height() )
167 p2.setY( ( contentsHeight() - ( p.y() * m_view->zoom() + contentsY() + pageOffsetY() ) ) );
168 else
169 p2.setY( ( height() - p.y() * m_view->zoom() + pageOffsetY() ) );
170 return p2;
171}
172
173KoPoint
174VCanvas::toContents( const KoPoint &p ) const
175{
176 KoPoint p2 = p;
177 p2.setX( ( p.x() + contentsX() - pageOffsetX() ) / m_view->zoom() );
178 if( contentsHeight() > height() )
179 p2.setY( ( contentsHeight() - ( p.y() + contentsY() + pageOffsetY()) ) / m_view->zoom() );
180 else
181 p2.setY( ( height() - p.y() - pageOffsetY() ) / m_view->zoom() );
182 return p2;
183}
184
185KoRect
186VCanvas::boundingBox() const
187{
188 KoPoint p1( 0, 0 );
189 KoPoint p2( width(), height() );
190 if( !m_view->documentDeleted() )
191 {
192 p1 = toContents( p1 );
193 p2 = toContents( p2 );
194 }
195 return KoRect( p1, p2 ).normalize();
196}
197
198void
199VCanvas::setYMirroring( VPainter *p )
200{
201 TQWMatrix mat;
202
203 mat.scale( 1, -1 );
204 mat.translate( pageOffsetX(), pageOffsetY() );
205
206 if( contentsHeight() > visibleHeight() )
207 mat.translate( -contentsX(), contentsY() - contentsHeight() );
208 else
209 mat.translate( 0, -visibleHeight() );
210
211 p->setWorldMatrix( mat );
212}
213
214void
215VCanvas::viewportPaintEvent( TQPaintEvent *e )
216{
217 TQRect eventRect = e->rect();
218 KoRect rect = KoRect::fromTQRect( eventRect );
219
220 setYMirroring( m_view->painterFactory()->editpainter() );
221 viewport()->setUpdatesEnabled( false );
222 VPainter *p = m_view->painterFactory()->painter();
223
224 // TODO : only update ROIs
225 p->begin();
226 p->clear( rect, TQColor( 195, 194, 193 ) );
227 p->setZoomFactor( m_view->zoom() );
228 setYMirroring( p );
229
230 // TRICK : slightly adjust the matrix so libart AA looks better
231 TQWMatrix mat = p->worldMatrix();
232 p->setWorldMatrix( mat.translate( -.5, -.5 ) );
233
234 // set up clippath
235 p->newPath();
236 p->moveTo( rect.topLeft() );
237 p->lineTo( rect.topRight() );
238 p->lineTo( rect.bottomRight() );
239 p->lineTo( rect.bottomLeft() );
240 p->lineTo( rect.topLeft() );
241 p->setClipPath();
242
243 m_part->document().drawPage( p, m_part->pageLayout(), m_view->showPageMargins() );
244 KoRect bbox = boundingBox();
245 m_part->document().draw( p, &bbox );
246
247 p->resetClipPath();
248 p->end();
249
250 // draw handle:
251 VTQPainter qpainter( p->device() );
252 setYMirroring( &qpainter );
253 qpainter.setZoomFactor( m_view->zoom() );
254 m_part->document().selection()->draw( &qpainter, m_view->zoom() );
255
256 if( m_view->toolController()->currentTool() )
257 m_view->toolController()->currentTool()->draw( &qpainter );
258
259 bitBlt( viewport(), eventRect.topLeft(), p->device(), eventRect );
260 viewport()->setUpdatesEnabled( true );
261}
262
263void
264VCanvas::setViewport( double centerX, double centerY )
265{
266 setContentsPos( int( centerX * contentsWidth() - 0.5 * visibleWidth() ),
267 int( centerY * contentsHeight() - 0.5 * visibleHeight() ) );
268}
269
270void
271VCanvas::setViewportRect( const KoRect &r )
272{
273 viewport()->setUpdatesEnabled( false );
274 double zoomX = m_view->zoom() * ( ( visibleWidth() / m_view->zoom() ) / r.width() );
275 double zoomY = m_view->zoom() * ( ( visibleHeight() / m_view->zoom() ) / r.height() );
276 double pageOffX = ( contentsWidth() - ( m_part->document().width() * m_view->zoom() ) ) / 2.0;
277 double centerX = double( ( r.center().x() ) * m_view->zoom() + pageOffX ) / double( contentsWidth() );
278 double pageOffY = ( contentsHeight() - ( m_part->document().height() * m_view->zoom() ) ) / 2.0;
279 double centerY = double( ( r.center().y() ) * m_view->zoom() + pageOffY ) / double( contentsHeight() );
280 double zoom = zoomX < zoomY ? zoomX : zoomY;
281 resizeContents( int( ( zoom / m_view->zoom() ) * contentsWidth() ),
282 int( ( zoom / m_view->zoom() ) * contentsHeight() ) );
283 setViewport( centerX, 1.0 - centerY );
284 m_view->setZoomAt( zoom );
285 viewport()->setUpdatesEnabled( true );
286}
287
288void
289VCanvas::drawContents( TQPainter* painter, int clipx, int clipy,
290 int clipw, int cliph )
291{
292 drawDocument( painter, KoRect( clipx, clipy, clipw, cliph ) );
293}
294
295void
296VCanvas::drawDocument( TQPainter* /*painter*/, const KoRect&, bool drawVObjects )
297{
298 setYMirroring( m_view->painterFactory()->editpainter() );
299
300 VPainter* p = m_view->painterFactory()->painter();
301 if( drawVObjects )
302 {
303 p->begin();
304 p->clear( TQColor( 195, 194, 193 ) );
305 p->setZoomFactor( m_view->zoom() );
306 setYMirroring( p );
307 // TRICK : slightly adjust the matrix so libart AA looks better
308 TQWMatrix mat = p->worldMatrix();
309 p->setWorldMatrix( mat.translate( -.5, -.5 ) );
310
311 m_part->document().drawPage( p, m_part->pageLayout(), m_view->showPageMargins() );
312 KoRect r2 = boundingBox();
313 m_part->document().draw( p, &r2 );
314
315 p->end();
316 }
317
318 // draw handle:
319 VTQPainter qpainter( p->device() );
320 setYMirroring( &qpainter );
321 qpainter.setZoomFactor( m_view->zoom() );
322 m_part->document().selection()->draw( &qpainter, m_view->zoom() );
323
324 if( m_view->toolController()->currentTool() )
325 m_view->toolController()->currentTool()->draw( &qpainter );
326
327 bitBlt( viewport(), 0, 0, p->device(), 0, 0, width(), height() );
328}
329
330void
331VCanvas::repaintAll( bool drawVObjects )
332{
333 drawDocument( 0, KoRect( 0, 0, width(), height() ), drawVObjects );
334}
335
337void
338VCanvas::repaintAll( const KoRect &r )
339{
340 drawDocument( 0, r );
341}
342
343void
344VCanvas::resizeEvent( TQResizeEvent* event )
345{
346 double centerX = double( contentsX() + 0.5 * visibleWidth() ) / double( contentsWidth() );
347 double centerY = double( contentsY() + 0.5 * visibleHeight() ) / double( contentsHeight() );
348
349 TQScrollView::resizeEvent( event );
350 if( !m_pixmap )
351 m_pixmap = new TQPixmap( width(), height() );
352 else
353 m_pixmap->resize( width(), height() );
354
355 VPainter *p = m_view->painterFactory()->painter();
356 p->resize( width(), height() );
357 p->clear( TQColor( 195, 194, 193 ) );
358 setViewport( centerX, centerY );
359}
360
361void
362VCanvas::slotContentsMoving( int /*x*/, int /*y*/ )
363{
364 emit viewportChanged();
365}
366
367void
368VCanvas::dragEnterEvent( TQDragEnterEvent *e )
369{
370 e->accept( KarbonDrag::canDecode( e ) || KColorDrag::canDecode( e ) );
371}
372
373void
374VCanvas::dropEvent( TQDropEvent *e )
375{
376 m_view->dropEvent( e );
377}
378
379#include "vcanvas.moc"
380
Keeps track of visual per document properties.
Definition karbon_part.h:46