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