]> sigrok.org Git - pulseview.git/blame - pv/view/ruler.cpp
CursorHeader: Make the size dependend on the used font.
[pulseview.git] / pv / view / ruler.cpp
CommitLineData
ccdd3ef5 1/*
b3f22de0 2 * This file is part of the PulseView project.
ccdd3ef5
JH
3 *
4 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "ruler.h"
ca4ec3ea 22
ccdd3ef5 23#include "view.h"
f0c9f81c 24#include "pv/util.h"
ccdd3ef5 25
cef18fc6 26#include <extdef.h>
ccdd3ef5 27
819f4c25 28using namespace Qt;
f76af637 29
ccdd3ef5
JH
30namespace pv {
31namespace view {
32
a6c1726e 33const int Ruler::RulerHeight = 30;
ccdd3ef5
JH
34const int Ruler::MinorTickSubdivision = 4;
35const int Ruler::ScaleUnits[3] = {1, 2, 5};
36
b3a7c013
JH
37const int Ruler::HoverArrowSize = 5;
38
ccdd3ef5 39Ruler::Ruler(View &parent) :
84a0d458 40 MarginWidget(parent)
ccdd3ef5 41{
b3a7c013
JH
42 setMouseTracking(true);
43
44 connect(&_view, SIGNAL(hover_point_changed()),
45 this, SLOT(hover_point_changed()));
ccdd3ef5
JH
46}
47
a6c1726e
JH
48QSize Ruler::sizeHint() const
49{
50 return QSize(0, RulerHeight);
51}
52
e314eca4 53void Ruler::paintEvent(QPaintEvent*)
ccdd3ef5 54{
3f509c1f
JH
55 const double SpacingIncrement = 32.0f;
56 const double MinValueSpacing = 32.0f;
f260e3bf 57 const int ValueMargin = 3;
3f509c1f 58
ccdd3ef5 59 QPainter p(this);
ce6e73a8 60 p.setRenderHint(QPainter::Antialiasing);
ccdd3ef5 61
3f509c1f
JH
62 double min_width = SpacingIncrement, typical_width;
63 double tick_period;
64 unsigned int prefix;
ccdd3ef5 65
3f509c1f
JH
66 // Find tick spacing, and number formatting that does not cause
67 // value to collide.
68 do
69 {
70 const double min_period = _view.scale() * min_width;
ccdd3ef5 71
3f509c1f 72 const int order = (int)floorf(log10f(min_period));
4d3c4e34 73 const double order_decimal = pow(10.0, order);
ccdd3ef5 74
3f509c1f 75 unsigned int unit = 0;
ccdd3ef5 76
3f509c1f
JH
77 do
78 {
79 tick_period = order_decimal * ScaleUnits[unit++];
80 } while (tick_period < min_period && unit < countof(ScaleUnits));
ccdd3ef5 81
f0c9f81c 82 prefix = (order - pv::util::FirstSIPrefixPower) / 3;
3f509c1f
JH
83
84 typical_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
f0c9f81c 85 AlignLeft | AlignTop, pv::util::format_time(_view.offset(),
3a6fe081 86 prefix)).width() + MinValueSpacing;
3f509c1f
JH
87
88 min_width += SpacingIncrement;
89
90 } while(typical_width > tick_period / _view.scale());
1b5813fe 91
ccdd3ef5 92 const int text_height = p.boundingRect(0, 0, INT_MAX, INT_MAX,
3af62a24 93 AlignLeft | AlignTop, "8").height();
ccdd3ef5
JH
94
95 // Draw the tick marks
d2caed8d 96 p.setPen(palette().color(foregroundRole()));
ccdd3ef5
JH
97
98 const double minor_tick_period = tick_period / MinorTickSubdivision;
99 const double first_major_division =
100 floor(_view.offset() / tick_period);
101 const double first_minor_division =
102 ceil(_view.offset() / minor_tick_period);
103 const double t0 = first_major_division * tick_period;
104
105 int division = (int)round(first_minor_division -
64b678ba 106 first_major_division * MinorTickSubdivision) - 1;
f260e3bf
JH
107
108 const int major_tick_y1 = text_height + ValueMargin * 2;
109 const int tick_y2 = height();
110 const int minor_tick_y1 = (major_tick_y1 + tick_y2) / 2;
111
64b678ba 112 double x;
ccdd3ef5 113
64b678ba
JH
114 do {
115 const double t = t0 + division * minor_tick_period;
116 x = (t - _view.offset()) / _view.scale();
ccdd3ef5 117
333d5bbc 118 if (division % MinorTickSubdivision == 0)
ccdd3ef5
JH
119 {
120 // Draw a major tick
f260e3bf
JH
121 p.drawText(x, ValueMargin, 0, text_height,
122 AlignCenter | AlignTop | TextDontClip,
f0c9f81c 123 pv::util::format_time(t, prefix));
f260e3bf
JH
124 p.drawLine(QPointF(x, major_tick_y1),
125 QPointF(x, tick_y2));
ccdd3ef5
JH
126 }
127 else
128 {
129 // Draw a minor tick
f260e3bf
JH
130 p.drawLine(QPointF(x, minor_tick_y1),
131 QPointF(x, tick_y2));
ccdd3ef5
JH
132 }
133
134 division++;
64b678ba
JH
135
136 } while (x < width());
ccdd3ef5 137
b3a7c013
JH
138 // Draw the hover mark
139 draw_hover_mark(p);
ca4ec3ea
JH
140}
141
b3a7c013
JH
142void Ruler::draw_hover_mark(QPainter &p)
143{
144 const int x = _view.hover_point().x();
333d5bbc 145
84a0d458 146 if (x == -1)
b3a7c013
JH
147 return;
148
149 p.setPen(QPen(Qt::NoPen));
ad1d8e2b 150 p.setBrush(QBrush(palette().color(foregroundRole())));
b3a7c013
JH
151
152 const int b = height() - 1;
153 const QPointF points[] = {
154 QPointF(x, b),
155 QPointF(x - HoverArrowSize, b - HoverArrowSize),
156 QPointF(x + HoverArrowSize, b - HoverArrowSize)
157 };
158 p.drawPolygon(points, countof(points));
159}
160
161void Ruler::hover_point_changed()
162{
163 update();
164}
165
ccdd3ef5
JH
166} // namespace view
167} // namespace pv