common: win32utils - compile fix
[supercollider.git] / QtCollider / widgets / QcKnob.cpp
blob8affc13fc49a6aedc67af42522cb5627717542e8
1 /************************************************************************
3 * Copyright 2011-2012 Jakob Leben (jakob.leben@gmail.com)
5 * This file is part of SuperCollider Qt GUI.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ************************************************************************/
22 #include "QcKnob.hpp"
23 #include "../QcWidgetFactory.h"
24 #include "../style/routines.hpp"
26 #include <QMouseEvent>
27 #include <QPainter>
29 using namespace QtCollider;
31 QC_DECLARE_QWIDGET_FACTORY(QcKnob);
33 QcKnob::QcKnob() :
34 Style::Client(this),
35 _value(0.f),
36 _mode(0),
37 _step(0.01),
38 _centered(false)
40 setFocusPolicy( Qt::StrongFocus );
41 setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
44 void QcKnob::setValue( double val )
46 _value = qBound( 0.0, val, 1.0 );
47 update();
50 void QcKnob::mousePressEvent( QMouseEvent *e )
52 if( _mode == 0 ) {
53 setValue( value( e->pos() ) );
54 Q_EMIT( action() );
56 _prevPos = e->pos();
59 void QcKnob::mouseMoveEvent( QMouseEvent *e )
61 if( _mode == 0 ) {
62 double val = value( e->pos() );
63 if( !(val < 0.0 && _value > 0.5) && !(val > 1.0 && _value < 0.5) )
64 setValue( value( e->pos() ) );
65 Q_EMIT( action() );
67 else {
68 int dif;
69 dif = _mode == 1 ?
70 e->pos().x() - _prevPos.x() :
71 _prevPos.y() - e->pos().y();
72 if( dif != 0 ) {
73 float step = _step;
74 modifyStep( &step );
75 setValue( _value + dif * step );
76 Q_EMIT( action() );
79 _prevPos = e->pos();
82 void QcKnob::paintEvent( QPaintEvent * )
84 using namespace QtCollider::Style;
85 using QtCollider::Style::Ellipse;
87 QPainter p(this);
88 p.setRenderHint( QPainter::Antialiasing, true );
90 const QPalette &plt( palette() );
91 QColor cGroove = plt.color( QPalette::Window ).lighter( 115 );
92 QColor cVal = plt.color( QPalette::ButtonText );
94 QRect bounds( rect() );
95 int sz = qMin( bounds.width(), bounds.height() );
96 float sz_2 = sz * 0.5f;
97 QPointF center = QRectF(bounds).center();
99 p.translate( center );
101 double rad = sz_2 * 0.75;
102 Ellipse shKnob(QRectF(-rad, -rad, rad*2, rad*2));
103 drawRaised( &p, plt, shKnob,
104 plt.color( QPalette::Button ).lighter(105),
105 hasFocus() ? focusColor() : QColor() );
107 p.scale( sz_2, sz_2 );
109 QPen pen;
110 pen.setWidthF( 0.1 );
111 p.setBrush( Qt::NoBrush );
113 QRectF r( -0.95, -0.95, 1.9, 1.9 );
115 p.save(); // groove & value indicator rotation
117 double range = 300.0;
119 p.rotate( - 90 - range * 0.5 );
121 double valAng = - _value * range;
123 if( _centered ) {
124 double min = qMin( valAng, -range * 0.5 );
125 double max = qMax( valAng, -range * 0.5 );
127 pen.setColor( cGroove );
128 p.setPen( pen );
129 p.drawArc( r, -range * 16.f, (min + range) * 16.f );
130 p.drawArc( r, max * 16.f, -max * 16.f );
132 pen.setColor( plt.color(QPalette::WindowText) );
133 p.setPen( pen );
134 p.drawArc( r, min * 16.f, (max - min) * 16.f );
136 else {
137 pen.setColor( cGroove );
138 p.setPen( pen );
139 p.drawArc( r, -range * 16.f, (valAng + range) * 16.f );
141 pen.setColor( plt.color(QPalette::WindowText) );
142 p.setPen( pen );
143 p.drawArc( r, valAng * 16.f, -valAng * 16.f );
146 p.restore(); // groove & value indicator rotation
148 p.rotate( (360.0 - range) * 0.5 - valAng );
150 QLineF line( 0, 0.05, 0, 0.55 );
151 pen.setColor(cVal);
152 pen.setWidthF( 0.15 );
153 pen.setCapStyle( Qt::RoundCap );
154 p.setPen( pen );
155 p.drawLine( line );
158 double QcKnob::value( const QPoint &pt )
160 double angle = QLineF( rect().center(), pt ).angle();
162 if( angle > 270.0 ) angle -= 270.0;
163 else angle += 90;
164 return (330 - angle) / 300.0;