]> Git trees. - libqmvoc.git/commitdiff
Adding files for libkdeeduplot...sorry for the confusion; I had trouble
authorJason Harris <kstars@30doradus.org>
Fri, 11 Jul 2003 13:11:18 +0000 (13:11 +0000)
committerJason Harris <kstars@30doradus.org>
Fri, 11 Jul 2003 13:11:18 +0000 (13:11 +0000)
adding these initially, but I thought I had finally committed them.  Hope
it works this time.

CCMAIL: mueller@kde.org

svn path=/trunk/kdeedu/libkdeedu/; revision=236545

kdeeduplot/Makefile.am
kdeeduplot/README [new file with mode: 0644]
kdeeduplot/kplotobject.cpp [new file with mode: 0644]
kdeeduplot/kplotobject.h [new file with mode: 0644]
kdeeduplot/kplotwidget.cpp [new file with mode: 0644]
kdeeduplot/kplotwidget.h [new file with mode: 0644]

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..512e836c0dd2e6603cb5261e7e1cb1619c82cf93 100644 (file)
@@ -0,0 +1,13 @@
+INCLUDES= $(all_includes)
+SUBDIRS = . 
+
+lib_LTLIBRARIES = libkdeeduplot.la
+
+libkdeeduplot_la_SOURCES = \
+            kplotobject.cpp kplotwidget.cpp
+
+libkdeeduplot_la_LDFLAGS = $(all_libraries) -no-undefined -version-info 3:0:2
+libkdeeduplot_la_LIBADD = $(LIB_KDECORE) $(LIB_QT)
+
+METASOURCES = AUTO
+
diff --git a/kdeeduplot/README b/kdeeduplot/README
new file mode 100644 (file)
index 0000000..ab695f9
--- /dev/null
@@ -0,0 +1,23 @@
+This library provides KPlotWidget and KPlotObject classes.
+
+KPlotWidget is a QWidget-derived class that provides a virtual baseclass 
+for easy data-plotting. The idea behind KPlotWidget is that you only have 
+to specify information in "data units"; i.e., the natural units of the 
+data being plotted.  KPlotWidget automatically converts everything 
+to screen pixel units.
+
+KPlotWidget draws X and Y axes with tickmarks and tick labels.  It 
+automatically determines how many tickmarks to use and where they should 
+be, based on the data limits specified for the plot.  You change the limits 
+by calling setLimits( double x1, double x2, double y1, double y2 ), and 
+then calling updateTickmarks() to recompute the positions of tickmarks 
+and ticklabels.
+
+Data to be plotted are stored using the KPlotObject class.  KPlotObject
+consists of a QPtrList of DPoints, each specifying the X,Y coordinates
+of a data point (DPoint is like QPoint, but the X and Y values are doubles 
+instead of ints).  KPlotObject also specifies the "type" of data to be 
+plotted (POINTS or CURVE or POLYGON or LABEL).
+
+Jason Harris
+kstars@30doradus.org
diff --git a/kdeeduplot/kplotobject.cpp b/kdeeduplot/kplotobject.cpp
new file mode 100644 (file)
index 0000000..63bfa95
--- /dev/null
@@ -0,0 +1,53 @@
+/***************************************************************************
+                          kplotobject.cpp - A list of points to be plotted
+                             -------------------
+    begin                : Sun 18 May 2003
+    copyright            : (C) 2003 by Jason Harris
+    email                : kstars@30doradus.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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 <qcolor.h>
+#include <qpainter.h>
+#include <qrect.h>
+#include <qstring.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include "kplotobject.h"
+
+KPlotObject::KPlotObject() {
+       KPlotObject( "", "white", POINTS );
+}
+
+KPlotObject::KPlotObject( const QString &n, const QString &c, PTYPE t, unsigned int s, unsigned int p ) {
+       //We use the set functions because they may include data validation
+       setName( n );
+       setColor( c );
+       setType( t );
+       setSize( s );
+       setParam( p );
+
+       pList.setAutoDelete( TRUE );
+}
+
+KPlotObject::~KPlotObject()
+{
+}
+
+void KPlotObject::removePoint( unsigned int index ) {
+       if ( index > pList.count() - 1 ) {
+               kdWarning() << i18n( "Ignoring attempt to remove non-existent plot object" ) << endl;
+               return;
+       }
+
+       pList.remove( index );
+}
+
diff --git a/kdeeduplot/kplotobject.h b/kdeeduplot/kplotobject.h
new file mode 100644 (file)
index 0000000..e4e8fc2
--- /dev/null
@@ -0,0 +1,205 @@
+/***************************************************************************
+                          kplotobject.h - A list of points to be plotted
+                             -------------------
+    begin                : Sun 18 May 2003
+    copyright            : (C) 2003 by Jason Harris
+    email                : kstars@30doradus.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef KPLOTOBJECT_H
+#define KPLOTOBJECT_H
+
+#include <qpoint.h>
+#include <qptrlist.h>
+
+class QString;
+class QPainter;
+
+/**class DRect
+       *@short equivalent of QRect with double x,y coordinates
+       *@author Jason Harris
+       *@version 1.0
+       */
+class DRect {
+public:
+       DRect() { DRect( 0.0, 0.0, 1.0, 1.0 ); }
+       DRect( double x, double y, double w, double h ) { X = x; Y = y; W = w; H = h; }
+       ~DRect() {}
+
+       double x() const { return X; }
+       double y() const { return Y; }
+       double x2() const { return X + W; }
+       double y2() const { return Y + H; }
+       double width() const { return W; }
+       double height() const { return H; }
+
+       void setX( double x ) { X = x; }
+       void setY( double y ) { Y = y; }
+       void setWidth( double w ) { W = w; }
+       void setHeight( double h ) { H = h; }
+
+private:
+       double X,Y,W,H;
+};
+
+/**class DPoint
+       *@short equivalent of QPoint with double x,y coordinates
+       *@author Jason Harris
+       *@version 1.0
+       */
+class DPoint {
+public:
+       DPoint() { DPoint( 0.0, 0.0 ); }
+       DPoint( double x, double y ) { setX( x ); setY( y ); }
+       ~DPoint() {}
+
+       double x() const { return X; }
+       double y() const { return Y; }
+
+       QPoint qpoint( QRect pb, DRect db ) {
+               int px = pb.left() + int( pb.width()*( x() -  db.x() )/db.width() );
+               int py = pb.top() + int( pb.height()*( db.y2() - y() )/db.height() );
+               return QPoint( px, py );
+       }
+
+       void setX( double x ) { X = x; }
+       void setY( double y ) { Y = y; }
+
+private:
+       double X, Y;
+};
+
+/**@class KPlotObject
+       *@short Encapsulates an object to be plotted in a KPlotWidget.
+       *@author Jason Harris
+       *@version 1.0
+       *Each KPlotObject consists of a list of QPoints, an object type, a color, a size,
+       *and a QString name.  An additional integer (param) specifies something further
+       *about the object's appearance, depending on its type.  There is a draw function
+       *for plotting the object on a KPlotWidget's QPainter.
+       */
+class KPlotObject{
+public:
+/**@enum PTYPE
+       *The Type classification of the KPlotObject
+       */
+       enum PTYPE { POINTS=0, CURVE=1, LABEL=2, POLYGON=3, UNKNOWN_TYPE };
+
+/**@enum PPARAM
+       *Parameter specifying the kind of points
+       */
+       enum PPARAM { DOT=0, CIRCLE=1, SQUARE=2, LETTER=3, UNKNOWN_POINT };
+
+/**@enum CPARAM
+       *Parameter specifying the kind of line.  These are numerically equal to
+       *the Qt::PenStyle enum values.
+       */
+       enum CPARAM { NO_LINE=0, SOLID=1, DASHED=2, DOTTED=3, DASHDOTTED=4, DASHDOTDOTTED=5, UNKNOWN_CURVE };
+
+/**Default constructor.  Create a POINTS-type object with an empty list of points.
+       */
+       KPlotObject();
+
+/**Constructor.  Create a KPlotObject according to the arguments.
+       */
+       KPlotObject( const QString &name, const QString &color, PTYPE otype, unsigned int size=2, unsigned int param=0 );
+
+/**Destructor (empty)
+       */
+       ~KPlotObject();
+
+/**@return the KPlotObject's Name
+       */
+       QString name() const { return Name; }
+
+/**@short set the KPlotObject's Name
+       *@param n the new name
+       */
+       void setName( const QString &n ) { Name = n; }
+
+/**@return the KPlotObject's Color
+       */
+       QString color() const { return Color; }
+
+/**@short set the KPlotObject's Color
+       *@param n the new color
+       */
+       void setColor( const QString &c ) { Color = c; }
+
+/**@return the KPlotObject's Type
+       */
+       PTYPE type() const { return Type; }
+
+/**@short set the KPlotObject's Type
+       *@param t the new type
+       */
+       void setType( PTYPE t ) { Type = t; }
+
+/**@return the KPlotObject's Size
+       */
+       unsigned int size() const { return Size; }
+
+/**@short set the KPlotObject's Size
+       *@param s the new size
+       */
+       void setSize( unsigned int s ) { Size = s; }
+
+/**@return the KPlotObject's type-specific Parameter
+       *Parameter is an unsigned int because it can either be a PPARAM or a CPARAM enum.
+       */
+       unsigned int param() const { return Parameter; }
+
+/**@short set the KPlotObject's type-specific Parameter
+       *@param p the new parameter
+       *Parameter is an unsigned int because it can either be a PPARAM or a CPARAM enum.
+       */
+       void setParam( unsigned int p ) { Parameter = p; }
+
+/**@return a pointer to the DPoint at position i
+       *@param i the index of the desired point.
+       */
+       DPoint* point( unsigned int i ) { return pList.at(i); }
+
+       QPtrList<DPoint>* points() { return &pList; }
+
+/**@short Add a point to the object's list.
+       *@param p the DPoint to add.
+       */
+       void addPoint( const DPoint &p ) { pList.append( new DPoint( p.x(), p.y() ) ); }
+
+/**@short Add a point to the object's list.  This is an overloaded function,
+       *provided for convenience.  It behaves essentially like the above function.
+       *@param p pointer to the DPoint to add.
+       */
+       void addPoint( DPoint *p ) { pList.append( p ); }
+
+/**@short remove the QPoint at position index from the list of points
+       *@param index the index of the point to be removed.
+       */
+       void removePoint( unsigned int index );
+
+/**@return the number of QPoints currently in the list
+       */
+       unsigned int count() const { return pList.count(); }
+
+/**@short clear the Object's points list
+       */
+       void clearPoints() { pList.clear(); }
+
+private:
+       QPtrList<DPoint> pList;
+       PTYPE Type;
+       unsigned int Size, Parameter;
+       QString Color, Name;
+};
+
+#endif
diff --git a/kdeeduplot/kplotwidget.cpp b/kdeeduplot/kplotwidget.cpp
new file mode 100644 (file)
index 0000000..f4d47c0
--- /dev/null
@@ -0,0 +1,330 @@
+/***************************************************************************
+                          kplotwidget.cpp - A widget for plotting in KStars
+                             -------------------
+    begin                : Sun 18 May 2003
+    copyright            : (C) 2003 by Jason Harris
+    email                : kstars@30doradus.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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 <math.h> //for log10(), pow(), modf()
+#include <kdebug.h>
+#include <qcolor.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qstring.h>
+
+#include "kplotwidget.h"
+
+KPlotWidget::KPlotWidget( double x1, double x2, double y1, double y2, QWidget *parent, const char* name )
+ : QWidget( parent, name ),
+   dXtick(0.0), dYtick(0.0),
+   nmajX(0), nminX(0), nmajY(0), nminY(0),
+   ShowAxes( true ), ShowTickMarks( true ), ShowTickLabels( true ), ShowGrid( false ) {
+
+       //set DataRect
+       setLimits( x1, x2, y1, y2 );
+
+       //Set PixRect (starts at (0,0) because we will translate by XPADDING,YPADDING)
+       PixRect = QRect( 0, 0, width() - XPADDING, height() - YPADDING );
+
+       buffer = new QPixmap();
+
+       //default colors:
+       setBGColor( QColor( "black" ) );
+       setFGColor( QColor( "white" ) );
+       setGridColor( QColor( "grey" ) );
+
+       ObjectList.setAutoDelete( TRUE );
+}
+
+void KPlotWidget::setLimits( 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; }
+
+       DataRect = DRect( XA1, YA1, XA2-XA1, YA2-YA1 );
+       updateTickmarks();
+}
+
+void KPlotWidget::updateTickmarks() {
+       // Determine the number and spacing of tickmarks for the current plot limits.
+       if ( dataWidth() == 0.0 ) {
+               kdWarning() << "X range invalid! " << x() << " to " << x2() << endl;
+               DataRect.setWidth( 1.0 );
+               return;
+       }
+       if ( dataHeight() == 0.0 ) {
+               kdWarning() << "Y range invalid! " << y() << " to " << y2() << endl;
+               DataRect.setHeight( 1.0 );
+               return;
+       }
+
+       int nmajor(0), nminor(0);
+       double z(0.0), z2(0.0);
+       double Range(0.0), s(0.0), t(0.0), pwr(0.0), dTick(0.0);
+
+       //loop over X and Y axes...the z variables substitute for either X or Y
+       for ( unsigned int iaxis=0; iaxis<2; ++iaxis ) {
+               if ( iaxis == 1 ) {
+                       z = x(); z2 = x2();
+               } else {
+                       z = y(); z2 = y2();
+               }
+
+               //determine size of region to be drawn, in draw units
+               Range = z2 - z;
+
+               //s is the power-of-ten factor of Range:
+               //Range = t * s; s = 10^(pwr).  e.g., Range=350.0 then t=3.5, s = 100.0; pwr = 2.0
+               modf( log10(Range), &pwr );
+               s = pow( 10.0, pwr );
+               t = Range/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 btwn 3 and 30
+               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 ( iaxis==1 ) { //X axis
+                       nmajX = nmajor;
+                       nminX = nminor;
+                       dXtick = dTick;
+               } else { //Y axis
+                       nmajY = nmajor;
+                       nminY = nminor;
+                       dYtick = dTick;
+               }
+       } //end for iaxis
+}
+
+void KPlotWidget::resizeEvent( QResizeEvent *e ) {
+       int newWidth = width() - 2*XPADDING;
+       int newHeight = height() - 2*YPADDING;
+       PixRect = QRect( 0, 0, newWidth, newHeight );
+
+       buffer->resize( width(), height() );
+}
+
+void KPlotWidget::paintEvent( QPaintEvent *e ) {
+       QPainter p;
+
+       p.begin( buffer );
+       p.fillRect( 0, 0, width(), height(), bgColor() );
+
+       p.translate( XPADDING, YPADDING );
+
+       drawObjects( &p );
+       drawBox( &p );
+
+       p.end();
+       bitBlt( this, 0, 0, buffer );
+}
+
+void KPlotWidget::drawObjects( QPainter *p ) {
+       for ( KPlotObject *po = ObjectList.first(); po; po = ObjectList.next() ) {
+               
+               if ( po->points()->count() ) { 
+                       //draw the plot object
+                       p->setPen( QColor( po->color() ) );
+
+                       switch ( po->type() ) {
+                               case KPlotObject::POINTS :
+                               {
+                                       p->setBrush( QColor( po->color() ) );
+
+                                       for ( DPoint *dp = po->points()->first(); dp; dp = po->points()->next() ) {
+                                               QPoint q = dp->qpoint( PixRect, DataRect );
+                                               int x1 = q.x() - po->size()/2;
+                                               int y1 = q.y() - po->size()/2;
+
+                                               switch( po->param() ) {
+                                                       case KPlotObject::CIRCLE : p->drawEllipse( x1, y1, po->size(), po->size() ); break;
+                                                       case KPlotObject::SQUARE : p->drawRect( x1, y1, po->size(), po->size() ); break;
+                                                       case KPlotObject::LETTER : p->drawText( q, po->name().left(1) ); break;
+                                                       default: p->drawPoint( q );
+                                               }
+                                       }
+
+                                       p->setBrush( Qt::NoBrush );
+                                       break;
+                               }
+
+                               case KPlotObject::CURVE :
+                               {
+                                       p->setPen( QPen( QColor( po->color() ), po->size(), (QPen::PenStyle)po->param() ) );
+                                       DPoint *dp = po->points()->first();
+                                       p->moveTo( dp->qpoint( PixRect, DataRect ) );
+                                       for ( dp = po->points()->next(); dp; dp = po->points()->next() )
+                                               p->lineTo( dp->qpoint( PixRect, DataRect ) );
+                                       break;
+                               }
+
+                               case KPlotObject::LABEL :
+                               {
+                                       QPoint q = po->points()->first()->qpoint( PixRect, DataRect );
+                                       p->drawText( q, po->name() );
+                                       break;
+                               }
+
+                               case KPlotObject::POLYGON :
+                               {
+                                       p->setPen( QPen( QColor( po->color() ), po->size(), (QPen::PenStyle)po->param() ) );
+                                       p->setBrush( po->color() );
+
+                                       QPointArray a( po->count() );
+
+                                       unsigned int i=0;
+                                       for ( DPoint *dp = po->points()->first(); dp; dp = po->points()->next() )
+                                               a.setPoint( i++, dp->qpoint( PixRect, DataRect ) );
+
+                                       p->drawPolygon( a );
+                                       break;
+                               }
+
+                               case KPlotObject::UNKNOWN_TYPE : break;
+                       }
+               }
+       }
+}
+
+double KPlotWidget::dmod( double a, double b ) { return ( b * ( ( a / b ) - int( a / b ) ) ); }
+
+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() );
+       //right padding
+       p->drawRect( PixRect.width(), -YPADDING, XPADDING, height() );
+       //top padding
+       p->drawRect( 0, -YPADDING, PixRect.width(), YPADDING );
+       //bottom padding
+       p->drawRect( 0, PixRect.height(), PixRect.width(), YPADDING );
+
+       if ( ShowGrid ) {
+               //Grid lines are placed at locations of primary axes' major tickmarks
+               p->setPen( gridColor() );
+
+               //vertical grid lines
+               double x0 = x() - dmod( x(), dXtick ); //zeropoint; x(i) is this plus i*dXtick1
+               for ( int ix = 0; ix <= nmajX+1; ix++ ) {
+                       int px = int( PixRect.width() * ( (x0 + ix*dXtick - x())/dataWidth() ) );
+                       p->drawLine( px, 0, px, PixRect.height() );
+               }
+
+               //horizontal grid lines
+               double y0 = y() - dmod( y(), dYtick ); //zeropoint; y(i) is this plus i*mX
+               for ( int iy = 0; iy <= nmajY+1; iy++ ) {
+                       int py = int( PixRect.height() * ( (y0 + iy*dYtick - y())/dataHeight() ) );
+                       p->drawLine( 0, py, PixRect.width(), py );
+               }
+       }
+
+       p->setPen( fgColor() );
+       p->setBrush( Qt::NoBrush );
+
+       if ( ShowAxes ) p->drawRect( PixRect ); //box outline
+
+       if ( ShowTickMarks ) {
+               //spacing between minor tickmarks (in data units)
+               double dminX = dXtick/nminX;
+               double dminY = dYtick/nminY;
+
+               //--- 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;
+
+               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 );
+                       }
+
+                       //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, 0, 'g', 2 );
+                               if ( px > 0 && px < PixRect.width() )
+                                       p->drawText( px - BIGTICKSIZE, PixRect.height() + 2*BIGTICKSIZE, 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 );
+                               }
+                       }
+               }
+
+               //--- Draw Y tickmarks---//
+               double y0 = y() - dmod( 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 );
+                       }
+
+                       //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
+
+                               QString str = QString( "%1" ).arg( lab, 0, 'g', 2 );
+                               if ( py > 0 && py < PixRect.height() )
+                                       p->drawText( -2*BIGTICKSIZE, py + SMALLTICKSIZE, str );
+                       }
+
+                       //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 );
+                               }
+                       }
+               } //end draw Y tickmarks
+       } //end if ( ShowTickMarks )
+}
+
+#include "kplotwidget.moc"
diff --git a/kdeeduplot/kplotwidget.h b/kdeeduplot/kplotwidget.h
new file mode 100644 (file)
index 0000000..7f237d2
--- /dev/null
@@ -0,0 +1,188 @@
+/***************************************************************************
+                          kplotwidget.h - A generic data-plotting widget
+                             -------------------
+    begin                : Sun 18 May 2003
+    copyright            : (C) 2003 by Jason Harris
+    email                : kstars@30doradus.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef _KPLOTWIDGET_H_
+#define _KPLOTWIDGET_H_
+
+#include <qwidget.h>
+#include "kplotobject.h"
+
+#define BIGTICKSIZE 10
+#define SMALLTICKSIZE 4
+#define XPADDING 40
+#define YPADDING 40
+
+class QColor;
+class QPixmap;
+
+/**@class KPlotWidget
+       *@short Genric data plotting widget.
+       *@author Jason Harris
+       *@version 1.0
+       *Widget for drawing plots.  Includes adjustable axes with
+       *tickmarks and labels, and a list of KPlotObjects to be drawn.
+       */
+
+class KPlotWidget : public QWidget {
+       Q_OBJECT
+public:
+       /**@short Constructor.  Sets the primary x and y limits in data units.
+               *@param x1 the minimum X value in data units
+               *@param x2 the maximum X value in data units
+               *@param y1 the minimum Y value in data units
+               *@param y2 the maximum Y value in data units
+               *@param parent the parent widget
+               *@param name name label for the KPlotWidget
+               */
+       KPlotWidget( double x1=0.0, double x2=1.0, double y1=0.0, double y2=1.0, QWidget *parent=0, const char* name=0 );
+
+       /**Destructor (empty)
+               */
+       virtual ~KPlotWidget() {}
+
+       /**@short Determine the placement of major and minor tickmarks,
+               *based on the current Limit settings
+               */
+       virtual void updateTickmarks();
+
+       /**@short Reset the data limits.
+               *@param x1 the minimum X value in data units
+               *@param x2 the maximum X value in data units
+               *@param y1 the minimum Y value in data units
+               *@param y2 the maximum Y value in data units
+               */
+       virtual void setLimits( double x1, double x2, double y1, double y2 );
+
+       /**@return the minimum X value in data units*/
+       virtual double x() const { return DataRect.x(); }
+
+       /**@return the maximum X value in data units*/
+       virtual double x2() const { return DataRect.x2(); }
+
+       /**@return the minimum Y value in data units*/
+       virtual double y() const { return DataRect.y(); }
+
+       /**@return the maximum Y value in data units*/
+       virtual double y2() const { return DataRect.y2(); }
+
+       /**@return the width in data units*/
+       virtual double dataWidth() const { return DataRect.width(); }
+
+       /**@return the height in data units*/
+       virtual double dataHeight() const { return DataRect.height(); }
+
+       /**@short Add an item to the list of KPlotObjects to be plotted.
+               *@param o pointer to the KPlotObject to be added
+               */
+       virtual void addObject( KPlotObject *o ) { ObjectList.append( o ); }
+
+       /**@short Remove all items from the list of KPlotObjects
+               */
+       virtual void clearObjectList() { ObjectList.clear(); update(); }
+
+       /**@short replace an item in the KPlotObject list.
+               *@param i the index of th item to be replaced
+               *@param o pointer to the replacement KPlotObject
+               */
+       virtual void replaceObject( int i, KPlotObject *o ) { ObjectList.replace( i, o ); }
+
+       /**@return the number of KPlotObjects in the list
+               */
+       virtual int objectCount() const { return ObjectList.count(); }
+
+       /**@return a pointer to a specific KPlotObject in the list
+        *@param i the index of the desired KPlotObject
+        */
+       virtual KPlotObject *object( int i ) { return ObjectList.at(i); }
+
+       /**@return the background color */
+       virtual QColor bgColor() const { return cBackground; }
+
+       /**@return the foreground color */
+       virtual QColor fgColor() const { return cForeground; }
+
+       /**@return the grid color */
+       virtual QColor gridColor() const { return cGrid; }
+
+       /**@short set the background color
+               *@param bg the new background color
+               */
+       virtual void setBGColor( const QColor &bg ) { cBackground = bg; setBackgroundColor( bg ); }
+
+       /**@short set the foreground color
+               *@param bg the new foreground color
+               */
+       virtual void setFGColor( const QColor &fg ) { cForeground = fg; }
+
+       /**@short set the grid color
+               *@param bg the new grid color
+               */
+       virtual void setGridColor( const QColor &gc ) { cGrid = gc; }
+
+       virtual void setShowAxes( bool show ) { ShowAxes = show; }
+       virtual void setShowTickMarks( bool show ) { ShowTickMarks = show; }
+       virtual void setShowTickLabels( bool show ) { ShowTickLabels = show; }
+       virtual void setShowGrid( bool show ) { ShowGrid = show; }
+
+protected:
+       /**@short the paint event handler, executed when update() or repaint() is called.
+               */
+       virtual void paintEvent( QPaintEvent *e );
+
+       /**@short the resize event handler, called when the widget is resized.
+               */
+       virtual void resizeEvent( QResizeEvent *e );
+
+       /**@short draws all of the objects onto the widget.  Internal use only; one should simply call update()
+               *to draw the widget with axes and all objects.
+               *@param p pointer to the painter on which we are drawing
+               */
+       virtual void drawObjects( QPainter *p );
+
+       /**@short draws the plot axes and axis labels.  Internal use only; one should simply call update()
+               *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 );
+
+       /**@short modulus function for double variables.
+               *For example, dmod( 17.0, 7.0 ) returns 3.0
+               *@return the remainder after dividing b into a.
+               */
+       double dmod( double a, double b );
+
+       //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
+       QRect PixRect;
+       //Limits of the plot area in data units
+       DRect DataRect;
+       //List of KPlotObjects 
+       QPtrList<KPlotObject> ObjectList;
+
+       //Colors
+       QColor cBackground, cForeground, cGrid;
+       //draw options
+       bool ShowAxes, ShowTickMarks, ShowTickLabels, ShowGrid;
+
+       QPixmap *buffer;
+};
+
+#endif