• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdeedu
  • Sitemap
  • Contact Us
 

kig

construct_mode.cc

Go to the documentation of this file.
00001 // Copyright (C)  2003  Dominique Devriese <devriese@kde.org>
00002 
00003 // This program is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU General Public License
00005 // as published by the Free Software Foundation; either version 2
00006 // of the License, or (at your option) any later version.
00007 
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00016 // 02110-1301, USA.
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 //  mcursorholder = new ObjectHolder( mcursor );
00060 }
00061 
00062 BaseConstructMode::~BaseConstructMode()
00063 {
00064   delete mcursor;
00065 //  delete mcursorholder;
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 // mp: duplicationchecked controls whether the arguments list is
00112 // free of duplications or if a duplication is safe (asking this to
00113 // the Constructor class through the "isAlreadySelectedOK" method).
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     // add mpt to the document..
00133     ObjectHolder* n = new ObjectHolder( mpt.get() );
00134     mdoc.addObject( n );
00135     selectObject( n, w );
00136     // get a new mpt for our further use..
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     // DON'T add mpt to the document..
00148     // the objectholder has been constructed once and for all
00149     // when entering construction mode, and delete in the
00150     // destructor.
00151     ObjectHolder* n = new ObjectHolder( mcursor );
00152     selectObject( n, w );
00153     mcursor = ObjectFactory::instance()->cursorPointCalcer( w.fromScreen( p ) );
00154 //    mcursor = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w );
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   // TODO ?
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 //      d.draw( *mcursor->imp(), pter, true );
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   // we add the data objects to the document cause
00294   // ObjectFactory::redefinePoint does that too, and this way, we can
00295   // depend on them already being known by the doc when we add the
00296   // mpt..
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   // TODO ?
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   // set the text next to the arrow cursor like in modes/normal.cc
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 // does a test result have a frame by default ?
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   // usetext
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   // test result
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 //    parents.push_back(
00493 //      new ObjectPropertyCalcer(
00494 //        mresult.get(), "test-result" ) );
00495 //    parents.back()->calc( mdoc.document() );
00496 
00497 /* (mp)
00498  * now we can refer directly to the TestResultImp, since it is also a StringImp
00499  * this creates a backward compatibility issue with kig save files: new versions of
00500  * kig can still read old saved files, but files created with the new kig version
00501  * cannot be read by old versions of kig.  This is necessary in order to allow a test
00502  * result to also carry its intrinsic boolean value and thus be used in further
00503  * constructions, e.g. as an argument to a python script.
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     // nothing to be done here, really
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     // nothing to be done here, really
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 }

kig

Skip menu "kig"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

kdeedu

Skip menu "kdeedu"
  • kalzium
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  •   docs
  •   src
  • parley
  •   stepcore
Generated for kdeedu by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal