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.
324 lines
7.4 KiB
324 lines
7.4 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 "object_calcer.h"
|
|
|
|
#include "object_holder.h"
|
|
#include "object_imp.h"
|
|
#include "object_type.h"
|
|
#include "../misc/coordinate.h"
|
|
#include "common.h"
|
|
|
|
#include <algorithm>
|
|
#include <set>
|
|
|
|
void ObjectTypeCalcer::calc( const KigDocument& doc )
|
|
{
|
|
Args a;
|
|
a.reserve( mparents.size() );
|
|
std::transform( mparents.begin(), mparents.end(),
|
|
std::back_inserter( a ), std::mem_fun( &ObjectCalcer::imp ) );
|
|
ObjectImp* n = mtype->calc( a, doc );
|
|
delete mimp;
|
|
mimp = n;
|
|
}
|
|
|
|
ObjectTypeCalcer::ObjectTypeCalcer( const ObjectType* type,
|
|
const std::vector<ObjectCalcer*>& parents, bool sort )
|
|
: mparents( ( sort )?type->sortArgs( parents ):parents ), mtype( type ), mimp( 0 )
|
|
{
|
|
std::for_each( mparents.begin(), mparents.end(),
|
|
std::bind2nd( std::mem_fun( &ObjectCalcer::addChild ), this ) );
|
|
}
|
|
|
|
ObjectCalcer::~ObjectCalcer()
|
|
{
|
|
}
|
|
|
|
ObjectConstCalcer::ObjectConstCalcer( ObjectImp* imp )
|
|
: mimp( imp )
|
|
{
|
|
}
|
|
|
|
ObjectConstCalcer::~ObjectConstCalcer()
|
|
{
|
|
delete mimp;
|
|
}
|
|
|
|
const ObjectImp* ObjectConstCalcer::imp() const
|
|
{
|
|
return mimp;
|
|
}
|
|
|
|
void ObjectConstCalcer::calc( const KigDocument& )
|
|
{
|
|
}
|
|
|
|
std::vector<ObjectCalcer*> ObjectConstCalcer::parents() const
|
|
{
|
|
// we have no parents..
|
|
return std::vector<ObjectCalcer*>();
|
|
}
|
|
|
|
void ObjectCalcer::ref()
|
|
{
|
|
++refcount;
|
|
}
|
|
|
|
void ObjectCalcer::deref()
|
|
{
|
|
if ( --refcount <= 0 ) delete this;
|
|
}
|
|
|
|
void intrusive_ptr_add_ref( ObjectCalcer* p )
|
|
{
|
|
p->ref();
|
|
}
|
|
|
|
void intrusive_ptr_release( ObjectCalcer* p )
|
|
{
|
|
p->deref();
|
|
}
|
|
|
|
const ObjectImp* ObjectTypeCalcer::imp() const
|
|
{
|
|
return mimp;
|
|
}
|
|
|
|
std::vector<ObjectCalcer*> ObjectTypeCalcer::parents() const
|
|
{
|
|
return mparents;
|
|
}
|
|
|
|
void ObjectCalcer::addChild( ObjectCalcer* c )
|
|
{
|
|
mtqchildren.push_back( c );
|
|
ref();
|
|
}
|
|
|
|
void ObjectCalcer::delChild( ObjectCalcer* c )
|
|
{
|
|
std::vector<ObjectCalcer*>::iterator i = std::find( mtqchildren.begin(), mtqchildren.end(), c );
|
|
assert( i != mtqchildren.end() );
|
|
|
|
mtqchildren.erase( i );
|
|
deref();
|
|
}
|
|
|
|
ObjectTypeCalcer::~ObjectTypeCalcer()
|
|
{
|
|
std::for_each( mparents.begin(), mparents.end(),
|
|
std::bind2nd( std::mem_fun( &ObjectCalcer::delChild ), this ) );
|
|
delete mimp;
|
|
}
|
|
|
|
const ObjectType* ObjectTypeCalcer::type() const
|
|
{
|
|
return mtype;
|
|
}
|
|
|
|
ObjectPropertyCalcer::ObjectPropertyCalcer( ObjectCalcer* parent, int propid )
|
|
: mimp( 0 ), mparent( parent ), mpropid( propid )
|
|
{
|
|
// Some weird C++ thing prevents me from calling protected members
|
|
// of ObjectCalcer on mparent.. This is an ugly workaround..
|
|
( mparent->*&ObjectCalcer::addChild )( this );
|
|
//mparent->addChild( this );
|
|
}
|
|
|
|
ObjectPropertyCalcer::~ObjectPropertyCalcer()
|
|
{
|
|
// Some weird C++ thing prevents me from calling protected members
|
|
// of ObjectCalcer on mparent.. This is an ugly workaround..
|
|
( mparent->*&ObjectCalcer::delChild )( this );
|
|
//mparent->delChild( this );
|
|
delete mimp;
|
|
}
|
|
|
|
const ObjectImp* ObjectPropertyCalcer::imp() const
|
|
{
|
|
return mimp;
|
|
}
|
|
|
|
std::vector<ObjectCalcer*> ObjectPropertyCalcer::parents() const
|
|
{
|
|
std::vector<ObjectCalcer*> ret;
|
|
ret.push_back( mparent );
|
|
return ret;
|
|
}
|
|
|
|
void ObjectPropertyCalcer::calc( const KigDocument& doc )
|
|
{
|
|
ObjectImp* n = mparent->imp()->property( mpropid, doc );
|
|
delete mimp;
|
|
mimp = n;
|
|
}
|
|
|
|
ObjectImp* ObjectConstCalcer::switchImp( ObjectImp* newimp )
|
|
{
|
|
ObjectImp* ret = mimp;
|
|
mimp = newimp;
|
|
return ret;
|
|
}
|
|
|
|
std::vector<ObjectCalcer*> ObjectCalcer::tqchildren() const
|
|
{
|
|
return mtqchildren;
|
|
}
|
|
|
|
const ObjectImpType* ObjectPropertyCalcer::impRequirement(
|
|
ObjectCalcer*, const std::vector<ObjectCalcer*>& ) const
|
|
{
|
|
return mparent->imp()->impRequirementForProperty( mpropid );
|
|
}
|
|
|
|
const ObjectImpType* ObjectConstCalcer::impRequirement(
|
|
ObjectCalcer*, const std::vector<ObjectCalcer*>& ) const
|
|
{
|
|
assert( false );
|
|
return ObjectImp::stype();
|
|
}
|
|
|
|
const ObjectImpType* ObjectTypeCalcer::impRequirement(
|
|
ObjectCalcer* o, const std::vector<ObjectCalcer*>& os ) const
|
|
{
|
|
Args args;
|
|
args.reserve( mparents.size() );
|
|
std::transform(
|
|
os.begin(), os.end(),
|
|
std::back_inserter( args ),
|
|
std::mem_fun( &ObjectCalcer::imp ) );
|
|
assert( std::find( args.begin(), args.end(), o->imp() ) != args.end() );
|
|
return mtype->impRequirement( o->imp(), args );
|
|
}
|
|
|
|
int ObjectPropertyCalcer::propId() const
|
|
{
|
|
return mpropid;
|
|
}
|
|
|
|
void ObjectConstCalcer::setImp( ObjectImp* newimp )
|
|
{
|
|
delete switchImp( newimp );
|
|
}
|
|
|
|
void ObjectTypeCalcer::setParents( const std::vector<ObjectCalcer*> np )
|
|
{
|
|
std::for_each( np.begin(), np.end(),
|
|
std::bind2nd( std::mem_fun( &ObjectCalcer::addChild ), this ) );
|
|
std::for_each( mparents.begin(), mparents.end(),
|
|
std::bind2nd( std::mem_fun( &ObjectCalcer::delChild ), this ) );
|
|
mparents = np;
|
|
}
|
|
|
|
void ObjectTypeCalcer::setType( const ObjectType* t )
|
|
{
|
|
mtype = t;
|
|
}
|
|
|
|
bool ObjectCalcer::canMove() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool ObjectCalcer::isFreelyTranslatable() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Coordinate ObjectCalcer::moveReferencePoint() const
|
|
{
|
|
assert( false );
|
|
return Coordinate::invalidCoord();
|
|
}
|
|
|
|
void ObjectCalcer::move( const Coordinate&, const KigDocument& )
|
|
{
|
|
assert( false );
|
|
}
|
|
|
|
bool ObjectTypeCalcer::canMove() const
|
|
{
|
|
return mtype->canMove( *this );
|
|
}
|
|
|
|
bool ObjectTypeCalcer::isFreelyTranslatable() const
|
|
{
|
|
return mtype->isFreelyTranslatable( *this );
|
|
}
|
|
|
|
Coordinate ObjectTypeCalcer::moveReferencePoint() const
|
|
{
|
|
return mtype->moveReferencePoint( *this );
|
|
}
|
|
|
|
void ObjectTypeCalcer::move( const Coordinate& to, const KigDocument& doc )
|
|
{
|
|
// we need to check if type can in fact move, because this check is
|
|
// not done for us in all circumstances ( e.g. LineABType::move uses
|
|
// move on its parents to move them ), and the ObjectType's depend
|
|
// on move only being called if canMove() returns true..
|
|
if ( mtype->canMove( *this ) )
|
|
mtype->move( *this, to, doc );
|
|
}
|
|
|
|
ObjectCalcer* ObjectPropertyCalcer::parent() const
|
|
{
|
|
return mparent;
|
|
}
|
|
|
|
ObjectCalcer::ObjectCalcer()
|
|
: refcount( 0 )
|
|
{
|
|
}
|
|
|
|
std::vector<ObjectCalcer*> ObjectCalcer::movableParents() const
|
|
{
|
|
return std::vector<ObjectCalcer*>();
|
|
}
|
|
|
|
std::vector<ObjectCalcer*> ObjectTypeCalcer::movableParents() const
|
|
{
|
|
return mtype->movableParents( *this );
|
|
}
|
|
|
|
bool ObjectConstCalcer::isDefinedOnOrThrough( const ObjectCalcer* ) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool ObjectPropertyCalcer::isDefinedOnOrThrough( const ObjectCalcer* o ) const
|
|
{
|
|
return o == mparent &&
|
|
mparent->imp()->isPropertyDefinedOnOrThroughThisImp( propId() );
|
|
}
|
|
|
|
bool ObjectTypeCalcer::isDefinedOnOrThrough( const ObjectCalcer* o ) const
|
|
{
|
|
Args args;
|
|
args.reserve( mparents.size() );
|
|
std::transform(
|
|
mparents.begin(), mparents.end(),
|
|
std::back_inserter( args ),
|
|
std::mem_fun( &ObjectCalcer::imp ) );
|
|
if ( std::find( args.begin(), args.end(), o->imp() ) == args.end() )
|
|
return false;
|
|
|
|
return mtype->isDefinedOnOrThrough( o->imp(), args );
|
|
}
|
|
|