MuseScore/awl/knob.cpp
2020-03-20 12:18:07 +02:00

274 lines
7.8 KiB
C++

//=============================================================================
// Awl
// Audio Widget Library
//
// Copyright (C) 2002-2006 by Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "knob.h"
namespace Awl {
//---------------------------------------------------------
// Knob
/// this is the AwlKnob constructor
//---------------------------------------------------------
Knob::Knob(QWidget* parent)
: AbstractSlider(parent)
{
_spanDegrees = 270;
_markSize = 6;
_border = 2;
points = 0;
startY = 0;
}
//---------------------------------------------------------
// Knob
//---------------------------------------------------------
Knob::~Knob()
{
if (points)
delete points;
}
//---------------------------------------------------------
// setText
//---------------------------------------------------------
void Knob::setText(const QString& s)
{
if (s != _text) {
_text = s;
update();
}
}
//---------------------------------------------------------
// setScaleSize
//! set the scale size in degrees
//
//! the scale size is the max moving angle measured
//! in degrees
//---------------------------------------------------------
void Knob::setSpanDegrees(double val)
{
if (val != _spanDegrees) {
_spanDegrees = val;
update();
}
}
//---------------------------------------------------------
// setMarkSize
//! set size of the center marker
//---------------------------------------------------------
void Knob::setMarkSize(int val)
{
if (val != _markSize) {
_markSize = val;
update();
}
}
//---------------------------------------------------------
// setBorder
//! set border size
//---------------------------------------------------------
void Knob::setBorder(int val)
{
if (val != _border) {
_border = val;
update();
}
}
//---------------------------------------------------------
// setKnobIcon
//---------------------------------------------------------
void Knob::setKnobIcon(const QIcon& icon)
{
_knobIcon = icon;
update();
}
//---------------------------------------------------------
// mousePressEvent
//---------------------------------------------------------
void Knob::mousePressEvent(QMouseEvent* ev)
{
startY = ev->y();
emit sliderPressed(__id);
if (_center) {
QRect r(points->boundingRect().toRect());
if (r.contains(ev->pos())) {
auto centerVal = (maxValue() - minValue()) / 2 + 0.5;
setValue(centerVal);
valueChange();
}
}
}
//---------------------------------------------------------
// mouseReleaseEvent
//---------------------------------------------------------
void Knob::mouseReleaseEvent(QMouseEvent*)
{
emit sliderReleased(__id);
}
//---------------------------------------------------------
// mouseMoveEvent
//---------------------------------------------------------
void Knob::mouseMoveEvent(QMouseEvent* ev)
{
int y = ev->y();
double delta = (maxValue() - minValue()) / 100.0f;
if (delta == 0)
delta = 1;
_value += (startY - y) * delta;
if (_value < minValue())
_value = _minValue;
else if (_value > maxValue())
_value = _maxValue;
startY = y;
valueChange();
}
//---------------------------------------------------------
// paintEvent
// r - phys coord system
//---------------------------------------------------------
void Knob::paintEvent(QPaintEvent* /*ev*/)
{
#if 0 // yet(?) unused
QRect rr(ev->rect());
#endif
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing, true);
int markSize2 = _markSize/2;
int emptyDegrees = 360 - _spanDegrees;
int w = width() - _scaleWidth - 2 * _border;
int h = height() - _scaleWidth/2 - 2 * _border;
int xoffset, yoffset;
if (_center)
h -= _markSize;
if (w > h) {
yoffset = 0;
xoffset = (w - h) / 2;
w = h;
}
else {
xoffset = 0;
yoffset = h - w; // top align
h = w;
}
int x = xoffset + _scaleWidth / 2 + _border;
int y = yoffset + _scaleWidth / 2 + _border + (_center ? _markSize+_scaleWidth/2 : 0);
QRectF dialArea(x, y, w, h);
QColor dialBgCol(isEnabled() ? _scaleColor : Qt::gray);
QColor dialCol(isEnabled() ? _scaleValueColor : Qt::lightGray);
//-----------------------------------------
// draw arc
//-----------------------------------------
double maxVal = maxValue();
double minVal = minValue();
double val = value();
double span = maxVal - minVal;
p.setPen(QPen(dialBgCol, _scaleWidth));
p.drawArc(dialArea, (90 + (_spanDegrees / 2)) * 16, -_spanDegrees * 16);
if (_center) {
double frac = (val - minVal) / span - 0.5;
p.setPen(QPen(dialCol, _scaleWidth));
p.drawArc(dialArea, 90 * 16, -frac * _spanDegrees * 16);
}
else {
double frac = (val - minVal) / span;
p.setPen(QPen(dialBgCol, _scaleWidth));
p.drawArc(dialArea, (90 + (_spanDegrees / 2)) * 16, frac * -_spanDegrees * 16);
}
//-----------------------------------------
// draw pointer
//-----------------------------------------
//knob image
if (!_knobIcon.isNull()) {
QRect r((int)dialArea.x(), (int)dialArea.y(), (int)dialArea.width(), (int)dialArea.height());
_knobIcon.paint(&p, r);
}
//indicator line
p.setPen(QPen(dialCol, _scaleWidth));
double r1 = double(_spanDegrees) * (_value - _minValue) / span + 90.0
+ double(emptyDegrees / 2);
r1 = r1 / 180.0 * M_PI; // convert to radians
int rd = w/2;
int x1 = x + rd;
int y1 = y + rd;
int x2 = x1 + lrint(cos(r1) * double(rd));
int y2 = y1 + lrint(sin(r1) * double(rd));
p.drawLine(x1, y1, x2, y2);
//-----------------------------------------
// draw center mark
//-----------------------------------------
p.setPen(QPen(dialCol, 0));
p.setBrush(dialCol);
if (_center) {
if (points)
delete points;
qreal x3 = dialArea.width() / 2 + dialArea.x();
qreal y3 = dialArea.y() - _markSize - _scaleWidth/2;
points = new QPainterPath(QPointF(x3 - markSize2, y3));
points->lineTo(x3 + markSize2, y3);
points->lineTo(x3, _markSize + y3);
points->closeSubpath();
p.drawPath(*points);
}
//-----------------------------------------
// draw text
//-----------------------------------------
if (!_text.isEmpty()) {
p.drawText(dialArea, Qt::AlignBottom | Qt::AlignHCenter, _text);
}
}
}