diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kivio/kiviopart/kivio_canvas.cpp | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kivio/kiviopart/kivio_canvas.cpp')
-rw-r--r-- | kivio/kiviopart/kivio_canvas.cpp | 1291 |
1 files changed, 1291 insertions, 0 deletions
diff --git a/kivio/kiviopart/kivio_canvas.cpp b/kivio/kiviopart/kivio_canvas.cpp new file mode 100644 index 00000000..162f076f --- /dev/null +++ b/kivio/kiviopart/kivio_canvas.cpp @@ -0,0 +1,1291 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000-2001 theKompany.com & Dave Marotti + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "kivio_canvas.h" +#include "kivio_page.h" +#include "kivio_map.h" +#include "kivio_view.h" +#include "kivio_doc.h" + +#include "kivio_icon_view.h" +#include "kivio_stencil.h" +#include "kivio_stencil_spawner.h" +#include "kivio_stencil_spawner_info.h" +#include "kivio_stackbar.h" +#include "kivio_screen_painter.h" +#include "kivio_grid_data.h" +#include "kivio_layer.h" + +#include "kivio_pluginmanager.h" + +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kcursor.h> +#include <KoGlobal.h> +#include <KoZoomHandler.h> +#include <KoSize.h> +#include <KoRuler.h> +#include <KoPoint.h> +#include <KoTabBar.h> +#include <kapplication.h> + +#include <assert.h> +#include <stdio.h> +#include <qlabel.h> +#include <qpixmap.h> +#include <qscrollbar.h> +#include <qtimer.h> +#include <qsize.h> + +using namespace Kivio; + +KivioCanvas::KivioCanvas( QWidget *par, KivioView* view, KivioDoc* doc, QScrollBar* vs, QScrollBar* hs) +: QWidget(par, "KivioCanvas", WResizeNoErase | WRepaintNoErase), + m_pView(view), + m_pDoc(doc), + m_pVertScrollBar(vs), + m_pHorzScrollBar(hs), + m_guides(view, view->zoomHandler()) +{ + setBackgroundMode(NoBackground); + setAcceptDrops(true); + setMouseTracking(true); + setFocusPolicy(StrongFocus); + setFocus(); + + m_showConnectorTargets = false; + delegateThisEvent = true; + + m_pVertScrollBar->setLineStep(1); + m_pHorzScrollBar->setLineStep(1); + + + m_pVertScrollBar->setPageStep(10); + m_pHorzScrollBar->setPageStep(10); + + connect(m_pVertScrollBar, SIGNAL(valueChanged(int)), SLOT(scrollV(int))); + connect( m_pHorzScrollBar, SIGNAL(valueChanged(int)), SLOT(scrollH(int))); + + m_iXOffset = 0; + m_iYOffset = 0; + + m_pScrollX = 0; + m_pScrollY = 0; + + m_pageOffsetX = 0; + m_pageOffsetY = 0; + + m_pasteMoving = false; + + m_buffer = new QPixmap(); + + m_pDragStencil = 0L; + unclippedSpawnerPainter = 0L; + unclippedPainter = 0L; + + m_borderTimer = new QTimer(this); + connect(m_borderTimer,SIGNAL(timeout()),SLOT(borderTimerTimeout())); +} + +KivioCanvas::~KivioCanvas() +{ + delete m_buffer; + delete m_borderTimer; + delete unclippedPainter; +} + +KivioPage* KivioCanvas::findPage( const QString& _name ) +{ + return m_pDoc->map()->findPage( _name ); +} + +const KivioPage* KivioCanvas::activePage() const +{ + return m_pView->activePage(); +} + +KivioPage* KivioCanvas::activePage() +{ + return m_pView->activePage(); +} + +void KivioCanvas::scrollH( int value ) +{ + // Relative movement + int dx = m_iXOffset - value; + // New absolute position + m_iXOffset = value; + + bitBlt(m_buffer, dx, 0, m_buffer); + scroll(dx, 0); + + emit visibleAreaChanged(); +} + +void KivioCanvas::scrollV( int value ) +{ + // Relative movement + int dy = m_iYOffset - value; + // New absolute position + m_iYOffset = value; + + bitBlt(m_buffer, 0, dy, m_buffer); + scroll(0, dy); + + emit visibleAreaChanged(); +} + +void KivioCanvas::scrollDx( int dx ) +{ + if ( dx == 0 ) + return; + + int value = m_iXOffset - dx; + m_pHorzScrollBar->setValue(value); +} + +void KivioCanvas::scrollDy( int dy ) +{ + if ( dy == 0 ) + return; + + int value = m_iYOffset - dy; + m_pVertScrollBar->setValue(value); +} + +void KivioCanvas::resizeEvent( QResizeEvent* ) +{ + m_buffer->resize(size()); + updateScrollBars(); + + emit visibleAreaChanged(); +} + +void KivioCanvas::wheelEvent( QWheelEvent* ev ) +{ + ev->accept(); + + if( (ev->delta()>0)) + { + if(ev->state() == ControlButton) { + zoomIn(ev->pos()); + } else if(ev->state() == ShiftButton) { + m_pVertScrollBar->setValue(m_pVertScrollBar->value() - height()); + } else { + m_pVertScrollBar->setValue(m_pVertScrollBar->value() - 30); + } + } + else + { + if(ev->state() == ControlButton) { + zoomOut(ev->pos()); + } else if(ev->state() == ShiftButton) { + m_pVertScrollBar->setValue(m_pVertScrollBar->value() + height()); + } else { + m_pVertScrollBar->setValue(m_pVertScrollBar->value() + 30); + } + } +} + +void KivioCanvas::setUpdatesEnabled( bool isUpdate ) +{ + static int i = 0; + + QWidget::setUpdatesEnabled(isUpdate); + if (isUpdate) { + --i; + if (i == 0) { + update(); + updateScrollBars(); + + blockSignals(false); + + emit visibleAreaChanged(); + } + } else { + i++; + blockSignals(true); + } +} + +void KivioCanvas::zoomIn(const QPoint &p) +{ + setUpdatesEnabled(false); + KoPoint p0 = mapFromScreen(p); + m_pView->viewZoom(m_pView->zoomHandler()->zoom() + 25); + QPoint p1 = mapToScreen(p0); + scrollDx(-p1.x()+p.x()); + scrollDy(-p1.y()+p.y()); + setUpdatesEnabled(true); +} + +void KivioCanvas::zoomOut(const QPoint &p) +{ + setUpdatesEnabled(false); + KoPoint p0 = mapFromScreen(p); + int newZoom = m_pView->zoomHandler()->zoom() - 25; + + if(newZoom > 0) { + m_pView->viewZoom(newZoom); + QPoint p1 = mapToScreen(p0); + scrollDx(-p1.x()+p.x()); + scrollDy(-p1.y()+p.y()); + } + setUpdatesEnabled(true); +} + +void KivioCanvas::paintEvent( QPaintEvent* ev ) +{ + if ( m_pDoc->isLoading() || !activePage() ) + return; + + KivioPage* page = activePage(); + + QPainter painter; + painter.begin(m_buffer); + + KoPageLayout pl = page->paperLayout(); + int pw = m_pView->zoomHandler()->zoomItX(pl.ptWidth); + int ph = m_pView->zoomHandler()->zoomItY(pl.ptHeight); + QRect fillRect(0, 0, pw, ph); + QRect paintRect = ev->rect(); + QRegion grayRegion(paintRect); + grayRegion.translate(m_iXOffset - m_pageOffsetX, m_iYOffset - m_pageOffsetY); + grayRegion -= fillRect; + grayRegion.translate(-m_iXOffset + m_pageOffsetX, -m_iYOffset + m_pageOffsetY); + + // This code comes from KPresenter's kprcanvas.cpp + // Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + painter.save(); + painter.setClipRegion(grayRegion, QPainter::CoordPainter); + painter.setPen(Qt::NoPen); + painter.fillRect(grayRegion.boundingRect(), KApplication::palette().active().brush(QColorGroup::Mid)); + painter.restore(); + // end of copy... + + painter.translate(-m_iXOffset + m_pageOffsetX, -m_iYOffset +m_pageOffsetY); + painter.fillRect(fillRect, white); + + // Draw Grid + if(m_pDoc->grid().isShow) { + KoPoint topLeft(0, 0); + KoPoint bottomRight(pl.ptWidth, pl.ptHeight); + QPoint zoomedTL = m_pView->zoomHandler()->zoomPoint(topLeft); + QPoint zoomedBR = m_pView->zoomHandler()->zoomPoint(bottomRight); + + KoSize freq = m_pDoc->grid().freq; + + painter.setPen(m_pDoc->grid().color); + + double x = qRound(topLeft.x() / freq.width()) * freq.width(); + int zoomed = 0; + + while(x <= bottomRight.x()) { + zoomed = m_pView->zoomHandler()->zoomItX(x); + painter.drawLine(zoomed, zoomedTL.y(), zoomed, zoomedBR.y()); + x += freq.width(); + } + + double y = qRound(topLeft.y() / freq.height()) * freq.height(); + + while(y <= bottomRight.y()) { + zoomed = m_pView->zoomHandler()->zoomItY(y); + painter.drawLine(zoomedTL.x(), zoomed, zoomedBR.x(), zoomed); + y += freq.height(); + } + } + + if(m_pView->isShowPageMargins()) { + int ml = m_pView->zoomHandler()->zoomItX(pl.ptLeft); + int mt = m_pView->zoomHandler()->zoomItY(pl.ptTop); + int mr = m_pView->zoomHandler()->zoomItX(pl.ptRight); + int mb = m_pView->zoomHandler()->zoomItY(pl.ptBottom); + + painter.save(); + painter.setPen(QPen("#C7C7C7",1,SolidLine)); + painter.drawRect(ml,mt,pw-ml-mr,ph-mt-mb); + painter.restore(); + } + + // Draw page borders + painter.setPen(black); + painter.fillRect(pw, 3, 5, ph, gray); + painter.fillRect(3, ph, pw, 3, gray); + painter.drawRect(0, 0, pw, ph); + + // Draw content + KivioScreenPainter kpainter; + kpainter.start(m_buffer); + kpainter.translateBy(-m_iXOffset + m_pageOffsetX, -m_iYOffset + m_pageOffsetY); + m_pDoc->paintContent(kpainter, paintRect, false, page, QPoint(0, 0), m_pView->zoomHandler(), showConnectorTargets(), true); + kpainter.stop(); + + if(m_pView->isShowGuides()) { + m_guides.paintGuides(painter); + } + + painter.end(); + + bitBlt(this, paintRect.left(), paintRect.top(), m_buffer, + paintRect.left(), paintRect.top(), paintRect.width(), paintRect.height()); +} + +void KivioCanvas::updateScrollBars() +{ + if(!activePage()) { + return; + } + + KoPageLayout pl = activePage()->paperLayout(); + int pw = m_pView->zoomHandler()->zoomItX(pl.ptWidth); + int ph = m_pView->zoomHandler()->zoomItY(pl.ptHeight); + + m_pScrollX = QMAX(pw - width(), 0); + m_pScrollY = QMAX(ph - height(), 0); + + m_pHorzScrollBar->setRange(0, m_pScrollX); + if ( m_pHorzScrollBar->value() > m_pHorzScrollBar->maxValue() || + m_pHorzScrollBar->value() < m_pHorzScrollBar->minValue() ) + { + m_pHorzScrollBar->setValue(0); + } + + m_pVertScrollBar->setRange(0, m_pScrollY); + if ( m_pVertScrollBar->value() > m_pVertScrollBar->maxValue() || + m_pVertScrollBar->value() < m_pVertScrollBar->minValue() ) + { + m_pVertScrollBar->setValue(0); + } + + m_pVertScrollBar->setPageStep( height() ); + m_pHorzScrollBar->setPageStep( width() ); + + if(pw >= width()) { + m_pageOffsetX = 0; + } else { + m_pageOffsetX = (width() - pw) / 2; + } + + if(ph >= height()) { + m_pageOffsetY = 0; + } else { + m_pageOffsetY = (height() - ph) / 2; + } +} + +QSize KivioCanvas::actualSize() const +{ + return QSize(m_pScrollX, m_pScrollY); +} + +bool KivioCanvas::event( QEvent* e ) +{ + bool f = QWidget::event(e); + + if (m_pView->pluginManager() && delegateThisEvent) { + f = m_pView->pluginManager()->delegateEvent(e); + } + + delegateThisEvent = true; + return f; +} + +void KivioCanvas::enterEvent( QEvent* ) +{ +} + +void KivioCanvas::leaveEvent( QEvent* ) +{ + m_pView->setMousePos(-1, -1); +} + +void KivioCanvas::mousePressEvent(QMouseEvent* e) +{ + if(!m_pDoc->isReadWrite()) + return; + + if(m_pasteMoving) { + endPasteMoving(); + return; + } + + Kivio::PluginManager* pluginManager = view()->pluginManager(); + + if(m_pView->isShowGuides() && (!pluginManager || (pluginManager->defaultTool() == pluginManager->activeTool()))) { + if(m_guides.mousePressEvent(e)) { + delegateThisEvent = false; + return; + } + } +} + +void KivioCanvas::mouseReleaseEvent(QMouseEvent* e) +{ + if(!m_pDoc->isReadWrite()) + return; + + Kivio::PluginManager* pluginManager = view()->pluginManager(); + + if(view()->isShowGuides() && (!pluginManager || (pluginManager->defaultTool() == pluginManager->activeTool()))) { + if(m_guides.mouseReleaseEvent(e)) { + delegateThisEvent = false; + return; + } + } +} + +void KivioCanvas::mouseMoveEvent(QMouseEvent* e) +{ + if(!m_pDoc->isReadWrite()) + return; + + if(m_pasteMoving) { + continuePasteMoving(e->pos()); + } else { + Kivio::PluginManager* pluginManager = view()->pluginManager(); + + if(m_pView->isShowGuides() && (!pluginManager || (pluginManager->defaultTool() == pluginManager->activeTool()))) { + delegateThisEvent = !m_guides.mouseMoveEvent(e); + } + } + + lastPoint = e->pos(); + view()->setMousePos(lastPoint.x(), lastPoint.y()); +} + +QPoint KivioCanvas::mapToScreen(const KoPoint& pos) +{ + QPoint p; + int x = m_pView->zoomHandler()->zoomItX(pos.x()); + int y = m_pView->zoomHandler()->zoomItY(pos.y()); + + p.setX( x - m_iXOffset + m_pageOffsetX); + p.setY( y - m_iYOffset + m_pageOffsetY); + + return p; +} + +KoPoint KivioCanvas::mapFromScreen( const QPoint & pos ) +{ + int x = pos.x() + m_iXOffset - m_pageOffsetX; + int y = pos.y() + m_iYOffset - m_pageOffsetY; + double xf = m_pView->zoomHandler()->unzoomItX(x); + double yf = m_pView->zoomHandler()->unzoomItY(y); + + KoPoint p(xf, yf); + return p; +} + +void KivioCanvas::startRectDraw( const QPoint &p, RectType ) +{ + currRect = QRect( 0, 0, -1, -1 ); + + QPoint pos( p ); + oldRectValid = false; + beginUnclippedPainter(); + rectAnchor = pos; + currRect = QRect( rectAnchor, QPoint(0,0) ); + + m_borderTimer->start(100); +} + +void KivioCanvas::continueRectDraw( const QPoint &p, RectType ) +{ + QPoint pos = p; + QPoint p2 = pos; + QRect r( rectAnchor, p2 ); + r = r.normalize(); + + if ( oldRectValid ) + unclippedPainter->drawRect( currRect ); + if ( r.width() > 1 || r.height() > 1 ) { + oldRectValid = true; + currRect = r; + unclippedPainter->drawRect( currRect ); + } else { + oldRectValid = false; + } +} + +void KivioCanvas::endRectDraw() +{ + m_borderTimer->stop(); + + if ( !unclippedPainter ) + return; + + if ( oldRectValid ) + unclippedPainter->drawRect( currRect ); + + endUnclippedPainter(); +} + +/** + * Starts a new drag & draw (called from the drag enter event) + * + * @param p The point to begin at + * + * This will allocate a new KivioStencil for drawing with and + * set some class variables used during redraws. + */ +void KivioCanvas::startSpawnerDragDraw( const QPoint &p ) +{ + currRect = QRect( 0, 0, -1, -1 ); + + KivioStencilSpawner *pSpawner = KivioIconView::curDragSpawner(); + if( !pSpawner ) + return; + + // If we for some reason didn't delete an old drag stencil, + // do so now. + if( m_pDragStencil ) + { + kdDebug(43000) << "KivioCanvas::startSpawnerDragDraw() - m_pDragStencil still exists. BUG!" << endl; + delete m_pDragStencil; + m_pDragStencil = 0L; + } + + // Map the point from screenspace to page space + KoPoint qp = mapFromScreen( p ); + qp = snapToGrid(qp); + + // Allocate a new stencil for dragging around + m_pDragStencil = pSpawner->newStencil(); + m_pDragStencil->setPosition( qp.x(), qp.y() ); + + // Invalidate the rectangle + oldRectValid = true; + + // Create a new painter object + beginUnclippedSpawnerPainter(); + + // Translate the painter so that 0,0 means where the page starts on the canvas + unclippedSpawnerPainter->painter()->save(); + unclippedSpawnerPainter->painter()->translate(-m_iXOffset + m_pageOffsetX, -m_iYOffset + m_pageOffsetY); + + // Assign the painter object to the intra-stencil data object, as well + // as the zoom factor + m_dragStencilData.painter = unclippedSpawnerPainter; + m_dragStencilData.zoomHandler = m_pView->zoomHandler(); + + // Draw the outline of the stencil + m_pDragStencil->paintOutline( &m_dragStencilData ); + + unclippedSpawnerPainter->painter()->restore(); +} + +/** + * Undraws the old stencil outline, draws the new one + */ +void KivioCanvas::continueSpawnerDragDraw( const QPoint &p ) +{ + bool snappedX, snappedY; + + // Translate the painter so that 0,0 means where the page starts on the canvas + unclippedSpawnerPainter->painter()->save(); + unclippedSpawnerPainter->painter()->translate(-m_iXOffset + m_pageOffsetX, -m_iYOffset + m_pageOffsetY); + + // Undraw the old outline + if( oldRectValid ) + { + m_pDragStencil->paintOutline( &m_dragStencilData ); + } + + // Map the new point from screenspace to page space + KoPoint orig = mapFromScreen(p); + KoPoint qp = snapToGrid( orig ); + + // First snap to screen + qp = snapToGrid(qp); + m_pDragStencil->setPosition( qp.x(), qp.y() ); + + // Now snap to the guides + qp.setCoords(orig.x() + m_pDragStencil->w(), orig.y() + m_pDragStencil->h()); + qp = snapToGuides(qp, snappedX, snappedY); + + if(snappedX) { + m_pDragStencil->setX(qp.x() - m_pDragStencil->w()); + } + + if(snappedY) { + m_pDragStencil->setY(qp.y() - m_pDragStencil->h()); + } + + qp.setCoords(orig.x() + (m_pDragStencil->w() / 2.0), orig.y() + (m_pDragStencil->h() / 2.0)); + qp = snapToGuides(qp, snappedX, snappedY); + + if(snappedX) { + m_pDragStencil->setX(qp.x() - (m_pDragStencil->w() / 2.0)); + } + + if(snappedY) { + m_pDragStencil->setY(qp.y() - (m_pDragStencil->h() / 2.0)); + } + + qp.setCoords(orig.x(), orig.y()); + qp = snapToGuides(qp, snappedX, snappedY); + + if(snappedX) { + m_pDragStencil->setX(qp.x()); + } + + if(snappedY) { + m_pDragStencil->setY(qp.y()); + } + + // Redraw the new outline + oldRectValid = true; + m_pDragStencil->paintOutline( &m_dragStencilData ); + unclippedSpawnerPainter->painter()->restore(); + +} + + +/** + * Ends the ability to draw a drag & drop spawner object + */ +void KivioCanvas::endSpawnerDragDraw() +{ + // Avoid the noid + if ( !unclippedSpawnerPainter ) + return; + + // If we have a valid old drawing spot, undraw it + if ( oldRectValid ) + { + unclippedSpawnerPainter->painter()->save(); + unclippedSpawnerPainter->painter()->translate(-m_iXOffset + m_pageOffsetX, -m_iYOffset + m_pageOffsetY); + m_pDragStencil->paintOutline( &m_dragStencilData ); + unclippedSpawnerPainter->painter()->restore(); + } + + // Smack the painter around a bit + endUnclippedSpawnerPainter(); + + // If we have a stencil we were dragging around, delete it. + if( m_pDragStencil ) + { + delete m_pDragStencil; + m_pDragStencil = 0L; + } + + setFocus(); +} + + +/** + * Creates a new spawner drawing object + */ +void KivioCanvas::beginUnclippedSpawnerPainter() +{ + // End any previous attempts + endUnclippedSpawnerPainter(); + + // I have no idea what this does. Max? + bool unclipped = testWFlags( WPaintUnclipped ); + setWFlags( WPaintUnclipped ); + + + // Allocate a new painter object for use in drawing + unclippedSpawnerPainter = new KivioScreenPainter(); + + // Tell it to start (allocates a Qpainter object) + unclippedSpawnerPainter->start(this); + + // Uhhhhh?? + if( !unclipped ) + clearWFlags( WPaintUnclipped ); + + + // Make sure it's doing NOT drawing. + unclippedSpawnerPainter->painter()->setRasterOp( NotROP ); + unclippedSpawnerPainter->painter()->setPen( QColor(0,0,250) ); + +} + + +/** + * Deletes the current spawner drawing object + */ +void KivioCanvas::endUnclippedSpawnerPainter() +{ + if( unclippedSpawnerPainter ) + { + unclippedSpawnerPainter->stop(); + delete unclippedSpawnerPainter; + unclippedSpawnerPainter = 0L; + } +} + +void KivioCanvas::beginUnclippedPainter() +{ + endUnclippedPainter(); + bool unclipped = testWFlags( WPaintUnclipped ); + + setWFlags( WPaintUnclipped ); + unclippedPainter = new QPainter; + unclippedPainter->begin( this ); + + if ( !unclipped ) + clearWFlags( WPaintUnclipped ); + + unclippedPainter->setRasterOp( NotROP ); + unclippedPainter->setPen( QPen(blue,1,DotLine) ); +} + +void KivioCanvas::endUnclippedPainter() +{ + if ( unclippedPainter ) + { + unclippedPainter->end(); + delete unclippedPainter; + unclippedPainter = 0; + } +} + +void KivioCanvas::borderTimerTimeout() +{ + QPoint p = mapFromGlobal(QCursor::pos()); + int dx = 0; + int dy = 0; + int d = 10; + + QRect r(currRect); + int vpos = m_pVertScrollBar->value(); + int vmax = m_pVertScrollBar->maxValue(); + int vmin = m_pVertScrollBar->minValue(); + + int hpos = m_pHorzScrollBar->value(); + int hmax = m_pHorzScrollBar->maxValue(); + int hmin = m_pHorzScrollBar->minValue(); + + if ( p.x() < 0 && hpos > hmin ) { + dx = QMIN(d,hpos-hmin); + r.setRight(r.right()+dx); + rectAnchor.setX(rectAnchor.x()+dx); + } + + if ( p.y() < 0 && vpos > vmin ) { + dy = QMIN(d,vpos-vmin); + r.setBottom(r.bottom()+dy); + rectAnchor.setY(rectAnchor.y()+dy); + } + + if ( p.x() > width() && hpos < hmax ) { + dx = -QMIN(d,hmax-hpos); + r.setLeft(r.left()+dx); + rectAnchor.setX(rectAnchor.x()+dx); + } + + if ( p.y() > height() && vpos < vmax ) { + dy = -QMIN(d,vmax-vpos); + r.setTop(r.top()+dy); + rectAnchor.setY(rectAnchor.y()+dy); + } + + if ( dx != 0 || dy != 0 ) { + unclippedPainter->drawRect( currRect ); + scrollDx(dx); + scrollDy(dy); + unclippedPainter->drawRect( r ); + currRect = r; + } +} + + +/** + * Handles the initial drag event + * + * @param e The event + * + * This will check to make sure the drag object is of the correct mimetype. + * If it is, it accepts it, and the calls startSpawnerDragDraw which will + * allocate a new drawing object and set some class variables for future + * drawing. + */ +void KivioCanvas::dragEnterEvent( QDragEnterEvent *e ) +{ + if( e->provides("kivio/stencilSpawner") ) + { + e->accept(); + startSpawnerDragDraw( e->pos() ); + activePage()->unselectAllStencils(); + updateAutoGuideLines(); + } +} + + + +/** + * Handles drag-move events + * + * @param e The event + * + * This makes sure the drag object is of type kivio/stencilSpawner since these + * are currently the only type of mime-types accepted. If so, it accepts the + * event, and then tells the drawing object to update itself with a new position. + */ +void KivioCanvas::dragMoveEvent( QDragMoveEvent *e ) +{ + // Does it speak our language? + if( e->provides("kivio/stencilSpawner") ) + { + e->accept(); + continueSpawnerDragDraw( e->pos() ); + } +} + + +/** + * Handles drops for this object + * + * @param e The drop event object + * + * This function takes care of handling the final drop event of this object. It will + * allocate a new object of the currently dragged Spawner type (stencil), and add it + * to the active page of the document (which actually adds it to the active layer + * of the active page). + */ +void KivioCanvas::dropEvent( QDropEvent *e ) +{ + // Terminate the drawing object + endSpawnerDragDraw(); + + // Get a pointer to the currently dragged KivioStencilSpawner object + KivioStencilSpawner *pSpawner = KivioIconView::curDragSpawner(); + + if( !pSpawner ) + return; + + QPoint pos = e->pos(); + KoPoint pagePoint = snapToGrid(mapFromScreen( pos )); + view()->addStencilFromSpawner(pSpawner, pagePoint.x(), pagePoint.y()); + + // FIXME Select the "selection tool" in case it's not done +} + + +/** + * Handles when a drag leaves this object + * + * @param e The event object + * + * This will call endSpawnerDragDraw() which terminates the drawing + * object and ends interaction with the drag. + */ +void KivioCanvas::dragLeaveEvent( QDragLeaveEvent * ) +{ + endSpawnerDragDraw(); +} + + + +void KivioCanvas::drawSelectedStencilsXOR() +{ + // This should never happen, but check just in case + if ( !unclippedSpawnerPainter ) + return; + + // Translate the painter so that 0,0 means where the page starts on the canvas + unclippedSpawnerPainter->painter()->save(); + unclippedSpawnerPainter->painter()->translate(-m_iXOffset + m_pageOffsetX, -m_iYOffset + m_pageOffsetY); + + // Assign the painter object to the intra-stencil data object, as well + // as the zoom factor + m_dragStencilData.painter = unclippedSpawnerPainter; + m_dragStencilData.zoomHandler = m_pView->zoomHandler(); + + KivioStencil *pStencil = activePage()->selectedStencils()->first(); + while( pStencil ) + { + pStencil->paintOutline( &m_dragStencilData ); + pStencil->paintSelectionHandles( &m_dragStencilData ); + + pStencil = activePage()->selectedStencils()->next(); + } + + unclippedSpawnerPainter->painter()->restore(); +} + +void KivioCanvas::drawStencilXOR( KivioStencil *pStencil ) +{ + // This should never happen, but check just in case + if ( !unclippedSpawnerPainter ) + return; + + // Translate the painter so that 0,0 means where the page starts on the canvas + unclippedSpawnerPainter->painter()->save(); + unclippedSpawnerPainter->painter()->translate(-m_iXOffset + m_pageOffsetX, -m_iYOffset + m_pageOffsetY); + + // Assign the painter object to the intra-stencil data object, as well + // as the zoom factor + m_dragStencilData.painter = unclippedSpawnerPainter; + m_dragStencilData.zoomHandler = m_pView->zoomHandler(); + + pStencil->paintOutline( &m_dragStencilData ); + pStencil->paintSelectionHandles( &m_dragStencilData ); + + unclippedSpawnerPainter->painter()->restore(); +} + +void KivioCanvas::keyPressEvent( QKeyEvent *e ) +{ + if(view()->isShowGuides() && m_guides.keyPressEvent(e)) { + return; + } +} + +KoPoint KivioCanvas::snapToGridAndGuides(const KoPoint& point) +{ + KoPoint p = point; + + p = snapToGrid(p); + + bool snappedX, snappedY; + KoPoint guidePoint = snapToGuides(point, snappedX, snappedY); + + if(snappedX) { + p.setX(guidePoint.x()); + } + + if(snappedY) { + p.setY(guidePoint.y()); + } + + return p; +} + +KoPoint KivioCanvas::snapToGrid(const KoPoint& point) +{ + if (!m_pDoc->grid().isSnap) + return point; + + KoPoint p = point; + + KoSize dist = m_pDoc->grid().snap; + KoSize freq = m_pDoc->grid().freq; + + double dx = qRound(p.x() / freq.width()); + double dy = qRound(p.y() / freq.height()); + + double distx = QABS(p.x() - (freq.width() * dx)); + double disty = QABS(p.y() - (freq.height() * dy)); + + if(distx < dist.width()) { + p.setX(freq.width() * dx); + } + + if(disty < dist.height()) { + p.setY(freq.height() * dy); + } + + return p; +} + +KoPoint KivioCanvas::snapToGuides(const KoPoint& point, bool &snappedX, bool &snappedY) +{ + snappedX = false; + snappedY = false; + KoPoint p = point; + + if (m_pView->isSnapGuides()) + { + KoGuides::SnapStatus status = KoGuides::SNAP_NONE; + KoPoint diff; + m_guides.snapToGuideLines(p, 4, status, diff); + p += diff; + + if(status & KoGuides::SNAP_HORIZ) { + snappedY = true; + } + if(status & KoGuides::SNAP_VERT) { + snappedX = true; + } + + m_guides.repaintSnapping(p, status); + } + + return p; +} + +void KivioCanvas::setViewCenterPoint(const KoPoint &p) +{ + setUpdatesEnabled(false); + + KoRect va = visibleArea(); + + double x = QMAX(0.0, p.x() - (va.width() / 2.0)); + double y = QMAX(0.0, p.y() - (va.height() / 2.0)); + + m_pVertScrollBar->setValue(m_pView->zoomHandler()->zoomItY(y)); + m_pHorzScrollBar->setValue(m_pView->zoomHandler()->zoomItX(x)); + + setUpdatesEnabled(true); +} + +KoRect KivioCanvas::visibleArea() +{ + KoPoint p0 = mapFromScreen(QPoint(0,0)); + KoPoint p1 = mapFromScreen(QPoint(width()-1,height()-1)); + + return KoRect(p0.x(), p0.y(), p1.x() - p0.x(), p1.y() - p0.y()); +} + +void KivioCanvas::setVisibleArea(KoRect r, int margin) +{ + setUpdatesEnabled(false); + KoZoomHandler zoom; + zoom.setZoomAndResolution(100, KoGlobal::dpiX(), + KoGlobal::dpiY()); + + float cw = width() - 2 * margin; + float ch = height() - 2 * margin; + + float zw = cw / (float)zoom.zoomItX(r.width()); + float zh = ch / (float)zoom.zoomItY(r.height()); + float z = QMIN(zw, zh); + + m_pView->viewZoom(qRound(z * 100)); + + KoPoint c = r.center(); + + setViewCenterPoint(KoPoint(c.x(), c.y())); + setUpdatesEnabled(true); +} + +void KivioCanvas::setVisibleAreaByWidth(KoRect r, int margin) +{ + setUpdatesEnabled(false); + KoZoomHandler zoom; + zoom.setZoomAndResolution(100, KoGlobal::dpiX(), + KoGlobal::dpiY()); + + float cw = width() - 2*margin; + float z = cw / (float)zoom.zoomItX(r.width()); + + m_pView->viewZoom(qRound(z * 100)); + + KoPoint c = r.center(); + + setViewCenterPoint(KoPoint(c.x(), c.y())); + setUpdatesEnabled(true); +} + +void KivioCanvas::setVisibleAreaByHeight(KoRect r, int margin) +{ + setUpdatesEnabled(false); + KoZoomHandler zoom; + zoom.setZoomAndResolution(100, KoGlobal::dpiX(), + KoGlobal::dpiY()); + + float ch = height() - 2*margin; + float z = ch / (float)zoom.zoomItY(r.height()); + + m_pView->viewZoom(qRound(z * 100)); + + KoPoint c = r.center(); + + setViewCenterPoint(KoPoint(c.x(), c.y())); + setUpdatesEnabled(true); +} + +void KivioCanvas::startPasteMoving() +{ + setEnabled(false); + KoPoint p = activePage()->getRectForAllSelectedStencils().center(); + m_origPoint.setCoords(p.x(), p.y()); + + // Create a new painter object + beginUnclippedSpawnerPainter(); + drawSelectedStencilsXOR(); + + // Build the list of old geometry + KoRect *pData; + m_lstOldGeometry.clear(); + KivioStencil* pStencil = activePage()->selectedStencils()->first(); + + while( pStencil ) + { + pData = new KoRect; + *pData = pStencil->rect(); + m_lstOldGeometry.append(pData); + + pStencil = activePage()->selectedStencils()->next(); + } + + continuePasteMoving(lastPoint); + m_pasteMoving = true; + setEnabled(true); +} + +void KivioCanvas::continuePasteMoving(const QPoint &pos) +{ + KoPoint pagePoint = mapFromScreen( pos ); + + double dx = pagePoint.x() - m_origPoint.x(); + double dy = pagePoint.y() - m_origPoint.y(); + + bool snappedX; + bool snappedY; + + double newX, newY; + + // Undraw the old stencils + drawSelectedStencilsXOR(); + + // Translate to the new position + KoPoint p; + KoRect selectedRect = activePage()->getRectForAllSelectedStencils(); + + newX = selectedRect.x() + dx; + newY = selectedRect.y() + dy; + + // First attempt a snap-to-grid + p.setCoords(newX, newY); + p = snapToGrid(p); + + newX = p.x(); + newY = p.y(); + + // Now the guides override the grid so we attempt to snap to them + p.setCoords(selectedRect.x() + dx + selectedRect.width(), selectedRect.y() + dy + selectedRect.height()); + p = snapToGuides(p, snappedX, snappedY); + + if(snappedX) { + newX = p.x() - selectedRect.width(); + } + + if(snappedY) { + newY = p.y() - selectedRect.height(); + } + + p.setCoords(selectedRect.x() + dx + (selectedRect.width() / 2.0), selectedRect.y() + dy + (selectedRect.height() / 2.0)); + p = snapToGuides(p, snappedX, snappedY); + + if(snappedX) { + newX = p.x() - (selectedRect.width() / 2.0); + } + + if(snappedY) { + newY = p.y() - (selectedRect.height() / 2.0); + } + + p.setCoords(selectedRect.x() + dx, selectedRect.y() + dy); + p = snapToGuides(p, snappedX, snappedY); + + if(snappedX) { + newX = p.x(); + } + + if(snappedY) { + newY = p.y(); + } + + dx = newX - selectedRect.x(); + dy = newY - selectedRect.y(); + + // Translate to the new position + KivioStencil *pStencil = activePage()->selectedStencils()->first(); + KoRect* pData = m_lstOldGeometry.first(); + // bool move = true; + + while( pStencil && pData ) + { + newX = pData->x() + dx; + newY = pData->y() + dy; + + if( pStencil->protection()->at( kpX ) == false ) { + pStencil->setX(newX); + } + if( pStencil->protection()->at( kpY ) == false ) { + pStencil->setY(newY); + } + + pData = m_lstOldGeometry.next(); + pStencil = activePage()->selectedStencils()->next(); + } + + // Draw the stencils + drawSelectedStencilsXOR(); + m_pView->updateToolBars(); +} + +void KivioCanvas::endPasteMoving() +{ + KivioStencil *pStencil = activePage()->selectedStencils()->first(); + KoRect *pData = m_lstOldGeometry.first(); + + while( pStencil && pData ) + { + if(pStencil->type() == kstConnector) { + pStencil->searchForConnections(m_pView->activePage(), m_pView->zoomHandler()->unzoomItY(4)); + } + + pData = m_lstOldGeometry.next(); + pStencil = activePage()->selectedStencils()->next(); + } + + drawSelectedStencilsXOR(); + + endUnclippedSpawnerPainter(); + + // Clear the list of old geometry + m_lstOldGeometry.clear(); + m_pasteMoving = false; +} + +void KivioCanvas::updateAutoGuideLines() +{ + QValueList<double> hGuideLines; + QValueList<double> vGuideLines; + QPtrList<KivioLayer> layerList = *(activePage()->layers()); + QPtrListIterator<KivioLayer> layerIt(layerList); + KivioLayer* layer = 0; + QPtrList<KivioStencil> stencilList; + QPtrListIterator<KivioStencil> stencilIt(stencilList); + KivioStencil* stencil = 0; + + while((layer = layerIt.current()) != 0) { + ++layerIt; + + if(layer->visible()) { + stencilList = *(layer->stencilList()); + stencilIt.toFirst(); + + while((stencil = stencilIt.current()) != 0) { + ++stencilIt; + + if(!stencil->isSelected()) { + hGuideLines << stencil->y() << (stencil->y() + (stencil->h() / 2.0)) << (stencil->y() + stencil->h()); + vGuideLines << stencil->x() << (stencil->x() + (stencil->w() / 2.0)) << (stencil->x() + stencil->w()); + } + } + } + } + + KoPageLayout pl = activePage()->paperLayout(); + + // Add the middle of the page and the margins + hGuideLines << (pl.ptHeight / 2.0) << pl.ptTop << pl.ptBottom; + vGuideLines << (pl.ptWidth / 2.0) << pl.ptLeft << pl.ptRight; + + guideLines().setAutoGuideLines(hGuideLines, vGuideLines); +} + +#include "kivio_canvas.moc" |