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.

947 lines
28 KiB

/***************************************************************************
qscobject.cpp
-------------------
begin : Sun Jan 9 2000
copyright : (C) 2000 by Kamil Dobkowski
email : kamildbk@friko.onet.pl
***************************************************************************/
/***************************************************************************
* *
* 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 "qscobject.h"
#include "qsdrvqt.h"
#include "qsaxes.h"
#include "qsaxis.h"
#include "qschildlist.h"
#include <math.h>
#include <qmetaobject.h>
#include <qcstring.h>
#include <qvariant.h>
#include <assert.h>
//-------------------------------------------------------------//
QSCObjectCollection::QSCObjectCollection( QObject *parent, bool autoDelete )
: QObject(parent), QSSerializable()
{
m_auto_updates = true;
m_objects = new QSChildList<QSCObject>(autoDelete);
}
//-------------------------------------------------------------//
QSCObjectCollection::~QSCObjectCollection()
{
stop();
delete m_objects;
//cout << "deleting object collection" << endl;
}
//-------------------------------------------------------------//
void QSCObjectCollection::setAutoUpdates( bool enable )
{
if ( m_auto_updates != enable ) {
m_auto_updates = enable;
listChanged();
changed();
}
}
//-------------------------------------------------------------//
int QSCObjectCollection::count() const
{
return m_objects->count();
}
//-------------------------------------------------------------//
bool QSCObjectCollection::tempAutoUpdatesOff()
{
bool result = m_auto_updates;
m_auto_updates = false;
return result;
}
//-------------------------------------------------------------//
void QSCObjectCollection::tempAutoUpdatesRestore( bool enable )
{
m_auto_updates = enable;
}
//-------------------------------------------------------------//
void QSCObjectCollection::clear()
{
parametersChanging();
bool temp = tempAutoUpdatesOff();
while( count() ) removeDelete(0);
tempAutoUpdatesRestore( temp );
listChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSCObjectCollection::add( QSCObject *newObject )
{
insert( count(), newObject );
}
//-------------------------------------------------------------//
void QSCObjectCollection::insert( int position, QSCObject *newObject )
{
if ( newObject && find(newObject) < 0 ) {
parametersChanging();
if ( m_objects->autoDelete() ) newObject->stop();
m_objects->insert( position, newObject );
connect( newObject, SIGNAL(sigUpdate()), this, SLOT(slot_object_changed()) );
if ( newObject->isAxesShadow() ) {
connect( newObject->parentAxes(), SIGNAL(sigChildListChanged()), this, SLOT(slot_data_child_list_changed()) );
}
if ( dynamic_cast<QSCGroup*>(newObject) ) {
QSCGroup *group = (QSCGroup *)newObject;
connect( group->objects(), SIGNAL(sigAdded(QSCObjectCollection*,QSCObject*)), this, SLOT(slot_added(QSCObjectCollection*,QSCObject*)) );
connect( group->objects(), SIGNAL(sigRemoved(QSCObjectCollection*,QSCObject*)), this, SLOT(slot_removed(QSCObjectCollection*,QSCObject*)) );
connect( group->objects(), SIGNAL(sigOrderChanged(QSCObjectCollection*)), this, SLOT(slot_order_changed(QSCObjectCollection*)) );
connect( group->objects(), SIGNAL(sigListChanged(QSCObjectCollection*)), this, SLOT(slot_list_changed(QSCObjectCollection*)) );
connect( group->objects(), SIGNAL(sigDataChildListChanged()), this, SLOT(slot_data_child_list_changed()) );
}
if ( m_objects->autoDelete() ) {
newObject->setCollection(this);
}
emit sigAdded( newObject );
emit sigAdded( this, newObject );
listChanged();
parametersChanged();
}
}
//-------------------------------------------------------------//
void QSCObjectCollection::remove( int index )
{
QSCObject *object_to_remove = object( index );
if ( object_to_remove ) {
parametersChanging();
if ( m_objects->autoDelete() ) {
object_to_remove->stop();
object_to_remove->setCollection(NULL);
}
if ( object_to_remove->isAxesShadow() ) {
disconnect( object_to_remove->parentAxes(), SIGNAL(sigChildListChanged()), this, SLOT(slot_data_child_list_changed()) );
}
if ( dynamic_cast<QSCGroup*>(object_to_remove) ) {
QSCGroup *group = (QSCGroup *)object_to_remove;
disconnect( group->objects(), SIGNAL(sigAdded(QSCObjectCollection*,QSCObject*)), this, SLOT(slot_added(QSCObjectCollection*,QSCObject*)) );
disconnect( group->objects(), SIGNAL(sigRemoved(QSCObjectCollection*,QSCObject*)), this, SLOT(slot_removed(QSCObjectCollection*,QSCObject*)) );
disconnect( group->objects(), SIGNAL(sigOrderChanged(QSCObjectCollection*)), this, SLOT(slot_order_changed(QSCObjectCollection*)) );
disconnect( group->objects(), SIGNAL(sigListChanged(QSCObjectCollection*)), this, SLOT(slot_list_changed(QSCObjectCollection*)) );
disconnect( group->objects(), SIGNAL(sigDataChildListChanged()), this, SLOT(slot_data_child_list_changed()) );
}
disconnect( object_to_remove, SIGNAL(sigUpdate()), this, SLOT(slot_object_changed()) );
m_objects->remove( index );
emit sigRemoved( object_to_remove );
emit sigRemoved( this, object_to_remove );
listChanged();
parametersChanged();
}
}
//-------------------------------------------------------------//
void QSCObjectCollection::removeDelete( int index )
{
QSCObject *object_to_delete = object( index );
if ( object_to_delete ) {
remove( index );
if ( m_objects->autoDelete() ) delete object_to_delete;
}
}
//-------------------------------------------------------------//
void QSCObjectCollection::raise( int index )
{
parametersChanging();
m_objects->raise( index );
orderChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSCObjectCollection::lower( int index )
{
parametersChanging();
m_objects->lower( index );
orderChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSCObjectCollection::toFront( int index )
{
parametersChanging();
m_objects->toFront( index );
orderChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSCObjectCollection::toBack( int index )
{
parametersChanging();
m_objects->toBack( index );
orderChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSCObjectCollection::reorder( int position, int index )
{
parametersChanging();
m_objects->reorder( position, index );
orderChanged();
parametersChanged();
}
//-------------------------------------------------------------//
int QSCObjectCollection::find( QSCObject *object ) const
{
return m_objects->find( object );
}
//-------------------------------------------------------------//
QSCObject *QSCObjectCollection::object( int index ) const
{
return (*m_objects)[index];
}
//-------------------------------------------------------------//
void QSCObjectCollection::paintSkeleton( QPainter *p, double dpi )
{
for( int i=0; i<count(); i++ ) object(i)->paintSkeleton( p, dpi );
}
//-------------------------------------------------------------//
void QSCObjectCollection::paint( QPainter *p, double dpi, bool blocking, bool transparent )
{
for( int i=0; i<count(); i++ ) {
object(i)->paint( p, dpi, blocking, transparent );
if ( object(i)->busy() ) connect( object(i), SIGNAL(sigDrawEnds(QSCObject*)), this, SLOT(slot_draw_ends(QSCObject*)) );
}
slot_draw_ends(NULL);
}
//-------------------------------------------------------------//
void QSCObjectCollection::draw( QSDrv *drv, bool blocking, bool transparent )
{
for( int i=0; i<count(); i++ ) {
object(i)->draw( drv, blocking, transparent );
if ( object(i)->busy() ) connect( object(i), SIGNAL(sigDrawEnds(QSCObject*)), this, SLOT(slot_draw_ends(QSCObject*)) );
}
slot_draw_ends(NULL);
}
//-------------------------------------------------------------//
void QSCObjectCollection::slot_draw_ends( QSCObject *object )
{
if ( object ) disconnect( object, SIGNAL(sigDrawEnds(QSCObject*)), this, SLOT(slot_draw_ends(QSCObject*)) );
if ( !busy() ) emit sigDrawEnds();
}
//-------------------------------------------------------------//
bool QSCObjectCollection::busy() const
{
for( int i=0; i<count(); i++ ) if ( object(i)->busy() ) return true;
return false;
}
//-------------------------------------------------------------//
void QSCObjectCollection::stop()
{
for( int i=0; i<count(); i++ ) object(i)->stop();
}
//-------------------------------------------------------------//
QSCObject *QSCObjectCollection::objectAt( const QSPt2f &p, QSDrv* drv, bool recursive )
{
for( int i=count()-1; i>=0; i-- )
if ( object(i)->isHit(p,drv) )
if ( recursive && dynamic_cast<QSCGroup*>(object(i)) ) {
QSCObject *hit_object = ((QSCGroup*)(object(i)))->objects()->objectAt( p, drv, recursive );
return hit_object ? hit_object : object(i);
} else {
return object(i);
}
return NULL;
}
//-------------------------------------------------------------//
bool QSCObjectCollection::contains( QSCObject *checkedObject, bool recursive )
{
if ( find(checkedObject) >= 0 ) return true;
if ( recursive )
for( int i=0; i<count(); i++ ) if ( dynamic_cast<QSCGroup*>(object(i)) ) {
if ( ((QSCGroup*)(object(i)))->objects()->contains( checkedObject, recursive ) ) return true;
}
return false;
}
//-------------------------------------------------------------//
void QSCObjectCollection::loadStateFromStream( QDataStream& stream, QSObjectFactory *factory )
// we dont load auto-delete
{
clear();
int object_count; stream >> object_count;
for( int i=0; i<object_count; i++ ) {
QSCObject *new_object = dynamic_cast<QSCObject *>(factory->loadObjectFromStream(stream));
assert( new_object ); add( new_object );
}
}
//-------------------------------------------------------------//
void QSCObjectCollection::saveStateToStream( QDataStream& stream, QSObjectFactory *factory )
// we dont save auto-delete
{
QSSerializable::saveStateToStream( stream, factory );
stream << (int )count();
for( int i=0; i<count(); i++ ) factory->saveObjectToStream( object(i), stream );
}
//-------------------------------------------------------------//
void QSCObjectCollection::parametersChanging()
{
emit sigParametersChanging();
}
//-------------------------------------------------------------//
void QSCObjectCollection::parametersChanged()
{
emit sigParametersChanged();
changed();
}
//-------------------------------------------------------------//
void QSCObjectCollection::orderChanged()
{
emit sigOrderChanged();
emit sigOrderChanged( this );
listChanged();
}
//-------------------------------------------------------------//
void QSCObjectCollection::listChanged()
{
if ( m_auto_updates ) {
emit sigListChanged();
emit sigListChanged( this );
}
}
//-------------------------------------------------------------//
void QSCObjectCollection::changed()
{
if ( m_auto_updates ) emit sigChanged();
}
//-------------------------------------------------------------//
void QSCObjectCollection::slot_added( QSCObjectCollection *collection, QSCObject*object )
{
emit sigAdded( collection, object );
}
//-------------------------------------------------------------//
void QSCObjectCollection::slot_removed( QSCObjectCollection *collection, QSCObject *object )
{
emit sigRemoved( collection, object );
}
//-------------------------------------------------------------//
void QSCObjectCollection::slot_order_changed( QSCObjectCollection *collection )
{
emit sigOrderChanged( collection );
}
//-------------------------------------------------------------//
void QSCObjectCollection::slot_list_changed( QSCObjectCollection *collection )
{
if ( m_auto_updates ) emit sigListChanged( collection );
}
//-------------------------------------------------------------//
void QSCObjectCollection::slot_object_changed()
{
changed();
}
//---------------------------------------------------------------------------------------------------//
void QSCObjectCollection::slot_data_child_list_changed()
{
emit sigDataChildListChanged();
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
QSCObject::QSCObject( QObject *parent ):
QObject(parent), QSSerializable()
{
m_group = NULL;
m_collection = NULL;
m_parent_axes = NULL;
m_auto_updates = true;
m_default_axis[0] = NULL;
m_default_axis[1] = NULL;
m_default_axis[2] = NULL;
}
//-------------------------------------------------------------//
QSCObject::~QSCObject()
{
}
//-------------------------------------------------------------//
void QSCObject::setParentAxes( QSAxes *axes )
{
if ( axes != m_parent_axes ) {
parametersChanging();
if ( m_parent_axes ) {
m_default_axis[0] = NULL;
m_default_axis[1] = NULL;
m_default_axis[2] = NULL;
disconnect( m_parent_axes, SIGNAL(sigChildRemoved(QSData*)), this, SLOT(axisRemoved(QSData*)) );
disconnect( m_parent_axes, SIGNAL(sigDeleted(QSData*)), this, SLOT(parentAxesRemoved(QSData*)) );
}
m_parent_axes = axes;
if ( m_parent_axes ) {
m_default_axis[0] = m_parent_axes->axisOfType(QSAxis::XAxisType);
m_default_axis[1] = m_parent_axes->axisOfType(QSAxis::YAxisType);
m_default_axis[2] = m_parent_axes->axisOfType(QSAxis::ZAxisType);
connect( m_parent_axes, SIGNAL(sigChildRemoved(QSData*)), this, SLOT(axisRemoved(QSData*)) );
connect( m_parent_axes, SIGNAL(sigDeleted(QSData*)), this, SLOT(parentAxesRemoved(QSData*)) );
}
parametersChanged();
}
}
//-------------------------------------------------------------//
void QSCObject::setCollection( QSCObjectCollection *parent )
{
m_collection = parent;
}
//-------------------------------------------------------------//
void QSCObject::setGroup( QSCGroup *group )
{
m_group = group;
}
//-------------------------------------------------------------//
void QSCObject::raise()
{
if ( m_collection ) m_collection->raise( m_collection->find(this) );
}
//-------------------------------------------------------------//
void QSCObject::lower()
{
if ( m_collection ) m_collection->lower( m_collection->find(this) );
}
//-------------------------------------------------------------//
void QSCObject::toFront()
{
if ( m_collection ) m_collection->toFront( m_collection->find(this) );
}
//-------------------------------------------------------------//
void QSCObject::toBack()
{
if ( m_collection ) m_collection->toBack( m_collection->find(this) );
}
//-------------------------------------------------------------//
void QSCObject::reorder( int newPosition )
{
if ( m_collection ) m_collection->reorder( newPosition, m_collection->find(this) );
}
//-------------------------------------------------------------//
void QSCObject::axisRemoved( QSData *removedObject )
{
if ( m_parent_axes ) {
if ( m_default_axis[0] == removedObject ) m_default_axis[0] = m_parent_axes->axisOfType(QSAxis::XAxisType);
if ( m_default_axis[1] == removedObject ) m_default_axis[1] = m_parent_axes->axisOfType(QSAxis::YAxisType);
if ( m_default_axis[2] == removedObject ) m_default_axis[2] = m_parent_axes->axisOfType(QSAxis::ZAxisType);
}
}
//-------------------------------------------------------------//
void QSCObject::parentAxesRemoved( QSData *removedObject )
{
if ( removedObject == m_parent_axes ) {
setParentAxes(NULL);
}
}
//-------------------------------------------------------------//
QSAxis *QSCObject::defaultAxis( int axisType ) const
{
if ( axisType == QSAxis::XAxisType ||
axisType == QSAxis::YAxisType ||
axisType == QSAxis::ZAxisType ) {
return m_default_axis[axisType];
}
return NULL;
}
//-------------------------------------------------------------//
void QSCObject::setDefaultAxis( QSAxis *axis )
{
if ( axis &&
axis->parentAxes() == m_parent_axes &&
( axis->type() == QSAxis::XAxisType ||
axis->type() == QSAxis::YAxisType ||
axis->type() == QSAxis::ZAxisType ) ) {
parametersChanging();
m_default_axis[axis->type()] = axis;
parametersChanged();
}
}
//-------------------------------------------------------------//
QSPt3f QSCObject::mixedToCanvas( const QSPt3f& pos, int xCoordIn, int yCoordIn, int zCoordIn, double dpi )
{
QSPt3f result;
if ( m_parent_axes ) {
QSAxes::CoordinateSystem in_coord[3];
in_coord[0] = (QSAxes::CoordinateSystem )xCoordIn;
in_coord[1] = (QSAxes::CoordinateSystem )yCoordIn;
in_coord[2] = (QSAxes::CoordinateSystem )zCoordIn;
result = m_parent_axes->mixedToCanvas( pos, in_coord, dpi, m_default_axis[0], m_default_axis[1], m_default_axis[2] );
} else {
result = QSPt3f( QSCoord::mmToPixels( pos.x, dpi ),
QSCoord::mmToPixels( pos.y, dpi ),
QSCoord::mmToPixels( pos.z, dpi ) );
}
return result;
}
//-------------------------------------------------------------//
QSPt3f QSCObject::canvasToMixed( const QSPt3f& pos, int xCoordOut, int yCoordOut, int zCoordOut, double dpi )
{
QSPt3f result;
if ( m_parent_axes ) {
QSAxes::CoordinateSystem out_coord[3];
out_coord[0] = (QSAxes::CoordinateSystem )xCoordOut;
out_coord[1] = (QSAxes::CoordinateSystem )yCoordOut;
out_coord[2] = (QSAxes::CoordinateSystem )zCoordOut;
result = m_parent_axes->canvasToMixed( pos, out_coord, dpi, m_default_axis[0], m_default_axis[1], m_default_axis[2] );
} else {
result = QSPt3f( QSCoord::pixelsToMM( pos.x, dpi ),
QSCoord::pixelsToMM( pos.y, dpi ),
QSCoord::pixelsToMM( pos.z, dpi ) );
}
return result;
}
//-------------------------------------------------------------//
void QSCObject::setAutoUpdates( bool enabled )
{
m_auto_updates = enabled;
}
//-------------------------------------------------------------//
void QSCObject::paintSkeleton( QPainter *p, double dpi )
{
QSCObject::paint( p, dpi );
}
//-------------------------------------------------------------//
void QSCObject::paint( QPainter *p, double dpi, bool blocking, bool transparent )
{
QSDrvQt qtdrv;
qtdrv.setDC(p,dpi,false);
draw( &qtdrv, blocking, transparent );
}
//-------------------------------------------------------------//
void QSCObject::setBox( const QSRectf&, QSDrv* )
{
}
//-------------------------------------------------------------//
QSRectf QSCObject::box( QSDrv * )
{
return QSRectf();
}
//-------------------------------------------------------------//
void QSCObject::setAngle( int )
{
}
//-------------------------------------------------------------//
QSPt2f QSCObject::rCenter( QSDrv * )
{
return QSPt2f();
}
//-------------------------------------------------------------//
void QSCObject::parametersChanging()
{
stop();
}
//-------------------------------------------------------------//
void QSCObject::parametersChanged()
{
if ( m_auto_updates ) {
emit sigUpdate( this );
emit sigUpdate();
}
}
//-------------------------------------------------------------//
void QSCObject::forceUpdate()
{
emit sigUpdate( this );
emit sigUpdate();
}
//-------------------------------------------------------------//
void QSCObject::setDefaultXAxis( int axisIndex )
{
setDefaultAxis( m_parent_axes ? m_parent_axes->axis(axisIndex) : NULL );
}
//-------------------------------------------------------------//
void QSCObject::setDefaultYAxis( int axisIndex )
{
setDefaultAxis( m_parent_axes ? m_parent_axes->axis(axisIndex) : NULL );
}
//-------------------------------------------------------------//
void QSCObject::setDefaultZAxis( int axisIndex )
{
setDefaultAxis( m_parent_axes ? m_parent_axes->axis(axisIndex) : NULL );
}
//-------------------------------------------------------------//
int QSCObject::defaultXAxis() const
{
return m_parent_axes ? m_parent_axes->axisIndex(m_default_axis[QSAxis::XAxisType]) : -1;
}
//-------------------------------------------------------------//
int QSCObject::defaultYAxis() const
{
return m_parent_axes ? m_parent_axes->axisIndex(m_default_axis[QSAxis::YAxisType]) : -1;
}
//-------------------------------------------------------------//
int QSCObject::defaultZAxis() const
{
return m_parent_axes ? m_parent_axes->axisIndex(m_default_axis[QSAxis::ZAxisType]) : -1;
}
//-------------------------------------------------------------//
QSCObjectCollection *QSCObject::rootCollection()
{
QSCGroup *curr_group = group();
while( curr_group && curr_group->group() ) curr_group = curr_group->group();
if ( curr_group ) return curr_group->collection();
else return collection();
}
//-------------------------------------------------------------//
void QSCObject::loadStateFromStream( QDataStream& stream, QSObjectFactory *factory )
{
QSSerializable::loadStateFromStream( stream, factory );
QMetaObject *meta_object = metaObject();
QStrList properties = meta_object->propertyNames( TRUE );
for( unsigned int property_nr=0; property_nr<properties.count(); property_nr++ ) {
QCString property_name;
QVariant property_value;
stream >> property_name >> property_value;
setProperty(property_name,property_value);
}
}
//-------------------------------------------------------------//
void QSCObject::saveStateToStream( QDataStream& stream, QSObjectFactory *factory )
{
QSSerializable::saveStateToStream( stream, factory );
QMetaObject *meta_object = metaObject();
QStrList properties = meta_object->propertyNames( TRUE );
for( unsigned int property_nr=0; property_nr<properties.count(); property_nr++ ) {
stream << QCString(properties.at(property_nr)) << property(properties.at(property_nr));
}
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
QSCGroup::QSCGroup( QObject *parent )
: QSCObject(parent)
{
m_w_minus = false;
m_h_minus = false;
m_objects = new QSCObjectCollection( this );
connect( m_objects, SIGNAL(sigChanged()), this, SLOT(slot_collection_changed()) );
connect( m_objects, SIGNAL(sigParametersChanging()), this, SLOT(parametersChanging()) );
connect( m_objects, SIGNAL(sigParametersChanged()), this, SLOT(parametersChanged()) );
connect( m_objects, SIGNAL(sigAdded(QSCObject*)), this, SLOT(slot_object_added(QSCObject*)) );
connect( m_objects, SIGNAL(sigRemoved(QSCObject*)), this, SLOT(slot_object_removed(QSCObject*)) );
}
//-------------------------------------------------------------//
QSCGroup::~QSCGroup()
{
}
//-------------------------------------------------------------//
void QSCGroup::paintSkeleton( QPainter *p, double dpi )
{
m_objects->paintSkeleton( p, dpi );
}
//-------------------------------------------------------------//
void QSCGroup::paint( QPainter *p, double dpi, bool blocking, bool transparent )
{
connect( m_objects, SIGNAL(sigDrawEnds()), this, SLOT(slot_draw_ends()) );
m_objects->paint( p, dpi, blocking, transparent );
}
//-------------------------------------------------------------//
void QSCGroup::draw( QSDrv *drv, bool blocking, bool transparent )
{
connect( m_objects, SIGNAL(sigDrawEnds()), this, SLOT(slot_draw_ends()) );
m_objects->draw( drv, blocking, transparent );
}
//-------------------------------------------------------------//
void QSCGroup::slot_draw_ends()
{
disconnect( m_objects, SIGNAL(sigDrawEnds()), this, SLOT(slot_draw_ends()) );
emit sigDrawEnds( this );
}
//-------------------------------------------------------------//
bool QSCGroup::busy() const
{
return m_objects->busy();
}
//-------------------------------------------------------------//
void QSCGroup::stop()
{
m_objects->stop();
}
//-------------------------------------------------------------//
bool QSCGroup::isHit( const QSPt2f &p, QSDrv* drv )
{
return (m_objects->objectAt(p,drv) != NULL);
}
//-------------------------------------------------------------//
void QSCGroup::setBox( const QSRectf& new_rect, QSDrv *drv )
{
// Ups !!!
// allow rectangles with size < 0 (mirroring )
QSRectf newRect = new_rect;
if ( newRect.size.x >= 0.0 && newRect.size.x < 1.0 ) newRect.size.x = 1.0;
if ( newRect.size.y >= 0.0 && newRect.size.y < 1.0 ) newRect.size.y = 1.0;
if ( newRect.size.x < 0.0 && newRect.size.x > -1.0 ) newRect.size.x = -1.0;
if ( newRect.size.y < 0.0 && newRect.size.y > -1.0 ) newRect.size.y = -1.0;
parametersChanging();
disconnect( m_objects, SIGNAL(sigChanged()), this, SLOT(slot_collection_changed()) );
QSRectf rect = box(drv);
QSPt2f scale;
scale.x = newRect.size.x/rect.size.x;
scale.y = newRect.size.y/rect.size.y;
for( int i=0;i<objects()->count(); i++ ) {
QSRectf curr_rect = objects()->object(i)->box(drv);
curr_rect.pos = QSPt2f( ((curr_rect.pos.x-rect.pos.x)*scale.x+newRect.pos.x),
((curr_rect.pos.y-rect.pos.y)*scale.y+newRect.pos.y) );
curr_rect.size.x *= scale.x;
curr_rect.size.y *= scale.y;
objects()->object(i)->setBox(curr_rect,drv);
}
if ( (newRect.size.x < 0.0) != m_w_minus ) m_w_minus = !m_w_minus;
if ( (newRect.size.y < 0.0) != m_h_minus ) m_h_minus = !m_h_minus;
connect( m_objects, SIGNAL(sigChanged()), this, SLOT(slot_collection_changed()) );
parametersChanged();
}
//-------------------------------------------------------------//
QSRectf QSCGroup::box( QSDrv *drv )
{
QSRectf result;
if ( objects()->count() > 0 ) {
result = objects()->object(0)->box(drv).normalize();
for( int i=1; i<objects()->count(); i++ ) result.unite( objects()->object(i)->box(drv).normalize() );
}
if ( m_w_minus ) { result.pos.x += result.size.x; result.size.x = -result.size.x; }
if ( m_h_minus ) { result.pos.y += result.size.y; result.size.y = -result.size.y; }
return result;
}
//-------------------------------------------------------------//
QString QSCGroup::name()
{
return tr("Group of %1 objects").arg(objects()->count());
}
//-------------------------------------------------------------//
void QSCGroup::setParentAxes( QSAxes *axes )
{
QSCObject::setParentAxes( axes );
for( int i=0; i<objects()->count(); i++ ) objects()->object(i)->setParentAxes( axes );
}
//-------------------------------------------------------------//
void QSCGroup::slot_collection_changed()
{
emit sigUpdate(this);
emit sigUpdate();
}
//-------------------------------------------------------------//
void QSCGroup::slot_object_added( QSCObject *object )
// we hope that this signal is received by this object before any other object which also connects
// to QSCObjectCollection::sigAdded will get this signal. So this other object will see a newly added object
// which has already group() property set.
{
object->setGroup( this );
object->setParentAxes( parentAxes() );
}
//-------------------------------------------------------------//
void QSCGroup::slot_object_removed( QSCObject *object )
{
object->setGroup( NULL );
object->setParentAxes( NULL );
}
//-------------------------------------------------------------//
void QSCGroup::loadStateFromStream( QDataStream& stream, QSObjectFactory *factory )
{
QSCObject::loadStateFromStream( stream, factory );
int w_minus; stream >> w_minus; m_w_minus = (bool )w_minus;
int h_minus; stream >> h_minus; m_h_minus = (bool )h_minus;
m_objects->loadStateFromStream( stream, factory );
}
//-------------------------------------------------------------//
void QSCGroup::saveStateToStream( QDataStream& stream, QSObjectFactory *factory )
{
QSCObject::saveStateToStream( stream, factory );
stream << (int)m_w_minus;
stream << (int)m_h_minus;
m_objects->saveStateToStream( stream, factory );
}