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.
tdeedu/kig/objects/object_calcer.cpp

324 lines
7.5 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_fn( &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::bind( std::mem_fn( &ObjectCalcer::addChild ), std::placeholders::_1, 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 )
{
mchildren.push_back( c );
ref();
}
void ObjectCalcer::delChild( ObjectCalcer* c )
{
std::vector<ObjectCalcer*>::iterator i = std::find( mchildren.begin(), mchildren.end(), c );
assert( i != mchildren.end() );
mchildren.erase( i );
deref();
}
ObjectTypeCalcer::~ObjectTypeCalcer()
{
std::for_each( mparents.begin(), mparents.end(),
std::bind( std::mem_fn( &ObjectCalcer::delChild ), std::placeholders::_1, 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::children() const
{
return mchildren;
}
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_fn( &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::bind( std::mem_fn( &ObjectCalcer::addChild ), std::placeholders::_1, this ) );
std::for_each( mparents.begin(), mparents.end(),
std::bind( std::mem_fn( &ObjectCalcer::delChild ), std::placeholders::_1, 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_fn( &ObjectCalcer::imp ) );
if ( std::find( args.begin(), args.end(), o->imp() ) == args.end() )
return false;
return mtype->isDefinedOnOrThrough( o->imp(), args );
}