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