157 lines
3.5 KiB
C++
157 lines
3.5 KiB
C++
/******************************************************************************
|
|
* QSkinny - Copyright (C) The authors
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*****************************************************************************/
|
|
|
|
#include "QskPlotCurve.h"
|
|
#include "QskPlotCurveData.h"
|
|
|
|
#include <qpointer.h>
|
|
#include <qcolor.h>
|
|
|
|
QSK_SUBCONTROL( QskPlotCurve, Line )
|
|
|
|
class QskPlotCurve::PrivateData
|
|
{
|
|
public:
|
|
QPointer< QskPlotCurveData > curveData;
|
|
};
|
|
|
|
QskPlotCurve::QskPlotCurve( QObject* object )
|
|
: Inherited( object )
|
|
, m_data( new PrivateData )
|
|
{
|
|
}
|
|
|
|
QskPlotCurve::~QskPlotCurve()
|
|
{
|
|
}
|
|
|
|
void QskPlotCurve::setColor( const QColor& color )
|
|
{
|
|
if ( setColor( Line, color ) )
|
|
{
|
|
markDirty();
|
|
Q_EMIT colorChanged( color );
|
|
}
|
|
}
|
|
|
|
QColor QskPlotCurve::color() const
|
|
{
|
|
return color( Line );
|
|
}
|
|
|
|
void QskPlotCurve::setLineWidth( qreal lineWidth )
|
|
{
|
|
lineWidth = qMax( lineWidth, 0.0 );
|
|
|
|
if ( setMetric( Line | QskAspect::Size, lineWidth ) )
|
|
{
|
|
markDirty();
|
|
Q_EMIT lineWidthChanged( lineWidth );
|
|
}
|
|
}
|
|
|
|
qreal QskPlotCurve::lineWidth() const
|
|
{
|
|
return metric( Line | QskAspect::Size );
|
|
}
|
|
|
|
void QskPlotCurve::setPoints( const QVector< QPointF >& points )
|
|
{
|
|
setData( new QskPlotCurvePoints( points, this ) );
|
|
}
|
|
|
|
void QskPlotCurve::setData( QskPlotCurveData* curveData )
|
|
{
|
|
if ( curveData == m_data->curveData )
|
|
return;
|
|
|
|
auto oldData = m_data->curveData.data();
|
|
m_data->curveData = curveData;
|
|
|
|
if ( oldData )
|
|
{
|
|
if ( oldData->parent() == this )
|
|
delete oldData;
|
|
else
|
|
disconnect( oldData, &QskPlotCurveData::changed, this, &QskPlotItem::markDirty );
|
|
}
|
|
|
|
if ( curveData )
|
|
{
|
|
if ( curveData->parent() == nullptr )
|
|
curveData->setParent( this );
|
|
|
|
connect( curveData, &QskPlotCurveData::changed, this, &QskPlotItem::markDirty );
|
|
}
|
|
|
|
markDirty();
|
|
}
|
|
|
|
QskPlotCurveData* QskPlotCurve::data() const
|
|
{
|
|
return m_data->curveData;
|
|
}
|
|
|
|
QPointF QskPlotCurve::interpolatedPoint(
|
|
Qt::Orientation orientation, qreal value ) const
|
|
{
|
|
if ( m_data->curveData )
|
|
return m_data->curveData->interpolatedPoint( orientation, value );
|
|
|
|
return QPointF();
|
|
}
|
|
|
|
void QskPlotCurve::transformationChanged( ChangeFlags flags )
|
|
{
|
|
if ( flags & ( XBoundariesChanged | YBoundariesChanged ) )
|
|
{
|
|
/*
|
|
We could skip updates, when the curve is inside
|
|
of old and new boundaries TODO ...
|
|
*/
|
|
}
|
|
|
|
Inherited::transformationChanged( flags );
|
|
}
|
|
|
|
bool QskPlotCurve::needsClipping() const
|
|
{
|
|
auto data = m_data->curveData.data();
|
|
if ( data == nullptr || data->count() == 0 )
|
|
return false;
|
|
|
|
// The skinlet does basic polygon clipping for monotonic data.
|
|
|
|
using D = QskPlotCurveData;
|
|
|
|
const auto hints = data->hints();
|
|
if ( ( hints & D::MonotonicX ) && ( hints & D::MonotonicY ) )
|
|
return false;
|
|
|
|
if ( data->hints() & QskPlotCurveData::BoundingRectangle )
|
|
{
|
|
const auto curveRect = data->boundingRect();
|
|
const auto plotRect = scaleRect();
|
|
|
|
if ( hints & D::MonotonicX )
|
|
{
|
|
return ( curveRect.top() < plotRect.top() )
|
|
|| ( curveRect.bottom() > plotRect.bottom() );
|
|
}
|
|
|
|
if ( hints & D::MonotonicY )
|
|
{
|
|
return ( curveRect.left() < plotRect.left() )
|
|
&& ( curveRect.right() > plotRect.right() );
|
|
}
|
|
|
|
return !plotRect.contains( curveRect );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#include "moc_QskPlotCurve.cpp"
|