1 /*****************************************************************************
2 * seekstyle.cpp : Seek slider style
3 ****************************************************************************
4 * Copyright (C) 2011-2012 VLC authors and VideoLAN
6 * Authors: Ludovic Fauvet <etix@videolan.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #include "seekstyle.hpp"
24 #include "util/input_slider.hpp"
25 #include "adapters/seekpoints.hpp"
27 #include <QWindowsStyle>
28 #include <QStyleOptionSlider>
33 #define CHAPTERSSPOTSIZE 3
35 int SeekStyle::pixelMetric( PixelMetric metric, const QStyleOption *option, const QWidget *widget ) const
37 const QStyleOptionSlider *slider;
39 if ( metric == PM_SliderLength && ( slider = qstyleoption_cast<const QStyleOptionSlider *>( option ) ) )
40 return slider->rect.height();
42 return QWindowsStyle::pixelMetric( metric, option, widget );
45 void SeekStyle::drawComplexControl( ComplexControl cc, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget ) const
49 painter->setRenderHints( QPainter::Antialiasing );
51 if ( const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>( option ) )
53 const SeekSlider *seekSlider = qobject_cast<const SeekSlider*>( widget );
56 /* Get the needed subcontrols to draw the slider */
57 QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget);
58 QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget);
60 /* Adjust the size of the groove so the handle stays centered */
61 groove.adjust( handle.width() / 2, 0, -handle.width() / 2, 0 );
63 /* Reduce the height of the groove */
64 // Note: in the original 2.0.0 code, the groove had a height of 9px and to
65 // comply with the original style (but still allow the widget to expand) I
66 // had to remove 1 from the rect bottom.
67 groove.adjust( 0, (qreal)groove.height() / 3.7, 0, (qreal)-groove.height() / 3.7 - 1 );
69 if ( ( slider->subControls & SC_SliderGroove ) && groove.isValid() )
71 sliderPos = ( ( (qreal)groove.width() ) / (qreal)slider->maximum )
72 * (qreal)slider->sliderPosition;
74 /* set the background color and gradient */
75 QColor backgroundBase( slider->palette.window().color() );
76 QLinearGradient backgroundGradient( 0, 0, 0, slider->rect.height() );
77 backgroundGradient.setColorAt( 0.0, backgroundBase.darker( 140 ) );
78 backgroundGradient.setColorAt( 1.0, backgroundBase );
80 /* set the foreground color and gradient */
81 QColor foregroundBase( 50, 156, 255 );
82 QLinearGradient foregroundGradient( 0, 0, 0, groove.height() );
83 foregroundGradient.setColorAt( 0.0, foregroundBase );
84 foregroundGradient.setColorAt( 1.0, foregroundBase.darker( 125 ) );
86 /* draw a slight 3d effect on the bottom */
87 painter->setPen( QColor( 230, 230, 230 ) );
88 painter->setBrush( Qt::NoBrush );
89 painter->drawRoundedRect( groove.adjusted( 0, 2, 0, 0 ), RADIUS, RADIUS );
92 painter->setPen( Qt::NoPen );
93 painter->setBrush( backgroundGradient );
94 painter->drawRoundedRect( groove, RADIUS, RADIUS );
96 /* adjusted foreground rectangle */
97 QRect valueRect = groove.adjusted( 1, 1, -1, 0 );
99 valueRect.setWidth( sliderPos );
101 /* draw foreground */
102 if ( slider->sliderPosition > slider->minimum && slider->sliderPosition <= slider->maximum )
104 painter->setPen( Qt::NoPen );
105 painter->setBrush( foregroundGradient );
106 painter->drawRoundedRect( valueRect, RADIUS, RADIUS );
109 /* draw buffering overlay */
110 if ( seekSlider && seekSlider->f_buffering < 1.0 )
112 QRect innerRect = groove.adjusted( 1, 1,
113 groove.width() * ( -1.0 + seekSlider->f_buffering ) - 1, 0 );
114 QColor overlayColor = QColor( "Orange" );
115 overlayColor.setAlpha( 128 );
116 painter->setBrush( overlayColor );
117 painter->drawRoundedRect( innerRect, RADIUS, RADIUS );
121 if ( slider->subControls & SC_SliderTickmarks ) {
122 QStyleOptionSlider tmpSlider = *slider;
123 tmpSlider.subControls = SC_SliderTickmarks;
124 QWindowsStyle::drawComplexControl(cc, &tmpSlider, painter, widget);
127 if ( slider->subControls & SC_SliderHandle && handle.isValid() )
129 /* Useful for debugging */
130 //painter->setBrush( QColor( 0, 0, 255, 150 ) );
131 //painter->drawRect( handle );
133 if ( option->state & QStyle::State_MouseOver || (seekSlider && seekSlider->isAnimationRunning() ) )
135 QPalette p = slider->palette;
137 /* draw chapters tickpoints */
138 if ( seekSlider->chapters && seekSlider->inputLength && groove.width() )
140 QColor background = p.color( QPalette::Active, QPalette::Window );
141 QColor foreground = p.color( QPalette::Active, QPalette::WindowText );
142 foreground.setHsv( foreground.hue(),
143 ( background.saturation() + foreground.saturation() ) / 2,
144 ( background.value() + foreground.value() ) / 2 );
145 if ( slider->orientation == Qt::Horizontal ) /* TODO: vertical */
147 QList<SeekPoint> points = seekSlider->chapters->getPoints();
148 foreach( SeekPoint point, points )
150 int x = groove.x() + point.time / 1000000.0 / seekSlider->inputLength * groove.width();
151 painter->setPen( foreground );
152 painter->setBrush( Qt::NoBrush );
153 painter->drawLine( x, slider->rect.height(), x, slider->rect.height() - CHAPTERSSPOTSIZE );
159 if ( option->state & QStyle::State_Enabled && sliderPos != -1 )
161 QSize hSize = QSize( handle.height(), handle.height() ) - QSize( 6, 6 );;
162 QPoint pos = QPoint( handle.center().x() - ( hSize.width() / 2 ), handle.center().y() - ( hSize.height() / 2 ) );
164 QPoint shadowPos( pos - QPoint( 2, 2 ) );
165 QSize sSize( QSize( handle.height(), handle.height() ) - QSize( 2, 2 ) );
167 /* prepare the handle's gradient */
168 QLinearGradient handleGradient( 0, 0, 0, hSize.height() );
169 handleGradient.setColorAt( 0.0, p.window().color().lighter( 120 ) );
170 handleGradient.setColorAt( 0.9, p.window().color().darker( 120 ) );
172 /* prepare the handle's shadow gradient */
173 QColor shadowBase = p.shadow().color();
174 if( shadowBase.lightness() > 100 )
175 shadowBase = QColor( 60, 60, 60 ); // Palette's shadow is too bright
176 QColor shadowDark( shadowBase.darker( 150 ) );
177 QColor shadowLight( shadowBase.lighter( 180 ) );
178 shadowLight.setAlpha( 50 );
180 QRadialGradient shadowGradient( shadowPos.x() + ( sSize.width() / 2 ),
181 shadowPos.y() + ( sSize.height() / 2 ),
182 qMax( sSize.width(), sSize.height() ) / 2 );
183 shadowGradient.setColorAt( 0.4, shadowDark );
184 shadowGradient.setColorAt( 1.0, shadowLight );
186 painter->setPen( Qt::NoPen );
187 if ( seekSlider != NULL )
188 painter->setOpacity( seekSlider->mHandleOpacity );
190 /* draw the handle's shadow */
191 painter->setBrush( shadowGradient );
192 painter->drawEllipse( shadowPos.x(), shadowPos.y() + 1, sSize.width(), sSize.height() );
194 /* finally draw the handle */
195 painter->setBrush( handleGradient );
196 painter->drawEllipse( pos.x(), pos.y(), hSize.width(), hSize.height() );
204 qWarning() << "SeekStyle: Drawing an unmanaged control";
205 QWindowsStyle::drawComplexControl( cc, option, painter, widget );