KoTabBar.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003 Ariya Hidayat <ariya@kde.org>
3 Copyright (C) 2003 Norbert Andres <nandres@web.de>
4 Copyright (C) 2002 Laurent Montel <montel@kde.org>
5 Copyright (C) 1999 David Faure <faure@kde.org>
6 Copyright (C) 1999 Boris Wedl <boris.wedl@kfunigraz.ac.at>
7 Copyright (C) 1998-2000 Torben Weis <weis@kde.org>
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public License
20 along with this library; see the file COPYING.LIB. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23*/
24
25#include "KoTabBar.h"
26
27#include <tqdrawutil.h>
28#include <tqpainter.h>
29#include <tqstring.h>
30#include <tqstringlist.h>
31#include <tqstyle.h>
32#include <tqtimer.h>
33#include <tqtoolbutton.h>
34#include <tqvaluevector.h>
35#include <tqwidget.h>
36
37// TODO
38// improvement possibilities
39// - use offscreen buffer to reduce flicker even more
40// - keep track of tabs, only (re)layout when necessary
41// - paint all tabs to buffer, show only by shifting
42// - customizable button pixmaps
43// - use TQStyle to paint the tabs & buttons (is it good/possible?)
44
45
46class KoTabBarPrivate
47{
48public:
49 KoTabBar* tabbar;
50
51 // scroll buttons
52 TQToolButton* scrollFirstButton;
53 TQToolButton* scrollLastButton;
54 TQToolButton* scrollBackButton;
55 TQToolButton* scrollForwardButton;
56
57 // read-only: no mouse drag, double-click, right-click
58 bool readOnly;
59
60 // if true, layout is from right to left
61 bool reverseLayout;
62
63 // list of all tabs, in order of appearance
64 TQStringList tabs;
65
66 // array of TQRect for each visible tabs
67 TQValueVector<TQRect> tabRects;
68
69 // leftmost tab (or rightmost if reverseLayout)
70 int firstTab;
71
72 // rightmost tab (or leftmost if reverseLayout)
73 int lastTab;
74
75 // the active tab in the range form 1..n.
76 // if this value is 0, that means that no tab is active.
77 int activeTab;
78
79 // unusable space on the left, taken by the scroll buttons
80 int offset;
81
82 // when the user drag the tab (in order to move it)
83 // this is the target position, it's 0 if no tab is dragged
84 int targetTab;
85
86 // wheel movement since selected tab was last changed by the
87 // mouse wheel
88 int wheelDelta;
89
90 // true if autoscroll is active
91 bool autoScroll;
92
93 // calculate the bounding rectangle for each visible tab
94 void layoutTabs();
95
96 // reposition scroll buttons
97 void layoutButtons();
98
99 // find a tab whose bounding rectangle contains the pos
100 // return -1 if no such tab is found
101 int tabAt( const TQPoint& pos );
102
103 // draw a single tab
104 void drawTab( TQPainter& painter, TQRect& rect, const TQString& text, bool active );
105
106 // draw a marker to indicate tab moving
107 void drawMoveMarker( TQPainter& painter, int x, int y );
108
109 // update the enable/disable status of scroll buttons
110 void updateButtons();
111
112};
113
114// built-in pixmap for scroll-first button
115static const char * arrow_leftmost_xpm[] = {
116"10 10 2 1",
117" c None",
118". c #000000",
119" ",
120" . . ",
121" . .. ",
122" . ... ",
123" . .... ",
124" . ... ",
125" . .. ",
126" . . ",
127" ",
128" "};
129
130// built-in pixmap for scroll-last button
131static const char * arrow_rightmost_xpm[] = {
132"10 10 2 1",
133" c None",
134". c #000000",
135" ",
136" . . ",
137" .. . ",
138" ... . ",
139" .... . ",
140" ... . ",
141" .. . ",
142" . . ",
143" ",
144" "};
145
146// built-in pixmap for scroll-left button
147static const char * arrow_left_xpm[] = {
148"10 10 2 1",
149" c None",
150". c #000000",
151" ",
152" . ",
153" .. ",
154" ... ",
155" .... ",
156" ... ",
157" .. ",
158" . ",
159" ",
160" "};
161
162// built-in pixmap for scroll-right button
163static const char * arrow_right_xpm[] = {
164"10 10 2 1",
165" c None",
166". c #000000",
167" ",
168" . ",
169" .. ",
170" ... ",
171" .... ",
172" ... ",
173" .. ",
174" . ",
175" ",
176" "};
177
178
179void KoTabBarPrivate::layoutTabs()
180{
181 tabRects.clear();
182
183 TQPainter painter( tabbar );
184
185 TQFont f = painter.font();
186 f.setBold( true );
187 painter.setFont( f );
188 TQFontMetrics fm = painter.fontMetrics();
189
190 if( !reverseLayout )
191 {
192 // left to right
193 int x = 0;
194 for( unsigned c = 0; c < tabs.count(); c++ )
195 {
196 TQRect rect;
197 if( (int)c >= firstTab-1 )
198 {
199 TQString text = tabs[ c ];
200 int tw = fm.width( text ) + 4;
201 rect = TQRect( x, 0, tw + 20, tabbar->height() );
202 x = x + tw + 20;
203 }
204 tabRects.append( rect );
205 }
206
207 lastTab = tabRects.count();
208 for( unsigned i = 0; i < tabRects.count(); i++ )
209 if( tabRects[i].right()-10+offset > tabbar->width() )
210 {
211 lastTab = i;
212 break;
213 }
214 }
215 else
216 {
217 // right to left
218 int x = tabbar->width() - offset;
219 for( unsigned c = 0; c < tabs.count(); c++ )
220 {
221 TQRect rect;
222 if( (int)c >= firstTab-1 )
223 {
224 TQString text = tabs[ c ];
225 int tw = fm.width( text ) + 4;
226 rect = TQRect( x - tw - 20, 0, tw + 20, tabbar->height() );
227 x = x - tw - 20;
228 }
229 tabRects.append( rect );
230 }
231
232 lastTab = tabRects.count();
233 for( unsigned i = tabRects.count()-1; i>0; i-- )
234 if( tabRects[i].left() > 0 )
235 {
236 lastTab = i+1;
237 break;
238 }
239 }
240}
241
242int KoTabBarPrivate::tabAt( const TQPoint& pos )
243{
244 for( unsigned i = 0; i < tabRects.count(); i++ )
245 {
246 TQRect rect = tabRects[ i ];
247 if( rect.isNull() ) continue;
248 if( rect.contains( pos ) ) return i;
249 }
250
251 return -1; // not found
252}
253
254void KoTabBarPrivate::drawTab( TQPainter& painter, TQRect& rect, const TQString& text, bool active )
255{
256 TQPointArray polygon;
257
258 if( !reverseLayout )
259 polygon.setPoints( 6, rect.x(), rect.y(),
260 rect.x(), rect.bottom()-3,
261 rect.x()+2, rect.bottom(),
262 rect.right()-4, rect.bottom(),
263 rect.right()-2, rect.bottom()-2,
264 rect.right()+5, rect.top() );
265 else
266 polygon.setPoints( 6, rect.right(), rect.top(),
267 rect.right(), rect.bottom()-3,
268 rect.right()-2, rect.bottom(),
269 rect.x()+4, rect.bottom(),
270 rect.x()+2, rect.bottom()-2,
271 rect.x()-5, rect.top() );
272
273 painter.save();
274
275 // fill it first
276 TQBrush bg = tabbar->colorGroup().background();
277 if( active ) bg = TQBrush(tabbar->colorGroup().base());
278 painter.setBrush( bg );
279 painter.setPen( TQPen( TQt::NoPen ) );
280 painter.drawPolygon( polygon );
281
282 // draw the lines
283 painter.setPen( tabbar->colorGroup().dark() );
284 if( !active )
285 painter.drawLine( rect.x()-25, rect.y(), rect.right()+25, rect.top() );
286 painter.drawPolyline( polygon );
287
288 painter.setPen( tabbar->colorGroup().buttonText() );
289 TQFont f = painter.font();
290 if( active ) f.setBold( true );
291 painter.setFont( f );
292 TQFontMetrics fm = painter.fontMetrics();
293 int tx = rect.x() + ( rect.width() - fm.width( text ) ) / 2;
294 int ty = rect.y() + ( rect.height() - fm.height() ) / 2 + fm.ascent();
295 painter.drawText( tx, ty, text );
296
297 painter.restore();
298}
299
300void KoTabBarPrivate::drawMoveMarker( TQPainter& painter, int x, int y )
301{
302 TQPointArray movmark;
303 movmark.setPoints( 3, x, y, x + 7, y, x + 4, y + 6);
304 TQBrush oldBrush = painter.brush();
305 painter.setBrush( TQt::black );
306 painter.drawPolygon(movmark);
307 painter.setBrush( oldBrush );
308}
309
310void KoTabBarPrivate::layoutButtons()
311{
312 int bw = tabbar->height();
313 int w = tabbar->width();
314 offset = bw * 4;
315
316 if( !reverseLayout )
317 {
318 scrollFirstButton->setGeometry( 0, 0, bw, bw );
319 scrollFirstButton->setPixmap( arrow_leftmost_xpm );
320 scrollBackButton->setGeometry( bw, 0, bw, bw );
321 scrollBackButton->setPixmap( arrow_left_xpm );
322 scrollForwardButton->setGeometry( bw*2, 0, bw, bw );
323 scrollForwardButton->setPixmap( arrow_right_xpm );
324 scrollLastButton->setGeometry( bw*3, 0, bw, bw );
325 scrollLastButton->setPixmap( arrow_rightmost_xpm );
326 }
327 else
328 {
329 scrollFirstButton->setGeometry( w-bw, 0, bw, bw );
330 scrollFirstButton->setPixmap( arrow_rightmost_xpm );
331 scrollBackButton->setGeometry( w-2*bw, 0, bw, bw );
332 scrollBackButton->setPixmap( arrow_right_xpm );
333 scrollForwardButton->setGeometry( w-3*bw, 0, bw, bw );
334 scrollForwardButton->setPixmap( arrow_left_xpm );
335 scrollLastButton->setGeometry( w-4*bw, 0, bw, bw );
336 scrollLastButton->setPixmap( arrow_leftmost_xpm );
337 }
338 }
339
340void KoTabBarPrivate::updateButtons()
341{
342 scrollFirstButton->setEnabled( tabbar->canScrollBack() );
343 scrollBackButton->setEnabled( tabbar->canScrollBack() );
344 scrollForwardButton->setEnabled( tabbar->canScrollForward() );
345 scrollLastButton->setEnabled( tabbar->canScrollForward() );
346}
347
348// creates a new tabbar
349KoTabBar::KoTabBar( TQWidget* parent, const char* name )
350 : TQWidget( parent, name, TQt::WResizeNoErase | TQt::WRepaintNoErase )
351{
352 d = new KoTabBarPrivate;
353 d->tabbar = this;
354 d->readOnly = false;
355 d->reverseLayout = false;
356 d->firstTab = 1;
357 d->lastTab = 0;
358 d->activeTab = 0;
359 d->targetTab = 0;
360 d->wheelDelta = 0;
361 d->autoScroll = false;
362 d->offset = 64;
363
364 // initialize the scroll buttons
365 d->scrollFirstButton = new TQToolButton( this );
366 connect( d->scrollFirstButton, TQ_SIGNAL( clicked() ),
367 this, TQ_SLOT( scrollFirst() ) );
368 d->scrollLastButton = new TQToolButton( this );
369 connect( d->scrollLastButton, TQ_SIGNAL( clicked() ),
370 this, TQ_SLOT( scrollLast() ) );
371 d->scrollBackButton = new TQToolButton( this );
372 connect( d->scrollBackButton, TQ_SIGNAL( clicked() ),
373 this, TQ_SLOT( scrollBack() ) );
374 d->scrollForwardButton = new TQToolButton( this );
375 connect( d->scrollForwardButton, TQ_SIGNAL( clicked() ),
376 this, TQ_SLOT( scrollForward() ) );
377 d->layoutButtons();
378 d->updateButtons();
379}
380
381// destroys the tabbar
383{
384 delete d;
385}
386
387// adds a new visible tab
388void KoTabBar::addTab( const TQString& text )
389{
390 d->tabs.append( text );
391
392 update();
393}
394
395// removes a tab
396void KoTabBar::removeTab( const TQString& text )
397{
398 int i = d->tabs.findIndex( text );
399 if ( i == -1 ) return;
400
401 if ( d->activeTab == i + 1 )
402 d->activeTab = 0;
403
404 d->tabs.remove( text );
405
406 update();
407}
408
409// removes all tabs
411{
412 d->tabs.clear();
413 d->activeTab = 0;
414 d->firstTab = 1;
415
416 update();
417}
418
420{
421 return d->readOnly;
422}
423
425{
426 d->readOnly = ro;
427}
428
430{
431 return d->reverseLayout;
432}
433
434void KoTabBar::setReverseLayout( bool reverse )
435{
436 if( reverse != d->reverseLayout )
437 {
438 d->reverseLayout = reverse;
439 d->layoutTabs();
440 d->layoutButtons();
441 d->updateButtons();
442 update();
443 }
444}
445
446void KoTabBar::setTabs( const TQStringList& list )
447{
448 TQString left, active;
449
450 if( d->activeTab > 0 )
451 active = d->tabs[ d->activeTab-1 ];
452 if( d->firstTab > 0 )
453 left = d->tabs[ d->firstTab-1 ];
454
455 d->tabs = list;
456
457 if( !left.isNull() )
458 {
459 d->firstTab = d->tabs.findIndex( left ) + 1;
460 if( d->firstTab > (int)d->tabs.count() )
461 d->firstTab = 1;
462 if( d->firstTab <= 0 )
463 d->firstTab = 1;
464 }
465
466 d->activeTab = 0;
467 if( !active.isNull() )
468 setActiveTab( active );
469
470 update();
471}
472
473TQStringList KoTabBar::tabs() const
474{
475 return d->tabs;
476}
477
478unsigned KoTabBar::count() const
479{
480 return d->tabs.count();
481}
482
484{
485 if ( d->tabs.count() == 0 )
486 return false;
487
488 return d->firstTab > 1;
489}
490
492{
493 if ( d->tabs.count() == 0 )
494 return false;
495
496 return d->lastTab < (int)d->tabs.count();
497}
498
500{
501 if ( !canScrollBack() )
502 return;
503
504 d->firstTab--;
505 if( d->firstTab < 1 ) d->firstTab = 1;
506
507 d->layoutTabs();
508 d->updateButtons();
509 update();
510}
511
513{
514 if ( !canScrollForward() )
515 return;
516
517 d->firstTab ++;
518 if( d->firstTab > (int)d->tabs.count() )
519 d->firstTab = d->tabs.count();
520
521 d->layoutTabs();
522 d->updateButtons();
523 update();
524}
525
527{
528 if ( !canScrollBack() )
529 return;
530
531 d->firstTab = 1;
532 d->layoutTabs();
533 d->updateButtons();
534 update();
535}
536
538{
539 if ( !canScrollForward() )
540 return;
541
542 d->layoutTabs();
543
544 if( !d->reverseLayout )
545 {
546 int fullWidth = d->tabRects[ d->tabRects.count()-1 ].right();
547 int delta = fullWidth - width() + d->offset;
548 for( unsigned i = 0; i < d->tabRects.count(); i++ )
549 if( d->tabRects[i].x() > delta )
550 {
551 d->firstTab = i+1;
552 break;
553 }
554 }
555 else
556 {
557 // FIXME optimize this, perhaps without loop
558 for( ; d->firstTab <= (int)d->tabRects.count();)
559 {
560 int x = d->tabRects[ d->tabRects.count()-1 ].x();
561 if( x > 0 ) break;
562 d->firstTab++;
563 d->layoutTabs();
564 }
565 }
566
567 d->layoutTabs();
568 d->updateButtons();
569 update();
570}
571
572void KoTabBar::ensureVisible( const TQString& tab )
573{
574 int i = d->tabs.findIndex( tab );
575 if ( i == -1 )
576 return;
577 i++;
578
579 // already visible, then do nothing
580 if( ( i >= d->firstTab ) && ( i <= d->lastTab ) )
581 return;
582
583 if( i < d->firstTab )
584 while( i < d->firstTab )
585 scrollBack();
586
587 if( i > d->lastTab )
588 while( i > d->lastTab )
590}
591
592void KoTabBar::moveTab( unsigned tab, unsigned target )
593{
594 TQString tabName = d->tabs[ tab ];
595 TQStringList::Iterator it;
596
597 it = d->tabs.at( tab );
598 d->tabs.remove( it );
599
600 if( target > tab ) target--;
601 it = d->tabs.at( target );
602 if( target >= d->tabs.count() )
603 it = d->tabs.end();
604 d->tabs.insert( it, tabName );
605
606 if( d->activeTab == (int)tab+1 )
607 d->activeTab = target+1;
608
609 update();
610}
611
612void KoTabBar::setActiveTab( const TQString& text )
613{
614 int i = d->tabs.findIndex( text );
615 if ( i == -1 )
616 return;
617
618 if ( i + 1 == d->activeTab )
619 return;
620
621 d->activeTab = i + 1;
622 d->updateButtons();
623 update();
624
625 emit tabChanged( text );
626}
627
628void KoTabBar::autoScrollBack()
629{
630 if( !d->autoScroll ) return;
631
632 scrollBack();
633
634 if( !canScrollBack() )
635 d->autoScroll = false;
636 else
637 TQTimer::singleShot( 400, this, TQ_SLOT( autoScrollBack() ) );
638}
639
640void KoTabBar::autoScrollForward()
641{
642 if( !d->autoScroll ) return;
643
645
646 if( !canScrollForward() )
647 d->autoScroll = false;
648 else
649 TQTimer::singleShot( 400, this, TQ_SLOT( autoScrollForward() ) );
650}
651
652void KoTabBar::paintEvent( TQPaintEvent* )
653{
654 if ( d->tabs.count() == 0 )
655 {
656 erase();
657 return;
658 }
659
660 TQPainter painter;
661 TQPixmap pm( size() );
662 pm.fill( colorGroup().background() );
663 painter.begin( &pm, this );
664
665 painter.setPen( colorGroup().dark() );
666 painter.drawLine( 0, 0, width(), 0 );
667
668 if( !d->reverseLayout )
669 painter.translate( 5, 0 );
670
671 d->layoutTabs();
672 d->updateButtons();
673
674 // draw first all non-active, visible tabs
675 for( int c = d->tabRects.count()-1; c>=0; c-- )
676 {
677 TQRect rect = d->tabRects[ c ];
678 if( rect.isNull() ) continue;
679 TQString text = d->tabs[ c ];
680 d->drawTab( painter, rect, text, false );
681 }
682
683 // draw the active tab
684 if( d->activeTab > 0 )
685 {
686 TQRect rect = d->tabRects[ d->activeTab-1 ];
687 if( !rect.isNull() )
688 {
689 TQString text = d->tabs[ d->activeTab-1 ];
690 d->drawTab( painter, rect, text, true );
691 }
692 }
693
694 // draw the move marker
695 if( d->targetTab > 0 )
696 {
697 int p = TQMIN( d->targetTab, (int)d->tabRects.count() );
698 TQRect rect = d->tabRects[ p-1 ];
699 if( !rect.isNull() )
700 {
701 int x = !d->reverseLayout ? rect.x() : rect.right()-7;
702 if( d->targetTab > (int)d->tabRects.count() )
703 x = !d->reverseLayout ? rect.right()-7 : rect.x()-3;
704 d->drawMoveMarker( painter, x, rect.y() );
705 }
706 }
707
708 painter.end();
709
710 if( !d->reverseLayout )
711 bitBlt( this, d->offset, 0, &pm );
712 else
713 bitBlt( this, 0, 0, &pm );
714
715}
716
717void KoTabBar::resizeEvent( TQResizeEvent* )
718{
719 d->layoutButtons();
720 d->updateButtons();
721 update();
722}
723
724TQSize KoTabBar::sizeHint() const
725{
726 return TQSize( 40, style().pixelMetric( TQStyle::PM_ScrollBarExtent, this ) );
727}
728
729void KoTabBar::renameTab( const TQString& old_name, const TQString& new_name )
730{
731 TQStringList::Iterator it = d->tabs.find( old_name );
732 (*it) = new_name;
733
734 update();
735}
736
737TQString KoTabBar::activeTab() const
738{
739 if( d->activeTab == 0 )
740 return TQString();
741 else
742 return d->tabs[ d->activeTab ];
743}
744
745void KoTabBar::mousePressEvent( TQMouseEvent* ev )
746{
747 if ( d->tabs.count() == 0 )
748 {
749 erase();
750 return;
751 }
752
753 d->layoutTabs();
754
755 TQPoint pos = ev->pos();
756 if( !d->reverseLayout ) pos = pos - TQPoint( d->offset,0 );
757
758 int tab = d->tabAt( pos ) + 1;
759 if( ( tab > 0 ) && ( tab != d->activeTab ) )
760 {
761 d->activeTab = tab;
762 update();
763
764 emit tabChanged( d->tabs[ d->activeTab-1] );
765
766 // scroll if partially visible
767 if( d->tabRects[ tab-1 ].right() > width() - d->offset )
769 }
770
771 if( ev->button() == TQt::RightButton )
772 if( !d->readOnly )
773 emit contextMenu( ev->globalPos() );
774}
775
776void KoTabBar::mouseReleaseEvent( TQMouseEvent* ev )
777{
778 if ( d->readOnly ) return;
779
780 d->autoScroll = false;
781
782 if ( ev->button() == TQt::LeftButton && d->targetTab != 0 )
783 {
784 emit tabMoved( d->activeTab-1, d->targetTab-1 );
785 d->targetTab = 0;
786 }
787}
788
789void KoTabBar::mouseMoveEvent( TQMouseEvent* ev )
790{
791 if ( d->readOnly ) return;
792
793 TQPoint pos = ev->pos();
794 if( !d->reverseLayout) pos = pos - TQPoint( d->offset,0 );
795
796 // check if user drags a tab to move it
797 int i = d->tabAt( pos ) + 1;
798 if( ( i > 0 ) && ( i != d->targetTab ) )
799 {
800 if( i == d->activeTab ) i = 0;
801 if( i == d->activeTab+1 ) i = 0;
802
803 if( i != d->targetTab )
804 {
805 d->targetTab = i;
806 d->autoScroll = false;
807 update();
808 }
809 }
810
811 // drag past the very latest visible tab
812 // e.g move a tab to the last ordering position
813 TQRect r = d->tabRects[ d->tabRects.count()-1 ];
814 bool moveToLast = false;
815 if( r.isValid() )
816 {
817 if( !d->reverseLayout )
818 if( pos.x() > r.right() )
819 if( pos.x() < width() )
820 moveToLast = true;
821 if( d->reverseLayout )
822 if( pos.x() < r.x() )
823 if( pos.x() > 0 )
824 moveToLast = true;
825 }
826 if( moveToLast )
827 if( d->targetTab != (int)d->tabRects.count()+1 )
828 {
829 d->targetTab = d->tabRects.count()+1;
830 d->autoScroll = false;
831 update();
832 }
833
834 // outside far too left ? activate autoscroll...
835 if ( pos.x() < 0 && !d->autoScroll )
836 {
837 d->autoScroll = true;
838 autoScrollBack();
839 }
840
841 // outside far too right ? activate autoscroll...
842 int w = width() - d->offset;
843 if ( pos.x() > w && !d->autoScroll )
844 {
845 d->autoScroll = true;
846 autoScrollForward();
847 }
848}
849
850void KoTabBar::mouseDoubleClickEvent( TQMouseEvent* ev )
851{
852 int offset = d->reverseLayout ? 0 : d->offset;
853 if( ev->pos().x() > offset )
854 if( !d->readOnly )
855 emit doubleClicked();
856}
857
858void KoTabBar::wheelEvent( TQWheelEvent * e )
859{
860 if ( d->tabs.count() == 0 )
861 {
862 erase();
863 return;
864 }
865
866 // Currently one wheel movement is a delta of 120.
867 // The 'unused' delta is stored for devices that allow
868 // a higher scrolling resolution.
869 // The delta required to move one tab is one wheel movement:
870 const int deltaRequired = 120;
871
872 d->wheelDelta += e->delta();
873 int tabDelta = - (d->wheelDelta / deltaRequired);
874 d->wheelDelta = d->wheelDelta % deltaRequired;
875 int numTabs = d->tabs.size();
876
877 if(d->activeTab + tabDelta > numTabs)
878 {
879 // Would take us past the last tab
880 d->activeTab = numTabs;
881 }
882 else if (d->activeTab + tabDelta < 1)
883 {
884 // Would take us before the first tab
885 d->activeTab = 1;
886 }
887 else
888 {
889 d->activeTab = d->activeTab + tabDelta;
890 }
891
892 // Find the left and right edge of the new tab. If we're
893 // going forward, and the right of the new tab isn't visible
894 // then scroll forward. Likewise, if going back, and the
895 // left of the new tab isn't visible, then scroll back.
896 int activeTabRight = d->tabRects[ d->activeTab-1 ].right();
897 int activeTabLeft = d->tabRects[ d->activeTab-1 ].left();
898 if(tabDelta > 0 && activeTabRight > width() - d->offset )
899 {
901 }
902 else if(tabDelta < 0 && activeTabLeft < width() - d->offset )
903 {
904 scrollBack();
905 }
906
907 update();
908 emit tabChanged( d->tabs[ d->activeTab-1] );
909}
910
911
912#include "KoTabBar.moc"
The KoTabBar class provides a tab bar, for use to switch active page/sheet in a document.
Definition KoTabBar.h:62
void removeTab(const TQString &text)
Removes a tab from the bar.
Definition KoTabBar.cpp:396
void scrollFirst()
Scrolls to the first tab.
Definition KoTabBar.cpp:526
void tabMoved(unsigned tab, unsigned target)
This signal is emitted whenever a tab is dragged, moved and released.
void setReadOnly(bool ro)
Sets the tab bar to be read only.
Definition KoTabBar.cpp:424
KoTabBar(TQWidget *parent=0, const char *name=0)
Creates a new tabbar.
Definition KoTabBar.cpp:349
void doubleClicked()
This signal is emitted whenever the tab bar is double-clicked.
void setActiveTab(const TQString &text)
Sets active tab.
Definition KoTabBar.cpp:612
TQString activeTab() const
Returns the active tab.
Definition KoTabBar.cpp:737
TQStringList tabs() const
Returns all the tab as list of strings.
Definition KoTabBar.cpp:473
void clear()
Removes all tabs.
Definition KoTabBar.cpp:410
void setReverseLayout(bool reverse)
If reverse is true, dialogs and scroll buttonswidgets will be laid out in a mirrored as if the sheet ...
Definition KoTabBar.cpp:434
void moveTab(unsigned tab, unsigned target)
Moves a tab to another position and reorder other tabs.
Definition KoTabBar.cpp:592
void ensureVisible(const TQString &tab)
Ensures that specified tab is visible.
Definition KoTabBar.cpp:572
void addTab(const TQString &text)
Adds a tab to the tab bar.
Definition KoTabBar.cpp:388
void scrollForward()
Scrolls one tab forward.
Definition KoTabBar.cpp:512
void renameTab(const TQString &old_name, const TQString &new_name)
Renames a tab.
Definition KoTabBar.cpp:729
bool canScrollBack() const
Returns true if it is possible to scroll one tab back.
Definition KoTabBar.cpp:483
bool canScrollForward() const
Returns true if it is possible to scroll one tab forward.
Definition KoTabBar.cpp:491
void contextMenu(const TQPoint &pos)
This signal is emitted whenever the tab bar is right-clicked.
unsigned count() const
Returns number of tabs.
Definition KoTabBar.cpp:478
void setTabs(const TQStringList &list)
Replaces all tabs with the list of strings.
Definition KoTabBar.cpp:446
bool reverseLayout() const
Returns true if tabs and scroll buttons will be laid out in a mirrored (right to left) fashion.
Definition KoTabBar.cpp:429
void scrollBack()
Scrolls one tab back.
Definition KoTabBar.cpp:499
void tabChanged(const TQString &_text)
Emitted if the active tab changed.
void scrollLast()
Scrolls to the last tab.
Definition KoTabBar.cpp:537
bool readOnly() const
Returns true if the tab bar is read only.
Definition KoTabBar.cpp:419
virtual ~KoTabBar()
Destroy the tabbar.
Definition KoTabBar.cpp:382