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.

1093 lines
30 KiB

/***************************************************************************
qsaxes.cpp
-------------------
begin : 01-January-2000
copyright : (C) 2000 by Kamil Dobkowski
email : kamildobk@poczta.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"qsaxes.h"
#include"qsaxis.h"
#include"qsplot.h"
#include"qschildlist.h"
#include<assert.h>
#include<math.h>
#include<algo.h>
#include<qregexp.h>
#include<qtimer.h>
#include<qpainter.h>
struct QSAxes::qsaxes_private_data {
QSChildList<QSPlot> m_plots;
QSChildList<QSAxis> m_axes;
};
//-------------------------------------------------------------//
QSCAxesShadow::QSCAxesShadow( QSAxes *parent )
: QSCGroup(parent) {
m_parent_axes = parent;
connect( parent, SIGNAL(sigUpdate()), this, SLOT(slot_update()) );
connect( objects(), SIGNAL(sigAdded(QSCObject*)), this, SLOT(slot_object_added(QSCObject*)) );
connect( objects(), SIGNAL(sigRemoved(QSCObject*)), this, SLOT(slot_object_removed(QSCObject*)) );
}
//-------------------------------------------------------------//
QSCAxesShadow::~QSCAxesShadow() {
// parent axes object deletes itself after QSAxesShadow has been deleted.
// see QSAxes::childEvent
}
//-------------------------------------------------------------//
void QSCAxesShadow::setAutoUpdates( bool enabled ) {
QSCObject::setAutoUpdates( enabled );
m_parent_axes->setAutoUpdates( enabled );
}
//-------------------------------------------------------------//
void QSCAxesShadow::forceUpdate() {
m_parent_axes->forceUpdate();
}
//-------------------------------------------------------------//
void QSCAxesShadow::slot_update() {
QSCGroup::forceUpdate();
}
//-------------------------------------------------------------//
void QSCAxesShadow::setParentAxes( QSAxes * ) {
// can't change parent axes
}
//-------------------------------------------------------------//
void QSCAxesShadow::setBox( const QSRectf& rect, QSDrv *drv ) {
QSRectf r = rect.normalize();
m_parent_axes->setPosMM( QSPt2f( QSCoord::pixelsToMM(r.pos.x,drv->dpi),
QSCoord::pixelsToMM(r.pos.y,drv->dpi)) );
m_parent_axes->setSizeMM( QSPt2f( QSCoord::pixelsToMM(r.size.x,drv->dpi),
QSCoord::pixelsToMM(r.size.y,drv->dpi)) );
m_parent_axes->setCanvasRect(m_parent_axes->calculateCanvasRect(drv->dpi));
}
//-------------------------------------------------------------//
QSRectf QSCAxesShadow::box( QSDrv *drv ) {
return QSRectf( QSCoord::mmToPixels(m_parent_axes->posMM().x,drv->dpi),
QSCoord::mmToPixels(m_parent_axes->posMM().y,drv->dpi),
QSCoord::mmToPixels(m_parent_axes->sizeMM().x,drv->dpi),
QSCoord::mmToPixels(m_parent_axes->sizeMM().y,drv->dpi) );
}
//-------------------------------------------------------------//
bool QSCAxesShadow::isHit( const QSPt2f &p, QSDrv* drv )
{
return box(drv).contains(p) || m_objects->objectAt(p,drv,true);
}
//-------------------------------------------------------------//
bool QSCAxesShadow::isAxesShadow() {
return true;
}
//-------------------------------------------------------------//
int QSCAxesShadow::style() {
return Resizeable | Moveable;
}
//-------------------------------------------------------------//
QString QSCAxesShadow::name() {
return QString(tr("Axes: "))+m_parent_axes->title();
}
//-------------------------------------------------------------//
void QSCAxesShadow::draw( QSDrv *drv, bool blocking, bool transparent ) {
connect( m_parent_axes, SIGNAL(sigDrawEnds()), this, SLOT(slot_draw_ends()) );
connect( m_parent_axes, SIGNAL(sigUserDraw(QSDrv*,bool,bool)), this, SLOT(slot_draw_objects(QSDrv*,bool,bool)) );
bool blocking_drawing = !m_parent_axes->drawInBackground() || blocking;
m_parent_axes->setCanvasRect(m_parent_axes->calculateCanvasRect(drv->dpi));
m_parent_axes->drawPlot( drv, blocking_drawing, transparent );
}
//-------------------------------------------------------------//
void QSCAxesShadow::paint( QPainter *p, double dpi, bool blocking, bool transparent ) {
connect( m_parent_axes, SIGNAL(sigDrawEnds()), this, SLOT(slot_draw_ends()) );
connect( m_parent_axes, SIGNAL(sigUserDraw(QSDrv*,bool,bool)), this, SLOT(slot_draw_objects(QSDrv*,bool,bool)) );
bool blocking_drawing = !m_parent_axes->drawInBackground() || blocking;
m_parent_axes->setCanvasRect(m_parent_axes->calculateCanvasRect(dpi));
m_parent_axes->paintPlot( p, dpi, blocking_drawing, transparent );
}
//-------------------------------------------------------------//
void QSCAxesShadow::slot_draw_objects( QSDrv *drv, bool blocking, bool transparent ) {
disconnect( m_parent_axes, SIGNAL(sigUserDraw(QSDrv*,bool,bool)), this, SLOT(slot_draw_objects(QSDrv*,bool,bool)) );
m_objects->draw( drv, blocking, transparent );
}
//-------------------------------------------------------------//
void QSCAxesShadow::paintSkeleton( QPainter *p, double dpi ) {
m_parent_axes->setCanvasRect(m_parent_axes->calculateCanvasRect(dpi));
m_parent_axes->paintSkeleton(p,dpi,true);
m_objects->paintSkeleton(p,dpi);
}
//-------------------------------------------------------------//
void QSCAxesShadow::slot_draw_ends() {
disconnect( m_parent_axes, SIGNAL(sigDrawEnds()), this, SLOT(slot_draw_ends()) );
emit sigDrawEnds( this );
}
//-------------------------------------------------------------//
bool QSCAxesShadow::busy() const {
return ( m_parent_axes->state() == QSAxes::Busy );
}
//-------------------------------------------------------------//
void QSCAxesShadow::stop() {
m_parent_axes->stop();
}
//-------------------------------------------------------------//
void QSCAxesShadow::loadStateFromStream( QDataStream& stream, QSObjectFactory *factory ) {
QSCGroup::loadStateFromStream( stream, factory );
parentAxes()->loadStateFromStream( stream, factory );
}
//-------------------------------------------------------------//
void QSCAxesShadow::saveStateToStream( QDataStream& stream, QSObjectFactory *factory ) {
QSCGroup::saveStateToStream( stream, factory );
parentAxes()->saveStateToStream( stream, factory );
}
//-------------------------------------------------------------//
void QSCAxesShadow::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 parentAxes() property set.
{
object->setParentAxes( m_parent_axes );
}
//-------------------------------------------------------------//
void QSCAxesShadow::slot_object_removed( QSCObject *object )
{
object->setParentAxes( NULL );
}
//-------------------------------------------------------------//
QSCAxesShadow *QSAxes::shadowObject()
{
if ( !m_shadow_object ) m_shadow_object = new QSCAxesShadow( this );
return m_shadow_object;
}
//-------------------------------------------------------------//
void QSAxes::childEvent ( QChildEvent *e )
{
if ( e->removed() && e->child() == shadowObject() ) delete this;
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
QSAxes::QSAxes(QObject* parent, const QSProjection *proj, const char* name )
:QSGraphicalData(parent, NULL, name )
{
m_internal_state = Waiting;
m_bkg_handler = true;
m_auto_updates = true;
m_is_complete = false;
m_axes_only = false;
m_really_fast = false;
m_delete_driver = false;
m_runtime_data_allocated = false;
m_shadow_object = NULL;
m_bckg_fill = QSGFill::transparentFill;
m_transformation_rect = false;
m_draw_in_background = true;
m_proj = proj;
m_curr_dpi = 72.0;
m_cpos.set( 0.0, 0.0 );
m_csize.set( 100.0, 100.0 );
m_pos_mm.set( 20.0, 20.0 );
m_size_mm.set( 100.0, 100.0 );
m_m.l = 0;
m_m.r = 0;
m_m.t = 0;
m_m.b = 0;
d = new qsaxes_private_data();
m_timer = new QTimer( this );
connect( m_timer, SIGNAL(timeout()), this, SLOT(work_proc()) );
// default axes
axisAdd( new QSAxis( QSAxis::XAxisType, this ) );
axisAdd( new QSAxis( QSAxis::YAxisType, this ) );
axisAdd( new QSAxis( QSAxis::ZAxisType, this ) );
axisAdd( new QSAxis( QSAxis::VAxisType, this ) );
}
//-------------------------------------------------------------//
QSAxes::~QSAxes()
{
stop();
delete d;
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
// Graphics attributes
void QSAxes::setPosMM( const QSPt2f& new_pos_mm )
{
SET_PROPERTY( m_pos_mm, new_pos_mm );
}
//-------------------------------------------------------------//
void QSAxes::setXPosMM( double x_mm )
{
SET_PROPERTY( m_pos_mm.x, x_mm );
}
//-------------------------------------------------------------//
void QSAxes::setYPosMM( double y_mm )
{
SET_PROPERTY( m_pos_mm.y, y_mm );
}
//-------------------------------------------------------------//
void QSAxes::setSizeMM( const QSPt2f& new_size_mm )
{
SET_PROPERTY( m_size_mm, new_size_mm );
}
//-------------------------------------------------------------//
void QSAxes::setWidthMM( double w_mm )
{
SET_PROPERTY( m_size_mm.x, w_mm );
}
//-------------------------------------------------------------//
void QSAxes::setHeightMM( double h_mm )
{
SET_PROPERTY( m_size_mm.y, h_mm );
}
//-------------------------------------------------------------//
void QSAxes::setDrawInBackground( bool enabled )
{
SET_PROPERTY( m_draw_in_background, enabled );
}
//-------------------------------------------------------------//
void QSAxes::setAxesOnly( bool enabled )
{
SET_PROPERTY( m_axes_only, enabled );
}
//-------------------------------------------------------------//
void QSAxes::setBackground( const QSGFill& fill )
{
SET_PROPERTY( m_bckg_fill, fill );
}
//-------------------------------------------------------------//
QSGFill QSAxes::background() const
{
return m_transparent ? m_bckg_fill : QSGFill();
}
//-------------------------------------------------------------//
void QSAxes::set_background_property( const QString& value )
{
setBackground( toQSGFill(value) );
}
//-------------------------------------------------------------//
QString QSAxes::background_property() const
{
return toQString(background());
}
//-------------------------------------------------------------//
void QSAxes::setAutoUpdates( bool enabled )
{
m_auto_updates = enabled;
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
double QSAxes::canvasToNormalizedX( double value ) const
{
return m_csize.x>0.0 ? ((value-m_cpos.x)/m_csize.x) : 0.0;
}
//-------------------------------------------------------------//
double QSAxes::canvasToNormalizedY( double value ) const
{
return m_csize.y>0.0 ? ((value-m_cpos.y)/m_csize.y) : 0.0;
}
//-------------------------------------------------------------//
QSPt2f QSAxes::canvasToNormalized( const QSPt2f& pos ) const
{
return QSPt2f( m_csize.x>0.0 ? ((pos.x-m_cpos.x)/m_csize.x) : 0.0,
m_csize.y>0.0 ? ((pos.y-m_cpos.y)/m_csize.y) : 0.0 );
}
//-------------------------------------------------------------//
double QSAxes::normalizedXToCanvas( double x ) const
{
return m_cpos.x + x * m_csize.x;
}
//-------------------------------------------------------------//
double QSAxes::normalizedYToCanvas( double y ) const
{
return m_cpos.y + y * m_csize.y;
}
//-------------------------------------------------------------//
QSPt2f QSAxes::normalizedToCanvas( const QSPt2f& pos ) const
{
return QSPt2f( m_cpos.x + pos.x * m_csize.x,
m_cpos.y + pos.y * m_csize.y );
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
QSPt2f QSAxes::dataToCanvas( const QSPt3f& pos, QSAxis *xAxis, QSAxis *yAxis, QSAxis *zAxis ) const
{
return m_proj->world3DToCanvas( QSPt3f( xAxis->dataToWorld( pos.x ),
yAxis->dataToWorld( pos.y ),
zAxis->dataToWorld( pos.z ) ) );
}
//-------------------------------------------------------------//
QSPt2f QSAxes::dataToCanvas( const QSPt2f& pos, QSAxis *xAxis, QSAxis *yAxis ) const
{
return m_proj->world2DToCanvas( QSPt2f( xAxis->dataToWorld( pos.x ),
yAxis->dataToWorld( pos.y ) ) );
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
// d->m_plots
//-------------------------------------------------------------//
int QSAxes::plotCount() const
{
return d->m_plots.count();
}
//-------------------------------------------------------------//
void QSAxes::plotAdd( QSPlot *p )
{
if ( p ) {
parametersChanging();
d->m_plots.add( p );
emit sigChildAdded( p );
emit sigChildListChanged();
parametersChanged();
}
}
//-------------------------------------------------------------//
void QSAxes::plotInsert( int beforePos, QSPlot *p )
{
if ( p ) {
parametersChanging();
d->m_plots.insert( beforePos, p );
emit sigChildAdded( p );
emit sigChildListChanged();
parametersChanged();
}
}
//-------------------------------------------------------------//
void QSAxes::plotRemove( QSPlot *p )
// not deleted
// signal emmited after removal !!!!!!
{
if ( p ) {
parametersChanging();
if ( d->m_plots.remove(d->m_plots.find(p)) ) {
emit sigChildRemoved( p );
emit sigChildListChanged();
}
parametersChanged();
}
}
//-------------------------------------------------------------//
void QSAxes::plotDelete( QSPlot *p )
{
if ( p ) {
parametersChanging();
if ( d->m_plots.remove(d->m_plots.find(p)) ) {
emit sigChildRemoved( p );
emit sigChildListChanged();
delete p;
}
parametersChanged();
}
}
//-------------------------------------------------------------//
QSPlot *QSAxes::plot( int index ) const
{
return d->m_plots[index];
}
//-------------------------------------------------------------//
int QSAxes::plotIndex( QSPlot *o ) const
{
return d->m_plots.find(o);
}
//-------------------------------------------------------------//
void QSAxes::plotToFront( QSPlot *o )
{
parametersChanging();
d->m_plots.toFront( d->m_plots.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSAxes::plotToBack( QSPlot *o )
{
parametersChanging();
d->m_plots.toBack( d->m_plots.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSAxes::plotLower( QSPlot *o )
{
parametersChanging();
d->m_plots.lower( d->m_plots.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSAxes::plotRaise( QSPlot *o )
{
parametersChanging();
d->m_plots.raise( d->m_plots.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSAxes::plotReorder( int position, QSPlot *o )
{
parametersChanging();
d->m_plots.reorder( position, d->m_plots.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
int QSAxes::axisCount() const
{
return d->m_axes.count();
}
//-------------------------------------------------------------//
void QSAxes::axisAdd( QSAxis *p )
{
if ( p ) {
parametersChanging();
d->m_axes.add( p );
emit sigChildAdded( p );
emit sigChildListChanged();
parametersChanged();
}
}
//-------------------------------------------------------------//
void QSAxes::axisInsert( int beforePos, QSAxis *p )
{
if ( p ) {
parametersChanging();
d->m_axes.insert( beforePos, p );
emit sigChildAdded( p );
emit sigChildListChanged();
parametersChanged();
}
}
//-------------------------------------------------------------//
bool QSAxes::axisRemove( QSAxis *a )
// not deleted
// signal emitted after removal !!!!!
{
if ( a ) {
// can't remove the last axis of the given type
int axes_count = 0;
for( int i=0; i<axisCount(); i++ ) if ( axis(i)->type() == a->type() ) axes_count++;
if ( axes_count < 2 && a->type() != QSAxis::UnknownAxisType ) return false;
parametersChanging();
if ( d->m_axes.remove(d->m_axes.find(a)) ) {
emit sigChildRemoved( a );
emit sigChildListChanged();
}
parametersChanged();
return true;
}
return false;
}
//-------------------------------------------------------------//
bool QSAxes::axisDelete( QSAxis *a )
{
if ( a ) {
// can't remove the last axis of the given type
int axes_count = 0;
for( int i=0; i<axisCount(); i++ ) if ( axis(i)->type() == a->type() ) axes_count++;
if ( axes_count < 2 ) return false;
parametersChanging();
if ( d->m_axes.remove(d->m_axes.find(a)) ) {
emit sigChildRemoved( a );
emit sigChildListChanged();
delete a;
}
parametersChanged();
return true;
}
return false;
}
//-------------------------------------------------------------//
QSAxis *QSAxes::axis( int index ) const
{
return d->m_axes[index];
}
//-------------------------------------------------------------//
int QSAxes::axisIndex( QSAxis *o ) const
{
return d->m_axes.find(o);
}
//-------------------------------------------------------------//
QSAxis *QSAxes::axisOfType( int type ) const
{
for ( int axis_nr=0; axis_nr<axisCount(); axis_nr++ )
if ( axis(axis_nr)->type() == type ) return axis(axis_nr);
return NULL;
}
//-------------------------------------------------------------//
void QSAxes::axisToFront( QSAxis *o )
{
parametersChanging();
d->m_axes.toFront( d->m_axes.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSAxes::axisToBack( QSAxis *o )
{
parametersChanging();
d->m_axes.toBack( d->m_axes.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSAxes::axisLower( QSAxis *o )
{
parametersChanging();
d->m_axes.lower( d->m_axes.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSAxes::axisRaise( QSAxis *o )
{
parametersChanging();
d->m_axes.raise( d->m_axes.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
void QSAxes::axisReorder( int position, QSAxis *o )
{
parametersChanging();
d->m_axes.reorder( position, d->m_axes.find(o) );
emit sigChildOrder();
emit sigChildListChanged();
parametersChanged();
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
int QSAxes::childCount() const
{
return axisCount()+plotCount();
}
//-------------------------------------------------------------//
QSData *QSAxes::child( int index ) const
{
return ( index < axisCount() ? (QSData *)axis(index) : (QSData *)plot(index-axisCount()) );
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
// Parameters/Data changing
//-------------------------------------------------------------//
void QSAxes::parametersChanging()
{
stop();
QSGraphicalData::parametersChanging();
}
//-------------------------------------------------------------//
void QSAxes::parametersChanged()
{
stop();
if ( m_auto_updates ) emit sigUpdate();
}
//-------------------------------------------------------------//
void QSAxes::dataChanging( QSData *object, int channel )
{
stop();
QSGraphicalData::dataChanging( object, channel );
}
//-------------------------------------------------------------//
void QSAxes::dataChanged( QSData *object, int channel )
{
stop();
QSGraphicalData::dataChanged(object,channel);
if ( m_auto_updates ) emit sigUpdate();
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
// Redrawing
//-------------------------------------------------------------//
void QSAxes::start( QSDrv *init_drv, bool blocking, bool transparent )
{
if ( m_internal_state == Busy ) stop();
m_bkg_handler = !blocking && !m_axes_only;
if ( m_bkg_handler ) {
m_drv = init_drv->copy();
m_delete_driver = true;
} else {
m_drv = init_drv;
m_delete_driver = false;
}
m_curr_dpi = m_drv->dpi;
m_is_complete = false;
m_blocking = blocking;
m_transparent = transparent;
d->m_plots.setPos( 0 );
m_drv->setCurrentElement( GeneralCategory, 0 );
m_internal_state = Busy;
allocRuntimeData();
m_runtime_data_allocated = true;
calculate_auto_ranges();
axisRangesCalculated();
// draw minor grid
if ( !m_really_fast )
for( int axis=0; axis < d->m_axes.count(); axis++ ) {
m_drv->setCurrentElement( GridCategory, axis );
drawGrid( d->m_axes[axis], false );
}
// draw major grid
if ( !m_really_fast )
for( int axis=0; axis < d->m_axes.count(); axis++ ) {
m_drv->setCurrentElement( GridCategory, axis );
drawGrid( d->m_axes[axis], true );
}
// draw axes
for( int axis=0; axis < d->m_axes.count(); axis++ ) {
m_drv->setCurrentElement( AxisCategory, axis );
drawAxis( d->m_axes[axis] );
}
// start drawing datasets - see work_proc() for the rest.
m_curr_dataset_nr = 0;
m_drv->setClipping( true );
if ( d->m_plots.isValidPos() && !m_axes_only ) {
m_drv->setCurrentElement( DatasetCategory, m_curr_dataset_nr++ );
m_current_started = d->m_plots.current()->start();
if ( m_bkg_handler ) m_timer->start( 0, FALSE );
else while( d->m_plots.isValidPos() ) work_proc();
} else {
d->m_plots.setPos( d->m_plots.count() ); // immediately move to the end
stop();
}
}
//-------------------------------------------------------------//
void QSAxes::work_proc()
// drawing datasets
{
if ( !m_current_started || !d->m_plots.current()->step() ) {
d->m_plots.current()->end();
d->m_plots.setPos( d->m_plots.pos() + 1 );
if ( d->m_plots.isValidPos() ) {
m_drv->setCurrentElement( DatasetCategory, m_curr_dataset_nr++ );
m_current_started = d->m_plots.current()->start();
} else {
stop();
}
}
}
//-------------------------------------------------------------//
void QSAxes::stop()
// stop drawing now.
// Make sure that next drawing will start from beginnig.
{
if ( m_internal_state == Busy ) {
// not completed !
if ( d->m_plots.isValidPos() ) { d->m_plots.current()->end(); }
emit sigUserDraw( m_drv, m_blocking, m_transparent );
m_timer->stop();
}
d->m_plots.setPos( d->m_plots.count() );
if ( m_runtime_data_allocated ) freeRuntimeData();
m_runtime_data_allocated = false;
if ( m_delete_driver ) delete m_drv;
m_delete_driver = false;
m_drv = NULL;
if ( m_internal_state == Busy ) {
m_internal_state = Waiting;
emit sigDrawEnds();
}
}
//-------------------------------------------------------------//
void QSAxes::calculate_auto_ranges()
{
// initialize axes
for ( int axis=0; axis<d->m_axes.count(); axis++ ) {
bool first_time = true;
bool is_data = false;
double data_min = 1.0;
double data_max = 1.0;
for ( int i=0; i<d->m_plots.count(); i++ ) {
double min = 0.0;
double max = 0.0;
if ( d->m_plots[i]->getAxisRange(d->m_axes[axis],min,max) ) {
is_data = true;
if ( first_time ) {
first_time = false;
data_min = min;
data_max = max;
} else {
data_min = QMIN( data_min, min );
data_max = QMAX( data_max, max );
}
}
}
d->m_axes[axis]->initAxis( data_min, data_max, is_data );
}
}
//-------------------------------------------------------------//
QString QSAxes::posInfo( QSPt2f& pos )
{
QString result = QString::null;
for( int i=plotCount()-1; i>=0; i-- )
if ( (result=plot(i)->posInfo(pos)) != QString::null ) {
result = tr(" You clicked at:\n\n Plot ") + QString::number(i) + QString(" : ") + plot(i)->title() + "\n\n" + result;
return result;
}
return result;
}
//-------------------------------------------------------------//
QSRectf QSAxes::calculateCanvasRect( double dpi )
{
return QSRectf( QSCoord::mmToPixels(posMM().x,dpi),
QSCoord::mmToPixels(posMM().y,dpi),
QSCoord::mmToPixels(sizeMM().x,dpi),
QSCoord::mmToPixels(sizeMM().y,dpi) );
}
//-------------------------------------------------------------//
void QSAxes::paintSkeleton( QPainter *p, double dpi, bool reallyFast )
{
m_really_fast = reallyFast;
bool m_prev_axes_only = m_axes_only;
m_axes_only = true;
paintPlot(p,dpi,true,true);
m_axes_only = m_prev_axes_only;
m_really_fast = false;
}
//-------------------------------------------------------------//
void QSAxes::initMappings( QSDrv *init_drv )
{
if ( !state() ) {
calculate_auto_ranges();
m_drv = init_drv;
m_curr_dpi = m_drv->dpi;
}
}
//-------------------------------------------------------------//
void QSAxes::setCanvasRect( const QSRectf& r )
{
m_cpos.x = r.pos.x;
m_cpos.y = r.pos.y;
m_csize.x = r.size.x;
m_csize.y = r.size.y;
}
//-------------------------------------------------------------//
void QSAxes::setFitToCanvasRect( bool enabled )
{
m_transformation_rect = enabled;
}
//-------------------------------------------------------------//
void QSAxes::rememberCurrentView( int index )
{
if ( index >=0 && index < 3 )
for( int i=0; i<axisCount(); i++ ) axis(i)->rememberCurrentView( index );
}
//-------------------------------------------------------------//
void QSAxes::setRememberedView( int index )
{
if ( index >=0 && index < 3 )
for( int i=0; i<axisCount(); i++ ) axis(i)->setRememberedView( index );
}
//-------------------------------------------------------------//
void QSAxes::loadStateFromStream( QDataStream& stream, QSObjectFactory *factory )
{
QSGraphicalData::loadStateFromStream( stream, factory );
// load all axes
int axes_to_delete = axisCount();
int axis_count; stream >> axis_count;
for( int i=0; i<axis_count; i++ ) {
QSAxis *new_axis = dynamic_cast<QSAxis*>(factory->loadObjectFromStream(stream,this));
assert( new_axis ); axisAdd( new_axis );
}
for( int i=0; i<axes_to_delete; i++ ) {
axisDelete( axis(0) );
}
// load datasets
for( int i=0; i<plotCount(); i++ ) {
plotDelete( plot(i) );
}
int plot_count; stream >> plot_count;
for( int i=0; i<plot_count; i++ ) {
QSPlot *new_plot = dynamic_cast<QSPlot*>(factory->loadObjectFromStream(stream,this));
assert( new_plot ); plotAdd( new_plot );
}
}
//-------------------------------------------------------------//
void QSAxes::saveStateToStream( QDataStream& stream, QSObjectFactory *factory )
{
QSGraphicalData::saveStateToStream( stream, factory );
// save all axes
stream << (int)axisCount();
for( int i=0; i<axisCount(); i++ ) {
factory->saveObjectToStream( axis(i), stream );
}
// save all datasets
stream << (int)plotCount();
for( int i=0; i<plotCount(); i++ ) {
factory->saveObjectToStream( plot(i), stream );
}
}
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
QSAxesChild::QSAxesChild( QSAxes *parentAxes, const char *name )
:QSGraphicalData(NULL,parentAxes,name)
{
assert(parentAxes);
m_axes = parentAxes;
}
//-------------------------------------------------------------//
QSAxesChild::~QSAxesChild()
{
}