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();
}
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() );
p.begin( buffer );
p.fillRect( 0, 0, width(), height(), bgColor() );
-
- p.translate( XPADDING, YPADDING );
+ p.translate( leftPadding(), topPadding() );
drawObjects( &p );
drawBox( &p );
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() ) );
//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
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;
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
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
}
} //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"
#define BIGTICKSIZE 10
#define SMALLTICKSIZE 4
-#define XPADDING 40
-#define YPADDING 40
+#define XPADDING 20
+#define YPADDING 20
class QColor;
class QPixmap;
*/
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.
*/
QRect PixRect;
//Limits of the plot area in data units
DRect DataRect;
- //List of KPlotObjects
+ //List of KPlotObjects
QPtrList<KPlotObject> ObjectList;
//Colors
//draw options
bool ShowAxes, ShowTickMarks, ShowTickLabels, ShowGrid;
+ //padding
+ int LeftPadding, RightPadding, TopPadding, BottomPadding;
+
+ //Axis Labels
+ QString XAxisLabel, YAxisLabel;
+
QPixmap *buffer;
};