class library: PriorityQueue - implement removeValue, hide array
[supercollider.git] / QtCollider / widgets / QcRangeSlider.cpp
bloba248ce298f066f00b0d798369be7cebee6e04327
1 /************************************************************************
3 * Copyright 2010 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 "QcRangeSlider.h"
23 #include "../QcWidgetFactory.h"
25 #include <QKeyEvent>
26 #include <QMouseEvent>
27 #include <QApplication>
28 #include <QPainter>
30 static QcWidgetFactory<QcRangeSlider> factory;
32 QcRangeSlider::QcRangeSlider() :
33 _lo( 0.f ),
34 _hi( 1.f ),
35 _step( 0.01f ),
36 mouseMode( None )
38 setFocusPolicy( Qt::StrongFocus );
39 setOrientation( Qt::Vertical );
42 void QcRangeSlider::setOrientation( Qt::Orientation o )
44 _ort = o;
46 if( _ort == Qt::Horizontal ) {
47 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
49 else {
50 setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
53 updateGeometry();
54 update();
57 void QcRangeSlider::setLoValue( float val )
59 val = qMax( 0.f, qMin( 1.f, val ) );
60 if( val <= _hi ) {
61 _lo = val;
63 else {
64 _lo = _hi;
65 _hi = val;
67 update();
70 void QcRangeSlider::setHiValue( float val )
72 val = qMax( 0.f, qMin( 1.f, val ) );
73 if( val >= _lo ) {
74 _hi = val;
76 else {
77 _hi = _lo;
78 _lo = val;
80 update();
83 QSize QcRangeSlider::sizeHint() const
85 return ( _ort == Qt::Horizontal ? QSize( 100, 20 ) : QSize( 20, 100 ) );
88 QSize QcRangeSlider::minimumSizeHint() const
90 return ( _ort == Qt::Horizontal ? QSize( 30, 10 ) : QSize( 10, 30 ) );
93 void QcRangeSlider::increment( double factor )
95 moveBy( factor * _step );
98 void QcRangeSlider::decrement( double factor )
100 moveBy( -factor * _step );
103 void QcRangeSlider::increment()
105 float step = _step;
106 modifyStep( &step );
107 moveBy( step );
110 void QcRangeSlider::decrement()
112 float step = _step;
113 modifyStep( &step );
114 moveBy( -step );
117 QRect QcRangeSlider::thumbRect()
119 QRect r;
121 if( _ort == Qt::Horizontal ) {
122 r.setX( _lo * width() );
123 r.setRight( _hi * width() );
124 r.setHeight( height() );
126 else {
127 r.setY( (1.f - _hi) * height() );
128 r.setBottom( (1.f - _lo ) * height() );
129 r.setWidth( width() );
132 return r;
135 float QcRangeSlider::valueFromPos( const QPoint& pos )
137 float val = _ort == Qt::Horizontal ?
138 (float)pos.x() / width() :
139 1.f - ((float)pos.y() / height());
140 return val;
143 void QcRangeSlider::moveBy( float dif )
145 if( _lo + dif < 0.f ) {
146 _hi += 0.f - _lo;
147 _lo = 0.f;
149 else if( _hi + dif > 1.f ) {
150 _lo += 1.f - _hi;
151 _hi = 1.f;
153 else {
154 _lo += dif;
155 _hi += dif;
157 update();
160 void QcRangeSlider::mouseMoveEvent ( QMouseEvent * e )
162 if( mouseMode == Drag ) {
163 QPoint pt = e->pos() + dragOffset;
164 float dif;
165 if( _ort == Qt::Horizontal )
166 dif = ( (float)pt.x() / width() ) - _lo;
167 else
168 dif = 1.f - ( (float)pt.y() / height() ) - _hi;
170 if( dif == 0.f ) return;
172 moveBy( dif );
174 else {
175 float val = valueFromPos( e->pos() );
176 if( mouseMode == SetLo ) {
177 if( val > _hi ) mouseMode = SetHi;
178 setLoValue( val );
180 else if( mouseMode == SetHi ) {
181 if( val < _lo ) mouseMode = SetLo;
182 setHiValue( val );
186 Q_EMIT( action() );
189 void QcRangeSlider::mousePressEvent ( QMouseEvent * e )
191 QRect r = thumbRect();
192 if( e->modifiers() & Qt::ShiftModifier ) {
193 float center = (_hi + _lo) * 0.5;
194 float val = valueFromPos( e->pos() );
195 if( val < center ) {
196 mouseMode = SetLo;
197 setLoValue( val );
199 else {
200 mouseMode = SetHi;
201 setHiValue( val );
203 Q_EMIT( action() );
205 else if( r.contains( e->pos() ) ){
206 mouseMode = Drag;
207 dragOffset = r.topLeft() - e->pos();
209 else {
210 _lo = _hi = valueFromPos( e->pos() );
211 update();
212 mouseMode = SetHi;
213 Q_EMIT( action() );
217 void QcRangeSlider::mouseReleaseEvent ( QMouseEvent * e )
219 Q_UNUSED(e);
220 mouseMode = None;
223 void QcRangeSlider::keyPressEvent ( QKeyEvent *e )
225 switch( e->key() ) {
226 case Qt::Key_Up:
227 case Qt::Key_Right:
228 increment(); break;
229 case Qt::Key_Down:
230 case Qt::Key_Left:
231 decrement(); break;
232 case Qt::Key_A:
233 _lo = 0.f; _hi = 1.f; update(); break;
234 case Qt::Key_N:
235 _lo = 0.f; _hi = 0.f; update(); break;
236 case Qt::Key_X:
237 _lo = 1.f; _hi = 1.f; update(); break;
238 case Qt::Key_C:
239 _lo = 0.5; _hi = 0.5; update(); break;
240 default:
241 return QWidget::keyPressEvent( e );
243 Q_EMIT( action() );
246 void QcRangeSlider::paintEvent ( QPaintEvent *e )
248 Q_UNUSED(e);
249 QPainter p;
250 p.begin(this);
252 QPalette plt = palette();
254 p.setBrush( plt.color( QPalette::Base ) );
255 p.setPen( plt.color( QPalette::Mid ) );
256 p.drawRect( rect().adjusted(0,0,-1,-1) );
258 p.fillRect( thumbRect(), plt.color( QPalette::Text ) );
259 p.end();