karbon

vselectnodestool.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002, The Karbon Developers
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 <math.h>
00021 
00022 #include <qcursor.h>
00023 #include <qlabel.h>
00024 
00025 #include <klocale.h>
00026 #include <KoPoint.h>
00027 #include <KoRect.h>
00028 
00029 #include <karbon_part.h>
00030 #include <karbon_view.h>
00031 
00032 #include <render/vpainter.h>
00033 #include <render/vpainterfactory.h>
00034 #include <visitors/vselectnodes.h>
00035 #include <commands/vtransformcmd.h>
00036 #include <visitors/vdrawselection.h>
00037 #include <core/vselection.h>
00038 #include <core/vcursor.h>
00039 #include "vselectnodestool.h"
00040 #include <vtransformnodes.h>
00041 #include <commands/vdeletenodescmd.h>
00042 #include <widgets/vcanvas.h>
00043 
00044 #include <kdebug.h>
00045 
00046 VSelectNodesTool::VSelectNodesTool( KarbonView* view )
00047     : VTool( view, "tool_select_nodes" ), m_state( normal ), m_select( true )
00048 {
00049     registerTool( this );
00050 }
00051 
00052 VSelectNodesTool::~VSelectNodesTool()
00053 {
00054 }
00055 
00056 void
00057 VSelectNodesTool::activate()
00058 {
00059     if( view() )
00060     {
00061         view()->setCursor( VCursor::needleArrow() );
00062         view()->part()->document().selection()->showHandle( false );
00063         view()->part()->document().selection()->setSelectObjects( false );
00064         // deselect all nodes
00065         view()->part()->document().selection()->selectNodes( false );
00066         view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00067     }
00068     VTool::activate();
00069 }
00070 
00071 QString
00072 VSelectNodesTool::statusText()
00073 {
00074     if( m_state == normal )
00075         return i18n( "Editing Nodes" );
00076     else
00077         return QString( "" );
00078 }
00079 
00080 void
00081 VSelectNodesTool::draw()
00082 {
00083     VPainter *painter = view()->painterFactory()->editpainter();
00084     painter->setZoomFactor( view()->zoom() );
00085     painter->setRasterOp( Qt::NotROP );
00086 
00087     VSelection* selection = view()->part()->document().selection();
00088 
00089     KoRect selrect = calcSelRect( last() ); 
00090 
00091     QPtrList<VSegment> segments = selection->getSegments( selrect );
00092     if( selection->objects().count() > 0 &&
00093         m_state != dragging && ( m_state >= moving || segments.count() > 0 ) )
00094     {
00095         if( m_state == normal )
00096         {
00097             if( segments.count() == 1 && !selrect.contains( segments.at( 0 )->knot() ) )
00098             {
00099                 if( selrect.contains( segments.at( 0 )->point( 1 ) ) )
00100 //                  segments.at( 0 )->prev()->type() != VSegment::curve )
00101                 {
00102                     m_state = movingbezier1;
00103                     segments.at( 0 )->selectPoint( 1, false );
00104                 }
00105                 else
00106                 {
00107                     m_state = movingbezier2;
00108                     segments.at( 0 )->selectPoint( 0, false );
00109                 }
00110                 selection->append( selrect.normalize(), false, true );
00111             }
00112             else
00113             {
00114                 m_state = moving;
00115                 selection->append( selrect.normalize(), false, false );
00116             }
00117 
00118             recalc();
00119         }
00120 
00121         VDrawSelection op( m_objects, painter, true, selection->handleSize() );
00122         VObjectListIterator itr = m_objects;
00123         for( ; itr.current(); ++itr )
00124             op.visit( *( itr.current() ) );
00125     }
00126     else
00127     {
00128         painter->setPen( Qt::DotLine );
00129         painter->newPath();
00130         painter->moveTo( KoPoint( first().x(), first().y() ) );
00131         painter->lineTo( KoPoint( m_current.x(), first().y() ) );
00132         painter->lineTo( KoPoint( m_current.x(), m_current.y() ) );
00133         painter->lineTo( KoPoint( first().x(), m_current.y() ) );
00134         painter->lineTo( KoPoint( first().x(), first().y() ) );
00135         painter->strokePath();
00136 
00137         m_state = dragging;
00138     }
00139 }
00140 
00141 void
00142 VSelectNodesTool::setCursor() const
00143 {
00144     if( m_state == moving ) return;
00145 
00146     KoRect selrect = calcSelRect( last() );
00147 
00148     QPtrList<VSegment> segments = view()->part()->document().selection()->getSegments( selrect );
00149     if( segments.count() > 0 &&
00150         ( segments.at( 0 )->knotIsSelected() ||
00151           segments.at( 0 )->pointIsSelected( 0 ) ||
00152           segments.at( 0 )->pointIsSelected( 1 ) ||
00153           selrect.contains( segments.at( 0 )->knot() ) ) )
00154     {
00155         view()->setCursor( VCursor::needleMoveArrow() );
00156     }
00157     else
00158         view()->setCursor( VCursor::needleArrow() );
00159 }
00160 
00161 void
00162 VSelectNodesTool::mouseButtonPress()
00163 {
00164     m_current = first();
00165 
00166     m_state = normal;
00167     m_select = true;
00168 
00169     recalc();
00170 
00171     view()->part()->document().selection()->setState( VObject::edit );
00172     view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00173     view()->part()->document().selection()->setState( VObject::selected );
00174 
00175     draw();
00176 }
00177 
00178 void 
00179 VSelectNodesTool::rightMouseButtonPress()
00180 {
00181     m_current = first();
00182 
00183     m_state = normal;
00184     m_select = false;
00185 
00186     recalc();
00187 
00188     view()->part()->document().selection()->setState( VObject::edit );
00189     view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00190     view()->part()->document().selection()->setState( VObject::selected );
00191 
00192     draw();
00193 }
00194 
00195 bool
00196 VSelectNodesTool::keyReleased( Qt::Key key )
00197 {
00198     
00199     VSelection* selection = view()->part()->document().selection();
00200 
00201     switch( key )
00202     {
00203         // increase/decrease the handle size
00204         case Qt::Key_I:
00205         {
00206             uint handleSize = selection->handleSize();
00207             if( shiftPressed() ) 
00208                 selection->setHandleSize( ++handleSize );
00209             else if( handleSize > 1 )
00210                 selection->setHandleSize( --handleSize );
00211         }
00212         break;
00213         case Qt::Key_Delete:
00214             if( selection->objects().count() > 0 )
00215                 view()->part()->addCommand( new VDeleteNodeCmd( &view()->part()->document() ), true );
00216         break;
00217         default: return false;
00218     }
00219 
00220     if( view() )
00221         view()->repaintAll( selection->boundingBox() );
00222 
00223     return true;
00224 }
00225 
00226 void
00227 VSelectNodesTool::mouseButtonRelease()
00228 {
00229     // erase old object:
00230     draw();
00231 
00232     VSelection* selection = view()->part()->document().selection();
00233 
00234     KoRect selrect = calcSelRect( last() );
00235 
00236     if( ctrlPressed() )
00237         selection->append( selrect.normalize(), false, false );
00238     else
00239         selection->append( selrect.normalize(), false, true );
00240 
00241     view()->selectionChanged();
00242     view()->part()->repaintAllViews();
00243     m_state = normal;
00244 }
00245 
00246 void 
00247 VSelectNodesTool::rightMouseButtonRelease()
00248 {
00249     // erase old object:
00250     draw();
00251 
00252     VSelection* selection = view()->part()->document().selection();
00253 
00254     KoRect selrect = calcSelRect( last() );
00255 
00256     selection->take( selrect.normalize(), false, false );
00257 
00258     view()->selectionChanged();
00259     view()->part()->repaintAllViews();
00260     m_state = normal;
00261 }
00262 
00263 void
00264 VSelectNodesTool::mouseDrag()
00265 {
00266     draw();
00267 
00268     recalc();
00269 
00270     draw();
00271 }
00272 
00273 void
00274 VSelectNodesTool::mouseDragRelease()
00275 {
00276     if( m_state >= moving )
00277     {
00278         view()->part()->document().selection()->setState( VObject::selected );
00279         VCommand *cmd;
00280         QPtrList<VSegment> segments;
00281         if( m_state == movingbezier1 || m_state == movingbezier2 )
00282         {
00283             KoRect selrect = calcSelRect( first() );
00284             segments = view()->part()->document().selection()->getSegments( selrect );
00285             cmd = new VTranslateBezierCmd( &view()->part()->document(), segments.at( 0 ),
00286                     qRound( ( last().x() - first().x() ) ),
00287                     qRound( ( last().y() - first().y() ) ),
00288                     m_state == movingbezier2 );
00289         }
00290         else
00291         {
00292             cmd = new VTranslatePointCmd(
00293                     &view()->part()->document(),
00294                     qRound( ( last().x() - first().x() ) ),
00295                     qRound( ( last().y() - first().y() ) ) );
00296         }
00297         view()->part()->addCommand( cmd, true );
00298         m_state = normal;
00299     }
00300     else
00301     {
00302         KoPoint fp = first();
00303         KoPoint lp = last();
00304 
00305         if ( (fabs(lp.x() - fp.x()) + fabs(lp.y()-fp.y())) < 3.0 )
00306         {
00307             // AK - should take the middle point here
00308             fp = last() - KoPoint(8.0, 8.0);
00309             lp = last() + KoPoint(8.0, 8.0);
00310         }
00311 
00312         // erase old object:
00313         draw();
00314 
00315         if( m_select )
00316         {
00317             view()->part()->document().selection()->append();   // select all
00318             view()->part()->document().selection()->append(
00319                 KoRect( fp.x(), fp.y(), lp.x() - fp.x(), lp.y() - fp.y() ).normalize(),
00320                 false );
00321         }
00322         else
00323         {
00324             view()->part()->document().selection()->take(
00325                 KoRect( fp.x(), fp.y(), lp.x() - fp.x(), lp.y() - fp.y() ).normalize(),
00326                 false, false );
00327         }
00328         view()->selectionChanged();
00329         view()->part()->repaintAllViews();
00330         m_state = normal;
00331     }
00332 }
00333 
00334 void
00335 VSelectNodesTool::cancel()
00336 {
00337     // Erase old object:
00338     if ( isDragging() )
00339     {
00340         draw();
00341         m_state = normal;
00342         view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00343     }
00344 }
00345 
00346 void
00347 VSelectNodesTool::recalc()
00348 {
00349     if( m_state == dragging )
00350     {
00351         m_current = last();
00352     }
00353     else if( m_state == moving || m_state == movingbezier1 || m_state == movingbezier2 )
00354     {
00355         KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
00356         double distx = _last.x() - first().x();
00357         double disty = _last.y() - first().y();
00358         // move operation
00359         QWMatrix mat;
00360         mat.translate( distx, disty );
00361 
00362         // Copy selected objects and transform:
00363         m_objects.clear();
00364         VObject* copy;
00365 
00366         VTransformNodes op( mat );
00367 
00368         VObjectListIterator itr = view()->part()->document().selection()->objects();
00369         for ( ; itr.current() ; ++itr )
00370         {
00371             if( itr.current()->state() != VObject::deleted )
00372             {
00373                 copy = itr.current()->clone();
00374                 copy->setState( VObject::edit );
00375                 op.visit( *copy );
00376                 m_objects.append( copy );
00377             }
00378         }
00379     }
00380 }
00381 
00382 void
00383 VSelectNodesTool::setup( KActionCollection *collection )
00384 {
00385     m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
00386 
00387     if( m_action == 0 )
00388     {
00389         m_action = new KRadioAction( i18n( "Select Nodes Tool" ), "14_selectnodes", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
00390         m_action->setToolTip( i18n( "Select Nodes" ) );
00391         m_action->setExclusiveGroup( "select" );
00392         //m_ownAction = true;
00393     }
00394 }
00395 
00396 KoRect 
00397 VSelectNodesTool::calcSelRect( const KoPoint &pos ) const
00398 {
00399     double tolerance = view()->part()->document().selection()->handleSize() / view()->zoom();
00400     return KoRect( pos.x() - tolerance, pos.y() - tolerance, 2 * tolerance + 1.0, 2 * tolerance + 1.0 );
00401 }
KDE Home | KDE Accessibility Home | Description of Access Keys