diff options
Diffstat (limited to 'kdeui/kruler.cpp')
-rw-r--r-- | kdeui/kruler.cpp | 742 |
1 files changed, 742 insertions, 0 deletions
diff --git a/kdeui/kruler.cpp b/kdeui/kruler.cpp new file mode 100644 index 000000000..08cea5515 --- /dev/null +++ b/kdeui/kruler.cpp @@ -0,0 +1,742 @@ +/* This file is part of the KDE libraries + Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include "kruler.h" + +#include <qpainter.h> +#include <qfont.h> + +#define INIT_VALUE 0 +#define INIT_MIN_VALUE 0 +#define INIT_MAX_VALUE 100 +#define INIT_TINY_MARK_DISTANCE 1 +#define INIT_LITTLE_MARK_DISTANCE 5 +#define INIT_MIDDLE_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 2) +#define INIT_BIG_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 10) +#define INIT_SHOW_TINY_MARK false +#define INIT_SHOW_LITTLE_MARK true +#define INIT_SHOW_MEDIUM_MARK true +#define INIT_SHOW_BIG_MARK true +#define INIT_SHOW_END_MARK true +#define INIT_SHOW_POINTER true +#define INIT_SHOW_END_LABEL true + +#define INIT_PIXEL_PER_MARK (double)10.0 /* distance between 2 base marks in pixel */ +#define INIT_OFFSET (-20) +#define INIT_LENGTH_FIX true +#define INIT_END_OFFSET 0 + +#define FIX_WIDTH 20 /* widget width in pixel */ +#define LINE_END (FIX_WIDTH - 3) +#define END_MARK_LENGTH (FIX_WIDTH - 6) +#define END_MARK_X2 LINE_END +#define END_MARK_X1 (END_MARK_X2 - END_MARK_LENGTH) +#define BIG_MARK_LENGTH (END_MARK_LENGTH*3/4) +#define BIG_MARK_X2 LINE_END +#define BIG_MARK_X1 (BIG_MARK_X2 - BIG_MARK_LENGTH) +#define MIDDLE_MARK_LENGTH (END_MARK_LENGTH/2) +#define MIDDLE_MARK_X2 LINE_END +#define MIDDLE_MARK_X1 (MIDDLE_MARK_X2 - MIDDLE_MARK_LENGTH) +#define LITTLE_MARK_LENGTH (MIDDLE_MARK_LENGTH/2) +#define LITTLE_MARK_X2 LINE_END +#define LITTLE_MARK_X1 (LITTLE_MARK_X2 - LITTLE_MARK_LENGTH) +#define BASE_MARK_LENGTH (LITTLE_MARK_LENGTH/2) +#define BASE_MARK_X2 LINE_END +#define BASE_MARK_X1 (BASE_MARK_X2 - BASE_MARK_LENGTH) + +#define LABEL_SIZE 8 +#define END_LABEL_X 4 +#define END_LABEL_Y (END_LABEL_X + LABEL_SIZE - 2) + +#undef PROFILING + +#ifdef PROFILING +# include <qdatetime.h> +#endif + +class KRuler::KRulerPrivate +{ +public: + bool showpointer; + bool showEndL; + bool lengthFix; + int endOffset_length; /* marks the offset at the end of the ruler + * i.e. right side at horizontal and down side + * at vertical rulers. + * the ruler end mark is moved endOffset_length + * ticks away from the widget end. + * positive offset moves end mark inside the ruler. + * if lengthFix is true, endOffset_length holds the + * length of the ruler. + */ + int fontWidth; // ONLY valid for vertical rulers +}; + + + +KRuler::KRuler(QWidget *parent, const char *name) + : QFrame(parent, name), + range(INIT_MIN_VALUE, INIT_MAX_VALUE, 1, 10, INIT_VALUE), + dir(Horizontal) +{ + init(); + setFixedHeight(FIX_WIDTH); +} + + +KRuler::KRuler(Orientation orient, + QWidget *parent, const char *name, WFlags f) + : QFrame(parent, name, f), + range(INIT_MIN_VALUE, INIT_MAX_VALUE, 1, 10, INIT_VALUE), + dir(orient) +{ + init(); + if (orient == Horizontal) + setFixedHeight(FIX_WIDTH); + else + setFixedWidth(FIX_WIDTH); +} + + +KRuler::KRuler(Orientation orient, int widgetWidth, + QWidget *parent, const char *name, WFlags f) + : QFrame(parent, name, f), + range(INIT_MIN_VALUE, INIT_MAX_VALUE, 1, 10, INIT_VALUE), + dir(orient) +{ + init(); + + if (orient == Horizontal) + setFixedHeight(widgetWidth); + else + setFixedWidth(widgetWidth); +} + + +void KRuler::init() +{ + setFrameStyle(WinPanel | Raised); + + tmDist = INIT_TINY_MARK_DISTANCE; + lmDist = INIT_LITTLE_MARK_DISTANCE; + mmDist = INIT_MIDDLE_MARK_DISTANCE; + bmDist = INIT_BIG_MARK_DISTANCE; + offset_= INIT_OFFSET; + showtm = INIT_SHOW_TINY_MARK; + showlm = INIT_SHOW_LITTLE_MARK; + showmm = INIT_SHOW_MEDIUM_MARK; + showbm = INIT_SHOW_BIG_MARK; + showem = INIT_SHOW_END_MARK; + ppm = INIT_PIXEL_PER_MARK; + + d = new KRuler::KRulerPrivate; + d->showpointer = INIT_SHOW_POINTER; + d->showEndL = INIT_SHOW_END_LABEL; + d->lengthFix = INIT_LENGTH_FIX; + d->endOffset_length = INIT_END_OFFSET; +} + + +KRuler::~KRuler() +{ + delete d; +} + +void +KRuler::setMinValue(int value) +{ + if (range.minValue() != value) { + range.setRange( value, range.maxValue() ); + update(contentsRect()); + } +} + +void +KRuler::setMaxValue(int value) +{ + if (range.maxValue() != value) { + range.setRange( range.minValue(), value ); + update(contentsRect()); + } +} + +void +KRuler::setRange(int min, int max) +{// debug("set range from %i to %i", min, max); + if ((range.minValue() != min) || (range.maxValue() != max)) { + range.setRange( min, max ); + update(contentsRect()); + } +} + +void +KRuler::setValue(int value) +{ + range.setValue(value); + update(contentsRect()); +} + +void +KRuler::setTinyMarkDistance(int dist) +{ + if (dist != tmDist) { + tmDist = dist; + update(contentsRect()); + } +} + +void +KRuler::setLittleMarkDistance(int dist) +{ + if (dist != lmDist) { + lmDist = dist; + update(contentsRect()); + } +} + +void +KRuler::setMediumMarkDistance(int dist) +{ + if (dist != mmDist) { + mmDist = dist; + update(contentsRect()); + } +} + +void +KRuler::setBigMarkDistance(int dist) +{ + if (dist != bmDist) { + bmDist = dist; + update(contentsRect()); + } +} + +void +KRuler::setShowTinyMarks(bool show) +{ + if (show != showtm) { + showtm = show; + update(contentsRect()); + } +} + +bool +KRuler::showTinyMarks() const +{ + return showtm; +} + +void +KRuler::setShowLittleMarks(bool show) +{ + if (show != showlm) { + showlm = show; + update(contentsRect()); + } +} + +bool +KRuler::showLittleMarks() const +{ + return showlm; +} + +void +KRuler::setShowMediumMarks(bool show) +{ + if (show != showmm) { + showmm = show; + update(contentsRect()); + } +} + +bool +KRuler::showMediumMarks() const +{ + return showmm; +} + +void +KRuler::setShowBigMarks(bool show) +{ + if (show != showbm) { + showbm = show; + update(contentsRect()); + } +} + + +bool +KRuler::showBigMarks() const +{ + return showbm; +} + +void +KRuler::setShowEndMarks(bool show) +{ + if (show != showem) { + showem = show; + update(contentsRect()); + } +} + +bool +KRuler::showEndMarks() const +{ + return showem; +} + +void +KRuler::setShowPointer(bool show) +{ + if (show != d->showpointer) { + d->showpointer = show; + update(contentsRect()); + } +} + + +bool +KRuler::showPointer() const +{ + return d->showpointer; +} + +void +KRuler::setValuePerLittleMark(int) +{ + update(contentsRect()); +} + +void +KRuler::setValuePerMediumMark(int) +{ + update(contentsRect()); +} + +void +KRuler::setValuePerBigMark(int) +{ + update(contentsRect()); +} + +void +KRuler::setShowEndLabel(bool show) +{ + if (d->showEndL != show) { + d->showEndL = show; + update(contentsRect()); + } +} + + +bool +KRuler::showEndLabel() const +{ + return d->showEndL; +} + + +void +KRuler::setEndLabel(const QString& label) +{ + endlabel = label; + + // premeasure the fontwidth and save it + if (dir == Vertical) { + QFont font = this->font(); + font.setPointSize(LABEL_SIZE); + QFontMetrics fm(font); + d->fontWidth = fm.width(endlabel); + } + update(contentsRect()); +} + +QString KRuler::endLabel() const +{ + return endlabel; +} + +void +KRuler::setRulerMetricStyle(KRuler::MetricStyle style) +{ + switch (style) { + default: /* fall through */ + case Custom: + return; + case Pixel: + setLittleMarkDistance(1); + setMediumMarkDistance(5); + setBigMarkDistance(10); + + setShowTinyMarks(false); + setShowLittleMarks(true); + setShowMediumMarks(true); + setShowBigMarks(true); + setShowEndMarks(true); + + update(contentsRect()); + setPixelPerMark(10.0); + + break; + case Inch: + setTinyMarkDistance(1); + setLittleMarkDistance(2); + setMediumMarkDistance(4); + setBigMarkDistance(8); + + setShowTinyMarks(true); + setShowLittleMarks(true); + setShowMediumMarks(true); + setShowBigMarks(true); + setShowEndMarks(true); + + update(contentsRect()); + setPixelPerMark(9.0); + + break; + case Millimetres: /* fall through */ + case Centimetres: /* fall through */ + case Metres: + setLittleMarkDistance(1); + setMediumMarkDistance(5); + setBigMarkDistance(10); + + setShowTinyMarks(false); + setShowLittleMarks(true); + setShowMediumMarks(true); + setShowBigMarks(true); + setShowEndMarks(true); + + update(contentsRect()); + setPixelPerMark(3.0); + } + switch (style) { + case Pixel: + setEndLabel(QString::fromLatin1("pixel")); + break; + case Inch: + setEndLabel(QString::fromLatin1("inch")); + break; + case Millimetres: + setEndLabel(QString::fromLatin1("mm")); + break; + case Centimetres: + setEndLabel(QString::fromLatin1("cm")); + break; + case Metres: + setEndLabel(QString::fromLatin1("m")); + default: /* never reached, see above switch */ + /* empty command */; + } + // if the style changes one of the values, + // update would have been called inside the methods + // -> no update() call needed here ! +} + +void +KRuler::setPixelPerMark(double rate) +{ // never compare floats against each other :) + ppm = rate; + update(contentsRect()); +} + + +void +KRuler::setLength(int length) +{ + int tmp; + if (d->lengthFix) { + tmp = length; + } + else { + tmp = this->width() - length; + } + if (tmp != d->endOffset_length) { + d->endOffset_length = tmp; + update(contentsRect()); + } +} + +int +KRuler::length() const +{ + if (d->lengthFix) { + return d->endOffset_length; + } + return (this->width() - d->endOffset_length); +} + + +void +KRuler::setLengthFixed(bool fix) +{ + d->lengthFix = fix; +} + +bool +KRuler::lengthFixed() const +{ + return d->lengthFix; +} + +void +KRuler::setOffset(int _offset) +{// debug("set offset %i", _offset); + if (offset_ != _offset) { + offset_ = _offset; + update(contentsRect()); + } +} + +int +KRuler::endOffset() const +{ + if (d->lengthFix) { + return (this->width() - d->endOffset_length); + } + return d->endOffset_length; +} + + +void +KRuler::slideUp(int count) +{ + if (count) { + offset_ += count; + update(contentsRect()); + } +} + +void +KRuler::slideDown(int count) +{ + if (count) { + offset_ -= count; + update(contentsRect()); + } +} + + +void +KRuler::slotNewValue(int _value) +{ + int oldvalue = range.value(); + if (oldvalue == _value) { + return; + } + // setValue(_value); + range.setValue(_value); + if (range.value() == oldvalue) { + return; + } + // get the rectangular of the old and the new ruler pointer + // and repaint only him + if (dir == Horizontal) { + QRect oldrec(-5+oldvalue,10, 11,6); + QRect newrec(-5+_value,10, 11,6); + repaint( oldrec.unite(newrec) ); + } + else { + QRect oldrec(10,-5+oldvalue, 6,11); + QRect newrec(10,-5+_value, 6,11); + repaint( oldrec.unite(newrec) ); + } +} + +void +KRuler::slotNewOffset(int _offset) +{ + if (offset_ != _offset) { + //setOffset(_offset); + offset_ = _offset; + repaint(contentsRect()); + } +} + + +void +KRuler::slotEndOffset(int offset) +{ + int tmp; + if (d->lengthFix) { + tmp = this->width() - offset; + } + else { + tmp = offset; + } + if (d->endOffset_length != tmp) { + d->endOffset_length = tmp; + repaint(contentsRect()); + } +} + +void +KRuler::drawContents(QPainter *p) +{ + // debug ("KRuler::drawContents, %s",(horizontal==dir)?"horizontal":"vertical"); + +#ifdef PROFILING + QTime time; + time.start(); + for (int profile=0; profile<10; profile++) { +#endif + + int value = range.value(), + minval = range.minValue(), + maxval; + if (dir == Horizontal) { + maxval = range.maxValue() + + offset_ + - (d->lengthFix?(height()-d->endOffset_length):d->endOffset_length); + } + else + { + maxval = range.maxValue() + + offset_ + - (d->lengthFix?(width()-d->endOffset_length):d->endOffset_length); + } + //ioffsetval = value-offset; + // pixelpm = (int)ppm; + // left = clip.left(), + // right = clip.right(); + double f, fend, + offsetmin=(double)(minval-offset_), + offsetmax=(double)(maxval-offset_), + fontOffset = (((double)minval)>offsetmin)?(double)minval:offsetmin; + + // draw labels + QFont font = p->font(); + font.setPointSize(LABEL_SIZE); + p->setFont( font ); + // draw littlemarklabel + + // draw mediummarklabel + + // draw bigmarklabel + + // draw endlabel + if (d->showEndL) { + if (dir == Horizontal) { + p->translate( fontOffset, 0 ); + p->drawText( END_LABEL_X, END_LABEL_Y, endlabel ); + } + else { // rotate text +pi/2 and move down a bit + //QFontMetrics fm(font); +#ifdef KRULER_ROTATE_TEST + p->rotate( -90.0 + rotate ); + p->translate( -8.0 - fontOffset - d->fontWidth + xtrans, + ytrans ); +#else + p->rotate( -90.0 ); + p->translate( -8.0 - fontOffset - d->fontWidth, 0.0 ); +#endif + p->drawText( END_LABEL_X, END_LABEL_Y, endlabel ); + } + p->resetXForm(); + } + + // draw the tiny marks + if (showtm) { + fend = ppm*tmDist; + for ( f=offsetmin; f<offsetmax; f+=fend ) { + if (dir == Horizontal) { + p->drawLine((int)f, BASE_MARK_X1, (int)f, BASE_MARK_X2); + } + else { + p->drawLine(BASE_MARK_X1, (int)f, BASE_MARK_X2, (int)f); + } + } + } + if (showlm) { + // draw the little marks + fend = ppm*lmDist; + for ( f=offsetmin; f<offsetmax; f+=fend ) { + if (dir == Horizontal) { + p->drawLine((int)f, LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2); + } + else { + p->drawLine(LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2, (int)f); + } + } + } + if (showmm) { + // draw medium marks + fend = ppm*mmDist; + for ( f=offsetmin; f<offsetmax; f+=fend ) { + if (dir == Horizontal) { + p->drawLine((int)f, MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2); + } + else { + p->drawLine(MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2, (int)f); + } + } + } + if (showbm) { + // draw big marks + fend = ppm*bmDist; + for ( f=offsetmin; f<offsetmax; f+=fend ) { + if (dir == Horizontal) { + p->drawLine((int)f, BIG_MARK_X1, (int)f, BIG_MARK_X2); + } + else { + p->drawLine(BIG_MARK_X1, (int)f, BIG_MARK_X2, (int)f); + } + } + } + if (showem) { + // draw end marks + if (dir == Horizontal) { + p->drawLine(minval-offset_, END_MARK_X1, minval-offset_, END_MARK_X2); + p->drawLine(maxval-offset_, END_MARK_X1, maxval-offset_, END_MARK_X2); + } + else { + p->drawLine(END_MARK_X1, minval-offset_, END_MARK_X2, minval-offset_); + p->drawLine(END_MARK_X1, maxval-offset_, END_MARK_X2, maxval-offset_); + } + } + + // draw pointer + if (d->showpointer) { + QPointArray pa(4); + if (dir == Horizontal) { + pa.setPoints(3, value-5, 10, value+5, 10, value/*+0*/,15); + } + else { + pa.setPoints(3, 10, value-5, 10, value+5, 15, value/*+0*/); + } + p->setBrush( p->backgroundColor() ); + p->drawPolygon( pa ); + } + +#ifdef PROFILING + } + int elapsed = time.elapsed(); + debug("paint time %i",elapsed); +#endif + +} + +void KRuler::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +#include "kruler.moc" |