From: Jason Harris Date: Sun, 20 Jul 2003 04:52:06 +0000 (+0000) Subject: Added ability to add axis labels to the plot X-Git-Tag: v3.2.0~5 X-Git-Url: https://git.rmz.fi/?a=commitdiff_plain;h=d794935dc15742385b9c2f29b067d9f81c05cc08;p=libqmvoc.git Added ability to add axis labels to the plot (setXAxisLabel(QString)/setYAxisLabel(QString)). The "padding" space around the plot area is no longer hard-coded. The amount of padding can be set explicitly with setXXXPadding(int), where XXX={Left, Right, Top, Bottom}. If not explicitly set, the code will automatically choose a good amount of padding, depending on whether there are Axis Labels and/or Tick Mark Labels present. Also, the placement of Tick Mark Labels is a bit smarter now; the labels should be better centered on the corresponding tick. CCMAIL: kstars-devel@lists.sourceforge.net svn path=/trunk/kdeedu/libkdeedu/; revision=238085 --- diff --git a/kdeeduplot/kplotwidget.cpp b/kdeeduplot/kplotwidget.cpp index ddfb4e7..602bb82 100644 --- a/kdeeduplot/kplotwidget.cpp +++ b/kdeeduplot/kplotwidget.cpp @@ -26,15 +26,17 @@ KPlotWidget::KPlotWidget( double x1, double x2, double y1, double y2, QWidget *parent, const char* name ) : QWidget( parent, name ), - dXtick(0.0), dYtick(0.0), + dXtick(0.0), dYtick(0.0), XAxisLabel(), YAxisLabel(), nmajX(0), nminX(0), nmajY(0), nminY(0), ShowAxes( true ), ShowTickMarks( true ), ShowTickLabels( true ), ShowGrid( false ) { //set DataRect setLimits( x1, x2, y1, y2 ); + setDefaultPadding(); - //Set PixRect (starts at (0,0) because we will translate by XPADDING,YPADDING) - PixRect = QRect( 0, 0, width() - XPADDING, height() - YPADDING ); + //Set PixRect (starts at (0,0) because we will translate by leftPadding(), topPadding() ) + PixRect = QRect( 0, 0, width() - leftPadding() - rightPadding(), + height() - topPadding() - bottomPadding() ); buffer = new QPixmap(); @@ -124,8 +126,8 @@ void KPlotWidget::updateTickmarks() { } void KPlotWidget::resizeEvent( QResizeEvent* /* e */ ) { - int newWidth = width() - 2*XPADDING; - int newHeight = height() - 2*YPADDING; + int newWidth = width() - leftPadding() - rightPadding(); + int newHeight = height() - topPadding() - bottomPadding(); PixRect = QRect( 0, 0, newWidth, newHeight ); buffer->resize( width(), height() ); @@ -136,8 +138,7 @@ void KPlotWidget::paintEvent( QPaintEvent* /* e */ ) { p.begin( buffer ); p.fillRect( 0, 0, width(), height(), bgColor() ); - - p.translate( XPADDING, YPADDING ); + p.translate( leftPadding(), topPadding() ); drawObjects( &p ); drawBox( &p ); @@ -148,8 +149,8 @@ void KPlotWidget::paintEvent( QPaintEvent* /* e */ ) { void KPlotWidget::drawObjects( QPainter *p ) { for ( KPlotObject *po = ObjectList.first(); po; po = ObjectList.next() ) { - - if ( po->points()->count() ) { + + if ( po->points()->count() ) { //draw the plot object p->setPen( QColor( po->color() ) ); @@ -219,14 +220,18 @@ void KPlotWidget::drawBox( QPainter *p ) { //First, fill in padding region with bgColor() to mask out-of-bounds plot data p->setPen( bgColor() ); p->setBrush( bgColor() ); + //left padding ( don't forget: we have translated by XPADDING, YPADDING ) - p->drawRect( -XPADDING, -YPADDING, XPADDING, height() ); + p->drawRect( -leftPadding(), -topPadding(), leftPadding(), height() ); + //right padding - p->drawRect( PixRect.width(), -YPADDING, XPADDING, height() ); + p->drawRect( PixRect.width(), -topPadding(), rightPadding(), height() ); + //top padding - p->drawRect( 0, -YPADDING, PixRect.width(), YPADDING ); + p->drawRect( 0, -topPadding(), PixRect.width(), topPadding() ); + //bottom padding - p->drawRect( 0, PixRect.height(), PixRect.width(), YPADDING ); + p->drawRect( 0, PixRect.height(), PixRect.width(), bottomPadding() ); if ( ShowGrid ) { //Grid lines are placed at locations of primary axes' major tickmarks @@ -257,6 +262,12 @@ void KPlotWidget::drawBox( QPainter *p ) { 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 X tickmarks---// double x0 = x() - dmod( x(), dXtick ); //zeropoint; tickmark i is this plus i*dXtick (in data units) if ( x() < 0.0 ) x0 -= dXtick; @@ -276,8 +287,10 @@ void KPlotWidget::drawBox( QPainter *p ) { if ( fabs(lab)/dXtick < 0.00001 ) lab = 0.0; //fix occassional roundoff error with "0.0" label QString str = QString( "%1" ).arg( lab, 0, 'g', 2 ); - if ( px > 0 && px < PixRect.width() ) - p->drawText( px - BIGTICKSIZE, PixRect.height() + 2*BIGTICKSIZE, str ); + if ( px > 0 && px < PixRect.width() ) { + QRect r( px - BIGTICKSIZE, PixRect.height()+BIGTICKSIZE, 2*BIGTICKSIZE, BIGTICKSIZE ); + p->drawText( r, Qt::AlignCenter | Qt::DontClip, str ); + } } //draw minor ticks @@ -310,8 +323,10 @@ void KPlotWidget::drawBox( QPainter *p ) { if ( fabs(lab)/dYtick < 0.00001 ) lab = 0.0; //fix occassional roundoff error with "0.0" label QString str = QString( "%1" ).arg( lab, 0, 'g', 2 ); - if ( py > 0 && py < PixRect.height() ) - p->drawText( -2*BIGTICKSIZE, py + SMALLTICKSIZE, str ); + if ( py > 0 && py < PixRect.height() ) { + QRect r( -2*BIGTICKSIZE, py-SMALLTICKSIZE, 2*BIGTICKSIZE, 2*SMALLTICKSIZE ); + p->drawText( r, Qt::AlignCenter | Qt::DontClip, str ); + } } //minor ticks @@ -325,6 +340,51 @@ void KPlotWidget::drawBox( QPainter *p ) { } } //end draw Y tickmarks } //end if ( ShowTickMarks ) + + //Draw X Axis Label + if ( ! XAxisLabel.isEmpty() ) { + QRect r( 0, PixRect.height() + 2*YPADDING, PixRect.width(), YPADDING ); + p->drawText( r, Qt::AlignCenter, XAxisLabel ); + } + + //Draw Y Axis Label. We need to draw the text sideways. + if ( ! YAxisLabel.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, YAxisLabel ); //draw the label, now that we are sideways + + p->restore(); //restore translation/rotation state + } +} + +int KPlotWidget::leftPadding() const { + if ( LeftPadding >= 0 ) return LeftPadding; + if ( ! YAxisLabel.isEmpty() && ShowTickLabels ) return 3*XPADDING; + if ( ! YAxisLabel.isEmpty() || ShowTickLabels ) return 2*XPADDING; + return XPADDING; +} + +int KPlotWidget::rightPadding() const { + if ( RightPadding >= 0 ) return RightPadding; + return XPADDING; +} + +int KPlotWidget::topPadding() const { + if ( TopPadding >= 0 ) return TopPadding; + return YPADDING; +} + +int KPlotWidget::bottomPadding() const { + if ( BottomPadding >= 0 ) return BottomPadding; + if ( ! XAxisLabel.isEmpty() && ShowTickLabels ) return 3*YPADDING; + if ( ! XAxisLabel.isEmpty() || ShowTickLabels ) return 2*YPADDING; + return YPADDING; } #include "kplotwidget.moc" diff --git a/kdeeduplot/kplotwidget.h b/kdeeduplot/kplotwidget.h index 6c41566..6ce8e28 100644 --- a/kdeeduplot/kplotwidget.h +++ b/kdeeduplot/kplotwidget.h @@ -23,8 +23,8 @@ #define BIGTICKSIZE 10 #define SMALLTICKSIZE 4 -#define XPADDING 40 -#define YPADDING 40 +#define XPADDING 20 +#define YPADDING 20 class QColor; class QPixmap; @@ -133,11 +133,77 @@ public: */ virtual void setGridColor( const QColor &gc ) { cGrid = gc; } + /**@short toggle whether plot axes are drawn. + *@param show if true, axes will be drawn. + *The axes are just a box outline around the plot. + */ virtual void setShowAxes( bool show ) { ShowAxes = show; } + /**@short toggle whether tick marks are drawn along the axes. + *@param show if true, tick marks will be drawn. + */ virtual void setShowTickMarks( bool show ) { ShowTickMarks = show; } + /**@short toggle whether tick labels are drawn at major tickmarks. + *@param show if true, tick labels will be drawn. + */ virtual void setShowTickLabels( bool show ) { ShowTickLabels = show; } + /**@short toggle whether grid lines are drawn at major tickmarks. + *@param show if true, grid lines will be drawn. + */ virtual void setShowGrid( bool show ) { ShowGrid = show; } + /**@short set the X-axis label + *@param xlabel a short string describing the data plotted on the x-axis. + *Set the label to an empty string to omit the axis label. + */ + virtual void setXAxisLabel( QString xlabel ) { XAxisLabel = xlabel; } + /**@short set the Y-axis label + *@param ylabel a short string describing the data plotted on the y-axis. + *Set the label to an empty string to omit the axis label. + */ + virtual void setYAxisLabel( QString ylabel ) { YAxisLabel = ylabel; } + + /**@returns 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; + /**@returns 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; + /**@returns 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; + /**@returns 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; + + /**@short set the number of pixels to the left of the plot area. + *Set this to -1 to revert to automatic determination of padding values. + */ + virtual void setLeftPadding( int pad ) { LeftPadding = pad; } + /**@short set the number of pixels to the right of the plot area. + *Set this to -1 to revert to automatic determination of padding values. + */ + virtual void setRightPadding( int pad ) { RightPadding = pad; } + /**@short set the number of pixels above the plot area. + *Set this to -1 to revert to automatic determination of padding values. + */ + virtual void setTopPadding( int pad ) { TopPadding = pad; } + /**@short set the number of pixels below the plot area. + *Set this to -1 to revert to automatic determination of padding values. + */ + virtual void setBottomPadding( int pad ) { BottomPadding = pad; } + + /**@short revert all four padding values to be automatically determined. + */ + virtual void setDefaultPadding() { LeftPadding = -1; RightPadding = -1; TopPadding = -1; BottomPadding = -1; } + protected: /**@short the paint event handler, executed when update() or repaint() is called. */ @@ -174,7 +240,7 @@ protected: QRect PixRect; //Limits of the plot area in data units DRect DataRect; - //List of KPlotObjects + //List of KPlotObjects QPtrList ObjectList; //Colors @@ -182,6 +248,12 @@ protected: //draw options bool ShowAxes, ShowTickMarks, ShowTickLabels, ShowGrid; + //padding + int LeftPadding, RightPadding, TopPadding, BottomPadding; + + //Axis Labels + QString XAxisLabel, YAxisLabel; + QPixmap *buffer; };