KWidgetsAddons

kruler.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1998 Jörg Habenicht <j.habenicht@europemail.com>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "kruler.h"
9
10#include <QFont>
11#include <QPolygon>
12#include <QStylePainter>
13
14#define INIT_VALUE 0
15#define INIT_MIN_VALUE 0
16#define INIT_MAX_VALUE 100
17#define INIT_TINY_MARK_DISTANCE 1
18#define INIT_LITTLE_MARK_DISTANCE 5
19#define INIT_MIDDLE_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 2)
20#define INIT_BIG_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 10)
21#define INIT_SHOW_TINY_MARK false
22#define INIT_SHOW_LITTLE_MARK true
23#define INIT_SHOW_MEDIUM_MARK true
24#define INIT_SHOW_BIG_MARK true
25#define INIT_SHOW_END_MARK true
26#define INIT_SHOW_POINTER true
27#define INIT_SHOW_END_LABEL true
28
29#define INIT_PIXEL_PER_MARK (double)10.0 /* distance between 2 base marks in pixel */
30#define INIT_OFFSET (-20)
31#define INIT_LENGTH_FIX true
32#define INIT_END_OFFSET 0
33
34#define FIX_WIDTH 20 /* widget width in pixel */
35#define LINE_END (FIX_WIDTH - 3)
36#define END_MARK_LENGTH (FIX_WIDTH - 6)
37#define END_MARK_X2 LINE_END
38#define END_MARK_X1 (END_MARK_X2 - END_MARK_LENGTH)
39#define BIG_MARK_LENGTH (END_MARK_LENGTH * 3 / 4)
40#define BIG_MARK_X2 LINE_END
41#define BIG_MARK_X1 (BIG_MARK_X2 - BIG_MARK_LENGTH)
42#define MIDDLE_MARK_LENGTH (END_MARK_LENGTH / 2)
43#define MIDDLE_MARK_X2 LINE_END
44#define MIDDLE_MARK_X1 (MIDDLE_MARK_X2 - MIDDLE_MARK_LENGTH)
45#define LITTLE_MARK_LENGTH (MIDDLE_MARK_LENGTH / 2)
46#define LITTLE_MARK_X2 LINE_END
47#define LITTLE_MARK_X1 (LITTLE_MARK_X2 - LITTLE_MARK_LENGTH)
48#define BASE_MARK_LENGTH (LITTLE_MARK_LENGTH / 2)
49#define BASE_MARK_X2 LINE_END
50#define BASE_MARK_X1 (BASE_MARK_X2 - BASE_MARK_LENGTH)
51
52#define LABEL_SIZE 8
53#define END_LABEL_X 4
54#define END_LABEL_Y (END_LABEL_X + LABEL_SIZE - 2)
55
56#undef PROFILING
57
58#ifdef PROFILING
59#include <qdatetime.h>
60#endif
61
62class KRulerPrivate
63{
64public:
65 int endOffset_length; /* marks the offset at the end of the ruler
66 * i.e. right side at horizontal and down side
67 * at vertical rulers.
68 * the ruler end mark is moved endOffset_length
69 * ticks away from the widget end.
70 * positive offset moves end mark inside the ruler.
71 * if lengthFix is true, endOffset_length holds the
72 * length of the ruler.
73 */
74 int fontWidth; // ONLY valid for vertical rulers
75
76 QAbstractSlider range;
78 int tmDist;
79 int lmDist;
80 int mmDist;
81 int bmDist;
82 int offset;
83 bool showtm : 1; /* show tiny, little, medium, big, endmarks */
84 bool showlm : 1;
85 bool showmm : 1;
86 bool showbm : 1;
87 bool showem : 1;
88
89 bool showpointer : 1;
90 bool showEndL : 1;
91 bool lengthFix : 1;
92
93 double ppm; /* pixel per mark */
94
95 QString endlabel;
96};
97
99 : QAbstractSlider(parent)
100 , d(new KRulerPrivate)
101{
102 setRange(INIT_MIN_VALUE, INIT_MAX_VALUE);
103 setPageStep(10);
104 setValue(INIT_VALUE);
105 initWidget(Qt::Horizontal);
106 setFixedHeight(FIX_WIDTH);
107}
108
110 : QAbstractSlider(parent)
111 , d(new KRulerPrivate)
112{
113 setRange(INIT_MIN_VALUE, INIT_MAX_VALUE);
114 setPageStep(10);
115 setValue(INIT_VALUE);
117 initWidget(orient);
118 if (orient == Qt::Horizontal) {
119 setFixedHeight(FIX_WIDTH);
120 } else {
121 setFixedWidth(FIX_WIDTH);
122 }
123}
124
125KRuler::KRuler(Qt::Orientation orient, int widgetWidth, QWidget *parent, Qt::WindowFlags f)
126 : QAbstractSlider(parent)
127 , d(new KRulerPrivate)
128{
129 setRange(INIT_MIN_VALUE, INIT_MAX_VALUE);
130 setPageStep(10);
131 setValue(INIT_VALUE);
133 initWidget(orient);
134 if (orient == Qt::Horizontal) {
135 setFixedHeight(widgetWidth);
136 } else {
137 setFixedWidth(widgetWidth);
138 }
139}
140
141void KRuler::initWidget(Qt::Orientation orientation)
142{
143 d->showpointer = INIT_SHOW_POINTER;
144 d->showEndL = INIT_SHOW_END_LABEL;
145 d->lengthFix = INIT_LENGTH_FIX;
146 d->endOffset_length = INIT_END_OFFSET;
147
148 d->tmDist = INIT_TINY_MARK_DISTANCE;
149 d->lmDist = INIT_LITTLE_MARK_DISTANCE;
150 d->mmDist = INIT_MIDDLE_MARK_DISTANCE;
151 d->bmDist = INIT_BIG_MARK_DISTANCE;
152 d->offset = INIT_OFFSET;
153 d->showtm = INIT_SHOW_TINY_MARK;
154 d->showlm = INIT_SHOW_LITTLE_MARK;
155 d->showmm = INIT_SHOW_MEDIUM_MARK;
156 d->showbm = INIT_SHOW_BIG_MARK;
157 d->showem = INIT_SHOW_END_MARK;
158 d->ppm = INIT_PIXEL_PER_MARK;
159 d->dir = orientation;
160}
161
162KRuler::~KRuler() = default;
163
165{
166 if (dist != d->tmDist) {
167 d->tmDist = dist;
169 }
170}
171
172int KRuler::tinyMarkDistance() const
173{
174 return d->tmDist;
175}
176
178{
179 if (dist != d->lmDist) {
180 d->lmDist = dist;
182 }
183}
184
185int KRuler::littleMarkDistance() const
186{
187 return d->lmDist;
188}
189
191{
192 if (dist != d->mmDist) {
193 d->mmDist = dist;
195 }
196}
197
198int KRuler::mediumMarkDistance() const
199{
200 return d->mmDist;
201}
202
204{
205 if (dist != d->bmDist) {
206 d->bmDist = dist;
208 }
209}
210
211int KRuler::bigMarkDistance() const
212{
213 return d->bmDist;
214}
215
217{
218 if (show != d->showtm) {
219 d->showtm = show;
221 }
222}
223
224bool KRuler::showTinyMarks() const
225{
226 return d->showtm;
227}
228
230{
231 if (show != d->showlm) {
232 d->showlm = show;
234 }
235}
236
237bool KRuler::showLittleMarks() const
238{
239 return d->showlm;
240}
241
243{
244 if (show != d->showmm) {
245 d->showmm = show;
247 }
248}
249
250bool KRuler::showMediumMarks() const
251{
252 return d->showmm;
253}
254
256{
257 if (show != d->showbm) {
258 d->showbm = show;
260 }
261}
262
263bool KRuler::showBigMarks() const
264{
265 return d->showbm;
266}
267
269{
270 if (show != d->showem) {
271 d->showem = show;
273 }
274}
275
276bool KRuler::showEndMarks() const
277{
278 return d->showem;
279}
280
282{
283 if (show != d->showpointer) {
284 d->showpointer = show;
286 }
287}
288
289bool KRuler::showPointer() const
290{
291 return d->showpointer;
292}
293
295{
296 if (d->showEndL != show) {
297 d->showEndL = show;
299 }
300}
301
302bool KRuler::showEndLabel() const
303{
304 return d->showEndL;
305}
306
307void KRuler::setEndLabel(const QString &label)
308{
309 d->endlabel = label;
310
311 // premeasure the fontwidth and save it
312 if (d->dir == Qt::Vertical) {
313 QFont font = this->font();
314 font.setPointSize(LABEL_SIZE);
315 QFontMetrics fm(font);
316 d->fontWidth = fm.horizontalAdvance(d->endlabel);
317 }
319}
320
321QString KRuler::endLabel() const
322{
323 return d->endlabel;
324}
325
327{
328 switch (style) {
329 default: /* fall through */
330 case Custom:
331 return;
332 case Pixel:
336
337 setShowTinyMarks(false);
338 setShowLittleMarks(true);
339 setShowMediumMarks(true);
340 setShowBigMarks(true);
341 setShowEndMarks(true);
342
344 setPixelPerMark(10.0);
345
346 break;
347 case Inch:
352
353 setShowTinyMarks(true);
354 setShowLittleMarks(true);
355 setShowMediumMarks(true);
356 setShowBigMarks(true);
357 setShowEndMarks(true);
358
360 setPixelPerMark(9.0);
361
362 break;
363 case Millimetres: /* fall through */
364 case Centimetres: /* fall through */
365 case Metres:
369
370 setShowTinyMarks(false);
371 setShowLittleMarks(true);
372 setShowMediumMarks(true);
373 setShowBigMarks(true);
374 setShowEndMarks(true);
375
377 setPixelPerMark(3.0);
378 }
379 switch (style) {
380 case Pixel:
381 setEndLabel(QStringLiteral("pixel"));
382 break;
383 case Inch:
384 setEndLabel(QStringLiteral("inch"));
385 break;
386 case Millimetres:
387 setEndLabel(QStringLiteral("mm"));
388 break;
389 case Centimetres:
390 setEndLabel(QStringLiteral("cm"));
391 break;
392 case Metres:
393 setEndLabel(QStringLiteral("m"));
394 default: /* never reached, see above switch */
395 /* empty command */;
396 }
397 // if the style changes one of the values,
398 // update would have been called inside the methods
399 // -> no update() call needed here !
400}
401
402void KRuler::setPixelPerMark(double rate)
403{
404 // never compare floats against each other :)
405 d->ppm = rate;
407}
408
409double KRuler::pixelPerMark() const
410{
411 return d->ppm;
412}
413
414void KRuler::setLength(int length)
415{
416 int tmp;
417 if (d->lengthFix) {
418 tmp = length;
419 } else {
420 tmp = width() - length;
421 }
422 if (tmp != d->endOffset_length) {
423 d->endOffset_length = tmp;
425 }
426}
427
428int KRuler::length() const
429{
430 if (d->lengthFix) {
431 return d->endOffset_length;
432 }
433 return (width() - d->endOffset_length);
434}
435
437{
438 d->lengthFix = fix;
439}
440
441bool KRuler::lengthFixed() const
442{
443 return d->lengthFix;
444}
445
446void KRuler::setOffset(int _offset)
447{
448 // debug("set offset %i", _offset);
449 if (d->offset != _offset) {
450 d->offset = _offset;
452 }
453}
454
455int KRuler::offset() const
456{
457 return d->offset;
458}
459
460int KRuler::endOffset() const
461{
462 if (d->lengthFix) {
463 return (width() - d->endOffset_length);
464 }
465 return d->endOffset_length;
466}
467
468void KRuler::slideUp(int count)
469{
470 if (count) {
471 d->offset += count;
473 }
474}
475
476void KRuler::slideDown(int count)
477{
478 if (count) {
479 d->offset -= count;
481 }
482}
483
484void KRuler::slotNewValue(int _value)
485{
486 int oldvalue = value();
487 if (oldvalue == _value) {
488 return;
489 }
490 // setValue(_value);
491 setValue(_value);
492 if (value() == oldvalue) {
493 return;
494 }
495 // get the rectangular of the old and the new ruler pointer
496 // and repaint only him
497 if (d->dir == Qt::Horizontal) {
498 QRect oldrec(-5 + oldvalue, 10, 11, 6);
499 QRect newrec(-5 + _value, 10, 11, 6);
500 repaint(oldrec.united(newrec));
501 } else {
502 QRect oldrec(10, -5 + oldvalue, 6, 11);
503 QRect newrec(10, -5 + _value, 6, 11);
504 repaint(oldrec.united(newrec));
505 }
506}
507
508void KRuler::slotNewOffset(int _offset)
509{
510 if (d->offset != _offset) {
511 // setOffset(_offset);
512 d->offset = _offset;
514 }
515}
516
517void KRuler::slotEndOffset(int offset)
518{
519 int tmp;
520 if (d->lengthFix) {
521 tmp = width() - offset;
522 } else {
523 tmp = offset;
524 }
525 if (d->endOffset_length != tmp) {
526 d->endOffset_length = tmp;
528 }
529}
530
531void KRuler::paintEvent(QPaintEvent * /*e*/)
532{
533 // debug ("KRuler::drawContents, %s",(horizontal==dir)?"horizontal":"vertical");
534
535 QStylePainter p(this);
536#ifdef PROFILING
537 QTime time;
538 time.start();
539 for (int profile = 0; profile < 10; profile++) {
540#endif
541
542 int value = this->value();
543 int minval = minimum();
544 int maxval;
545 if (d->dir == Qt::Horizontal) {
546 maxval = maximum() + d->offset - (d->lengthFix ? (height() - d->endOffset_length) : d->endOffset_length);
547 } else {
548 maxval = maximum() + d->offset - (d->lengthFix ? (width() - d->endOffset_length) : d->endOffset_length);
549 }
550 // ioffsetval = value-offset;
551 // pixelpm = (int)ppm;
552 // left = clip.left(),
553 // right = clip.right();
554 double f;
555 double fend;
556 double offsetmin = (double)(minval - d->offset);
557 double offsetmax = (double)(maxval - d->offset);
558 double fontOffset = (((double)minval) > offsetmin) ? (double)minval : offsetmin;
559
560 // draw labels
561 QFont font = p.font();
562 font.setPointSize(LABEL_SIZE);
563 p.setFont(font);
564 // draw littlemarklabel
565
566 // draw mediummarklabel
567
568 // draw bigmarklabel
569
570 // draw endlabel
571 if (d->showEndL) {
572 if (d->dir == Qt::Horizontal) {
573 p.translate(fontOffset, 0);
574 p.drawText(END_LABEL_X, END_LABEL_Y, d->endlabel);
575 } else { // rotate text +pi/2 and move down a bit
576 // QFontMetrics fm(font);
577#ifdef KRULER_ROTATE_TEST
578 p.rotate(-90.0 + rotate);
579 p.translate(-8.0 - fontOffset - d->fontWidth + xtrans, ytrans);
580#else
581 p.rotate(-90.0);
582 p.translate(-8.0 - fontOffset - d->fontWidth, 0.0);
583#endif
584 p.drawText(END_LABEL_X, END_LABEL_Y, d->endlabel);
585 }
586 p.resetTransform();
587 }
588
589 // draw the tiny marks
590 if (d->showtm) {
591 fend = d->ppm * d->tmDist;
592 for (f = offsetmin; f < offsetmax; f += fend) {
593 if (d->dir == Qt::Horizontal) {
594 p.drawLine((int)f, BASE_MARK_X1, (int)f, BASE_MARK_X2);
595 } else {
596 p.drawLine(BASE_MARK_X1, (int)f, BASE_MARK_X2, (int)f);
597 }
598 }
599 }
600 if (d->showlm) {
601 // draw the little marks
602 fend = d->ppm * d->lmDist;
603 for (f = offsetmin; f < offsetmax; f += fend) {
604 if (d->dir == Qt::Horizontal) {
605 p.drawLine((int)f, LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2);
606 } else {
607 p.drawLine(LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2, (int)f);
608 }
609 }
610 }
611 if (d->showmm) {
612 // draw medium marks
613 fend = d->ppm * d->mmDist;
614 for (f = offsetmin; f < offsetmax; f += fend) {
615 if (d->dir == Qt::Horizontal) {
616 p.drawLine((int)f, MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2);
617 } else {
618 p.drawLine(MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2, (int)f);
619 }
620 }
621 }
622 if (d->showbm) {
623 // draw big marks
624 fend = d->ppm * d->bmDist;
625 for (f = offsetmin; f < offsetmax; f += fend) {
626 if (d->dir == Qt::Horizontal) {
627 p.drawLine((int)f, BIG_MARK_X1, (int)f, BIG_MARK_X2);
628 } else {
629 p.drawLine(BIG_MARK_X1, (int)f, BIG_MARK_X2, (int)f);
630 }
631 }
632 }
633 if (d->showem) {
634 // draw end marks
635 if (d->dir == Qt::Horizontal) {
636 p.drawLine(minval - d->offset, END_MARK_X1, minval - d->offset, END_MARK_X2);
637 p.drawLine(maxval - d->offset, END_MARK_X1, maxval - d->offset, END_MARK_X2);
638 } else {
639 p.drawLine(END_MARK_X1, minval - d->offset, END_MARK_X2, minval - d->offset);
640 p.drawLine(END_MARK_X1, maxval - d->offset, END_MARK_X2, maxval - d->offset);
641 }
642 }
643
644 // draw pointer
645 if (d->showpointer) {
646 QPolygon pa(4);
647 if (d->dir == Qt::Horizontal) {
648 pa.setPoints(3, value - 5, 10, value + 5, 10, value /*+0*/, 15);
649 } else {
650 pa.setPoints(3, 10, value - 5, 10, value + 5, 15, value /*+0*/);
651 }
652 p.setBrush(p.background().color());
653 p.drawPolygon(pa);
654 }
655
656#ifdef PROFILING
657 }
658 int elapsed = time.elapsed();
659 debug("paint time %i", elapsed);
660#endif
661}
662
663#include "moc_kruler.cpp"
void setMediumMarkDistance(int)
Sets the distance between medium marks.
Definition kruler.cpp:190
void slotNewOffset(int)
Sets the ruler marks to a new position.
Definition kruler.cpp:508
void setPixelPerMark(double rate)
Sets the number of pixels between two base marks.
Definition kruler.cpp:402
void setShowEndLabel(bool)
Show/hide number values of the end marks.
Definition kruler.cpp:294
KRuler(QWidget *parent=nullptr)
Constructs a horizontal ruler.
Definition kruler.cpp:98
void setLittleMarkDistance(int)
Sets the distance between little marks.
Definition kruler.cpp:177
void setShowBigMarks(bool)
Shows/hides big marks.
Definition kruler.cpp:255
void setShowTinyMarks(bool)
Shows/hides tiny marks.
Definition kruler.cpp:216
void slideUp(int count=1)
Sets the number of pixels by which the ruler may slide up or left.
Definition kruler.cpp:468
void setRulerMetricStyle(KRuler::MetricStyle)
Sets up the necessary tasks for the provided styles.
Definition kruler.cpp:326
void setLengthFixed(bool fix)
Locks the length of the ruler, i.e.
Definition kruler.cpp:436
void setEndLabel(const QString &)
Sets the label this is drawn at the beginning of the visible part of the ruler to label.
Definition kruler.cpp:307
void setOffset(int offset)
Sets the ruler slide offset.
Definition kruler.cpp:446
~KRuler() override
Destructor.
void slideDown(int count=1)
Sets the number of pixels by which the ruler may slide down or right.
Definition kruler.cpp:476
void setShowEndMarks(bool)
Shows/hides end marks.
Definition kruler.cpp:268
void setBigMarkDistance(int)
Sets distance between big marks.
Definition kruler.cpp:203
void setTinyMarkDistance(int)
Sets the distance between tiny marks.
Definition kruler.cpp:164
void slotNewValue(int)
Sets the pointer to a new position.
Definition kruler.cpp:484
void setShowPointer(bool)
Shows/hides the pointer.
Definition kruler.cpp:281
void setShowLittleMarks(bool)
Shows/hides little marks.
Definition kruler.cpp:229
void setLength(int)
Sets the length of the ruler, i.e.
Definition kruler.cpp:414
MetricStyle
The types of units used.
Definition kruler.h:77
void setShowMediumMarks(bool)
Shows/hides medium marks.
Definition kruler.cpp:242
void setPageStep(int)
void setRange(int min, int max)
void setValue(int)
void setPointSize(int pointSize)
int horizontalAdvance(QChar ch) const const
QRect united(const QRect &rectangle) const const
Orientation
typedef WindowFlags
QRect contentsRect() const const
void repaint()
void setFixedHeight(int h)
void setFixedWidth(int w)
void show()
QStyle * style() const const
void update()
void setWindowFlags(Qt::WindowFlags type)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:59:27 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.