1 /************************************************************************
3 * Copyright 2010-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 "QcRangeSlider.h"
23 #include "../QcWidgetFactory.h"
24 #include "../style/routines.hpp"
27 #include <QMouseEvent>
28 #include <QApplication>
33 QC_DECLARE_QWIDGET_FACTORY(QcRangeSlider
);
35 QcRangeSlider::QcRangeSlider() :
36 QtCollider::Style::Client(this),
42 setFocusPolicy( Qt::StrongFocus
);
43 setOrientation( Qt::Vertical
);
46 void QcRangeSlider::setOrientation( Qt::Orientation o
)
50 if( _ort
== Qt::Horizontal
) {
51 setSizePolicy( QSizePolicy::Expanding
, QSizePolicy::Fixed
);
54 setSizePolicy( QSizePolicy::Fixed
, QSizePolicy::Expanding
);
61 void QcRangeSlider::setLoValue( double val
)
63 val
= qMax( 0.0, qMin( 1.0, val
) );
74 void QcRangeSlider::setHiValue( double val
)
76 val
= qMax( 0.0, qMin( 1.0, val
) );
87 void QcRangeSlider::setRange( double val
, double range
)
89 range
= qBound( 0.0, range
, 1.0 );
90 _lo
= qBound( 0.0, val
, 1.0 - range
);
95 QSize
QcRangeSlider::sizeHint() const
97 return ( _ort
== Qt::Horizontal
? QSize( 150, 20 ) : QSize( 20, 150 ) );
100 QSize
QcRangeSlider::minimumSizeHint() const
102 return ( _ort
== Qt::Horizontal
? QSize( 30, 20 ) : QSize( 20, 30 ) );
105 void QcRangeSlider::increment( double factor
)
107 moveBy( factor
* _step
);
110 void QcRangeSlider::decrement( double factor
)
112 moveBy( -factor
* _step
);
115 void QcRangeSlider::increment()
122 void QcRangeSlider::decrement()
129 QRect
QcRangeSlider::thumbRect()
131 using namespace QtCollider::Style
;
132 QRect
contRect( sunkenContentsRect(rect()) );
134 if( _ort
== Qt::Horizontal
) {
135 double valRange
= contRect
.width() - hnd2
;
136 double left
= _lo
* valRange
;
137 double right
= _hi
* valRange
; right
+= hnd2
;
138 return QRect( left
+ contRect
.x(), contRect
.y(), right
- left
, contRect
.height() );
141 double valRange
= contRect
.height() - hnd2
;
142 int up
= (1.0 - _hi
) * valRange
;
143 int down
= (1.0 - _lo
) * valRange
; down
+= hnd2
;
144 return QRect( contRect
.x(), contRect
.y() + up
, contRect
.width(), down
- up
);
148 double QcRangeSlider::valueFromPos( const QPoint
& pos
)
150 using namespace QtCollider::Style
;
152 bool horiz
= _ort
== Qt::Horizontal
;
154 QSize margins
= horiz
? QSize(HND
*2, 0) : QSize(0, HND
*2);
155 QRect valBounds
= marginsRect( sunkenContentsRect(rect()), margins
);
157 return horiz
? xValue( pos
.x(), valBounds
) : yValue( pos
.y(), valBounds
);
160 void QcRangeSlider::moveBy( double dif
)
162 if( _lo
+ dif
< 0.0 ) {
166 else if( _hi
+ dif
> 1.0 ) {
177 void QcRangeSlider::mouseMoveEvent ( QMouseEvent
* e
)
179 using namespace QtCollider::Style
;
181 if( !e
->buttons() ) return;
183 if( mouseMode
== SetHi
|| mouseMode
== SetLo
)
185 double val
= valueFromPos( e
->pos() );
186 if( mouseMode
== SetLo
) {
187 if( val
> _hi
) mouseMode
= SetHi
;
190 else if( mouseMode
== SetHi
) {
191 if( val
< _lo
) mouseMode
= SetLo
;
195 else if( mouseMode
!= None
)
197 QPoint pt
= e
->pos() - dragOrigin
;
198 QRect
contRect( sunkenContentsRect(rect()) );
201 if( _ort
== Qt::Horizontal
) {
202 double range
= contRect
.width() - HND
*2;
203 dif
= range
> 0 ? pt
.x() / range
: 0.0;
206 double range
= contRect
.height() - HND
*2;
207 dif
= range
> 0 ? - pt
.y() / range
: 0.0;
211 switch( mouseMode
) {
213 setRange( dragVal
+ dif
, dragRange
); break;
215 setHiValue( qMax(dragVal
+ dif
, (double)_lo
) ); break;
217 setLoValue( qMin(dragVal
+ dif
, (double)_hi
) ); break;
227 void QcRangeSlider::mousePressEvent ( QMouseEvent
* e
)
229 using namespace QtCollider::Style
;
231 if( e
->modifiers() & Qt::ShiftModifier
) {
232 double center
= (_hi
+ _lo
) * 0.5;
233 double val
= valueFromPos( e
->pos() );
245 QRect
thumb( thumbRect() );
249 if( _ort
== Qt::Horizontal
) {
251 pos
= e
->pos().x() - thumb
.left();
254 len
= thumb
.height();
255 pos
= thumb
.top() + len
- e
->pos().y();
258 if( pos
< 0 || pos
> len
) return;
260 dragOrigin
= e
->pos();
266 else if( pos
>= len
- HND
) {
273 dragRange
= _hi
- _lo
;
280 void QcRangeSlider::mouseReleaseEvent ( QMouseEvent
* e
)
286 void QcRangeSlider::keyPressEvent ( QKeyEvent
*e
)
296 _lo
= 0.0; _hi
= 1.0; update(); break;
298 _lo
= 0.0; _hi
= 0.0; update(); break;
300 _lo
= 1.0; _hi
= 1.0; update(); break;
302 _lo
= 0.5; _hi
= 0.5; update(); break;
304 return QWidget::keyPressEvent( e
);
309 inline void drawMarker( QPainter
*p
, const QColor
&color
,
310 Qt::Orientation ort
, bool first
, const QPoint
& pt
, int len
)
313 p
->setRenderHint( QPainter::Antialiasing
, false );
317 bool vert
= ort
== Qt::Vertical
;
320 pen
.setWidth(1); p
->setPen(pen
);
321 p
->drawPoint( QPoint( pt
.x() + len
* 0.5, first
? pt
.y() - 5 : pt
.y() + 5 ) );
323 pen
.setWidth(2); p
->setPen(pen
);
324 QLine
line( pt
.x() + 1, pt
.y(), pt
.x() + len
- 1, pt
.y() );
327 pen
.setWidth(1); p
->setPen(pen
);
328 p
->drawPoint( QPoint( first
? pt
.x() - 5 : pt
.x() + 5, pt
.y() + len
* 0.5 ) );
330 pen
.setWidth(2); p
->setPen(pen
);
331 QLine
line( pt
.x(), pt
.y() + 1, pt
.x(), pt
.y() + len
- 1 );
337 void QcRangeSlider::paintEvent ( QPaintEvent
*e
)
339 using namespace QtCollider::Style
;
340 using QtCollider::Style::RoundRect
;
345 p
.setRenderHint( QPainter::Antialiasing
, true );
347 const QPalette
& plt
= palette();
348 const QColor
& knobClr
= knobColor();
350 RoundRect
frame(rect(), 2);
351 drawSunken( &p
, plt
, frame
, grooveColor(), hasFocus() ? focusColor() : QColor() );
353 QRect
contRect( sunkenContentsRect(rect()) );
358 bool horiz
= _ort
== Qt::Horizontal
;
361 double valRange
= contRect
.width() - HND2
;
362 int lo
= _lo
* valRange
;
363 int hi
= _hi
* valRange
;
364 valRect
= QRect( lo
+ HND
+ contRect
.x(), contRect
.y(), hi
- lo
, contRect
.height() );
365 hndRect
= valRect
.adjusted( -HND
, 0, HND
, 0 );
368 double valRange
= contRect
.height() - HND2
;
369 int hi
= _hi
* valRange
;
370 int lo
= _lo
* valRange
;
371 valRect
= QRect( contRect
.x(), contRect
.y() + contRect
.height() - hi
- HND
, contRect
.width(), hi
- lo
);
372 hndRect
= valRect
.adjusted( 0, -HND
, 0, HND
);
377 RoundRect
handle(hndRect
, 2);
378 drawRaised( &p
, plt
, handle
, plt
.color(QPalette::Button
).lighter(105) );
383 int mark_len
= hndRect
.height() - 4;
385 QPoint
pt( hndRect
.left() + HND
, hndRect
.top() + 2 );
386 drawMarker( &p
, knobClr
, _ort
, true, pt
, mark_len
);
388 pt
.setX( hndRect
.right() - HND
+ 1 );
389 drawMarker( &p
, knobClr
, _ort
, false, pt
, mark_len
);
391 int mark_len
= hndRect
.width() - 4;
392 QPoint
pt( hndRect
.left() + 2, hndRect
.top() + HND
);
393 drawMarker( &p
, knobClr
, _ort
, true, pt
, mark_len
);
395 pt
.setY( hndRect
.bottom() - HND
+ 1 );
396 drawMarker( &p
, knobClr
, _ort
, false, pt
, mark_len
);
401 if( horiz
? valRect
.width() > 2 : valRect
.height() > 2 ) {
402 p
.setRenderHint( QPainter::Antialiasing
, false );
410 p
.drawRect(valRect
.adjusted( 1, 2, -1, -2 ));
412 p
.drawRect(valRect
.adjusted( 2, 1, -2, -1 ));