00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <klocale.h>
00022
00023 #include "vcomposite.h"
00024 #include "vpath.h"
00025 #include "vsegment.h"
00026 #include "vselection.h"
00027 #include "vtext.h"
00028 #include "vimage.h"
00029 #include "vtransformcmd.h"
00030 #include "vstroke.h"
00031 #include "vfill.h"
00032 #include "vdocument.h"
00033
00034 #include <kdebug.h>
00035
00036 VTransformCmd::VTransformCmd( VDocument *doc, const QWMatrix& mat, bool duplicate )
00037 : VCommand( doc, i18n( "Transform Objects" ) ), m_mat( mat ), m_duplicate( duplicate )
00038 {
00039 m_selection = ( document() && document()->selection() )
00040 ? document()->selection()->clone()
00041 : new VSelection();
00042
00043 if( m_duplicate )
00044 {
00045 if( !m_selection || m_selection->objects().count() == 1 )
00046 setName( i18n( "Duplicate Object" ) );
00047 else
00048 setName( i18n( "Duplicate Objects" ) );
00049 }
00050 else if( !m_selection || m_selection->objects().count() == 1 )
00051 setName( i18n( "Transform Object" ) );
00052 }
00053
00054 VTransformCmd::VTransformCmd( VDocument *doc, const QString& name, const QString& icon, bool duplicate )
00055 : VCommand( doc, name, icon ), m_duplicate( duplicate )
00056 {
00057 m_selection = ( document() && document()->selection() )
00058 ? document()->selection()->clone()
00059 : new VSelection();
00060
00061 if( m_duplicate )
00062 {
00063 if( !m_selection || m_selection->objects().count() == 1 )
00064 setName( i18n( "Duplicate Object" ) );
00065 else
00066 setName( i18n( "Duplicate Objects" ) );
00067 }
00068 }
00069
00070 VTransformCmd::~VTransformCmd()
00071 {
00072 delete( m_selection );
00073 m_selection = 0L;
00074 }
00075
00076 void
00077 VTransformCmd::execute()
00078 {
00079 VObjectListIterator itr( m_selection->objects() );
00080
00081 if( m_duplicate )
00082 {
00083
00084 VObject *copy = 0L;
00085 for( ; itr.current() ; ++itr )
00086 {
00087 copy = itr.current()->clone();
00088 visit( *copy );
00089 document()->append( copy );
00090 document()->selection()->take( *itr.current() );
00091 document()->selection()->append( copy );
00092 m_duplicates.append( copy );
00093 }
00094 }
00095 else
00096 {
00097
00098 document()->selection()->clear();
00099
00100 for( ; itr.current() ; ++itr )
00101 {
00102 visit( *itr.current() );
00103 }
00104
00105 document()->selection()->append( m_selection->objects() );
00106 }
00107
00108 setSuccess( true );
00109 }
00110
00111 void
00112 VTransformCmd::unexecute()
00113 {
00114
00115 m_mat = m_mat.invert();
00116
00117 if( m_duplicate )
00118 {
00119
00120 VObjectListIterator itr( m_duplicates );
00121 for( ; itr.current() ; ++itr )
00122 {
00123 document()->selection()->take( *itr.current() );
00124 itr.current()->setState( VObject::deleted );
00125 }
00126 VObjectListIterator jtr( m_selection->objects() );
00127
00128
00129 for( ; jtr.current() ; ++jtr )
00130 {
00131 document()->selection()->append( jtr.current() );
00132 }
00133 }
00134 else
00135 {
00136 document()->selection()->clear();
00137
00138 visit( *m_selection );
00139 document()->selection()->append( m_selection->objects() );
00140 }
00141
00142 m_mat = m_mat.invert();
00143 setSuccess( false );
00144 }
00145
00146 void
00147 VTransformCmd::visitVObject( VObject& object )
00148 {
00149
00150 VStroke* stroke = object.stroke();
00151 if( stroke && stroke->type() == VStroke::grad )
00152 stroke->gradient().transform( m_mat );
00153 else if( stroke && stroke->type() == VStroke::patt )
00154 stroke->pattern().transform( m_mat );
00155
00156 VFill* fill = object.fill();
00157 if( fill && fill->type() == VFill::grad )
00158 fill->gradient().transform( m_mat );
00159 else if( fill && fill->type() == VFill::patt )
00160 fill->pattern().transform( m_mat );
00161 }
00162
00163 void
00164 VTransformCmd::visitVPath( VPath& composite )
00165 {
00166 if( composite.state() == VObject::hidden ||
00167 composite.state() == VObject::normal_locked ||
00168 composite.state() == VObject::hidden_locked )
00169 return;
00170
00171 visitVObject( composite );
00172
00173 composite.transform( m_mat );
00174
00175 VVisitor::visitVPath( composite );
00176 }
00177
00178 void
00179 VTransformCmd::visitVSubpath( VSubpath& path )
00180 {
00181 if( path.state() == VObject::hidden ||
00182 path.state() == VObject::normal_locked ||
00183 path.state() == VObject::hidden_locked )
00184 return;
00185
00186 VSegment* segment = path.first();
00187
00188 while( segment )
00189 {
00190 for( unsigned short i = 0; i < segment->degree(); ++i )
00191 {
00192 segment->setPoint( i, segment->point( i ).transform( m_mat ) );
00193 }
00194
00195 segment = segment->next();
00196 }
00197
00198 path.invalidateBoundingBox();
00199 }
00200
00201 void
00202 VTransformCmd::visitVText( VText& text )
00203 {
00204 if( text.state() == VObject::hidden ||
00205 text.state() == VObject::normal_locked ||
00206 text.state() == VObject::hidden_locked )
00207 return;
00208
00209 visitVObject( text );
00210
00211 visit( text.basePath() );
00212
00213 VPathListIterator itr( text.glyphs() );
00214
00215 for( ; itr.current() ; ++itr )
00216 {
00217 visit( *itr.current() );
00218 }
00219
00220 text.invalidateBoundingBox();
00221 }
00222
00223 void
00224 VTransformCmd::visitVImage( VImage &img )
00225 {
00226 if( img.state() == VObject::hidden ||
00227 img.state() == VObject::normal_locked ||
00228 img.state() == VObject::hidden_locked )
00229 return;
00230
00231 img.transform( m_mat );
00232 }
00233
00234 VTranslateCmd::VTranslateCmd( VDocument *doc, double d1, double d2, bool duplicate )
00235 : VTransformCmd( doc, i18n( "Translate Objects" ), "translate", duplicate )
00236 {
00237 if( !duplicate && ( !m_selection || m_selection->objects().count() == 1 ) )
00238 setName( i18n( "Translate Object" ) );
00239
00240 m_mat.translate( d1, d2 );
00241 }
00242
00243
00244 VScaleCmd::VScaleCmd( VDocument *doc, const KoPoint& p, double s1, double s2, bool duplicate )
00245 : VTransformCmd( doc, i18n( "Scale Objects" ), "14_select", duplicate )
00246 {
00247 if( !duplicate && ( !m_selection || m_selection->objects().count() == 1 ) )
00248 setName( i18n( "Scale Object" ) );
00249
00250 m_mat.translate( p.x(), p.y() );
00251 m_mat.scale( s1, s2 );
00252 m_mat.translate( -p.x(), -p.y() );
00253 }
00254
00255
00256 VShearCmd::VShearCmd( VDocument *doc, const KoPoint& p, double s1, double s2, bool duplicate )
00257 : VTransformCmd( doc, i18n( "Shear Objects" ), "14_shear", duplicate )
00258 {
00259 if( !duplicate && ( !m_selection || m_selection->objects().count() == 1 ) )
00260 setName( i18n( "Shear Object" ) );
00261
00262 m_mat.translate( p.x(), p.y() );
00263 m_mat.shear( s1, s2 );
00264 m_mat.translate( -p.x(), -p.y() );
00265 }
00266
00267 VRotateCmd::VRotateCmd( VDocument *doc, const KoPoint& p, double angle, bool duplicate )
00268 : VTransformCmd( doc, i18n( "Rotate Objects" ), "14_rotate", duplicate )
00269 {
00270 if( !duplicate && ( !m_selection || m_selection->objects().count() == 1 ) )
00271 setName( i18n( "Rotate Object" ) );
00272
00273 m_mat.translate( p.x(), p.y() );
00274 m_mat.rotate( angle );
00275 m_mat.translate( -p.x(), -p.y() );
00276 }
00277
00278 VTranslateBezierCmd::VTranslateBezierCmd( VDocument *doc, VSegment *segment, double d1, double d2, bool firstControl )
00279 : VCommand( doc, i18n( "Translate Bezier" ) ), m_segment( segment ), m_firstControl( firstControl )
00280 , m_subpath(0L)
00281 {
00282 m_mat.translate( d1, d2 );
00283 m_segmenttwo = 0L;
00284
00285 if( document() && document()->selection() )
00286 {
00287 VObjectListIterator itr( document()->selection()->objects() );
00288
00289
00290 for( ; itr.current() ; ++itr )
00291 visit( *itr.current() );
00292 }
00293 }
00294
00295 VTranslateBezierCmd::~VTranslateBezierCmd()
00296 {
00297 }
00298
00299 void
00300 VTranslateBezierCmd::execute()
00301 {
00302 if( m_segment->degree() == 3 )
00303 {
00304 QWMatrix m2( m_mat.m11(), m_mat.m12(), m_mat.m21(), m_mat.m22(), -m_mat.dx(), -m_mat.dy() );
00305 if( m_firstControl )
00306 {
00307 if( m_segment->prev() &&
00308 m_segment->prev()->degree() == 3 &&
00309 m_segment->prev()->isSmooth() )
00310 {
00311 m_segmenttwo = m_segment->prev();
00312 for( uint i = 0;i < m_segmenttwo->degree();i++ )
00313 {
00314 m_segmenttwo->selectPoint( i, i == 1 );
00315
00316 if( i == 1 )
00317 m_segmenttwo->setPoint( i, m_segmenttwo->point( i ).transform( m2 ) );
00318 }
00319 }
00320 }
00321 else
00322 {
00323 m_segmenttwo = ( m_segment->isSmooth() && m_segment->next()->degree() == 3 ) ? m_segment->next() : 0L;
00324 if( m_segmenttwo )
00325 {
00326 for( uint i = 0;i < m_segmenttwo->degree();i++ )
00327 {
00328 m_segmenttwo->selectPoint( i, i == 0 );
00329
00330 if( i == 0 )
00331 m_segmenttwo->setPoint( i, m_segmenttwo->point( i ).transform( m2 ) );
00332 }
00333 }
00334 }
00335
00336 for( uint i = 0;i < m_segment->degree();i++ )
00337 {
00338 m_segment->selectPoint( i, i == uint( m_firstControl ? 0 : 1 ) );
00339
00340 if( i == uint( m_firstControl ? 0 : 1 ) )
00341 m_segment->setPoint( i, m_segment->point( i ).transform( m_mat ) );
00342 }
00343 }
00344
00345 if( m_subpath )
00346 m_subpath->invalidateBoundingBox();
00347
00348 setSuccess( true );
00349 }
00350
00351 void
00352 VTranslateBezierCmd::unexecute()
00353 {
00354 QWMatrix m2( m_mat.m11(), m_mat.m12(), m_mat.m21(), m_mat.m22(), -m_mat.dx(), -m_mat.dy() );
00355 if( m_segment )
00356 {
00357 for( uint i = 0;i < m_segment->degree();i++ )
00358 {
00359 m_segment->selectPoint( i, i == uint( m_firstControl ? 0 : 1 ) );
00360
00361 if( i == uint( m_firstControl ? 0 : 1 ) )
00362 m_segment->setPoint( i, m_segment->point( i ).transform( m_mat.invert() ) );
00363 }
00364
00365 if( m_segmenttwo )
00366 {
00367 uint index = m_firstControl ? 1 : 0;
00368 for( uint i = 0;i < m_segmenttwo->degree();i++ )
00369 {
00370 m_segmenttwo->selectPoint( i, i == index );
00371
00372 if( i == index )
00373 m_segmenttwo->setPoint( i, m_segmenttwo->point( i ).transform( m2.invert() ) );
00374 }
00375 }
00376 }
00377 setSuccess( false );
00378 }
00379
00380 void
00381 VTranslateBezierCmd::visitVSubpath( VSubpath& path )
00382 {
00383 if( m_subpath )
00384 return;
00385
00386 VSegment* segment = path.first();
00387
00388
00389 while( segment )
00390 {
00391 if( segment == m_segment )
00392 {
00393 m_subpath = &path;
00394 break;
00395 }
00396 segment = segment->next();
00397 }
00398 }
00399
00400 VTranslatePointCmd::VTranslatePointCmd( VDocument *doc, double d1, double d2 )
00401 : VCommand( doc, i18n( "Translate Points" ), "translate" )
00402 {
00403 m_mat.translate( d1, d2 );
00404
00405 if( document() && document()->selection() )
00406 {
00407 VObjectListIterator itr( document()->selection()->objects() );
00408
00409
00410 for( ; itr.current() ; ++itr )
00411 visit( *itr.current() );
00412
00413 if( m_segPnts.size() > 1 || ( m_segPnts.size() == 0 && m_segPnts.begin().data().size() > 1 ) )
00414 setName( i18n( "Translate Point" ) );
00415 }
00416 }
00417
00418 VTranslatePointCmd::~VTranslatePointCmd()
00419 {
00420 }
00421
00422 void
00423 VTranslatePointCmd::execute()
00424 {
00425 translatePoints();
00426 setSuccess( true );
00427 }
00428
00429 void
00430 VTranslatePointCmd::unexecute()
00431 {
00432 m_mat = m_mat.invert();
00433 translatePoints();
00434 m_mat = m_mat.invert();
00435 setSuccess( false );
00436 }
00437
00438 void
00439 VTranslatePointCmd::visitVSubpath( VSubpath& path )
00440 {
00441 if( path.state() == VObject::hidden ||
00442 path.state() == VObject::normal_locked ||
00443 path.state() == VObject::hidden_locked )
00444 return;
00445
00446 VSegment* segment = path.first();
00447
00448 uint segCnt = m_segPnts.size();
00449
00450
00451 while( segment )
00452 {
00453 QValueVector<int> pnts;
00454
00455 for( unsigned short i = 0; i < segment->degree(); ++i )
00456 {
00457 if( segment->pointIsSelected( i ) )
00458 pnts.push_back( i );
00459 }
00460 if( pnts.size() )
00461 m_segPnts[segment] = pnts;
00462
00463 segment = segment->next();
00464 }
00465
00466
00467 if( segCnt != m_segPnts.size() )
00468 m_subpaths.append( &path );
00469 }
00470
00471 void
00472 VTranslatePointCmd::translatePoints()
00473 {
00474 QMap<VSegment*, QValueVector<int> >::iterator it, et = m_segPnts.end();
00475
00476
00477 for( it = m_segPnts.begin(); it != et; ++it )
00478 {
00479 VSegment *segment = it.key();
00480 QValueVector<int> &pnts = it.data();
00481
00482 int pntCnt = pnts.size();
00483 for( int i = 0; i < pntCnt; ++i )
00484 segment->setPoint( pnts[i], segment->point( pnts[i] ).transform( m_mat ) );
00485 }
00486
00487
00488 VObjectListIterator itr( m_subpaths );
00489 for( ; itr.current(); ++itr )
00490 itr.current()->invalidateBoundingBox();
00491 }