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.
246 lines
8.3 KiB
246 lines
8.3 KiB
// Copyright (C) 2002 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 "moving.h"
|
|
|
|
#include "normal.h"
|
|
|
|
#include "../objects/object_imp.h"
|
|
#include "../objects/object_factory.h"
|
|
#include "../kig/kig_document.h"
|
|
#include "../kig/kig_part.h"
|
|
#include "../kig/kig_view.h"
|
|
#include "../kig/kig_commands.h"
|
|
#include "../misc/kigpainter.h"
|
|
#include "../misc/calcpaths.h"
|
|
#include "../misc/coordinate_system.h"
|
|
|
|
#include <qevent.h>
|
|
|
|
#include <functional>
|
|
#include <algorithm>
|
|
#include <map>
|
|
|
|
void MovingModeBase::initScreen( const std::vector<ObjectCalcer*>& in )
|
|
{
|
|
mcalcable = in;
|
|
std::set<ObjectCalcer*> calcableset( mcalcable.begin(), mcalcable.end() );
|
|
|
|
// don't try to move objects that have been deleted from the
|
|
// document or internal objects that the user is not aware of..
|
|
std::vector<ObjectHolder*> docobjs = mdoc.document().objects();
|
|
for ( std::vector<ObjectHolder*>::iterator i = docobjs.begin();
|
|
i != docobjs.end(); ++i )
|
|
if ( calcableset.find( ( *i )->calcer() ) != calcableset.end() )
|
|
mdrawable.push_back( *i );
|
|
|
|
std::set<ObjectHolder*> docobjsset( docobjs.begin(), docobjs.end() );
|
|
std::set<ObjectHolder*> drawableset( mdrawable.begin(), mdrawable.end() );
|
|
std::set<ObjectHolder*> notmovingobjs;
|
|
std::set_difference( docobjsset.begin(), docobjsset.end(), drawableset.begin(), drawableset.end(),
|
|
std::inserter( notmovingobjs, notmovingobjs.begin() ) );
|
|
|
|
mview.clearStillPix();
|
|
KigPainter p( mview.screenInfo(), &mview.stillPix, mdoc.document() );
|
|
p.drawGrid( mdoc.document().coordinateSystem(), mdoc.document().grid(),
|
|
mdoc.document().axes() );
|
|
p.drawObjects( notmovingobjs.begin(), notmovingobjs.end(), false );
|
|
mview.updateCurPix();
|
|
|
|
KigPainter p2( mview.screenInfo(), &mview.curPix, mdoc.document() );
|
|
p2.drawObjects( drawableset.begin(), drawableset.end(), true );
|
|
}
|
|
|
|
void MovingModeBase::leftReleased( QMouseEvent*, KigWidget* v )
|
|
{
|
|
// clean up after ourselves:
|
|
for ( std::vector<ObjectCalcer*>::iterator i = mcalcable.begin();
|
|
i != mcalcable.end(); ++i )
|
|
( *i )->calc( mdoc.document() );
|
|
stopMove();
|
|
mdoc.setModified( true );
|
|
|
|
// refresh the screen:
|
|
v->redrawScreen( std::vector<ObjectHolder*>() );
|
|
v->updateScrollBars();
|
|
|
|
mdoc.doneMode( this );
|
|
}
|
|
|
|
void MovingModeBase::mouseMoved( QMouseEvent* e, KigWidget* v )
|
|
{
|
|
v->updateCurPix();
|
|
Coordinate c = v->fromScreen( e->pos() );
|
|
|
|
bool snaptogrid = e->state() & Qt::ShiftButton;
|
|
moveTo( c, snaptogrid );
|
|
for ( std::vector<ObjectCalcer*>::iterator i = mcalcable.begin();
|
|
i != mcalcable.end(); ++i )
|
|
( *i )->calc( mdoc.document() );
|
|
KigPainter p( v->screenInfo(), &v->curPix, mdoc.document() );
|
|
// TODO: only draw the explicitly moving objects as selected, the
|
|
// other ones as deselected.. Needs some support from the
|
|
// subclasses..
|
|
p.drawObjects( mdrawable, true );
|
|
v->updateWidget( p.overlay() );
|
|
v->updateScrollBars();
|
|
}
|
|
|
|
class MovingMode::Private
|
|
{
|
|
public:
|
|
// explicitly moving objects: these are the objects that the user
|
|
// requested to move...
|
|
std::vector<ObjectCalcer*> emo;
|
|
// point where we started moving..
|
|
Coordinate pwwsm;
|
|
MonitorDataObjects* mon;
|
|
// we keep a map from the emo objects to their reference location.
|
|
// This is the location that they claim to be at before moving
|
|
// starts, and we use it as a reference point to determine where
|
|
// they should move next..
|
|
std::map<const ObjectCalcer*, Coordinate> refmap;
|
|
};
|
|
|
|
MovingMode::MovingMode( const std::vector<ObjectHolder*>& os, const Coordinate& c,
|
|
KigWidget& v, KigPart& doc )
|
|
: MovingModeBase( doc, v ), d( new Private )
|
|
{
|
|
d->pwwsm = c;
|
|
std::vector<ObjectCalcer*> emo;
|
|
std::set<ObjectCalcer*> objs;
|
|
for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
|
|
if ( (*i)->canMove() )
|
|
{
|
|
emo.push_back( ( *i )->calcer() );
|
|
d->refmap[( *i )->calcer()] = (*i)->moveReferencePoint();
|
|
objs.insert( ( *i )->calcer() );
|
|
std::vector<ObjectCalcer*> parents = ( *i )->calcer()->movableParents();
|
|
objs.insert( parents.begin(), parents.end() );
|
|
};
|
|
|
|
emo = calcPath( emo );
|
|
for ( std::vector<ObjectCalcer*>::const_iterator i = emo.begin(); i != emo.end(); ++i )
|
|
if ( !isChild( *i, d->emo ) )
|
|
d->emo.push_back( *i );
|
|
|
|
d->mon = new MonitorDataObjects( std::vector<ObjectCalcer*>( objs.begin(),objs.end() ) );
|
|
|
|
std::set<ObjectCalcer*> tmp = objs;
|
|
for ( std::set<ObjectCalcer*>::const_iterator i = tmp.begin(); i != tmp.end(); ++i )
|
|
{
|
|
std::set<ObjectCalcer*> children = getAllChildren(*i);
|
|
objs.insert( children.begin(), children.end() );
|
|
}
|
|
|
|
initScreen( calcPath( std::vector<ObjectCalcer*>( objs.begin(), objs.end() ) ) );
|
|
}
|
|
|
|
void MovingMode::stopMove()
|
|
{
|
|
QString text = d->emo.size() == 1 ?
|
|
d->emo[0]->imp()->type()->moveAStatement() :
|
|
i18n( "Move %1 Objects" ).arg( d->emo.size() );
|
|
KigCommand* mc = new KigCommand( mdoc, text );
|
|
d->mon->finish( mc );
|
|
mdoc.history()->addCommand( mc );
|
|
}
|
|
|
|
void MovingMode::moveTo( const Coordinate& o, bool snaptogrid )
|
|
{
|
|
for( std::vector<ObjectCalcer*>::iterator i = d->emo.begin(); i != d->emo.end(); ++i )
|
|
{
|
|
assert( d->refmap.find( *i ) != d->refmap.end() );
|
|
Coordinate nc = d->refmap[*i] + ( o - d->pwwsm );
|
|
if ( snaptogrid ) nc = mdoc.document().coordinateSystem().snapToGrid( nc, mview );
|
|
(*i)->move( nc, mdoc.document() );
|
|
};
|
|
}
|
|
|
|
PointRedefineMode::PointRedefineMode( ObjectHolder* p, KigPart& d, KigWidget& v )
|
|
: MovingModeBase( d, v ), mp( p ), mmon( 0 )
|
|
{
|
|
assert( dynamic_cast<ObjectTypeCalcer*>( p->calcer() ) );
|
|
moldtype = static_cast<ObjectTypeCalcer*>( p->calcer() )->type();
|
|
std::vector<ObjectCalcer*> oldparents = p->calcer()->parents();
|
|
std::copy( oldparents.begin(), oldparents.end(), std::back_inserter( moldparents ) );
|
|
|
|
std::vector<ObjectCalcer*> parents = getAllParents( mp->calcer() );
|
|
mmon = new MonitorDataObjects( parents );
|
|
std::vector<ObjectCalcer*> moving = parents;
|
|
std::set<ObjectCalcer*> children = getAllChildren( mp->calcer() );
|
|
std::copy( children.begin(), children.end(), std::back_inserter( moving ) );
|
|
initScreen( moving );
|
|
}
|
|
|
|
void PointRedefineMode::moveTo( const Coordinate& o, bool snaptogrid )
|
|
{
|
|
Coordinate realo =
|
|
snaptogrid ? mdoc.document().coordinateSystem().snapToGrid( o, mview ) : o;
|
|
ObjectFactory::instance()->redefinePoint(
|
|
static_cast<ObjectTypeCalcer*>( mp->calcer() ), realo, mdoc.document(), mview );
|
|
}
|
|
|
|
PointRedefineMode::~PointRedefineMode()
|
|
{
|
|
}
|
|
|
|
MovingModeBase::MovingModeBase( KigPart& doc, KigWidget& v )
|
|
: KigMode( doc ), mview( v )
|
|
{
|
|
}
|
|
|
|
MovingModeBase::~MovingModeBase()
|
|
{
|
|
}
|
|
|
|
void MovingModeBase::leftMouseMoved( QMouseEvent* e, KigWidget* v )
|
|
{
|
|
mouseMoved( e, v );
|
|
}
|
|
|
|
MovingMode::~MovingMode()
|
|
{
|
|
delete d->mon;
|
|
delete d;
|
|
}
|
|
|
|
void PointRedefineMode::stopMove()
|
|
{
|
|
assert( dynamic_cast<ObjectTypeCalcer*>( mp->calcer() ) );
|
|
ObjectTypeCalcer* mpcalc = static_cast<ObjectTypeCalcer*>( mp->calcer() );
|
|
|
|
std::vector<ObjectCalcer*> newparents = mpcalc->parents();
|
|
std::vector<ObjectCalcer::shared_ptr> newparentsref(
|
|
newparents.begin(), newparents.end() );
|
|
const ObjectType* newtype = mpcalc->type();
|
|
|
|
std::vector<ObjectCalcer*> oldparents;
|
|
for( std::vector<ObjectCalcer::shared_ptr>::iterator i = moldparents.begin();
|
|
i != moldparents.end(); ++i )
|
|
oldparents.push_back( i->get() );
|
|
mpcalc->setType( moldtype );
|
|
mpcalc->setParents( oldparents );
|
|
mp->calc( mdoc.document() );
|
|
|
|
KigCommand* command = new KigCommand( mdoc, i18n( "Redefine Point" ) );
|
|
command->addTask(
|
|
new ChangeParentsAndTypeTask( mpcalc, newparents, newtype ) );
|
|
mmon->finish( command );
|
|
mdoc.history()->addCommand( command );
|
|
}
|