Improved icons (brighter braces).
[kdbg.git] / STabCtl / stabbar.cpp
blob01ec4361407af99e3eb4f527a35e7f40a8ec8704
1 /***************************************************************************
2 STabCtl part of KDEStudio
3 -------------------
4 copyright : (C) 1999 by Judin Maximus
5 email : novaprint@mtu-net.ru
6 ***************************************************************************/
8 #include "stabbar.h"
10 #include <qapp.h>
11 #include <qwmatrix.h>
12 #include <qpushbutton.h>
13 #include <qpainter.h>
16 BarPainter::BarPainter( STabBar* parent )
17 :QWidget( parent )
19 delta = 0;
20 buffer = new QPixmap(0,0);
23 BarPainter::~BarPainter()
25 delete buffer;
28 void BarPainter::paintEvent( QPaintEvent* )
30 if ( buffer->isNull() ) return;
31 drawBuffer();
33 switch ( ((STabBar*)parent())->tabPos )
34 case STabBar::TAB_TOP:{
35 bitBlt( this, 0, 0, buffer, 0, 0, width(), height() );
36 break;
37 case STabBar::TAB_RIGHT:{
38 QWMatrix m;
39 m.rotate( -90 );
40 QPixmap xbuffer = buffer->xForm(m);
41 bitBlt( this, 0, 0, &xbuffer, 0, 0, width(), height() );
42 break;
47 void BarPainter::resizeEvent( QResizeEvent * )
49 delete buffer;
50 switch ( ((STabBar*)parent())->tabPos )
51 case STabBar::TAB_TOP:{
52 buffer = new QPixmap( width(), height() );
53 break;
54 case STabBar::TAB_RIGHT:{
55 buffer = new QPixmap( height(), width() );
56 break;
61 void BarPainter::drawBuffer()
63 QColor c1 = white;
64 QColor c2 = colorGroup().dark();
65 QColor c4 = white; // for paint top line;
67 int W = 0;
68 int H = 0;
69 int shadowX = 1;
70 int shadowY = 1;
71 switch ( ((STabBar*)parent())->tabPos )
72 case STabBar::TAB_TOP:{
73 W = width();
74 H = height();
75 break;
76 case STabBar::TAB_RIGHT:{
77 shadowX = -1;
78 c1 = colorGroup().dark();
79 c2 = white;
80 H = width();
81 W = height();
82 break;
86 QPainter paint;
87 paint.begin(buffer);
88 paint.setBrushOrigin(0,0);
89 QBrush bgBrush = colorGroup().brush(QColorGroup::Background);
90 paint.fillRect( 0, 0, W, H, bgBrush);
92 int x = 2;
93 int curTab = ((STabBar*)parent())->_currentTab;
94 int curTabNum = -1;
95 int leftTab = ((STabBar*)parent())->leftTab;
96 int curx = -1; // start current tab ( selected )
97 int curWidth = -1;
98 int broken = -1;
99 bool iconShow = ((STabBar*)parent())->iconShow;
101 QList<TabBarData> *mainData = ((STabBar*)parent())->mainData;
102 for ( uint k = 0; k < mainData->count(); k++ ){
103 int x1 = x;
104 int y1 = 2;
105 int width = mainData->at(k)->width;
107 if ( mainData->at(k)->id == curTab ){ // store current tab start x
108 curTabNum = k;
109 curx = x;
110 curWidth = width;
111 x1 -= 1;
112 y1 -= 1;
115 if ( mainData->at(k)->pix != 0L && iconShow ){
116 QWMatrix m;
117 switch ( ((STabBar*)parent())->tabPos )
118 case STabBar::TAB_TOP:{
119 break;
120 case STabBar::TAB_RIGHT:{
121 m.rotate( 90 );
122 break;
125 paint.drawPixmap( x1+ 11, y1 + 2 , mainData->at(k)->pix->xForm(m) );
128 int ty = ( H + fontMetrics().height() ) / 2 - 2;
129 int tx = ( mainData->at(k)->pix != 0L && iconShow ) ? 32:12;
131 paint.setFont( parentWidget()->font() );
133 if ( mainData->at(k)->enabled ){
134 paint.setPen( mainData->at(k)->textColor );
135 paint.drawText( x1 + tx , ty + y1 , mainData->at(k)->label );
136 } else {
137 paint.setPen( colorGroup().light() );
138 paint.drawText( x1 + tx + shadowX, ty + y1 + shadowY, mainData->at(k)->label );
139 paint.setPen( colorGroup().mid() );
140 paint.drawText( x1 + tx , ty + y1 , mainData->at(k)->label );
143 paint.setPen( c1 );
144 paint.moveTo( x1, H + 1 -y1 );
145 paint.lineTo( x1, y1 );
147 paint.setPen( c4 );
148 paint.lineTo( x1 + width - 1, y1 );
150 paint.setPen( c2 );
151 paint.lineTo( x1 + width - 1, H+1-y1 );
153 /***************************************************************/
154 paint.setPen( c1 );
155 paint.moveTo( x1 + 4, y1 + H - 5 );
156 paint.lineTo( x1 + 4, 3+y1 );
158 paint.moveTo( x1 + 7, y1 + H - 5 );
159 paint.lineTo( x1 + 7, 3+y1 );
161 paint.setPen( c2 );
162 paint.moveTo( x1 + 5, y1 + H - 5 );
163 paint.lineTo( x1 + 5, 3+y1 );
165 paint.moveTo( x1 + 8, y1 + H - 5 );
166 paint.lineTo( x1 + 8, 3+y1 );
167 /***************************************************************/
169 // fixed picture for leftTab
170 if ( leftTab == (int)k + 1 ){
171 paint.fillRect( x1 + width - 2, 0, 2, H - 1, bgBrush);
174 // paint broken left
175 if ( (int)k == leftTab && k != 0 )
177 int yy = y1;
178 int xx = x1 - 2;
179 paint.fillRect( x1, 0, 1, H - 1, bgBrush);
180 paint.setPen( c1 );
181 do {
182 paint.drawPoint( xx + 2, yy );
183 paint.drawPoint( xx + 1, yy + 1 );
184 paint.moveTo( xx + 1, yy + 1 );
185 paint.lineTo( xx + 1, yy + 3 );
186 paint.drawPoint( xx + 2, yy + 4 );
187 paint.lineTo( xx + 2, yy + 6 );
188 paint.drawPoint( xx + 3, yy + 7 );
189 paint.lineTo( xx + 3, yy + 9 );
190 paint.drawPoint( xx + 2, yy + 10 );
191 paint.drawPoint( xx + 2, yy + 11 );
192 yy+= 12;
193 } while ( yy < H );
196 x += width;
197 if ( x >= W && broken == -1 ) broken = k; // store right broken tab
200 // modify ( paint ) selected tab
201 if ( curx != -1 && curTabNum >= leftTab ){
202 curx -= 2;
203 curWidth += 4;
204 paint.setPen( c1 );
205 paint.moveTo( curx, H-1 );
206 paint.lineTo( curx, 0 );
207 paint.setPen( c4 );
208 paint.lineTo( curx + curWidth - 2, 0 );
210 paint.setPen( c2 );
211 paint.moveTo( curx + curWidth - 1, 0 );
212 paint.lineTo( curx + curWidth - 1, H-1 );
214 paint.fillRect( curx + 1, 1, 2, H - 1, bgBrush);
215 paint.fillRect( curx + curWidth - 4, 1, 3, H - 1, bgBrush);
216 paint.fillRect( curx + 1, 1, curWidth - 3, 2, bgBrush);
219 if ( curTabNum == leftTab && curTabNum != 0 )
221 int yy = 0;
222 int xx = curx;
223 paint.fillRect( curx, 0, 1, H - 1, bgBrush);
224 paint.setPen( c1 );
225 do {
226 paint.drawPoint( xx + 2, yy );
227 paint.drawPoint( xx + 1, yy + 1 );
228 paint.moveTo( xx + 1, yy + 1 );
229 paint.lineTo( xx + 1, yy + 3 );
230 paint.drawPoint( xx + 2, yy + 4 );
231 paint.lineTo( xx + 2, yy + 6 );
232 paint.drawPoint( xx + 3, yy + 7 );
233 paint.lineTo( xx + 3, yy + 9 );
234 paint.drawPoint( xx + 2, yy + 10 );
235 paint.drawPoint( xx + 2, yy + 11 );
236 yy+= 12;
237 } while ( yy < H );
240 // paint broken right
241 if ( broken != -1 )
243 int yy = broken == curTabNum ? 0:2;
244 int xx = W;
245 paint.fillRect( xx - 2, 0, 2, H - 1, bgBrush );
246 paint.fillRect( xx - 5, yy + 1, 5, H - 2 - yy, bgBrush );
247 paint.setPen( c2 );
248 do {
249 paint.drawPoint( xx - 2, yy );
250 paint.drawPoint( xx - 1, yy + 1 );
251 paint.moveTo( xx - 1, yy + 1 );
252 paint.lineTo( xx - 1, yy + 3 );
253 paint.drawPoint( xx - 2, yy + 4 );
254 paint.lineTo( xx - 2, yy + 6 );
255 paint.drawPoint( xx - 3, yy + 7 );
256 paint.lineTo( xx - 3, yy + 9 );
257 paint.drawPoint( xx - 2, yy + 10 );
258 paint.drawPoint( xx - 2, yy + 11 );
259 yy+= 12;
260 } while ( yy < H );
262 paint.end();
265 int BarPainter::findBarByPos( int x, int y )
267 int dx = 5; // overlaped
269 switch ( ((STabBar*)parent())->tabPos ){
270 case STabBar::TAB_TOP:
271 break;
272 case STabBar::TAB_RIGHT:
273 x = height() - y;
274 break;
277 STabBar* bar = (STabBar*)parent();
279 QList<TabBarData> *mainData = bar->mainData;
280 if ( mainData->isEmpty() ) return -1;
282 int end = 0;
283 int find = -1;
284 int findWidth = -1;
285 for ( uint k = 0; k < mainData->count(); k++ ){
286 end += mainData->at(k)->width;
287 if ( x < end ){
288 find = k;
289 findWidth = mainData->at(k)->width;
290 break;
294 int idCurTab = bar->_currentTab;
295 int curTab = -1;
296 for ( uint k = 0; k < mainData->count(); k++ )
297 if ( mainData->at(k)->id == idCurTab ){
298 curTab = k;
299 break;
302 // process first Tab manualy
303 if ( x < dx && curTab != mainData->at(0)->id ) return -1;
305 // process last Tab manyaly
306 if ( find == -1 )
307 if ( x < (end + dx) && curTab == (int)mainData->count() - 1 )
308 find = mainData->count() - 1;
310 if ( find == -1 ) return -1;
312 // process overlaped
313 if ( find > 0 )
314 if ( curTab == (find - 1) && x < (end - findWidth + dx ) ) find -= 1;
316 if ( find < (int)mainData->count() - 1 )
317 if ( curTab == (find + 1) && x > (end - dx ) ) find += 1;
319 return mainData->at(find)->id;
322 void BarPainter::mousePressEvent( QMouseEvent* e )
324 int cur = findBarByPos( e->x(), e->y() );
325 if ( e->button() == RightButton )
326 emit ((STabBar*)parent())->rightButtonPress( cur, e->globalPos() );
327 else
328 mousePressTab = cur;
331 void BarPainter::mouseReleaseEvent( QMouseEvent* e )
333 int cur = findBarByPos( e->x(), e->y() );
334 if ( cur != -1 && cur == mousePressTab ){
335 ((STabBar*)parent())->setCurrentTab( cur );
339 /***************************************************************************/
341 STabBar::STabBar( QWidget * parent, const char * name )
342 :QWidget( parent, name )
344 /* Set up bitmaps */
345 #include "b_left.xpm"
346 left_xpm = new QPixmap( b_left_xpm );
348 QWMatrix m;
349 m.scale( -1, 1 );
350 right_xpm = new QPixmap( left_xpm->xForm(m) );
352 m.reset();
353 m.rotate( 90 );
354 down_xpm = new QPixmap( left_xpm->xForm(m) );
356 m.reset();
357 m.scale( 1, -1 );
358 up_xpm = new QPixmap( down_xpm->xForm(m) );
359 /****************************************************************/
361 tabPos = TAB_TOP;
362 iconShow = true;
364 barPainter = new BarPainter( this );
365 move( 0, 0 );
367 mainData = new QList<TabBarData>;
368 mainData->setAutoDelete( true );
369 _currentTab = -1;
370 leftTab = 0;
372 left = new QPushButton(this); left->hide();
373 left->setAutoRepeat( true );
374 connect( left, SIGNAL(clicked()), SLOT( leftClicked()) );
375 right = new QPushButton(this); right->hide();
376 right->setAutoRepeat( true );
377 connect( right, SIGNAL(clicked()), SLOT( rightClicked()) );
379 setFixedHeight( fontMetrics().height() + 10 );
381 setButtonPixmap();
384 STabBar::~STabBar()
386 delete barPainter;
387 delete left;
388 delete right;
389 delete mainData;
392 void STabBar::paintEvent(QPaintEvent *)
394 QPainter paint;
395 paint.begin( this );
397 // find current ( selected ) tab data
398 TabBarData* data = 0L;
399 int curx = 2 - barPainter->delta;
400 int curWidth = 0;
401 for ( uint k = 0; k < mainData->count(); k++ ){
402 data = mainData->at(k);
403 if ( data->id == _currentTab ){
404 curWidth = data->width + 4 ;
405 curx -= 2;
406 break;
408 curx += data->width;
411 if ( curWidth == 0 ) curx = 0; // no tab selected
413 QBrush bgBrush = colorGroup().brush(QColorGroup::Background);
415 // paint button line
416 switch ( tabPos ){
417 case TAB_TOP:
418 paint.fillRect( 0, height()-1, width(), 1, bgBrush);
419 paint.setPen( white );
420 paint.moveTo( 0, height()-1 );
421 paint.lineTo( curx, height()-1 );
422 paint.moveTo( QMIN( curx + curWidth, width() - 50 ), height()-1 );
423 paint.lineTo( width() - 1, height()-1 );
424 break;
425 case TAB_RIGHT:
426 paint.fillRect( width() - 1, 0, 1, height(), bgBrush);
427 curx = height() - curx;
428 paint.setPen( colorGroup().dark() );
429 paint.drawPoint( width() - 1, height()-1 );
431 paint.moveTo( width() - 1, height()-2 );
432 paint.setPen( white );
433 if ( curx != height() ) paint.lineTo( width() - 1, curx );
434 paint.moveTo( width() - 1, QMAX( curx - curWidth, 50 ) );
435 paint.lineTo( width() - 1, 0 );
436 break;
438 paint.end();
439 barPainter->repaint( false );
442 int STabBar::insertTab( const QString &label, int id )
444 if ( id == -1 ){
445 id = 0;
446 for ( uint k = 0; k < mainData->count(); k++ )
447 if ( mainData->at(k)->id > id ) id = mainData->at(k)->id;
449 TabBarData* data = new TabBarData( id, label );
451 data->width = 4 + fontMetrics().width( label ) + 14;
452 mainData->append( data );
454 resizeEvent(0);
455 repaint( false );
456 return id;
459 void STabBar::showTabIcon( bool show )
461 if ( iconShow == show ) return;
462 iconShow = show;
463 updateHeight();
464 tabsRecreate();
467 TabBarData* STabBar::findData( int id )
469 TabBarData* data = 0L;
470 for ( uint k = 0; k < mainData->count(); k++ )
471 if ( mainData->at(k)->id == id ){
472 data = mainData->at(k);
473 break;
475 return data;
478 void STabBar::setPixmap( int id, const QPixmap &pix )
480 TabBarData* data = findData( id );
481 if ( data != 0L ){
482 if ( data->pix != 0L ) delete data->pix;
483 data->pix = new QPixmap( pix );
484 if ( iconShow ) data->width += 16 + 4;
485 tabsRecreate();
489 void STabBar::setTextColor( int id, const QColor &color )
491 TabBarData* data = findData( id );
492 if ( data != 0L ){
493 data->textColor = color;
494 repaint( false );
498 void STabBar::removeTab( int id )
500 TabBarData* data = findData( id );
501 if ( data != 0L ){
502 if ( _currentTab == data->id )
504 for ( uint k = 0; k < mainData->count(); k++ )
506 if ( mainData->at(k)->id == data->id ){
507 if ( mainData->count() == 1 ){
508 setCurrentTab( -1 );
509 } else {
510 setCurrentTab( mainData->at(k+1)->id );
512 break;
515 if ( mainData->at(k+1)->id == data->id ){
516 setCurrentTab( mainData->at(k)->id );
517 break;
521 mainData->remove( data );
522 resizeEvent(0);
523 repaint( false );
527 void STabBar::setCurrentTab( int id, bool allowDisable )
529 TabBarData* data = findData( id );
530 if ( data != 0L )
531 if ( (data->enabled || allowDisable ) && _currentTab != data->id )
533 _currentTab = data->id;
534 repaint( false );
536 int curx = 2;
537 for ( uint k = 0; k < mainData->count(); k++ ){
538 data = mainData->at(k);
539 if ( data->id == id ){
540 curx += 30;
541 break;
543 curx += data->width;
546 switch ( tabPos ){
547 case TAB_TOP:
548 while ( width() - 50 > 30 && ((-barPainter->delta + curx < 0) || (-barPainter->delta + curx > width() - 50)) ){
549 if ( -barPainter->delta + curx < 0 )
550 leftClicked();
551 else
552 rightClicked();
554 break;
555 case TAB_RIGHT:
556 while ( height() - 50 > 30 && ((-barPainter->delta + curx < 0) || (-barPainter->delta + curx > height() - 50)) ){
557 if ( -barPainter->delta + curx < 0 )
558 leftClicked();
559 else
560 rightClicked();
562 break;
564 emit tabSelected( id );
568 void STabBar::setTabEnabled( int id , bool enabled )
570 TabBarData* data = findData( id );
571 if ( data == 0L ) return;
573 if ( data->enabled != enabled )
575 data->enabled = enabled;
576 if ( _currentTab == data->id ){
577 for ( uint k = 0; k < mainData->count(); k++ ){
578 if ( mainData->at(k)->enabled ){
579 setCurrentTab( mainData->at(k)->id );
580 break;
584 if ( enabled ){
585 data = findData( _currentTab );
586 if ( !data->enabled ) setCurrentTab( id );
588 repaint( false );
592 bool STabBar::isTabEnabled( int id )
594 TabBarData* data = findData( id );
595 return data == 0L ? false:data->enabled;
598 void STabBar::show()
600 if ( _currentTab == 0 )
601 if ( !mainData->isEmpty() )
602 _currentTab = mainData->at(0)->id;
604 if ( _currentTab != 0 ){
605 setCurrentTab( _currentTab );
607 QWidget::show();
610 int STabBar::tabsWidth()
612 int width = 0;
613 for ( uint k = 0; k < mainData->count(); k++ ){
614 width += mainData->at(k)->width;
616 return width == 0 ? 0:width + 4;
619 void STabBar::resizeEvent(QResizeEvent *)
621 int maxAllowWidth = 0;
622 int maxAllowHeight = 0;
623 switch ( tabPos ){
624 case TAB_TOP:
625 if ( width() - 50 > tabsWidth() ){
626 barPainter->delta = 0;
627 leftTab = 0;
629 maxAllowWidth = width() - 50 + barPainter->delta;
630 barPainter->move( -barPainter->delta, 0 );
631 barPainter->resize( QMIN(tabsWidth(),maxAllowWidth), height() - 1 );
632 break;
633 case TAB_RIGHT:
634 if ( height() - 50 > tabsWidth() ){
635 barPainter->delta = 0;
636 leftTab = 0;
638 maxAllowHeight = height() - 50 + barPainter->delta;
639 barPainter->resize( width() - 1, QMIN(tabsWidth(),maxAllowHeight) );
640 barPainter->move( 0, height() - barPainter->height() + barPainter->delta );
641 break;
644 if ( tabPos == TAB_TOP ){
645 left->setGeometry( width()-2*18-2, height()-20, 18, 18 );
646 right->setGeometry( width()-18, height()-20, 18, 18 );
648 if ( barPainter->delta > 0 || tabsWidth() > maxAllowWidth ){
649 left->show();
650 right->show();
651 } else {
652 left->hide();
653 right->hide();
657 if ( tabPos == TAB_RIGHT ){
658 left->setGeometry( width()-20, 18+2, 18, 18 );
659 right->setGeometry( width()-20, 0, 18, 18 );
661 if ( barPainter->delta > 0 || tabsWidth() > maxAllowHeight ){
662 left->show();
663 right->show();
664 } else {
665 left->hide();
666 right->hide();
671 void STabBar::leftClicked()
673 if ( leftTab > 0 ){
674 leftTab--;
675 int dx = mainData->at( leftTab )->width;
676 barPainter->delta -= dx;
677 barPainter->move( barPainter->x() + dx, barPainter->y() );
678 resizeEvent(0);
679 repaint( false );
683 void STabBar::rightClicked()
685 if ( leftTab != (int)mainData->count() - 1 ){
686 int dx = mainData->at( leftTab )->width;
687 barPainter->delta += dx;
688 leftTab++;
689 barPainter->move( barPainter->x() - dx, barPainter->y() );
690 resizeEvent(0);
691 repaint( false );
695 void STabBar::setTabPos( TabPos pos )
697 tabPos = pos;
698 updateHeight();
699 setButtonPixmap();
700 tabsRecreate();
703 void STabBar::updateHeight()
705 switch ( tabPos ){
706 case TAB_TOP:
707 setMaximumWidth(32767);
708 if ( iconShow )
709 setFixedHeight( fontMetrics().height() + 10 );
710 else
711 setFixedHeight( fontMetrics().height() + 4 );
712 break;
713 case TAB_RIGHT:
714 setMaximumHeight(32767);
715 if ( iconShow )
716 setFixedWidth( fontMetrics().height() + 10 );
717 else
718 setFixedWidth( fontMetrics().height() + 4 );
719 break;
723 void STabBar::setButtonPixmap()
725 switch ( tabPos ){
726 case TAB_TOP:
727 left->setPixmap( *left_xpm );
728 right->setPixmap( *right_xpm );
729 break;
730 case TAB_RIGHT:
731 left->setPixmap( *up_xpm );
732 right->setPixmap( *down_xpm );
733 break;
737 void STabBar::setFont( const QFont &f )
739 QWidget::setFont( f );
740 tabsRecreate();
743 void STabBar::setTabCaption( int id, const QString &caption )
745 TabBarData* data = findData( id );
746 if ( data != 0L ){
747 data->label = caption;
748 tabsRecreate();
752 QString STabBar::tabCaption( int id )
754 TabBarData* data = findData( id );
755 return data == 0L ? QString(""):data->label;
758 void STabBar::tabsRecreate()
760 for ( uint k = 0; k < mainData->count(); k++ ){
761 TabBarData* data = mainData->at(k);
762 data->width = 4 + fontMetrics().width( data->label ) + 14;
763 if ( iconShow && data->pix != 0L ) data->width += 16 + 4;
765 resizeEvent(0);
766 repaint( false );
769 const QColor& STabBar::textColor( int id )
771 TabBarData* data = findData( id );
772 if ( data != 0L ){
773 return data->textColor;
775 return black;