GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svtools / source / control / tabbar.cxx
blobc0b8059e8d1cb581278f2ef98e8d9d346a45a7c3
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 );
109 virtual void MouseButtonDown( const MouseEvent& rMEvt );
111 virtual void Command( const CommandEvent& rCEvt );
114 void ImplTabButton::MouseButtonDown( const MouseEvent& rMEvt )
116 PushButton::MouseButtonDown(rMEvt);
119 void ImplTabButton::Command( const CommandEvent& rCEvt )
121 sal_uInt16 nCmd = rCEvt.GetCommand();
122 if ( nCmd == COMMAND_CONTEXTMENU )
124 TabBar *pParent = GetParent();
125 pParent->maScrollAreaContextHdl.Call((void*)&rCEvt);
127 PushButton::Command(rCEvt);
130 // =======================================================================
132 long ImplTabButton::PreNotify( NotifyEvent& rNEvt )
134 if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
136 if ( GetParent()->IsInEditMode() )
138 GetParent()->EndEditMode();
139 return sal_True;
143 return PushButton::PreNotify( rNEvt );
146 // =======================================================================
148 // ----------------
149 // - ImplTabSizer -
150 // ----------------
152 class ImplTabSizer : public Window
154 public:
155 ImplTabSizer( TabBar* pParent, WinBits nWinStyle = 0 );
157 TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
159 private:
160 void ImplTrack( const Point& rScreenPos );
162 virtual void MouseButtonDown( const MouseEvent& rMEvt );
163 virtual void Tracking( const TrackingEvent& rTEvt );
164 virtual void Paint( const Rectangle& rRect );
166 Point maStartPos;
167 long mnStartWidth;
170 // -----------------------------------------------------------------------
172 ImplTabSizer::ImplTabSizer( TabBar* pParent, WinBits nWinStyle )
173 : Window( pParent, nWinStyle & WB_3DLOOK )
174 , mnStartWidth(0)
176 SetPointer( Pointer( POINTER_HSIZEBAR ) );
177 SetSizePixel( Size( 7, 0 ) );
180 // -----------------------------------------------------------------------
182 void ImplTabSizer::ImplTrack( const Point& rScreenPos )
184 TabBar* pParent = GetParent();
185 long nDiff = rScreenPos.X() - maStartPos.X();
186 pParent->mnSplitSize = mnStartWidth + (pParent->IsMirrored() ? -nDiff : nDiff);
187 if ( pParent->mnSplitSize < TABBAR_MINSIZE )
188 pParent->mnSplitSize = TABBAR_MINSIZE;
189 pParent->Split();
190 pParent->Update();
193 // -----------------------------------------------------------------------
195 void ImplTabSizer::MouseButtonDown( const MouseEvent& rMEvt )
197 if ( GetParent()->IsInEditMode() )
199 GetParent()->EndEditMode();
200 return;
203 if ( rMEvt.IsLeft() )
205 maStartPos = OutputToScreenPixel( rMEvt.GetPosPixel() );
206 mnStartWidth = GetParent()->GetSizePixel().Width();
207 StartTracking();
211 // -----------------------------------------------------------------------
213 void ImplTabSizer::Tracking( const TrackingEvent& rTEvt )
215 if ( rTEvt.IsTrackingEnded() )
217 if ( rTEvt.IsTrackingCanceled() )
218 ImplTrack( maStartPos );
219 GetParent()->mnSplitSize = 0;
221 else
222 ImplTrack( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
225 // -----------------------------------------------------------------------
227 void ImplTabSizer::Paint( const Rectangle& )
229 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
230 DecorationView aDecoView( this );
231 long nOffX = 0;
232 Size aOutputSize = GetOutputSizePixel();
234 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
236 SetLineColor( rStyleSettings.GetDarkShadowColor() );
237 DrawLine( Point( 0, 0 ), Point( 0, aOutputSize.Height()-1 ) );
238 nOffX++;
239 aOutputSize.Width()--;
241 aDecoView.DrawButton( Rectangle( Point( nOffX, 0 ), aOutputSize ), BUTTON_DRAW_NOLIGHTBORDER );
244 // =======================================================================
246 // Heisst nicht Impl, da evtl. mal von aussen benutz- und ueberladbar
248 // --------------
249 // - TabBarEdit -
250 // --------------
252 class TabBarEdit : public Edit
254 private:
255 Timer maLoseFocusTimer;
256 sal_Bool mbPostEvt;
258 DECL_LINK( ImplEndEditHdl, void* );
259 DECL_LINK( ImplEndTimerHdl, void* );
261 public:
262 TabBarEdit( TabBar* pParent, WinBits nWinStyle = 0 );
264 TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
266 void SetPostEvent() { mbPostEvt = sal_True; }
267 void ResetPostEvent() { mbPostEvt = sal_False; }
269 virtual long PreNotify( NotifyEvent& rNEvt );
270 virtual void LoseFocus();
273 // -----------------------------------------------------------------------
275 TabBarEdit::TabBarEdit( TabBar* pParent, WinBits nWinStyle ) :
276 Edit( pParent, nWinStyle )
278 mbPostEvt = sal_False;
281 // -----------------------------------------------------------------------
283 long TabBarEdit::PreNotify( NotifyEvent& rNEvt )
285 if ( rNEvt.GetType() == EVENT_KEYINPUT )
287 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
288 if ( !pKEvt->GetKeyCode().GetModifier() )
290 if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN )
292 if ( !mbPostEvt )
294 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) )
295 mbPostEvt = sal_True;
297 return sal_True;
299 else if ( pKEvt->GetKeyCode().GetCode() == KEY_ESCAPE )
301 if ( !mbPostEvt )
303 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_True ) )
304 mbPostEvt = sal_True;
306 return sal_True;
311 return Edit::PreNotify( rNEvt );
314 // -----------------------------------------------------------------------
316 void TabBarEdit::LoseFocus()
318 if ( !mbPostEvt )
320 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) )
321 mbPostEvt = sal_True;
324 Edit::LoseFocus();
327 // -----------------------------------------------------------------------
329 IMPL_LINK( TabBarEdit, ImplEndEditHdl, void*, pCancel )
331 ResetPostEvent();
332 maLoseFocusTimer.Stop();
334 // We need this query, because the edit get a losefous event,
335 // when it shows the context menu or the insert symbol dialog
336 if ( !HasFocus() && HasChildPathFocus( sal_True ) )
338 maLoseFocusTimer.SetTimeout( 30 );
339 maLoseFocusTimer.SetTimeoutHdl( LINK( this, TabBarEdit, ImplEndTimerHdl ) );
340 maLoseFocusTimer.Start();
342 else
343 GetParent()->EndEditMode( pCancel != 0 );
345 return 0;
348 // -----------------------------------------------------------------------
350 IMPL_LINK_NOARG(TabBarEdit, ImplEndTimerHdl)
352 if ( HasFocus() )
353 return 0;
355 // We need this query, because the edit get a losefous event,
356 // when it shows the context menu or the insert symbol dialog
357 if ( HasChildPathFocus( sal_True ) )
358 maLoseFocusTimer.Start();
359 else
360 GetParent()->EndEditMode( sal_True );
362 return 0;
365 // =======================================================================
366 struct TabBar_Impl
368 ImplTabSizer* mpSizer;
369 ::svt::AccessibleFactoryAccess maAccessibleFactory;
371 TabBar_Impl()
372 :mpSizer( NULL )
375 ~TabBar_Impl()
377 delete mpSizer;
381 // =======================================================================
383 const sal_uInt16 TabBar::APPEND = ::std::numeric_limits<sal_uInt16>::max();
384 const sal_uInt16 TabBar::PAGE_NOT_FOUND = ::std::numeric_limits<sal_uInt16>::max();
385 const sal_uInt16 TabBar::INSERT_TAB_POS = ::std::numeric_limits<sal_uInt16>::max() - 1;
387 void TabBar::ImplInit( WinBits nWinStyle )
389 mpItemList = new ImplTabBarList;
390 mpFirstBtn = NULL;
391 mpPrevBtn = NULL;
392 mpNextBtn = NULL;
393 mpLastBtn = NULL;
394 mpImpl = new TabBar_Impl;
395 mpEdit = NULL;
396 mnMaxPageWidth = 0;
397 mnCurMaxWidth = 0;
398 mnOffX = 0;
399 mnOffY = 0;
400 mnLastOffX = 0;
401 mnSplitSize = 0;
402 mnSwitchTime = 0;
403 mnWinStyle = nWinStyle;
404 mnCurPageId = 0;
405 mnFirstPos = 0;
406 mnDropPos = 0;
407 mnSwitchId = 0;
408 mnEditId = 0;
409 mbFormat = sal_True;
410 mbFirstFormat = sal_True;
411 mbSizeFormat = sal_True;
412 mbAutoMaxWidth = sal_True;
413 mbInSwitching = sal_False;
414 mbAutoEditMode = sal_False;
415 mbEditCanceled = sal_False;
416 mbDropPos = sal_False;
417 mbInSelect = sal_False;
418 mbSelColor = sal_False;
419 mbSelTextColor = sal_False;
420 mbMirrored = sal_False;
421 mbMirrored = sal_False;
422 mbScrollAlwaysEnabled = false;
424 if ( nWinStyle & WB_3DTAB )
425 mnOffY++;
427 ImplInitControls();
429 if(mpFirstBtn)
430 mpFirstBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVET0HOME));
431 if(mpPrevBtn)
432 mpPrevBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVELEFT));
433 if(mpNextBtn)
434 mpNextBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVERIGHT));
435 if(mpLastBtn)
436 mpLastBtn->SetAccessibleName(SVT_RESSTR(STR_TABBAR_PUSHBUTTON_MOVETOEND));
438 SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) );
439 ImplInitSettings( sal_True, sal_True );
442 // -----------------------------------------------------------------------
444 TabBar::TabBar( Window* pParent, WinBits nWinStyle ) :
445 Window( pParent, (nWinStyle & WB_3DLOOK) | WB_CLIPCHILDREN )
447 ImplInit( nWinStyle );
448 maCurrentItemList = 0;
451 // -----------------------------------------------------------------------
453 TabBar::~TabBar()
455 EndEditMode( sal_True );
457 // Controls loeschen
458 if ( mpPrevBtn )
459 delete mpPrevBtn;
460 if ( mpNextBtn )
461 delete mpNextBtn;
462 if ( mpFirstBtn )
463 delete mpFirstBtn;
464 if ( mpLastBtn )
465 delete mpLastBtn;
466 delete mpImpl;
468 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i ) {
469 delete (*mpItemList)[ i ];
471 delete mpItemList;
474 // -----------------------------------------------------------------------
475 ImplTabBarItem* TabBar::seek( size_t i )
477 if ( i < mpItemList->size() )
479 maCurrentItemList = i;
480 return (*mpItemList)[ maCurrentItemList ];
482 return NULL;
485 ImplTabBarItem* TabBar::prev()
487 if ( maCurrentItemList > 0 ) {
488 return (*mpItemList)[ --maCurrentItemList ];
490 return NULL;
493 ImplTabBarItem* TabBar::next()
495 if ( maCurrentItemList+1 < mpItemList->size() ) {
496 return (*mpItemList)[ ++maCurrentItemList ];
498 return NULL;
501 // -----------------------------------------------------------------------
503 void TabBar::ImplInitSettings( sal_Bool bFont, sal_Bool bBackground )
505 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
507 if ( bFont )
509 Font aToolFont;
510 aToolFont = rStyleSettings.GetToolFont();
511 if ( IsControlFont() )
512 aToolFont.Merge( GetControlFont() );
513 aToolFont.SetWeight( WEIGHT_BOLD );
514 SetZoomedPointFont( aToolFont );
516 // Font in der groesse Anpassen, wenn Fenster zu klein?
517 while ( GetTextHeight() > (GetOutputSizePixel().Height()-1) )
519 Font aFont = GetFont();
520 if ( aFont.GetHeight() <= 6 )
521 break;
522 aFont.SetHeight( aFont.GetHeight()-1 );
523 SetFont( aFont );
527 if ( bBackground )
529 Color aColor;
530 if ( IsControlBackground() )
531 aColor = GetControlBackground();
532 else
533 aColor = rStyleSettings.GetFaceColor();
534 SetBackground( aColor );
538 // -----------------------------------------------------------------------
540 void TabBar::ImplGetColors( Color& rFaceColor, Color& rFaceTextColor,
541 Color& rSelectColor, Color& rSelectTextColor )
543 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
545 if ( IsControlBackground() )
546 rFaceColor = GetControlBackground();
547 else
548 rFaceColor = rStyleSettings.GetInactiveTabColor();
549 if ( IsControlForeground() )
550 rFaceTextColor = GetControlForeground();
551 else
552 rFaceTextColor = rStyleSettings.GetButtonTextColor();
553 if ( mbSelColor )
554 rSelectColor = maSelColor;
555 else
556 rSelectColor = rStyleSettings.GetActiveTabColor();
557 if ( mbSelTextColor )
558 rSelectTextColor = maSelTextColor;
559 else
560 rSelectTextColor = rStyleSettings.GetWindowTextColor();
562 // Bei 3D-Tabs wird Selektions- und Face-Farbe umgedreht, da die
563 // selektierten Tabs in 3D erscheinen sollen
564 if ( mnWinStyle & WB_3DTAB )
566 Color aTempColor = rFaceColor;
567 rFaceColor = rSelectColor;
568 rSelectColor = aTempColor;
569 aTempColor = rFaceTextColor;
570 rFaceTextColor = rSelectTextColor;
571 rSelectTextColor = rFaceTextColor;
575 // -----------------------------------------------------------------------
577 sal_Bool TabBar::ImplCalcWidth()
579 // Groessen muessen nur ermittelt werden, wenn sich Text aendert oder
580 // wenn der Font geaendert wurde
581 if ( !mbSizeFormat )
582 return sal_False;
584 // Breiten der Tabs mit dem fetten Font ermitteln
585 Font aFont = GetFont();
586 if ( aFont.GetWeight() != WEIGHT_BOLD )
588 aFont.SetWeight( WEIGHT_BOLD );
589 SetFont( aFont );
592 if ( mnMaxPageWidth )
593 mnCurMaxWidth = mnMaxPageWidth;
594 else if ( mbAutoMaxWidth )
596 mnCurMaxWidth = mnLastOffX-mnOffX-
597 TABBAR_OFFSET_X-TABBAR_OFFSET_X-
598 TABBAR_OFFSET_X2-TABBAR_OFFSET_X2-TABBAR_OFFSET_X2;
599 if ( mnCurMaxWidth < 1 )
600 mnCurMaxWidth = 1;
602 else
603 mnCurMaxWidth = 0;
605 sal_Bool bChanged = sal_False;
606 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
608 ImplTabBarItem* pItem = (*mpItemList)[ i ];
609 long nNewWidth = GetTextWidth( pItem->maText );
610 if ( mnCurMaxWidth && (nNewWidth > mnCurMaxWidth) )
612 pItem->mbShort = sal_True;
613 nNewWidth = mnCurMaxWidth;
615 else
616 pItem->mbShort = sal_False;
617 nNewWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
618 if ( pItem->mnWidth != nNewWidth )
620 pItem->mnWidth = nNewWidth;
621 if ( !pItem->maRect.IsEmpty() )
622 bChanged = sal_True;
625 mbSizeFormat = sal_False;
626 mbFormat = sal_True;
627 return bChanged;
630 // -----------------------------------------------------------------------
632 void TabBar::ImplFormat()
634 ImplCalcWidth();
636 if ( !mbFormat )
637 return;
639 sal_uInt16 n = 0;
640 long x = mnOffX;
641 for ( size_t i = 0, nL = mpItemList->size(); i < nL; ++i )
643 ImplTabBarItem* pItem = (*mpItemList)[ i ];
644 // Bei allen nicht sichtbaren Tabs, wird ein leeres Rechteck
645 // gesetzt
646 if ( (n+1 < mnFirstPos) || (x > mnLastOffX) )
647 pItem->maRect.SetEmpty();
648 else
650 // Etwas von der Tab vor der ersten sichtbaren Page
651 // muss auch zu sehen sein
652 if ( n+1 == mnFirstPos )
653 pItem->maRect.Left() = x-pItem->mnWidth;
654 else
656 pItem->maRect.Left() = x;
657 x += pItem->mnWidth;
659 pItem->maRect.Right() = x+TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
660 pItem->maRect.Bottom() = maWinSize.Height()-1;
662 if( mbMirrored )
664 long nTmp = mnOffX + mnLastOffX - pItem->maRect.Right();
665 pItem->maRect.Right() = mnOffX + mnLastOffX - pItem->maRect.Left();
666 pItem->maRect.Left() = nTmp;
670 n++;
673 mbFormat = sal_False;
675 // Button enablen/disablen
676 ImplEnableControls();
679 // -----------------------------------------------------------------------
681 sal_uInt16 TabBar::ImplGetLastFirstPos()
683 sal_uInt16 nCount = (sal_uInt16)(mpItemList->size());
684 if ( !nCount || mbSizeFormat || mbFormat )
685 return 0;
687 sal_uInt16 nLastFirstPos = nCount-1;
688 long nWinWidth = mnLastOffX-mnOffX-TABBAR_OFFSET_X-ADDNEWPAGE_AREAWIDTH;
689 long nWidth = (*mpItemList)[ nLastFirstPos ]->mnWidth;
690 while ( nLastFirstPos && (nWidth < nWinWidth) )
692 nLastFirstPos--;
693 nWidth += (*mpItemList)[ nLastFirstPos ]->mnWidth;
695 if ( (nLastFirstPos != (sal_uInt16)(mpItemList->size()-1)) &&
696 (nWidth > nWinWidth) )
697 nLastFirstPos++;
698 return nLastFirstPos;
701 // -----------------------------------------------------------------------
703 void TabBar::ImplInitControls()
705 if ( mnWinStyle & WB_SIZEABLE )
707 if ( !mpImpl->mpSizer )
708 mpImpl->mpSizer = new ImplTabSizer( this, mnWinStyle & (WB_DRAG | WB_3DLOOK) );
709 mpImpl->mpSizer->Show();
711 else
713 DELETEZ( mpImpl->mpSizer );
716 Link aLink = LINK( this, TabBar, ImplClickHdl );
718 if ( mnWinStyle & (WB_MINSCROLL | WB_SCROLL) )
720 if ( !mpPrevBtn )
722 mpPrevBtn = new ImplTabButton( this, WB_REPEAT );
723 mpPrevBtn->SetClickHdl( aLink );
725 mpPrevBtn->SetSymbol( mbMirrored ? SYMBOL_NEXT : SYMBOL_PREV );
726 mpPrevBtn->Show();
728 if ( !mpNextBtn )
730 mpNextBtn = new ImplTabButton( this, WB_REPEAT );
731 mpNextBtn->SetClickHdl( aLink );
733 mpNextBtn->SetSymbol( mbMirrored ? SYMBOL_PREV : SYMBOL_NEXT );
734 mpNextBtn->Show();
736 else
738 DELETEZ( mpPrevBtn );
739 DELETEZ( mpNextBtn );
742 if ( mnWinStyle & WB_SCROLL )
744 if ( !mpFirstBtn )
746 mpFirstBtn = new ImplTabButton( this );
747 mpFirstBtn->SetClickHdl( aLink );
749 mpFirstBtn->SetSymbol( mbMirrored ? SYMBOL_LAST : SYMBOL_FIRST );
750 mpFirstBtn->Show();
752 if ( !mpLastBtn )
754 mpLastBtn = new ImplTabButton( this );
755 mpLastBtn->SetClickHdl( aLink );
757 mpLastBtn->SetSymbol( mbMirrored ? SYMBOL_FIRST : SYMBOL_LAST );
758 mpLastBtn->Show();
760 else
762 DELETEZ( mpFirstBtn );
763 DELETEZ( mpLastBtn );
766 mbHasInsertTab = (mnWinStyle & WB_INSERTTAB);
769 // -----------------------------------------------------------------------
771 void TabBar::ImplEnableControls()
773 if ( mbSizeFormat || mbFormat )
774 return;
776 // Buttons enablen/disblen
777 sal_Bool bEnableBtn = mbScrollAlwaysEnabled || mnFirstPos > 0;
778 if ( mpFirstBtn )
779 mpFirstBtn->Enable( bEnableBtn );
780 if ( mpPrevBtn )
781 mpPrevBtn->Enable( bEnableBtn );
783 bEnableBtn = mbScrollAlwaysEnabled || mnFirstPos < ImplGetLastFirstPos();
784 if ( mpNextBtn )
785 mpNextBtn->Enable( bEnableBtn );
786 if ( mpLastBtn )
787 mpLastBtn->Enable( bEnableBtn );
790 void TabBar::SetScrollAlwaysEnabled(bool bScrollAlwaysEnabled)
792 mbScrollAlwaysEnabled = bScrollAlwaysEnabled;
793 ImplEnableControls();
796 // -----------------------------------------------------------------------
798 void TabBar::ImplShowPage( sal_uInt16 nPos )
800 // Breite berechnen
801 long nWidth = GetOutputSizePixel().Width();
802 if ( nWidth >= TABBAR_OFFSET_X )
803 nWidth -= TABBAR_OFFSET_X;
804 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
805 if ( nPos < mnFirstPos )
806 SetFirstPageId( pItem->mnId );
807 else if ( pItem->maRect.Right() > nWidth )
809 while ( pItem->maRect.Right() > nWidth )
811 sal_uInt16 nNewPos = mnFirstPos+1;
812 SetFirstPageId( GetPageId( nNewPos ) );
813 ImplFormat();
814 if ( nNewPos != mnFirstPos )
815 break;
820 // -----------------------------------------------------------------------
822 IMPL_LINK( TabBar, ImplClickHdl, ImplTabButton*, pBtn )
824 EndEditMode();
826 sal_uInt16 nNewPos = mnFirstPos;
828 if ( pBtn == mpFirstBtn )
829 nNewPos = 0;
830 else if ( pBtn == mpPrevBtn )
832 if ( mnFirstPos )
833 nNewPos = mnFirstPos-1;
835 else if ( pBtn == mpNextBtn )
837 sal_uInt16 nCount = GetPageCount();
838 if ( mnFirstPos < nCount )
839 nNewPos = mnFirstPos+1;
841 else
843 sal_uInt16 nCount = GetPageCount();
844 if ( nCount )
845 nNewPos = nCount-1;
848 if ( nNewPos != mnFirstPos )
849 SetFirstPageId( GetPageId( nNewPos ) );
850 return 0;
853 // -----------------------------------------------------------------------
855 void TabBar::MouseMove( const MouseEvent& rMEvt )
857 if ( rMEvt.IsLeaveWindow() )
858 mbInSelect = sal_False;
860 Window::MouseMove( rMEvt );
863 // -----------------------------------------------------------------------
865 void TabBar::MouseButtonDown( const MouseEvent& rMEvt )
867 // Bei Klick in unser Fenster EditModus nur beenden und Klick nicht
868 // ausfuehren
869 if ( IsInEditMode() )
871 EndEditMode();
872 return;
875 ImplTabBarItem* pItem;
876 sal_uInt16 nSelId = GetPageId( rMEvt.GetPosPixel() );
878 if ( !rMEvt.IsLeft() )
880 Window::MouseButtonDown( rMEvt );
881 if ( (nSelId > 0) && (nSelId != mnCurPageId) )
883 sal_uInt16 nPos = GetPagePos( nSelId );
884 pItem = (*mpItemList)[ nPos ];
886 if ( pItem->mbEnable )
888 if ( ImplDeactivatePage() )
890 SetCurPageId( nSelId );
891 Update();
892 ImplActivatePage();
893 ImplSelect();
895 mbInSelect = sal_True;
898 return;
901 if ( rMEvt.IsMod2() && mbAutoEditMode && nSelId )
903 if ( StartEditMode( nSelId ) )
904 return;
907 if ( (rMEvt.GetMode() & (MOUSE_MULTISELECT | MOUSE_RANGESELECT)) && (rMEvt.GetClicks() == 1) )
909 if ( nSelId )
911 sal_uInt16 nPos = GetPagePos( nSelId );
912 sal_Bool bSelectTab = sal_False;
913 pItem = (*mpItemList)[ nPos ];
915 if ( pItem->mbEnable )
917 if ( (rMEvt.GetMode() & MOUSE_MULTISELECT) && (mnWinStyle & WB_MULTISELECT) )
919 if ( nSelId != mnCurPageId )
921 SelectPage( nSelId, !IsPageSelected( nSelId ) );
922 bSelectTab = sal_True;
925 else if ( mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT) )
927 bSelectTab = sal_True;
928 sal_uInt16 n;
929 sal_Bool bSelect;
930 sal_uInt16 nCurPos = GetPagePos( mnCurPageId );
931 if ( nPos <= nCurPos )
933 // Alle Tabs bis zur angeklickten Tab deselektieren
934 // und alle Tabs von der angeklickten Tab bis
935 // zur aktuellen Position selektieren
936 n = 0;
937 while ( n < nCurPos )
939 pItem = (*mpItemList)[ n ];
940 if ( n < nPos )
941 bSelect = sal_False;
942 else
943 bSelect = sal_True;
945 if ( pItem->mbSelect != bSelect )
947 pItem->mbSelect = bSelect;
948 if ( !pItem->maRect.IsEmpty() )
949 Invalidate( pItem->maRect );
952 n++;
956 if ( nPos >= nCurPos )
958 // Alle Tabs von der aktuellen bis zur angeklickten
959 // Tab selektieren und alle Tabs von der angeklickten
960 // Tab bis zur letzten Tab deselektieren
961 sal_uInt16 nCount = (sal_uInt16)mpItemList->size();
962 n = nCurPos;
963 while ( n < nCount )
965 pItem = (*mpItemList)[ n ];
967 if ( n <= nPos )
968 bSelect = sal_True;
969 else
970 bSelect = sal_False;
972 if ( pItem->mbSelect != bSelect )
974 pItem->mbSelect = bSelect;
975 if ( !pItem->maRect.IsEmpty() )
976 Invalidate( pItem->maRect );
979 n++;
984 // Gegebenenfalls muss die selektierte Tab gescrollt werden
985 if ( bSelectTab )
987 ImplShowPage( nPos );
988 Update();
989 ImplSelect();
992 else
993 ImplShowPage( nPos );
994 mbInSelect = sal_True;
996 return;
999 else if ( rMEvt.GetClicks() == 2 )
1001 // Gegebenenfalls den Double-Click-Handler rufen
1002 if ( !rMEvt.GetModifier() && (!nSelId || (nSelId == mnCurPageId)) )
1004 sal_uInt16 nOldCurId = mnCurPageId;
1005 mnCurPageId = nSelId;
1006 DoubleClick();
1007 // Abfrage, da im DoubleClick-Handler die aktuelle Seite
1008 // umgeschaltet werden konnte
1009 if ( mnCurPageId == nSelId )
1010 mnCurPageId = nOldCurId;
1013 return;
1015 else
1017 if ( nSelId )
1019 // Nur Select ausfuehren, wenn noch nicht aktuelle Page
1020 if ( nSelId != mnCurPageId )
1022 sal_uInt16 nPos = GetPagePos( nSelId );
1023 pItem = (*mpItemList)[ nPos ];
1025 if ( pItem->mbEnable )
1027 if ( !pItem->mbSelect )
1029 // Muss invalidiert werden
1030 sal_Bool bUpdate = sal_False;
1031 if ( IsReallyVisible() && IsUpdateMode() )
1032 bUpdate = sal_True;
1034 // Alle selektierten Items deselektieren
1035 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
1037 pItem = (*mpItemList)[ i ];
1038 if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) )
1040 pItem->mbSelect = sal_False;
1041 if ( bUpdate )
1042 Invalidate( pItem->maRect );
1047 if ( ImplDeactivatePage() )
1049 SetCurPageId( nSelId );
1050 Update();
1051 ImplActivatePage();
1052 ImplSelect();
1055 else
1056 ImplShowPage( nPos );
1057 mbInSelect = sal_True;
1060 return;
1064 Window::MouseButtonDown( rMEvt );
1067 // -----------------------------------------------------------------------
1069 void TabBar::MouseButtonUp( const MouseEvent& rMEvt )
1071 mbInSelect = sal_False;
1072 Window::MouseButtonUp( rMEvt );
1076 // -----------------------------------------------------------------------
1078 namespace {
1080 class TabBarPaintGuard
1082 public:
1083 explicit TabBarPaintGuard(TabBar& rParent) :
1084 mrParent(rParent),
1085 maFont(rParent.GetFont())
1087 // #i36013# exclude push buttons from painting area
1088 mrParent.SetClipRegion( Region(mrParent.GetPageArea()) );
1091 ~TabBarPaintGuard()
1093 // Restore original font.
1094 mrParent.SetFont(maFont);
1095 // remove clip region
1096 mrParent.SetClipRegion();
1098 private:
1099 TabBar& mrParent;
1100 Font maFont;
1103 class TabDrawer
1105 public:
1107 explicit TabDrawer(TabBar& rParent) :
1108 mrParent(rParent),
1109 mpStyleSettings(&mrParent.GetSettings().GetStyleSettings()),
1110 maPoly(4),
1111 mbSelected(false),
1112 mbCustomColored(false),
1113 mbSpecialTab(false),
1114 mbEnabled(false)
1118 void drawOutputAreaBorder()
1120 WinBits nWinStyle = mrParent.GetStyle();
1122 // Bei Border oben und unten einen Strich extra malen
1123 if ( (nWinStyle & WB_BORDER) || (nWinStyle & WB_TOPBORDER) )
1125 Size aOutputSize = mrParent.GetOutputSizePixel();
1126 Rectangle aOutRect = mrParent.GetPageArea();
1128 // Bei 3D-Tabs wird auch der Border in 3D gemalt
1129 if ( nWinStyle & WB_3DTAB )
1131 mrParent.SetLineColor( mpStyleSettings->GetShadowColor() );
1132 mrParent.DrawLine( Point( aOutRect.Left(), 0 ), Point( aOutputSize.Width(), 0 ) );
1135 // Border malen (Strich oben und Strich unten)
1136 mrParent.SetLineColor( mpStyleSettings->GetDarkShadowColor() );
1137 mrParent.DrawLine( aOutRect.TopLeft(), Point( aOutputSize.Width()-1, aOutRect.Top() ) );
1141 void drawOuterFrame()
1143 mrParent.DrawPolygon(maPoly);
1146 void drawLeftShadow()
1148 Point p1 = maPoly[0], p2 = maPoly[1];
1149 p1.X()++;
1150 p2.X()++;
1151 p2.Y()--;
1152 mrParent.DrawLine(p1, p2);
1155 void drawRightShadow()
1157 Point p1 = maPoly[2];
1158 Point p2 = maPoly[3];
1159 p1.X()--;
1160 p2.X()--;
1161 mrParent.DrawLine(p1, p2);
1164 void drawTopInnerShadow()
1166 Point p1 = maPoly[0], p2 = maPoly[3];
1167 p1.Y()++;
1168 p2.Y()++;
1169 mrParent.DrawLine(p1, p2);
1172 void drawBottomShadow(bool bColored)
1174 Point p1 = maPoly[1], p2 = maPoly[2];
1175 p1.X() += 1;
1176 p1.Y() -= 1;
1177 p2.X() -= 1;
1178 p2.Y() -= 1;
1179 mrParent.DrawLine(p1, p2);
1180 if (bColored)
1182 p1 += Point(-1, -1);
1183 p2 += Point(1, -1);
1184 mrParent.DrawLine(p1, p2);
1188 void drawText(const OUString& aText)
1190 Rectangle aRect = maRect;
1191 long nTextWidth = mrParent.GetTextWidth(aText);
1192 long nTextHeight = mrParent.GetTextHeight();
1193 Point aPos = aRect.TopLeft();
1194 aPos.X() += (aRect.getWidth() - nTextWidth) / 2;
1195 aPos.Y() += (aRect.getHeight() - nTextHeight) / 2;
1197 if (mbEnabled)
1198 mrParent.DrawText(aPos, aText);
1199 else
1200 mrParent.DrawCtrlText(
1201 aPos, aText, 0, STRING_LEN, (TEXT_DRAW_DISABLE | TEXT_DRAW_MNEMONIC));
1204 void drawOverTopBorder(bool b3DTab)
1206 Point p1 = maPoly[0], p2 = maPoly[3];
1207 p1.X() += 1;
1208 p2.X() -= 1;
1209 Rectangle aDelRect(p1, p2);
1210 mrParent.DrawRect(aDelRect);
1211 if (b3DTab)
1213 aDelRect.Top()--;
1214 mrParent.DrawRect(aDelRect);
1218 void drawTab()
1220 mrParent.SetLineColor(mpStyleSettings->GetDarkShadowColor());
1222 // Je nach Status die richtige FillInBrush setzen
1223 // Set the correct FillInBrush depending upon status
1224 if ( mbSelected )
1226 // Currently selected Tab
1227 mrParent.SetFillColor( maSelectedColor );
1229 else if ( mbCustomColored )
1231 mrParent.SetFillColor( maCustomColor );
1233 else
1235 mrParent.SetFillColor( maUnselectedColor );
1238 drawOuterFrame();
1240 // If this is the current tab, draw the left inner shadow the default color,
1241 // otherwise make it the same as the custom background color
1242 Color aColor = mpStyleSettings->GetLightColor();
1243 if (mbCustomColored && !mbSelected)
1244 aColor = maCustomColor;
1246 mrParent.SetLineColor(aColor);
1247 drawLeftShadow();
1249 if ( !mbSelected )
1250 drawTopInnerShadow();
1252 mrParent.SetLineColor( mpStyleSettings->GetShadowColor() );
1253 drawRightShadow();
1254 if ( mbCustomColored && mbSelected )
1256 mrParent.SetLineColor(maCustomColor);
1257 drawBottomShadow(true);
1259 else
1260 drawBottomShadow(false);
1262 // Draw the outer frame once more. In some environments, the outer frame
1263 // gets overpainted.
1264 mrParent.SetLineColor( mpStyleSettings->GetDarkShadowColor() );
1265 mrParent.SetFillColor();
1266 drawOuterFrame();
1269 void drawPlusImage()
1271 SvtResId id( BMP_LIST_ADD );
1272 Image aPlusImg( id );
1273 // Center the image within the bounding rectangle.
1274 Size aSize = aPlusImg.GetSizePixel();
1275 Point pt = maRect.TopLeft();
1276 long nXOffSet = (maRect.GetWidth() - aSize.Width()) / 2;
1277 long nYOffset = (maRect.GetHeight() - aSize.Height()) / 2;
1278 pt += Point(nXOffSet, nYOffset);
1279 pt.X() += 1;
1280 mrParent.DrawImage(pt, aPlusImg);
1283 void setRect(const Rectangle& rRect)
1285 maRect = rRect;
1287 long nOffY = mrParent.GetPageArea().getY();
1289 // Zuerst geben wir das Polygon gefuellt aus
1290 maPoly[0] = Point( rRect.Left(), nOffY );
1291 maPoly[1] = Point( rRect.Left()+TABBAR_OFFSET_X, rRect.Bottom() );
1292 maPoly[2] = Point( rRect.Right()-TABBAR_OFFSET_X, rRect.Bottom() );
1293 maPoly[3] = Point( rRect.Right(), nOffY );
1296 void setSelected(bool b)
1298 mbSelected = b;
1301 void setCustomColored(bool b)
1303 mbCustomColored = b;
1306 void setSpecialTab(bool b)
1308 mbSpecialTab = b;
1311 void setEnabled(bool b)
1313 mbEnabled = b;
1316 void setSelectedFillColor(const Color& rColor)
1318 maSelectedColor = rColor;
1321 void setUnselectedFillColor(const Color& rColor)
1323 maUnselectedColor = rColor;
1326 void setCustomColor(const Color& rColor)
1328 maCustomColor = rColor;
1331 private:
1332 TabBar& mrParent;
1333 const StyleSettings* mpStyleSettings;
1335 Rectangle maRect;
1336 Polygon maPoly;
1338 Color maSelectedColor;
1339 Color maCustomColor;
1340 Color maUnselectedColor;
1342 bool mbSelected:1;
1343 bool mbCustomColored:1;
1344 bool mbSpecialTab:1;
1345 bool mbEnabled:1;
1350 void TabBar::Paint( const Rectangle& rect )
1352 if(IsNativeControlSupported(CTRL_WINDOW_BACKGROUND,PART_ENTIRE_CONTROL))
1353 DrawNativeControl(CTRL_WINDOW_BACKGROUND,PART_ENTIRE_CONTROL,rect,
1354 CTRL_STATE_ENABLED,ImplControlValue(0),OUString());
1356 // Items berechnen und ausgeben
1357 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
1358 if (!nItemCount)
1359 return;
1361 ImplPrePaint();
1363 Color aFaceColor, aSelectColor, aFaceTextColor, aSelectTextColor;
1364 ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor );
1366 // Font selektieren
1367 Font aFont = GetFont();
1368 Font aLightFont = aFont;
1369 aLightFont.SetWeight( WEIGHT_NORMAL );
1371 TabBarPaintGuard aGuard(*this);
1372 TabDrawer aDrawer(*this);
1373 aDrawer.setSelectedFillColor(aSelectColor);
1374 aDrawer.setUnselectedFillColor(aFaceColor);
1375 aDrawer.drawOutputAreaBorder();
1377 // Now, start drawing the tabs.
1379 ImplTabBarItem* pItem = ImplGetLastTabBarItem(nItemCount);
1381 if (pItem && mbHasInsertTab)
1383 // Draw the insert tab at the right end.
1384 Rectangle aRect = ImplGetInsertTabRect(pItem);
1385 aDrawer.setRect(aRect);
1386 aDrawer.drawTab();
1387 aDrawer.drawPlusImage();
1390 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1391 ImplTabBarItem* pCurItem = NULL;
1392 while ( pItem )
1394 // CurrentItem als letztes ausgeben, da es alle anderen ueberdeckt
1395 if ( !pCurItem && (pItem->mnId == mnCurPageId) )
1397 pCurItem = pItem;
1398 pItem = prev();
1399 if ( !pItem )
1400 pItem = pCurItem;
1401 continue;
1404 bool bCurrent = pItem == pCurItem;
1406 if ( !pItem->maRect.IsEmpty() )
1408 Rectangle aRect = pItem->maRect;
1409 bool bSelected = pItem->IsSelected(pCurItem);
1410 // We disable custom background color in high contrast mode.
1411 bool bCustomBgColor = !pItem->IsDefaultTabBgColor() && !rStyleSettings.GetHighContrastMode();
1412 bool bSpecialTab = (pItem->mnBits & TPB_SPECIAL);
1413 bool bEnabled = pItem->mbEnable;
1414 OUString aText = pItem->mbShort ?
1415 GetEllipsisString(pItem->maText, mnCurMaxWidth, TEXT_DRAW_ENDELLIPSIS) : pItem->maText;
1417 aDrawer.setRect(aRect);
1418 aDrawer.setSelected(bSelected);
1419 aDrawer.setCustomColored(bCustomBgColor);
1420 aDrawer.setSpecialTab(bSpecialTab);
1421 aDrawer.setEnabled(bEnabled);
1422 aDrawer.setCustomColor(pItem->maTabBgColor);
1423 aDrawer.drawTab();
1425 // Aktuelle Page wird mit einem fetten Font ausgegeben
1426 if ( bCurrent )
1427 SetFont( aFont );
1428 else
1429 SetFont( aLightFont );
1431 // Je nach Status die richtige FillInBrush setzen
1432 // Set the correct FillInBrush depending upon status
1433 if ( bSelected )
1434 SetTextColor( aSelectTextColor );
1435 else if ( bCustomBgColor )
1436 SetTextColor( pItem->maTabTextColor );
1437 else
1438 SetTextColor( aFaceTextColor );
1440 // This tab is "special", and a special tab needs a blue text.
1441 if (bSpecialTab)
1442 SetTextColor(Color(COL_LIGHTBLUE));
1444 aDrawer.drawText(aText);
1446 if ( bCurrent )
1448 SetLineColor();
1449 SetFillColor(aSelectColor);
1450 aDrawer.drawOverTopBorder(mnWinStyle & WB_3DTAB);
1451 return;
1454 pItem = prev();
1456 else
1458 if ( bCurrent )
1459 return;
1461 pItem = NULL;
1464 if ( !pItem )
1465 pItem = pCurItem;
1469 // -----------------------------------------------------------------------
1470 void TabBar::Resize()
1472 Size aNewSize = GetOutputSizePixel();
1474 long nSizerWidth = 0;
1475 long nButtonWidth = 0;
1477 // Sizer anordnen
1478 if ( mpImpl->mpSizer )
1480 Size aSizerSize = mpImpl->mpSizer->GetSizePixel();
1481 Point aNewSizerPos( mbMirrored ? 0 : (aNewSize.Width()-aSizerSize.Width()), 0 );
1482 Size aNewSizerSize( aSizerSize.Width(), aNewSize.Height() );
1483 mpImpl->mpSizer->SetPosSizePixel( aNewSizerPos, aNewSizerSize );
1484 nSizerWidth = aSizerSize.Width();
1487 // Scroll-Buttons anordnen
1488 long nHeight = aNewSize.Height();
1489 // Font in der groesse Anpassen?
1490 ImplInitSettings( sal_True, sal_False );
1492 long nX = mbMirrored ? (aNewSize.Width()-nHeight) : 0;
1493 long nXDiff = mbMirrored ? -nHeight : nHeight;
1495 Size aBtnSize( nHeight, nHeight );
1496 if ( mpFirstBtn )
1498 mpFirstBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1499 nX += nXDiff;
1500 nButtonWidth += nHeight;
1502 if ( mpPrevBtn )
1504 mpPrevBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1505 nX += nXDiff;
1506 nButtonWidth += nHeight;
1508 if ( mpNextBtn )
1510 mpNextBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1511 nX += nXDiff;
1512 nButtonWidth += nHeight;
1514 if ( mpLastBtn )
1516 mpLastBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
1517 nX += nXDiff;
1518 nButtonWidth += nHeight;
1521 // Groesse merken
1522 maWinSize = aNewSize;
1524 if( mbMirrored )
1526 mnOffX = nSizerWidth;
1527 mnLastOffX = maWinSize.Width() - nButtonWidth - 1;
1529 else
1531 mnOffX = nButtonWidth;
1532 mnLastOffX = maWinSize.Width() - nSizerWidth - 1;
1535 // Neu formatieren
1536 mbSizeFormat = sal_True;
1537 if ( IsReallyVisible() )
1539 if ( ImplCalcWidth() )
1540 Invalidate();
1541 ImplFormat();
1544 // Button enablen/disablen
1545 ImplEnableControls();
1548 // -----------------------------------------------------------------------
1550 void TabBar::RequestHelp( const HelpEvent& rHEvt )
1552 sal_uInt16 nItemId = GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
1553 if ( nItemId )
1555 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
1557 OUString aStr = GetHelpText( nItemId );
1558 if (!aStr.isEmpty())
1560 Rectangle aItemRect = GetPageRect( nItemId );
1561 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1562 aItemRect.Left() = aPt.X();
1563 aItemRect.Top() = aPt.Y();
1564 aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1565 aItemRect.Right() = aPt.X();
1566 aItemRect.Bottom() = aPt.Y();
1567 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
1568 return;
1571 else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
1573 OUString aHelpId( OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) );
1574 if ( !aHelpId.isEmpty() )
1576 // Wenn eine Hilfe existiert, dann ausloesen
1577 Help* pHelp = Application::GetHelp();
1578 if ( pHelp )
1579 pHelp->Start( aHelpId, this );
1580 return;
1584 // Bei Quick- oder Ballloon-Help zeigen wir den Text an,
1585 // wenn dieser abgeschnitten oder nicht voll sichtbar ist
1586 if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
1588 sal_uInt16 nPos = GetPagePos( nItemId );
1589 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
1590 if ( pItem->mbShort ||
1591 (pItem->maRect.Right()-TABBAR_OFFSET_X-5 > mnLastOffX) )
1593 Rectangle aItemRect = GetPageRect( nItemId );
1594 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
1595 aItemRect.Left() = aPt.X();
1596 aItemRect.Top() = aPt.Y();
1597 aPt = OutputToScreenPixel( aItemRect.BottomRight() );
1598 aItemRect.Right() = aPt.X();
1599 aItemRect.Bottom() = aPt.Y();
1600 OUString aStr = (*mpItemList)[ nPos ]->maText;
1601 if (!aStr.isEmpty())
1603 if ( rHEvt.GetMode() & HELPMODE_BALLOON )
1604 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
1605 else
1606 Help::ShowQuickHelp( this, aItemRect, aStr );
1607 return;
1613 Window::RequestHelp( rHEvt );
1616 // -----------------------------------------------------------------------
1618 void TabBar::StateChanged( StateChangedType nType )
1620 Window::StateChanged( nType );
1622 if ( nType == STATE_CHANGE_INITSHOW )
1624 if ( (mbSizeFormat || mbFormat) && !mpItemList->empty() )
1625 ImplFormat();
1627 else if ( (nType == STATE_CHANGE_ZOOM) ||
1628 (nType == STATE_CHANGE_CONTROLFONT) )
1630 ImplInitSettings( sal_True, sal_False );
1631 Invalidate();
1633 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
1634 Invalidate();
1635 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1637 ImplInitSettings( sal_False, sal_True );
1638 Invalidate();
1640 else if ( nType == STATE_CHANGE_MIRRORING )
1642 // reacts on calls of EnableRTL, have to mirror all child controls
1643 if( mpFirstBtn ) mpFirstBtn->EnableRTL( IsRTLEnabled() );
1644 if( mpPrevBtn ) mpPrevBtn->EnableRTL( IsRTLEnabled() );
1645 if( mpNextBtn ) mpNextBtn->EnableRTL( IsRTLEnabled() );
1646 if( mpLastBtn ) mpLastBtn->EnableRTL( IsRTLEnabled() );
1647 if( mpImpl->mpSizer ) mpImpl->mpSizer->EnableRTL( IsRTLEnabled() );
1648 if( mpEdit ) mpEdit->EnableRTL( IsRTLEnabled() );
1652 // -----------------------------------------------------------------------
1654 void TabBar::DataChanged( const DataChangedEvent& rDCEvt )
1656 Window::DataChanged( rDCEvt );
1658 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1659 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1660 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1661 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1663 ImplInitSettings( sal_True, sal_True );
1664 Invalidate();
1668 // -----------------------------------------------------------------------
1670 void TabBar::ImplSelect()
1672 Select();
1674 CallEventListeners( VCLEVENT_TABBAR_PAGESELECTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
1677 // -----------------------------------------------------------------------
1679 void TabBar::Select()
1681 maSelectHdl.Call( this );
1684 // -----------------------------------------------------------------------
1686 void TabBar::DoubleClick()
1688 maDoubleClickHdl.Call( this );
1691 // -----------------------------------------------------------------------
1693 void TabBar::Split()
1695 maSplitHdl.Call( this );
1698 // -----------------------------------------------------------------------
1700 void TabBar::ImplActivatePage()
1702 ActivatePage();
1704 CallEventListeners( VCLEVENT_TABBAR_PAGEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
1707 // -----------------------------------------------------------------------
1709 void TabBar::ActivatePage()
1711 maActivatePageHdl.Call( this );
1714 // -----------------------------------------------------------------------
1716 long TabBar::ImplDeactivatePage()
1718 long nRet = DeactivatePage();
1720 CallEventListeners( VCLEVENT_TABBAR_PAGEDEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
1722 return nRet;
1725 void TabBar::ImplPrePaint()
1727 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
1728 if (!nItemCount)
1729 return;
1731 ImplTabBarItem* pItem;
1733 // TabBar muss formatiert sein
1734 ImplFormat();
1736 // Beim ersten Format auch dafuer sorgen, das aktuelle TabPage
1737 // sichtbar wird
1738 if ( mbFirstFormat )
1740 mbFirstFormat = sal_False;
1742 if ( mnCurPageId && (mnFirstPos == 0) && !mbDropPos )
1744 pItem = (*mpItemList)[ GetPagePos( mnCurPageId ) ];
1745 if ( pItem->maRect.IsEmpty() )
1747 // mbDropPos setzen (bzw. misbrauchen) um Invalidate()
1748 // zu unterbinden
1749 mbDropPos = sal_True;
1750 SetFirstPageId( mnCurPageId );
1751 mbDropPos = sal_False;
1752 if ( mnFirstPos != 0 )
1753 ImplFormat();
1759 ImplTabBarItem* TabBar::ImplGetLastTabBarItem( sal_uInt16 nItemCount )
1761 // letzten sichtbaren Eintrag suchen
1762 sal_uInt16 n = mnFirstPos+1;
1763 if ( n >= nItemCount )
1764 n = nItemCount-1;
1765 ImplTabBarItem* pItem = seek( n );
1766 while ( pItem )
1768 if ( !pItem->maRect.IsEmpty() )
1770 n++;
1771 pItem = next();
1773 else
1774 break;
1777 // Alle Tabs ausgeben (von hinten nach vorn und aktuellen zuletzt)
1778 if ( pItem )
1779 n--;
1780 else if ( n >= nItemCount )
1781 n = nItemCount-1;
1782 pItem = seek( n );
1783 return pItem;
1786 Rectangle TabBar::ImplGetInsertTabRect(ImplTabBarItem* pItem) const
1788 if (mbHasInsertTab && pItem)
1790 Rectangle aInsTabRect = pItem->maRect;
1791 if ( !mbMirrored )
1792 aInsTabRect.setX(
1793 aInsTabRect.getX() + aInsTabRect.getWidth() - TABBAR_OFFSET_X - TABBAR_OFFSET_X2);
1794 else
1795 aInsTabRect.setX(
1796 aInsTabRect.getX() - 3*TABBAR_OFFSET_X - TABBAR_OFFSET_X2);
1797 aInsTabRect.setWidth(32);
1798 return aInsTabRect;
1800 return Rectangle();
1803 // -----------------------------------------------------------------------
1805 long TabBar::DeactivatePage()
1807 if ( maDeactivatePageHdl.IsSet() )
1808 return maDeactivatePageHdl.Call( this );
1809 else
1810 return sal_True;
1813 // -----------------------------------------------------------------------
1815 long TabBar::StartRenaming()
1817 if ( maStartRenamingHdl.IsSet() )
1818 return maStartRenamingHdl.Call( this );
1819 else
1820 return sal_True;
1823 // -----------------------------------------------------------------------
1825 long TabBar::AllowRenaming()
1827 if ( maAllowRenamingHdl.IsSet() )
1828 return maAllowRenamingHdl.Call( this );
1829 else
1830 return sal_True;
1833 // -----------------------------------------------------------------------
1835 void TabBar::EndRenaming()
1837 maEndRenamingHdl.Call( this );
1840 // -----------------------------------------------------------------------
1842 void TabBar::Mirror()
1847 // -----------------------------------------------------------------------
1849 void TabBar::InsertPage( sal_uInt16 nPageId, const OUString& rText,
1850 TabBarPageBits nBits, sal_uInt16 nPos )
1852 DBG_ASSERT( nPageId, "TabBar::InsertPage(): PageId == 0" );
1853 DBG_ASSERT( GetPagePos( nPageId ) == PAGE_NOT_FOUND,
1854 "TabBar::InsertPage(): PageId already exists" );
1855 DBG_ASSERT( nBits <= TPB_SPECIAL, "TabBar::InsertPage(): nBits is wrong" );
1857 // PageItem anlegen und in die Item-Liste eintragen
1858 ImplTabBarItem* pItem = new ImplTabBarItem( nPageId, rText, nBits );
1859 if ( nPos < mpItemList->size() ) {
1860 ImplTabBarList::iterator it = mpItemList->begin();
1861 ::std::advance( it, nPos );
1862 mpItemList->insert( it, pItem );
1863 } else {
1864 mpItemList->push_back( pItem );
1866 mbSizeFormat = sal_True;
1868 // CurPageId gegebenenfalls setzen
1869 if ( !mnCurPageId )
1870 mnCurPageId = nPageId;
1872 // Leiste neu ausgeben
1873 if ( IsReallyVisible() && IsUpdateMode() )
1874 Invalidate();
1876 CallEventListeners( VCLEVENT_TABBAR_PAGEINSERTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
1879 // -----------------------------------------------------------------------
1881 Color TabBar::GetTabBgColor( sal_uInt16 nPageId ) const
1883 sal_uInt16 nPos = GetPagePos( nPageId );
1885 if ( nPos != PAGE_NOT_FOUND )
1886 return (*mpItemList)[ nPos ]->maTabBgColor;
1887 else
1888 return Color( COL_AUTO );
1891 void TabBar::SetTabBgColor( sal_uInt16 nPageId, const Color& aTabBgColor )
1893 sal_uInt16 nPos = GetPagePos( nPageId );
1894 ImplTabBarItem* pItem;
1895 if ( nPos != PAGE_NOT_FOUND )
1897 pItem = (*mpItemList)[ nPos ];
1898 if ( aTabBgColor != Color( COL_AUTO ) )
1900 pItem->maTabBgColor = aTabBgColor;
1901 if ( aTabBgColor.GetLuminance() <= 128 ) //Do not use aTabBgColor.IsDark(), because that threshold is way too low...
1902 pItem->maTabTextColor = Color( COL_WHITE );
1903 else
1904 pItem->maTabTextColor = Color( COL_BLACK );
1906 else
1908 pItem->maTabBgColor = Color( COL_AUTO );
1909 pItem->maTabTextColor = Color( COL_AUTO );
1914 // -----------------------------------------------------------------------
1916 void TabBar::RemovePage( sal_uInt16 nPageId )
1918 sal_uInt16 nPos = GetPagePos( nPageId );
1920 // Existiert Item
1921 if ( nPos != PAGE_NOT_FOUND )
1923 if ( mnCurPageId == nPageId )
1924 mnCurPageId = 0;
1926 // Testen, ob erste sichtbare Seite verschoben werden muss
1927 if ( mnFirstPos > nPos )
1928 mnFirstPos--;
1930 // Item-Daten loeschen
1931 ImplTabBarList::iterator it = mpItemList->begin();
1932 ::std::advance( it, nPos );
1933 delete *it;
1934 mpItemList->erase( it );
1936 // Leiste neu ausgeben
1937 if ( IsReallyVisible() && IsUpdateMode() )
1938 Invalidate();
1940 CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
1944 // -----------------------------------------------------------------------
1946 void TabBar::MovePage( sal_uInt16 nPageId, sal_uInt16 nNewPos )
1948 sal_uInt16 nPos = GetPagePos( nPageId );
1949 Pair aPair( nPos, nNewPos );
1951 if ( nPos < nNewPos )
1952 nNewPos--;
1954 if ( nPos == nNewPos )
1955 return;
1957 // Existiert Item
1958 if ( nPos != PAGE_NOT_FOUND )
1960 // TabBar-Item in der Liste verschieben
1961 ImplTabBarList::iterator it = mpItemList->begin();
1962 ::std::advance( it, nPos );
1963 ImplTabBarItem* pItem = *it;
1964 mpItemList->erase( it );
1965 if ( nNewPos < mpItemList->size() ) {
1966 it = mpItemList->begin();
1967 ::std::advance( it, nNewPos );
1968 mpItemList->insert( it, pItem );
1969 } else {
1970 mpItemList->push_back( pItem );
1973 // Leiste neu ausgeben
1974 if ( IsReallyVisible() && IsUpdateMode() )
1975 Invalidate();
1977 CallEventListeners( VCLEVENT_TABBAR_PAGEMOVED, (void*) &aPair );
1981 // -----------------------------------------------------------------------
1983 void TabBar::Clear()
1985 // Alle Items loeschen
1986 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i ) {
1987 delete (*mpItemList)[ i ];
1989 mpItemList->clear();
1991 // Items aus der Liste loeschen
1992 mbSizeFormat = sal_True;
1993 mnCurPageId = 0;
1994 mnFirstPos = 0;
1995 maCurrentItemList = 0;
1997 // Leiste neu ausgeben
1998 if ( IsReallyVisible() && IsUpdateMode() )
1999 Invalidate();
2001 CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(PAGE_NOT_FOUND)) );
2004 // -----------------------------------------------------------------------
2006 sal_Bool TabBar::IsPageEnabled( sal_uInt16 nPageId ) const
2008 sal_uInt16 nPos = GetPagePos( nPageId );
2010 if ( nPos != PAGE_NOT_FOUND )
2011 return (*mpItemList)[ nPos ]->mbEnable;
2012 else
2013 return sal_False;
2016 // -----------------------------------------------------------------------
2018 void TabBar::SetPageBits( sal_uInt16 nPageId, TabBarPageBits nBits )
2020 sal_uInt16 nPos = GetPagePos( nPageId );
2022 if ( nPos != PAGE_NOT_FOUND )
2024 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2026 if ( pItem->mnBits != nBits )
2028 pItem->mnBits = nBits;
2030 // Leiste neu ausgeben
2031 if ( IsReallyVisible() && IsUpdateMode() )
2032 Invalidate( pItem->maRect );
2037 // -----------------------------------------------------------------------
2039 TabBarPageBits TabBar::GetPageBits( sal_uInt16 nPageId ) const
2041 sal_uInt16 nPos = GetPagePos( nPageId );
2043 if ( nPos != PAGE_NOT_FOUND )
2044 return (*mpItemList)[ nPos ]->mnBits;
2045 else
2046 return sal_False;
2049 // -----------------------------------------------------------------------
2051 sal_uInt16 TabBar::GetPageCount() const
2053 return (sal_uInt16)mpItemList->size();
2056 // -----------------------------------------------------------------------
2058 sal_uInt16 TabBar::GetPageId( sal_uInt16 nPos ) const
2060 return ( nPos < mpItemList->size() ) ? (*mpItemList)[ nPos ]->mnId : 0;
2063 // -----------------------------------------------------------------------
2065 sal_uInt16 TabBar::GetPagePos( sal_uInt16 nPageId ) const
2067 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i ) {
2068 if ( (*mpItemList)[ i ]->mnId == nPageId ) {
2069 return sal_uInt16( i );
2072 return PAGE_NOT_FOUND;
2075 // -----------------------------------------------------------------------
2077 sal_uInt16 TabBar::GetPageId( const Point& rPos, bool bCheckInsTab ) const
2079 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
2081 ImplTabBarItem* pItem = (*mpItemList)[ i ];
2082 if ( pItem->maRect.IsInside( rPos ) )
2083 return pItem->mnId;
2086 if (bCheckInsTab && mbHasInsertTab && !mpItemList->empty())
2088 ImplTabBarItem* pItem = mpItemList->back();
2089 if (ImplGetInsertTabRect(pItem).IsInside(rPos))
2090 return INSERT_TAB_POS;
2093 return 0;
2096 // -----------------------------------------------------------------------
2098 Rectangle TabBar::GetPageRect( sal_uInt16 nPageId ) const
2100 sal_uInt16 nPos = GetPagePos( nPageId );
2102 if ( nPos != PAGE_NOT_FOUND )
2103 return (*mpItemList)[ nPos ]->maRect;
2104 else
2105 return Rectangle();
2108 // -----------------------------------------------------------------------
2110 void TabBar::SetCurPageId( sal_uInt16 nPageId )
2112 sal_uInt16 nPos = GetPagePos( nPageId );
2114 // Wenn Item nicht existiert, dann nichts machen
2115 if ( nPos != PAGE_NOT_FOUND )
2117 // Wenn sich aktuelle Page nicht geaendert hat, dann muessen wir
2118 // jetzt nichts mehr machen
2119 if ( nPageId == mnCurPageId )
2120 return;
2122 // Muss invalidiert werden
2123 sal_Bool bUpdate = sal_False;
2124 if ( IsReallyVisible() && IsUpdateMode() )
2125 bUpdate = sal_True;
2127 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2128 ImplTabBarItem* pOldItem;
2130 if ( mnCurPageId )
2131 pOldItem = (*mpItemList)[ GetPagePos( mnCurPageId ) ];
2132 else
2133 pOldItem = NULL;
2135 // Wenn Page nicht selektiert, dann vorher selektierte Seite
2136 // deselktieren, wenn dies die einzige selektierte Seite ist
2137 if ( !pItem->mbSelect && pOldItem )
2139 sal_uInt16 nSelPageCount = GetSelectPageCount();
2140 if ( nSelPageCount == 1 )
2141 pOldItem->mbSelect = sal_False;
2142 pItem->mbSelect = sal_True;
2145 mnCurPageId = nPageId;
2146 mbFormat = sal_True;
2148 // Dafuer sorgen, das aktuelle Page sichtbar wird
2149 if ( IsReallyVisible() )
2151 if ( nPos < mnFirstPos )
2152 SetFirstPageId( nPageId );
2153 else
2155 // sichtbare Breite berechnen
2156 long nWidth = mnLastOffX;
2157 if ( nWidth > TABBAR_OFFSET_X )
2158 nWidth -= TABBAR_OFFSET_X;
2159 if ( nWidth > ADDNEWPAGE_AREAWIDTH )
2160 nWidth -= ADDNEWPAGE_AREAWIDTH;
2162 if ( pItem->maRect.IsEmpty() )
2163 ImplFormat();
2165 while ( (mbMirrored ? (pItem->maRect.Left() < mnOffX) : (pItem->maRect.Right() > nWidth)) ||
2166 pItem->maRect.IsEmpty() )
2168 sal_uInt16 nNewPos = mnFirstPos+1;
2169 // Dafuer sorgen, das min. die aktuelle TabPages als
2170 // erste TabPage sichtbar ist
2171 if ( nNewPos >= nPos )
2173 SetFirstPageId( nPageId );
2174 break;
2176 else
2177 SetFirstPageId( GetPageId( nNewPos ) );
2178 ImplFormat();
2179 // Falls erste Seite nicht weitergeschaltet wird, dann
2180 // koennen wir abbrechen
2181 if ( nNewPos != mnFirstPos )
2182 break;
2187 // Leiste neu ausgeben
2188 if ( bUpdate )
2190 Invalidate( pItem->maRect );
2191 if ( pOldItem )
2192 Invalidate( pOldItem->maRect );
2197 // -----------------------------------------------------------------------
2199 void TabBar::MakeVisible( sal_uInt16 nPageId )
2201 if ( !IsReallyVisible() )
2202 return;
2204 sal_uInt16 nPos = GetPagePos( nPageId );
2206 // Wenn Item nicht existiert, dann nichts machen
2207 if ( nPos != PAGE_NOT_FOUND )
2209 if ( nPos < mnFirstPos )
2210 SetFirstPageId( nPageId );
2211 else
2213 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2215 // sichtbare Breite berechnen
2216 long nWidth = mnLastOffX;
2217 if ( nWidth > TABBAR_OFFSET_X )
2218 nWidth -= TABBAR_OFFSET_X;
2220 if ( mbFormat || pItem->maRect.IsEmpty() )
2222 mbFormat = sal_True;
2223 ImplFormat();
2226 while ( (pItem->maRect.Right() > nWidth) ||
2227 pItem->maRect.IsEmpty() )
2229 sal_uInt16 nNewPos = mnFirstPos+1;
2230 // Dafuer sorgen, das min. die aktuelle TabPages als
2231 // erste TabPage sichtbar ist
2232 if ( nNewPos >= nPos )
2234 SetFirstPageId( nPageId );
2235 break;
2237 else
2238 SetFirstPageId( GetPageId( nNewPos ) );
2239 ImplFormat();
2240 // Falls erste Seite nicht weitergeschaltet wird, dann
2241 // koennen wir abbrechen
2242 if ( nNewPos != mnFirstPos )
2243 break;
2249 // -----------------------------------------------------------------------
2251 void TabBar::SetFirstPageId( sal_uInt16 nPageId )
2253 sal_uInt16 nPos = GetPagePos( nPageId );
2255 // Wenn Item nicht existiert, dann sal_False zurueckgeben
2256 if ( nPos != PAGE_NOT_FOUND )
2258 if ( nPos != mnFirstPos )
2260 // Dafuer sorgen, das nach Moeglichkteit soviele Pages wie
2261 // moeglich sichtbar sind
2262 ImplFormat();
2263 sal_uInt16 nLastFirstPos = ImplGetLastFirstPos();
2264 sal_uInt16 nNewPos;
2265 if ( nPos > nLastFirstPos )
2266 nNewPos = nLastFirstPos;
2267 else
2268 nNewPos = nPos;
2270 if ( nNewPos != mnFirstPos )
2272 mnFirstPos = nNewPos;
2273 mbFormat = sal_True;
2275 // Leiste neu ausgeben (Achtung: mbDropPos beachten, da wenn
2276 // dieses Flag gesetzt ist, wird direkt gepaintet)
2277 if ( IsReallyVisible() && IsUpdateMode() && !mbDropPos )
2278 Invalidate();
2284 // -----------------------------------------------------------------------
2286 void TabBar::SelectPage( sal_uInt16 nPageId, sal_Bool bSelect )
2288 sal_uInt16 nPos = GetPagePos( nPageId );
2290 if ( nPos != PAGE_NOT_FOUND )
2292 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2294 if ( pItem->mbSelect != bSelect )
2296 pItem->mbSelect = bSelect;
2298 // Leiste neu ausgeben
2299 if ( IsReallyVisible() && IsUpdateMode() )
2300 Invalidate( pItem->maRect );
2305 // -----------------------------------------------------------------------
2307 sal_uInt16 TabBar::GetSelectPageCount() const
2309 sal_uInt16 nSelected = 0;
2310 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
2312 ImplTabBarItem* pItem = (*mpItemList)[ i ];
2313 if ( pItem->mbSelect )
2314 nSelected++;
2317 return nSelected;
2320 // -----------------------------------------------------------------------
2322 sal_Bool TabBar::IsPageSelected( sal_uInt16 nPageId ) const
2324 sal_uInt16 nPos = GetPagePos( nPageId );
2325 if ( nPos != PAGE_NOT_FOUND )
2326 return (*mpItemList)[ nPos ]->mbSelect;
2327 else
2328 return sal_False;
2331 // -----------------------------------------------------------------------
2333 sal_Bool TabBar::StartEditMode( sal_uInt16 nPageId )
2335 sal_uInt16 nPos = GetPagePos( nPageId );
2336 if ( mpEdit || (nPos == PAGE_NOT_FOUND) || (mnLastOffX < 8) )
2337 return sal_False;
2339 mnEditId = nPageId;
2340 if ( StartRenaming() )
2342 ImplShowPage( nPos );
2343 ImplFormat();
2344 Update();
2346 mpEdit = new TabBarEdit( this, WB_CENTER );
2347 Rectangle aRect = GetPageRect( mnEditId );
2348 long nX = aRect.Left()+TABBAR_OFFSET_X+(TABBAR_OFFSET_X2/2);
2349 long nWidth = aRect.GetWidth()-(TABBAR_OFFSET_X*2)-TABBAR_OFFSET_X2;
2350 if ( mnEditId != GetCurPageId() )
2351 nX += 1;
2352 if ( nX+nWidth > mnLastOffX )
2353 nWidth = mnLastOffX-nX;
2354 if ( nWidth < 3 )
2356 nX = aRect.Left();
2357 nWidth = aRect.GetWidth();
2359 mpEdit->SetText( GetPageText( mnEditId ) );
2360 mpEdit->setPosSizePixel( nX, aRect.Top()+mnOffY+1, nWidth, aRect.GetHeight()-3 );
2361 Font aFont = GetPointFont();
2362 Color aForegroundColor;
2363 Color aBackgroundColor;
2364 Color aFaceColor;
2365 Color aSelectColor;
2366 Color aFaceTextColor;
2367 Color aSelectTextColor;
2368 ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor );
2369 if ( mnEditId != GetCurPageId() )
2370 aFont.SetWeight( WEIGHT_LIGHT );
2371 if ( IsPageSelected( mnEditId ) || (mnEditId == GetCurPageId()) )
2373 aForegroundColor = aSelectTextColor;
2374 aBackgroundColor = aSelectColor;
2376 else
2378 aForegroundColor = aFaceTextColor;
2379 aBackgroundColor = aFaceColor;
2381 if ( GetPageBits( mnEditId ) & TPB_SPECIAL )
2382 aForegroundColor = Color( COL_LIGHTBLUE );
2383 mpEdit->SetControlFont( aFont );
2384 mpEdit->SetControlForeground( aForegroundColor );
2385 mpEdit->SetControlBackground( aBackgroundColor );
2386 mpEdit->GrabFocus();
2387 mpEdit->SetSelection( Selection( 0, mpEdit->GetText().getLength() ) );
2388 mpEdit->Show();
2389 return sal_True;
2391 else
2393 mnEditId = 0;
2394 return sal_False;
2398 // -----------------------------------------------------------------------
2400 void TabBar::EndEditMode( sal_Bool bCancel )
2402 if ( mpEdit )
2404 // call hdl
2405 sal_Bool bEnd = sal_True;
2406 mbEditCanceled = bCancel;
2407 maEditText = mpEdit->GetText();
2408 mpEdit->SetPostEvent();
2409 if ( !bCancel )
2411 long nAllowRenaming = AllowRenaming();
2412 if ( nAllowRenaming == TABBAR_RENAMING_YES )
2413 SetPageText( mnEditId, maEditText );
2414 else if ( nAllowRenaming == TABBAR_RENAMING_NO )
2415 bEnd = sal_False;
2416 else // nAllowRenaming == TABBAR_RENAMING_CANCEL
2417 mbEditCanceled = sal_True;
2420 // renaming not allowed, than reset edit data
2421 if ( !bEnd )
2423 mpEdit->ResetPostEvent();
2424 mpEdit->GrabFocus();
2426 else
2428 // close edit and call end hdl
2429 delete mpEdit;
2430 mpEdit = NULL;
2431 EndRenaming();
2432 mnEditId = 0;
2435 // reset
2436 maEditText = OUString();
2437 mbEditCanceled = false;
2441 // -----------------------------------------------------------------------
2443 void TabBar::SetMirrored(bool bMirrored)
2445 if( mbMirrored != bMirrored )
2447 mbMirrored = bMirrored;
2448 mbSizeFormat = true;
2449 ImplInitControls(); // for button images
2450 Resize(); // recalculates control positions
2451 Mirror();
2455 void TabBar::SetEffectiveRTL( bool bRTL )
2457 SetMirrored( bRTL != Application::GetSettings().GetLayoutRTL() );
2460 bool TabBar::IsEffectiveRTL() const
2462 return IsMirrored() != Application::GetSettings().GetLayoutRTL();
2465 // -----------------------------------------------------------------------
2467 void TabBar::SetMaxPageWidth( long nMaxWidth )
2469 if ( mnMaxPageWidth != nMaxWidth )
2471 mnMaxPageWidth = nMaxWidth;
2472 mbSizeFormat = sal_True;
2474 // Leiste neu ausgeben
2475 if ( IsReallyVisible() && IsUpdateMode() )
2476 Invalidate();
2480 // -----------------------------------------------------------------------
2482 void TabBar::SetPageText( sal_uInt16 nPageId, const OUString& rText )
2484 sal_uInt16 nPos = GetPagePos( nPageId );
2485 if ( nPos != PAGE_NOT_FOUND )
2487 (*mpItemList)[ nPos ]->maText = rText;
2488 mbSizeFormat = sal_True;
2490 // Leiste neu ausgeben
2491 if ( IsReallyVisible() && IsUpdateMode() )
2492 Invalidate();
2494 CallEventListeners( VCLEVENT_TABBAR_PAGETEXTCHANGED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
2498 // -----------------------------------------------------------------------
2500 OUString TabBar::GetPageText( sal_uInt16 nPageId ) const
2502 sal_uInt16 nPos = GetPagePos( nPageId );
2503 if ( nPos != PAGE_NOT_FOUND )
2504 return (*mpItemList)[ nPos ]->maText;
2505 return OUString();
2508 // -----------------------------------------------------------------------
2510 OUString TabBar::GetHelpText( sal_uInt16 nPageId ) const
2512 sal_uInt16 nPos = GetPagePos( nPageId );
2513 if ( nPos != PAGE_NOT_FOUND )
2515 ImplTabBarItem* pItem = (*mpItemList)[ nPos ];
2516 if (pItem->maHelpText.isEmpty() && !pItem->maHelpId.isEmpty())
2518 Help* pHelp = Application::GetHelp();
2519 if ( pHelp )
2520 pItem->maHelpText = pHelp->GetHelpText( OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
2523 return pItem->maHelpText;
2525 return OUString();
2528 // -----------------------------------------------------------------------
2530 OString TabBar::GetHelpId( sal_uInt16 nPageId ) const
2532 sal_uInt16 nPos = GetPagePos( nPageId );
2533 OString aRet;
2534 if ( nPos != PAGE_NOT_FOUND )
2535 return (*mpItemList)[ nPos ]->maHelpId;
2536 return aRet;
2539 // -----------------------------------------------------------------------
2541 sal_Bool TabBar::StartDrag( const CommandEvent& rCEvt, Region& rRegion )
2543 if ( !(mnWinStyle & WB_DRAG) || (rCEvt.GetCommand() != COMMAND_STARTDRAG) )
2544 return sal_False;
2546 // Testen, ob angeklickte Seite selektiert ist. Falls dies nicht
2547 // der Fall ist, setzen wir ihn als aktuellen Eintrag. Falls Drag and
2548 // Drop auch mal ueber Tastatur ausgeloest werden kann, testen wir
2549 // dies nur bei einer Mausaktion.
2550 // Ausserdem machen wir das nur, wenn kein Select() ausgeloest wurde,
2551 // da der Select schon den Bereich gescrollt haben kann
2552 if ( rCEvt.IsMouseEvent() && !mbInSelect )
2554 sal_uInt16 nSelId = GetPageId( rCEvt.GetMousePosPixel() );
2556 // Falls kein Eintrag angeklickt wurde, starten wir kein Dragging
2557 if ( !nSelId )
2558 return sal_False;
2560 // Testen, ob Seite selektiertiert ist. Falls nicht, als aktuelle
2561 // Seite setzen und Select rufen.
2562 if ( !IsPageSelected( nSelId ) )
2564 if ( ImplDeactivatePage() )
2566 SetCurPageId( nSelId );
2567 Update();
2568 ImplActivatePage();
2569 ImplSelect();
2571 else
2572 return sal_False;
2575 mbInSelect = sal_False;
2577 Region aRegion;
2579 // Region zuweisen
2580 rRegion = aRegion;
2582 return sal_True;
2585 // -----------------------------------------------------------------------
2587 sal_uInt16 TabBar::ShowDropPos( const Point& rPos )
2589 ImplTabBarItem* pItem;
2590 sal_uInt16 nDropId;
2591 sal_uInt16 nNewDropPos;
2592 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
2593 short nScroll = 0;
2595 if ( rPos.X() > mnLastOffX-TABBAR_DRAG_SCROLLOFF )
2597 pItem = (*mpItemList)[ mpItemList->size()-1 ];
2598 if ( !pItem->maRect.IsEmpty() && (rPos.X() > pItem->maRect.Right()) )
2599 nNewDropPos = (sal_uInt16)mpItemList->size();
2600 else
2602 nNewDropPos = mnFirstPos+1;
2603 nScroll = 1;
2606 else if ( (rPos.X() <= mnOffX) ||
2607 (!mnOffX && (rPos.X() <= TABBAR_DRAG_SCROLLOFF)) )
2609 if ( mnFirstPos )
2611 nNewDropPos = mnFirstPos;
2612 nScroll = -1;
2614 else
2615 nNewDropPos = 0;
2617 else
2619 nDropId = GetPageId( rPos );
2620 if ( nDropId )
2622 nNewDropPos = GetPagePos( nDropId );
2623 if ( mnFirstPos && (nNewDropPos == mnFirstPos-1) )
2624 nScroll = -1;
2626 else
2627 nNewDropPos = nItemCount;
2630 if ( mbDropPos && (nNewDropPos == mnDropPos) && !nScroll )
2631 return mnDropPos;
2633 if ( mbDropPos )
2634 HideDropPos();
2635 mbDropPos = sal_True;
2636 mnDropPos = nNewDropPos;
2638 if ( nScroll )
2640 sal_uInt16 nOldFirstPos = mnFirstPos;
2641 SetFirstPageId( GetPageId( mnFirstPos+nScroll ) );
2643 // Direkt ausgeben, da kein Paint bei Drag and Drop moeglich
2644 if ( nOldFirstPos != mnFirstPos )
2646 Rectangle aRect( mnOffX, 0, mnLastOffX, maWinSize.Height() );
2647 SetFillColor( GetBackground().GetColor() );
2648 DrawRect( aRect );
2649 Paint( aRect );
2653 // Drop-Position-Pfeile ausgeben
2654 Color aBlackColor( COL_BLACK );
2655 long nX;
2656 long nY = (maWinSize.Height()/2)-1;
2657 sal_uInt16 nCurPos = GetPagePos( mnCurPageId );
2659 SetLineColor( aBlackColor );
2660 if ( mnDropPos < nItemCount )
2662 pItem = (*mpItemList)[ mnDropPos ];
2663 nX = pItem->maRect.Left()+TABBAR_OFFSET_X;
2664 if ( mnDropPos == nCurPos )
2665 nX--;
2666 else
2667 nX++;
2668 if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
2669 SetLineColor( pItem->maTabTextColor );
2670 DrawLine( Point( nX, nY ), Point( nX, nY ) );
2671 DrawLine( Point( nX+1, nY-1 ), Point( nX+1, nY+1 ) );
2672 DrawLine( Point( nX+2, nY-2 ), Point( nX+2, nY+2 ) );
2673 SetLineColor( aBlackColor );
2675 if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) )
2677 pItem = (*mpItemList)[ mnDropPos-1 ];
2678 nX = pItem->maRect.Right()-TABBAR_OFFSET_X;
2679 if ( mnDropPos == nCurPos )
2680 nX++;
2681 if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
2682 SetLineColor( pItem->maTabTextColor );
2683 DrawLine( Point( nX, nY ), Point( nX, nY ) );
2684 DrawLine( Point( nX-1, nY-1 ), Point( nX-1, nY+1 ) );
2685 DrawLine( Point( nX-2, nY-2 ), Point( nX-2, nY+2 ) );
2688 return mnDropPos;
2691 // -----------------------------------------------------------------------
2693 void TabBar::HideDropPos()
2695 if ( mbDropPos )
2697 ImplTabBarItem* pItem;
2698 long nX;
2699 long nY1 = (maWinSize.Height()/2)-3;
2700 long nY2 = nY1 + 5;
2701 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->size();
2703 if ( mnDropPos < nItemCount )
2705 pItem = (*mpItemList)[ mnDropPos ];
2706 nX = pItem->maRect.Left()+TABBAR_OFFSET_X;
2707 // Paint direkt aufrufen, da bei Drag and Drop kein Paint
2708 // moeglich
2709 Rectangle aRect( nX-1, nY1, nX+3, nY2 );
2710 Region aRegion( aRect );
2711 SetClipRegion( aRegion );
2712 Paint( aRect );
2713 SetClipRegion();
2715 if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) )
2717 pItem = (*mpItemList)[ mnDropPos-1 ];
2718 nX = pItem->maRect.Right()-TABBAR_OFFSET_X;
2719 // Paint direkt aufrufen, da bei Drag and Drop kein Paint
2720 // moeglich
2721 Rectangle aRect( nX-2, nY1, nX+1, nY2 );
2722 Region aRegion( aRect );
2723 SetClipRegion( aRegion );
2724 Paint( aRect );
2725 SetClipRegion();
2728 mbDropPos = sal_False;
2729 mnDropPos = 0;
2733 // -----------------------------------------------------------------------
2735 sal_Bool TabBar::SwitchPage( const Point& rPos )
2737 sal_Bool bSwitch = sal_False;
2738 sal_uInt16 nSwitchId = GetPageId( rPos );
2739 if ( !nSwitchId )
2740 EndSwitchPage();
2741 else
2743 if ( nSwitchId != mnSwitchId )
2745 mnSwitchId = nSwitchId;
2746 mnSwitchTime = Time::GetSystemTicks();
2748 else
2750 // Erst nach 500 ms umschalten
2751 if ( mnSwitchId != GetCurPageId() )
2753 if ( Time::GetSystemTicks() > mnSwitchTime+500 )
2755 mbInSwitching = sal_True;
2756 if ( ImplDeactivatePage() )
2758 SetCurPageId( mnSwitchId );
2759 Update();
2760 ImplActivatePage();
2761 ImplSelect();
2762 bSwitch = sal_True;
2764 mbInSwitching = sal_False;
2770 return bSwitch;
2773 // -----------------------------------------------------------------------
2775 void TabBar::EndSwitchPage()
2777 mnSwitchTime = 0;
2778 mnSwitchId = 0;
2781 // -----------------------------------------------------------------------
2783 void TabBar::SetStyle( WinBits nStyle )
2785 mnWinStyle = nStyle;
2786 ImplInitControls();
2787 // Evt. Controls neu anordnen
2788 if ( IsReallyVisible() && IsUpdateMode() )
2789 Resize();
2792 // -----------------------------------------------------------------------
2794 Size TabBar::CalcWindowSizePixel() const
2796 long nWidth = 0;
2798 if ( mpItemList->size() )
2800 ((TabBar*)this)->ImplCalcWidth();
2801 for ( size_t i = 0, n = mpItemList->size(); i < n; ++i )
2803 ImplTabBarItem* pItem = (*mpItemList)[ i ];
2804 nWidth += pItem->mnWidth;
2806 nWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
2809 return Size( nWidth, GetSettings().GetStyleSettings().GetScrollBarSize() );
2811 // -----------------------------------------------------------------------
2813 Rectangle TabBar::GetPageArea() const
2815 return Rectangle( Point( mnOffX, mnOffY ), Size( mnLastOffX-mnOffX+1, GetSizePixel().Height()-mnOffY ) );
2818 // -----------------------------------------------------------------------
2820 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > TabBar::CreateAccessible()
2822 return mpImpl->maAccessibleFactory.getFactory().createAccessibleTabBar( *this );
2825 // -----------------------------------------------------------------------
2827 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */