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 Tue Nov 16 21:12:21 2004 for Qwt User's Guide by doxygen 1.3.8