Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAnimCurvesValuesHeader.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Jouni Pentikäinen <joupent@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <math.h>
10#include "kis_debug.h"
12
13#include <QPaintEvent>
14#include <QPainter>
15#include <QtMath>
16#include <QApplication>
17#include <QStyle>
18
20{
22 : valueOffset(-1.f)
23 , scale(1.f)
24 , mouseTracking(false)
25 , mouseLastPos(QPoint(0,0))
26 {}
27
29 qreal scale;
30
33
34 QScopedPointer<KisCustomModifiersCatcher> modifiersCatcher;
35};
36
38 : QHeaderView(Qt::Vertical, parent)
39 , m_d(new Private())
40{
41 m_d->modifiersCatcher.reset(new KisCustomModifiersCatcher(parent));
42 m_d->modifiersCatcher->addModifier("pan-zoom", Qt::Key_Space);
43}
44
47
49{
50 const qreal minimumScale = 0.001f;
51 m_d->scale = qMax(scale, minimumScale);
52 viewport()->update();
53 Q_EMIT scaleChanged(m_d->scale);
54}
55
57{
58 return m_d->scale;
59}
60
62{
63 m_d->valueOffset = offset;
64 viewport()->update();
65 valueOffsetChanged(m_d->valueOffset);
66}
67
69{
70 return m_d->valueOffset;
71}
72
74{
75 const int MIN_PIXEL_PER_STEP = UNIT_SIZE_PIXELS - 8;
76 const int MAX_PIXEL_PER_STEP = UNIT_SIZE_PIXELS * 10;
77
78 const qreal valueSpan = visibleValueDifference();
79 qreal step = roundDownPower10(valueSpan * 5);
80
81 if (pixelsPerStep(step) < MIN_PIXEL_PER_STEP) {
82 step *= 10;
83 } else if (pixelsPerStep(step) >= MAX_PIXEL_PER_STEP) {
84 step /= 10;
85 }
86
87 return step;
88}
89
91{
92 return rect().height() - (value - valueOffset()) * scaledUnit();
93}
94
96{
97 return (position - rect().height()) / (scaledUnit() * -1) + valueOffset();
98}
99
104
106{
107 const qreal range = (max-min);
108 const qreal rangePixels = range * UNIT_SIZE_PIXELS;
109 setValueOffset(min);
110 setScale(rect().height() / rangePixels);
111}
112
114{
115 QPainter painter(viewport());
116
117 // Colors.
118 const QColor textColor = qApp->palette().color(QPalette::ButtonText);
119 const QColor majorNotchColor = QColor(textColor.red(), textColor.green(), textColor.blue(), 192);
120 const QColor minorNotchColor = QColor(textColor.red(), textColor.green(), textColor.blue(), 128);
121 const QColor zeroColor = qApp->palette().highlight().color();
122
123 const qreal valueStep = step();
124 const qreal firstVisibleValue = firstVisibleStep();
125
126 const int visibleSteps = visibleValueDifference() / valueStep;
127 const int minorNotches = pixelsPerStep(valueStep) >= (UNIT_SIZE_PIXELS * 2) ? 9 : 3;
128 const int majorNotchLength = rect().width();
129 const int minorNotchLength = 12;
130
131 // Draw notch at each major step.
132 //const qreal upperValueThreshold = firstVisibleValue + (visibleSteps + 2) * valueStep;
133 for (int major = 0; major <= visibleSteps + 1; major++) {
134 const qreal value = firstVisibleValue + valueStep * major;
135
136 const QPoint majorRight = QPoint(majorNotchLength, valueToWidget(value));
137 const QPoint majorLeft = QPoint(0, valueToWidget(value));
138
139 painter.setPen(value != 0 ? majorNotchColor : zeroColor);
140 painter.drawLine(majorLeft, majorRight);
141
142 // Draw interior notches at minor substeps.
143 const qreal pixelsPerMinorNotch = pixelsPerStep(valueStep) / (minorNotches + 1);
144 for (int minor = 0; minor < minorNotches; minor++) {
145 const QPoint minorRight = QPoint(rect().width(), majorRight.y() + pixelsPerMinorNotch * (minor + 1));
146 const QPoint minorLeft = QPoint(minorRight.x() - minorNotchLength, minorRight.y());
147
148 painter.setPen(minorNotchColor);
149 painter.drawLine(minorLeft, minorRight);
150 }
151
152 { // Draw label.
153 const int padding = 4;
154
155 const QString label = QString::number(value, 'f', valueStep < 1 ? 2 : 0);
156 const QRect textRect = QRect(0, majorLeft.y(), rect().width() - minorNotchLength - padding, 32);
157
158 painter.setPen(value != 0 ? textColor : zeroColor);
159 painter.drawText(textRect, label, QTextOption(Qt::AlignRight));
160 }
161 }
162}
163
164void KisAnimCurvesValuesHeader::mouseMoveEvent(QMouseEvent* mouseEvent) {
165 if (mouseEvent->buttons() & Qt::LeftButton) {
166 if (m_d->mouseTracking) {
167 const qreal oldValue = orientation() == Qt::Vertical ? m_d->mouseLastPos.y() : m_d->mouseLastPos.x();
168 const qreal newValue = orientation() == Qt::Vertical ? mouseEvent->pos().y() : mouseEvent->pos().x();
169 if (m_d->modifiersCatcher->modifierPressed("pan-zoom")) {
170 const qreal delta = (newValue - oldValue);
171 setValueOffset(valueOffset() + delta * step() / 64);
172 } else {
173 const qreal delta = -1 * (newValue - oldValue) / 16;
174 setScale(scale() + delta / step());
175 }
176 m_d->mouseLastPos = mouseEvent->pos();
177 }
178 } else {
179 if (m_d->mouseTracking == true) {
180 m_d->mouseTracking = false;
181 }
182 }
183
184 QHeaderView::mouseMoveEvent(mouseEvent);
185}
186
187void KisAnimCurvesValuesHeader::mousePressEvent(QMouseEvent* mouseEvent) {
188 if (mouseEvent->buttons() & Qt::LeftButton) {
189 m_d->mouseTracking = true;
190 m_d->mouseLastPos = mouseEvent->pos();
191 }
192
193 QHeaderView::mousePressEvent(mouseEvent);
194}
float value(const T *src, size_t ch)
const int UNIT_SIZE_PIXELS
virtual void mouseMoveEvent(QMouseEvent *mouseEvent) override
qreal roundDownPower10(qreal value) const
qreal widgetToValue(qreal position) const
virtual void mousePressEvent(QMouseEvent *mouseEvent) override
qreal valueToWidget(qreal value) const
valueToWidgetOffset
qreal pixelsPerStep(const qreal step) const
void paintEvent(QPaintEvent *e) override
void valueOffsetChanged(qreal offset)
void scaleChanged(qreal scale)
const QScopedPointer< Private > m_d
void setValueOffset(qreal valueOffset)
void zoomToFitRange(qreal min, qreal max)
The KisCustomModifiersCatcher class is a special utility class that tracks custom modifiers pressed....
QScopedPointer< KisCustomModifiersCatcher > modifiersCatcher