]> SALOME platform Git repositories - modules/gui.git/blob - src/Style/Style_Tools.cxx
Salome HOME
8ba7c60c687ffe0cff3b3e4c035ae41c3b2eb5a6
[modules/gui.git] / src / Style / Style_Tools.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File   : Style_Tools.cxx
23 // Author : Natalia Ermolaeva, Open CASCADE S.A.S.
24 //
25 #include "Style_Tools.h"
26
27 #include <QPainter>
28 #include <QPainterPath>
29 #include <QRect>
30 #include <QColor>
31 #include <QSize>
32 #include <QTabWidget>
33
34 /*!
35   \class Style_Tools
36   \brief A set of utility functions used by SALOME style to draw widgets
37 */
38
39 /*!
40   \brief Create painter path for specified rectangle
41   \param r rectangle on which painter path is build
42   \return resulting painter path
43 */
44 QPainterPath Style_Tools::painterPath( const QRect& r )
45 {
46   QPainterPath res;
47   double x = r.x(), y = r.y(), right = r.right(), bottom = r.bottom();
48   res.moveTo( x, y );
49   res.lineTo( right, y );
50   res.lineTo( right, bottom );
51   res.lineTo( x, bottom );
52   res.closeSubpath();
53   return res;
54 }
55
56 /*!
57   \brief Create painter path by subtracting painter path \a path from another
58   painter path \a fromPath
59   \param fromPath initial painter path
60   \param path painter path being subtracted from \a fromPath
61   \return resulting painter path
62 */
63 QPainterPath Style_Tools::substractPath( const QPainterPath& fromPath,
64                                          const QPainterPath& path )
65 {
66   QPainterPath res;
67   QRegion aFromRegion( fromPath.toFillPolygon().toPolygon() );
68   QRegion aRegion( path.toFillPolygon().toPolygon() );
69   aFromRegion -= aRegion;
70   res.addRegion( aFromRegion );
71   return res;
72 }
73
74 /*!
75   \brief Create painter path basing on specified rectangle \a r with rounded corners
76   specified by radius \a r, operation \a type and shadow type \a shType.
77   \param r initial rectangle
78   \param rad rounding radius
79   \param type rounding type operation (Style_Tools::RoundType)
80   \param shType shadow type (Style_Tools::ShadowType)
81   \return resulting painter path
82 */
83 QPainterPath Style_Tools::roundRect( const QRect& r, const double rad, int type,
84                                      int shType )
85 {
86   QPainterPath res;
87   if ( type & None )
88     return painterPath( r );
89   double x = r.x(), y = r.y(), right = r.right(), bottom = r.bottom();
90   int aRad = getMaxRect( r, (int)rad );
91
92   if ( shType == WholePath || shType == TopPath ) {
93     if ( type & ( All | Left | BottomLeft ) ) {
94       res.moveTo( x+aRad, bottom );
95       res.arcTo( x, bottom-2*aRad, 2*aRad, 2*aRad, 270, -90 );
96     }
97     else
98       res.moveTo( x, bottom );
99     res.lineTo( x, y+aRad );
100     if ( type & (All | Left | TopLeft ) )
101       res.arcTo( x, y, 2*aRad, 2*aRad, 180, -90 );
102     else
103       res.lineTo( x, y );
104     res.lineTo( right-aRad, y );
105     if ( type & ( All | Right | TopRight ) )
106       res.arcTo( right-2*aRad, y, 2*aRad, 2*aRad, 90, -90 );
107     else
108       res.lineTo( right, y );
109   }
110   if ( shType == WholePath || shType == BottomPath ) {
111     if ( shType == BottomPath ) {
112       if ( type & ( All | Right | TopRight ) )
113         res.moveTo( right, y+aRad );
114       else
115         res.moveTo( right, y );
116     }
117     res.lineTo( right, bottom-aRad );
118     if ( type & ( All | Right | BottomRight ) )
119       res.arcTo( right-2*aRad, bottom-2*aRad, 2*aRad, 2*aRad, 0, -90 );
120     else
121       res.lineTo( right, bottom );
122
123     if ( type & ( All | Left | BottomLeft ) )
124       res.lineTo( x+aRad, bottom );
125     else
126       res.lineTo( x, bottom ); 
127   }
128   if ( shType == WholePath )
129     res.closeSubpath();
130   return res;
131 }
132
133 /*!
134   \brief Draw rectangle with rounded corners.
135   \param p painter
136   \param r drawing rectangle
137   \param rad corner rounding radius
138   \param type rounding type operation (Style_Tools::RoundType)
139   \param c1 first gradient color
140   \param c2 second gradient color
141   \param fill if \c true rectangle is filled with gradiented background according to \a c1 and \a c2
142   \param antial if \c true, rectangle corners are anti-aliased
143 */
144 void Style_Tools::roundRect( QPainter* p, const QRect& r, const double rad, const int type,
145                              const QColor& c1, const QColor& c2, bool fill, bool antial )
146 {
147   if ( antial )
148     p->setRenderHint( QPainter::Antialiasing );
149
150   QPainterPath path = roundRect( r, rad, type );
151
152   if ( fill ) {
153     QLinearGradient gr( r.x(), r.y(), r.x(), r.bottom() );
154     gr.setColorAt( 0.0, c1 );
155     gr.setColorAt( 0.5, c1 );
156     gr.setColorAt( 1.0, c2 );
157     p->fillPath( path, gr );
158   }
159   p->strokePath( path, QPen( c2, Qt::SolidLine ) );
160 }
161
162 /*!
163   \brief Draw rectangle with rounded corners and shadow.
164   \param p painter
165   \param r drawing rectangle
166   \param rad corner rounding radius
167   \param marg drawing margin
168   \param shad shadow size
169   \param type rounding type operation (Style_Tools::RoundType)
170   \param light background's first gradient color
171   \param dark background's second gradient color
172   \param border_top top-left border's color
173   \param border_bot bottom-right border's color
174   \param antialize if \c true, rectangle corners are anti-aliased
175   \param isButton \c true if button is drawn
176   \param btnOn \c true if button is drawn and it is pressed
177   \param fill if \c true rectangle is filled with gradiented background according to \a light and \a dark
178 */
179 void Style_Tools::shadowRect( QPainter* p, const QRect& r, const double rad, const double marg,
180                               const int shad, int type, const QColor& light, const QColor& dark,
181                               const QColor& border_top, const QColor& border_bot, const bool antialize,
182                               const bool isButton, const bool btnOn, const bool fill )
183 {
184   QColor aLight = light, aDark = dark, aBrdTop = border_top, aBrdBot = border_bot;
185   if ( isButton && btnOn ) {
186     aLight = dark;
187     aDark = light;
188     aBrdTop = border_bot;
189     aBrdBot = border_top;
190   }
191
192   // gradients
193   QLinearGradient
194     gr1( r.x(), r.y(), r.right(), r.y() ),
195     gr2( r.x(), r.y(), r.x(), r.bottom() );
196   if ( fill ) {
197     if ( isButton ) {
198       gr2.setColorAt( 0.0, aLight );
199       if ( marg > 0 )
200         gr2.setColorAt( marg / r.height(), aLight );
201       gr2.setColorAt( 1.0, aDark );
202     }
203     else {
204       QColor _c1 = aLight; _c1.setAlpha( 0 );
205       QColor _c2 = aDark;
206       gr1.setColorAt( 0.0, _c2 );
207       if ( marg > 0 )
208         gr1.setColorAt( marg / r.width(), _c1 );
209       gr1.setColorAt( 1.0, _c1 );
210       gr2.setColorAt( 0.0, _c2 );
211       if ( marg > 0 )
212         gr2.setColorAt( marg / r.height(), _c1 );
213       gr2.setColorAt( 1.0, _c1 );
214     }
215   }
216   // paths
217   int x = r.x(), y = r.y(), right = r.right(), bottom = r.bottom();
218   // main path
219   QRect rCont;
220   if ( antialize )
221    rCont = QRect( QPoint( x+shad, y+shad ), QPoint( right-shad, bottom-shad ) );
222   else
223     rCont = QRect( QPoint( x, y ), QPoint( right, bottom ) );
224
225   QPainterPath path = roundRect( rCont, rad, type );
226
227   // draw paths
228   p->save();
229   if ( antialize )
230     p->setRenderHint( QPainter::Antialiasing, true );
231   else
232     p->setRenderHint( QPainter::Antialiasing, false );
233
234   if( fill ) {
235     p->fillPath( path, aLight );
236     if ( !isButton )
237       p->fillPath( path, gr1 );
238     p->fillPath( path, gr2 );
239   }
240   if ( antialize )
241     p->strokePath( path, QPen( aBrdBot, Qt::SolidLine ) );
242
243   QPainterPath bottomPath = roundRect( rCont, rad, type, BottomPath ),
244                topPath = roundRect( rCont, rad, type, TopPath );
245   p->strokePath( bottomPath, aBrdBot );
246   p->strokePath( topPath, aBrdTop );
247
248   if ( antialize )
249       p->setRenderHint( QPainter::Antialiasing, false );
250   p->restore();
251 }
252
253 /*!
254   \brief Draw shadow of the check-mark
255   \param p painter
256   \param r drawing rectangle
257   \param rad corner rounding radius
258   \param type rounding type operation (Style_Tools::RoundType)
259   \param light background's first gradient color
260   \param dark background's second gradient color
261   \param border_top top-left border's color
262   \param border_bot bottom-right border's color
263 */
264 void Style_Tools::shadowCheck( QPainter* p, const QRect& r, const double rad, const int type,
265                                const QColor& light, const QColor& dark,
266                                const QColor& border_top, const QColor& border_bot  )
267 {
268   // main path
269   QPainterPath path = roundRect( r, rad, type );
270
271   QLinearGradient gr( r.x(), r.y(), r.right(), r.bottom() );
272   gr.setColorAt( 0.0, dark );
273   gr.setColorAt( 1.0, light );
274  
275   p->fillPath( path, gr ); //fill
276
277   QPainterPath bottomPath = roundRect( r, rad, type, BottomPath ),
278                topPath = roundRect( r, rad, type, TopPath );
279   p->strokePath( bottomPath, border_bot );
280   p->strokePath( topPath, border_top );
281 }
282
283 /*!
284   \brief Draw rectnagle arrow
285   \param p painter
286   \param re drawing rectangle
287   \param frame frame color
288   \param gr1 background's first gradient color
289   \param gr2 background's second gradient color
290 */
291 void Style_Tools::arrowRect( QPainter* p, const QRect& re, const QColor& frame,
292                              const QColor& gr1, const QColor& gr2 )
293 {
294   QPainterPath path;
295   const int r = 4;
296   const double d = re.height()/2;
297
298   path.moveTo( re.x()+r,            re.y() );
299   path.lineTo( re.x()+re.width(),   re.y() );
300   path.lineTo( re.x()+re.width()+d, re.y()+d );
301   path.lineTo( re.x()+re.width(),   re.y()+re.height() );
302   path.lineTo( re.x()+r,            re.y()+re.height() );
303   path.arcTo ( re.x(),              re.y()+2*d-2*r, 2*r, 2*r, 270, -90 );
304   path.lineTo( re.x(),              re.y()+r );
305   path.arcTo ( re.x(),              re.y(), 2*r, 2*r, 180, -90 );
306   path.closeSubpath();
307
308   QLinearGradient gr( re.x(), re.y(), re.x(), re.y()+re.height() );
309   gr.setColorAt( 0.0, gr1 );
310   gr.setColorAt( 0.4, gr2 );
311   gr.setColorAt( 0.6, gr2 );
312   gr.setColorAt( 1.0, gr1 );
313
314   p->fillPath( path, gr );
315   p->strokePath( path, QPen( frame, Qt::SolidLine ) );
316 }
317
318 /*!
319   \brief Fill rectangle with gradiented background
320   \param p painter
321   \param re drawing rectangle
322   \param c1 background's first gradient color
323   \param c2 background's second gradient color
324 */
325 void Style_Tools::fillRect( QPainter* p, const QRect& re, const QColor& c1,
326                             const QColor& c2, const int alpha )
327 {
328   QLinearGradient gr( re.x(), re.y(), re.x()+re.width(), re.y()+re.height() );
329   QColor cc1 = c1, cc2 = c2;
330   cc1.setAlpha( alpha );
331   cc2.setAlpha( alpha );
332   gr.setColorAt( 0.0, cc1 );
333   gr.setColorAt( 1.0, cc2 );
334   p->fillRect( re, gr );
335 }
336
337 /*!
338   \brief Draw arrow (for example, for combo-box drop-down menu button)
339   \param type primitive type
340   \param p painter
341   \param r drawing rectangle
342   \param pen foreground painter pen
343   \param brush background painter brush
344 */
345 void Style_Tools::drawArrow( QStyle::PrimitiveElement type, QPainter* p, const QRect& r,
346                              const QColor& pen, const QColor& brush )
347 {
348   p->save();
349   QPainterPath arrow1;
350   int x = r.x(), y = r.y(), w = r.right()-x, h = r.bottom()-y;
351   int x11 = 0, x12 = 0, y11 = 0, y12 = 0;
352   int aDelta = qMin( (int)(w/3.5), (int)(h/3.5) );
353   int deltaX = aDelta, deltaY = aDelta;
354   QLineF line( 0, 0, 1, 0 );
355   int xc = r.center().x(), yc = r.center().y();
356   p->translate( xc, yc );
357   bool correct = false;
358   switch( type ) {
359     case QStyle::PE_IndicatorArrowDown:
360       correct = true;
361     case QStyle::PE_IndicatorArrowUp: {
362       int widthArr2 = (int)(deltaX/3.);
363       if ( correct )
364         deltaY = -deltaY; // change arrow direction
365       arrow1.moveTo(  0,          deltaY );
366       arrow1.lineTo(  widthArr2,  deltaY );
367       arrow1.lineTo(  widthArr2,  0 );
368       arrow1.lineTo(  deltaX,     0 );
369       arrow1.lineTo(  0,          -deltaY );
370       arrow1.lineTo( -deltaX,     0. );
371       arrow1.lineTo( -widthArr2,  0 );
372       arrow1.lineTo( -widthArr2, deltaY );
373       arrow1.lineTo(  0,         deltaY );
374       if ( correct )
375         deltaX = -deltaX;
376       x11 = -deltaX; y11 = -deltaY; x12 = deltaX; y12 = deltaY;
377       break;
378     }
379     case QStyle::PE_IndicatorArrowLeft: // to change
380       correct = true;
381     case QStyle::PE_IndicatorArrowRight: {
382       int widthArr2 = (int)(deltaX/3.);
383       if ( correct )
384         deltaX = -deltaX; // change arrow direction
385       arrow1.moveTo( -deltaX,  0 );
386       arrow1.lineTo( -deltaX,  widthArr2 );
387       arrow1.lineTo(  0,       widthArr2 );
388       arrow1.lineTo(  0,       deltaY );
389       arrow1.lineTo(  deltaX,  0 );
390       arrow1.lineTo(  0,      -deltaY );
391       arrow1.lineTo(  0,      -widthArr2 );
392       arrow1.lineTo( -deltaX, -widthArr2 );
393       arrow1.lineTo( -deltaX,  0 );
394       x11 = deltaX; y11 = deltaY; x12 = -deltaX; y12 = -deltaY;
395       break;
396     }
397     case QStyle::PE_IndicatorSpinDown:
398       correct = true;
399     case QStyle::PE_IndicatorSpinUp: {
400       aDelta = (int)(deltaY/2);
401       if ( correct ) {
402         aDelta = (int)(-aDelta/2);
403         deltaY = -deltaY;
404       }
405       arrow1.moveTo(  deltaX,     -aDelta );
406       arrow1.lineTo(  0,          -aDelta-deltaY );
407       arrow1.lineTo( -deltaX,     -aDelta );
408       arrow1.lineTo(  deltaX,     -aDelta );
409       if ( correct )
410         deltaX = -deltaX;
411       x11 = -deltaX, y11 = -deltaY, x12 = deltaX, y12 = 0;
412       break;
413     }
414     default:
415       p->restore();
416       return;
417   }
418   p->setPen( pen );
419   p->setBrush( brush );
420
421   QLinearGradient gr( x11, y11, x12, y12 );
422   gr.setColorAt( 0.0, pen );                // grayer
423   gr.setColorAt( 1.0, brush);               // lighter
424   p->fillPath( arrow1, gr );
425   p->strokePath( arrow1, QPen( pen, Qt::SolidLine ) );
426
427   p->restore();
428 }
429
430 /*!
431   \brief Draw indicator (for example, for spin box's increment/decrement buttons)
432   \param type primitive type
433   \param p painter
434   \param r drawing rectangle
435   \param pen foreground painter pen
436   \param brush background painter brush
437 */
438 void Style_Tools::drawSign( QStyle::PrimitiveElement type, QPainter* p, const QRect& r,
439                             const QColor& pen, const QColor& brush )
440 {
441   p->save();
442   QPainterPath sign;
443   int x = r.x(), y = r.y(), w = r.right()-x, h = r.bottom()-y;
444   int x11 = 0, x12 = 0, y11 = 0, y12 = 0;
445   int aDelta = qMin( (int)(w/3.5), (int)(h/3.5) );
446   int deltaX = aDelta, deltaY = aDelta;
447   QLineF line( 0, 0, 1, 0 );
448   int xc = r.center().x(), yc = r.center().y();
449   p->translate( xc, yc );
450   bool correct = false;
451   switch( type ) {
452     case QStyle::PE_IndicatorSpinMinus:
453       correct = true;
454     case QStyle::PE_IndicatorSpinPlus: {
455       aDelta = (int)(deltaY/2);
456       if ( correct ) {
457         aDelta = -aDelta;
458         deltaY = -deltaY;
459       }
460       if ( correct ) 
461         sign.moveTo(  deltaY/2,   -aDelta/2-(deltaY/2-aDelta/3) );
462       else {
463         sign.moveTo(  aDelta/3,   -aDelta/2 );
464         sign.lineTo(  aDelta/3,   -aDelta/2-(deltaY/2-aDelta/3) );
465         sign.lineTo(  deltaY/2,   -aDelta/2-(deltaY/2-aDelta/3) );
466       }
467       
468       sign.lineTo(    deltaY/2,   -aDelta/2-(deltaY/2-aDelta/3)-2*aDelta/3 );
469       
470       if ( !correct ) {
471         sign.lineTo(  aDelta/3,   -aDelta/2-(deltaY/2-aDelta/3)-2*aDelta/3 );
472         sign.lineTo(  aDelta/3,   -aDelta/2-deltaY );
473         sign.lineTo( -aDelta/3,   -aDelta/2-deltaY );
474         sign.lineTo( -aDelta/3,   -aDelta/2-(deltaY/2-aDelta/3)-2*aDelta/3 );
475       }
476       
477       sign.lineTo(   -deltaY/2,   -aDelta/2-(deltaY/2-aDelta/3)-2*aDelta/3 );
478       sign.lineTo(   -deltaY/2,   -aDelta/2-(deltaY/2-aDelta/3) );
479
480       if ( correct ) 
481         sign.lineTo(  deltaY/2,   -aDelta/2-(deltaY/2-aDelta/3) );
482       else {
483         sign.lineTo( -aDelta/3,   -aDelta/2-(deltaY/2-aDelta/3) );
484         sign.lineTo( -aDelta/3,   -aDelta/2 );
485         sign.lineTo(  aDelta/3,   -aDelta/2);
486       }
487
488       if ( correct )
489         deltaX = -deltaX;
490       x11 = -deltaX, y11 = -deltaY, x12 = deltaX, y12 = 0;
491       break;
492     }
493     default:
494       p->restore();
495       return;
496   }
497   p->setPen( pen );
498   p->setBrush( brush );
499
500   QLinearGradient gr( x11, y11, x12, y12 );
501   gr.setColorAt( 0.0, pen );                // grayer
502   gr.setColorAt( 1.0, brush);               // lighter
503   p->fillPath( sign, gr );
504   p->strokePath( sign, QPen( pen, Qt::SolidLine ) );
505
506   p->restore();
507 }
508
509 /*!
510   \brief Create painter path for tab bar and optionally draw it
511   \param p painter
512   \param r drawing rectangle
513   \param position tab position
514   \param rad rounding radius
515   \param delta gap between tabs
516   \param light background's first gradient color
517   \param dark background's second gradient color
518   \param border_top top-left border's color
519   \param border_bot bottom-right border's color
520   \param selected \c true if tab is selected
521   \param isLast \c true if tab is last in the tabs list
522   \param isHover \c true if tab is hovered
523   \param focusRect focus rectangle
524   \param draw if \c true, tab bar is drawn
525   \return tab bar's painter path
526 */
527 QPainterPath Style_Tools::tabRect( QPainter* p, const QRect& r, const int position, const double rad,
528                                    const double delta, const QColor& light, const QColor& dark,
529                                    const QColor& border_top, const QColor& border_bot,
530                                    const bool selected, const bool isLast,  const bool isHover,
531                                    const bool focusRect, const bool draw )
532 {
533   // paths
534   int x = r.x()+1, y = r.y()+1, right = r.right()+1, left = r.left()-1,
535       bottom = r.bottom()-1, top = r.top()+1;
536   int aDelta;
537   if ( position == QTabWidget::North || position == QTabWidget::South )
538     aDelta = (int)((bottom - top)*delta/2);
539   else
540     aDelta = (int)((right-left)*delta/2);  
541
542   int aRad = getMaxRect( r, (int)rad );
543
544   // main path
545   QPainterPath path, strokePath;
546   switch ( position ) {
547     case QTabWidget::North: {
548       path.moveTo( x, bottom );
549       path.lineTo( x, y+aRad );
550       path.arcTo( x, y, 2*aRad, 2*aRad, 180, -90 );
551       if ( isLast )
552         right = right - aDelta;
553       path.lineTo( right-aDelta, y );
554       path.lineTo( right+aDelta, bottom );
555       strokePath.moveTo( x, bottom );
556       strokePath.lineTo( right+aDelta, bottom );
557       break;
558     }
559     case QTabWidget::South: {
560       path.moveTo( x, y );
561       path.lineTo( x, bottom-aRad );
562       path.arcTo( x, bottom-2*aRad, 2*aRad, 2*aRad, 180, 90 );
563       if ( isLast )
564         right = right - aDelta;
565       path.lineTo( right-aDelta, bottom );
566       path.lineTo( right+aDelta, y );
567       strokePath.moveTo( x, y );
568       strokePath.lineTo( right+aDelta, y );
569       break;
570     }
571     case QTabWidget::West: {
572       path.moveTo( right, y );
573       path.lineTo( x+aRad, y );
574       path.arcTo( x, y, 2*aRad, 2*aRad, 90, 90 );
575       if ( isLast )
576         bottom = bottom - aDelta;
577       path.lineTo( x, bottom-aDelta );
578       path.lineTo( right, bottom+aDelta );
579       strokePath.moveTo( right, y );
580       strokePath.lineTo( right, bottom+aDelta );
581       break;
582     }
583     case QTabWidget::East: {
584       path.moveTo( x, y );
585       path.lineTo( right-aRad, y );
586       path.arcTo( right-2*aRad, y, 2*aRad, 2*aRad, 90, -90 );
587       if ( isLast )
588         bottom = bottom - aDelta;
589       path.lineTo( right, bottom-aDelta );
590       path.lineTo( x, bottom+aDelta );
591       strokePath.moveTo( x, y );
592       strokePath.lineTo( x, bottom+aDelta );
593       break;
594     }
595   }
596   if ( !draw )
597     return path;
598
599   // draw path
600   p->save();
601   p->setRenderHint( QPainter::Antialiasing, true );
602   if ( focusRect ) {
603     path.closeSubpath();
604     drawFocus( p, path, dark, false );
605   }
606   else {
607     QLinearGradient gr( x, y, x, bottom );
608     if ( selected ) {
609       gr.setColorAt( 0.0, light );
610       gr.setColorAt( 1.0, light );
611     }
612     else if ( isHover ) {
613       gr.setColorAt( 0.0, dark );
614       gr.setColorAt( 0.2, light );
615       gr.setColorAt( 0.8, light );
616       gr.setColorAt( 1.0, dark );
617       QLinearGradient gr_1( x, y, right, y );
618       QColor aLight = light;
619       aLight.setAlpha( 0 );
620       gr_1.setColorAt( 0.0, dark );
621       gr_1.setColorAt( 0.2, aLight );
622       gr_1.setColorAt( 0.7, aLight );
623       gr_1.setColorAt( 1.0, dark );
624       p->fillPath( path, gr );
625       p->fillPath( path, gr_1 );
626     }
627     else {
628       gr.setColorAt( 0.0, light );
629       gr.setColorAt( 0.3, dark );
630       gr.setColorAt( 0.7, dark );
631       gr.setColorAt( 1.0, light );
632     }
633     if ( !isHover || selected )
634       p->fillPath( path, gr );
635
636     QColor bordCol = border_top;
637     if ( position == QTabWidget::South || position == QTabWidget::East )
638       bordCol = border_bot;
639     else
640       bordCol = border_top;
641     p->strokePath( path, QPen( bordCol, Qt::SolidLine ) );
642     p->setRenderHint( QPainter::Antialiasing, false );
643     p->strokePath( strokePath, QPen( selected ? light : bordCol, Qt::SolidLine ) );
644   }
645   p->restore();
646   return path;
647 }
648
649 /*!
650   \brief Draw widget's focus
651   \param p painter
652   \param aRect drawing rectangle
653   \param rad rounding radius
654   \param type rounding operation type
655   \param border focus rectangle color
656 */
657 void Style_Tools::drawFocus( QPainter* p, const QRect& aRect, const double rad, const int type,
658                              const QColor& border )
659 {
660   QPainterPath path = Style_Tools::roundRect( aRect, rad, type );
661
662   drawFocus( p, path, border );
663 }
664
665 /*!
666   \brief Draw widget's focus
667   \param p painter
668   \param path drawing painter path
669   \param border focus rectangle color
670   \param line if \c true, focus is drawn as dotted line
671 */
672 void Style_Tools::drawFocus( QPainter* p, const QPainterPath& path, const QColor& border,
673                              const bool line )
674 {
675   QPen oldPen = p->pen();
676   QPen aPen = oldPen;
677   aPen.setColor( border );
678   if ( !line )
679     aPen.setStyle( Qt::DotLine );
680   p->setPen( aPen );
681
682   p->drawPath( path );
683   p->setPen( oldPen );
684 }
685
686 /*!
687   \brief Draw slider
688   \param p painter
689   \param r drawing rectangle
690   \param rad rounding radius
691   \param slider slider type
692   \param light background's first gradient color
693   \param dark background's second gradient color
694   \param border_top top-left border's color
695   \param border_bot bottom-right border's color
696 */
697 void Style_Tools::drawSlider( QPainter* p, const QRect& r, const double rad,
698                               SliderType type, const QColor& light, const QColor& dark,
699                               const QColor& border_top, const QColor& border_bot )
700 {
701   p->save();
702   QPainterPath path, bottomPath;
703   if ( rad == 0 )
704     type = SlNone;
705   int aRad = getMaxRect( r, (int)rad );
706   int w = r.width(), h = r.height();
707   int xc = r.center().x(), yc = r.center().y();
708   p->translate( xc, yc );
709   QLinearGradient gr;
710   switch ( type ) {
711     case SlUp:
712     case SlDown: {
713       int aDeltaX = (int)(w/2), aDeltaY = (int)(h/4), aDeltaArr = (int)(aDeltaY/2);
714       if ( type == SlDown )
715         p->rotate( 180 );
716       path.moveTo(  0,       -2*aDeltaY );
717       path.lineTo(  aDeltaX, -aDeltaY+aDeltaArr );
718       path.lineTo(  aDeltaX, 2*aDeltaY-aRad );
719       path.arcTo(   aDeltaX-2*aRad, 2*aDeltaY-2*aRad, 2*aRad, 2*aRad, 0, -90 );
720       path.lineTo( -aDeltaX+aRad, 2*aDeltaY );
721       path.arcTo(  -aDeltaX,  2*aDeltaY-2*aRad, 2*aRad, 2*aRad, 270, -90 );
722       path.lineTo( -aDeltaX, -aDeltaY+aDeltaArr );
723       path.lineTo( 0,       -2*aDeltaY );
724       bottomPath = path;
725       gr.setStart( 0, -2*aDeltaY );
726       gr.setFinalStop( 0, 2*aDeltaY );
727       break;
728     }
729     case SlLeft:
730     case SlRight: {
731       int aDeltaX = (int)(w/4), aDeltaY = (int)(h/2), aDeltaArr = (int)(aDeltaX/2);
732       if ( type == SlRight )
733         p->rotate( 180 );
734       path.moveTo( -2*aDeltaX,        0 );
735       path.lineTo( -aDeltaX+aDeltaArr,aDeltaY );
736       path.lineTo(  2*aDeltaX-aRad,   aDeltaY );
737       path.arcTo(   2*aDeltaX-2*aRad, aDeltaY-2*aRad, 2*aRad, 2*aRad, 270, 90 );
738       path.lineTo(  2*aDeltaX,       -aDeltaY+aRad );
739       path.arcTo(   2*aDeltaX-2*aRad, -aDeltaY, 2*aRad, 2*aRad, 0, 90 );
740       path.lineTo( -aDeltaX+aDeltaArr,-aDeltaY );
741       path.lineTo( -2*aDeltaX,       0 );
742       gr.setStart( -2*aDeltaX, 0 );
743       gr.setFinalStop( 2*aDeltaX, 0 );
744       bottomPath = path;
745       break;
746     }
747     case SlNone: {
748       p->translate( -xc, -yc );
749       path = Style_Tools::roundRect( r, rad, Style_Tools::All );
750       bottomPath = path;
751       gr.setStart( r.x(), r.y() );
752       gr.setFinalStop( r.x(), r.bottom() );
753       break;
754     }
755     default:
756       return;
757   }
758   p->setRenderHint( QPainter::Antialiasing );
759   gr.setColorAt( 0.0, light );
760   gr.setColorAt( 1.0, dark );
761   p->fillPath( path, gr );
762
763   QColor bottomShadow = border_bot;
764   p->strokePath( bottomPath, bottomShadow );
765   p->setRenderHint( QPainter::Antialiasing, false );
766   p->restore();
767 }
768
769 /*!
770   \brief Draw highlighted rectangle
771   \param p painter
772   \param rect drawing rectangle
773   \param rad rounding radius
774   \param type rounding operation type
775   \parma marg margin size
776   \param center background's center gradient color
777   \param out_center background's second color
778   \param border border color
779 */
780 void Style_Tools::highlightRect( QPainter* p, const QRect& rect, const double rad, const int type,
781                                  const double marg, const QColor& center, const QColor& out_center,
782                                  const QColor& border )
783 {
784   QPainterPath path = Style_Tools::roundRect( rect, rad, type );
785   QLinearGradient gr_h( rect.x(), rect.y(), rect.right(), rect.y() ),
786                   gr_v( rect.x(), rect.y(), rect.x(), rect.bottom() );
787   double aXDelta = marg > 0 ? marg/rect.width() : 0.5;
788   double aYDelta = marg > 0 ? marg/rect.height() : 0.5;
789   if ( aYDelta > 0.5 )
790     aYDelta = 0.25;
791   gr_v.setColorAt( 0.0, out_center );
792   gr_v.setColorAt( aYDelta, center );
793   gr_v.setColorAt( 1-aYDelta, center );
794   gr_v.setColorAt( 1.0, out_center );
795
796   QColor aCenter = center;
797   aCenter.setAlpha( 0 );
798   if ( aXDelta > 0.5 )
799     aXDelta = 0.25;
800   gr_h.setColorAt( 0.0, out_center );
801   gr_h.setColorAt( aXDelta, aCenter );
802   gr_h.setColorAt( 1-aXDelta, aCenter );
803   gr_h.setColorAt( 1.0, out_center );
804
805   p->fillPath( path, gr_v );
806   if ( marg > 0 )
807     p->fillPath( path, gr_h );
808   p->strokePath( path, border );
809 }
810
811 /*!
812   \brief Get minimal delta value (the minimum between \a rect and \a size dimensions)
813   \param rect rectangle
814   \param size size
815   \param defDelta default minimum delta
816   \return resulting minimum value
817 */
818 int Style_Tools::getMinDelta( const QRect& rect, const QSize& size, const int defDelta )
819 {
820   int aDelta = defDelta;
821   aDelta = qMin( aDelta, ( rect.height() - size.height() ) / 2 );
822   aDelta = qMin( aDelta, ( rect.width()  - size.width() )  / 2 );
823   return aDelta;
824 }
825
826 /*!
827   \brief Get halved size of the quadrangle covering specified rectangle
828   \param rect rectangle
829   \param defRect default quadranle size value
830   \return resulting value
831 */
832 int Style_Tools::getMaxRect( const QRect& rect, const int defRect )
833 {
834   int aRect = defRect;
835   aRect = qMin( aRect, rect.height() / 2 );
836   aRect = qMin( aRect, rect.width()  / 2 );
837   return aRect;
838 }