Salome HOME
Join modifications from branch OCC_debug_for_3_2_0b1
[modules/gui.git] / src / Style / SalomeStyle.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
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.
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/
18 //
19 #include "SalomeStyle.h"
20
21 #include <qimage.h>
22 #include <qcursor.h>
23 #include <qtabbar.h>
24 #include <qpalette.h>
25 #include <qtoolbar.h>
26 #include <qspinbox.h>
27 #include <qpainter.h>
28 #include <qlineedit.h>
29 #include <qlistview.h>
30 #include <qdrawutil.h>
31 #include <qpopupmenu.h>
32 #include <qpushbutton.h>
33 #include <qobjectlist.h>
34 #include <qtoolbutton.h>
35 #include <qapplication.h>
36
37 static const char* const hole_xpm[] = {
38 "3 3 3 1",
39 ". c None",
40 "a c #999999",
41 "b c #FFFFFF",
42 "aa.",
43 "aab",
44 ".bb"
45 };
46
47 static const char* const cross_xpm[] = {
48 "12 12 4 1",
49 ". c None",
50 "a c #000000",
51 "b c #FFFFFF",
52 "c c #666666",
53 "............",
54 "............",
55 "............",
56 ".aaaa..aaaa.",
57 "..abbaabba..",
58 "...abbbba...",
59 "....abba....",
60 "...abbbba...",
61 "..abbaabba..",
62 ".aaaa..aaaa.",
63 "............",
64 "............"
65 };
66
67 static const char* const maximize_xpm[] = {
68 "12 12 4 1",
69 ". c None",
70 "a c #000000",
71 "b c #FFFFFF",
72 "c c #666666",
73 "............",
74 ".aaaaaaaaaa.",
75 ".acccccccca.",
76 ".acccccccca.",
77 ".abbbbbbbba.",
78 ".abbbbbbbba.",
79 ".abbbbbbbba.",
80 ".abbbbbbbba.",
81 ".abbbbbbbba.",
82 ".abbbbbbbba.",
83 ".aaaaaaaaaa.",
84 "............"
85 };
86
87 static const char* const normal_xpm[] = {
88 "12 12 4 1",
89 ". c None",
90 "a c #000000",
91 "b c #FFFFFF",
92 "c c #666666",
93 "............",
94 "...aaaaaaaa.",
95 "...acccccca.",
96 "...abbbbbba.",
97 "...aaaaaaba.",
98 ".aaaaaaaaba.",
99 ".accccccaba.",
100 ".abbbbbbaaa.",
101 ".abbbbbba...",
102 ".abbbbbba...",
103 ".aaaaaaaa...",
104 "............"
105 };
106
107 static const char* const minimize_xpm[] = {
108 "12 12 4 1",
109 ". c None",
110 "a c #000000",
111 "b c #FFFFFF",
112 "c c #666666",
113 "............",
114 "............",
115 "............",
116 "............",
117 "............",
118 "............",
119 "............",
120 "............",
121 "aaaaaaaaaaaa",
122 "abbbbbbbbbba",
123 "aaaaaaaaaaaa",
124 "............"
125 };
126
127 /*!
128     Class: SalomeStyle [Public]
129     Descr: Style for SALOME platform
130 */
131
132 /*!
133   Constructor
134 */
135 SalomeStyle::SalomeStyle()
136 : myTitleParent( 0 )
137 {
138   qApp->installEventFilter( this ); 
139 }
140
141 /*!
142   Destructor
143 */
144 SalomeStyle::~SalomeStyle()
145 {
146 }
147
148 /*!
149   Delayed initialization of style
150 */
151 void SalomeStyle::polish( QWidget* w )
152 {
153   if ( !w )
154     return;
155 /*
156   if ( w->inherits( "QLineEdit" ) )
157   {
158     QLineEdit* fr = (QLineEdit*)w;
159     if ( w->parentWidget() && w->parentWidget()->inherits( "QSpinWidget" ) )
160       fr->setFrameStyle( QFrame::Plain );
161     else
162     {
163       fr->setFrameStyle( QFrame::Plain | QFrame::Box );
164       fr->setLineWidth( 1 );
165       fr->setMidLineWidth( 0 );
166     }
167   }
168   else
169 */
170   if ( w->inherits( "QToolBar" ) )
171   {
172     QToolBar* tb = (QToolBar*)w;
173     tb->setFrameStyle( QFrame::ToolBarPanel | QFrame::Plain );
174     tb->setLineWidth( 1 );
175     tb->setMidLineWidth( 1 );
176   }
177   else
178   if ( w->inherits( "QDockWindow" ) )
179   {
180     QDockWindow* dw = (QDockWindow*)w;
181     dw->setFrameStyle( QFrame::ToolBarPanel | QFrame::Raised );
182   }
183 /*
184   else if ( w->inherits( "QListView" ) )
185   {
186     QListView* lv = (QListView*)w;
187     lv->setFrameStyle( QFrame::Box | QFrame::Plain );
188   }
189 */
190   else
191     PARENT_STYLE::polish( w );
192 }
193
194 /*!
195   Custom event filter
196 */
197 bool SalomeStyle::eventFilter( QObject* o, QEvent* e )
198 {
199   if ( e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut )
200   {
201     QDockWindow* wnd = NULL;
202     while( o && !wnd )
203       if( o->inherits( "QDockWindow" ) )
204         wnd = ( QDockWindow* )o;
205       else
206         o = o->parent();
207
208     if ( wnd )
209     {
210       const QObjectList* objList = o->children();
211       for( QObjectListIterator anIt( *objList ); anIt.current(); ++anIt )
212         if( anIt.current()->inherits( "QDockWindowHandle" ) )
213         {
214           QWidget* ww = ( QWidget* )anIt.current();
215           ww->repaint( ww->rect() );
216           const QObjectList* wc = ww->children();
217           for( QObjectListIterator anIt2( *wc ); anIt2.current(); ++anIt2 )
218             if( anIt2.current()->inherits( "QToolButton" ) )
219             {
220               QWidget* tb = ( QWidget* )anIt2.current();
221               tb->repaint( tb->rect() );
222             }
223         }      
224     }
225   }
226
227   if ( o && o->inherits( "QPushButton" ) && ( e->type() == QEvent::Enter || e->type() == QEvent::Leave ) )
228     ((QWidget*)o)->update();
229
230   return false;
231 }
232
233 double linear( double x )
234 {
235   return x;
236 }
237
238 /*!
239   Mixes two colors, part of first is 1-t, part of second is t
240   \param t - part parameter
241   \param c1, c2 - colors
242   \param res - result color
243 */
244 void SalomeStyle::mix( const double t, const QColor& c1, const QColor& c2, QColor& res )
245 {
246   if( t<0.0 || t>1.0 )
247     return;
248
249   int r = int( c1.red() * (1-t) + c2.red() * t ),
250       g = int( c1.green() * (1-t) + c2.green() * t ),
251       b = int( c1.blue() * (1-t) + c2.blue() * t );
252   res.setRgb( r, g, b );
253 }
254
255 /*!
256   Mixes two colors, part of first is 1-t, part of second is t
257   \param t - part parameter
258   \param rgb1, rgb2 - colors (result is stored in rgb1)
259 */
260 void SalomeStyle::mix( const double t, QRgb& rgb1, const QRgb& rgb2 )
261 {
262   if( t<0.0 || t>1.0 )
263     return;
264
265   int c[2][4] = { qRed( rgb1 ), qGreen( rgb1 ), qBlue( rgb1 ), qAlpha( rgb1 ),
266                   qRed( rgb2 ), qGreen( rgb2 ), qBlue( rgb2 ), qAlpha( rgb2 ) };
267   for( int i=0; i<4; i++ )
268     c[0][i] = (int)( c[0][i] * (1-t) + c[1][i] * t );
269
270   rgb1 = qRgba( c[0][0], c[0][1], c[0][2], qAlpha( rgb1 ) );
271 }
272
273 /*!
274   Mixes colors of pixmap points with other color
275   \param t - part parameter
276   \param pix - pixmap to be processed
277   \param col - other color
278 */
279 void SalomeStyle::mix( const double t, QPixmap& pix, const QColor& col )
280 {
281   if( t<0.0 || t>1.0 )
282     return;
283
284   QImage anImage = pix.convertToImage();
285   if( anImage.isNull() )
286     return;
287
288   if( anImage.depth()!=32 )
289     anImage = anImage.convertDepth( 32 );
290
291   int w = anImage.width(),
292       h = anImage.height();
293
294   QRgb colrgb = col.rgb(), cur;
295   for( int y=0; y<h; y++ )
296   {
297     uchar* line = anImage.scanLine( y );
298     QRgb*  colorline = ( QRgb* ) line;
299     for( int x=0; x<w; x++ )
300     {
301       cur = colorline[ x ];
302       mix( t, cur, colrgb );
303       colorline[ x ] = cur;
304     }
305   }
306   pix = anImage;
307 }
308
309 /*!
310   Converts pixmap to grayscale
311   \param pix - pixmap to be processed
312   \param k - factor (gray value after conversion will be multiplied on it and truncated by 255.0)
313 */
314 void SalomeStyle::toGrayscale( QPixmap& pix, double k )
315 {
316   QImage anImage = pix.convertToImage();
317   if( anImage.isNull() )
318     return;
319
320   if( anImage.depth()!=32 )
321     anImage = anImage.convertDepth( 32 );
322
323   int w = anImage.width(),
324       h = anImage.height();
325
326   for( int y=0; y<h; y++ )
327   {
328     uchar* line = anImage.scanLine( y );
329     QRgb*  colorline = ( QRgb* ) line;
330     for( int x=0; x<w; x++ )
331     {
332       int gray = (int)( k * qGray( colorline[ x ] ) );
333       if ( gray>255 )
334         gray = 255;
335       else if( gray<0 )
336         gray = 0;
337       colorline[ x ] = qRgba( gray, gray, gray, qAlpha( colorline[x] ) );
338     }
339   }
340   pix = anImage;
341 }
342
343 /*!
344   Draws gradient filling
345   \param p - painter
346   \param r - rect
347   \param c1, c2 - two colors of gradient
348   \param d - direction of gradient
349   \param f - gradient function (maps co-ordinate to part parameter)
350 */
351 void SalomeStyle::drawGradient( QPainter* p, const QRect& r,
352                                     const QColor& c1, const QColor& c2,
353                                     const Direction d, gradient_func f ) const 
354 {
355   p->save();
356   p->translate( r.x(), r.y() );
357
358   QColor mid;
359   if( d==LeftToRight || d==RightToLeft )
360     for( int xmax = r.width(), x = d==LeftToRight ? 0 : xmax;
361          d==LeftToRight ? x<=xmax : x>=0;
362          d==LeftToRight ? x++ : x-- )
363     {
364       double t = double( x ) / double( xmax );
365       mix( d==LeftToRight ? f(t) : 1-f(t), c1, c2, mid );
366       p->setPen( mid );
367       p->drawLine( x, 0, x, r.height() );
368     }
369   else
370     for( int ymax = r.height(), y = d==UpToDown ? 0 : ymax;
371          d==UpToDown ? y<=ymax : y>=0;
372          d==UpToDown ? y++ : y-- )
373     {
374       double t = double( y ) / double( ymax );
375       mix( d==UpToDown ? f(t) : 1-f(t), c1, c2, mid );
376       p->setPen( mid );
377       p->drawLine( 0, y, r.width(), y );
378     }
379
380   p->restore();
381 }
382
383 /*!
384   Draws primitive element
385   \param pe - type of primitive element
386   \param p - painter
387   \param r - rect
388   \param cg - group of colors
389   \param flags - is used to control how the PrimitiveElement is drawn
390   \param opt - can be used to control how various PrimitiveElements are drawn
391 */
392 void SalomeStyle::drawPrimitive( PrimitiveElement pe, QPainter* p, const QRect& r,
393                                  const QColorGroup& cg, SFlags flags, const QStyleOption& opt ) const
394 {
395   switch ( pe )
396   {
397   case PE_ButtonTool:
398     if ( !myTitleParent )
399       PARENT_STYLE::drawPrimitive( pe, p, r, cg, flags, opt );
400     break;
401
402   case PE_DockWindowResizeHandle:
403     p->fillRect( r.x(), r.y(), r.width(), r.height(), cg.dark() );
404     if ( flags & Style_Horizontal )
405       p->fillRect( r.x(), r.y() + 1, r.width(), r.height() - 2, cg.midlight() );
406     else
407       p->fillRect( r.x() + 1, r.y(), r.width() - 2, r.height(), cg.midlight() );
408     break;
409
410   case PE_DockWindowHandle:
411     {
412       QPaintDevice* pd = p->device();
413       if ( !pd )
414         break;
415
416       QWidget* w = (QWidget*)pd;
417
418       if ( !w || !w->inherits( "QDockWindowHandle" ) )
419         break;
420
421       QDockWindow* wnd = ( QDockWindow* ) w->parent();
422       if ( !wnd )
423         return;
424
425       QObject* activeWidget = qApp->focusWidget();
426       QDockWindow* activeWnd = 0;
427       while ( !activeWnd && activeWidget )
428       {
429         if ( activeWidget->inherits( "QDockWindow" ) )
430           activeWnd = (QDockWindow*)activeWidget;
431         else
432           activeWidget = activeWidget->parent();
433       }
434
435       bool act = wnd == activeWnd, horiz = flags & Style_Horizontal;
436
437       QPixmap hole( (const char**)hole_xpm );
438
439       if ( wnd->inherits( "QToolBar" ) )
440       {
441         drawGradient( p, r, cg.light(), cg.background(), horiz ? UpToDown : LeftToRight, linear );
442
443         int c = 4, i; double d = ( horiz ? r.height() : r.width() ) / ( c + 1 );
444         QBrush fill = cg.brush( QColorGroup::Dark );
445         p->setPen( Qt::red );
446         for ( i = 0; i < c; i++ )
447         {
448           if ( horiz )
449             p->drawPixmap( r.x() + r.width() / 2 - 1, (int)( r.y() + ( i + 1 ) * d - 1 ), hole );
450           else
451             p->drawPixmap( (int) ( r.x() + ( i + 1 ) * d - 1 ), r.y() + r.height() / 2 - 1, hole );
452         }
453
454         int dd = (int(d)/2) + (int(d)%2);
455         for ( i = 0; i < c - 1; i++ )
456         {
457           if ( horiz )
458             p->drawPixmap( r.x() + r.width() / 2 + 2, (int)( r.y() + dd + ( i + 1 ) * d - 1 ), hole );
459           else
460             p->drawPixmap( (int)( r.x() + dd + ( i + 1 ) * d - 1 ), r.y() + r.height() / 2 + 2, hole );
461         }
462       }
463       else
464       {
465         int d = 1;
466         QRect rr( r.x()+d, r.y()+d, r.width()-2*d, r.height()-2*d );
467
468         QColor col; 
469         if ( act )
470           mix( 0.5, cg.highlight(), Qt::white, col );
471         else
472           col = cg.background();
473
474         drawGradient( p, rr, act ? cg.highlight() : cg.dark(), col,
475                       horiz ? LeftToRight : UpToDown, linear );
476
477                     QRect rt = rr;
478         if ( flags & Style_Horizontal )
479           rt.addCoords( 0, 20, 0, 0 );
480         else
481           rt.addCoords( 0, 0, -20, 0 );
482
483         int textW = flags & Style_Horizontal ? rt.height() : rt.width();
484         int textH = flags & Style_Horizontal ? rt.width() : rt.height();
485
486         QString title = titleText( wnd->caption(), textW, p->fontMetrics() );
487
488                     if ( wnd )
489         {
490                       QColorGroup cgroup = wnd->isActiveWindow() ? wnd->palette().active() : wnd->palette().inactive();
491                       p->setPen( cgroup.highlightedText() );
492
493                       if ( flags & Style_Horizontal )
494           {
495                         p->rotate( 270.0 );
496                         p->translate( -(rt.height()+rt.y()), (rt.width()-rt.x()) );
497                         p->drawText( 0, 0, title );
498                       }
499           else
500                         p->drawText( 2, 2, textW, textH, AlignLeft, title );
501               }
502       }
503       break;
504     }
505
506   case PE_DockWindowSeparator:
507     {
508       bool horiz = ( flags & Style_Horizontal );
509       QWidget* w = ( QWidget* )p->device();
510       if( w->inherits( "QToolBarSeparator" ) )
511       {
512         drawGradient( p, r, cg.light(), cg.background(), horiz ? UpToDown : LeftToRight, linear );
513         int w = r.width(), h = r.height();
514         int part = 8;
515
516         p->setPen( cg.dark() );
517         if( horiz )
518           p->drawLine( r.x() + w/2, r.y() + h/part, r.x() + w/2, r.y() + (part-1)*h/part );
519         else
520           p->drawLine( r.x() + w/part, r.y() + h/2, r.x() + (part-1)*w/part, r.y() + h/2 );
521
522         p->setPen( cg.light() );
523         if( horiz )
524           p->drawLine( r.x() + w/2 + 1, r.y() + h/part + 1, r.x() + w/2 + 1, r.y() + (part-1)*h/part + 1 );
525         else
526           p->drawLine( r.x() + w/part + 1, r.y() + h/2 + 1, r.x() + (part-1)*w/part + 1, r.y() + h/2 + 1 );
527       }
528       else
529         PARENT_STYLE::drawPrimitive( pe, p, r, cg, flags, opt );
530       break;
531     }
532     
533   case PE_PanelDockWindow:
534     {
535       QWidget* w = ( QWidget* )p->device();
536
537       int offset = pixelMetric( PM_DockWindowHandleExtent, w );
538       if ( w->inherits( "QToolBar" ) )
539       {
540         bool vert = ( ( QToolBar* )w )->orientation() == Qt::Vertical;
541         if ( vert )
542           drawGradient( p, QRect( r.x(), r.y()+offset, r.x()+r.width(), r.y()+offset ),
543                         cg.light(), cg.background(), LeftToRight, linear );
544         else
545           drawGradient( p, QRect( r.x()+offset, r.y(), r.x()+offset, r.y()+r.height() ),
546                         cg.light(), cg.background(), UpToDown, linear );
547
548         p->setPen( QPen( cg.light(), 1 ) );
549         p->drawRect( r );
550       }
551       else
552       {
553         p->setPen( QPen( cg.dark(), 1 ) );
554         p->setBrush( cg.light() );
555         p->drawRect( r );
556       }
557
558       break;
559     }
560
561   case PE_PanelPopup:
562     p->setPen( QPen( cg.dark(), 1 ) );
563     p->setBrush( cg.light() );
564     p->drawRect( r );
565     break;
566
567   case PE_HeaderSection:
568     {
569       QColor col; mix( 0.2, cg.light(), Qt::black, col );
570       drawGradient( p, r, cg.light(), col, DownToUp, linear );
571       drawGradient( p, QRect( r.x(), r.y(), 1, r.height() ), cg.light(), cg.dark(), DownToUp, linear );
572       p->setPen( cg.dark() );
573       p->drawLine( r.x(), r.y()+r.height()-1, r.x()+r.width(), r.y()+r.height()-1 );
574       break;
575     }
576
577   case PE_Splitter:
578     p->fillRect( r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2, cg.dark() );
579     p->fillRect( r.x() + 2, r.y() + 2, r.width() - 4, r.height() - 4, cg.midlight() );
580           break;
581
582   case PE_ButtonBevel:
583     PARENT_STYLE::drawPrimitive( PE_ButtonDropDown, p, r, cg, flags, opt );
584     break;
585
586   case PE_ButtonCommand:
587     {
588       QColorGroup cGrp( cg );
589       if ( flags & Style_MouseOver )
590         cGrp.setColor( QColorGroup::Button, cGrp.midlight() );
591
592       if ( flags & Style_MouseOver )
593         PARENT_STYLE::drawPrimitive( PE_ButtonDropDown, p, r, cGrp, flags, opt );
594       else
595         PARENT_STYLE::drawPrimitive( flags & Style_Raised ? PE_ButtonDropDown : pe, p, r, cGrp, flags, opt );
596     }
597     break;
598
599   default:
600     PARENT_STYLE::drawPrimitive( pe, p, r, cg, flags, opt );
601     break;
602   }
603 }
604
605 /*!
606   Draws control element
607   \param element - type of control element
608   \param p - painter
609   \param widget - widget
610   \param r - rect
611   \param cg - group of colors
612   \param flags - is used to control how the element is drawn
613   \param opt - can be used to control how various elements are drawn
614 */
615 void SalomeStyle::drawControl( ControlElement element, QPainter* p, const QWidget* widget, const QRect& r,
616                                const QColorGroup& cg, SFlags flags, const QStyleOption& opt ) const 
617 {
618   switch( element )
619   {
620     case CE_PopupMenuItem:
621     {
622           if(! widget || opt.isDefault())
623             break;
624
625       const QPopupMenu *popupmenu = (const QPopupMenu *) widget;
626       QMenuItem *mi = opt.menuItem();
627       if( !mi )
628             break;
629
630           int tab = opt.tabWidth();
631           int maxpmw = opt.maxIconWidth();
632           bool dis = !( flags & Style_Enabled );
633           bool checkable = popupmenu->isCheckable();
634           bool act = flags & Style_Active;
635       bool use2000style = true;
636           int x, y, w, h;
637
638       int windowsItemFrame = 2,
639           windowsItemHMargin = 5,
640           windowsItemVMargin = 1,
641           windowsRightBorder = 2,
642           windowsArrowHMargin = 2;
643
644           r.rect(&x, &y, &w, &h);
645
646           if ( checkable )
647       {
648             // space for the checkmarks
649         if (use2000style)
650                   maxpmw = QMAX( maxpmw, 20 );
651                 else
652                   maxpmw = QMAX( maxpmw, 12 );
653           }
654
655           int checkcol = maxpmw;
656
657           if ( mi && mi->isSeparator() )
658       {
659                 p->setPen( cg.dark() );
660                 p->drawLine( x+3*checkcol/2, y, x+w, y );
661                 //p->setPen( cg.light() );
662                 //p->drawLine( x, y+1, x+w, y+1 );
663                 return;
664           }
665
666       QBrush fill = ( act && !dis ?
667                  cg.brush( QColorGroup::Highlight ) :
668                          cg.brush( QColorGroup::Light ) );
669           p->fillRect( x, y, w, h, fill );
670
671           if( !mi )
672                 return;
673
674           int xpos = x;
675           QRect vrect = visualRect( QRect( xpos, y, checkcol, h ), r );
676           int xvis = vrect.x();
677
678           if( mi->isChecked() )
679       {
680             if( act && !dis )
681                   qDrawShadePanel( p, xvis, y, checkcol, h,
682                            cg, TRUE, 1, &cg.brush( QColorGroup::Button ) );
683                 else
684         {
685                   QBrush fill( cg.light(), Dense4Pattern );
686                   // set the brush origin for the hash pattern to the x/y coordinate
687                   // of the menu item's checkmark... this way, the check marks have
688                   // a consistent look
689                   QPoint origin = p->brushOrigin();
690                   p->setBrushOrigin( xvis, y );
691                   qDrawShadePanel( p, xvis, y, checkcol, h, cg, TRUE, 1, &fill );
692           // restore the previous brush origin
693                   p->setBrushOrigin( origin );
694                 }
695           }
696       else if( !act )
697                 p->fillRect(x+checkcol, y, w-checkcol , h, cg.brush( QColorGroup::Light ));
698
699       if( !( act && !dis ) && !mi->isChecked() )
700       {
701         QColor col; mix( 0.5, cg.mid(), Qt::white, col );
702         drawGradient( p, QRect( xvis, y, checkcol, h+1 ), cg.light(), col, LeftToRight, linear );
703       }
704
705       if( mi->iconSet() )
706       { // draw iconset
707                 QIconSet::Mode mode = dis ? QIconSet::Active : QIconSet::Normal;
708                 if(act && !dis )
709                   mode = QIconSet::Active;
710                 QPixmap pixmap;
711                 if( checkable && mi->isChecked() )
712                   pixmap = mi->iconSet()->pixmap( QIconSet::Small, mode, QIconSet::On );
713                 else
714                   pixmap = mi->iconSet()->pixmap( QIconSet::Small, mode );
715                 int pixw = pixmap.width();
716                 int pixh = pixmap.height();
717
718         if( dis )
719           toGrayscale( pixmap, 1.1 );
720
721                 //if( act && !dis && !mi->isChecked() )
722                 //  qDrawShadePanel( p, xvis, y, checkcol, h, cg, FALSE, 1, &cg.brush( QColorGroup::Button ) );
723
724                 QRect pmr( 0, 0, pixw, pixh );
725                 pmr.moveCenter( vrect.center() );
726                 p->setPen( cg.text() );
727                 p->drawPixmap( pmr.topLeft(), pixmap );
728
729                 QBrush fill = ( act ? cg.brush( QColorGroup::Highlight ) : cg.brush( QColorGroup::Light ));
730                 int xp = xpos + checkcol + 1;
731         if( !dis )
732                   p->fillRect( visualRect( QRect( xp, y, w - checkcol - 1, h ), r ), fill);
733           }
734       else if( checkable )
735       {  // just "checking"...
736                 if( mi->isChecked() )
737         {
738                   int xp = xpos + windowsItemFrame;
739
740                   SFlags cflags = Style_Default;
741                   if( !dis )
742                     cflags |= Style_Enabled;
743                   if( act )
744                         cflags |= Style_On;
745
746                   drawPrimitive( PE_CheckMark, p,
747                                          visualRect( QRect( xp, y + windowsItemFrame,
748                                              checkcol - 2*windowsItemFrame,
749                                              h - 2*windowsItemFrame), r ), cg, cflags, opt );
750                 }
751           }
752
753           p->setPen( act ? cg.highlightedText() : cg.buttonText() );
754
755           QColor discol;
756           if( dis )
757       {
758                 discol = cg.text();
759                 p->setPen( discol );
760           }
761
762           int xm = windowsItemFrame + checkcol + windowsItemHMargin;
763           xpos += xm;
764
765           vrect = visualRect( QRect( xpos, y+windowsItemVMargin, w-xm-tab+1, h-2*windowsItemVMargin ), r );
766           xvis = vrect.x();
767           if( mi->custom() )
768       {
769                 p->save();
770                 if ( dis && !act )
771         {
772                   p->setPen( cg.light() );
773                   mi->custom()->paint( p, cg, act, !dis,
774                                                    xvis+1, y+windowsItemVMargin+1,
775                                w-xm-tab+1, h-2*windowsItemVMargin );
776                   p->setPen( discol );
777                 }
778                 mi->custom()->paint( p, cg, act, !dis, xvis, y+windowsItemVMargin,
779                              w-xm-tab+1, h-2*windowsItemVMargin );
780                 p->restore();
781           }
782           QString s = mi->text();
783           if( !s.isNull() )
784       { // draw text
785                 int t = s.find( '\t' );
786                 int text_flags = AlignVCenter | ShowPrefix | DontClip | SingleLine;
787                 if( !styleHint( SH_UnderlineAccelerator, widget ) )
788                   text_flags |= NoAccel;
789                 text_flags |= (QApplication::reverseLayout() ? AlignRight : AlignLeft );
790                 if( t >= 0 )
791         { // draw tab text
792                   int xp = x + w - tab - windowsItemHMargin - windowsItemFrame + 1;
793                   if( use2000style )
794                     xp -= 20;
795                   else
796                         xp -= windowsRightBorder;
797                   int xoff = visualRect( QRect( xp, y+windowsItemVMargin, tab, h-2*windowsItemVMargin ), r ).x();
798                   if( dis && !act )
799           {
800                         p->setPen( cg.light() );
801                         p->drawText( xoff+1, y+windowsItemVMargin+1, tab, h-2*windowsItemVMargin, text_flags, s.mid( t+1 ));
802                         p->setPen( discol );
803                   }
804                   p->drawText( xoff, y+windowsItemVMargin, tab, h-2*windowsItemVMargin, text_flags, s.mid( t+1 ) );
805                   s = s.left( t );
806                 }
807                 if( dis && !act )
808         {
809                   p->setPen( cg.light() );
810                   p->drawText( xvis+1, y+windowsItemVMargin+1, w-xm-tab+1, h-2*windowsItemVMargin, text_flags, s, t );
811                   p->setPen( discol );
812                 }
813                 p->drawText( xvis, y+windowsItemVMargin, w-xm-tab+1, h-2*windowsItemVMargin, text_flags, s, t );
814           }
815       else if( mi->pixmap() )
816       { // draw pixmap
817                 QPixmap *pixmap = mi->pixmap();
818                 if( pixmap->depth() == 1 )
819                   p->setBackgroundMode( OpaqueMode );
820                 p->drawPixmap( xvis, y+windowsItemFrame, *pixmap );
821                 if( pixmap->depth() == 1 )
822                   p->setBackgroundMode( TransparentMode );
823           }
824           if( mi->popup() )
825       { // draw sub menu arrow
826                 int dim = (h-2*windowsItemFrame) / 2;
827                 PrimitiveElement arrow;
828                 arrow = ( QApplication::reverseLayout() ? PE_ArrowLeft : PE_ArrowRight );
829                 xpos = x+w - windowsArrowHMargin - windowsItemFrame - dim;
830                 vrect = visualRect( QRect(xpos, y + h / 2 - dim / 2, dim, dim), r );
831                 if( act )
832         {
833                   QColorGroup g2 = cg;
834                   g2.setColor( QColorGroup::ButtonText, g2.highlightedText() );
835                   drawPrimitive( arrow, p, vrect, g2, dis ? Style_Default : Style_Enabled, opt );
836                 }
837         else
838         {
839                   drawPrimitive( arrow, p, vrect, cg, dis ? Style_Default : Style_Enabled, opt );
840                 }
841           }
842
843       if( act && !dis )
844       {
845         p->setPen( cg.dark() );
846         p->drawRect( r );
847       }
848           break;
849     }
850
851     case CE_MenuBarItem:
852         {
853       bool active = flags & Style_Active;
854           bool down = flags & Style_Down;
855           QRect pr = r;
856
857       p->save();
858       if( active && down )
859       {
860         //QColor col; mix( 0.5, cg.mid(), Qt::white, col );
861         //drawGradient( p, r, col, cg.light(), UpToDown, linear );
862         p->setPen( cg.light() );
863         p->setBrush( cg.light() );
864         p->drawRect( r );
865         
866         p->setPen( cg.dark() );
867         int w = r.width()-1, h = r.height();
868         p->drawLine( r.x(), r.y(), r.x()+w, r.y() );
869         p->drawLine( r.x(), r.y(), r.x(), r.y()+h );
870         p->drawLine( r.x()+w, r.y(), r.x()+w, r.y()+h );
871
872         p->translate( 1, 1 );
873       }
874       else
875         drawGradient( p, r, cg.light(), cg.background(), active ? DownToUp : UpToDown, linear );
876
877           QCommonStyle::drawControl(element, p, widget, pr, cg, flags, opt);
878       p->restore();
879           break;
880         }
881
882     case CE_MenuBarEmptyArea:
883     {
884       drawGradient( p, r, cg.light(), cg.background(), UpToDown, linear );
885           break;
886     }
887
888     case CE_ToolButtonLabel:
889         {
890       const QToolButton *toolbutton = (const QToolButton *) widget;
891       QObject* parent = toolbutton->parent();
892
893       QToolBar* tb = NULL;
894       while( parent )
895         if( parent->inherits( "QToolBar" ) )
896         {
897           tb = ( QToolBar* )parent;
898           break;
899         }
900         else
901           parent = parent->parent();
902       parent = toolbutton->parent();
903
904       int horiz = -1;
905       if( tb )
906       {
907         if( tb->orientation()==Qt::Horizontal )
908           horiz = 1;
909         else
910           horiz = 0;
911         drawGradient( p, r, cg.light(), cg.background(), horiz ? UpToDown : LeftToRight, linear );
912       }
913       else if( parent->inherits( "QDockWindowHandle" ) )
914       {
915         QWidget* w = ( QWidget* ) parent;
916         QDockWindow* wnd = ( QDockWindow* )w->parent();
917         if( !wnd->orientation()==Qt::Horizontal )
918           horiz=1;
919         else
920           horiz=0;
921
922         QPoint pp( r.x(), r.y() ),
923                qq = toolbutton->mapToParent( pp );
924         
925         bitBlt( p->device(), r.x(), r.y(), w, horiz ? qq.x()-r.width() : qq.x(),
926                 horiz ? qq.y() : qq.y()+r.height(),
927                 r.width(), r.height(), Qt::CopyROP, true );
928       }
929
930       bool highlight = ( flags & Style_MouseOver ),
931            down = ( flags & ( Style_Down | Style_On ) ),
932            en = toolbutton->isEnabled();
933
934       if( down )
935         if( horiz>=0 )
936         {
937           drawGradient( p, r, cg.light(), cg.background(), horiz==1 ? DownToUp : RightToLeft, linear );
938           p->setPen( cg.background() );
939           p->drawRect( r );
940         }
941         else
942         {
943           p->setPen( cg.dark() );
944           p->setBrush( cg.light() );
945           p->drawRect( r );
946         }
947       if( highlight )
948       {
949         p->setPen( cg.dark() );
950         QColor col; mix( 0.05, cg.background(), Qt::black, col );
951         p->setBrush( col );
952         p->drawRect( r );
953       }
954
955
956           QRect rect = r;
957           Qt::ArrowType arrowType = opt.isDefault() ? Qt::DownArrow : opt.arrowType();
958
959           int shiftX = 0, shiftY = 0;
960           if( flags & ( Style_Down | Style_On ) )
961       {
962                 shiftX = pixelMetric(PM_ButtonShiftHorizontal, widget);
963                 shiftY = pixelMetric(PM_ButtonShiftVertical, widget);
964           }
965
966           if (!opt.isDefault())
967       {
968                 PrimitiveElement pe;
969                 switch (arrowType)
970         {
971                   case Qt::LeftArrow:  pe = PE_ArrowLeft;  break;
972                   case Qt::RightArrow: pe = PE_ArrowRight; break;
973                   case Qt::UpArrow:    pe = PE_ArrowUp;    break;
974                   default:
975                   case Qt::DownArrow:  pe = PE_ArrowDown;  break;
976         }
977
978         rect.moveBy(shiftX, shiftY);
979             drawPrimitive(pe, p, rect, cg, flags, opt);
980           }
981       else
982       {
983                 QColor btext = toolbutton->paletteForegroundColor();
984
985                 if (toolbutton->iconSet().isNull() &&
986                     ! toolbutton->text().isNull() &&
987                     ! toolbutton->usesTextLabel())
988         {
989                     int alignment = AlignCenter | ShowPrefix;
990                     if (!styleHint(SH_UnderlineAccelerator, widget, QStyleOption::Default, 0))
991                           alignment |= NoAccel;
992
993                     rect.moveBy(shiftX, shiftY);
994                     drawItem( p, rect, alignment, cg, flags & Style_Enabled, 0, toolbutton->text(),
995                                   toolbutton->text().length(), &btext);
996         }
997         else
998         {
999               QPixmap pm;
1000                   QIconSet::Size size =
1001                   toolbutton->usesBigPixmap() ? QIconSet::Large : QIconSet::Small;
1002                   QIconSet::State state = toolbutton->isOn() ? QIconSet::On : QIconSet::Off;
1003                   QIconSet::Mode mode;
1004                   if( !toolbutton->isEnabled() )
1005                 mode = QIconSet::Active; //QIconSet::Disabled;
1006                   else if( flags & (Style_Down | Style_On ) || ( flags & Style_Raised ) && (flags & Style_AutoRaise))
1007                     mode = QIconSet::Active;
1008                   else
1009                     mode = QIconSet::Normal;
1010                   pm = toolbutton->iconSet().pixmap( size, mode, state );
1011
1012                   if( toolbutton->usesTextLabel() )
1013           {
1014                     p->setFont( toolbutton->font() );
1015                     QRect pr = rect, tr = rect;
1016                     int alignment = ShowPrefix;
1017                     if (!styleHint(SH_UnderlineAccelerator, widget, QStyleOption::Default, 0))
1018                           alignment |= NoAccel;
1019
1020                     if( toolbutton->textPosition() == QToolButton::Under )
1021             {
1022                           int fh = p->fontMetrics().height();
1023                           pr.addCoords( 0, 1, 0, -fh-3 );
1024                           tr.addCoords( 0, pr.bottom(), 0, -3 );
1025                           pr.moveBy(shiftX, shiftY);
1026                           drawItem( p, pr, AlignCenter, cg, TRUE, &pm, QString::null );
1027                           alignment |= AlignCenter;
1028             }
1029             else
1030             {
1031                           pr.setWidth( pm.width() + 8 );
1032                           tr.addCoords( pr.right(), 0, 0, 0 );
1033                           pr.moveBy(shiftX, shiftY);
1034  
1035                           drawItem( p, pr, AlignCenter, cg, TRUE, &pm, QString::null );
1036                           alignment |= AlignLeft | AlignVCenter;
1037             }
1038
1039                 tr.moveBy(shiftX, shiftY);
1040                     drawItem( p, tr, alignment, cg, flags & Style_Enabled, 0, toolbutton->textLabel(),
1041                                       toolbutton->textLabel().length(), &btext);
1042           }
1043           else
1044           {
1045             /*if( en && !highlight )
1046               mix( 0.6, pm, cg.background() );
1047             else*/ if( !en )
1048             {
1049               toGrayscale( pm, 1.1 );
1050               mix( 0.8, pm, cg.background() );
1051             }
1052
1053                     rect.moveBy(shiftX, shiftY);
1054                     drawItem( p, rect, AlignCenter, cg, true, &pm, QString::null );
1055           }
1056         }
1057       }
1058     }
1059     break;
1060
1061     case CE_TabBarTab:
1062           {
1063       QPen oldPen = p->pen();
1064
1065             QRect r2( r );
1066             bool selected = flags & Style_Selected;
1067
1068       p->setPen( cg.midlight() );
1069       p->drawLine( r2.left(), r2.bottom(), r2.right(), r2.bottom() );
1070
1071       if ( !selected )
1072         r2.setRect( r2.left(), r2.top() + 1, r2.width(), r2.height() - 1 );
1073       else
1074         r2.setRect( r2.left(), r2.top(), r2.width() - 2, r2.height() - 1 );
1075
1076       p->setPen( cg.foreground() );
1077       drawGradient( p, QRect( r2.left(), r2.top(), r2.width(), r2.height() - 1 ),
1078                     selected ? cg.highlight() : cg.dark(), cg.background(), UpToDown, linear );
1079
1080 //      p->fillRect( r2.left(), r2.top(), r2.width(), r2.height() - 1, selected ? cg.highlight() : cg.background() );
1081       p->drawRect( r2.left(), r2.top(), r2.width(), r2.height() - 1 );
1082
1083       if ( selected )
1084       {
1085         p->setPen( cg.shadow() );
1086         p->drawLine( r2.left() + 1, r2.bottom(), r2.right() + 1, r2.bottom() );
1087         p->drawLine( r2.right() + 1, r2.top() + 1, r2.right() + 1, r2.bottom() );
1088       }
1089
1090             break;
1091     }
1092
1093     case CE_TabBarLabel:
1094       {
1095         QColorGroup tmp( cg );
1096         if ( flags & Style_Selected )
1097           tmp.setColor( QColorGroup::Foreground, tmp.highlightedText() );
1098         PARENT_STYLE::drawControl( element, p, widget, r, tmp, flags, opt );
1099       }
1100       break;
1101
1102     case CE_PushButton:
1103           {
1104       if ( flags & Style_Enabled && !( flags & Style_Down || flags & Style_On ) )
1105       {
1106               const QPushButton* button = (const QPushButton*)widget;
1107         QRect br = QRect( button->mapToGlobal( button->rect().topLeft() ), button->rect().size() );
1108         if ( br.contains( QCursor::pos() )  )
1109           flags |= Style_MouseOver;
1110       }
1111
1112       PARENT_STYLE::drawControl( element, p, widget, r, cg, flags, opt );
1113             break;
1114           }
1115
1116     default:
1117       PARENT_STYLE::drawControl( element, p, widget, r, cg, flags, opt );
1118       break;
1119   }
1120 }
1121
1122 /*!
1123   \return the sub-area for the widget in logical coordinates
1124   \param subrect - type of sub area
1125   \param w - widget
1126 */
1127 QRect SalomeStyle::subRect( SubRect subrect, const QWidget* w ) const
1128 {
1129   QRect r = PARENT_STYLE::subRect( subrect, w );
1130   if ( subrect==SR_DockWindowHandleRect && w->inherits( "QDockWindowHandle" ) )
1131   {
1132     QDockWindow* wnd = ( QDockWindow* ) w->parent();
1133     if( wnd->orientation()==Qt::Vertical )
1134       r.setWidth( w->width() );
1135     else
1136     {
1137       r.setY( r.y()+r.height()-w->height() );
1138       r.setHeight( w->height() );
1139     }
1140   }
1141
1142   return r;
1143 }
1144
1145 /*!
1146   Draws the ComplexControl
1147   \param control - type of complex control element
1148   \param p - painter
1149   \param widget - widget
1150   \param r - rect
1151   \param cg - group of colors
1152   \param flags, controls, active - is used to control how the element is drawn
1153   \param opt - can be used to control how various elements are drawn
1154 */
1155 void SalomeStyle::drawComplexControl( ComplexControl control, QPainter* p, const QWidget* widget,
1156                                                               const QRect& r, const QColorGroup& cg, SFlags flags,
1157                                                               SCFlags controls, SCFlags active, const QStyleOption& opt ) const
1158 {
1159
1160
1161
1162
1163   ((SalomeStyle*)this)->myTitleParent = 0;
1164
1165   switch ( control )
1166   {
1167   case CC_ComboBox:
1168           if ( controls & SC_ComboBoxArrow )
1169     {
1170             SFlags flags = Style_Default;
1171
1172       qDrawShadeRect( p, r, cg, true, pixelMetric( PM_DefaultFrameWidth, widget ),
1173                       0, widget->isEnabled() ? &cg.brush( QColorGroup::Base ) : &cg.brush( QColorGroup::Background ) );
1174
1175             QRect ar = QStyle::visualRect( querySubControlMetrics( CC_ComboBox, widget, SC_ComboBoxArrow ), widget );
1176             if ( active == SC_ComboBoxArrow )
1177       {
1178                     p->setPen( cg.dark() );
1179                     p->setBrush( cg.brush( QColorGroup::Button ) );
1180                     p->drawRect( ar );
1181             }
1182       else
1183                     qDrawWinPanel( p, ar, cg, FALSE, &cg.brush( QColorGroup::Button ) );
1184
1185             ar.addCoords( 2, 2, -2, -2 );
1186             if ( widget->isEnabled() )
1187                     flags |= Style_Enabled;
1188
1189             if ( active == SC_ComboBoxArrow )
1190                     flags |= Style_Sunken;
1191             drawPrimitive( PE_ArrowDown, p, ar, cg, flags );
1192           }
1193     PARENT_STYLE::drawComplexControl( control, p, widget, r, cg, flags, controls & ~SC_ComboBoxArrow, active, opt );
1194     break;
1195
1196   case CC_TitleBar:
1197     if( widget->inherits( "QTitleBar" ) )
1198       ( ( SalomeStyle* )this )->myTitleParent = ( QWidget* )widget->parent();
1199
1200   default:
1201     PARENT_STYLE::drawComplexControl( control, p, widget, r, cg, flags, controls, active, opt );
1202     break;
1203   }
1204 }
1205
1206 /*!
1207   \return pixmap by type
1208   \param st - type of pixmap
1209   \param w - widget
1210   \param opt - style option flags
1211 */
1212 QPixmap SalomeStyle::stylePixmap( StylePixmap st, const QWidget* w, const QStyleOption& opt ) const
1213 {
1214   switch ( st )
1215   {
1216   case SP_DockWindowCloseButton:
1217   case SP_TitleBarCloseButton:
1218     return QPixmap( cross_xpm );
1219   case SP_TitleBarMaxButton:
1220     return QPixmap( maximize_xpm );
1221   case SP_TitleBarNormalButton:
1222     return QPixmap( normal_xpm );
1223   case SP_TitleBarMinButton:
1224     return QPixmap( minimize_xpm );
1225   default:
1226     return PARENT_STYLE::stylePixmap( st, w, opt );
1227   }
1228 }
1229
1230 /*!
1231   \return the pixel size
1232   \param pm - type of pixel metrics
1233   \param widget - widget
1234 */
1235 int SalomeStyle::pixelMetric( PixelMetric pm, const QWidget* widget ) const
1236 {
1237   int ret = 0;
1238
1239   switch ( pm )
1240   {
1241   case PM_ButtonMargin:
1242     ret = 5;
1243     break;
1244   case PM_DockWindowFrameWidth:
1245     ret = 0;
1246     break;
1247   case PM_TabBarTabOverlap:
1248           ret = 2;
1249           break;
1250   case PM_TabBarTabHSpace:
1251           ret = 20;
1252           break;
1253   case PM_TabBarTabShiftHorizontal:
1254   case PM_TabBarTabShiftVertical:
1255           ret = 0;
1256           break;
1257   case PM_TabBarTabVSpace:
1258                 ret = 5;
1259     break;
1260   case PM_DefaultFrameWidth:
1261     ret = 1;
1262     break;
1263   case PM_SpinBoxFrameWidth:
1264     ret = 1;
1265     break;
1266   case PM_ProgressBarChunkWidth:
1267     ret = 1;
1268     break;
1269   default:
1270     ret = PARENT_STYLE::pixelMetric( pm, widget );
1271     break;
1272   }
1273   return ret;
1274 }
1275
1276 /*!
1277   \return corrected title text
1278   \param txt - title text
1279   \param w - possible width
1280   \param fm - font metrics
1281 */
1282 QString SalomeStyle::titleText( const QString& txt, const int W, const QFontMetrics& fm ) const
1283 {
1284   QString res = txt.stripWhiteSpace();
1285
1286   if ( fm.width( res ) > W )
1287   {
1288     QString end( "..." );
1289     while ( !res.isEmpty() && fm.width( res + end ) > W )
1290       res.remove( res.length() - 1, 1 );
1291
1292     if ( !res.isEmpty() )
1293       res += end;
1294   }
1295
1296   return res;
1297 }
1298
1299 /*!
1300     Class: SalomeStylePlugin [Internal]
1301     Constructor
1302 */
1303 SalomeStylePlugin::SalomeStylePlugin()
1304 {
1305 }
1306
1307 /*!
1308   Destructor
1309 */
1310 SalomeStylePlugin::~SalomeStylePlugin()
1311 {
1312 }
1313
1314 /*!
1315   \return keys of styles of plugin
1316 */
1317 QStringList SalomeStylePlugin::keys() const
1318 {
1319   return QStringList() << "salome";
1320 }
1321
1322 /*!
1323   \return just created style 
1324   \param str - style key
1325 */
1326 QStyle* SalomeStylePlugin::create( const QString& str )
1327 {
1328   if ( str == "salome" )
1329     return new SalomeStyle();
1330   else
1331     return 0;
1332 }
1333
1334 Q_EXPORT_PLUGIN( SalomeStylePlugin )