lib

KoContainerHandler.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999, 2000 Torben Weis <weis@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "KoContainerHandler.h"
00021 #include <KoView.h>
00022 #include <math.h>
00023 #include <kcursor.h>
00024 #include <kdebug.h>
00025 
00026 KoEventHandler::KoEventHandler( QObject* target )
00027 {
00028     m_target = target;
00029 
00030     m_target->installEventFilter( this );
00031 }
00032 
00033 KoEventHandler::~KoEventHandler()
00034 {
00035 }
00036 
00037 QObject* KoEventHandler::target()
00038 {
00039     return m_target;
00040 }
00041 
00042 // ------------------------------------------------------
00043 
00044 class KoPartResizeHandlerPrivate {
00045 public:
00046     KoPartResizeHandlerPrivate( const QWMatrix& matrix, KoView *view, KoChild* child,
00047                               KoChild::Gadget gadget, const QPoint& point ) :
00048         m_gadget(gadget), m_view(view), m_child(child), m_parentMatrix(matrix) {
00049 
00050         m_geometryStart = child->geometry();
00051         m_matrix = child->matrix() * matrix;
00052         m_invertParentMatrix = matrix.invert();
00053 
00054         bool ok = true;
00055         m_invert = m_matrix.invert( &ok );
00056         Q_ASSERT( ok );
00057         m_mouseStart = m_invert.map( m_invertParentMatrix.map( point ) );
00058     }
00059     ~KoPartResizeHandlerPrivate() {}
00060 
00061     KoChild::Gadget m_gadget;
00062     QPoint m_mouseStart;
00063     QRect m_geometryStart;
00064     KoView* m_view;
00065     KoChild* m_child;
00066     QWMatrix m_invert;
00067     QWMatrix m_matrix;
00068     QWMatrix m_parentMatrix;
00069     QWMatrix m_invertParentMatrix;
00070 };
00071 
00072 KoPartResizeHandler::KoPartResizeHandler( QWidget* widget, const QWMatrix& matrix, KoView* view, KoChild* child,
00073                                       KoChild::Gadget gadget, const QPoint& point )
00074     : KoEventHandler( widget )
00075 {
00076     child->lock();
00077     d=new KoPartResizeHandlerPrivate(matrix, view, child, gadget, point);
00078 }
00079 
00080 KoPartResizeHandler::~KoPartResizeHandler()
00081 {
00082     d->m_child->unlock();
00083     delete d;
00084     d=0L;
00085 }
00086 
00087 void KoPartResizeHandler::repaint(QRegion &rgn)
00088 {
00089   rgn = rgn.unite( d->m_child->frameRegion( d->m_parentMatrix, true ) );
00090  // rgn.translate(- d->m_view->canvasXOffset(), - d->m_view->canvasYOffset());
00091   ((QWidget*)target())->repaint( rgn );
00092 }
00093 
00094 bool KoPartResizeHandler::eventFilter( QObject*, QEvent* ev )
00095 {
00096     if ( ev->type() == QEvent::MouseButtonRelease )
00097     {
00098         delete this;
00099         return true;
00100     }
00101     else if ( ev->type() == QEvent::MouseMove )
00102     {
00103         QMouseEvent* e = (QMouseEvent*)ev;
00104         QPoint p = d->m_invert.map( d->m_invertParentMatrix.map( e->pos() /*+ QPoint(d->m_view->canvasXOffset(), d->m_view->canvasYOffset()) */ ) );
00105         QRegion rgn( d->m_child->frameRegion( d->m_parentMatrix, true ) );
00106 
00107         double x1_x, x1_y, x2_x, x2_y;
00108         d->m_matrix.map( double( p.x() ), 0.0, &x1_x, &x1_y );
00109         d->m_matrix.map( double( d->m_mouseStart.x() ), 0.0, &x2_x, &x2_y );
00110         double y1_x, y1_y, y2_x, y2_y;
00111         d->m_matrix.map( 0.0, double( p.y() ), &y1_x, &y1_y );
00112         d->m_matrix.map( 0.0, double( d->m_mouseStart.y() ), &y2_x, &y2_y );
00113 
00114         double dx = x2_x - x1_x;
00115         double dy = x2_y - x1_y;
00116         int x = int( sqrt( dx * dx + dy * dy ) * ( d->m_mouseStart.x() < p.x() ? 1.0 : -1.0 ) );
00117 
00118         dx = y2_x - y1_x;
00119         dy = y2_y - y1_y;
00120         int y = int( sqrt( dx * dx + dy * dy ) * ( d->m_mouseStart.y() < p.y() ? 1.0 : -1.0 ) );
00121 
00122         switch( d->m_gadget )
00123         {
00124         case KoChild::TopLeft:
00125             {
00126                 x = QMIN( d->m_geometryStart.width() - 1, x );
00127                 y = QMIN( d->m_geometryStart.height() - 1, y );
00128 
00129                 d->m_child->setGeometry( QRect( d->m_geometryStart.x() + x, d->m_geometryStart.y() + y,
00130                                              d->m_geometryStart.width() - x, d->m_geometryStart.height() - y ) );
00131                 repaint(rgn);
00132             }
00133             break;
00134         case KoChild::TopMid:
00135             {
00136                 y = QMIN( d->m_geometryStart.height() - 1, y );
00137 
00138                 d->m_child->setGeometry( QRect( d->m_geometryStart.x(), d->m_geometryStart.y() + y,
00139                                              d->m_geometryStart.width(), d->m_geometryStart.height() - y ) );
00140                 repaint(rgn);
00141             }
00142             break;
00143         case KoChild::TopRight:
00144             {
00145                 x = QMAX( -d->m_geometryStart.width() + 1, x );
00146                 y = QMIN( d->m_geometryStart.height() - 1, y );
00147 
00148                 d->m_child->setGeometry( QRect( d->m_geometryStart.x(), d->m_geometryStart.y() + y,
00149                                              d->m_geometryStart.width() + x, d->m_geometryStart.height() - y ) );
00150                 repaint(rgn);
00151             }
00152             break;
00153         case KoChild::MidLeft:
00154             {
00155                 x = QMIN( d->m_geometryStart.width() - 1, x );
00156 
00157                 d->m_child->setGeometry( QRect( d->m_geometryStart.x() + x, d->m_geometryStart.y(),
00158                                              d->m_geometryStart.width() - x, d->m_geometryStart.height() ) );
00159                 repaint(rgn);
00160             }
00161             break;
00162         case KoChild::MidRight:
00163             {
00164                 x = QMAX( -d->m_geometryStart.width() + 1, x );
00165 
00166                 d->m_child->setGeometry( QRect( d->m_geometryStart.x(), d->m_geometryStart.y(),
00167                                              d->m_geometryStart.width() + x, d->m_geometryStart.height() ) );
00168                 repaint(rgn);
00169             }
00170             break;
00171         case KoChild::BottomLeft:
00172             {
00173                 x = QMIN( d->m_geometryStart.width() - 1, x );
00174                 y = QMAX( -d->m_geometryStart.height() + 1, y );
00175 
00176                 d->m_child->setGeometry( QRect( d->m_geometryStart.x() + x, d->m_geometryStart.y(),
00177                                              d->m_geometryStart.width() - x, d->m_geometryStart.height() + y ) );
00178                 repaint(rgn);
00179             }
00180             break;
00181         case KoChild::BottomMid:
00182             {
00183                 y = QMAX( -d->m_geometryStart.height() + 1, y );
00184 
00185                 d->m_child->setGeometry( QRect( d->m_geometryStart.x(), d->m_geometryStart.y(),
00186                                              d->m_geometryStart.width(), d->m_geometryStart.height() + y ) );
00187                 repaint(rgn);
00188             }
00189             break;
00190         case KoChild::BottomRight:
00191             {
00192                 x = QMAX( -d->m_geometryStart.width() + 1, x );
00193                 y = QMAX( -d->m_geometryStart.height() + 1, y );
00194 
00195                 d->m_child->setGeometry( QRect( d->m_geometryStart.x(), d->m_geometryStart.y(),
00196                                              d->m_geometryStart.width() + x, d->m_geometryStart.height() + y ) );
00197                 repaint(rgn);
00198             }
00199             break;
00200         default:
00201             Q_ASSERT( 0 );
00202         }
00203         return true;
00204     }
00205     return false;
00206 }
00207 
00208 // --------------------------------------------------------------
00209 
00210 class KoPartMoveHandlerPrivate {
00211 public:
00212     KoPartMoveHandlerPrivate( const QWMatrix& matrix, KoView* view, KoChild* child,
00213                             const QPoint& point) : m_view(view), m_dragChild(child),
00214                                                    m_parentMatrix(matrix) {
00215         m_invertParentMatrix = matrix.invert();
00216         m_mouseDragStart = m_invertParentMatrix.map( point );
00217         m_geometryDragStart = m_dragChild->geometry();
00218         m_rotationDragStart = m_dragChild->rotationPoint();
00219     }
00220     ~KoPartMoveHandlerPrivate() {}
00221 
00222     KoView* m_view;
00223     KoChild* m_dragChild;
00224     QPoint m_mouseDragStart;
00225     QRect m_geometryDragStart;
00226     QPoint m_rotationDragStart;
00227     QWMatrix m_invertParentMatrix;
00228     QWMatrix m_parentMatrix;
00229 };
00230 
00231 KoPartMoveHandler::KoPartMoveHandler( QWidget* widget, const QWMatrix& matrix, KoView* view, KoChild* child,
00232                                   const QPoint& point )
00233     : KoEventHandler( widget )
00234 {
00235     child->lock();
00236     d=new KoPartMoveHandlerPrivate(matrix, view, child, point);
00237 }
00238 
00239 KoPartMoveHandler::~KoPartMoveHandler()
00240 {
00241     d->m_dragChild->unlock();
00242     delete d;
00243     d=0L;
00244 }
00245 
00246 bool KoPartMoveHandler::eventFilter( QObject*, QEvent* ev )
00247 {
00248     if ( ev->type() == QEvent::MouseButtonRelease )
00249     {
00250         delete this;
00251         return true;
00252     }
00253     else if ( ev->type() == QEvent::MouseMove )
00254     {
00255         QMouseEvent* e = (QMouseEvent*)ev;
00256 
00257         QRegion bound = d->m_dragChild->frameRegion( d->m_parentMatrix, true );
00258         QPoint pos = d->m_invertParentMatrix.map( e->pos() /* + QPoint(d->m_view->canvasXOffset(), d->m_view->canvasYOffset()) */ );
00259         d->m_dragChild->setGeometry( QRect( d->m_geometryDragStart.x() + pos.x() - d->m_mouseDragStart.x(),
00260                                              d->m_geometryDragStart.y() + pos.y() - d->m_mouseDragStart.y(),
00261                                              d->m_geometryDragStart.width(), d->m_geometryDragStart.height() ) );
00262         d->m_dragChild->setRotationPoint( QPoint( d->m_rotationDragStart.x() + pos.x() - d->m_mouseDragStart.x(),
00263                                                d->m_rotationDragStart.y() + pos.y() - d->m_mouseDragStart.y() ) );
00264         bound = bound.unite( d->m_dragChild->frameRegion( d->m_parentMatrix, false ) );
00265       //  bound.translate(- d->m_view->canvasXOffset(), - d->m_view->canvasYOffset());
00266         ((QWidget*)target())->repaint( bound );
00267 
00268         return true;
00269     }
00270 
00271     return false;
00272 }
00273 
00274 // -------------------------------------------------------
00275 
00276 KoContainerHandler::KoContainerHandler( KoView* view, QWidget* widget )
00277     : KoEventHandler( widget )
00278 {
00279     m_view = view;
00280 }
00281 
00282 KoContainerHandler::~KoContainerHandler()
00283 {
00284 }
00285 
00286 bool KoContainerHandler::eventFilter( QObject*, QEvent* ev )
00287 {
00288     if ( ev->type() == QEvent::KeyPress )
00289     {
00290     QKeyEvent* keyEvent=(QKeyEvent*)ev;
00291 
00292     KoChild* child=m_view->selectedChild();
00293 
00294     if (child != 0)
00295     {
00296         if (keyEvent->key()==Qt::Key_Delete)
00297             emit deleteChild(child);
00298     }
00299     }
00300 
00301     if ( ev->type() == QEvent::MouseButtonPress )
00302     {
00303         KoChild::Gadget gadget;
00304         QPoint pos;
00305         QMouseEvent *e=static_cast<QMouseEvent*>(ev);
00306         KoChild *ch=child(gadget, pos, e);
00307 
00308     if ( e->button() == RightButton && gadget != KoChild::NoGadget )
00309         {
00310         emit popupMenu( ch, e->globalPos() );
00311             return true;
00312         }
00313         else if ( e->button() == LeftButton && gadget == KoChild::Move )
00314         {
00315             (void)new KoPartMoveHandler( static_cast<QWidget*>(target()), m_view->matrix(), m_view, ch, pos );
00316             return true;
00317         }
00318         else if ( e->button() == LeftButton && gadget != KoChild::NoGadget )
00319         {
00320             (void)new KoPartResizeHandler( static_cast<QWidget*>(target()), m_view->matrix(), m_view, ch, gadget, pos );
00321             return true;
00322         }
00323         return false;
00324     }
00325     else if ( ev->type() == QEvent::MouseMove )
00326     {
00327         QWidget *targetWidget = static_cast<QWidget *>( target() );
00328         KoChild::Gadget gadget;
00329         QPoint pos;
00330         QMouseEvent *e=static_cast<QMouseEvent*>(ev);
00331         child(gadget, pos, e);
00332 
00333         bool retval = true;
00334         if ( gadget == KoChild::NoGadget )
00335             retval = false;
00336 
00337         if ( gadget == KoChild::TopLeft || gadget == KoChild::BottomRight )
00338             targetWidget->setCursor( sizeFDiagCursor );
00339         else if ( gadget == KoChild::TopRight || gadget == KoChild::BottomLeft )
00340             targetWidget->setCursor( sizeBDiagCursor );
00341         else if ( gadget == KoChild::TopMid || gadget == KoChild::BottomMid )
00342             targetWidget->setCursor( sizeVerCursor );
00343         else if ( gadget == KoChild::MidLeft || gadget == KoChild::MidRight )
00344             targetWidget->setCursor( sizeHorCursor );
00345         else if ( gadget == KoChild::Move )
00346             targetWidget->setCursor( KCursor::handCursor() );
00347         else
00348         {
00349 //            targetWidget->setCursor( arrowCursor );
00350             return false;
00351         }
00352         return retval;
00353     }
00354     return false;
00355 }
00356 
00357 KoChild *KoContainerHandler::child(KoChild::Gadget &gadget, QPoint &pos, const QMouseEvent *ev) {
00358 
00359     pos = ev->pos(); //+ QPoint(m_view->canvasXOffset(), m_view->canvasYOffset());
00360 
00361     pos = m_view->reverseViewTransformations( pos );
00362 
00363     KoChild *child = 0;
00364     KoDocumentChild* docChild = m_view->selectedChild();
00365     gadget = KoChild::NoGadget;
00366     if ( docChild )
00367     {
00368         KoViewChild *viewChild = m_view->child( docChild->document() );
00369 
00370         if ( viewChild )
00371             child = viewChild;
00372         else
00373             child = docChild;
00374 
00375         gadget = child->gadgetHitTest( pos );
00376     }
00377     if ( gadget == KoChild::NoGadget )
00378     {
00379         docChild = m_view->activeChild();
00380         if ( docChild )
00381         {
00382             KoViewChild *viewChild = m_view->child( docChild->document() );
00383 
00384             if ( viewChild )
00385                 child = viewChild;
00386             else
00387                 child = docChild;
00388 
00389             gadget = child->gadgetHitTest( pos );
00390         }
00391     }
00392     return child;
00393 }
00394 
00395 #include "KoContainerHandler.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys