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