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