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.
tdegraphics/kpovmodeler/pmcompositeobject.cpp

397 lines
9.5 KiB

/*
**************************************************************************
description
--------------------
copyright : (C) 2000-2001 by Andreas Zehender
email : zehender@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. *
* *
**************************************************************************/
#include "pmcompositeobject.h"
#include "pmxmlhelper.h"
#include "pmmemento.h"
#include "pmviewstructure.h"
#include <tqdom.h>
PMMetaObject* PMCompositeObject::s_pMetaObject = 0;
PMCompositeObject::PMCompositeObject( PMPart* part )
: Base( part )
{
m_pFirstChild = 0;
m_pLastChild = 0;
m_selectedChildren = 0;
m_bViewStructureChanged = true;
m_pViewStructure = 0;
}
PMCompositeObject::PMCompositeObject( const PMCompositeObject& c )
: Base( c )
{
m_pFirstChild = 0;
m_pLastChild = 0;
m_selectedChildren = 0;
m_bViewStructureChanged = true;
m_pViewStructure = 0;
PMObject* o = c.m_pFirstChild;
for( ; o; o = o->nextSibling( ) )
appendChild( o->copy( ) );
}
PMCompositeObject::~PMCompositeObject( )
{
PMObject* tmp;
PMObject* next;
tmp = m_pFirstChild;
while( tmp )
{
next = tmp->m_pNextSibling;
delete tmp;
tmp = next;
}
if( m_pViewStructure )
delete m_pViewStructure;
}
PMMetaObject* PMCompositeObject::metaObject( ) const
{
if( !s_pMetaObject )
s_pMetaObject = new PMMetaObject( "CompositeObject", Base::metaObject( ) );
return s_pMetaObject;
}
void PMCompositeObject::cleanUp( ) const
{
if( s_pMetaObject )
{
delete s_pMetaObject;
s_pMetaObject = 0;
}
Base::cleanUp( );
}
PMObject* PMCompositeObject::childAt( uint index ) const
{
PMObject* tmp;
uint i = 0;
for( tmp = m_pFirstChild; tmp && ( i < index ); tmp = tmp->nextSibling( ) )
i++;
return tmp;
}
int PMCompositeObject::findChild( PMObject* o )
{
if( o->parent( ) != this )
return -1;
PMObject* tmp;
int index = 0;
for( tmp = m_pFirstChild; tmp; tmp = tmp->nextSibling( ) )
{
if( tmp == o )
return index;
else
index++;
}
return -1;
}
bool PMCompositeObject::insertChild( PMObject* o, int i )
{
if( i < 0 )
return appendChild( o );
else
{
if( i == 0 )
{
if( canInsert( o, 0 ) )
{
o->m_pNextSibling = m_pFirstChild;
o->m_pPrevSibling = 0;
if( m_pFirstChild )
m_pFirstChild->m_pPrevSibling = o;
m_pFirstChild = o;
if( !m_pLastChild )
m_pLastChild = o;
o->m_pParent = this;
}
else
return false;
}
else
{
PMObject* tmp = childAt( ( uint ) ( i - 1 ) );
if( !tmp )
{
kdError( PMArea ) << "Index too big" << "\n";
return false;
}
if( canInsert( o, tmp ) )
{
o->m_pPrevSibling = tmp;
o->m_pNextSibling = tmp->m_pNextSibling;
if( tmp->m_pNextSibling )
tmp->m_pNextSibling->m_pPrevSibling = o;
else
m_pLastChild = o;
tmp->m_pNextSibling = o;
o->m_pParent = this;
}
else
return false;
}
childAdded( o );
return true;
}
return false;
}
bool PMCompositeObject::appendChild( PMObject* o )
{
if( canInsert( o, m_pLastChild ) )
{
o->m_pParent = this;
o->m_pPrevSibling = m_pLastChild;
o->m_pNextSibling = 0;
if( m_pLastChild )
m_pLastChild->m_pNextSibling = o;
else
m_pFirstChild = o;
m_pLastChild = o;
childAdded( o );
return true;
}
return false;
}
bool PMCompositeObject::insertChildAfter( PMObject* obj, PMObject* after )
{
if( canInsert( obj, after ) )
{
if( after->m_pParent == this )
{
obj->m_pParent = this;
obj->m_pPrevSibling = after;
obj->m_pNextSibling = after->m_pNextSibling;
if( after->m_pNextSibling )
after->m_pNextSibling->m_pPrevSibling = obj;
else
m_pLastChild = obj;
after->m_pNextSibling = obj;
childAdded( obj );
return true;
}
else
{
kdError( PMArea ) << "Object after is no child" << "\n";
return false;
}
}
return false;
}
bool PMCompositeObject::insertChildBefore( PMObject* obj, PMObject* before )
{
if( before )
{
if( canInsert( obj, before->m_pPrevSibling ) )
{
if( before->m_pParent == this )
{
obj->m_pParent = this;
obj->m_pPrevSibling = before->m_pPrevSibling;
obj->m_pNextSibling = before;
if( before->m_pPrevSibling )
before->m_pPrevSibling->m_pNextSibling = obj;
else
m_pFirstChild = obj;
before->m_pPrevSibling = obj;
childAdded( obj );
return true;
}
else
{
kdError( PMArea ) << "Object before is no child" << "\n";
return false;
}
}
}
return false;
}
bool PMCompositeObject::takeChild( PMObject* o )
{
if( ( PMObject* ) this == o->m_pParent )
{
// deselect the object and all child objects of o
if( o->isSelected( ) )
o->setSelected( false );
else if( o->selectedChildren( ) > 0 )
o->deselectChildren( );
// remove it, but do NOT delete it.
if( o->m_pPrevSibling )
o->m_pPrevSibling->m_pNextSibling = o->m_pNextSibling;
else
m_pFirstChild = o->m_pNextSibling;
if( o->m_pNextSibling )
o->m_pNextSibling->m_pPrevSibling = o->m_pPrevSibling;
else
m_pLastChild = o->m_pPrevSibling;
o->m_pParent = 0;
o->m_pPrevSibling = 0;
o->m_pNextSibling = 0;
childRemoved( o );
return true;
}
kdError( PMArea ) << "o is no child" << "\n";
return false;
}
bool PMCompositeObject::takeChild( uint i )
{
PMObject* tmp = childAt( i );
if( tmp )
return takeChild( tmp );
kdError( PMArea ) << "Index too big";
return false;
}
void PMCompositeObject::serialize( TQDomElement& e, TQDomDocument& doc ) const
{
PMObject* tmp;
for( tmp = m_pFirstChild; tmp; tmp = tmp->m_pNextSibling )
e.appendChild( tmp->serialize( doc ) );
}
int PMCompositeObject::countChildren( ) const
{
int num = 0;
PMObject* tmp;
for( tmp = m_pFirstChild; tmp; tmp = tmp->m_pNextSibling )
num++;
return num;
}
void PMCompositeObject::adjustSelectedChildren( int num )
{
m_selectedChildren += num;
if( m_selectedChildren < 0 )
{
kdError( PMArea ) << "num too big in PMCompositeObject::adjustSelectedChildren( )\n";
m_selectedChildren = 0;
}
if( m_pParent )
m_pParent->adjustSelectedChildren( num );
}
void PMCompositeObject::deselectChildren( )
{
PMObject* tmp;
if( m_selectedChildren > 0 )
{
tmp = m_pFirstChild;
while( tmp && ( m_selectedChildren > 0 ) )
{
if( tmp->isSelected( ) )
tmp->setSelected( false );
else if( tmp->selectedChildren( ) > 0 )
tmp->deselectChildren( );
tmp = tmp->m_pNextSibling;
}
}
}
PMViewStructure* PMCompositeObject::viewStructure( )
{
if( m_pViewStructure )
{
if( m_pViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
{
// the default view structure or the parameters (detail level)
// have changed
m_bViewStructureChanged = true;
delete m_pViewStructure;
m_pViewStructure = 0;
}
}
if( m_bViewStructureChanged )
{
PMViewStructure* dvs = defaultViewStructure( );
if( dvs )
if( dvs->parameterKey( ) == -1 ) // newly created view structure
dvs->setParameterKey( viewStructureParameterKey( ) );
if( isDefault( ) )
{
if( dvs )
{
if( m_pViewStructure )
{
if( *m_pViewStructure != *dvs )
{
delete m_pViewStructure;
m_pViewStructure = new PMViewStructure( dvs );
}
}
else
m_pViewStructure = new PMViewStructure( dvs );
}
if( !m_pViewStructure )
kdError( PMArea ) << "isDefault( ) returned true, but no default view structure is provided\n";
}
else
{
if( dvs )
{
if( m_pViewStructure && ( *m_pViewStructure == *dvs ) )
{
delete m_pViewStructure;
m_pViewStructure = 0;
}
}
createViewStructure( );
if( m_pViewStructure )
m_pViewStructure->setParameterKey( viewStructureParameterKey( ) );
}
m_bViewStructureChanged = false;
}
return m_pViewStructure;
}
void PMCompositeObject::setViewStructureChanged( )
{
m_bViewStructureChanged = true;
if( m_pMemento )
m_pMemento->setViewStructureChanged( );
}