update credits
[LibreOffice.git] / svtools / source / control / tabbar.cxx
blob0d4eb047e617ff163330df72cbe7ca3c676d65fe
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svtools/tabbar.hxx>
22 #include <tools/time.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/poly.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/help.hxx>
27 #include <vcl/decoview.hxx>
28 #include <vcl/button.hxx>
29 #include <vcl/edit.hxx>
30 #include <vcl/image.hxx>
31 #include "svtaccessiblefactory.hxx"
32 #include <filectrl.hrc>
33 #include <svtools/svtresid.hxx>
34 #include <svtools/svtools.hrc>
35 #include <limits>
37 // =======================================================================
39 #define TABBAR_OFFSET_X 7
40 #define TABBAR_OFFSET_X2 2
41 #define TABBAR_DRAG_SCROLLOFF 5
42 #define TABBAR_MINSIZE 5
44 const sal_uInt16 ADDNEWPAGE_AREAWIDTH = 10;
46 // =======================================================================
48 struct ImplTabBarItem
50 sal_uInt16 mnId;
51 TabBarPageBits mnBits;
52 OUString maText;
53 OUString maHelpText;
54 Rectangle maRect;
55 long mnWidth;
56 OString maHelpId;
57 sal_Bool mbShort;
58 sal_Bool mbSelect;
59 sal_Bool mbEnable;
60 Color maTabBgColor;
61 Color maTabTextColor;
63 ImplTabBarItem( sal_uInt16 nItemId, const OUString& rText,
64 TabBarPageBits nPageBits ) :
65 maText( rText )
67 mnId = nItemId;
68 mnBits = nPageBits;
69 mnWidth = 0;
70 mbShort = sal_False;
71 mbSelect = sal_False;
72 mbEnable = sal_True;
73 maTabBgColor = Color( COL_AUTO );
74 maTabTextColor = Color( COL_AUTO );
77 bool IsDefaultTabBgColor() const
79 return maTabBgColor == Color(COL_AUTO);
82 bool IsDefaultTabTextColor() const
84 return maTabTextColor == Color(COL_AUTO);
87 bool IsSelected(ImplTabBarItem* pCurItem) const
89 return mbSelect || (pCurItem == this);
93 // =======================================================================
95 // -----------------
96 // - ImplTabButton -
97 // -----------------
99 class ImplTabButton : public PushButton
101 public:
102 ImplTabButton( TabBar* pParent, WinBits nWinStyle = 0 ) :
103 PushButton( pParent, nWinStyle | WB_RECTSTYLE | WB_SMALLSTYLE | WB_NOLIGHTBORDER | WB_NOPOINTERFOCUS ) {}
105 TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
107 virtual long PreNotify( NotifyEvent& rNEvt );
110 // =======================================================================
112 long ImplTabButton::PreNotify( NotifyEvent& rNEvt )
114 if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
116 if ( GetParent()->IsInEditMode() )
118 GetParent()->EndEditMode();
119 return sal_True;
123 return PushButton::PreNotify( rNEvt );
126 // =======================================================================
128 // ----------------
129 // - ImplTabSizer -
130 // ----------------
132 class ImplTabSizer : public Window
134 public:
135 ImplTabSizer( TabBar* pParent, WinBits nWinStyle = 0 );
137 TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
139 private:
140 void ImplTrack( const Point& rScreenPos );
142 virtual void MouseButtonDown( const MouseEvent& rMEvt );
143 virtual void Tracking( const TrackingEvent& rTEvt );
144 virtual void Paint( const Rectangle& rRect );
146 Point maStartPos;
147 long mnStartWidth;
150 // -----------------------------------------------------------------------
152 ImplTabSizer::ImplTabSizer( TabBar* pParent, WinBits nWinStyle )
153 : Window( pParent, nWinStyle & WB_3DLOOK )
154 , mnStartWidth(0)
156 SetPointer( Pointer( POINTER_HSIZEBAR ) );
157 SetSizePixel( Size( 7, 0 ) );
160 // -----------------------------------------------------------------------
162 void ImplTabSizer::ImplTrack( const Point& rScreenPos )
164 TabBar* pParent = GetParent();
165 long nDiff = rScreenPos.X() - maStartPos.X();
166 pParent->mnSplitSize = mnStartWidth + (pParent->IsMirrored() ? -nDiff : nDiff);
167 if ( pParent->mnSplitSize < TABBAR_MINSIZE )
168 pParent->mnSplitSize = TABBAR_MINSIZE;
169 pParent->Split();
170 pParent->Update();
173 // -----------------------------------------------------------------------
175 void ImplTabSizer::MouseButtonDown( const MouseEvent& rMEvt )
177 if ( GetParent()->IsInEditMode() )
179 GetParent()->EndEditMode();
180 return;
183 if ( rMEvt.IsLeft() )
185 maStartPos = OutputToScreenPixel( rMEvt.GetPosPixel() );
186 mnStartWidth = GetParent()->GetSizePixel().Width();
187 StartTracking();
191 // -----------------------------------------------------------------------
193 void ImplTabSizer::Tracking( const TrackingEvent& rTEvt )
195 if ( rTEvt.IsTrackingEnded() )
197 if ( rTEvt.IsTrackingCanceled() )
198 ImplTrack( maStartPos );
199 GetParent()->mnSplitSize = 0;
201 else
202 ImplTrack( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
205 // -----------------------------------------------------------------------
207 void ImplTabSizer::Paint( const Rectangle& )
209 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
210 DecorationView aDecoView( this );
211 long nOffX = 0;
212 Size aOutputSize = GetOutputSizePixel();
214 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
216 SetLineColor( rStyleSettings.GetDarkShadowColor() );
217 DrawLine( Point( 0, 0 ), Point( 0, aOutputSize.Height()-1 ) );
218 nOffX++;
219 aOutputSize.Width()--;
221 aDecoView.DrawButton( Rectangle( Point( nOffX, 0 ), aOutputSize ), BUTTON_DRAW_NOLIGHTBORDER );
224 // =======================================================================
226 // Heisst nicht Impl, da evtl. mal von aussen benutz- und ueberladbar
228 // --------------
229 // - TabBarEdit -
230 // --------------
232 class TabBarEdit : public Edit
234 private:
235 Timer maLoseFocusTimer;
236 sal_Bool mbPostEvt;
238 DECL_LINK( ImplEndEditHdl, void* );
239 DECL_LINK( ImplEndTimerHdl, void* );
241 public:
242 TabBarEdit( TabBar* pParent, WinBits nWinStyle = 0 );
244 TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
246 void SetPostEvent() { mbPostEvt = sal_True; }
247 void ResetPostEvent() { mbPostEvt = sal_False; }
249 virtual long PreNotify( NotifyEvent& rNEvt );
250 virtual void LoseFocus();
253 // -----------------------------------------------------------------------
255 TabBarEdit::TabBarEdit( TabBar* pParent, WinBits nWinStyle ) :
256 Edit( pParent, nWinStyle )
258 mbPostEvt = sal_False;
261 // -----------------------------------------------------------------------
263 long TabBarEdit::PreNotify( NotifyEvent& rNEvt )
265 if ( rNEvt.GetType() == EVENT_KEYINPUT )
267 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
268 if ( !pKEvt->GetKeyCode().GetModifier() )
270 if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN )
272 if ( !mbPostEvt )
274 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) )
275 mbPostEvt = sal_True;
277 return sal_True;
279 else if ( pKEvt->GetKeyCode().GetCode() == KEY_ESCAPE )
281 if ( !mbPostEvt )
283 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_True ) )
284 mbPostEvt = sal_True;
286 return sal_True;
291 return Edit::PreNotify( rNEvt );
294 // -----------------------------------------------------------------------
296 void TabBarEdit::LoseFocus()
298 if ( !mbPostEvt )
300 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) )
301 mbPostEvt = sal_True;
304 Edit::LoseFocus();
307 // -----------------------------------------------------------------------
309 IMPL_LINK( TabBarEdit, ImplEndEditHdl, void*, pCancel )
311 ResetPostEvent();
312 maLoseFocusTimer.Stop();
314 // We need this query, because the edit get a losefous event,
315 // when it shows the context menu or the insert symbol dialog
316 if ( !HasFocus() && HasChildPathFocus( sal_True ) )
318 maLoseFocusTimer.SetTimeout( 30 );
319 maLoseFocusTimer.SetTimeoutHdl( LINK( this, TabBarEdit, ImplEndTimerHdl ) );
320 maLoseFocusTimer.Start();
322 else
323 GetParent()->EndEditMode( pCancel != 0 );
325 return 0;
328 // -----------------------------------------------------------------------
330 IMPL_LINK_NOARG(TabBarEdit, ImplEndTimerHdl)
332 if ( HasFocus() )
333 return 0;
335 // We need this query, because the edit get a losefous event,
336 // when it shows the context menu or the insert symbol dialog
337 if ( HasChildPathFocus( sal_True ) )
338 maLoseFocusTimer.Start();
339 else
340 GetParent()->EndEditMode( sal_True );
342 return 0;
345 // =======================================================================
346 struct TabBar_Impl
348 ImplTabSizer* mpSizer;
349 ::svt::AccessibleFactoryAccess maAccessibleFactory;
351 TabBar_Impl()
352 :mpSizer( NULL )
355 ~TabBar_Impl()
357 delete mpSizer;
361 // =======================================================================
363 const sal_uInt16 TabBar::APPEND = ::std::numeric_limits<sal_uInt16>::max();
364 const sal_uInt16 TabBar::PAGE_NOT_FOUND = ::std::numeric_limits<sal_uInt16>::max();
365 const sal_uInt16 TabBar::INSERT_TAB_POS = ::std::numeric_limits<sal_uInt16>::max() - 1;
367 void TabBar::ImplInit( WinBits nWinStyle )
369 mpItemList = new ImplTabBarList;
370 mpFirstBtn = NULL;
371 mpPrevBtn = NULL;
372 mpNextBtn = NULL;
373 mpLastBtn = NULL;
374 mpImpl = new TabBar_Impl;
375 mpEdit = NULL;
376 mnMaxPageWidth = 0;
377 mnCurMaxWidth = 0;
378 mnOffX = 0;
379 mnOffY = 0;
380 mnLastOffX = 0;
381 mnSplitSize = 0;
382 mnSwitchTime = 0;
383 mnWinStyle = nWinStyle;
384 mnCurPageId = 0;
385 mnFirstPos = 0;
386 mnDropPos = 0;
387 mnSwitchId = 0;
388 mnEditId = 0;
389 mbFormat = sal_True;
390 mbFirstFormat = sal_True;
391 mbSizeFormat = sal_True;
392 mbAutoMaxWidth = sal_True;
393 mbInSwitching = sal_False;
394 mbAutoEditMode = sal_False;
395 mbEditCanceled = sal_False;
396 mbDropPos = sal_False;
397 mbInSelect = sal_False;
398 mbSelColor = sal_False;
399 mbSelTextColor = sal_False;
400 mbMirrored = sal_False;
402 if ( nWinStyle & WB_3DTAB )
403 mnOffY++;
405 ImplInitControls();
407 if(mpFirstBtn)
408 mpFirstBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVET0HOME));
409 if(mpPrevBtn)
410 mpPrevBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVELEFT));
411 if(mpNextBtn)
412 mpNextBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVERIGHT));
413 if(mpLastBtn)
414 mpLastBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVETOEND));
416 SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) );
417 ImplInitSettings( sal_True, sal_True );
420 // -----------------------------------------------------------------------
422 TabBar::TabBar( Window* pParent, WinBits nWinStyle ) :
423 Window( pParent, (nWinStyle & WB_3DLOOK) | WB_CLIPCHILDREN )
425 ImplInit( nWinStyle );
426 maCurrentItemList = 0;
429 // -----------------------------------------------------------------------
431 TabBar::~TabBar()
433 EndEditMode( sal_True );
435 // Controls loeschen
436 if ( mpPrevBtn )
437 delete mpPrevBtn;
438 if ( mpNextBtn )
439 delete mpNextBtn;
440 if ( mpFirstBtn )
441 delete mpFirstBtn;
442 if ( mpLastBtn )
443 delete mpLastBtn;
444 delete mpImpl;
446 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i ) {
447 delete (*mpItemList)[ i ];
449 delete mpItemList;
452 // -----------------------------------------------------------------------
453 ImplTabBarItem* TabBar::seek( size_t i )
455 if ( i < mpItemList->size() )
457 maCurrentItemList = i;
458 return (*mpItemList)[ maCurrentItemList ];
460 return NULL;
463 ImplTabBarItem* TabBar::prev()
465 if ( maCurrentItemList > 0 ) {
466 return (*mpItemList)[ --maCurrentItemList ];
468 return NULL;
471 ImplTabBarItem* TabBar::next()
473 if ( maCurrentItemList+1 < mpItemList->size() ) {
474 return (*mpItemList)[ ++maCurrentItemList ];
476 return NULL;
479 // -----------------------------------------------------------------------
481 void TabBar::ImplInitSettings( sal_Bool bFont, sal_Bool bBackground )
483 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
485 if ( bFont )
487 Font aToolFont;
488 aToolFont = rStyleSettings.GetToolFont();
489 if ( IsControlFont() )
490 aToolFont.Merge( GetControlFont() );
491 aToolFont.SetWeight( WEIGHT_BOLD );
492 SetZoomedPointFont( aToolFont );
494 // Font in der groesse Anpassen, wenn Fenster zu klein?
495 while ( GetTextHeight() > (GetOutputSizePixel().Height()-1) )
497 Font aFont = GetFont();
498 if ( aFont.GetHeight() <= 6 )
499 break;
500 aFont.SetHeight( aFont.GetHeight()-1 );
501 SetFont( aFont );
505 if ( bBackground )
507 Color aColor;
508 if ( IsControlBackground() )
509 aColor = GetControlBackground();
510 else
511 aColor = rStyleSettings.GetFaceColor();
512 SetBackground( aColor );
516 // -----------------------------------------------------------------------
518 void TabBar::ImplGetColors( Color& rFaceColor, Color& rFaceTextColor,
519 Color& rSelectColor, Color& rSelectTextColor )
521 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
523 if ( IsControlBackground() )
524 rFaceColor = GetControlBackground();
525 else
526 rFaceColor = rStyleSettings.GetInactiveTabColor();
527 if ( IsControlForeground() )
528 rFaceTextColor = GetControlForeground();
529 else
530 rFaceTextColor = rStyleSettings.GetButtonTextColor();
531 if ( mbSelColor )
532 rSelectColor = maSelColor;
533 else
534 rSelectColor = rStyleSettings.GetActiveTabColor();
535 if ( mbSelTextColor )
536 rSelectTextColor = maSelTextColor;
537 else
538 rSelectTextColor = rStyleSettings.GetWindowTextColor();
540 // Bei 3D-Tabs wird Selektions- und Face-Farbe umgedreht, da die
541 // selektierten Tabs in 3D erscheinen sollen
542 if ( mnWinStyle & WB_3DTAB )
544 Color aTempColor = rFaceColor;
545 rFaceColor = rSelectColor;
546 rSelectColor = aTempColor;
547 aTempColor = rFaceTextColor;
548 rFaceTextColor = rSelectTextColor;
549 rSelectTextColor = rFaceTextColor;
553 // -----------------------------------------------------------------------
555 sal_Bool TabBar::ImplCalcWidth()
557 // Groessen muessen nur ermittelt werden, wenn sich Text aendert oder
558 // wenn der Font geaendert wurde
559 if ( !mbSizeFormat )
560 return sal_False;
562 // Breiten der Tabs mit dem fetten Font ermitteln
563 Font aFont = GetFont();
564 if ( aFont.GetWeight() != WEIGHT_BOLD )
566 aFont.SetWeight( WEIGHT_BOLD );
567 SetFont( aFont );
570 if ( mnMaxPageWidth )
571 mnCurMaxWidth = mnMaxPageWidth;
572 else if ( mbAutoMaxWidth )
574 mnCurMaxWidth = mnLastOffX-mnOffX-
575 TABBAR_OFFSET_X-TABBAR_OFFSET_X-
576 TABBAR_OFFSET_X2-TABBAR_OFFSET_X2-TABBAR_OFFSET_X2;
577 if ( mnCurMaxWidth < 1 )
578 mnCurMaxWidth = 1;
580 else
581 mnCurMaxWidth = 0;
583 sal_Bool bChanged = sal_False;
584 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
586 ImplTabBarItem* pItem = (*mpItemList)[ i ];
587 long nNewWidth = GetTextWidth( pItem->maText );
588 if ( mnCurMaxWidth && (nNewWidth > mnCurMaxWidth) )
590 pItem->mbShort = sal_True;
591 nNewWidth = mnCurMaxWidth;
593 else
594 pItem->mbShort = sal_False;
595 nNewWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
596 if ( pItem->mnWidth != nNewWidth )
598 pItem->mnWidth = nNewWidth;
599 if ( !pItem->maRect.IsEmpty() )
600 bChanged = sal_True;
603 mbSizeFormat = sal_False;
604 mbFormat = sal_True;
605 return bChanged;
608 // -----------------------------------------------------------------------
610 void TabBar::ImplFormat()
612 ImplCalcWidth();
614 if ( !mbFormat )
615 return;
617 sal_uInt16 n = 0;
618 long x = mnOffX;
619 for ( size_t i = 0, nL = mpItemList->size(); i < nL; ++i )
621 ImplTabBarItem* pItem = (*mpItemList)[ i ];
622 // Bei allen nicht sichtbaren Tabs, wird ein leeres Rechteck
623 // gesetzt
624 if ( (n+1 < mnFirstPos) || (x > mnLastOffX) )
625 pItem->maRect.SetEmpty();
626 else
628 // Etwas von der Tab vor der ersten sichtbaren Page
629 // muss auch zu sehen sein
630 if ( n+1 == mnFirstPos )
631 pItem->maRect.Left() = x-pItem->mnWidth;
632 else
634 pItem->maRect.Left() = x;
635 x += pItem->mnWidth;
637 pItem->maRect.Right() = x+TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
638 pItem->maRect.Bottom() = maWinSize.Height()-1;
640 if( mbMirrored )
642 long nTmp = mnOffX + mnLastOffX - pItem->maRect.Right();
643 pItem->maRect.Right() = mnOffX + mnLastOffX - pItem->maRect.Left();
644 pItem->maRect.Left() = nTmp;
648 n++;
651 mbFormat = sal_False;
653 // Button enablen/disablen
654 ImplEnableControls();
657 // -----------------------------------------------------------------------
659 sal_uInt16 TabBar::ImplGetLastFirstPos()
661 sal_uInt16 nCount = (sal_uInt16)(mpItemList->size());
662 if ( !nCount || mbSizeFormat || mbFormat )
663 return 0;
665 sal_uInt16 nLastFirstPos = nCount-1;
666 long nWinWidth = mnLastOffX-mnOffX-TABBAR_OFFSET_X-ADDNEWPAGE_AREAWIDTH;
667 long nWidth = (*mpItemList)[ nLastFirstPos ]->mnWidth;
668 while ( nLastFirstPos && (nWidth < nWinWidth) )
670 nLastFirstPos--;
671 nWidth += (*mpItemList)[ nLastFirstPos ]->mnWidth;
673 if ( (nLastFirstPos != (sal_uInt16)(mpItemList->size()-1)) &&
674 (nWidth > nWinWidth) )
675 nLastFirstPos++;
676 return nLastFirstPos;
679 // -----------------------------------------------------------------------
681 void TabBar::ImplInitControls()
683 if ( mnWinStyle & WB_SIZEABLE )
685 if ( !mpImpl->mpSizer )
686 mpImpl->mpSizer = new ImplTabSizer( this, mnWinStyle & (WB_DRAG | WB_3DLOOK) );
687 mpImpl->mpSizer->Show();
689 else
691 DELETEZ( mpImpl->mpSizer );
694 Link aLink = LINK( this, TabBar, ImplClickHdl );
696 if ( mnWinStyle & (WB_MINSCROLL | WB_SCROLL) )
698 if ( !mpPrevBtn )
700 mpPrevBtn = new ImplTabButton( this, WB_REPEAT );
701 mpPrevBtn->SetClickHdl( aLink );
703 mpPrevBtn->SetSymbol( mbMirrored ? SYMBOL_NEXT : SYMBOL_PREV );
704 mpPrevBtn->Show();
706 if ( !mpNextBtn )
708 mpNextBtn = new ImplTabButton( this, WB_REPEAT );
709 mpNextBtn->SetClickHdl( aLink );
711 mpNextBtn->SetSymbol( mbMirrored ? SYMBOL_PREV : SYMBOL_NEXT );
712 mpNextBtn->Show();
714 else
716 DELETEZ( mpPrevBtn );
717 DELETEZ( mpNextBtn );
720 if ( mnWinStyle & WB_SCROLL )
722 if ( !mpFirstBtn )
724 mpFirstBtn = new ImplTabButton( this );
725 mpFirstBtn->SetClickHdl( aLink );
727 mpFirstBtn->SetSymbol( mbMirrored ? SYMBOL_LAST : SYMBOL_FIRST );
728 mpFirstBtn->Show();
730 if ( !mpLastBtn )
732 mpLastBtn = new ImplTabButton( this );
733 mpLastBtn->SetClickHdl( aLink );
735 mpLastBtn->SetSymbol( mbMirrored ? SYMBOL_FIRST : SYMBOL_LAST );
736 mpLastBtn->Show();
738 else
740 DELETEZ( mpFirstBtn );
741 DELETEZ( mpLastBtn );
744 mbHasInsertTab = (mnWinStyle & WB_INSERTTAB);
747 // -----------------------------------------------------------------------
749 void TabBar::ImplEnableControls()
751 if ( mbSizeFormat || mbFormat )
752 return;
754 // Buttons enablen/disblen
755 sal_Bool bEnableBtn = mnFirstPos > 0;
756 if ( mpFirstBtn )
757 mpFirstBtn->Enable( bEnableBtn );
758 if ( mpPrevBtn )
759 mpPrevBtn->Enable( bEnableBtn );
761 bEnableBtn = mnFirstPos < ImplGetLastFirstPos();
762 if ( mpNextBtn )
763 mpNextBtn->Enable( bEnableBtn );
764 if ( mpLastBtn )
765 mpLastBtn->Enable( bEnableBtn );
768 // -----------------------------------------------------------------------
770 void TabBar::ImplShowPage( sal_uInt16 nPos )
772 // Breite berechnen
773 long nWidth = GetOutputSizePixel().Width();
774 if ( nWidth >= TABBAR_OFFSET_X )
775 nWidth -= TABBAR_OFFSET_X;
776 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
777 if ( nPos < mnFirstPos )
778 SetFirstPageId( pItem->mnId );
779 else if ( pItem->maRect.Right() > nWidth )
781 while ( pItem->maRect.Right() > nWidth )
783 sal_uInt16 nNewPos = mnFirstPos+1;
784 SetFirstPageId( GetPageId( nNewPos ) );
785 ImplFormat();
786 if ( nNewPos != mnFirstPos )
787 break;
792 // -----------------------------------------------------------------------
794 IMPL_LINK( TabBar, ImplClickHdl, ImplTabButton*, pBtn )
796 EndEditMode();
798 sal_uInt16 nNewPos = mnFirstPos;
800 if ( pBtn == mpFirstBtn )
801 nNewPos = 0;
802 else if ( pBtn == mpPrevBtn )
804 if ( mnFirstPos )
805 nNewPos = mnFirstPos-1;
807 else if ( pBtn == mpNextBtn )
809 sal_uInt16 nCount = GetPageCount();
810 if ( mnFirstPos < nCount )
811 nNewPos = mnFirstPos+1;
813 else
815 sal_uInt16 nCount = GetPageCount();
816 if ( nCount )
817 nNewPos = nCount-1;
820 if ( nNewPos != mnFirstPos )
821 SetFirstPageId( GetPageId( nNewPos ) );
822 return 0;
825 // -----------------------------------------------------------------------
827 void TabBar::MouseMove( const MouseEvent& rMEvt )
829 if ( rMEvt.IsLeaveWindow() )
830 mbInSelect = sal_False;
832 Window::MouseMove( rMEvt );
835 // -----------------------------------------------------------------------
837 void TabBar::MouseButtonDown( const MouseEvent& rMEvt )
839 // Bei Klick in unser Fenster EditModus nur beenden und Klick nicht
840 // ausfuehren
841 if ( IsInEditMode() )
843 EndEditMode();
844 return;
847 ImplTabBarItem* pItem;
848 sal_uInt16 nSelId = GetPageId( rMEvt.GetPosPixel() );
850 if ( !rMEvt.IsLeft() )
852 Window::MouseButtonDown( rMEvt );
853 if ( (nSelId > 0) && (nSelId != mnCurPageId) )
855 sal_uInt16 nPos = GetPagePos( nSelId );
856 pItem = (*mpItemList)[ nPos ];
858 if ( pItem->mbEnable )
860 if ( ImplDeactivatePage() )
862 SetCurPageId( nSelId );
863 Update();
864 ImplActivatePage();
865 ImplSelect();
867 mbInSelect = sal_True;
870 return;
873 if ( rMEvt.IsMod2() && mbAutoEditMode && nSelId )
875 if ( StartEditMode( nSelId ) )
876 return;
879 if ( (rMEvt.GetMode() & (MOUSE_MULTISELECT | MOUSE_RANGESELECT)) && (rMEvt.GetClicks() == 1) )
881 if ( nSelId )
883 sal_uInt16 nPos = GetPagePos( nSelId );
884 sal_Bool bSelectTab = sal_False;
885 pItem = (*mpItemList)[ nPos ];
887 if ( pItem->mbEnable )
889 if ( (rMEvt.GetMode() & MOUSE_MULTISELECT) && (mnWinStyle & WB_MULTISELECT) )
891 if ( nSelId != mnCurPageId )
893 SelectPage( nSelId, !IsPageSelected( nSelId ) );
894 bSelectTab = sal_True;
897 else if ( mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT) )
899 bSelectTab = sal_True;
900 sal_uInt16 n;
901 sal_Bool bSelect;
902 sal_uInt16 nCurPos = GetPagePos( mnCurPageId );
903 if ( nPos <= nCurPos )
905 // Alle Tabs bis zur angeklickten Tab deselektieren
906 // und alle Tabs von der angeklickten Tab bis
907 // zur aktuellen Position selektieren
908 n = 0;
909 while ( n < nCurPos )
911 pItem = (*mpItemList)[ n ];
912 if ( n < nPos )
913 bSelect = sal_False;
914 else
915 bSelect = sal_True;
917 if ( pItem->mbSelect != bSelect )
919 pItem->mbSelect = bSelect;
920 if ( !pItem->maRect.IsEmpty() )
921 Invalidate( pItem->maRect );
924 n++;
928 if ( nPos >= nCurPos )
930 // Alle Tabs von der aktuellen bis zur angeklickten
931 // Tab selektieren und alle Tabs von der angeklickten
932 // Tab bis zur letzten Tab deselektieren
933 sal_uInt16 nCount = (sal_uInt16)mpItemList->size();
934 n = nCurPos;
935 while ( n < nCount )
937 pItem = (*mpItemList)[ n ];
939 if ( n <= nPos )
940 bSelect = sal_True;
941 else
942 bSelect = sal_False;
944 if ( pItem->mbSelect != bSelect )
946 pItem->mbSelect = bSelect;
947 if ( !pItem->maRect.IsEmpty() )
948 Invalidate( pItem->maRect );
951 n++;
956 // Gegebenenfalls muss die selektierte Tab gescrollt werden
957 if ( bSelectTab )
959 ImplShowPage( nPos );
960 Update();
961 ImplSelect();
964 else
965 ImplShowPage( nPos );
966 mbInSelect = sal_True;
968 return;
971 else if ( rMEvt.GetClicks() == 2 )
973 // Gegebenenfalls den Double-Click-Handler rufen
974 if ( !rMEvt.GetModifier() && (!nSelId || (nSelId == mnCurPageId)) )
976 sal_uInt16 nOldCurId = mnCurPageId;
977 mnCurPageId = nSelId;
978 DoubleClick();
979 // Abfrage, da im DoubleClick-Handler die aktuelle Seite
980 // umgeschaltet werden konnte
981 if ( mnCurPageId == nSelId )
982 mnCurPageId = nOldCurId;
985 return;
987 else
989 if ( nSelId )
991 // Nur Select ausfuehren, wenn noch nicht aktuelle Page
992 if ( nSelId != mnCurPageId )
994 sal_uInt16 nPos = GetPagePos( nSelId );
995 pItem = (*mpItemList)[ nPos ];
997 if ( pItem->mbEnable )
999 if ( !pItem->mbSelect )
1001 // Muss invalidiert werden
1002 sal_Bool bUpdate = sal_False;
1003 if ( IsReallyVisible() && IsUpdateMode() )
1004 bUpdate = sal_True;
1006 // Alle selektierten Items deselektieren
1007 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
1009 pItem = (*mpItemList)[ i ];
1010 if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) )
1012 pItem->mbSelect = sal_False;
1013 if ( bUpdate )
1014 Invalidate( pItem->maRect );
1019 if ( ImplDeactivatePage() )
1021 SetCurPageId( nSelId );
1022 Update();
1023 ImplActivatePage();
1024 ImplSelect();
1027 else
1028 ImplShowPage( nPos );
1029 mbInSelect = sal_True;
1032 return;
1036 Window::MouseButtonDown( rMEvt );
1039 // -----------------------------------------------------------------------
1041 void TabBar::MouseButtonUp( const MouseEvent& rMEvt )
1043 mbInSelect = sal_False;
1044 Window::MouseButtonUp( rMEvt );
1048 // -----------------------------------------------------------------------
1050 namespace {
1052 class TabBarPaintGuard
1054 public:
1055 explicit TabBarPaintGuard(TabBar& rParent) :
1056 mrParent(rParent),
1057 maFont(rParent.GetFont())
1059 // #i36013# exclude push buttons from painting area
1060 mrParent.SetClipRegion( Region(mrParent.GetPageArea()) );
1063 ~TabBarPaintGuard()
1065 // Restore original font.
1066 mrParent.SetFont(maFont);
1067 // remove clip region
1068 mrParent.SetClipRegion();
1070 private:
1071 TabBar& mrParent;
1072 Font maFont;
1075 class TabDrawer
1077 public:
1079 explicit TabDrawer(TabBar& rParent) :
1080 mrParent(rParent),
1081 mpStyleSettings(&mrParent.GetSettings().GetStyleSettings()),
1082 maPoly(4),
1083 mbSelected(false),
1084 mbCustomColored(false),
1085 mbSpecialTab(false),
1086 mbEnabled(false)
1090 void drawOutputAreaBorder()
1092 WinBits nWinStyle = mrParent.GetStyle();
1094 // Bei Border oben und unten einen Strich extra malen
1095 if ( (nWinStyle & WB_BORDER) || (nWinStyle & WB_TOPBORDER) )
1097 Size aOutputSize = mrParent.GetOutputSizePixel();
1098 Rectangle aOutRect = mrParent.GetPageArea();
1100 // Bei 3D-Tabs wird auch der Border in 3D gemalt
1101 if ( nWinStyle & WB_3DTAB )
1103 mrParent.SetLineColor( mpStyleSettings->GetShadowColor() );
1104 mrParent.DrawLine( Point( aOutRect.Left(), 0 ), Point( aOutputSize.Width(), 0 ) );
1107 // Border malen (Strich oben und Strich unten)
1108 mrParent.SetLineColor( mpStyleSettings->GetDarkShadowColor() );
1109 mrParent.DrawLine( aOutRect.TopLeft(), Point( aOutputSize.Width()-1, aOutRect.Top() ) );
1113 void drawOuterFrame()
1115 mrParent.DrawPolygon(maPoly);
1118 void drawLeftShadow()
1120 Point p1 = maPoly[0], p2 = maPoly[1];
1121 p1.X()++;
1122 p2.X()++;
1123 p2.Y()--;
1124 mrParent.DrawLine(p1, p2);
1127 void drawRightShadow()
1129 Point p1 = maPoly[2];
1130 Point p2 = maPoly[3];
1131 p1.X()--;
1132 p2.X()--;
1133 mrParent.DrawLine(p1, p2);
1136 void drawTopInnerShadow()
1138 Point p1 = maPoly[0], p2 = maPoly[3];
1139 p1.Y()++;
1140 p2.Y()++;
1141 mrParent.DrawLine(p1, p2);
1144 void drawBottomShadow(bool bColored)
1146 Point p1 = maPoly[1], p2 = maPoly[2];
1147 p1.X() += 1;
1148 p1.Y() -= 1;
1149 p2.X() -= 1;
1150 p2.Y() -= 1;
1151 mrParent.DrawLine(p1, p2);
1152 if (bColored)
1154 p1 += Point(-1, -1);
1155 p2 += Point(1, -1);
1156 mrParent.DrawLine(p1, p2);
1160 void drawText(const String& aText)
1162 Rectangle aRect = maRect;
1163 long nTextWidth = mrParent.GetTextWidth(aText);
1164 long nTextHeight = mrParent.GetTextHeight();
1165 Point aPos = aRect.TopLeft();
1166 aPos.X() += (aRect.getWidth() - nTextWidth) / 2;
1167 aPos.Y() += (aRect.getHeight() - nTextHeight) / 2;
1169 if (mbEnabled)
1170 mrParent.DrawText(aPos, aText);
1171 else
1172 mrParent.DrawCtrlText(
1173 aPos, aText, 0, STRING_LEN, (TEXT_DRAW_DISABLE | TEXT_DRAW_MNEMONIC));
1176 void drawOverTopBorder(bool b3DTab)
1178 Point p1 = maPoly[0], p2 = maPoly[3];
1179 p1.X() += 1;
1180 p2.X() -= 1;
1181 Rectangle aDelRect(p1, p2);
1182 mrParent.DrawRect(aDelRect);
1183 if (b3DTab)
1185 aDelRect.Top()--;
1186 mrParent.DrawRect(aDelRect);
1190 void drawTab()
1192 mrParent.SetLineColor(mpStyleSettings->GetDarkShadowColor());
1194 // Je nach Status die richtige FillInBrush setzen
1195 // Set the correct FillInBrush depending upon status
1196 if ( mbSelected )
1198 // Currently selected Tab
1199 mrParent.SetFillColor( maSelectedColor );
1201 else if ( mbCustomColored )
1203 mrParent.SetFillColor( maCustomColor );
1205 else
1207 mrParent.SetFillColor( maUnselectedColor );
1210 drawOuterFrame();
1212 // If this is the current tab, draw the left inner shadow the default color,
1213 // otherwise make it the same as the custom background color
1214 Color aColor = mpStyleSettings->GetLightColor();
1215 if (mbCustomColored && !mbSelected)
1216 aColor = maCustomColor;
1218 mrParent.SetLineColor(aColor);
1219 drawLeftShadow();
1221 if ( !mbSelected )
1222 drawTopInnerShadow();
1224 mrParent.SetLineColor( mpStyleSettings->GetShadowColor() );
1225 drawRightShadow();
1226 if ( mbCustomColored && mbSelected )
1228 mrParent.SetLineColor(maCustomColor);
1229 drawBottomShadow(true);
1231 else
1232 drawBottomShadow(false);
1234 // Draw the outer frame once more. In some environments, the outer frame
1235 // gets overpainted.
1236 mrParent.SetLineColor( mpStyleSettings->GetDarkShadowColor() );
1237 mrParent.SetFillColor();
1238 drawOuterFrame();
1241 void drawPlusImage()
1243 SvtResId id( BMP_LIST_ADD );
1244 Image aPlusImg( id );
1245 // Center the image within the bounding rectangle.
1246 Size aSize = aPlusImg.GetSizePixel();
1247 Point pt = maRect.TopLeft();
1248 long nXOffSet = (maRect.GetWidth() - aSize.Width()) / 2;
1249 long nYOffset = (maRect.GetHeight() - aSize.Height()) / 2;
1250 pt += Point(nXOffSet, nYOffset);
1251 pt.X() += 1;
1252 mrParent.DrawImage(pt, aPlusImg);
1255 void setRect(const Rectangle& rRect)
1257 maRect = rRect;
1259 long nOffY = mrParent.GetPageArea().getY();
1261 // Zuerst geben wir das Polygon gefuellt aus
1262 maPoly[0] = Point( rRect.Left(), nOffY );
1263 maPoly[1] = Point( rRect.Left()+TABBAR_OFFSET_X, rRect.Bottom() );
1264 maPoly[2] = Point( rRect.Right()-TABBAR_OFFSET_X, rRect.Bottom() );
1265 maPoly[3] = Point( rRect.Right(), nOffY );
1268 void setSelected(bool b)
1270 mbSelected = b;
1273 void setCustomColored(bool b)
1275 mbCustomColored = b;
1278 void setSpecialTab(bool b)
1280 mbSpecialTab = b;
1283 void setEnabled(bool b)
1285 mbEnabled = b;
1288 void setSelectedFillColor(const Color& rColor)
1290 maSelectedColor = rColor;
1293 void setUnselectedFillColor(const Color& rColor)
1295 maUnselectedColor = rColor;
1298 void setCustomColor(const Color& rColor)
1300 maCustomColor = rColor;
1303 private:
1304 TabBar& mrParent;
1305 const StyleSettings* mpStyleSettings;
1307 Rectangle maRect;
1308 Polygon maPoly;
1310 Color maSelectedColor;
1311 Color maCustomColor;
1312 Color maUnselectedColor;
1314 bool mbSelected:1;
1315 bool mbCustomColored:1;
1316 bool mbSpecialTab:1;
1317 bool mbEnabled:1;
1322 void TabBar::Paint( const Rectangle& rect )
1324 if(IsNativeControlSupported(CTRL_WINDOW_BACKGROUND,PART_ENTIRE_CONTROL))
1325 DrawNativeControl(CTRL_WINDOW_BACKGROUND,PART_ENTIRE_CONTROL,rect,
1326 CTRL_STATE_ENABLED,ImplControlValue(0),OUString());
1328 // Items berechnen und ausgeben
1329 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
1330 if (!nItemCount)
1331 return;
1333 ImplPrePaint();
1335 Color aFaceColor, aSelectColor, aFaceTextColor, aSelectTextColor;
1336 ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor );
1338 // Font selektieren
1339 Font aFont = GetFont();
1340 Font aLightFont = aFont;
1341 aLightFont.SetWeight( WEIGHT_NORMAL );
1343 TabBarPaintGuard aGuard(*this);
1344 TabDrawer aDrawer(*this);
1345 aDrawer.setSelectedFillColor(aSelectColor);
1346 aDrawer.setUnselectedFillColor(aFaceColor);
1347 aDrawer.drawOutputAreaBorder();
1349 // Now, start drawing the tabs.
1351 ImplTabBarItem* pItem = ImplGetLastTabBarItem(nItemCount);
1353 if (pItem && mbHasInsertTab)
1355 // Draw the insert tab at the right end.
1356 Rectangle aRect = ImplGetInsertTabRect(pItem);
1357 aDrawer.setRect(aRect);
1358 aDrawer.drawTab();
1359 aDrawer.drawPlusImage();
1362 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1363 ImplTabBarItem* pCurItem = NULL;
1364 while ( pItem )
1366 // CurrentItem als letztes ausgeben, da es alle anderen ueberdeckt
1367 if ( !pCurItem && (pItem->mnId == mnCurPageId) )
1369 pCurItem = pItem;
1370 pItem = prev();
1371 if ( !pItem )
1372 pItem = pCurItem;
1373 continue;
1376 bool bCurrent = pItem == pCurItem;
1378 if ( !pItem->maRect.IsEmpty() )
1380 Rectangle aRect = pItem->maRect;
1381 bool bSelected = pItem->IsSelected(pCurItem);
1382 // We disable custom background color in high contrast mode.
1383 bool bCustomBgColor = !pItem->IsDefaultTabBgColor() && !rStyleSettings.GetHighContrastMode();
1384 bool bSpecialTab = (pItem->mnBits & TPB_SPECIAL);
1385 bool bEnabled = pItem->mbEnable;
1386 OUString aText = pItem->mbShort ?
1387 GetEllipsisString(pItem->maText, mnCurMaxWidth, TEXT_DRAW_ENDELLIPSIS) : pItem->maText;
1389 aDrawer.setRect(aRect);
1390 aDrawer.setSelected(bSelected);
1391 aDrawer.setCustomColored(bCustomBgColor);
1392 aDrawer.setSpecialTab(bSpecialTab);
1393 aDrawer.setEnabled(bEnabled);
1394 aDrawer.setCustomColor(pItem->maTabBgColor);
1395 aDrawer.drawTab();
1397 // Aktuelle Page wird mit einem fetten Font ausgegeben
1398 if ( bCurrent )
1399 SetFont( aFont );
1400 else
1401 SetFont( aLightFont );
1403 // Je nach Status die richtige FillInBrush setzen
1404 // Set the correct FillInBrush depending upon status
1405 if ( bSelected )
1406 SetTextColor( aSelectTextColor );
1407 else if ( bCustomBgColor )
1408 SetTextColor( pItem->maTabTextColor );
1409 else
1410 SetTextColor( aFaceTextColor );
1412 // This tab is "special", and a special tab needs a blue text.
1413 if (bSpecialTab)
1414 SetTextColor(Color(COL_LIGHTBLUE));
1416 aDrawer.drawText(aText);
1418 if ( bCurrent )
1420 SetLineColor();
1421 SetFillColor(aSelectColor);
1422 aDrawer.drawOverTopBorder(mnWinStyle & WB_3DTAB);
1423 return;
1426 pItem = prev();
1428 else
1430 if ( bCurrent )
1431 return;
1433 pItem = NULL;
1436 if ( !pItem )
1437 pItem = pCurItem;
1441 // -----------------------------------------------------------------------
1442 void TabBar::Resize()
1444 Size aNewSize = GetOutputSizePixel();
1446 long nSizerWidth = 0;
1447 long nButtonWidth = 0;
1449 // Sizer anordnen
1450 if ( mpImpl->mpSizer )
1452 Size aSizerSize = mpImpl->mpSizer->GetSizePixel();
1453 Point aNewSizerPos( mbMirrored ? 0 : (aNewSize.Width()-aSizerSize.Width()), 0 );
1454 Size aNewSizerSize( aSizerSize.Width(), aNewSize.Height() );
1455 mpImpl->mpSizer->SetPosSizePixel( aNewSizerPos, aNewSizerSize );
1456 nSizerWidth = aSizerSize.Width();
1459 // Scroll-Buttons anordnen
1460 long nHeight = aNewSize.Height();
1461 // Font in der groesse Anpassen?
1462 ImplInitSettings( sal_True, sal_False );
1464 long nX = mbMirrored ? (aNewSize.Width()-nHeight) : 0;
1465 long nXDiff = mbMirrored ? -nHeight : nHeight;
1467 Size aBtnSize( nHeight, nHeight );
1468 if ( mpFirstBtn )
1470 mpFirstBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1471 nX += nXDiff;
1472 nButtonWidth += nHeight;
1474 if ( mpPrevBtn )
1476 mpPrevBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1477 nX += nXDiff;
1478 nButtonWidth += nHeight;
1480 if ( mpNextBtn )
1482 mpNextBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1483 nX += nXDiff;
1484 nButtonWidth += nHeight;
1486 if ( mpLastBtn )
1488 mpLastBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1489 nX += nXDiff;
1490 nButtonWidth += nHeight;
1493 // Groesse merken
1494 maWinSize = aNewSize;
1496 if( mbMirrored )
1498 mnOffX = nSizerWidth;
1499 mnLastOffX = maWinSize.Width() - nButtonWidth - 1;
1501 else
1503 mnOffX = nButtonWidth;
1504 mnLastOffX = maWinSize.Width() - nSizerWidth - 1;
1507 // Neu formatieren
1508 mbSizeFormat = sal_True;
1509 if ( IsReallyVisible() )
1511 if ( ImplCalcWidth() )
1512 Invalidate();
1513 ImplFormat();
1516 // Button enablen/disablen
1517 ImplEnableControls();
1520 // -----------------------------------------------------------------------
1522 void TabBar::RequestHelp( const HelpEvent& rHEvt )
1524 sal_uInt16 nItemId = GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
1525 if ( nItemId )
1527 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
1529 OUString aStr = GetHelpText( nItemId );
1530 if (!aStr.isEmpty())
1532 Rectangle aItemRect = GetPageRect( nItemId );
1533 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1534 aItemRect.Left() = aPt.X();
1535 aItemRect.Top() = aPt.Y();
1536 aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1537 aItemRect.Right() = aPt.X();
1538 aItemRect.Bottom() = aPt.Y();
1539 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
1540 return;
1543 else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
1545 OUString aHelpId( OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) );
1546 if ( !aHelpId.isEmpty() )
1548 // Wenn eine Hilfe existiert, dann ausloesen
1549 Help* pHelp = Application::GetHelp();
1550 if ( pHelp )
1551 pHelp->Start( aHelpId, this );
1552 return;
1556 // Bei Quick- oder Ballloon-Help zeigen wir den Text an,
1557 // wenn dieser abgeschnitten oder nicht voll sichtbar ist
1558 if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
1560 sal_uInt16 nPos = GetPagePos( nItemId );
1561 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
1562 if ( pItem->mbShort ||
1563 (pItem->maRect.Right()-TABBAR_OFFSET_X-5 > mnLastOffX) )
1565 Rectangle aItemRect = GetPageRect( nItemId );
1566 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1567 aItemRect.Left() = aPt.X();
1568 aItemRect.Top() = aPt.Y();
1569 aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1570 aItemRect.Right() = aPt.X();
1571 aItemRect.Bottom() = aPt.Y();
1572 OUString aStr = (*mpItemList)[ nPos ]->maText;
1573 if (!aStr.isEmpty())
1575 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
1576 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
1577 else
1578 Help::ShowQuickHelp( this, aItemRect, aStr );
1579 return;
1585 Window::RequestHelp( rHEvt );
1588 // -----------------------------------------------------------------------
1590 void TabBar::StateChanged( StateChangedType nType )
1592 Window::StateChanged( nType );
1594 if ( nType == STATE_CHANGE_INITSHOW )
1596 if ( (mbSizeFormat || mbFormat) && !mpItemList->empty() )
1597 ImplFormat();
1599 else if ( (nType == STATE_CHANGE_ZOOM) ||
1600 (nType == STATE_CHANGE_CONTROLFONT) )
1602 ImplInitSettings( sal_True, sal_False );
1603 Invalidate();
1605 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
1606 Invalidate();
1607 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1609 ImplInitSettings( sal_False, sal_True );
1610 Invalidate();
1612 else if ( nType == STATE_CHANGE_MIRRORING )
1614 // reacts on calls of EnableRTL, have to mirror all child controls
1615 if( mpFirstBtn ) mpFirstBtn->EnableRTL( IsRTLEnabled() );
1616 if( mpPrevBtn ) mpPrevBtn->EnableRTL( IsRTLEnabled() );
1617 if( mpNextBtn ) mpNextBtn->EnableRTL( IsRTLEnabled() );
1618 if( mpLastBtn ) mpLastBtn->EnableRTL( IsRTLEnabled() );
1619 if( mpImpl->mpSizer ) mpImpl->mpSizer->EnableRTL( IsRTLEnabled() );
1620 if( mpEdit ) mpEdit->EnableRTL( IsRTLEnabled() );
1624 // -----------------------------------------------------------------------
1626 void TabBar::DataChanged( const DataChangedEvent& rDCEvt )
1628 Window::DataChanged( rDCEvt );
1630 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1631 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1632 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1633 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1635 ImplInitSettings( sal_True, sal_True );
1636 Invalidate();
1640 // -----------------------------------------------------------------------
1642 void TabBar::ImplSelect()
1644 Select();
1646 CallEventListeners( VCLEVENT_TABBAR_PAGESELECTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
1649 // -----------------------------------------------------------------------
1651 void TabBar::Select()
1653 maSelectHdl.Call( this );
1656 // -----------------------------------------------------------------------
1658 void TabBar::DoubleClick()
1660 maDoubleClickHdl.Call( this );
1663 // -----------------------------------------------------------------------
1665 void TabBar::Split()
1667 maSplitHdl.Call( this );
1670 // -----------------------------------------------------------------------
1672 void TabBar::ImplActivatePage()
1674 ActivatePage();
1676 CallEventListeners( VCLEVENT_TABBAR_PAGEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
1679 // -----------------------------------------------------------------------
1681 void TabBar::ActivatePage()
1683 maActivatePageHdl.Call( this );
1686 // -----------------------------------------------------------------------
1688 long TabBar::ImplDeactivatePage()
1690 long nRet = DeactivatePage();
1692 CallEventListeners( VCLEVENT_TABBAR_PAGEDEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
1694 return nRet;
1697 void TabBar::ImplPrePaint()
1699 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
1700 if (!nItemCount)
1701 return;
1703 ImplTabBarItem* pItem;
1705 // TabBar muss formatiert sein
1706 ImplFormat();
1708 // Beim ersten Format auch dafuer sorgen, das aktuelle TabPage
1709 // sichtbar wird
1710 if ( mbFirstFormat )
1712 mbFirstFormat = sal_False;
1714 if ( mnCurPageId && (mnFirstPos == 0) && !mbDropPos )
1716 pItem = (*mpItemList)[ GetPagePos( mnCurPageId ) ];
1717 if ( pItem->maRect.IsEmpty() )
1719 // mbDropPos setzen (bzw. misbrauchen) um Invalidate()
1720 // zu unterbinden
1721 mbDropPos = sal_True;
1722 SetFirstPageId( mnCurPageId );
1723 mbDropPos = sal_False;
1724 if ( mnFirstPos != 0 )
1725 ImplFormat();
1731 ImplTabBarItem* TabBar::ImplGetLastTabBarItem( sal_uInt16 nItemCount )
1733 // letzten sichtbaren Eintrag suchen
1734 sal_uInt16 n = mnFirstPos+1;
1735 if ( n >= nItemCount )
1736 n = nItemCount-1;
1737 ImplTabBarItem* pItem = seek( n );
1738 while ( pItem )
1740 if ( !pItem->maRect.IsEmpty() )
1742 n++;
1743 pItem = next();
1745 else
1746 break;
1749 // Alle Tabs ausgeben (von hinten nach vorn und aktuellen zuletzt)
1750 if ( pItem )
1751 n--;
1752 else if ( n >= nItemCount )
1753 n = nItemCount-1;
1754 pItem = seek( n );
1755 return pItem;
1758 Rectangle TabBar::ImplGetInsertTabRect(ImplTabBarItem* pItem) const
1760 if (mbHasInsertTab && pItem)
1762 Rectangle aInsTabRect = pItem->maRect;
1763 if ( !mbMirrored )
1764 aInsTabRect.setX(
1765 aInsTabRect.getX() + aInsTabRect.getWidth() - TABBAR_OFFSET_X - TABBAR_OFFSET_X2);
1766 else
1767 aInsTabRect.setX(
1768 aInsTabRect.getX() - 3*TABBAR_OFFSET_X - TABBAR_OFFSET_X2);
1769 aInsTabRect.setWidth(32);
1770 return aInsTabRect;
1772 return Rectangle();
1775 // -----------------------------------------------------------------------
1777 long TabBar::DeactivatePage()
1779 if ( maDeactivatePageHdl.IsSet() )
1780 return maDeactivatePageHdl.Call( this );
1781 else
1782 return sal_True;
1785 // -----------------------------------------------------------------------
1787 long TabBar::StartRenaming()
1789 if ( maStartRenamingHdl.IsSet() )
1790 return maStartRenamingHdl.Call( this );
1791 else
1792 return sal_True;
1795 // -----------------------------------------------------------------------
1797 long TabBar::AllowRenaming()
1799 if ( maAllowRenamingHdl.IsSet() )
1800 return maAllowRenamingHdl.Call( this );
1801 else
1802 return sal_True;
1805 // -----------------------------------------------------------------------
1807 void TabBar::EndRenaming()
1809 maEndRenamingHdl.Call( this );
1812 // -----------------------------------------------------------------------
1814 void TabBar::Mirror()
1819 // -----------------------------------------------------------------------
1821 void TabBar::InsertPage( sal_uInt16 nPageId, const OUString& rText,
1822 TabBarPageBits nBits, sal_uInt16 nPos )
1824 DBG_ASSERT( nPageId, "TabBar::InsertPage(): PageId == 0" );
1825 DBG_ASSERT( GetPagePos( nPageId ) == PAGE_NOT_FOUND,
1826 "TabBar::InsertPage(): PageId already exists" );
1827 DBG_ASSERT( nBits <= TPB_SPECIAL, "TabBar::InsertPage(): nBits is wrong" );
1829 // PageItem anlegen und in die Item-Liste eintragen
1830 ImplTabBarItem* pItem = new ImplTabBarItem( nPageId, rText, nBits );
1831 if ( nPos < mpItemList->size() ) {
1832 ImplTabBarList::iterator it = mpItemList->begin();
1833 ::std::advance( it, nPos );
1834 mpItemList->insert( it, pItem );
1835 } else {
1836 mpItemList->push_back( pItem );
1838 mbSizeFormat = sal_True;
1840 // CurPageId gegebenenfalls setzen
1841 if ( !mnCurPageId )
1842 mnCurPageId = nPageId;
1844 // Leiste neu ausgeben
1845 if ( IsReallyVisible() && IsUpdateMode() )
1846 Invalidate();
1848 CallEventListeners( VCLEVENT_TABBAR_PAGEINSERTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
1851 // -----------------------------------------------------------------------
1853 Color TabBar::GetTabBgColor( sal_uInt16 nPageId ) const
1855 sal_uInt16 nPos = GetPagePos( nPageId );
1857 if ( nPos != PAGE_NOT_FOUND )
1858 return (*mpItemList)[ nPos ]->maTabBgColor;
1859 else
1860 return Color( COL_AUTO );
1863 void TabBar::SetTabBgColor( sal_uInt16 nPageId, const Color& aTabBgColor )
1865 sal_uInt16 nPos = GetPagePos( nPageId );
1866 ImplTabBarItem* pItem;
1867 if ( nPos != PAGE_NOT_FOUND )
1869 pItem = (*mpItemList)[ nPos ];
1870 if ( aTabBgColor != Color( COL_AUTO ) )
1872 pItem->maTabBgColor = aTabBgColor;
1873 if ( aTabBgColor.GetLuminance() <= 128 ) //Do not use aTabBgColor.IsDark(), because that threshold is way too low...
1874 pItem->maTabTextColor = Color( COL_WHITE );
1875 else
1876 pItem->maTabTextColor = Color( COL_BLACK );
1878 else
1880 pItem->maTabBgColor = Color( COL_AUTO );
1881 pItem->maTabTextColor = Color( COL_AUTO );
1886 // -----------------------------------------------------------------------
1888 void TabBar::RemovePage( sal_uInt16 nPageId )
1890 sal_uInt16 nPos = GetPagePos( nPageId );
1892 // Existiert Item
1893 if ( nPos != PAGE_NOT_FOUND )
1895 if ( mnCurPageId == nPageId )
1896 mnCurPageId = 0;
1898 // Testen, ob erste sichtbare Seite verschoben werden muss
1899 if ( mnFirstPos > nPos )
1900 mnFirstPos--;
1902 // Item-Daten loeschen
1903 ImplTabBarList::iterator it = mpItemList->begin();
1904 ::std::advance( it, nPos );
1905 delete *it;
1906 mpItemList->erase( it );
1908 // Leiste neu ausgeben
1909 if ( IsReallyVisible() && IsUpdateMode() )
1910 Invalidate();
1912 CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
1916 // -----------------------------------------------------------------------
1918 void TabBar::MovePage( sal_uInt16 nPageId, sal_uInt16 nNewPos )
1920 sal_uInt16 nPos = GetPagePos( nPageId );
1921 Pair aPair( nPos, nNewPos );
1923 if ( nPos < nNewPos )
1924 nNewPos--;
1926 if ( nPos == nNewPos )
1927 return;
1929 // Existiert Item
1930 if ( nPos != PAGE_NOT_FOUND )
1932 // TabBar-Item in der Liste verschieben
1933 ImplTabBarList::iterator it = mpItemList->begin();
1934 ::std::advance( it, nPos );
1935 ImplTabBarItem* pItem = *it;
1936 mpItemList->erase( it );
1937 if ( nNewPos < mpItemList->size() ) {
1938 it = mpItemList->begin();
1939 ::std::advance( it, nNewPos );
1940 mpItemList->insert( it, pItem );
1941 } else {
1942 mpItemList->push_back( pItem );
1945 // Leiste neu ausgeben
1946 if ( IsReallyVisible() && IsUpdateMode() )
1947 Invalidate();
1949 CallEventListeners( VCLEVENT_TABBAR_PAGEMOVED, (void*) &aPair );
1953 // -----------------------------------------------------------------------
1955 void TabBar::Clear()
1957 // Alle Items loeschen
1958 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i ) {
1959 delete (*mpItemList)[ i ];
1961 mpItemList->clear();
1963 // Items aus der Liste loeschen
1964 mbSizeFormat = sal_True;
1965 mnCurPageId = 0;
1966 mnFirstPos = 0;
1967 maCurrentItemList = 0;
1969 // Leiste neu ausgeben
1970 if ( IsReallyVisible() && IsUpdateMode() )
1971 Invalidate();
1973 CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(PAGE_NOT_FOUND)) );
1976 // -----------------------------------------------------------------------
1978 sal_Bool TabBar::IsPageEnabled( sal_uInt16 nPageId ) const
1980 sal_uInt16 nPos = GetPagePos( nPageId );
1982 if ( nPos != PAGE_NOT_FOUND )
1983 return (*mpItemList)[ nPos ]->mbEnable;
1984 else
1985 return sal_False;
1988 // -----------------------------------------------------------------------
1990 void TabBar::SetPageBits( sal_uInt16 nPageId, TabBarPageBits nBits )
1992 sal_uInt16 nPos = GetPagePos( nPageId );
1994 if ( nPos != PAGE_NOT_FOUND )
1996 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
1998 if ( pItem->mnBits != nBits )
2000 pItem->mnBits = nBits;
2002 // Leiste neu ausgeben
2003 if ( IsReallyVisible() && IsUpdateMode() )
2004 Invalidate( pItem->maRect );
2009 // -----------------------------------------------------------------------
2011 TabBarPageBits TabBar::GetPageBits( sal_uInt16 nPageId ) const
2013 sal_uInt16 nPos = GetPagePos( nPageId );
2015 if ( nPos != PAGE_NOT_FOUND )
2016 return (*mpItemList)[ nPos ]->mnBits;
2017 else
2018 return sal_False;
2021 // -----------------------------------------------------------------------
2023 sal_uInt16 TabBar::GetPageCount() const
2025 return (sal_uInt16)mpItemList->size();
2028 // -----------------------------------------------------------------------
2030 sal_uInt16 TabBar::GetPageId( sal_uInt16 nPos ) const
2032 return ( nPos < mpItemList->size() ) ? (*mpItemList)[ nPos ]->mnId : 0;
2035 // -----------------------------------------------------------------------
2037 sal_uInt16 TabBar::GetPagePos( sal_uInt16 nPageId ) const
2039 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i ) {
2040 if ( (*mpItemList)[ i ]->mnId == nPageId ) {
2041 return sal_uInt16( i );
2044 return PAGE_NOT_FOUND;
2047 // -----------------------------------------------------------------------
2049 sal_uInt16 TabBar::GetPageId( const Point& rPos, bool bCheckInsTab ) const
2051 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
2053 ImplTabBarItem* pItem = (*mpItemList)[ i ];
2054 if ( pItem->maRect.IsInside( rPos ) )
2055 return pItem->mnId;
2058 if (bCheckInsTab && mbHasInsertTab && !mpItemList->empty())
2060 ImplTabBarItem* pItem = mpItemList->back();
2061 if (ImplGetInsertTabRect(pItem).IsInside(rPos))
2062 return INSERT_TAB_POS;
2065 return 0;
2068 // -----------------------------------------------------------------------
2070 Rectangle TabBar::GetPageRect( sal_uInt16 nPageId ) const
2072 sal_uInt16 nPos = GetPagePos( nPageId );
2074 if ( nPos != PAGE_NOT_FOUND )
2075 return (*mpItemList)[ nPos ]->maRect;
2076 else
2077 return Rectangle();
2080 // -----------------------------------------------------------------------
2082 void TabBar::SetCurPageId( sal_uInt16 nPageId )
2084 sal_uInt16 nPos = GetPagePos( nPageId );
2086 // Wenn Item nicht existiert, dann nichts machen
2087 if ( nPos != PAGE_NOT_FOUND )
2089 // Wenn sich aktuelle Page nicht geaendert hat, dann muessen wir
2090 // jetzt nichts mehr machen
2091 if ( nPageId == mnCurPageId )
2092 return;
2094 // Muss invalidiert werden
2095 sal_Bool bUpdate = sal_False;
2096 if ( IsReallyVisible() && IsUpdateMode() )
2097 bUpdate = sal_True;
2099 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2100 ImplTabBarItem* pOldItem;
2102 if ( mnCurPageId )
2103 pOldItem = (*mpItemList)[ GetPagePos( mnCurPageId ) ];
2104 else
2105 pOldItem = NULL;
2107 // Wenn Page nicht selektiert, dann vorher selektierte Seite
2108 // deselktieren, wenn dies die einzige selektierte Seite ist
2109 if ( !pItem->mbSelect && pOldItem )
2111 sal_uInt16 nSelPageCount = GetSelectPageCount();
2112 if ( nSelPageCount == 1 )
2113 pOldItem->mbSelect = sal_False;
2114 pItem->mbSelect = sal_True;
2117 mnCurPageId = nPageId;
2118 mbFormat = sal_True;
2120 // Dafuer sorgen, das aktuelle Page sichtbar wird
2121 if ( IsReallyVisible() )
2123 if ( nPos < mnFirstPos )
2124 SetFirstPageId( nPageId );
2125 else
2127 // sichtbare Breite berechnen
2128 long nWidth = mnLastOffX;
2129 if ( nWidth > TABBAR_OFFSET_X )
2130 nWidth -= TABBAR_OFFSET_X;
2131 if ( nWidth > ADDNEWPAGE_AREAWIDTH )
2132 nWidth -= ADDNEWPAGE_AREAWIDTH;
2134 if ( pItem->maRect.IsEmpty() )
2135 ImplFormat();
2137 while ( (mbMirrored ? (pItem->maRect.Left() < mnOffX) : (pItem->maRect.Right() > nWidth)) ||
2138 pItem->maRect.IsEmpty() )
2140 sal_uInt16 nNewPos = mnFirstPos+1;
2141 // Dafuer sorgen, das min. die aktuelle TabPages als
2142 // erste TabPage sichtbar ist
2143 if ( nNewPos >= nPos )
2145 SetFirstPageId( nPageId );
2146 break;
2148 else
2149 SetFirstPageId( GetPageId( nNewPos ) );
2150 ImplFormat();
2151 // Falls erste Seite nicht weitergeschaltet wird, dann
2152 // koennen wir abbrechen
2153 if ( nNewPos != mnFirstPos )
2154 break;
2159 // Leiste neu ausgeben
2160 if ( bUpdate )
2162 Invalidate( pItem->maRect );
2163 if ( pOldItem )
2164 Invalidate( pOldItem->maRect );
2169 // -----------------------------------------------------------------------
2171 void TabBar::MakeVisible( sal_uInt16 nPageId )
2173 if ( !IsReallyVisible() )
2174 return;
2176 sal_uInt16 nPos = GetPagePos( nPageId );
2178 // Wenn Item nicht existiert, dann nichts machen
2179 if ( nPos != PAGE_NOT_FOUND )
2181 if ( nPos < mnFirstPos )
2182 SetFirstPageId( nPageId );
2183 else
2185 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2187 // sichtbare Breite berechnen
2188 long nWidth = mnLastOffX;
2189 if ( nWidth > TABBAR_OFFSET_X )
2190 nWidth -= TABBAR_OFFSET_X;
2192 if ( mbFormat || pItem->maRect.IsEmpty() )
2194 mbFormat = sal_True;
2195 ImplFormat();
2198 while ( (pItem->maRect.Right() > nWidth) ||
2199 pItem->maRect.IsEmpty() )
2201 sal_uInt16 nNewPos = mnFirstPos+1;
2202 // Dafuer sorgen, das min. die aktuelle TabPages als
2203 // erste TabPage sichtbar ist
2204 if ( nNewPos >= nPos )
2206 SetFirstPageId( nPageId );
2207 break;
2209 else
2210 SetFirstPageId( GetPageId( nNewPos ) );
2211 ImplFormat();
2212 // Falls erste Seite nicht weitergeschaltet wird, dann
2213 // koennen wir abbrechen
2214 if ( nNewPos != mnFirstPos )
2215 break;
2221 // -----------------------------------------------------------------------
2223 void TabBar::SetFirstPageId( sal_uInt16 nPageId )
2225 sal_uInt16 nPos = GetPagePos( nPageId );
2227 // Wenn Item nicht existiert, dann sal_False zurueckgeben
2228 if ( nPos != PAGE_NOT_FOUND )
2230 if ( nPos != mnFirstPos )
2232 // Dafuer sorgen, das nach Moeglichkteit soviele Pages wie
2233 // moeglich sichtbar sind
2234 ImplFormat();
2235 sal_uInt16 nLastFirstPos = ImplGetLastFirstPos();
2236 sal_uInt16 nNewPos;
2237 if ( nPos > nLastFirstPos )
2238 nNewPos = nLastFirstPos;
2239 else
2240 nNewPos = nPos;
2242 if ( nNewPos != mnFirstPos )
2244 mnFirstPos = nNewPos;
2245 mbFormat = sal_True;
2247 // Leiste neu ausgeben (Achtung: mbDropPos beachten, da wenn
2248 // dieses Flag gesetzt ist, wird direkt gepaintet)
2249 if ( IsReallyVisible() && IsUpdateMode() && !mbDropPos )
2250 Invalidate();
2256 // -----------------------------------------------------------------------
2258 void TabBar::SelectPage( sal_uInt16 nPageId, sal_Bool bSelect )
2260 sal_uInt16 nPos = GetPagePos( nPageId );
2262 if ( nPos != PAGE_NOT_FOUND )
2264 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2266 if ( pItem->mbSelect != bSelect )
2268 pItem->mbSelect = bSelect;
2270 // Leiste neu ausgeben
2271 if ( IsReallyVisible() && IsUpdateMode() )
2272 Invalidate( pItem->maRect );
2277 // -----------------------------------------------------------------------
2279 sal_uInt16 TabBar::GetSelectPageCount() const
2281 sal_uInt16 nSelected = 0;
2282 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
2284 ImplTabBarItem* pItem = (*mpItemList)[ i ];
2285 if ( pItem->mbSelect )
2286 nSelected++;
2289 return nSelected;
2292 // -----------------------------------------------------------------------
2294 sal_Bool TabBar::IsPageSelected( sal_uInt16 nPageId ) const
2296 sal_uInt16 nPos = GetPagePos( nPageId );
2297 if ( nPos != PAGE_NOT_FOUND )
2298 return (*mpItemList)[ nPos ]->mbSelect;
2299 else
2300 return sal_False;
2303 // -----------------------------------------------------------------------
2305 sal_Bool TabBar::StartEditMode( sal_uInt16 nPageId )
2307 sal_uInt16 nPos = GetPagePos( nPageId );
2308 if ( mpEdit || (nPos == PAGE_NOT_FOUND) || (mnLastOffX < 8) )
2309 return sal_False;
2311 mnEditId = nPageId;
2312 if ( StartRenaming() )
2314 ImplShowPage( nPos );
2315 ImplFormat();
2316 Update();
2318 mpEdit = new TabBarEdit( this, WB_CENTER );
2319 Rectangle aRect = GetPageRect( mnEditId );
2320 long nX = aRect.Left()+TABBAR_OFFSET_X+(TABBAR_OFFSET_X2/2);
2321 long nWidth = aRect.GetWidth()-(TABBAR_OFFSET_X*2)-TABBAR_OFFSET_X2;
2322 if ( mnEditId != GetCurPageId() )
2323 nX += 1;
2324 if ( nX+nWidth > mnLastOffX )
2325 nWidth = mnLastOffX-nX;
2326 if ( nWidth < 3 )
2328 nX = aRect.Left();
2329 nWidth = aRect.GetWidth();
2331 mpEdit->SetText( GetPageText( mnEditId ) );
2332 mpEdit->setPosSizePixel( nX, aRect.Top()+mnOffY+1, nWidth, aRect.GetHeight()-3 );
2333 Font aFont = GetPointFont();
2334 Color aForegroundColor;
2335 Color aBackgroundColor;
2336 Color aFaceColor;
2337 Color aSelectColor;
2338 Color aFaceTextColor;
2339 Color aSelectTextColor;
2340 ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor );
2341 if ( mnEditId != GetCurPageId() )
2342 aFont.SetWeight( WEIGHT_LIGHT );
2343 if ( IsPageSelected( mnEditId ) || (mnEditId == GetCurPageId()) )
2345 aForegroundColor = aSelectTextColor;
2346 aBackgroundColor = aSelectColor;
2348 else
2350 aForegroundColor = aFaceTextColor;
2351 aBackgroundColor = aFaceColor;
2353 if ( GetPageBits( mnEditId ) & TPB_SPECIAL )
2354 aForegroundColor = Color( COL_LIGHTBLUE );
2355 mpEdit->SetControlFont( aFont );
2356 mpEdit->SetControlForeground( aForegroundColor );
2357 mpEdit->SetControlBackground( aBackgroundColor );
2358 mpEdit->GrabFocus();
2359 mpEdit->SetSelection( Selection( 0, mpEdit->GetText().getLength() ) );
2360 mpEdit->Show();
2361 return sal_True;
2363 else
2365 mnEditId = 0;
2366 return sal_False;
2370 // -----------------------------------------------------------------------
2372 void TabBar::EndEditMode( sal_Bool bCancel )
2374 if ( mpEdit )
2376 // call hdl
2377 sal_Bool bEnd = sal_True;
2378 mbEditCanceled = bCancel;
2379 maEditText = mpEdit->GetText();
2380 mpEdit->SetPostEvent();
2381 if ( !bCancel )
2383 long nAllowRenaming = AllowRenaming();
2384 if ( nAllowRenaming == TABBAR_RENAMING_YES )
2385 SetPageText( mnEditId, maEditText );
2386 else if ( nAllowRenaming == TABBAR_RENAMING_NO )
2387 bEnd = sal_False;
2388 else // nAllowRenaming == TABBAR_RENAMING_CANCEL
2389 mbEditCanceled = sal_True;
2392 // renaming not allowed, than reset edit data
2393 if ( !bEnd )
2395 mpEdit->ResetPostEvent();
2396 mpEdit->GrabFocus();
2398 else
2400 // close edit and call end hdl
2401 delete mpEdit;
2402 mpEdit = NULL;
2403 EndRenaming();
2404 mnEditId = 0;
2407 // reset
2408 maEditText = OUString();
2409 mbEditCanceled = false;
2413 // -----------------------------------------------------------------------
2415 void TabBar::SetMirrored(bool bMirrored)
2417 if( mbMirrored != bMirrored )
2419 mbMirrored = bMirrored;
2420 mbSizeFormat = true;
2421 ImplInitControls(); // for button images
2422 Resize(); // recalculates control positions
2423 Mirror();
2427 void TabBar::SetEffectiveRTL( bool bRTL )
2429 SetMirrored( bRTL != Application::GetSettings().GetLayoutRTL() );
2432 bool TabBar::IsEffectiveRTL() const
2434 return IsMirrored() != Application::GetSettings().GetLayoutRTL();
2437 // -----------------------------------------------------------------------
2439 void TabBar::SetMaxPageWidth( long nMaxWidth )
2441 if ( mnMaxPageWidth != nMaxWidth )
2443 mnMaxPageWidth = nMaxWidth;
2444 mbSizeFormat = sal_True;
2446 // Leiste neu ausgeben
2447 if ( IsReallyVisible() && IsUpdateMode() )
2448 Invalidate();
2452 // -----------------------------------------------------------------------
2454 void TabBar::SetPageText( sal_uInt16 nPageId, const OUString& rText )
2456 sal_uInt16 nPos = GetPagePos( nPageId );
2457 if ( nPos != PAGE_NOT_FOUND )
2459 (*mpItemList)[ nPos ]->maText = rText;
2460 mbSizeFormat = sal_True;
2462 // Leiste neu ausgeben
2463 if ( IsReallyVisible() && IsUpdateMode() )
2464 Invalidate();
2466 CallEventListeners( VCLEVENT_TABBAR_PAGETEXTCHANGED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
2470 // -----------------------------------------------------------------------
2472 OUString TabBar::GetPageText( sal_uInt16 nPageId ) const
2474 sal_uInt16 nPos = GetPagePos( nPageId );
2475 if ( nPos != PAGE_NOT_FOUND )
2476 return (*mpItemList)[ nPos ]->maText;
2477 return OUString();
2480 // -----------------------------------------------------------------------
2482 XubString TabBar::GetHelpText( sal_uInt16 nPageId ) const
2484 sal_uInt16 nPos = GetPagePos( nPageId );
2485 if ( nPos != PAGE_NOT_FOUND )
2487 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2488 if (pItem->maHelpText.isEmpty() && !pItem->maHelpId.isEmpty())
2490 Help* pHelp = Application::GetHelp();
2491 if ( pHelp )
2492 pItem->maHelpText = pHelp->GetHelpText( OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
2495 return pItem->maHelpText;
2497 return OUString();
2500 // -----------------------------------------------------------------------
2502 OString TabBar::GetHelpId( sal_uInt16 nPageId ) const
2504 sal_uInt16 nPos = GetPagePos( nPageId );
2505 OString aRet;
2506 if ( nPos != PAGE_NOT_FOUND )
2507 return (*mpItemList)[ nPos ]->maHelpId;
2508 return aRet;
2511 // -----------------------------------------------------------------------
2513 sal_Bool TabBar::StartDrag( const CommandEvent& rCEvt, Region& rRegion )
2515 if ( !(mnWinStyle & WB_DRAG) || (rCEvt.GetCommand() != COMMAND_STARTDRAG) )
2516 return sal_False;
2518 // Testen, ob angeklickte Seite selektiert ist. Falls dies nicht
2519 // der Fall ist, setzen wir ihn als aktuellen Eintrag. Falls Drag and
2520 // Drop auch mal ueber Tastatur ausgeloest werden kann, testen wir
2521 // dies nur bei einer Mausaktion.
2522 // Ausserdem machen wir das nur, wenn kein Select() ausgeloest wurde,
2523 // da der Select schon den Bereich gescrollt haben kann
2524 if ( rCEvt.IsMouseEvent() && !mbInSelect )
2526 sal_uInt16 nSelId = GetPageId( rCEvt.GetMousePosPixel() );
2528 // Falls kein Eintrag angeklickt wurde, starten wir kein Dragging
2529 if ( !nSelId )
2530 return sal_False;
2532 // Testen, ob Seite selektiertiert ist. Falls nicht, als aktuelle
2533 // Seite setzen und Select rufen.
2534 if ( !IsPageSelected( nSelId ) )
2536 if ( ImplDeactivatePage() )
2538 SetCurPageId( nSelId );
2539 Update();
2540 ImplActivatePage();
2541 ImplSelect();
2543 else
2544 return sal_False;
2547 mbInSelect = sal_False;
2549 Region aRegion;
2551 // Region zuweisen
2552 rRegion = aRegion;
2554 return sal_True;
2557 // -----------------------------------------------------------------------
2559 sal_uInt16 TabBar::ShowDropPos( const Point& rPos )
2561 ImplTabBarItem* pItem;
2562 sal_uInt16 nDropId;
2563 sal_uInt16 nNewDropPos;
2564 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
2565 short nScroll = 0;
2567 if ( rPos.X() > mnLastOffX-TABBAR_DRAG_SCROLLOFF )
2569 pItem = (*mpItemList)[ mpItemList->size()-1 ];
2570 if ( !pItem->maRect.IsEmpty() && (rPos.X() > pItem->maRect.Right()) )
2571 nNewDropPos = (sal_uInt16)mpItemList->size();
2572 else
2574 nNewDropPos = mnFirstPos+1;
2575 nScroll = 1;
2578 else if ( (rPos.X() <= mnOffX) ||
2579 (!mnOffX && (rPos.X() <= TABBAR_DRAG_SCROLLOFF)) )
2581 if ( mnFirstPos )
2583 nNewDropPos = mnFirstPos;
2584 nScroll = -1;
2586 else
2587 nNewDropPos = 0;
2589 else
2591 nDropId = GetPageId( rPos );
2592 if ( nDropId )
2594 nNewDropPos = GetPagePos( nDropId );
2595 if ( mnFirstPos && (nNewDropPos == mnFirstPos-1) )
2596 nScroll = -1;
2598 else
2599 nNewDropPos = nItemCount;
2602 if ( mbDropPos && (nNewDropPos == mnDropPos) && !nScroll )
2603 return mnDropPos;
2605 if ( mbDropPos )
2606 HideDropPos();
2607 mbDropPos = sal_True;
2608 mnDropPos = nNewDropPos;
2610 if ( nScroll )
2612 sal_uInt16 nOldFirstPos = mnFirstPos;
2613 SetFirstPageId( GetPageId( mnFirstPos+nScroll ) );
2615 // Direkt ausgeben, da kein Paint bei Drag and Drop moeglich
2616 if ( nOldFirstPos != mnFirstPos )
2618 Rectangle aRect( mnOffX, 0, mnLastOffX, maWinSize.Height() );
2619 SetFillColor( GetBackground().GetColor() );
2620 DrawRect( aRect );
2621 Paint( aRect );
2625 // Drop-Position-Pfeile ausgeben
2626 Color aBlackColor( COL_BLACK );
2627 long nX;
2628 long nY = (maWinSize.Height()/2)-1;
2629 sal_uInt16 nCurPos = GetPagePos( mnCurPageId );
2631 SetLineColor( aBlackColor );
2632 if ( mnDropPos < nItemCount )
2634 pItem = (*mpItemList)[ mnDropPos ];
2635 nX = pItem->maRect.Left()+TABBAR_OFFSET_X;
2636 if ( mnDropPos == nCurPos )
2637 nX--;
2638 else
2639 nX++;
2640 if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
2641 SetLineColor( pItem->maTabTextColor );
2642 DrawLine( Point( nX, nY ), Point( nX, nY ) );
2643 DrawLine( Point( nX+1, nY-1 ), Point( nX+1, nY+1 ) );
2644 DrawLine( Point( nX+2, nY-2 ), Point( nX+2, nY+2 ) );
2645 SetLineColor( aBlackColor );
2647 if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) )
2649 pItem = (*mpItemList)[ mnDropPos-1 ];
2650 nX = pItem->maRect.Right()-TABBAR_OFFSET_X;
2651 if ( mnDropPos == nCurPos )
2652 nX++;
2653 if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
2654 SetLineColor( pItem->maTabTextColor );
2655 DrawLine( Point( nX, nY ), Point( nX, nY ) );
2656 DrawLine( Point( nX-1, nY-1 ), Point( nX-1, nY+1 ) );
2657 DrawLine( Point( nX-2, nY-2 ), Point( nX-2, nY+2 ) );
2660 return mnDropPos;
2663 // -----------------------------------------------------------------------
2665 void TabBar::HideDropPos()
2667 if ( mbDropPos )
2669 ImplTabBarItem* pItem;
2670 long nX;
2671 long nY1 = (maWinSize.Height()/2)-3;
2672 long nY2 = nY1 + 5;
2673 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
2675 if ( mnDropPos < nItemCount )
2677 pItem = (*mpItemList)[ mnDropPos ];
2678 nX = pItem->maRect.Left()+TABBAR_OFFSET_X;
2679 // Paint direkt aufrufen, da bei Drag and Drop kein Paint
2680 // moeglich
2681 Rectangle aRect( nX-1, nY1, nX+3, nY2 );
2682 Region aRegion( aRect );
2683 SetClipRegion( aRegion );
2684 Paint( aRect );
2685 SetClipRegion();
2687 if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) )
2689 pItem = (*mpItemList)[ mnDropPos-1 ];
2690 nX = pItem->maRect.Right()-TABBAR_OFFSET_X;
2691 // Paint direkt aufrufen, da bei Drag and Drop kein Paint
2692 // moeglich
2693 Rectangle aRect( nX-2, nY1, nX+1, nY2 );
2694 Region aRegion( aRect );
2695 SetClipRegion( aRegion );
2696 Paint( aRect );
2697 SetClipRegion();
2700 mbDropPos = sal_False;
2701 mnDropPos = 0;
2705 // -----------------------------------------------------------------------
2707 sal_Bool TabBar::SwitchPage( const Point& rPos )
2709 sal_Bool bSwitch = sal_False;
2710 sal_uInt16 nSwitchId = GetPageId( rPos );
2711 if ( !nSwitchId )
2712 EndSwitchPage();
2713 else
2715 if ( nSwitchId != mnSwitchId )
2717 mnSwitchId = nSwitchId;
2718 mnSwitchTime = Time::GetSystemTicks();
2720 else
2722 // Erst nach 500 ms umschalten
2723 if ( mnSwitchId != GetCurPageId() )
2725 if ( Time::GetSystemTicks() > mnSwitchTime+500 )
2727 mbInSwitching = sal_True;
2728 if ( ImplDeactivatePage() )
2730 SetCurPageId( mnSwitchId );
2731 Update();
2732 ImplActivatePage();
2733 ImplSelect();
2734 bSwitch = sal_True;
2736 mbInSwitching = sal_False;
2742 return bSwitch;
2745 // -----------------------------------------------------------------------
2747 void TabBar::EndSwitchPage()
2749 mnSwitchTime = 0;
2750 mnSwitchId = 0;
2753 // -----------------------------------------------------------------------
2755 void TabBar::SetStyle( WinBits nStyle )
2757 mnWinStyle = nStyle;
2758 ImplInitControls();
2759 // Evt. Controls neu anordnen
2760 if ( IsReallyVisible() && IsUpdateMode() )
2761 Resize();
2764 // -----------------------------------------------------------------------
2766 Size TabBar::CalcWindowSizePixel() const
2768 long nWidth = 0;
2770 if ( mpItemList->size() )
2772 ((TabBar*)this)->ImplCalcWidth();
2773 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
2775 ImplTabBarItem* pItem = (*mpItemList)[ i ];
2776 nWidth += pItem->mnWidth;
2778 nWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
2781 return Size( nWidth, GetSettings().GetStyleSettings().GetScrollBarSize() );
2783 // -----------------------------------------------------------------------
2785 Rectangle TabBar::GetPageArea() const
2787 return Rectangle( Point( mnOffX, mnOffY ), Size( mnLastOffX-mnOffX+1, GetSizePixel().Height()-mnOffY ) );
2790 // -----------------------------------------------------------------------
2792 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > TabBar::CreateAccessible()
2794 return mpImpl->maAccessibleFactory.getFactory().createAccessibleTabBar( *this );
2797 // -----------------------------------------------------------------------
2799 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */