00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "construct_mode.h"
00019
00020 #include "../objects/object_factory.h"
00021 #include "../objects/object_drawer.h"
00022 #include "../objects/text_type.h"
00023 #include "../objects/text_imp.h"
00024 #include "../objects/bogus_imp.h"
00025 #include "../objects/point_imp.h"
00026 #include "../misc/argsparser.h"
00027
00028 #include "../kig/kig_document.h"
00029 #include "../kig/kig_part.h"
00030 #include "../kig/kig_view.h"
00031 #include "../misc/object_constructor.h"
00032 #include "../misc/coordinate_system.h"
00033 #include "../misc/kigpainter.h"
00034 #include "../misc/calcpaths.h"
00035
00036 #include "popup.h"
00037
00038 #include <qevent.h>
00039
00040 #include <kcursor.h>
00041 #include <kaction.h>
00042
00043 #include <algorithm>
00044 #include <functional>
00045
00046 static void redefinePoint( ObjectTypeCalcer* mpt, const Coordinate& c, KigDocument& doc, const KigWidget& w )
00047 {
00048 ObjectFactory::instance()->redefinePoint( mpt, c, doc, w );
00049 mpt->calc( doc );
00050 }
00051
00052 BaseConstructMode::BaseConstructMode( KigPart& d )
00053 : BaseMode( d )
00054 {
00055 mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate( 0, 0 ) );
00056 mpt->calc( d.document() );
00057 mcursor = ObjectFactory::instance()->cursorPointCalcer( Coordinate( 0, 0 ) );
00058 mcursor->calc( d.document() );
00059
00060 }
00061
00062 BaseConstructMode::~BaseConstructMode()
00063 {
00064 delete mcursor;
00065
00066 }
00067
00068 void BaseConstructMode::leftReleased( QMouseEvent* e, KigWidget* v )
00069 {
00070 if( (pointLocation() - e->pos()).manhattanLength() > 4 ) return;
00071
00072 ObjectHolder* o = 0;
00073 bool keyCtrlOrShift = ( e->modifiers() & ( Qt::ControlModifier | Qt::ShiftModifier) ) != 0;
00074 std::vector<ObjectHolder*> moco = oco();
00075 if ( ! moco.empty() )
00076 {
00077 std::vector<ObjectHolder*> goodargs;
00078 if ( !moco.empty() )
00079 {
00080 std::vector<ObjectHolder*>::const_iterator it;
00081 std::vector<ObjectCalcer*> testargs = getCalcers( mparents );
00082 for ( std::vector<ObjectHolder*>::const_iterator i = moco.begin(); i != moco.end(); ++i )
00083 {
00084 it = std::find( mparents.begin(), mparents.end(), *i );
00085 bool newdup =
00086 ( it == mparents.end() ) ||
00087 isAlreadySelectedOK( testargs, it - mparents.begin() );
00088 if ( newdup )
00089 {
00090 testargs.push_back( ( *i )->calcer() );
00091 if ( wantArgs( testargs, mdoc.document(), *v ) )
00092 goodargs.push_back( *i );
00093 testargs.pop_back();
00094 }
00095 }
00096 int id = ObjectChooserPopup::getObjectFromList( e->pos(), v, goodargs );
00097 if ( id >= 0 )
00098 o = goodargs[id];
00099 }
00100 }
00101 leftClickedObject( o, e->pos(), *v, keyCtrlOrShift );
00102 KigMode::leftReleased( e, v );
00103 }
00104
00105 void BaseConstructMode::leftClickedObject(
00106 ObjectHolder* o, const QPoint& p, KigWidget& w, bool )
00107 {
00108 std::vector<ObjectHolder*>::iterator it = std::find( mparents.begin(), mparents.end(), o );
00109 std::vector<ObjectCalcer*> nargs = getCalcers( mparents );
00110
00111
00112
00113
00114
00115 bool duplicationchecked =
00116 ( it == mparents.end() ) ||
00117 isAlreadySelectedOK( nargs, it - mparents.begin() );
00118 if ( o && duplicationchecked )
00119 {
00120 nargs.push_back( o->calcer() );
00121 if ( wantArgs( nargs, mdoc.document(), w ) )
00122 {
00123 selectObject( o, w );
00124 return;
00125 }
00126 }
00127
00128 nargs = getCalcers( mparents );
00129 nargs.push_back( mpt.get() );
00130 if ( wantArgs( nargs, mdoc.document(), w ) )
00131 {
00132
00133 ObjectHolder* n = new ObjectHolder( mpt.get() );
00134 mdoc.addObject( n );
00135 selectObject( n, w );
00136
00137 mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w );
00138 mpt->calc( mdoc.document() );
00139 return;
00140 }
00141
00142 nargs = getCalcers( mparents );
00143 nargs.push_back( mcursor );
00144
00145 if ( wantArgs( nargs, mdoc.document(), w ) )
00146 {
00147
00148
00149
00150
00151 ObjectHolder* n = new ObjectHolder( mcursor );
00152 selectObject( n, w );
00153 mcursor = ObjectFactory::instance()->cursorPointCalcer( w.fromScreen( p ) );
00154
00155 mcursor->calc( mdoc.document() );
00156 delete n;
00157 }
00158 }
00159
00160 void BaseConstructMode::midClicked( const QPoint& p, KigWidget& w )
00161 {
00162 std::vector<ObjectCalcer*> args = getCalcers( mparents );
00163 args.push_back( mpt.get() );
00164 if ( wantArgs( args, mdoc.document(), w ) )
00165 {
00166 ObjectHolder* n = new ObjectHolder( mpt.get() );
00167 mdoc.addObject( n );
00168
00169 selectObject( n, w );
00170
00171 mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w );
00172 mpt->calc( mdoc.document() );
00173 }
00174 }
00175
00176 void BaseConstructMode::rightClicked( const std::vector<ObjectHolder*>&, const QPoint&, KigWidget& )
00177 {
00178
00179 }
00180
00181 void BaseConstructMode::mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p,
00182 KigWidget& w, bool shiftpressed )
00183 {
00184 mdoc.emitStatusBarText( selectStatement( getCalcers( mparents ), w ) );
00185
00186 w.updateCurPix();
00187 KigPainter pter( w.screenInfo(), &w.curPix, mdoc.document() );
00188
00189 Coordinate ncoord = w.fromScreen( p );
00190 if ( shiftpressed )
00191 ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w );
00192
00193 redefinePoint( mpt.get(), ncoord, mdoc.document(), w );
00194 mcursor->move( ncoord, mdoc.document() );
00195 mcursor->calc( mdoc.document() );
00196
00197 std::vector<ObjectCalcer*> args = getCalcers( mparents );
00198 bool duplicationchecked = false;
00199 std::vector<ObjectHolder*> goodargs;
00200 if ( ! os.empty() )
00201 {
00202 std::vector<ObjectHolder*>::const_iterator it;
00203 std::vector<ObjectCalcer*> testargs = getCalcers( mparents );
00204 for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
00205 {
00206 it = std::find( mparents.begin(), mparents.end(), *i );
00207 bool newdup =
00208 ( it == mparents.end() ) ||
00209 isAlreadySelectedOK( args, it - mparents.begin() );
00210 if ( newdup )
00211 {
00212 testargs.push_back( ( *i )->calcer() );
00213 if ( wantArgs( testargs, mdoc.document(), w ) )
00214 goodargs.push_back( *i );
00215 testargs.pop_back();
00216 }
00217 duplicationchecked |= newdup;
00218 }
00219 }
00220 bool calcnow = ( goodargs.size() == 1 ) || ( ( goodargs.size() > 0 ) && ( goodargs.front()->imp()->inherits( PointImp::stype() ) ) );
00221 if ( calcnow )
00222 {
00223 args.push_back( goodargs.front()->calcer() );
00224 }
00225
00226 if ( !os.empty() && duplicationchecked && calcnow )
00227 {
00228 handlePrelim( args, p, pter, w );
00229
00230 w.setCursor( Qt::PointingHandCursor );
00231 }
00232 else
00233 {
00234 std::vector<ObjectCalcer*> args = getCalcers( mparents );
00235 args.push_back( mpt.get() );
00236 std::vector<ObjectCalcer*> argscursor = getCalcers( mparents );
00237 argscursor.push_back( mcursor );
00238 bool text = true;
00239 if ( wantArgs( args, mdoc.document(), w ) )
00240 {
00241 ObjectDrawer d;
00242 d.draw( *mpt->imp(), pter, true );
00243
00244 handlePrelim( args, p, pter, w );
00245
00246 w.setCursor( Qt::PointingHandCursor );
00247 }
00248 else if ( wantArgs( argscursor, mdoc.document(), w ) )
00249 {
00250 ObjectDrawer d;
00251
00252
00253 handlePrelim( argscursor, p, pter, w );
00254
00255 w.setCursor( Qt::CrossCursor );
00256 }
00257 else
00258 {
00259 w.setCursor( Qt::ArrowCursor );
00260 text = false;
00261 }
00262 if ( !text && ( goodargs.size() > 1 ) )
00263 {
00264 QString strwhich = i18n( "Which object?" );
00265 mdoc.emitStatusBarText( strwhich );
00266
00267 QPoint textloc = p;
00268 textloc.setX( textloc.x() + 15 );
00269 pter.drawTextStd( textloc, strwhich );
00270
00271 w.setCursor( Qt::PointingHandCursor );
00272 }
00273 }
00274 w.updateWidget( pter.overlay() );
00275 }
00276
00277 void BaseConstructMode::selectObject( ObjectHolder* o, KigWidget& w )
00278 {
00279 mparents.push_back( o );
00280 std::vector<ObjectCalcer*> args = getCalcers( mparents );
00281
00282 if ( wantArgs( args, mdoc.document(), w ) == ArgsParser::Complete )
00283 {
00284 handleArgs( args, w );
00285 };
00286
00287 w.redrawScreen( mparents );
00288 }
00289
00290 PointConstructMode::PointConstructMode( KigPart& d )
00291 : BaseMode( d )
00292 {
00293
00294
00295
00296
00297 mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate() );
00298 mpt->calc( d.document() );
00299
00300 mdoc.emitStatusBarText( i18n( "Click the location where you want to place the new point, or the curve that you want to attach it to..." ) );
00301 }
00302
00303 PointConstructMode::~PointConstructMode()
00304 {
00305 }
00306
00307 void PointConstructMode::leftClickedObject(
00308 ObjectHolder*, const QPoint&, KigWidget& w, bool )
00309 {
00310 mdoc.addObject( new ObjectHolder( mpt.get() ) );
00311 w.redrawScreen( std::vector<ObjectHolder*>() );
00312
00313 mdoc.emitStatusBarText( QString() );
00314 mdoc.doneMode( this );
00315 }
00316
00317 void PointConstructMode::midClicked( const QPoint& p, KigWidget& w )
00318 {
00319 leftClickedObject( 0, p, w, true );
00320 }
00321
00322 void PointConstructMode::rightClicked( const std::vector<ObjectHolder*>&, const QPoint&,
00323 KigWidget& )
00324 {
00325
00326 }
00327
00328 void PointConstructMode::mouseMoved(
00329 const std::vector<ObjectHolder*>&,
00330 const QPoint& p,
00331 KigWidget& w,
00332 bool shiftpressed )
00333 {
00334 w.updateCurPix();
00335 KigPainter pter( w.screenInfo(), &w.curPix, mdoc.document() );
00336
00337 Coordinate ncoord = w.fromScreen( p );
00338 if ( shiftpressed )
00339 ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w );
00340
00341 redefinePoint( mpt.get(), ncoord, mdoc.document(), w );
00342
00343 ObjectDrawer d;
00344 d.draw( *mpt->imp(), pter, true );
00345 w.setCursor( Qt::BlankCursor );
00346
00347 w.updateWidget( pter.overlay() );
00348 }
00349
00350 void BaseConstructMode::enableActions()
00351 {
00352 BaseMode::enableActions();
00353
00354 mdoc.aCancelConstruction->setEnabled( true );
00355 }
00356
00357 void BaseConstructMode::cancelConstruction()
00358 {
00359 finish();
00360 }
00361
00362 void PointConstructMode::enableActions()
00363 {
00364 BaseMode::enableActions();
00365
00366 mdoc.aCancelConstruction->setEnabled( true );
00367 }
00368
00369 void PointConstructMode::cancelConstruction()
00370 {
00371 mdoc.doneMode( this );
00372 }
00373
00374 void BaseConstructMode::selectObjects( const std::vector<ObjectHolder*>& os, KigWidget& w )
00375 {
00376 for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
00377 {
00378 std::vector<ObjectCalcer*> args = getCalcers( mparents );
00379 assert( wantArgs( args, mdoc.document(), w ) != ArgsParser::Complete );
00380 selectObject( *i, w );
00381 };
00382 }
00383
00384 void ConstructMode::handlePrelim( const std::vector<ObjectCalcer*>& args, const QPoint& p, KigPainter& pter, KigWidget& w )
00385 {
00386
00387 QPoint textloc = p;
00388 textloc.setX( textloc.x() + 15 );
00389
00390 mctor->handlePrelim( pter, args, mdoc.document(), w );
00391
00392 QString o = mctor->useText( *args.back(), args, mdoc.document(), w );
00393 pter.drawTextStd( textloc, o );
00394 }
00395
00396 int ConstructMode::isAlreadySelectedOK( const std::vector<ObjectCalcer*>& os,
00397 const int& pos )
00398 {
00399 return mctor->isAlreadySelectedOK( os, pos );
00400 }
00401
00402 int ConstructMode::wantArgs( const std::vector<ObjectCalcer*>& os, KigDocument& d, KigWidget& w )
00403 {
00404 return mctor->wantArgs( os, d, w );
00405 }
00406
00407 void BaseConstructMode::finish()
00408 {
00409 mdoc.doneMode( this );
00410 }
00411
00412 ConstructMode::ConstructMode( KigPart& d, const ObjectConstructor* ctor )
00413 : BaseConstructMode( d ), mctor( ctor )
00414 {
00415 }
00416
00417 ConstructMode::~ConstructMode()
00418 {
00419 }
00420
00421
00422 static const bool test_has_frame_dflt = true;
00423
00424 void TestConstructMode::handlePrelim( const std::vector<ObjectCalcer*>& os, const QPoint& p, KigPainter& pter, KigWidget& w )
00425 {
00426 Args args;
00427 std::transform( os.begin(), os.end(), std::back_inserter( args ),
00428 std::mem_fun( &ObjectCalcer::imp ) );
00429
00430
00431 QString usetext = i18n( mtype->argsParser().usetext( args.back(), args ).c_str() );
00432 QPoint textloc = p;
00433 textloc.setX( textloc.x() + 15 );
00434 pter.drawTextStd( textloc, usetext );
00435
00436
00437 ObjectImp* data = mtype->calc( args, mdoc.document() );
00438 if ( ! data->valid() ) return;
00439 assert( data->inherits( TestResultImp::stype() ) );
00440 QString outputtext = static_cast<TestResultImp*>( data )->data();
00441 TextImp ti( outputtext, w.fromScreen( p + QPoint( - 40, 30 ) ), test_has_frame_dflt );
00442 ti.draw( pter );
00443
00444 delete data;
00445 }
00446
00447 TestConstructMode::TestConstructMode( KigPart& d, const ArgsParserObjectType* type )
00448 : BaseConstructMode( d ), mtype( type )
00449 {
00450 }
00451
00452 TestConstructMode::~TestConstructMode()
00453 {
00454 }
00455
00456 void ConstructMode::handleArgs( const std::vector<ObjectCalcer*>& args, KigWidget& w )
00457 {
00458 mctor->handleArgs( args, mdoc, w );
00459 finish();
00460 }
00461
00462 int TestConstructMode::isAlreadySelectedOK( const std::vector<ObjectCalcer*>&,
00463 const int& )
00464 {
00465 return false;
00466 }
00467
00468 int TestConstructMode::wantArgs( const std::vector<ObjectCalcer*>& os, KigDocument&, KigWidget& )
00469 {
00470 return mtype->argsParser().check( os );
00471 }
00472
00473 void TestConstructMode::handleArgs( const std::vector<ObjectCalcer*>& args, KigWidget& )
00474 {
00475 mresult = new ObjectTypeCalcer( mtype, args );
00476 mresult->calc( mdoc.document() );
00477 mdoc.emitStatusBarText( i18n( "Now select the location for the result label." ) );
00478 }
00479
00480 void TestConstructMode::leftClickedObject( ObjectHolder* o, const QPoint& p,
00481 KigWidget& w, bool ctrlOrShiftDown )
00482 {
00483 if ( mresult ) {
00484 QPoint qloc = p + QPoint( -40, 0 );
00485 Coordinate loc = w.fromScreen( qloc );
00486
00487 std::vector<ObjectCalcer*> parents;
00488 parents.push_back( new ObjectConstCalcer( new IntImp( test_has_frame_dflt ) ) );
00489 parents.push_back( new ObjectConstCalcer( new PointImp( loc ) ) );
00490 parents.push_back( new ObjectConstCalcer( new StringImp( QString::fromLatin1( "%1" ) ) ) );
00491 assert( mresult->imp()->inherits( TestResultImp::stype() ) );
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 parents.push_back( mresult.get() );
00507
00508 ObjectCalcer* ret = new ObjectTypeCalcer( TextType::instance(), parents );
00509 ret->calc( mdoc.document() );
00510 mdoc.addObject( new ObjectHolder( ret ) );
00511
00512 w.unsetCursor();
00513 mdoc.emitStatusBarText( QString() );
00514
00515 finish();
00516 }
00517 else
00518 BaseConstructMode::leftClickedObject( o, p, w, ctrlOrShiftDown );
00519 }
00520
00521 void TestConstructMode::midClicked( const QPoint& p, KigWidget& w )
00522 {
00523 if ( mresult ) {
00524
00525 }
00526 else
00527 BaseConstructMode::midClicked( p, w );
00528 }
00529
00530 void TestConstructMode::rightClicked( const std::vector<ObjectHolder*>& oco, const QPoint& p, KigWidget& w )
00531 {
00532 if ( mresult ) {
00533
00534 }
00535 else
00536 BaseConstructMode::rightClicked( oco, p, w );
00537 }
00538
00539 void TestConstructMode::mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p, KigWidget& w, bool shiftPressed )
00540 {
00541 if ( mresult ) {
00542 w.setCursor( Qt::BlankCursor );
00543
00544 w.updateCurPix();
00545 KigPainter pter( w.screenInfo(), &w.curPix, mdoc.document() );
00546
00547 QPoint qloc = p + QPoint( -40, 0 );
00548 Coordinate loc = w.fromScreen( qloc );
00549 assert( dynamic_cast<const TestResultImp*>( mresult->imp() ) );
00550 TextImp ti( static_cast<const TestResultImp*>( mresult->imp() )->data(), loc, test_has_frame_dflt );
00551 ObjectDrawer d;
00552 d.draw( ti, pter, false );
00553
00554
00555 w.updateWidget( pter.overlay() );
00556 }
00557 else
00558 BaseConstructMode::mouseMoved( os, p, w, shiftPressed );
00559 }
00560
00561 QString ConstructMode::selectStatement( const std::vector<ObjectCalcer*>& args, const KigWidget& w )
00562 {
00563 return mctor->selectStatement( args, mdoc.document(), w );
00564 }
00565
00566 QString TestConstructMode::selectStatement( const std::vector<ObjectCalcer*>& sel, const KigWidget& )
00567 {
00568 using namespace std;
00569 Args args;
00570 transform( sel.begin(), sel.end(), back_inserter( args ), mem_fun( &ObjectCalcer::imp ) );
00571
00572 std::string ret = mtype->argsParser().selectStatement( args );
00573 if ( ret.empty() ) return QString();
00574 return i18n( ret.c_str() );
00575 }
00576
00577 void PointConstructMode::redrawScreen( KigWidget* w )
00578 {
00579 w->redrawScreen( std::vector<ObjectHolder*>() );
00580 }
00581
00582 void BaseConstructMode::redrawScreen( KigWidget* w )
00583 {
00584 w->redrawScreen( std::vector<ObjectHolder*>() );
00585 }