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