You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
573 lines
17 KiB
573 lines
17 KiB
// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
// 02110-1301, USA.
|
|
|
|
#include "construct_mode.h"
|
|
|
|
#include "../objects/object_factory.h"
|
|
#include "../objects/object_drawer.h"
|
|
#include "../objects/text_type.h"
|
|
#include "../objects/text_imp.h"
|
|
#include "../objects/bogus_imp.h"
|
|
#include "../objects/point_imp.h"
|
|
#include "../misc/argsparser.h"
|
|
|
|
#include "../kig/kig_document.h"
|
|
#include "../kig/kig_part.h"
|
|
#include "../kig/kig_view.h"
|
|
#include "../misc/object_constructor.h"
|
|
#include "../misc/coordinate_system.h"
|
|
#include "../misc/kigpainter.h"
|
|
#include "../misc/calcpaths.h"
|
|
|
|
#include "popup.h"
|
|
|
|
#include <kcursor.h>
|
|
#include <tdeaction.h>
|
|
|
|
#include <algorithm>
|
|
#include <functional>
|
|
|
|
static void redefinePoint( ObjectTypeCalcer* mpt, const Coordinate& c, KigDocument& doc, const KigWidget& w )
|
|
{
|
|
ObjectFactory::instance()->redefinePoint( mpt, c, doc, w );
|
|
mpt->calc( doc );
|
|
}
|
|
|
|
BaseConstructMode::BaseConstructMode( KigPart& d )
|
|
: BaseMode( d )
|
|
{
|
|
mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate( 0, 0 ) );
|
|
mpt->calc( d.document() );
|
|
mcursor = ObjectFactory::instance()->cursorPointCalcer( Coordinate( 0, 0 ) );
|
|
mcursor->calc( d.document() );
|
|
// mcursorholder = new ObjectHolder( mcursor );
|
|
}
|
|
|
|
BaseConstructMode::~BaseConstructMode()
|
|
{
|
|
delete mcursor;
|
|
// delete mcursorholder;
|
|
}
|
|
|
|
void BaseConstructMode::leftReleased( TQMouseEvent* e, KigWidget* v )
|
|
{
|
|
if( (pointLocation() - e->pos()).manhattanLength() > 4 ) return;
|
|
|
|
ObjectHolder* o = 0;
|
|
bool keyCtrlOrShift = ( e->state() & ( ControlButton | ShiftButton) ) != 0;
|
|
std::vector<ObjectHolder*> moco = oco();
|
|
if ( ! moco.empty() )
|
|
{
|
|
std::vector<ObjectHolder*> goodargs;
|
|
if ( !moco.empty() )
|
|
{
|
|
std::vector<ObjectHolder*>::const_iterator it;
|
|
std::vector<ObjectCalcer*> testargs = getCalcers( mparents );
|
|
for ( std::vector<ObjectHolder*>::const_iterator i = moco.begin(); i != moco.end(); ++i )
|
|
{
|
|
it = std::find( mparents.begin(), mparents.end(), *i );
|
|
bool newdup =
|
|
( it == mparents.end() ) ||
|
|
isAlreadySelectedOK( testargs, it - mparents.begin() );
|
|
if ( newdup )
|
|
{
|
|
testargs.push_back( ( *i )->calcer() );
|
|
if ( wantArgs( testargs, mdoc.document(), *v ) )
|
|
goodargs.push_back( *i );
|
|
testargs.pop_back();
|
|
}
|
|
}
|
|
int id = ObjectChooserPopup::getObjectFromList( e->pos(), v, goodargs );
|
|
if ( id >= 0 )
|
|
o = goodargs[id];
|
|
}
|
|
}
|
|
leftClickedObject( o, e->pos(), *v, keyCtrlOrShift );
|
|
KigMode::leftReleased( e, v );
|
|
}
|
|
|
|
void BaseConstructMode::leftClickedObject(
|
|
ObjectHolder* o, const TQPoint& p, KigWidget& w, bool )
|
|
{
|
|
std::vector<ObjectHolder*>::iterator it = std::find( mparents.begin(), mparents.end(), o );
|
|
std::vector<ObjectCalcer*> nargs = getCalcers( mparents );
|
|
//
|
|
// mp: duplicationchecked controls whether the arguments list is
|
|
// free of duplications or if a duplication is safe (asking this to
|
|
// the Constructor class through the "isAlreadySelectedOK" method).
|
|
//
|
|
bool duplicationchecked =
|
|
( it == mparents.end() ) ||
|
|
isAlreadySelectedOK( nargs, it - mparents.begin() );
|
|
if ( o && duplicationchecked )
|
|
{
|
|
nargs.push_back( o->calcer() );
|
|
if ( wantArgs( nargs, mdoc.document(), w ) )
|
|
{
|
|
selectObject( o, w );
|
|
return;
|
|
}
|
|
}
|
|
|
|
nargs = getCalcers( mparents );
|
|
nargs.push_back( mpt.get() );
|
|
if ( wantArgs( nargs, mdoc.document(), w ) )
|
|
{
|
|
// add mpt to the document..
|
|
ObjectHolder* n = new ObjectHolder( mpt.get() );
|
|
mdoc.addObject( n );
|
|
selectObject( n, w );
|
|
// get a new mpt for our further use..
|
|
mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w );
|
|
mpt->calc( mdoc.document() );
|
|
return;
|
|
}
|
|
|
|
nargs = getCalcers( mparents );
|
|
nargs.push_back( mcursor );
|
|
|
|
if ( wantArgs( nargs, mdoc.document(), w ) )
|
|
{
|
|
// DON'T add mpt to the document..
|
|
// the objectholder has been constructed once and for all
|
|
// when entering construction mode, and delete in the
|
|
// destructor.
|
|
ObjectHolder* n = new ObjectHolder( mcursor );
|
|
selectObject( n, w );
|
|
mcursor = ObjectFactory::instance()->cursorPointCalcer( w.fromScreen( p ) );
|
|
// mcursor = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w );
|
|
mcursor->calc( mdoc.document() );
|
|
delete n;
|
|
}
|
|
}
|
|
|
|
void BaseConstructMode::midClicked( const TQPoint& p, KigWidget& w )
|
|
{
|
|
std::vector<ObjectCalcer*> args = getCalcers( mparents );
|
|
args.push_back( mpt.get() );
|
|
if ( wantArgs( args, mdoc.document(), w ) )
|
|
{
|
|
ObjectHolder* n = new ObjectHolder( mpt.get() );
|
|
mdoc.addObject( n );
|
|
|
|
selectObject( n, w );
|
|
|
|
mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w );
|
|
mpt->calc( mdoc.document() );
|
|
}
|
|
}
|
|
|
|
void BaseConstructMode::rightClicked( const std::vector<ObjectHolder*>&, const TQPoint&, KigWidget& )
|
|
{
|
|
// TODO ?
|
|
}
|
|
|
|
void BaseConstructMode::mouseMoved( const std::vector<ObjectHolder*>& os, const TQPoint& p,
|
|
KigWidget& w, bool shiftpressed )
|
|
{
|
|
mdoc.emitStatusBarText( selectStatement( getCalcers( mparents ), w ) );
|
|
|
|
w.updateCurPix();
|
|
KigPainter pter( w.screenInfo(), &w.curPix, mdoc.document() );
|
|
|
|
Coordinate ncoord = w.fromScreen( p );
|
|
if ( shiftpressed )
|
|
ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w );
|
|
|
|
redefinePoint( mpt.get(), ncoord, mdoc.document(), w );
|
|
mcursor->move( ncoord, mdoc.document() );
|
|
mcursor->calc( mdoc.document() );
|
|
|
|
std::vector<ObjectCalcer*> args = getCalcers( mparents );
|
|
bool duplicationchecked = false;
|
|
std::vector<ObjectHolder*> goodargs;
|
|
if ( ! os.empty() )
|
|
{
|
|
std::vector<ObjectHolder*>::const_iterator it;
|
|
std::vector<ObjectCalcer*> testargs = getCalcers( mparents );
|
|
for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
|
|
{
|
|
it = std::find( mparents.begin(), mparents.end(), *i );
|
|
bool newdup =
|
|
( it == mparents.end() ) ||
|
|
isAlreadySelectedOK( args, it - mparents.begin() );
|
|
if ( newdup )
|
|
{
|
|
testargs.push_back( ( *i )->calcer() );
|
|
if ( wantArgs( testargs, mdoc.document(), w ) )
|
|
goodargs.push_back( *i );
|
|
testargs.pop_back();
|
|
}
|
|
duplicationchecked |= newdup;
|
|
}
|
|
}
|
|
bool calcnow = ( goodargs.size() == 1 ) || ( ( goodargs.size() > 0 ) && ( goodargs.front()->imp()->inherits( PointImp::stype() ) ) );
|
|
if ( calcnow )
|
|
{
|
|
args.push_back( goodargs.front()->calcer() );
|
|
}
|
|
|
|
if ( !os.empty() && duplicationchecked && calcnow )
|
|
{
|
|
handlePrelim( args, p, pter, w );
|
|
|
|
w.setCursor( KCursor::handCursor() );
|
|
}
|
|
else
|
|
{
|
|
std::vector<ObjectCalcer*> args = getCalcers( mparents );
|
|
args.push_back( mpt.get() );
|
|
std::vector<ObjectCalcer*> argscursor = getCalcers( mparents );
|
|
argscursor.push_back( mcursor );
|
|
bool text = true;
|
|
if ( wantArgs( args, mdoc.document(), w ) )
|
|
{
|
|
ObjectDrawer d;
|
|
d.draw( *mpt->imp(), pter, true );
|
|
|
|
handlePrelim( args, p, pter, w );
|
|
|
|
w.setCursor( KCursor::handCursor() );
|
|
}
|
|
else if ( wantArgs( argscursor, mdoc.document(), w ) )
|
|
{
|
|
ObjectDrawer d;
|
|
// d.draw( *mcursor->imp(), pter, true );
|
|
|
|
handlePrelim( argscursor, p, pter, w );
|
|
|
|
w.setCursor( KCursor::crossCursor() );
|
|
}
|
|
else
|
|
{
|
|
w.setCursor( KCursor::arrowCursor() );
|
|
text = false;
|
|
}
|
|
if ( !text && ( goodargs.size() > 1 ) )
|
|
{
|
|
TQString strwhich = i18n( "Which object?" );
|
|
mdoc.emitStatusBarText( strwhich );
|
|
|
|
TQPoint textloc = p;
|
|
textloc.setX( textloc.x() + 15 );
|
|
pter.drawTextStd( textloc, strwhich );
|
|
|
|
w.setCursor( KCursor::handCursor() );
|
|
}
|
|
}
|
|
w.updateWidget( pter.overlay() );
|
|
}
|
|
|
|
void BaseConstructMode::selectObject( ObjectHolder* o, KigWidget& w )
|
|
{
|
|
mparents.push_back( o );
|
|
std::vector<ObjectCalcer*> args = getCalcers( mparents );
|
|
|
|
if ( wantArgs( args, mdoc.document(), w ) == ArgsParser::Complete )
|
|
{
|
|
handleArgs( args, w );
|
|
};
|
|
|
|
w.redrawScreen( mparents );
|
|
}
|
|
|
|
PointConstructMode::PointConstructMode( KigPart& d )
|
|
: BaseMode( d )
|
|
{
|
|
// we add the data objects to the document cause
|
|
// ObjectFactory::redefinePoint does that too, and this way, we can
|
|
// depend on them already being known by the doc when we add the
|
|
// mpt..
|
|
mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate() );
|
|
mpt->calc( d.document() );
|
|
|
|
mdoc.emitStatusBarText( i18n( "Click the location where you want to place the new point, or the curve that you want to attach it to..." ) );
|
|
}
|
|
|
|
PointConstructMode::~PointConstructMode()
|
|
{
|
|
}
|
|
|
|
void PointConstructMode::leftClickedObject(
|
|
ObjectHolder*, const TQPoint&, KigWidget& w, bool )
|
|
{
|
|
mdoc.addObject( new ObjectHolder( mpt.get() ) );
|
|
w.redrawScreen( std::vector<ObjectHolder*>() );
|
|
|
|
mdoc.emitStatusBarText( TQString() );
|
|
mdoc.doneMode( this );
|
|
}
|
|
|
|
void PointConstructMode::midClicked( const TQPoint& p, KigWidget& w )
|
|
{
|
|
leftClickedObject( 0, p, w, true );
|
|
}
|
|
|
|
void PointConstructMode::rightClicked( const std::vector<ObjectHolder*>&, const TQPoint&,
|
|
KigWidget& )
|
|
{
|
|
// TODO ?
|
|
}
|
|
|
|
void PointConstructMode::mouseMoved(
|
|
const std::vector<ObjectHolder*>&,
|
|
const TQPoint& p,
|
|
KigWidget& w,
|
|
bool shiftpressed )
|
|
{
|
|
w.updateCurPix();
|
|
KigPainter pter( w.screenInfo(), &w.curPix, mdoc.document() );
|
|
|
|
Coordinate ncoord = w.fromScreen( p );
|
|
if ( shiftpressed )
|
|
ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w );
|
|
|
|
redefinePoint( mpt.get(), ncoord, mdoc.document(), w );
|
|
|
|
ObjectDrawer d;
|
|
d.draw( *mpt->imp(), pter, true );
|
|
w.setCursor( KCursor::blankCursor() );
|
|
|
|
w.updateWidget( pter.overlay() );
|
|
}
|
|
|
|
void BaseConstructMode::enableActions()
|
|
{
|
|
BaseMode::enableActions();
|
|
|
|
mdoc.aCancelConstruction->setEnabled( true );
|
|
}
|
|
|
|
void BaseConstructMode::cancelConstruction()
|
|
{
|
|
finish();
|
|
}
|
|
|
|
void PointConstructMode::enableActions()
|
|
{
|
|
BaseMode::enableActions();
|
|
|
|
mdoc.aCancelConstruction->setEnabled( true );
|
|
}
|
|
|
|
void PointConstructMode::cancelConstruction()
|
|
{
|
|
mdoc.doneMode( this );
|
|
}
|
|
|
|
void BaseConstructMode::selectObjects( const std::vector<ObjectHolder*>& os, KigWidget& w )
|
|
{
|
|
for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
|
|
{
|
|
std::vector<ObjectCalcer*> args = getCalcers( mparents );
|
|
assert( wantArgs( args, mdoc.document(), w ) != ArgsParser::Complete );
|
|
selectObject( *i, w );
|
|
};
|
|
}
|
|
|
|
void ConstructMode::handlePrelim( const std::vector<ObjectCalcer*>& args, const TQPoint& p, KigPainter& pter, KigWidget& w )
|
|
{
|
|
// set the text next to the arrow cursor like in modes/normal.cpp
|
|
TQPoint textloc = p;
|
|
textloc.setX( textloc.x() + 15 );
|
|
|
|
mctor->handlePrelim( pter, args, mdoc.document(), w );
|
|
|
|
TQString o = mctor->useText( *args.back(), args, mdoc.document(), w );
|
|
pter.drawTextStd( textloc, o );
|
|
}
|
|
|
|
int ConstructMode::isAlreadySelectedOK( const std::vector<ObjectCalcer*>& os,
|
|
const int& pos )
|
|
{
|
|
return mctor->isAlreadySelectedOK( os, pos );
|
|
}
|
|
|
|
int ConstructMode::wantArgs( const std::vector<ObjectCalcer*>& os, KigDocument& d, KigWidget& w )
|
|
{
|
|
return mctor->wantArgs( os, d, w );
|
|
}
|
|
|
|
void BaseConstructMode::finish()
|
|
{
|
|
mdoc.doneMode( this );
|
|
}
|
|
|
|
ConstructMode::ConstructMode( KigPart& d, const ObjectConstructor* ctor )
|
|
: BaseConstructMode( d ), mctor( ctor )
|
|
{
|
|
}
|
|
|
|
ConstructMode::~ConstructMode()
|
|
{
|
|
}
|
|
|
|
// does a test result have a frame by default ?
|
|
static const bool test_has_frame_dflt = true;
|
|
|
|
void TestConstructMode::handlePrelim( const std::vector<ObjectCalcer*>& os, const TQPoint& p, KigPainter& pter, KigWidget& w )
|
|
{
|
|
Args args;
|
|
std::transform( os.begin(), os.end(), std::back_inserter( args ),
|
|
std::mem_fn( &ObjectCalcer::imp ) );
|
|
|
|
// usetext
|
|
TQString usetext = i18n( mtype->argsParser().usetext( args.back(), args ).c_str() );
|
|
TQPoint textloc = p;
|
|
textloc.setX( textloc.x() + 15 );
|
|
pter.drawTextStd( textloc, usetext );
|
|
|
|
// test result
|
|
ObjectImp* data = mtype->calc( args, mdoc.document() );
|
|
if ( ! data->valid() ) return;
|
|
assert( data->inherits( TestResultImp::stype() ) );
|
|
TQString outputtext = static_cast<TestResultImp*>( data )->data();
|
|
TextImp ti( outputtext, w.fromScreen( p + TQPoint( - 40, 30 ) ), test_has_frame_dflt );
|
|
ti.draw( pter );
|
|
|
|
delete data;
|
|
}
|
|
|
|
TestConstructMode::TestConstructMode( KigPart& d, const ArgsParserObjectType* type )
|
|
: BaseConstructMode( d ), mtype( type )
|
|
{
|
|
}
|
|
|
|
TestConstructMode::~TestConstructMode()
|
|
{
|
|
}
|
|
|
|
void ConstructMode::handleArgs( const std::vector<ObjectCalcer*>& args, KigWidget& w )
|
|
{
|
|
mctor->handleArgs( args, mdoc, w );
|
|
finish();
|
|
}
|
|
|
|
int TestConstructMode::isAlreadySelectedOK( const std::vector<ObjectCalcer*>&,
|
|
const int& )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int TestConstructMode::wantArgs( const std::vector<ObjectCalcer*>& os, KigDocument&, KigWidget& )
|
|
{
|
|
return mtype->argsParser().check( os );
|
|
}
|
|
|
|
void TestConstructMode::handleArgs( const std::vector<ObjectCalcer*>& args, KigWidget& )
|
|
{
|
|
mresult = new ObjectTypeCalcer( mtype, args );
|
|
mresult->calc( mdoc.document() );
|
|
mdoc.emitStatusBarText( i18n( "Now select the location for the result label." ) );
|
|
}
|
|
|
|
void TestConstructMode::leftClickedObject( ObjectHolder* o, const TQPoint& p,
|
|
KigWidget& w, bool ctrlOrShiftDown )
|
|
{
|
|
if ( mresult ) {
|
|
TQPoint qloc = p + TQPoint( -40, 0 );
|
|
Coordinate loc = w.fromScreen( qloc );
|
|
|
|
std::vector<ObjectCalcer*> parents;
|
|
parents.push_back( new ObjectConstCalcer( new IntImp( test_has_frame_dflt ) ) );
|
|
parents.push_back( new ObjectConstCalcer( new PointImp( loc ) ) );
|
|
parents.push_back( new ObjectConstCalcer( new StringImp( TQString::fromLatin1( "%1" ) ) ) );
|
|
assert( mresult->imp()->inherits( TestResultImp::stype() ) );
|
|
parents.push_back(
|
|
new ObjectPropertyCalcer(
|
|
mresult.get(), mresult->imp()->propertiesInternalNames().findIndex( "test-result" ) ) );
|
|
parents.back()->calc( mdoc.document() );
|
|
|
|
ObjectCalcer* ret = new ObjectTypeCalcer( TextType::instance(), parents );
|
|
ret->calc( mdoc.document() );
|
|
mdoc.addObject( new ObjectHolder( ret ) );
|
|
|
|
w.unsetCursor();
|
|
mdoc.emitStatusBarText( TQString() );
|
|
|
|
finish();
|
|
}
|
|
else
|
|
BaseConstructMode::leftClickedObject( o, p, w, ctrlOrShiftDown );
|
|
}
|
|
|
|
void TestConstructMode::midClicked( const TQPoint& p, KigWidget& w )
|
|
{
|
|
if ( mresult ) {
|
|
// nothing to be done here, really
|
|
}
|
|
else
|
|
BaseConstructMode::midClicked( p, w );
|
|
}
|
|
|
|
void TestConstructMode::rightClicked( const std::vector<ObjectHolder*>& oco, const TQPoint& p, KigWidget& w )
|
|
{
|
|
if ( mresult ) {
|
|
// nothing to be done here, really
|
|
}
|
|
else
|
|
BaseConstructMode::rightClicked( oco, p, w );
|
|
}
|
|
|
|
void TestConstructMode::mouseMoved( const std::vector<ObjectHolder*>& os, const TQPoint& p, KigWidget& w, bool shiftPressed )
|
|
{
|
|
if ( mresult ) {
|
|
w.setCursor( KCursor::blankCursor() );
|
|
|
|
w.updateCurPix();
|
|
KigPainter pter( w.screenInfo(), &w.curPix, mdoc.document() );
|
|
|
|
TQPoint qloc = p + TQPoint( -40, 0 );
|
|
Coordinate loc = w.fromScreen( qloc );
|
|
assert( dynamic_cast<const TestResultImp*>( mresult->imp() ) );
|
|
TextImp ti( static_cast<const TestResultImp*>( mresult->imp() )->data(), loc, test_has_frame_dflt );
|
|
ObjectDrawer d;
|
|
d.draw( ti, pter, false );
|
|
|
|
|
|
w.updateWidget( pter.overlay() );
|
|
}
|
|
else
|
|
BaseConstructMode::mouseMoved( os, p, w, shiftPressed );
|
|
}
|
|
|
|
TQString ConstructMode::selectStatement( const std::vector<ObjectCalcer*>& args, const KigWidget& w )
|
|
{
|
|
return mctor->selectStatement( args, mdoc.document(), w );
|
|
}
|
|
|
|
TQString TestConstructMode::selectStatement( const std::vector<ObjectCalcer*>& sel, const KigWidget& )
|
|
{
|
|
using namespace std;
|
|
Args args;
|
|
transform( sel.begin(), sel.end(), back_inserter( args ), mem_fn( &ObjectCalcer::imp ) );
|
|
|
|
std::string ret = mtype->argsParser().selectStatement( args );
|
|
if ( ret.empty() ) return TQString();
|
|
return i18n( ret.c_str() );
|
|
}
|
|
|
|
void PointConstructMode::redrawScreen( KigWidget* w )
|
|
{
|
|
w->redrawScreen( std::vector<ObjectHolder*>() );
|
|
}
|
|
|
|
void BaseConstructMode::redrawScreen( KigWidget* w )
|
|
{
|
|
w->redrawScreen( std::vector<ObjectHolder*>() );
|
|
}
|