* *
***************************************************************************/
-#include <math.h> //for log10(), pow(), modf()
-
#include <kdebug.h>
#include <qevent.h>
#include <QPolygon>
#include <QToolTip>
#include <QtAlgorithms>
+#include <klocale.h>
#include "kplotwidget.h"
#include "kplotwidget.moc"
#define YPADDING 20
KPlotWidget::KPlotWidget( double x1, double x2, double y1, double y2, QWidget *parent )
- : QFrame( parent ),
- dXtick(0.0), dYtick(0.0),
- nmajX(0), nminX(0), nmajY(0), nminY(0),
- ShowTickMarks( true ), ShowTickLabels( true ), ShowGrid( false ), ShowObjectToolTips( true )
+ : QFrame( parent ), ShowGrid( false ), ShowObjectToolTips( true ), UseAntialias( false )
{
setAttribute( Qt::WA_NoBackground, true );
- // creating the axes
+ // create the axes
mAxes[LeftAxis] = new KPlotAxis();
mAxes[BottomAxis] = new KPlotAxis();
+ mAxes[RightAxis] = new KPlotAxis();
+ mAxes[TopAxis] = new KPlotAxis();
//set DataRect
setLimits( x1, x2, y1, y2 );
- setDefaultPaddings();
+ SecondDataRect = QRect(); //default: no secondary data rect
- //Set PixRect
- recalcPixRect();
+ //By default, the left and bottom axes have tickmark labels
+ axis(LeftAxis)->setShowTickLabels( true );
+ axis(BottomAxis)->setShowTickLabels( true );
- buffer = new QPixmap();
+ setDefaultPaddings();
//default colors:
setBackgroundColor( Qt::black );
KPlotWidget::~KPlotWidget()
{
- delete (buffer);
qDeleteAll( ObjectList );
ObjectList.clear();
qDeleteAll( mAxes );
if ( y2<y1) { YA1=y2; YA2=y1; }
else { YA1=y1; YA2=y2; }
+ if ( XA2 == XA1 ) {
+ kWarning() << k_funcinfo << ": " <<
+ i18n("x1 and x2 cannot be equal. Setting x2 = x1 + 1.0") << endl;
+ XA2 = XA1 + 1.0;
+ }
+ if ( YA2 == YA1 ) {
+ kWarning() << k_funcinfo << ": " <<
+ i18n("y1 and y2 cannot be equal. Setting y2 = y1 + 1.0") << endl;
+ YA2 = YA1 + 1.0;
+ }
DataRect = QRectF( XA1, YA1, XA2-XA1, YA2-YA1 );
- updateTickmarks();
- update();
-}
-void KPlotWidget::updateTickmarks() {
- // Determine the number and spacing of tickmarks for the current plot limits.
- if ( dataWidth() == 0.0 ) {
- kWarning() << "KPlotWidget::updateTickmarks(): X range [" << x() << ", " << x2() << "] invalid!" << endl;
- DataRect.setWidth( 1.0 );
- return;
- }
- if ( dataHeight() == 0.0 ) {
- kWarning() << "KPlotWidget::updateTickmarks(): Y range [" << y() << ", " << y2() << "] invalid!" << endl;
- DataRect.setHeight( 1.0 );
- return;
+ axis(LeftAxis)->setTickMarks( y(), dataHeight() );
+ axis(BottomAxis)->setTickMarks( x(), dataWidth() );
+
+ if ( secondaryDataRect().isNull() ) {
+ axis(RightAxis)->setTickMarks( y(), dataHeight() );
+ axis(TopAxis)->setTickMarks( x(), dataWidth() );
}
- calcTickMarks( DataRect.width(), dXtick, nmajX, nminX );
- calcTickMarks( DataRect.height(), dYtick, nmajY, nminY );
+ update();
}
-void KPlotWidget::calcTickMarks( double length, double& dTick, int& nmajor, int& nminor ) {
- //s is the power-of-ten factor of length:
- //length = t * s; s = 10^(pwr). e.g., length=350.0 then t=3.5, s = 100.0; pwr = 2.0
- double pwr = 0.0;
- modf( log10( length ), &pwr );
- double s = pow( 10.0, pwr );
- double t = length / s;
-
- //adjust s and t such that t is between 3 and 5:
- if ( t < 3.0 ) {
- t *= 10.0;
- s /= 10.0;
- // t now between 3 and 30
+void KPlotWidget::setSecondaryLimits( double x1, double x2, double y1, double y2 ) {
+ double XA1, XA2, YA1, YA2;
+ if (x2<x1) { XA1=x2; XA2=x1; }
+ else { XA1=x1; XA2=x2; }
+ if ( y2<y1) { YA1=y2; YA2=y1; }
+ else { YA1=y1; YA2=y2; }
+
+ if ( XA2 == XA1 ) {
+ kWarning() << k_funcinfo << ": " <<
+ i18n("x1 and x2 cannot be equal. Setting x2 = x1 + 1.0") << endl;
+ XA2 = XA1 + 1.0;
}
- double _dTick = 0.0;
- int _nmajor = 0;
- int _nminor = 0;
- if ( t < 6.0 ) { //accept current values
- _dTick = s;
- _nmajor = int( t );
- _nminor = 5;
- } else if ( t < 10.0 ) { //factor of 2
- _dTick = s * 2.0;
- _nmajor = int( t / 2.0 );
- _nminor = 4;
- } else if ( t < 20.0 ) { //factor of 4
- _dTick = s * 4.0;
- _nmajor = int( t / 4.0 );
- _nminor = 4;
- } else { //factor of 5
- _dTick = s * 5.0;
- _nmajor = int( t / 5.0 );
- _nminor = 5;
+ if ( YA2 == YA1 ) {
+ kWarning() << k_funcinfo << ": " <<
+ i18n("y1 and y2 cannot be equal. Setting y2 = y1 + 1.0") << endl;
+ YA2 = YA1 + 1.0;
}
+ SecondDataRect = QRectF( XA1, YA1, XA2-XA1, YA2-YA1 );
- nmajor = _nmajor;
- nminor = _nminor;
- dTick = _dTick;
+ axis(RightAxis)->setTickMarks( SecondDataRect.y(), SecondDataRect.height() );
+ axis(TopAxis)->setTickMarks( SecondDataRect.x(), SecondDataRect.width() );
+
+ update();
}
void KPlotWidget::addObject( KPlotObject *o ) {
update();
}
-void KPlotWidget::setShowAxes( bool show ) {
- QHash<Axis, KPlotAxis*>::iterator itEnd = mAxes.end();
- for ( QHash<Axis, KPlotAxis*>::iterator it = mAxes.begin(); it != itEnd; ++it ) {
- (*it)->setVisible(show);
- }
- update();
-}
-
-
-void KPlotWidget::setShowTickMarks( bool show ) {
- ShowTickMarks = show;
- update();
-}
-
-void KPlotWidget::setShowTickLabels( bool show ) {
- ShowTickLabels = show;
- recalcPixRect();
- update();
-}
-
void KPlotWidget::setShowGrid( bool show ) {
ShowGrid = show;
update();
return mAxes.contains( a ) ? mAxes[a] : 0;
}
-void KPlotWidget::recalcPixRect() {
- int newWidth = contentsRect().width() - leftPadding() - rightPadding();
- int newHeight = contentsRect().height() - topPadding() - bottomPadding();
- // PixRect starts at (0,0) because we will translate by leftPadding(), topPadding()
- PixRect = QRect( 0, 0, newWidth, newHeight );
-}
-
QList<KPlotObject*> KPlotWidget::pointsUnderPoint( const QPoint& p ) const {
QList<KPlotObject*> pts;
for ( QList<KPlotObject*>::ConstIterator it = ObjectList.begin(); it != ObjectList.constEnd(); ++it ) {
}
void KPlotWidget::resizeEvent( QResizeEvent* /* e */ ) {
- recalcPixRect();
+ update();
+}
- QPixmap *tmp = new QPixmap( contentsRect().size() );
- delete buffer;
- buffer = tmp;
- tmp = 0;
+void KPlotWidget::setPixRect() {
+ int newWidth = contentsRect().width() - leftPadding() - rightPadding();
+ int newHeight = contentsRect().height() - topPadding() - bottomPadding();
+ // PixRect starts at (0,0) because we will translate by leftPadding(), topPadding()
+ PixRect = QRect( 0, 0, newWidth, newHeight );
}
void KPlotWidget::paintEvent( QPaintEvent *e ) {
QFrame::paintEvent( e );
QPainter p;
- p.begin( buffer );
- p.fillRect( buffer->rect(), backgroundColor() );
+ p.begin( this );
+ p.setRenderHint( QPainter::Antialiasing, UseAntialias );
+ p.fillRect( rect(), backgroundColor() );
p.translate( leftPadding(), topPadding() );
+ setPixRect();
p.setClipRect( PixRect );
p.setClipping( true );
drawObjects( &p );
p.setClipping( false );
- drawBox( &p );
+ drawAxes( &p );
p.end();
- p.begin( this );
- p.drawPixmap( contentsRect().topLeft(), *buffer );
- p.end();
}
void KPlotWidget::drawObjects( QPainter *p ) {
}
}
-void KPlotWidget::drawBox( QPainter *p ) {
+void KPlotWidget::drawAxes( QPainter *p ) {
if ( ShowGrid ) {
- //Grid lines are placed at locations of primary axes' major tickmarks
p->setPen( gridColor() );
+ //Grid lines are placed at locations of primary axes' major tickmarks
//vertical grid lines
- double x0 = x() - fmod( x(), dXtick ); //zeropoint; x(i) is this plus i*dXtick1
- for ( int ix = 0; ix <= nmajX; ix++ ) {
- int px = int( PixRect.width() * ( (x0 + ix*dXtick - x())/dataWidth() ) );
- p->drawLine( px, 0, px, PixRect.height() );
+ foreach ( double xx, axis(BottomAxis)->majorTickMarks() ) {
+ double px = PixRect.width() * (xx - x()) / dataWidth();
+ p->drawLine( QPointF( px, 0.0 ), QPointF( px, double(PixRect.height()) ) );
}
-
//horizontal grid lines
- double y0 = y() - fmod( y(), dYtick ); //zeropoint; y(i) is this plus i*mX
- for ( int iy = 0; iy <= nmajY; iy++ ) {
- int py = PixRect.height() - int( PixRect.height() * ( (y0 + iy*dYtick - y())/dataHeight() ) );
- p->drawLine( 0, py, PixRect.width(), py );
+ foreach( double yy, axis(LeftAxis)->majorTickMarks() ) {
+ double py = PixRect.height() * (yy - y()) / dataHeight();
+ p->drawLine( QPointF( 0.0, py ), QPointF( double(PixRect.width()), py ) );
}
}
p->setPen( foregroundColor() );
p->setBrush( Qt::NoBrush );
- if (mAxes[BottomAxis]->isVisible() || mAxes[LeftAxis]->isVisible()) p->drawRect( PixRect ); //box outline
-
- if ( ShowTickMarks ) {
- //spacing between minor tickmarks (in data units)
- double dminX = dXtick/nminX;
- double dminY = dYtick/nminY;
-
- //set small font for tick labels
- QFont f = p->font();
- int s = f.pointSize();
- f.setPointSize( s - 2 );
- p->setFont( f );
-
- //--- Draw bottom X Axis ---//
- if (mAxes[BottomAxis]->isVisible()) {
- // Draw X tickmarks
- double x0 = x() - fmod( x(), dXtick ); //zeropoint; tickmark i is this plus i*dXtick (in data units)
- if ( x() < 0.0 ) x0 -= dXtick;
-
- for ( int ix = 0; ix <= nmajX+1; ix++ ) {
- //position of tickmark i (in screen units)
- int px = int( PixRect.width() * ( (x0 + ix*dXtick - x() )/dataWidth() ) );
-
- if ( px > 0 && px < PixRect.width() ) {
- p->drawLine( px, PixRect.height() - 2, px, PixRect.height() - BIGTICKSIZE - 2 );
- p->drawLine( px, 0, px, BIGTICKSIZE );
+ //set small font for tick labels
+ QFont f = p->font();
+ int s = f.pointSize();
+ f.setPointSize( s - 2 );
+ p->setFont( f );
+
+ /*** BottomAxis ***/
+ KPlotAxis *a = axis(BottomAxis);
+ if (a->isVisible()) {
+ //Draw axis line
+ p->drawLine( 0, PixRect.height(), PixRect.width(), PixRect.height() );
+
+ // Draw major tickmarks
+ foreach( double xx, a->majorTickMarks() ) {
+ double px = PixRect.width() * (xx - x()) / dataWidth();
+ if ( px > 0 && px < PixRect.width() ) {
+ p->drawLine( QPointF( px, double(PixRect.height() - 2.0)),
+ QPointF( px, double(PixRect.height() - BIGTICKSIZE - 2.0)) );
+
+ //Draw ticklabel
+ if ( a->showTickLabels() ) {
+ QRect r( int(px) - BIGTICKSIZE, PixRect.height()+BIGTICKSIZE, 2*BIGTICKSIZE, BIGTICKSIZE );
+ p->drawText( r, Qt::AlignCenter | Qt::TextDontClip, a->tickLabel( xx ) );
}
-
- //tick label
- if ( ShowTickLabels ) {
- double lab = x0 + ix*dXtick;
- if ( fabs(lab)/dXtick < 0.00001 ) lab = 0.0; //fix occassional roundoff error with "0.0" label
-
- QString str = QString( "%1" ).arg( lab, mAxes[BottomAxis]->labelFieldWidth(), mAxes[BottomAxis]->labelFmt(), mAxes[BottomAxis]->labelPrec() );
- if ( px > 0 && px < PixRect.width() ) {
- QRect r( px - BIGTICKSIZE, PixRect.height()+BIGTICKSIZE, 2*BIGTICKSIZE, BIGTICKSIZE );
- p->drawText( r, Qt::AlignCenter | Qt::TextDontClip, str );
- }
- }
-
- //draw minor ticks
- for ( int j=0; j < nminX; j++ ) {
- //position of minor tickmark j (in screen units)
- int pmin = int( px + PixRect.width()*j*dminX/dataWidth() );
-
- if ( pmin > 0 && pmin < PixRect.width() ) {
- p->drawLine( pmin, PixRect.height() - 2, pmin, PixRect.height() - SMALLTICKSIZE - 2 );
- p->drawLine( pmin, 0, pmin, SMALLTICKSIZE );
- }
- }
- } // end draw X tickmarks
-
- // Draw X Axis Label
- if ( ! mAxes[BottomAxis]->label().isEmpty() ) {
- QRect r( 0, PixRect.height() + 2*YPADDING, PixRect.width(), YPADDING );
- p->drawText( r, Qt::AlignCenter, mAxes[BottomAxis]->label() );
}
+ }
+ // Draw minor tickmarks
+ foreach ( double xx, a->minorTickMarks() ) {
+ double px = PixRect.width() * (xx - x()) / dataWidth();
+ if ( px > 0 && px < PixRect.width() ) {
+ p->drawLine( QPointF( px, double(PixRect.height() - 2.0)),
+ QPointF( px, double(PixRect.height() - SMALLTICKSIZE - 2.0)) );
+ }
}
- //--- Draw left Y Axis ---//
- if (mAxes[LeftAxis]->isVisible()) {
- // Draw Y tickmarks
- double y0 = y() - fmod( y(), dYtick ); //zeropoint; tickmark i is this plus i*dYtick1 (in data units)
- if ( y() < 0.0 ) y0 -= dYtick;
-
- for ( int iy = 0; iy <= nmajY+1; iy++ ) {
- //position of tickmark i (in screen units)
- int py = PixRect.height() - int( PixRect.height() * ( (y0 + iy*dYtick - y())/dataHeight() ) );
- if ( py > 0 && py < PixRect.height() ) {
- p->drawLine( 0, py, BIGTICKSIZE, py );
- p->drawLine( PixRect.width()-2, py, PixRect.width()-BIGTICKSIZE-2, py );
+ // Draw BottomAxis Label
+ if ( ! a->label().isEmpty() ) {
+ QRect r( 0, PixRect.height() + 2*YPADDING, PixRect.width(), YPADDING );
+ p->drawText( r, Qt::AlignCenter, a->label() );
+ }
+ } //End of BottomAxis
+
+ /*** LeftAxis ***/
+ a = axis(LeftAxis);
+ if (a->isVisible()) {
+ //Draw axis line
+ p->drawLine( 0, 0, 0, PixRect.height() );
+
+ // Draw major tickmarks
+ foreach( double yy, a->majorTickMarks() ) {
+ double py = PixRect.height() * ( 1.0 - (yy - y()) / dataHeight() );
+ if ( py > 0 && py < PixRect.height() ) {
+ p->drawLine( QPointF( 2.0, py ), QPointF( double(2.0 + BIGTICKSIZE), py ) );
+
+ //Draw ticklabel
+ if ( a->showTickLabels() ) {
+ QRect r( -2*BIGTICKSIZE-SMALLTICKSIZE, int(py)-SMALLTICKSIZE, 2*BIGTICKSIZE, 2*SMALLTICKSIZE );
+ p->drawText( r, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, a->tickLabel( yy ) );
}
+ }
+ }
+
+ // Draw minor tickmarks
+ foreach ( double yy, a->minorTickMarks() ) {
+ double py = PixRect.height() * ( 1.0 - (yy - y()) / dataHeight() );
+ if ( py > 0 && py < PixRect.height() ) {
+ p->drawLine( QPointF( 2.0, py ), QPointF( double(2.0 + SMALLTICKSIZE), py ) );
+ }
+ }
+
+ //Draw LeftAxis Label. We need to draw the text sideways.
+ if ( ! a->label().isEmpty() ) {
+ //store current painter translation/rotation state
+ p->save();
- //tick label
- if ( ShowTickLabels ) {
- double lab = y0 + iy*dYtick;
- if ( fabs(lab)/dYtick < 0.00001 ) lab = 0.0; //fix occassional roundoff error with "0.0" label
+ //translate coord sys to left corner of axis label rectangle, then rotate 90 degrees.
+ p->translate( -3*XPADDING, PixRect.height() );
+ p->rotate( -90.0 );
- QString str = QString( "%1" ).arg( lab, mAxes[LeftAxis]->labelFieldWidth(), mAxes[LeftAxis]->labelFmt(), mAxes[LeftAxis]->labelPrec() );
- if ( py > 0 && py < PixRect.height() ) {
- QRect r( -2*BIGTICKSIZE, py-SMALLTICKSIZE, 2*BIGTICKSIZE, 2*SMALLTICKSIZE );
- p->drawText( r, Qt::AlignCenter | Qt::TextDontClip, str );
- }
- }
+ QRect r( 0, 0, PixRect.height(), XPADDING );
+ p->drawText( r, Qt::AlignCenter, a->label() ); //draw the label, now that we are sideways
- //minor ticks
- for ( int j=0; j < nminY; j++ ) {
- //position of minor tickmark j (in screen units)
- int pmin = int( py - PixRect.height()*j*dminY/dataHeight() );
- if ( pmin > 0 && pmin < PixRect.height() ) {
- p->drawLine( 0, pmin, SMALLTICKSIZE, pmin );
- p->drawLine( PixRect.width()-2, pmin, PixRect.width()-SMALLTICKSIZE-2, pmin );
- }
+ p->restore(); //restore translation/rotation state
+ }
+ } //End of LeftAxis
+
+ /*** TopAxis ***/
+ a = axis(TopAxis);
+ if (a->isVisible()) {
+ //Draw axis line
+ p->drawLine( 0, 0, PixRect.width(), 0 );
+
+ // Draw major tickmarks
+ foreach( double xx, a->majorTickMarks() ) {
+ double px = PixRect.width() * (xx - x()) / dataWidth();
+ if ( px > 0 && px < PixRect.width() ) {
+ p->drawLine( QPointF( px, 2.0 ), QPointF( px, double(BIGTICKSIZE + 2.0)) );
+
+ //Draw ticklabel
+ if ( a->showTickLabels() ) {
+ QRect r( int(px) - BIGTICKSIZE, -1*BIGTICKSIZE, 2*BIGTICKSIZE, BIGTICKSIZE );
+ p->drawText( r, Qt::AlignCenter | Qt::TextDontClip, a->tickLabel( xx ) );
}
- } // end draw Y tickmarks
-
- //Draw Y Axis Label. We need to draw the text sideways.
- if ( ! mAxes[LeftAxis]->label().isEmpty() ) {
- //store current painter translation/rotation state
- p->save();
-
- //translate coord sys to left corner of axis label rectangle, then rotate 90 degrees.
- p->translate( -3*XPADDING, PixRect.height() );
- p->rotate( -90.0 );
-
- QRect r( 0, 0, PixRect.height(), XPADDING );
- p->drawText( r, Qt::AlignCenter, mAxes[LeftAxis]->label() ); //draw the label, now that we are sideways
-
- p->restore(); //restore translation/rotation state
}
}
- } //end if ( ShowTickMarks )
+ // Draw minor tickmarks
+ foreach ( double xx, a->minorTickMarks() ) {
+ double px = PixRect.width() * (xx - x()) / dataWidth();
+ if ( px > 0 && px < PixRect.width() ) {
+ p->drawLine( QPointF( px, 2.0 ), QPointF( px, double(SMALLTICKSIZE + 2.0)) );
+ }
+ }
+ // Draw TopAxis Label
+ if ( ! a->label().isEmpty() ) {
+ QRect r( 0, 0 - 3*YPADDING, PixRect.width(), YPADDING );
+ p->drawText( r, Qt::AlignCenter, a->label() );
+ }
+ } //End of TopAxis
+
+ /*** RightAxis ***/
+ a = axis(RightAxis);
+ if (a->isVisible()) {
+ //Draw axis line
+ p->drawLine( PixRect.width(), 0, PixRect.width(), PixRect.height() );
+
+ // Draw major tickmarks
+ foreach( double yy, a->majorTickMarks() ) {
+ double py = PixRect.height() * ( 1.0 - (yy - y()) / dataHeight() );
+ if ( py > 0 && py < PixRect.height() ) {
+ p->drawLine( QPointF( double(PixRect.width() - 2.0), py ),
+ QPointF( double(PixRect.width() - 2.0 - BIGTICKSIZE), py ) );
+
+ //Draw ticklabel
+ if ( a->showTickLabels() ) {
+ QRect r( PixRect.width() + SMALLTICKSIZE, int(py)-SMALLTICKSIZE, 2*BIGTICKSIZE, 2*SMALLTICKSIZE );
+ p->drawText( r, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, a->tickLabel( yy ) );
+ }
+ }
+ }
+ // Draw minor tickmarks
+ foreach ( double yy, a->minorTickMarks() ) {
+ double py = PixRect.height() * ( 1.0 - (yy - y()) / dataHeight() );
+ if ( py > 0 && py < PixRect.height() ) {
+ p->drawLine( QPointF( double(PixRect.width() - 2.0), py ),
+ QPointF( double(PixRect.width() - 2.0 - SMALLTICKSIZE), py ) );
+ }
+ }
+
+ //Draw RightAxis Label. We need to draw the text sideways.
+ if ( ! a->label().isEmpty() ) {
+ //store current painter translation/rotation state
+ p->save();
+
+ //translate coord sys to left corner of axis label rectangle, then rotate 90 degrees.
+ p->translate( PixRect.width() + 2*XPADDING, PixRect.height() );
+ p->rotate( -90.0 );
+
+ QRect r( 0, 0, PixRect.height(), XPADDING );
+ p->drawText( r, Qt::AlignCenter, a->label() ); //draw the label, now that we are sideways
+
+ p->restore(); //restore translation/rotation state
+ }
+ } //End of RightAxis
}
-int KPlotWidget::leftPadding() const {
+int KPlotWidget::leftPadding() {
if ( LeftPadding >= 0 ) return LeftPadding;
- if ( ! mAxes[LeftAxis]->label().isEmpty() && ShowTickLabels ) return 3*XPADDING;
- if ( ! mAxes[LeftAxis]->label().isEmpty() || ShowTickLabels ) return 2*XPADDING;
+ if ( axis(LeftAxis)->isVisible() && axis(LeftAxis)->showTickLabels() ) {
+ if ( ! axis(LeftAxis)->label().isEmpty() ) return 3*XPADDING;
+ else return 2*XPADDING;
+ }
return XPADDING;
}
-int KPlotWidget::rightPadding() const {
+int KPlotWidget::rightPadding() {
if ( RightPadding >= 0 ) return RightPadding;
+ if ( axis(RightAxis)->isVisible() && axis(RightAxis)->showTickLabels() ) {
+ if ( ! axis(RightAxis)->label().isEmpty() ) return 3*XPADDING;
+ else return 2*XPADDING;
+ }
return XPADDING;
}
-int KPlotWidget::topPadding() const {
+int KPlotWidget::topPadding() {
if ( TopPadding >= 0 ) return TopPadding;
+ if ( axis(TopAxis)->isVisible() && axis(TopAxis)->showTickLabels() ) {
+ if ( ! axis(TopAxis)->label().isEmpty() ) return 3*YPADDING;
+ else return 2*YPADDING;
+ }
return YPADDING;
}
-int KPlotWidget::bottomPadding() const {
+int KPlotWidget::bottomPadding() {
if ( BottomPadding >= 0 ) return BottomPadding;
- if ( ! mAxes[BottomAxis]->label().isEmpty() && ShowTickLabels ) return 3*YPADDING;
- if ( ! mAxes[BottomAxis]->label().isEmpty() || ShowTickLabels ) return 2*YPADDING;
+ if ( axis(BottomAxis)->isVisible() && axis(BottomAxis)->showTickLabels() ) {
+ if ( ! axis(BottomAxis)->label().isEmpty() ) return 3*YPADDING;
+ else return 2*YPADDING;
+ }
return YPADDING;
}
-
Q_PROPERTY(QColor foregroundColor READ foregroundColor WRITE setForegroundColor)
Q_PROPERTY(QColor gridColor READ gridColor WRITE setGridColor)
Q_PROPERTY(bool grid READ isGridShown WRITE setShowGrid)
- Q_PROPERTY(bool tickMarks READ areTickMarksShown WRITE setShowTickMarks)
- Q_PROPERTY(bool tickLabels READ areTickLabelsShown WRITE setShowTickLabels)
Q_PROPERTY(bool objectToolTip READ areObjectToolTipsShown WRITE setShowObjectToolTips)
public:
/**
/**
*@enum Axis The kinds of axes we have
*/
- enum Axis
- {
- LeftAxis = 0,
- BottomAxis
- };
+ enum Axis { LeftAxis = 0, BottomAxis, RightAxis, TopAxis };
/**
*@return suggested size for widget
*/
virtual QSize minimumSizeHint() const;
- /**
- * Determine the placement of major and minor tickmarks, based on the
- * current Limit settings
- */
- virtual void updateTickmarks();
-
/**
* Reset the data limits.
* @param x1 the minimum X value in data units
*/
virtual void setLimits( double x1, double x2, double y1, double y2 );
+ /**
+ * Reset the secondary data limits, which control the top and right axes.
+ * Note that all data points are plotted using the coordinates defined by
+ * the primary data limits, so this function is only useful for plotting
+ * alternate axes along the top and right edges.
+ * @param x1 the minimum X value in secondary data units
+ * @param x2 the maximum X value in secondary data units
+ * @param y1 the minimum Y value in secondary data units
+ * @param y2 the maximum Y value in secondary data units
+ * @sa setLimits()
+ */
+ virtual void setSecondaryLimits( double x1, double x2, double y1, double y2 );
+
/**
* @return the minimum X value in data units
*/
*/
virtual double dataHeight() const { return DataRect.height(); }
+ const QRectF& secondaryDataRect() const { return SecondDataRect; }
+
/**
* Add an item to the list of KPlotObjects to be plotted.
* @param o pointer to the KPlotObject to be added
*/
void setGridColor( const QColor &gc ) { cGrid = gc; }
- /**
- * Toggle whether plot axes are drawn.
- * @param show if true, axes will be drawn.
- * The axes are just a box outline around the plot.
- */
- void setShowAxes( bool show );
-
- /**
- * @return whether the tick marks are shown
- */
- bool areTickMarksShown() const { return ShowTickMarks; }
-
- /**
- * @return whether the tick labels are shown
- */
- bool areTickLabelsShown() const { return ShowTickLabels; }
-
/**
* @return whether the grid lines are shown
*/
*/
bool areObjectToolTipsShown() const { return ShowObjectToolTips; }
+ inline void setAntialias( bool b ) { UseAntialias = b; }
+
/**
* @return the number of pixels to the left of the plot area.
* Padding values are set to -1 by default; if unchanged, this function will try to guess
* a good value, based on whether ticklabels and/or axis labels are to be drawn.
*/
- virtual int leftPadding() const;
+ virtual int leftPadding();
/**
* @return the number of pixels to the right of the plot area.
* Padding values are set to -1 by default; if unchanged, this function will try to guess
* a good value, based on whether ticklabels and/or axis labels are to be drawn.
*/
- virtual int rightPadding() const;
+ virtual int rightPadding();
/**
* @return the number of pixels above the plot area.
* Padding values are set to -1 by default; if unchanged, this function will try to guess
* a good value, based on whether ticklabels and/or axis labels are to be drawn.
*/
- virtual int topPadding() const;
+ virtual int topPadding();
/**
* @return the number of pixels below the plot area.
* Padding values are set to -1 by default; if unchanged, this function will try to guess
* a good value, based on whether ticklabels and/or axis labels are to be drawn.
*/
- virtual int bottomPadding() const;
+ virtual int bottomPadding();
/**
* Set the number of pixels to the left of the plot area.
KPlotAxis* axis( Axis a );
public slots:
- /**
- * Toggle whether tick marks are drawn along the axes.
- * @param show if true, tick marks will be drawn.
- */
- void setShowTickMarks( bool show );
-
- /**
- * Toggle whether tick labels are drawn at major tickmarks.
- * @param show if true, tick labels will be drawn.
- */
- void setShowTickLabels( bool show );
-
/**
* Toggle whether grid lines are drawn at major tickmarks.
* @param show if true, grid lines will be drawn.
* to draw the widget with axes and all objects.
* @param p pointer to the painter on which we are drawing
*/
- virtual void drawBox( QPainter *p );
+ virtual void drawAxes( QPainter *p );
- virtual void recalcPixRect();
+ void setPixRect();
QList<KPlotObject*> pointsUnderPoint( const QPoint& p ) const;
- /**
- * Recalc the ticks for the specified @p length.
- * @p dTick , @p nmajor and @p nminor will contain respectively the
- * distance between every major tick, the number of number of major
- * ticks, and the number of minor ticks.
- */
- void calcTickMarks( double length, double& dTick, int& nmajor, int& nminor );
-
- //The distance between major tickmarks in data units
- double dXtick, dYtick;
- //The number of major and minor tickmarks to be plotted in X and Y
- int nmajX, nminX, nmajY, nminY;
-
/**
* Limits of the plot area in pixel units
*/
/**
* Limits of the plot area in data units
*/
- QRectF DataRect;
+ QRectF DataRect, SecondDataRect;
/**
* List of KPlotObjects
*/
//Colors
QColor cBackground, cForeground, cGrid;
//draw options
- bool ShowTickMarks, ShowTickLabels, ShowGrid, ShowObjectToolTips;
+ bool ShowGrid, ShowObjectToolTips, UseAntialias;
//padding
int LeftPadding, RightPadding, TopPadding, BottomPadding;
-
- QPixmap *buffer;
};
#endif