Loading...
Searching...
No Matches
Stepper.hpp
1#pragma once
2#include <score/model/Skin.hpp>
3
4#include <QPainter>
5#include <QRectF>
6
7#include <cmath>
8
9namespace score
10{
13struct Stepper
14{
15 static constexpr double width = 12.;
16
18 static bool visible(const QRectF& box) noexcept { return box.width() > 3. * width; }
19
20 static QRectF rect(const QRectF& box) noexcept
21 {
22 const double left = std::max(box.left(), box.right() - width);
23 return QRectF{QPointF{left, box.top()}, QPointF{box.right(), box.bottom()}};
24 }
25
27 static int stepAt(const QRectF& box, QPointF pos) noexcept
28 {
29 if(!visible(box))
30 return 0;
31 const QRectF r = rect(box);
32 if(!r.contains(pos))
33 return 0;
34 return pos.y() < r.center().y() ? +1 : -1;
35 }
36
38 static void paint(
39 QPainter& painter, const score::Skin& skin, const QRectF& box, int pressedStep)
40 {
41 const QRectF strip = rect(box);
42 const QRectF halves[2]
43 = {QRectF{strip.topLeft(), QSizeF{strip.width(), strip.height() / 2.}},
44 QRectF{
45 QPointF{strip.left(), strip.top() + strip.height() / 2.},
46 QSizeF{strip.width(), strip.height() / 2.}}};
47
48 // Half the glyph's arm length, so that + and - are the same width.
49 const double arm = 2.;
50 for(int i = 0; i < 2; i++)
51 {
52 const int step = i == 0 ? +1 : -1;
53 const QRectF& half = halves[i];
54
55 // A pressed half flashes in the text's orange, its glyph in the
56 // background colour.
57 const bool pressed = pressedStep == step;
58 if(pressed)
59 {
60 painter.setPen(skin.NoPen);
61 painter.setBrush(skin.Base4.main.brush);
62 painter.drawRect(half);
63 }
64
65 // Rounded: a one-pixel pen with antialiasing off needs a whole pixel,
66 // and the two glyphs have to line up with each other.
67 const QPointF c{std::round(half.center().x()), std::round(half.center().y())};
68 painter.setPen(pressed ? skin.Emphasis2.main.pen1 : skin.Base4.main.pen1);
69 painter.drawLine(QPointF{c.x() - arm, c.y()}, QPointF{c.x() + arm, c.y()});
70 if(step > 0)
71 painter.drawLine(QPointF{c.x(), c.y() - arm}, QPointF{c.x(), c.y() + arm});
72 }
73 }
74};
75}
Definition Skin.hpp:100
Base toolkit upon which the software is built.
Definition Application.cpp:108
Definition Stepper.hpp:14
static bool visible(const QRectF &box) noexcept
Shown only when the box leaves room for its content next to it.
Definition Stepper.hpp:18
static int stepAt(const QRectF &box, QPointF pos) noexcept
+1 for the upper half, -1 for the lower half, 0 outside the strip.
Definition Stepper.hpp:27
static void paint(QPainter &painter, const score::Skin &skin, const QRectF &box, int pressedStep)
pressedStep: the half held down (0 for none) while the pointer is on it.
Definition Stepper.hpp:38