00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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 if( m_state == dragging )
00088 {
00089 painter->setPen( Qt::DotLine );
00090 painter->newPath();
00091 painter->moveTo( KoPoint( m_first.x(), m_first.y() ) );
00092 painter->lineTo( KoPoint( m_current.x(), m_first.y() ) );
00093 painter->lineTo( KoPoint( m_current.x(), m_current.y() ) );
00094 painter->lineTo( KoPoint( m_first.x(), m_current.y() ) );
00095 painter->lineTo( KoPoint( m_first.x(), m_first.y() ) );
00096 painter->strokePath();
00097 }
00098 else
00099 {
00100 VDrawSelection op( m_objects, painter, true, VSelection::handleSize() );
00101 VObjectListIterator itr = m_objects;
00102 for( ; itr.current(); ++itr )
00103 op.visit( *( itr.current() ) );
00104 }
00105 }
00106
00107 void
00108 VSelectNodesTool::setCursor() const
00109 {
00110 if( m_state >= moving )
00111 {
00112 view()->setCursor( VCursor::needleMoveArrow() );
00113 return;
00114 }
00115
00116 KoRect selrect = calcSelRect( last() );
00117
00118 QPtrList<VSegment> segments = view()->part()->document().selection()->getSegments( selrect );
00119 if( segments.count() > 0 )
00120 {
00121 VSegment* seg = segments.at( 0 );
00122 for( int i = 0; i < seg->degree(); ++i )
00123 if( seg->pointIsSelected( i ) && selrect.contains( seg->point( i ) ) )
00124 {
00125 view()->setCursor( VCursor::needleMoveArrow() );
00126 break;
00127 }
00128 }
00129 else
00130 view()->setCursor( VCursor::needleArrow() );
00131 }
00132
00133 void
00134 VSelectNodesTool::mouseButtonPress()
00135 {
00136 m_first = m_current = first();
00137
00138 m_state = normal;
00139 m_select = true;
00140
00141 recalc();
00142
00143 view()->part()->document().selection()->setState( VObject::edit );
00144 view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00145 view()->part()->document().selection()->setState( VObject::selected );
00146
00147 VSelection* selection = view()->part()->document().selection();
00148
00149 KoRect selrect = calcSelRect( m_current );
00150
00151
00152 QPtrList<VSegment> segments = selection->getSegments( selrect );
00153 if( segments.count() > 0 )
00154 {
00155 VSegment *seg = segments.at( 0 );
00156 VSegment* prev = seg->prev();
00157 VSegment* next = seg->next();
00158
00159
00160
00161 if( segments.count() == 1 && ! selrect.contains( seg->knot() ) && ! seg->knotIsSelected()
00162 && ( prev && ! prev->knotIsSelected() ) )
00163 {
00164 if( selrect.contains( seg->point( 1 ) ) )
00165 {
00166 m_state = movingbezier1;
00167 if( next )
00168 next->selectPoint( 0, false );
00169 }
00170 else if( selrect.contains( seg->point( 0 ) ) )
00171 {
00172 m_state = movingbezier2;
00173 if( prev )
00174 prev->selectPoint( 1, false );
00175 }
00176 }
00177 else
00178 {
00179 for( VSegment *seg = segments.first(); seg; seg = segments.next() )
00180 {
00181 for( int i = 0; i < seg->degree(); ++i )
00182 {
00183 if( seg->pointIsSelected( i ) && selrect.contains( seg->point( i ) ) )
00184 {
00185 m_state = moving;
00186 break;
00187 }
00188 }
00189 if( m_state == moving )
00190 break;
00191 }
00192 }
00193
00194 double minDist = -1.0;
00195
00196 for( VSegment *seg = segments.first(); seg; seg = segments.next() )
00197 {
00198 for( int i = 0; i < seg->degree(); ++i )
00199 {
00200 if( selrect.contains( seg->point( i ) ) )
00201 {
00202 KoPoint vDist = seg->point( i ) - m_current;
00203 double dist = vDist.x()*vDist.x() + vDist.y()*vDist.y();
00204 if( minDist < 0.0 || dist < minDist )
00205 {
00206 m_first = seg->point( i );
00207 minDist = dist;
00208 }
00209 }
00210 }
00211 }
00212 recalc();
00213 }
00214 else
00215 m_state = dragging;
00216
00217 draw();
00218 }
00219
00220 void
00221 VSelectNodesTool::rightMouseButtonPress()
00222 {
00223 m_first = m_current = first();
00224
00225 m_state = normal;
00226 m_select = false;
00227
00228 recalc();
00229
00230 view()->part()->document().selection()->setState( VObject::edit );
00231 view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00232 view()->part()->document().selection()->setState( VObject::selected );
00233
00234 draw();
00235 }
00236
00237 bool
00238 VSelectNodesTool::keyReleased( Qt::Key key )
00239 {
00240 VSelection* selection = view()->part()->document().selection();
00241
00242 switch( key )
00243 {
00244
00245 case Qt::Key_I:
00246 {
00247 uint handleSize = selection->handleSize();
00248 if( shiftPressed() )
00249 selection->setHandleSize( ++handleSize );
00250 else if( handleSize > 1 )
00251 selection->setHandleSize( --handleSize );
00252 }
00253 break;
00254 case Qt::Key_Delete:
00255 if( selection->objects().count() > 0 )
00256 view()->part()->addCommand( new VDeleteNodeCmd( &view()->part()->document() ), true );
00257 break;
00258 default: return false;
00259 }
00260
00261 if( view() )
00262 view()->repaintAll( selection->boundingBox() );
00263
00264 return true;
00265 }
00266
00267 void
00268 VSelectNodesTool::mouseButtonRelease()
00269 {
00270
00271 draw();
00272
00273 VSelection* selection = view()->part()->document().selection();
00274
00275 KoRect selrect = calcSelRect( last() );
00276
00277 if( ctrlPressed() )
00278 selection->append( selrect.normalize(), false, false );
00279 else
00280 selection->append( selrect.normalize(), false, true );
00281
00282 view()->selectionChanged();
00283 view()->part()->repaintAllViews();
00284 m_state = normal;
00285 }
00286
00287 void
00288 VSelectNodesTool::rightMouseButtonRelease()
00289 {
00290
00291 draw();
00292
00293 VSelection* selection = view()->part()->document().selection();
00294
00295 KoRect selrect = calcSelRect( last() );
00296
00297 selection->take( selrect.normalize(), false, false );
00298
00299 view()->selectionChanged();
00300 view()->part()->repaintAllViews();
00301 m_state = normal;
00302 }
00303
00304 void
00305 VSelectNodesTool::mouseDrag()
00306 {
00307 draw();
00308
00309 recalc();
00310
00311 draw();
00312 }
00313
00314 void
00315 VSelectNodesTool::mouseDragRelease()
00316 {
00317 if( m_state >= moving )
00318 {
00319 view()->part()->document().selection()->setState( VObject::selected );
00320 VCommand *cmd;
00321 QPtrList<VSegment> segments;
00322 KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
00323 if( m_state == movingbezier1 || m_state == movingbezier2 )
00324 {
00325 KoRect selrect = calcSelRect( m_first );
00326 segments = view()->part()->document().selection()->getSegments( selrect );
00327 cmd = new VTranslateBezierCmd( &view()->part()->document(), segments.at( 0 ),
00328 qRound( ( _last.x() - m_first.x() ) ),
00329 qRound( ( _last.y() - m_first.y() ) ),
00330 m_state == movingbezier2 );
00331 }
00332 else
00333 {
00334 cmd = new VTranslatePointCmd(
00335 &view()->part()->document(),
00336 qRound( ( _last.x() - m_first.x() ) ),
00337 qRound( ( _last.y() - m_first.y() ) ) );
00338 }
00339 view()->part()->addCommand( cmd, true );
00340 m_state = normal;
00341 }
00342 else
00343 {
00344 KoPoint fp = m_first;
00345 KoPoint lp = last();
00346
00347 if ( (fabs(lp.x() - fp.x()) + fabs(lp.y()-fp.y())) < 3.0 )
00348 {
00349
00350 fp = last() - KoPoint(8.0, 8.0);
00351 lp = last() + KoPoint(8.0, 8.0);
00352 }
00353
00354
00355 draw();
00356
00357 if( m_select )
00358 {
00359 view()->part()->document().selection()->append();
00360 view()->part()->document().selection()->append(
00361 KoRect( fp.x(), fp.y(), lp.x() - fp.x(), lp.y() - fp.y() ).normalize(),
00362 false, true );
00363 }
00364 else
00365 {
00366 view()->part()->document().selection()->take(
00367 KoRect( fp.x(), fp.y(), lp.x() - fp.x(), lp.y() - fp.y() ).normalize(),
00368 false, false );
00369 }
00370 view()->selectionChanged();
00371 view()->part()->repaintAllViews();
00372 m_state = normal;
00373 }
00374 }
00375
00376 void
00377 VSelectNodesTool::cancel()
00378 {
00379
00380 if ( isDragging() )
00381 {
00382 draw();
00383 m_state = normal;
00384 view()->repaintAll( view()->part()->document().selection()->boundingBox() );
00385 }
00386 }
00387
00388 void
00389 VSelectNodesTool::recalc()
00390 {
00391 if( m_state == dragging )
00392 {
00393 m_current = last();
00394 }
00395 else if( m_state == moving || m_state == movingbezier1 || m_state == movingbezier2 )
00396 {
00397 KoPoint _last = view()->canvasWidget()->snapToGrid( last() );
00398 double distx = _last.x() - m_first.x();
00399 double disty = _last.y() - m_first.y();
00400
00401 QWMatrix mat;
00402 mat.translate( distx, disty );
00403
00404
00405 m_objects.clear();
00406 VObject* copy;
00407
00408 VTransformNodes op( mat );
00409
00410 VObjectListIterator itr = view()->part()->document().selection()->objects();
00411 for ( ; itr.current() ; ++itr )
00412 {
00413 if( itr.current()->state() != VObject::deleted )
00414 {
00415 copy = itr.current()->clone();
00416 copy->setState( VObject::edit );
00417 op.visit( *copy );
00418 m_objects.append( copy );
00419 }
00420 }
00421 }
00422 }
00423
00424 void
00425 VSelectNodesTool::setup( KActionCollection *collection )
00426 {
00427 m_action = static_cast<KRadioAction *>(collection -> action( name() ) );
00428
00429 if( m_action == 0 )
00430 {
00431 m_action = new KRadioAction( i18n( "Select Nodes Tool" ), "14_selectnodes", Qt::SHIFT+Qt::Key_H, this, SLOT( activate() ), collection, name() );
00432 m_action->setToolTip( i18n( "Select Nodes" ) );
00433 m_action->setExclusiveGroup( "select" );
00434
00435 }
00436 }
00437
00438 KoRect
00439 VSelectNodesTool::calcSelRect( const KoPoint &pos ) const
00440 {
00441 double tolerance = view()->part()->document().selection()->handleSize() / view()->zoom();
00442 return KoRect( pos.x() - tolerance, pos.y() - tolerance, 2 * tolerance + 1.0, 2 * tolerance + 1.0 );
00443 }