kdeui Library API Documentation

kruler.cpp

00001 /* This file is part of the KDE libraries
00002     Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com)
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017     Boston, MA 02111-1307, USA.
00018 */
00019 
00020 /*************************************************************************
00021  * $Id: kruler.cpp,v 1.19 2003/07/17 12:55:51 binner Exp $
00022  *************************************************************************/
00023 
00024 #include "kruler.h"
00025 
00026 #include <qpainter.h>
00027 #include <qfont.h>
00028 
00029 #define INIT_VALUE 0
00030 #define INIT_MIN_VALUE 0
00031 #define INIT_MAX_VALUE 100
00032 #define INIT_TINY_MARK_DISTANCE 1
00033 #define INIT_LITTLE_MARK_DISTANCE 5
00034 #define INIT_MIDDLE_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 2)
00035 #define INIT_BIG_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 10)
00036 #define INIT_SHOW_TINY_MARK false
00037 #define INIT_SHOW_LITTLE_MARK true
00038 #define INIT_SHOW_MEDIUM_MARK true
00039 #define INIT_SHOW_BIG_MARK true
00040 #define INIT_SHOW_END_MARK true
00041 #define INIT_SHOW_POINTER true
00042 #define INIT_SHOW_END_LABEL true
00043 
00044 #define INIT_PIXEL_PER_MARK (double)10.0 /* distance between 2 base marks in pixel */
00045 #define INIT_OFFSET (-20)
00046 #define INIT_LENGTH_FIX true
00047 #define INIT_END_OFFSET 0
00048 
00049 #define FIX_WIDTH 20 /* widget width in pixel */
00050 #define LINE_END (FIX_WIDTH - 3)
00051 #define END_MARK_LENGTH (FIX_WIDTH - 6)
00052 #define END_MARK_X2 LINE_END
00053 #define END_MARK_X1 (END_MARK_X2 - END_MARK_LENGTH)
00054 #define BIG_MARK_LENGTH (END_MARK_LENGTH*3/4)
00055 #define BIG_MARK_X2 LINE_END
00056 #define BIG_MARK_X1 (BIG_MARK_X2 - BIG_MARK_LENGTH)
00057 #define MIDDLE_MARK_LENGTH (END_MARK_LENGTH/2)
00058 #define MIDDLE_MARK_X2 LINE_END
00059 #define MIDDLE_MARK_X1 (MIDDLE_MARK_X2 - MIDDLE_MARK_LENGTH)
00060 #define LITTLE_MARK_LENGTH (MIDDLE_MARK_LENGTH/2)
00061 #define LITTLE_MARK_X2 LINE_END
00062 #define LITTLE_MARK_X1 (LITTLE_MARK_X2 - LITTLE_MARK_LENGTH)
00063 #define BASE_MARK_LENGTH (LITTLE_MARK_LENGTH/2)
00064 #define BASE_MARK_X2 LINE_END
00065 #define BASE_MARK_X1 (BASE_MARK_X2 - BASE_MARK_LENGTH)
00066 
00067 #define LABEL_SIZE 8
00068 #define END_LABEL_X 4
00069 #define END_LABEL_Y (END_LABEL_X + LABEL_SIZE - 2)
00070 
00071 #undef PROFILING
00072 
00073 #ifdef PROFILING
00074 # include <qdatetime.h>
00075 #endif
00076 
00077 class KRuler::KRulerPrivate
00078 {
00079 public:
00080   bool showpointer;
00081   bool showEndL;
00082   bool lengthFix;
00083   int  endOffset_length;  /* marks the offset at the end of the ruler
00084                            * i.e. right side at horizontal and down side
00085                            * at vertical rulers.
00086                            * the ruler end mark is moved endOffset_length
00087                            * ticks away from the widget end.
00088                            * positive offset moves end mark inside the ruler.
00089                            * if lengthFix is true, endOffset_length holds the
00090                            * length of the ruler.
00091                            */
00092   int fontWidth; // ONLY valid for vertical rulers
00093 };
00094 
00095 
00096 
00097 KRuler::KRuler(QWidget *parent, const char *name)
00098   : QFrame(parent, name),
00099     range(INIT_MIN_VALUE, INIT_MAX_VALUE, 1, 10, INIT_VALUE),
00100     dir(Horizontal)
00101 {
00102   init();
00103   setFixedHeight(FIX_WIDTH);
00104 }
00105 
00106 
00107 KRuler::KRuler(Orientation orient,
00108                QWidget *parent, const char *name, WFlags f)
00109   : QFrame(parent, name, f),
00110     range(INIT_MIN_VALUE, INIT_MAX_VALUE, 1, 10, INIT_VALUE),
00111     dir(orient)
00112 {
00113   init();
00114   if (orient == Horizontal)
00115     setFixedHeight(FIX_WIDTH);
00116   else
00117     setFixedWidth(FIX_WIDTH);
00118 }
00119 
00120 
00121 KRuler::KRuler(Orientation orient, int widgetWidth,
00122                QWidget *parent, const char *name, WFlags f)
00123   : QFrame(parent, name, f),
00124     range(INIT_MIN_VALUE, INIT_MAX_VALUE, 1, 10, INIT_VALUE),
00125     dir(orient)
00126 {
00127   init();
00128 
00129   if (orient == Horizontal)
00130     setFixedHeight(widgetWidth);
00131   else
00132     setFixedWidth(widgetWidth);
00133 }
00134 
00135 
00136 void KRuler::init()
00137 {
00138   setFrameStyle(WinPanel | Raised);
00139 
00140   tmDist = INIT_TINY_MARK_DISTANCE;
00141   lmDist = INIT_LITTLE_MARK_DISTANCE;
00142   mmDist = INIT_MIDDLE_MARK_DISTANCE;
00143   bmDist = INIT_BIG_MARK_DISTANCE;
00144   offset_= INIT_OFFSET;
00145   showtm = INIT_SHOW_TINY_MARK;
00146   showlm = INIT_SHOW_LITTLE_MARK;
00147   showmm = INIT_SHOW_MEDIUM_MARK;
00148   showbm = INIT_SHOW_BIG_MARK;
00149   showem = INIT_SHOW_END_MARK;
00150   ppm = INIT_PIXEL_PER_MARK;
00151 
00152   d = new KRuler::KRulerPrivate;
00153   d->showpointer = INIT_SHOW_POINTER;
00154   d->showEndL = INIT_SHOW_END_LABEL;
00155   d->lengthFix = INIT_LENGTH_FIX;
00156   d->endOffset_length = INIT_END_OFFSET;
00157 }
00158 
00159 
00160 KRuler::~KRuler()
00161 {
00162   delete d;
00163 }
00164 
00165 void
00166 KRuler::setMinValue(int value)
00167 {
00168   if (range.minValue() != value) {
00169     range.setRange( value, range.maxValue() );
00170     update(contentsRect());
00171   }
00172 }
00173 
00174 void
00175 KRuler::setMaxValue(int value)
00176 {
00177   if (range.maxValue() != value) {
00178     range.setRange( range.minValue(), value );
00179     update(contentsRect());
00180   }
00181 }
00182 
00183 void
00184 KRuler::setRange(int min, int max)
00185 {// debug("set range from %i to %i", min, max);
00186   if ((range.minValue() != min) || (range.maxValue() != max)) {
00187     range.setRange( min, max );
00188     update(contentsRect());
00189   }
00190 }
00191 
00192 void
00193 KRuler::setValue(int value)
00194 {
00195   range.setValue(value);
00196   update(contentsRect());
00197 }
00198 
00199 void
00200 KRuler::setTinyMarkDistance(int dist)
00201 {
00202   if (dist != tmDist) {
00203     tmDist = dist;
00204     update(contentsRect());
00205   }
00206 }
00207 
00208 void
00209 KRuler::setLittleMarkDistance(int dist)
00210 {
00211   if (dist != lmDist) {
00212     lmDist = dist;
00213     update(contentsRect());
00214   }
00215 }
00216 
00217 void
00218 KRuler::setMediumMarkDistance(int dist)
00219 {
00220   if (dist != mmDist) {
00221     mmDist = dist;
00222     update(contentsRect());
00223   }
00224 }
00225 
00226 void
00227 KRuler::setBigMarkDistance(int dist)
00228 {
00229   if (dist != bmDist) {
00230     bmDist = dist;
00231     update(contentsRect());
00232   }
00233 }
00234 
00235 void
00236 KRuler::setShowTinyMarks(bool show)
00237 {
00238   if (show != showtm) {
00239     showtm = show;
00240     update(contentsRect());
00241   }
00242 }
00243 
00244 bool
00245 KRuler::showTinyMarks() const
00246 {
00247   return showtm;
00248 }
00249 
00250 void
00251 KRuler::setShowLittleMarks(bool show)
00252 {
00253   if (show != showlm) {
00254     showlm = show;
00255     update(contentsRect());
00256   }
00257 }
00258 
00259 bool
00260 KRuler::showLittleMarks() const
00261 {
00262   return showlm;
00263 }
00264 
00265 void
00266 KRuler::setShowMediumMarks(bool show)
00267 {
00268   if (show != showmm) {
00269     showmm = show;
00270     update(contentsRect());
00271   }
00272 }
00273 
00274 bool
00275 KRuler::showMediumMarks() const
00276 {
00277   return showmm;
00278 }
00279 
00280 void
00281 KRuler::setShowBigMarks(bool show)
00282 {
00283   if (show != showbm) {
00284     showbm = show;
00285     update(contentsRect());
00286   }
00287 }
00288 
00289 
00290 bool
00291 KRuler::showBigMarks() const
00292 {
00293   return showbm;
00294 }
00295 
00296 void
00297 KRuler::setShowEndMarks(bool show)
00298 {
00299   if (show != showem) {
00300     showem = show;
00301     update(contentsRect());
00302   }
00303 }
00304 
00305 bool
00306 KRuler::showEndMarks() const
00307 {
00308   return showem;
00309 }
00310 
00311 void
00312 KRuler::setShowPointer(bool show)
00313 {
00314   if (show != d->showpointer) {
00315     d->showpointer = show;
00316     update(contentsRect());
00317   }
00318 }
00319 
00320 
00321 bool
00322 KRuler::showPointer() const
00323 {
00324   return d->showpointer;
00325 }
00326 
00327 void
00328 KRuler::setValuePerLittleMark(int)
00329 {
00330   update(contentsRect());
00331 }
00332 
00333 void
00334 KRuler::setValuePerMediumMark(int)
00335 {
00336    update(contentsRect());
00337 }
00338 
00339 void
00340 KRuler::setValuePerBigMark(int)
00341 {
00342  update(contentsRect());
00343 }
00344 
00345 void
00346 KRuler::setShowEndLabel(bool show)
00347 {
00348   if (d->showEndL != show) {
00349     d->showEndL = show;
00350     update(contentsRect());
00351   }
00352 }
00353 
00354 
00355 bool
00356 KRuler::showEndLabel() const
00357 {
00358     return d->showEndL;
00359 }
00360 
00361 
00362 void
00363 KRuler::setEndLabel(const QString& label)
00364 {
00365   endlabel = label;
00366 
00367   // premeasure the fontwidth and save it
00368   if (dir == Vertical) {
00369     QFont font = this->font();
00370     font.setPointSize(LABEL_SIZE);
00371     QFontMetrics fm(font);
00372     d->fontWidth = fm.width(endlabel);
00373   }
00374   update(contentsRect());
00375 }
00376 
00377 QString KRuler::endLabel() const
00378 {
00379   return endlabel;
00380 }
00381 
00382 void
00383 KRuler::setRulerMetricStyle(KRuler::MetricStyle style)
00384 {
00385   switch (style) {
00386   default: /* fall through */
00387   case Custom:
00388     return;
00389   case Pixel:
00390     setLittleMarkDistance(1);
00391     setMediumMarkDistance(5);
00392     setBigMarkDistance(10);
00393 
00394     setShowTinyMarks(false);
00395     setShowLittleMarks(true);
00396     setShowMediumMarks(true);
00397     setShowBigMarks(true);
00398     setShowEndMarks(true);
00399 
00400     setValuePerMediumMark(50);
00401     setPixelPerMark(10.0);
00402 
00403     break;
00404   case Inch:
00405     setTinyMarkDistance(1);
00406     setLittleMarkDistance(2);
00407     setMediumMarkDistance(4);
00408     setBigMarkDistance(8);
00409 
00410     setShowTinyMarks(true);
00411     setShowLittleMarks(true);
00412     setShowMediumMarks(true);
00413     setShowBigMarks(true);
00414     setShowEndMarks(true);
00415 
00416     setValuePerBigMark(1);
00417     setPixelPerMark(9.0);
00418 
00419     break;
00420   case Millimetres: /* fall through */
00421   case Centimetres: /* fall through */
00422   case Metres:
00423     setLittleMarkDistance(1);
00424     setMediumMarkDistance(5);
00425     setBigMarkDistance(10);
00426 
00427     setShowTinyMarks(false);
00428     setShowLittleMarks(true);
00429     setShowMediumMarks(true);
00430     setShowBigMarks(true);
00431     setShowEndMarks(true);
00432 
00433     setValuePerBigMark(10);
00434     setPixelPerMark(3.0);
00435   }
00436   switch (style) {
00437   case Pixel:
00438     setEndLabel(QString::fromLatin1("pixel"));
00439     break;
00440   case Inch:
00441     setEndLabel(QString::fromLatin1("inch"));
00442     break;
00443   case Millimetres:
00444     setEndLabel(QString::fromLatin1("mm"));
00445     break;
00446   case Centimetres:
00447     setEndLabel(QString::fromLatin1("cm"));
00448     break;
00449   case Metres:
00450     setEndLabel(QString::fromLatin1("m"));
00451   default: /* never reached, see above switch */
00452     /* empty command */;
00453   }
00454   // if the style changes one of the values,
00455   // update would have been called inside the methods
00456   // -> no update() call needed here !
00457 }
00458 
00459 void
00460 KRuler::setPixelPerMark(double rate)
00461 { // never compare floats against each other :)
00462   ppm = rate;
00463   update(contentsRect());
00464 }
00465 
00466 
00467 void
00468 KRuler::setLength(int length)
00469 {
00470   int tmp;
00471   if (d->lengthFix) {
00472     tmp = length;
00473   }
00474   else {
00475     tmp = this->width() - length;
00476   }
00477   if (tmp != d->endOffset_length) {
00478     d->endOffset_length = tmp;
00479     update(contentsRect());
00480   }
00481 }
00482 
00483 int
00484 KRuler::length() const
00485 {
00486   if (d->lengthFix) {
00487     return d->endOffset_length;
00488   }
00489   return (this->width() - d->endOffset_length);
00490 }
00491 
00492 
00493 void
00494 KRuler::setLengthFixed(bool fix)
00495 {
00496   d->lengthFix = fix;
00497 }
00498 
00499 bool
00500 KRuler::lengthFixed() const
00501 {
00502   return d->lengthFix;
00503 }
00504 
00505 void
00506 KRuler::setOffset(int _offset)
00507 {// debug("set offset %i", _offset);
00508   if (offset_ != _offset) {
00509     offset_ = _offset;
00510     update(contentsRect());
00511   }
00512 }
00513 
00514 int
00515 KRuler::endOffset() const
00516 {
00517   if (d->lengthFix) {
00518     return (this->width() - d->endOffset_length);
00519   }
00520   return d->endOffset_length;
00521 }
00522 
00523 
00524 void
00525 KRuler::slideUp(int count)
00526 {
00527   if (count) {
00528     offset_ += count;
00529     update(contentsRect());
00530   }
00531 }
00532 
00533 void
00534 KRuler::slideDown(int count)
00535 {
00536   if (count) {
00537     offset_ -= count;
00538     update(contentsRect());
00539   }
00540 }
00541 
00542 
00543 void
00544 KRuler::slotNewValue(int _value)
00545 {
00546   int oldvalue = range.value();
00547   if (oldvalue == _value) {
00548     return;
00549   }
00550   //    setValue(_value);
00551   range.setValue(_value);
00552   if (range.value() == oldvalue) {
00553     return;
00554   }
00555   // get the rectangular of the old and the new ruler pointer
00556   // and repaint only him
00557   if (dir == Horizontal) {
00558     QRect oldrec(-5+oldvalue,10, 11,6);
00559     QRect newrec(-5+_value,10, 11,6);
00560     repaint( oldrec.unite(newrec) );
00561   }
00562   else {
00563     QRect oldrec(10,-5+oldvalue, 6,11);
00564     QRect newrec(10,-5+_value, 6,11);
00565     repaint( oldrec.unite(newrec) );
00566   }
00567 }
00568 
00569 void
00570 KRuler::slotNewOffset(int _offset)
00571 {
00572   if (offset_ != _offset) {
00573     //setOffset(_offset);
00574     offset_ = _offset;
00575     repaint(contentsRect());
00576   }
00577 }
00578 
00579 
00580 void
00581 KRuler::slotEndOffset(int offset)
00582 {
00583   int tmp;
00584   if (d->lengthFix) {
00585     tmp = this->width() - offset;
00586   }
00587   else {
00588     tmp = offset;
00589   }
00590   if (d->endOffset_length != tmp) {
00591     d->endOffset_length = tmp;
00592     repaint(contentsRect());
00593   }
00594 }
00595 
00596 void
00597 KRuler::drawContents(QPainter *p)
00598 {
00599   //  debug ("KRuler::drawContents, %s",(horizontal==dir)?"horizontal":"vertical");
00600 
00601 #ifdef PROFILING
00602   QTime time;
00603   time.start();
00604   for (int profile=0; profile<10; profile++) {
00605 #endif
00606 
00607   int value  = range.value(),
00608     minval = range.minValue(),
00609     maxval;
00610     if (dir == Horizontal) {
00611     maxval = range.maxValue()
00612     + offset_
00613     - (d->lengthFix?(height()-d->endOffset_length):d->endOffset_length);
00614     }
00615     else
00616     {
00617     maxval = range.maxValue()
00618     + offset_
00619     - (d->lengthFix?(width()-d->endOffset_length):d->endOffset_length);
00620     }
00621     //ioffsetval = value-offset;
00622     //    pixelpm = (int)ppm;
00623   //    left  = clip.left(),
00624   //    right = clip.right();
00625   double f, fend,
00626     offsetmin=(double)(minval-offset_),
00627     offsetmax=(double)(maxval-offset_),
00628     fontOffset = (((double)minval)>offsetmin)?(double)minval:offsetmin;
00629 
00630   // draw labels
00631   QFont font = p->font();
00632   font.setPointSize(LABEL_SIZE);
00633   p->setFont( font );
00634   // draw littlemarklabel
00635 
00636   // draw mediummarklabel
00637 
00638   // draw bigmarklabel
00639 
00640   // draw endlabel
00641   if (d->showEndL) {
00642     if (dir == Horizontal) {
00643       p->translate( fontOffset, 0 );
00644       p->drawText( END_LABEL_X, END_LABEL_Y, endlabel );
00645     }
00646     else { // rotate text +pi/2 and move down a bit
00647       //QFontMetrics fm(font);
00648 #ifdef KRULER_ROTATE_TEST
00649       p->rotate( -90.0 + rotate );
00650       p->translate( -8.0 - fontOffset - d->fontWidth + xtrans,
00651                     ytrans );
00652 #else
00653       p->rotate( -90.0 );
00654       p->translate( -8.0 - fontOffset - d->fontWidth, 0.0 );
00655 #endif
00656       p->drawText( END_LABEL_X, END_LABEL_Y, endlabel );
00657     }
00658     p->resetXForm();
00659   }
00660 
00661   // draw the tiny marks
00662   if (showtm) {
00663     fend = ppm*tmDist;
00664     for ( f=offsetmin; f<offsetmax; f+=fend ) {
00665       if (dir == Horizontal) {
00666         p->drawLine((int)f, BASE_MARK_X1, (int)f, BASE_MARK_X2);
00667       }
00668       else {
00669         p->drawLine(BASE_MARK_X1, (int)f, BASE_MARK_X2, (int)f);
00670       }
00671     }
00672   }
00673   if (showlm) {
00674     // draw the little marks
00675     fend = ppm*lmDist;
00676     for ( f=offsetmin; f<offsetmax; f+=fend ) {
00677       if (dir == Horizontal) {
00678         p->drawLine((int)f, LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2);
00679       }
00680       else {
00681         p->drawLine(LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2, (int)f);
00682       }
00683     }
00684   }
00685   if (showmm) {
00686     // draw medium marks
00687     fend = ppm*mmDist;
00688     for ( f=offsetmin; f<offsetmax; f+=fend ) {
00689       if (dir == Horizontal) {
00690         p->drawLine((int)f, MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2);
00691       }
00692       else {
00693         p->drawLine(MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2, (int)f);
00694       }
00695     }
00696   }
00697   if (showbm) {
00698     // draw big marks
00699     fend = ppm*bmDist;
00700     for ( f=offsetmin; f<offsetmax; f+=fend ) {
00701       if (dir == Horizontal) {
00702         p->drawLine((int)f, BIG_MARK_X1, (int)f, BIG_MARK_X2);
00703       }
00704       else {
00705         p->drawLine(BIG_MARK_X1, (int)f, BIG_MARK_X2, (int)f);
00706       }
00707     }
00708   }
00709   if (showem) {
00710     // draw end marks
00711     if (dir == Horizontal) {
00712       p->drawLine(minval-offset_, END_MARK_X1, minval-offset_, END_MARK_X2);
00713       p->drawLine(maxval-offset_, END_MARK_X1, maxval-offset_, END_MARK_X2);
00714     }
00715     else {
00716       p->drawLine(END_MARK_X1, minval-offset_, END_MARK_X2, minval-offset_);
00717       p->drawLine(END_MARK_X1, maxval-offset_, END_MARK_X2, maxval-offset_);
00718     }
00719   }
00720 
00721   // draw pointer
00722   if (d->showpointer) {
00723     QPointArray pa(4);
00724     if (dir == Horizontal) {
00725       pa.setPoints(3, value-5, 10, value+5, 10, value/*+0*/,15);
00726     }
00727     else {
00728       pa.setPoints(3, 10, value-5, 10, value+5, 15, value/*+0*/);
00729     }
00730     p->setBrush( p->backgroundColor() );
00731     p->drawPolygon( pa );
00732   }
00733 
00734 #ifdef PROFILING
00735   }
00736   int elapsed = time.elapsed();
00737   debug("paint time %i",elapsed);
00738 #endif
00739 
00740 }
00741 
00742 void KRuler::virtual_hook( int, void* )
00743 { /*BASE::virtual_hook( id, data );*/ }
00744 
00745 #include "kruler.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Jan 21 09:57:28 2005 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003