Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

qwt_scldraw.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 // vim: expandtab
00011 
00012 #include <stdio.h>
00013 #include <qpainter.h>
00014 #include "qwt_math.h"
00015 #include "qwt_painter.h"
00016 #include "qwt_scldraw.h"
00017 #include "qwt_layout_metrics.h"
00018 
00019 static const double step_eps = 1.0e-6;
00020 
00029 QwtScaleDraw::QwtScaleDraw():
00030     d_options(Backbone),
00031     d_hpad(4),
00032     d_vpad(4),
00033     d_medLen(6),
00034     d_majLen(8),
00035     d_minLen(4),
00036     d_minAngle(-135 * 16),
00037     d_maxAngle(135 * 16),
00038     d_fmt('g'),
00039     d_prec(4),
00040     d_fieldwidth(0),
00041     d_labelAlignment(0),
00042     d_labelRotation(0.0)
00043 {
00044     // snprintf is C99 and therefore not portable :-(
00045     // fieldwidth and precision must be in the range 0, 1, .., 99.
00046     sprintf(d_formatBuffer, "%%%d.%d%c", d_fieldwidth, d_prec, d_fmt);
00047     setGeometry(0,0,100,Bottom);
00048     setScale(0,100,0,0,10);
00049 }
00050 
00052 QwtScaleDraw::~QwtScaleDraw()
00053 {
00054 }
00055 
00057 void QwtScaleDraw::setOptions(int opt)
00058 {
00059     d_options = opt;
00060 }
00061 
00065 int QwtScaleDraw::options() const
00066 {
00067     return d_options;
00068 }
00069 
00082 void QwtScaleDraw::setScale(double x1, double x2, int maxMajIntv,
00083                             int maxMinIntv, double step, int logscale)
00084 {
00085     d_scldiv.rebuild( x1, x2, maxMajIntv, maxMinIntv, logscale, step, FALSE );
00086     setDblRange( d_scldiv.lBound(), d_scldiv.hBound(), d_scldiv.logScale());
00087 }
00088 
00089 
00094 void QwtScaleDraw::setScale(const QwtScaleDiv &sd)
00095 {
00096     d_scldiv = sd;
00097     setDblRange(d_scldiv.lBound(),d_scldiv.hBound(),d_scldiv.logScale());
00098 }
00099 
00104 void QwtScaleDraw::draw(QPainter *p) const
00105 {
00106     uint i;
00107 
00108     for (i=0; i< d_scldiv.majCnt(); i++)
00109     {
00110         const double val = d_scldiv.majMark(i);
00111         drawTick(p, val, d_majLen);
00112         drawLabel(p, val);
00113     }
00114 
00115     if (d_scldiv.logScale())
00116     {
00117         for (i=0; i< d_scldiv.minCnt(); i++)
00118             drawTick(p, d_scldiv.minMark(i), d_minLen);
00119     }
00120     else
00121     {
00122         const int kmax = d_scldiv.majCnt() - 1;
00123         if (kmax > 0) 
00124         {
00125             double majTick = d_scldiv.majMark(0);
00126             double hval = majTick - 0.5 * d_scldiv.majStep();
00127 
00128             int k = 0;
00129             for (i=0; i< d_scldiv.minCnt(); i++)
00130             {
00131                 const double val = d_scldiv.minMark(i);
00132                 if  (val > majTick)
00133                 {
00134                     if (k < kmax)
00135                     {
00136                         k++;
00137                         majTick = d_scldiv.majMark(k);
00138                     }
00139                     else
00140                     {
00141                         majTick += d_scldiv.majMark(kmax) + d_scldiv.majStep();
00142                     }
00143                     hval = majTick - 0.5 * d_scldiv.majStep();
00144 
00145                 }
00146                 if (qwtAbs(val-hval) < step_eps * d_scldiv.majStep())
00147                     drawTick(p, val, d_medLen);
00148                 else
00149                     drawTick(p, val, d_minLen);
00150             }
00151         }
00152     }
00153 
00154     if ( options() & Backbone )
00155         drawBackbone(p);
00156 }
00157 
00158 
00160 void QwtScaleDraw::drawTick(QPainter *p, double val, int len) const
00161 {
00162     if ( len <= 0 )
00163         return;
00164 
00165     const int tval = transform(val);
00166 
00167     switch(d_orient)
00168     {
00169         case Left:
00170             QwtPainter::drawLine(p, d_xorg, tval, d_xorg - len, tval);
00171             break;
00172 
00173         case Right:
00174             QwtPainter::drawLine(p, d_xorg, tval, d_xorg + len, tval);
00175             break;
00176 
00177         case Bottom: 
00178             QwtPainter::drawLine(p, tval, d_yorg, tval, d_yorg + len);
00179             break;
00180 
00181         case Top:
00182             QwtPainter::drawLine(p, tval, d_yorg, tval, d_yorg - len);
00183             break;
00184 
00185         case Round:
00186             if ((tval <= d_minAngle + 359 * 16) 
00187                 || (tval >= d_minAngle - 359 * 16))
00188             {
00189                 const double arc = double(tval) / 16.0 * M_PI / 180.0;
00190                 const int x1 = qwtInt(d_xCenter + sin(arc) * d_radius);
00191                 const int x2 = qwtInt(d_xCenter + sin(arc) 
00192                     * (d_radius + double(len)));
00193                 const int y1 = qwtInt(d_yCenter - cos(arc) * d_radius);
00194                 const int y2 = qwtInt(d_yCenter - cos(arc) 
00195                     * (d_radius + double(len)));
00196 
00197                 QwtPainter::drawLine(p, x1, y1, x2, y2);
00198             }
00199             break;
00200     }
00201 }
00202 
00204 void QwtScaleDraw::drawLabel(QPainter *p, double val) const
00205 {
00206     QPoint pos;
00207     int alignment;
00208     double rotation;
00209     labelPlacement(QFontMetrics(p->font()), val, pos, alignment, rotation);
00210 
00211     if ( alignment )
00212     {
00213         const QString txt = label(val);
00214         if ( !txt.isEmpty() )
00215         {
00216             QWMatrix m = labelWorldMatrix(QFontMetrics(p->font()),
00217                 pos, alignment, rotation, txt);
00218 
00219             p->save();
00220 #ifndef QT_NO_TRANSFORMATIONS
00221             p->setWorldMatrix(m, TRUE);
00222 #else
00223             p->translate(m.dx(), m.dy());
00224 #endif
00225             QwtPainter::drawText(p, 0, 0, txt);
00226             p->restore();
00227         }
00228     }
00229 }
00230 
00232 void QwtScaleDraw::labelPlacement( const QFontMetrics &fm, double val, 
00233     QPoint &pos, int &alignment, double &rotation) const
00234 {
00235     // correct rounding errors if val = 0
00236     if ((!d_scldiv.logScale()) 
00237         && (qwtAbs(val) < qwtAbs(step_eps * d_scldiv.majStep())))
00238     {
00239        val = 0.0;
00240     }
00241     
00242     const int tval = transform(val);
00243 
00244     int x = 0;
00245     int y = 0;
00246     int align = 0;
00247 
00248     switch(d_orient)
00249     {
00250         case Right:
00251         {
00252             x = d_xorg + d_majLen + d_hpad + 1;
00253             y = tval;
00254             align = d_labelAlignment;
00255             if ( align == 0 )
00256                 align = Qt::AlignRight | Qt::AlignVCenter;
00257             break;
00258         }
00259         case Left:
00260         {
00261             x = d_xorg - d_majLen - d_hpad - 1;
00262             y = tval;
00263             align = d_labelAlignment;
00264             if ( align == 0 )
00265                 align = Qt::AlignLeft | Qt::AlignVCenter;
00266             break;
00267         }
00268         case Bottom:
00269         {
00270             x = tval;
00271             y = d_yorg + d_majLen + d_vpad + 1;
00272             align = d_labelAlignment;
00273             if ( align == 0 )
00274                 align = Qt::AlignHCenter | Qt::AlignBottom;
00275             break;
00276         }
00277         case Top:
00278         {
00279             x = tval;
00280             y = d_yorg - d_majLen - d_vpad - 1;
00281             align = d_labelAlignment;
00282             if ( align == 0 )
00283                 align = Qt::AlignHCenter | Qt::AlignTop;
00284             break;
00285         }
00286         case Round:
00287         {
00288             if ((tval > d_minAngle + 359 * 16) 
00289                 || (tval < d_minAngle - 359 * 16))
00290             {
00291                break;
00292             }
00293             
00294             const int fmh = fm.ascent() - 2; 
00295             const double arc = tval / 16.0 / 360.0 * 2 * M_PI;
00296             const double radius = d_radius + d_majLen + d_vpad;
00297 
00298             // First we find the point on a circle enlarged
00299             // by half of the font height.
00300 
00301             double xOffset = ( radius + fmh / 2 ) * sin(arc); 
00302             double yOffset = ( radius + fmh / 2 ) * cos(arc);
00303 
00304             if ( qwtInt(xOffset) != 0 ) 
00305             {
00306                 // The centered label might cut the circle 
00307                 // with distance: d_radius + d_majLen + d_vpad
00308                 // We align the label to the circle by moving
00309                 // the x-coordinate, because we have only
00310                 // horizontal labels here.
00311 
00312                 const int fmw = fm.width(label(val));
00313 
00314                 const double circleX = radius * sin(arc); 
00315                 if ( xOffset < 0 )
00316                     xOffset = circleX - fmw / 2; // left
00317                 else
00318                     xOffset = circleX + fmw / 2; // right
00319             }
00320             x = qwtInt(d_xCenter + xOffset);
00321             y = qwtInt(d_yCenter - yOffset);
00322             align = Qt::AlignHCenter | Qt::AlignVCenter;
00323 
00324             break;
00325         }
00326     }
00327 
00328     pos = QPoint(x, y);
00329     alignment = align;
00330     rotation = d_labelRotation;
00331 }
00332 
00334 
00335 QWMatrix QwtScaleDraw::labelWorldMatrix(const QFontMetrics &fm,
00336     const QPoint &pos, int alignment, 
00337 #ifdef QT_NO_TRANSFORMATIONS
00338     double,
00339 #else
00340     double rotation, 
00341 #endif
00342     const QString &txt) const
00343 {
00344     const int w = fm.boundingRect(0, 0, 
00345         QCOORD_MAX, QCOORD_MAX, 0, txt).width() - 2;
00346     const int h = fm.ascent() - 2;
00347     
00348     int x, y;
00349     if ( alignment & Qt::AlignLeft )
00350         x = -w;
00351     else if ( alignment & Qt::AlignRight )
00352         x = 0 - w % 2;
00353     else // Qt::AlignHCenter
00354         x = -(w / 2);
00355         
00356     if ( alignment & Qt::AlignTop )
00357         y = 0;
00358     else if ( alignment & Qt::AlignBottom )
00359         y = h - 1;
00360     else // Qt::AlignVCenter
00361         y = h / 2;
00362     
00363     QWMatrix m;
00364     m.translate(pos.x(), pos.y());
00365 #ifndef QT_NO_TRANSFORMATIONS
00366     m.rotate(rotation);
00367 #endif
00368     m.translate(x, y);
00369 
00370     return m;
00371 }
00372 
00374 void QwtScaleDraw::drawBackbone(QPainter *p) const
00375 {
00376     const int bw2 = p->pen().width() / 2;
00377     
00378     switch(d_orient)
00379     {
00380         case Left:
00381             QwtPainter::drawLine(p, d_xorg - bw2, 
00382                 d_yorg, d_xorg - bw2, d_yorg + d_len - 1);
00383             break;
00384         case Right:
00385             QwtPainter::drawLine(p, d_xorg + bw2, 
00386                 d_yorg, d_xorg + bw2, d_yorg + d_len - 1);
00387             break;
00388         case Top:
00389             QwtPainter::drawLine(p, d_xorg, d_yorg - bw2, 
00390                 d_xorg + d_len - 1, d_yorg - bw2);
00391             break;
00392         case Bottom:
00393             QwtPainter::drawLine(p, d_xorg, d_yorg + bw2, 
00394                 d_xorg + d_len - 1, d_yorg + bw2);
00395             break;
00396         case Round:
00397         {
00398             const int a1 = qwtMin(i1(), i2()) - 90 * 16; 
00399             const int a2 = qwtMax(i1(), i2()) - 90 * 16; 
00400             
00401             p->drawArc(d_xorg, d_yorg, d_len, d_len,
00402                 -a2, a2 - a1 + 1);           // counterclockwise
00403             break;
00404         }
00405     }
00406 }
00407 
00408 
00448 void QwtScaleDraw::setGeometry(int xorigin, int yorigin, 
00449     int length, Orientation o)
00450 {
00451     static int minLen = 10;
00452 
00453     d_xorg = xorigin;
00454     d_yorg = yorigin;
00455     d_radius = double(length) * 0.5;
00456     d_xCenter = double(xorigin) + double(length) * 0.5;
00457     d_yCenter = double(yorigin) + double(length) * 0.5;
00458     
00459     if (length > minLen)
00460        d_len = length;
00461     else
00462        d_len = minLen;
00463     
00464     d_orient = o;
00465     
00466     switch(d_orient)
00467     {
00468         case Left:
00469         case Right:
00470             setIntRange(d_yorg + d_len - 1, d_yorg);
00471             break;
00472         case Round:
00473             setIntRange(d_minAngle, d_maxAngle);
00474             break;
00475         case Top:
00476         case Bottom:
00477             setIntRange(d_xorg, d_xorg + d_len - 1);
00478             break;
00479     }
00480 }
00481 
00487 int QwtScaleDraw::maxWidth(const QPen &pen, const QFontMetrics &fm) const
00488 {
00489     int w = 0;
00490 
00491     switch (d_orient)
00492     {
00493         case Left:
00494         case Right:
00495             w += pen.width() + d_majLen + d_hpad + maxLabelWidth(fm);
00496             break;
00497         case Round:
00498             w += pen.width() + d_majLen + d_vpad + maxLabelWidth(fm);
00499             break;
00500         case Top:
00501         case Bottom:
00502             w = d_len + maxLabelWidth(fm);
00503             break;
00504     }
00505     return w;
00506 }
00507 
00513 int QwtScaleDraw::maxHeight(const QPen &pen, const QFontMetrics &fm) const 
00514 {
00515     int h = 0;
00516     
00517     switch (d_orient)
00518     {
00519         case Top:
00520         case Bottom:
00521             h = pen.width() + d_vpad + d_majLen + maxLabelHeight(fm);
00522             break;
00523         case Left:
00524         case Right:
00525             h = d_len + maxLabelHeight(fm);
00526             break;
00527         case Round:
00528             h = d_vpad + d_majLen;
00529             if ( maxLabelHeight(fm) > 0 )
00530                 h += fm.ascent() - 2;
00531             break;
00532     }
00533     
00534     return h;
00535 }
00536 
00546 void QwtScaleDraw::setLabelRotation(double rotation)
00547 {
00548     d_labelRotation = rotation;
00549 }
00550 
00555 double QwtScaleDraw::labelRotation() const
00556 {
00557     return d_labelRotation;
00558 }
00559 
00579 void QwtScaleDraw::setLabelAlignment(int alignment)
00580 {
00581     d_labelAlignment = alignment;
00582 }
00583 
00588 int QwtScaleDraw::labelAlignment() const
00589 {
00590     return d_labelAlignment;
00591 }
00592 
00611 void QwtScaleDraw::setAngleRange(double angle1, double angle2)
00612 {
00613     angle1 = qwtLim(angle1, -360.0, 360.0);
00614     angle2 = qwtLim(angle2, -360.0, 360.0);
00615 
00616     int amin = int(floor (qwtMin(angle1, angle2) * 16.0 + 0.5));
00617     int amax = int(floor (qwtMax(angle1, angle2) * 16.0 + 0.5));
00618     
00619     if (amin == amax)
00620     {
00621         amin -= 1;
00622         amax += 1;
00623     }
00624     
00625     d_minAngle = amin;
00626     d_maxAngle = amax;
00627     setIntRange(d_minAngle, d_maxAngle);
00628 }
00629 
00646 void QwtScaleDraw::setLabelFormat(char f, int prec, int fieldwidth)
00647 {
00648     switch(f)
00649     {
00650         case 'e':
00651         case 'f':
00652         case 'g':
00653             d_fmt = f;
00654             break;
00655         default:
00656             break;
00657     }
00658     if ((prec > -1) && (prec < 99))
00659         d_prec = prec;
00660     if ((fieldwidth > -1) && (fieldwidth < 99))
00661         d_fieldwidth = fieldwidth;
00662 
00663     sprintf(d_formatBuffer, "%%%d.%d%c", d_fieldwidth, d_prec, d_fmt);
00664 }
00665 
00679 void QwtScaleDraw::labelFormat(char &f, int &prec, int &fieldwidth) const
00680 {
00681     f = d_fmt;
00682     prec = d_prec;
00683     fieldwidth = d_fieldwidth;
00684 }
00685 
00692 void QwtScaleDraw::setMargin(uint hMargin, uint vMargin)
00693 {
00694     d_hpad = hMargin;
00695     d_vpad = vMargin;
00696 }
00697 
00701 void QwtScaleDraw::setTickLength(unsigned int minLen, 
00702     unsigned int medLen, unsigned int majLen)
00703 {
00704     const unsigned int maxTickLen = 1000;
00705 
00706     d_minLen = QMIN(minLen, maxTickLen);
00707     d_medLen = QMIN(medLen, maxTickLen);
00708     d_majLen = QMIN(majLen, maxTickLen);
00709 }
00710 
00715 void QwtScaleDraw::tickLength(unsigned int &minLen,
00716         unsigned int &medLen, unsigned int &majLen) const
00717 {
00718     minLen = d_minLen;
00719     medLen = d_medLen;
00720     majLen = d_majLen;
00721 }
00722 
00727 unsigned int QwtScaleDraw::majTickLength() const
00728 {
00729     return d_majLen;
00730 }
00731 
00736 int QwtScaleDraw::maxLabelWidth(const QFontMetrics &fm) const
00737 {
00738     int maxWidth = 0;
00739 
00740     for (uint i = 0; i < d_scldiv.majCnt(); i++)
00741     {
00742         double val = d_scldiv.majMark(i);
00743 
00744         // correct rounding errors if val = 0
00745 
00746         if ((!d_scldiv.logScale()) 
00747             && (qwtAbs(val) < step_eps * qwtAbs(d_scldiv.majStep())))
00748         {
00749             val = 0.0;
00750         }
00751 
00752         const int w = labelBoundingRect(fm, val).width();
00753         if ( w > maxWidth )
00754             maxWidth = w;
00755     }
00756 
00757     return maxWidth;
00758 }
00759 
00764 int QwtScaleDraw::maxLabelHeight(const QFontMetrics &fm) const
00765 {
00766     int maxHeight = 0;
00767 
00768     for (uint i = 0; i < d_scldiv.majCnt(); i++)
00769     {
00770         double val = d_scldiv.majMark(i);
00771 
00772         // correct rounding errors if val = 0
00773 
00774         if ((!d_scldiv.logScale()) 
00775             && (qwtAbs(val) < step_eps * qwtAbs(d_scldiv.majStep())))
00776         {
00777             val = 0.0;
00778         }
00779 
00780         const int h = labelBoundingRect(fm, val).height();
00781         if ( h > maxHeight )
00782             maxHeight = h;
00783     }
00784 
00785     return maxHeight;
00786 }
00787 
00793 QRect QwtScaleDraw::labelBoundingRect(
00794     const QFontMetrics &fm, double val) const
00795 {
00796     QString zeroString;
00797     if ( d_fieldwidth > 0 )
00798         zeroString.fill('0', d_fieldwidth);
00799 
00800     const QString lbl = label(val);
00801 
00802     const QString &txt = fm.width(zeroString) > fm.width(lbl) 
00803         ? zeroString : lbl;
00804     if ( txt.isEmpty() )
00805         return QRect(0, 0, 0, 0);
00806 
00807     QRect br;
00808 
00809     QPoint pos;
00810     int alignment;
00811     double rotation;
00812 
00813     labelPlacement(fm, val, pos, alignment, rotation);
00814     if ( alignment )
00815     {
00816         // Don't use fm.boundingRect(txt), it cuts off pixels.
00817         const int w = fm.boundingRect(0, 0, 
00818             QCOORD_MAX, QCOORD_MAX, 0, txt).width();
00819         const int h = -(fm.ascent() - 2);
00820 
00821         QWMatrix m = labelWorldMatrix(fm, pos, alignment, rotation, txt);
00822         br = QwtMetricsMap::translate(m, QRect(0, 0, w, h));
00823         br.moveBy(-pos.x(), -pos.y());
00824     }
00825 
00826     return br;
00827 }
00828 
00839 void QwtScaleDraw::minBorderDist(const QFontMetrics &fm,
00840     int &start, int &end ) const
00841 {
00842     start = 0;
00843     end = 0;
00844 
00845     if ( d_scldiv.majCnt() > 0 )
00846     {
00847         const QRect labelRectMin = labelBoundingRect(fm, d_scldiv.majMark(0));
00848         const QRect labelRectMax = labelBoundingRect(fm, 
00849             d_scldiv.majMark(d_scldiv.majCnt() - 1));
00850 
00851         switch (d_orient)
00852         {
00853             case Left:
00854             case Right:
00855                 end = -labelRectMin.y();
00856                 start = labelRectMax.height() + labelRectMax.y();
00857                 break;
00858             case Top:
00859             case Bottom:
00860                 start = -labelRectMin.x();
00861                 end = labelRectMax.width() + labelRectMax.x();
00862                 break;
00863             case Round:
00864                 start = labelRectMin.width();
00865                 end = labelRectMax.width();
00866                 break;
00867         }
00868     }
00869 }
00870 
00880 int QwtScaleDraw::minLabelDist(const QFontMetrics &fm) const
00881 {
00882     if ( d_orient == Round ) // no implementation
00883         return 0;
00884 
00885     if (0 == d_scldiv.majCnt())
00886     {
00887         return 0;
00888     }
00889 
00890     const bool vertical = (d_orient == Left || d_orient == Right);
00891 
00892     QRect bRect1;
00893     QRect bRect2 = labelBoundingRect(fm, d_scldiv.majMark(0));
00894     if ( vertical )
00895     {
00896         bRect2.setRect(-bRect2.bottom(), 0, bRect2.height(), bRect2.width());
00897     }
00898     int maxDist = 0;
00899 
00900     for (uint i = 1; i < d_scldiv.majCnt(); i++ )
00901     {
00902         bRect1 = bRect2;
00903         bRect2 = labelBoundingRect(fm, d_scldiv.majMark(i));
00904         if ( vertical )
00905         {
00906             bRect2.setRect(-bRect2.bottom(), 0,
00907                 bRect2.height(), bRect2.width());
00908         }
00909 
00910         int dist = fm.leading(); // space between the labels
00911         if ( bRect1.right() > 0 )
00912             dist += bRect1.right();
00913         if ( bRect2.left() < 0 )
00914             dist += -bRect2.left();
00915 
00916         if ( dist > maxDist )
00917             maxDist = dist;
00918     }
00919 
00920     double angle = d_labelRotation / 180.0 * M_PI;
00921     if ( vertical )
00922         angle += M_PI / 2;
00923 
00924     if ( sin(angle) == 0.0 )
00925         return maxDist;
00926 
00927     const int fmHeight = fm.ascent() - 2; 
00928 
00929     // The distance we need until there is
00930     // the height of the label font. This height is needed
00931     // for the neighbour labal.
00932 
00933     int labelDist = (int)(fmHeight / sin(angle) * cos(angle));
00934     if ( labelDist < 0 )
00935         labelDist = -labelDist;
00936 
00937     // The cast above floored labelDist. We want to ceil.
00938     labelDist++; 
00939 
00940     // For text orientations close to the scale orientation 
00941 
00942     if ( labelDist > maxDist )
00943         labelDist = maxDist;
00944 
00945     // For text orientations close to the opposite of the 
00946     // scale orientation
00947 
00948     if ( labelDist < fmHeight )
00949         labelDist = fmHeight;
00950 
00951     return labelDist;
00952 }
00953 
00960 int QwtScaleDraw::minHeight( const QPen &pen, const QFontMetrics &fm ) const
00961 {
00962     const int pw = QMAX( 1, pen.width() );  // penwidth can be zero
00963 
00964     int h = 0;
00965     switch ( d_orient )
00966     {
00967         case Left:
00968         case Right:
00969         {
00970             int bottomDist, topDist;
00971             minBorderDist(fm, bottomDist, topDist);
00972 
00973             h = bottomDist + topDist;
00974             if ( d_scldiv.majCnt() >= 2 ) 
00975                 h += minLabelDist(fm) * (d_scldiv.majCnt() - 1);
00976 
00977             int th = 2 * (d_scldiv.majCnt() + d_scldiv.minCnt()) * pw;
00978             if ( th > h )
00979                 h = th;
00980             break;
00981         }
00982         case Round:
00983             // compute the radial thickness
00984             h = pw + d_vpad + d_majLen + maxLabelWidth(fm);
00985             break;
00986         case Top:
00987         case Bottom:
00988             h = pw + d_vpad + d_majLen + maxLabelHeight(fm);
00989             break;
00990     }
00991     return h;
00992 }
00993 
01000 int QwtScaleDraw::minWidth( const QPen &pen, const QFontMetrics &fm ) const
01001 {
01002     const int pw = QMAX( 1, pen.width() );  // penwidth can be zero
01003 
01004     int w = 0;
01005 
01006     switch(d_orient)
01007     {
01008         case Left:
01009         case Right:
01010         {
01011             w = pw + d_hpad + d_majLen + maxLabelWidth(fm);
01012             break;
01013         }
01014         case Round:
01015         {   
01016             w = pw + d_vpad + d_majLen + maxLabelWidth(fm);
01017             break;
01018         }
01019         case Top:
01020         case Bottom:
01021         {
01022             int leftDist, rightDist;
01023             minBorderDist(fm, leftDist, rightDist);
01024 
01025             w = leftDist + rightDist + 
01026                 minLabelDist(fm) * (d_scldiv.majCnt() - 1);
01027 
01028             int tw = 2 * (d_scldiv.majCnt() + d_scldiv.minCnt()) * pw;
01029             if ( tw > w )
01030                 w = tw;
01031 
01032             break;
01033         }
01034     }
01035     return w;
01036 }
01037 
01045 QString QwtScaleDraw::label(double value) const
01046 {
01047 #if 1
01048     if ( value == -0 )
01049         value = 0;
01050 #endif
01051 
01052     // snprintf is C99 and therefore not portable :-(
01053     // sprintf is safe, when buffer is large enough for
01054     // a minus sign, 99 digits, a radix symbol,
01055     // an exponent character, a minus or plus sign, 3 digits,
01056     // and a '\0'.
01057     char buffer[128];
01058     sprintf(buffer, d_formatBuffer, value);
01059 
01060     return QString::fromLatin1(buffer);
01061 }
01062 
01064 int QwtScaleDraw::x() const
01065 {
01066     return d_xorg;
01067 }
01068 
01070 int QwtScaleDraw::y() const
01071 {
01072     return d_yorg;
01073 }
01074 
01076 int QwtScaleDraw::length() const
01077 {
01078     return d_len;
01079 }
01080 
01082 QwtScaleDraw::Orientation QwtScaleDraw::orientation() const 
01083 { 
01084     return d_orient; 
01085 }
01086 
01087 // Local Variables:
01088 // mode: C++
01089 // c-file-style: "stroustrup"
01090 // indent-tabs-mode: nil
01091 // End:

Generated on Sun Nov 21 11:12:44 2004 for Qwt User's Guide by doxygen 1.3.5