1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "tools/debug.hxx"
24 #include "vcl/svapp.hxx"
25 #include "vcl/help.hxx"
26 #include "vcl/event.hxx"
27 #include "vcl/menu.hxx"
28 #include "vcl/button.hxx"
29 #include "vcl/tabpage.hxx"
30 #include "vcl/tabctrl.hxx"
31 #include "vcl/controllayout.hxx"
32 #include "vcl/layout.hxx"
33 #include "vcl/lstbox.hxx"
35 #include "controldata.hxx"
39 #include <boost/unordered_map.hpp>
42 // =======================================================================
60 : mnId( 0 ), mpTabPage( NULL
),
61 mnLine( 0 ), mbFullVisible( sal_False
), mbEnabled( true )
65 // -----------------------------------------------------------------------
67 struct ImplTabCtrlData
69 boost::unordered_map
< int, int > maLayoutPageIdToLine
;
70 boost::unordered_map
< int, int > maLayoutLineToPageId
;
71 std::vector
< Rectangle
> maTabRectangles
;
72 Point maItemsOffset
; // offset of the tabitems
73 std::vector
< ImplTabItem
> maItemList
;
77 // -----------------------------------------------------------------------
80 #define TAB_TABOFFSET_X 3
81 #define TAB_TABOFFSET_Y 3
82 #define TAB_EXTRASPACE_X 6
83 #define TAB_BORDER_LEFT 1
84 #define TAB_BORDER_TOP 1
85 #define TAB_BORDER_RIGHT 2
86 #define TAB_BORDER_BOTTOM 2
88 // for the Tab positions
89 #define TAB_PAGERECT 0xFFFF
91 // =======================================================================
93 void TabControl::ImplInit( Window
* pParent
, WinBits nStyle
)
97 if ( !(nStyle
& WB_NOTABSTOP
) )
99 if ( !(nStyle
& WB_NOGROUP
) )
101 if ( !(nStyle
& WB_NODIALOGCONTROL
) )
102 nStyle
|= WB_DIALOGCONTROL
;
104 Control::ImplInit( pParent
, nStyle
, NULL
);
113 mbRestoreHelpId
= sal_False
;
114 mbRestoreUnqId
= sal_False
;
115 mbSmallInvalidate
= sal_False
;
116 mpTabCtrlData
= new ImplTabCtrlData
;
117 mpTabCtrlData
->mpListBox
= NULL
;
120 ImplInitSettings( sal_True
, sal_True
, sal_True
);
122 if( (nStyle
& WB_DROPDOWN
) )
124 mpTabCtrlData
->mpListBox
= new ListBox( this, WB_DROPDOWN
);
125 mpTabCtrlData
->mpListBox
->SetPosSizePixel( Point( 0, 0 ), Size( 200, 20 ) );
126 mpTabCtrlData
->mpListBox
->SetSelectHdl( LINK( this, TabControl
, ImplListBoxSelectHdl
) );
127 mpTabCtrlData
->mpListBox
->Show();
130 // if the tabcontrol is drawn (ie filled) by a native widget, make sure all contols will have transparent background
131 // otherwise they will paint with a wrong background
132 if( IsNativeControlSupported(CTRL_TAB_PANE
, PART_ENTIRE_CONTROL
) )
133 EnableChildTransparentMode( sal_True
);
135 if ( pParent
->IsDialog() )
136 pParent
->AddChildEventListener( LINK( this, TabControl
, ImplWindowEventListener
) );
139 // -----------------------------------------------------------------
141 const Font
& TabControl::GetCanonicalFont( const StyleSettings
& _rStyle
) const
143 return _rStyle
.GetAppFont();
146 // -----------------------------------------------------------------
147 const Color
& TabControl::GetCanonicalTextColor( const StyleSettings
& _rStyle
) const
149 return _rStyle
.GetButtonTextColor();
152 // -----------------------------------------------------------------------
154 void TabControl::ImplInitSettings( sal_Bool bFont
,
155 sal_Bool bForeground
, sal_Bool bBackground
)
157 Control::ImplInitSettings( bFont
, bForeground
);
161 Window
* pParent
= GetParent();
162 if ( !IsControlBackground() &&
163 (pParent
->IsChildTransparentModeEnabled()
164 || IsNativeControlSupported(CTRL_TAB_PANE
, PART_ENTIRE_CONTROL
)
165 || IsNativeControlSupported(CTRL_TAB_ITEM
, PART_ENTIRE_CONTROL
) ) )
168 // set transparent mode for NWF tabcontrols to have
169 // the background always cleared properly
170 EnableChildTransparentMode( sal_True
);
171 SetParentClipMode( PARENTCLIPMODE_NOCLIP
);
172 SetPaintTransparent( sal_True
);
174 ImplGetWindowImpl()->mbUseNativeFocus
= ImplGetSVData()->maNWFData
.mbNoFocusRects
;
178 EnableChildTransparentMode( sal_False
);
179 SetParentClipMode( 0 );
180 SetPaintTransparent( sal_False
);
182 if ( IsControlBackground() )
183 SetBackground( GetControlBackground() );
185 SetBackground( pParent
->GetBackground() );
190 // -----------------------------------------------------------------------
192 void TabControl::ImplFreeLayoutData()
194 if( HasLayoutData() )
196 ImplClearLayoutData();
197 mpTabCtrlData
->maLayoutPageIdToLine
.clear();
198 mpTabCtrlData
->maLayoutLineToPageId
.clear();
202 // -----------------------------------------------------------------------
204 TabControl::TabControl( Window
* pParent
, WinBits nStyle
) :
205 Control( WINDOW_TABCONTROL
)
207 ImplInit( pParent
, nStyle
);
208 OSL_TRACE("*** TABCONTROL no notabs? %s", ( GetStyle() & WB_NOBORDER
) ? "true" : "false" );
211 // -----------------------------------------------------------------------
213 TabControl::TabControl( Window
* pParent
, const ResId
& rResId
) :
214 Control( WINDOW_TABCONTROL
)
216 rResId
.SetRT( RSC_TABCONTROL
);
217 WinBits nStyle
= ImplInitRes( rResId
);
218 ImplInit( pParent
, nStyle
);
219 ImplLoadRes( rResId
);
221 if ( !(nStyle
& WB_HIDE
) )
225 // -----------------------------------------------------------------------
227 void TabControl::ImplLoadRes( const ResId
& rResId
)
229 Control::ImplLoadRes( rResId
);
231 sal_uLong nObjMask
= ReadLongRes();
233 if ( nObjMask
& RSC_TABCONTROL_ITEMLIST
)
235 sal_uLong nEle
= ReadLongRes();
238 for( sal_uLong i
= 0; i
< nEle
; i
++ )
240 InsertPage( ResId( (RSHEADER_TYPE
*)GetClassRes(), *rResId
.GetResMgr() ) );
241 IncrementRes( GetObjSizeRes( (RSHEADER_TYPE
*)GetClassRes() ) );
246 // -----------------------------------------------------------------------
248 TabControl::~TabControl()
250 if ( GetParent()->IsDialog() )
251 GetParent()->RemoveChildEventListener( LINK( this, TabControl
, ImplWindowEventListener
) );
253 ImplFreeLayoutData();
255 // delete TabCtrl data
258 if( mpTabCtrlData
->mpListBox
)
259 delete mpTabCtrlData
->mpListBox
;
260 delete mpTabCtrlData
;
264 // -----------------------------------------------------------------------
266 ImplTabItem
* TabControl::ImplGetItem( sal_uInt16 nId
) const
268 for( std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
269 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
271 if( it
->mnId
== nId
)
278 // -----------------------------------------------------------------------
280 Size
TabControl::ImplGetItemSize( ImplTabItem
* pItem
, long nMaxWidth
)
282 pItem
->maFormatText
= pItem
->maText
;
283 Size
aSize( GetCtrlTextWidth( pItem
->maFormatText
), GetTextHeight() );
284 Size
aImageSize( 0, 0 );
285 if( !!pItem
->maTabImage
)
287 aImageSize
= pItem
->maTabImage
.GetSizePixel();
288 if( pItem
->maFormatText
.Len() )
289 aImageSize
.Width() += GetTextHeight()/4;
291 aSize
.Width() += aImageSize
.Width();
292 if( aImageSize
.Height() > aSize
.Height() )
293 aSize
.Height() = aImageSize
.Height();
295 aSize
.Width() += TAB_TABOFFSET_X
*2;
296 aSize
.Height() += TAB_TABOFFSET_Y
*2;
298 Rectangle
aCtrlRegion( Point( 0, 0 ), aSize
);
299 Rectangle aBoundingRgn
, aContentRgn
;
300 const ImplControlValue aControlValue
;
301 if(GetNativeControlRegion( CTRL_TAB_ITEM
, PART_ENTIRE_CONTROL
, aCtrlRegion
,
302 CTRL_STATE_ENABLED
, aControlValue
, OUString(),
303 aBoundingRgn
, aContentRgn
) )
305 return aContentRgn
.GetSize();
308 // For languages with short names (e.g. Chinese), because the space is
309 // normally only one pixel per char
310 if ( pItem
->maFormatText
.Len() < TAB_EXTRASPACE_X
)
311 aSize
.Width() += TAB_EXTRASPACE_X
-pItem
->maFormatText
.Len();
313 // shorten Text if needed
314 if ( aSize
.Width()+4 >= nMaxWidth
)
316 OUString
aAppendStr("...");
317 pItem
->maFormatText
+= aAppendStr
;
320 pItem
->maFormatText
.Erase( pItem
->maFormatText
.Len()-aAppendStr
.getLength()-1, 1 );
321 aSize
.Width() = GetCtrlTextWidth( pItem
->maFormatText
);
322 aSize
.Width() += aImageSize
.Width();
323 aSize
.Width() += TAB_TABOFFSET_X
*2;
325 while ( (aSize
.Width()+4 >= nMaxWidth
) && (pItem
->maFormatText
.Len() > aAppendStr
.getLength()) );
326 if ( aSize
.Width()+4 >= nMaxWidth
)
328 pItem
->maFormatText
.Assign( '.' );
333 if( pItem
->maFormatText
.Len() == 0 )
335 if( aSize
.Height() < aImageSize
.Height()+4 ) //leave space for focus rect
336 aSize
.Height() = aImageSize
.Height()+4;
342 // -----------------------------------------------------------------------
344 Rectangle
TabControl::ImplGetTabRect( sal_uInt16 nItemPos
, long nWidth
, long nHeight
)
346 Size aWinSize
= Control::GetOutputSizePixel();
348 nWidth
= aWinSize
.Width();
350 nHeight
= aWinSize
.Height();
352 if ( mpTabCtrlData
->maItemList
.empty() )
354 long nW
= nWidth
-TAB_OFFSET
*2;
355 long nH
= nHeight
-TAB_OFFSET
*2;
356 return (nW
> 0 && nH
> 0)
357 ? Rectangle( Point( TAB_OFFSET
, TAB_OFFSET
), Size( nW
, nH
) )
361 if ( nItemPos
== TAB_PAGERECT
)
365 nLastPos
= GetPagePos( mnCurPageId
);
369 Rectangle aRect
= ImplGetTabRect( nLastPos
, nWidth
, nHeight
);
370 long nW
= nWidth
-TAB_OFFSET
*2;
371 long nH
= nHeight
-aRect
.Bottom()-TAB_OFFSET
*2;
372 aRect
= (nW
> 0 && nH
> 0)
373 ? Rectangle( Point( TAB_OFFSET
, aRect
.Bottom()+TAB_OFFSET
), Size( nW
, nH
) )
380 if ( (nWidth
<= 0) || (nHeight
<= 0) )
383 if ( mbFormat
|| (mnLastWidth
!= nWidth
) || (mnLastHeight
!= nHeight
) )
385 Font
aFont( GetFont() );
386 aFont
.SetTransparent( sal_True
);
390 const long nOffsetX
= 2 + GetItemsOffset().X();
391 const long nOffsetY
= 2 + GetItemsOffset().Y();
394 long nMaxWidth
= nWidth
;
397 if ( (mnMaxPageWidth
> 0) && (mnMaxPageWidth
< nMaxWidth
) )
398 nMaxWidth
= mnMaxPageWidth
;
399 nMaxWidth
-= GetItemsOffset().X();
401 sal_uInt16 nLines
= 0;
402 sal_uInt16 nCurLine
= 0;
403 long nLineWidthAry
[100];
404 sal_uInt16 nLinePosAry
[101];
406 nLineWidthAry
[0] = 0;
408 for( std::vector
<ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
409 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
411 aSize
= ImplGetItemSize( &(*it
), nMaxWidth
);
413 if ( ((nX
+aSize
.Width()) > nWidth
- 2) && (nWidth
> 2+nOffsetX
) )
419 nY
+= aSize
.Height();
421 nLineWidthAry
[nLines
] = 0;
422 nLinePosAry
[nLines
] = nPos
;
425 Rectangle
aNewRect( Point( nX
, nY
), aSize
);
426 if ( mbSmallInvalidate
&& (it
->maRect
!= aNewRect
) )
427 mbSmallInvalidate
= sal_False
;
428 it
->maRect
= aNewRect
;
430 it
->mbFullVisible
= sal_True
;
432 nLineWidthAry
[nLines
] += aSize
.Width();
435 if ( it
->mnId
== mnCurPageId
)
441 if ( nLines
&& !mpTabCtrlData
->maItemList
.empty() )
448 long nLineHeightAry
[100];
449 long nIH
= mpTabCtrlData
->maItemList
[0].maRect
.Bottom()-2;
452 while ( i
< nLines
+1 )
455 nLineHeightAry
[i
] = nIH
*(nLines
-(nCurLine
-i
)) + GetItemsOffset().Y();
457 nLineHeightAry
[i
] = nIH
*(i
-nCurLine
-1) + GetItemsOffset().Y();
463 nLinePosAry
[nLines
+1] = (sal_uInt16
)mpTabCtrlData
->maItemList
.size();
464 for( std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
465 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
467 if ( i
== nLinePosAry
[n
] )
473 if( nLinePosAry
[n
+1]-i
> 0 )
475 nDX
= (nWidth
-nOffsetX
-nLineWidthAry
[n
]) / (nLinePosAry
[n
+1]-i
);
476 nModDX
= (nWidth
-nOffsetX
-nLineWidthAry
[n
]) % (nLinePosAry
[n
+1]-i
);
480 // FIXME: this is a bad case of tabctrl way too small
487 it
->maRect
.Left() += nIDX
;
488 it
->maRect
.Right() += nIDX
+nDX
;
489 it
->maRect
.Top() = nLineHeightAry
[n
-1];
490 it
->maRect
.Bottom() = nLineHeightAry
[n
-1]+nIH
;
496 it
->maRect
.Right()++;
505 if(ImplGetSVData()->maNWFData
.mbCenteredTabs
)
507 int nRightSpace
=nMaxWidth
;//space left on the right by the tabs
508 for( std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
509 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
511 nRightSpace
-=it
->maRect
.Right()-it
->maRect
.Left();
513 for( std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
514 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
516 it
->maRect
.Left()+=(int) (nRightSpace
/2);
517 it
->maRect
.Right()+=(int) (nRightSpace
/2);
522 mnLastWidth
= nWidth
;
523 mnLastHeight
= nHeight
;
524 mbFormat
= sal_False
;
527 return size_t(nItemPos
) < mpTabCtrlData
->maItemList
.size() ? mpTabCtrlData
->maItemList
[nItemPos
].maRect
: Rectangle();
530 // -----------------------------------------------------------------------
532 void TabControl::ImplChangeTabPage( sal_uInt16 nId
, sal_uInt16 nOldId
)
534 ImplFreeLayoutData();
536 ImplTabItem
* pOldItem
= ImplGetItem( nOldId
);
537 ImplTabItem
* pItem
= ImplGetItem( nId
);
538 TabPage
* pOldPage
= (pOldItem
) ? pOldItem
->mpTabPage
: NULL
;
539 TabPage
* pPage
= (pItem
) ? pItem
->mpTabPage
: NULL
;
540 Window
* pCtrlParent
= GetParent();
542 if ( IsReallyVisible() && IsUpdateMode() )
544 sal_uInt16 nPos
= GetPagePos( nId
);
545 Rectangle aRect
= ImplGetTabRect( nPos
);
547 if ( !pOldItem
|| (pOldItem
->mnLine
!= pItem
->mnLine
) )
551 aRect
.Right() = Control::GetOutputSizePixel().Width();
559 nPos
= GetPagePos( nOldId
);
560 aRect
= ImplGetTabRect( nPos
);
568 if ( pOldPage
== pPage
)
571 Rectangle aRect
= ImplGetTabRect( TAB_PAGERECT
);
575 if ( mbRestoreHelpId
)
576 pCtrlParent
->SetHelpId( OString() );
577 if ( mbRestoreUnqId
)
578 pCtrlParent
->SetUniqueId( OString() );
579 pOldPage
->DeactivatePage();
584 if ( ( GetStyle() & WB_NOBORDER
) )
586 Rectangle
aRectNoTab( (const Point
&)Point( 0, 0 ), GetSizePixel() );
587 pPage
->SetPosSizePixel( aRectNoTab
.TopLeft(), aRectNoTab
.GetSize() );
590 pPage
->SetPosSizePixel( aRect
.TopLeft(), aRect
.GetSize() );
592 // activate page here so the conbtrols can be switched
593 // also set the help id of the parent window to that of the tab page
594 if ( GetHelpId().isEmpty() )
596 mbRestoreHelpId
= sal_True
;
597 pCtrlParent
->SetHelpId( pPage
->GetHelpId() );
599 if ( pCtrlParent
->GetUniqueId().isEmpty() )
601 mbRestoreUnqId
= sal_True
;
602 pCtrlParent
->SetUniqueId( pPage
->GetUniqueId() );
605 pPage
->ActivatePage();
607 if ( pOldPage
&& pOldPage
->HasChildPathFocus() )
610 Window
* pFirstChild
= pPage
->ImplGetDlgWindow( n
, DLGWINDOW_FIRST
);
612 pFirstChild
->ImplControlFocus( GETFOCUS_INIT
);
623 // Invalidate the same region that will be send to NWF
624 // to always allow for bitmap caching
625 // see Window::DrawNativeControl()
626 if( IsNativeControlSupported( CTRL_TAB_PANE
, PART_ENTIRE_CONTROL
) )
628 aRect
.Left() -= TAB_OFFSET
;
629 aRect
.Top() -= TAB_OFFSET
;
630 aRect
.Right() += TAB_OFFSET
;
631 aRect
.Bottom() += TAB_OFFSET
;
637 // -----------------------------------------------------------------------
639 sal_Bool
TabControl::ImplPosCurTabPage()
641 // resize/position current TabPage
642 ImplTabItem
* pItem
= ImplGetItem( GetCurPageId() );
643 if ( pItem
&& pItem
->mpTabPage
)
645 if ( ( GetStyle() & WB_NOBORDER
) )
647 Rectangle
aRectNoTab( (const Point
&)Point( 0, 0 ), GetSizePixel() );
648 pItem
->mpTabPage
->SetPosSizePixel( aRectNoTab
.TopLeft(), aRectNoTab
.GetSize() );
651 Rectangle aRect
= ImplGetTabRect( TAB_PAGERECT
);
652 pItem
->mpTabPage
->SetPosSizePixel( aRect
.TopLeft(), aRect
.GetSize() );
659 // -----------------------------------------------------------------------
661 void TabControl::ImplActivateTabPage( sal_Bool bNext
)
663 sal_uInt16 nCurPos
= GetPagePos( GetCurPageId() );
666 nCurPos
= (nCurPos
+ 1) % GetPageCount();
670 nCurPos
= GetPageCount()-1;
675 SelectTabPage( GetPageId( nCurPos
) );
678 // -----------------------------------------------------------------------
680 void TabControl::ImplShowFocus()
682 if ( !GetPageCount() || mpTabCtrlData
->mpListBox
)
685 sal_uInt16 nCurPos
= GetPagePos( mnCurPageId
);
686 Rectangle aRect
= ImplGetTabRect( nCurPos
);
687 const ImplTabItem
& rItem
= mpTabCtrlData
->maItemList
[ nCurPos
];
688 Size aTabSize
= aRect
.GetSize();
689 Size
aImageSize( 0, 0 );
690 long nTextHeight
= GetTextHeight();
691 long nTextWidth
= GetCtrlTextWidth( rItem
.maFormatText
);
694 if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_MONO
) )
699 if( !! rItem
.maTabImage
)
701 aImageSize
= rItem
.maTabImage
.GetSizePixel();
702 if( rItem
.maFormatText
.Len() )
703 aImageSize
.Width() += GetTextHeight()/4;
706 if( rItem
.maFormatText
.Len() )
708 // show focus around text
709 aRect
.Left() = aRect
.Left()+aImageSize
.Width()+((aTabSize
.Width()-nTextWidth
-aImageSize
.Width())/2)-nOff
-1-1;
710 aRect
.Top() = aRect
.Top()+((aTabSize
.Height()-nTextHeight
)/2)-1-1;
711 aRect
.Right() = aRect
.Left()+nTextWidth
+2;
712 aRect
.Bottom() = aRect
.Top()+nTextHeight
+2;
716 // show focus around image
717 long nXPos
= aRect
.Left()+((aTabSize
.Width()-nTextWidth
-aImageSize
.Width())/2)-nOff
-1;
718 long nYPos
= aRect
.Top();
719 if( aImageSize
.Height() < aRect
.GetHeight() )
720 nYPos
+= (aRect
.GetHeight() - aImageSize
.Height())/2;
722 aRect
.Left() = nXPos
- 2;
723 aRect
.Top() = nYPos
- 2;
724 aRect
.Right() = aRect
.Left() + aImageSize
.Width() + 4;
725 aRect
.Bottom() = aRect
.Top() + aImageSize
.Height() + 4;
730 // -----------------------------------------------------------------------
732 void TabControl::ImplDrawItem( ImplTabItem
* pItem
, const Rectangle
& rCurRect
, bool bLayout
, bool bFirstInGroup
, bool bLastInGroup
, bool /* bIsCurrentItem */ )
734 if ( pItem
->maRect
.IsEmpty() )
739 if( !HasLayoutData() )
741 mpControlData
->mpLayoutData
= new vcl::ControlLayoutData();
742 mpTabCtrlData
->maLayoutLineToPageId
.clear();
743 mpTabCtrlData
->maLayoutPageIdToLine
.clear();
744 mpTabCtrlData
->maTabRectangles
.clear();
748 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
749 Rectangle aRect
= pItem
->maRect
;
750 long nLeftBottom
= aRect
.Bottom();
751 long nRightBottom
= aRect
.Bottom();
752 bool bLeftBorder
= true;
753 bool bRightBorder
= true;
755 sal_Bool bNativeOK
= sal_False
;
757 sal_uInt16 nOff2
= 0;
758 sal_uInt16 nOff3
= 0;
760 if ( !(rStyleSettings
.GetOptions() & STYLE_OPTION_MONO
) )
765 // if this is the active Page, we have to draw a little more
766 if ( pItem
->mnId
== mnCurPageId
)
769 if( ! ImplGetSVData()->maNWFData
.mbNoActiveTabTextRaise
)
774 Point aLeftTestPos
= aRect
.BottomLeft();
775 Point aRightTestPos
= aRect
.BottomRight();
776 if ( aLeftTestPos
.Y() == rCurRect
.Bottom() )
778 aLeftTestPos
.X() -= 2;
779 if ( rCurRect
.IsInside( aLeftTestPos
) )
781 aRightTestPos
.X() += 2;
782 if ( rCurRect
.IsInside( aRightTestPos
) )
783 bRightBorder
= false;
787 if ( rCurRect
.IsInside( aLeftTestPos
) )
789 if ( rCurRect
.IsInside( aRightTestPos
) )
794 if( !bLayout
&& (bNativeOK
= IsNativeControlSupported(CTRL_TAB_ITEM
, PART_ENTIRE_CONTROL
)) == sal_True
)
796 Rectangle
aCtrlRegion( pItem
->maRect
);
797 ControlState nState
= 0;
799 if( pItem
->mnId
== mnCurPageId
)
801 nState
|= CTRL_STATE_SELECTED
;
802 // only the selected item can be focussed
804 nState
|= CTRL_STATE_FOCUSED
;
807 nState
|= CTRL_STATE_ENABLED
;
808 if( IsMouseOver() && pItem
->maRect
.IsInside( GetPointerPosPixel() ) )
810 nState
|= CTRL_STATE_ROLLOVER
;
811 for( std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
812 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
814 if( (&(*it
) != pItem
) && (it
->maRect
.IsInside( GetPointerPosPixel() ) ) )
816 nState
&= ~CTRL_STATE_ROLLOVER
; // avoid multiple highlighted tabs
822 TabitemValue tiValue
;
823 if(pItem
->maRect
.Left() < 5)
824 tiValue
.mnAlignment
|= TABITEM_LEFTALIGNED
;
825 if(pItem
->maRect
.Right() > mnLastWidth
- 5)
826 tiValue
.mnAlignment
|= TABITEM_RIGHTALIGNED
;
828 tiValue
.mnAlignment
|= TABITEM_FIRST_IN_GROUP
;
830 tiValue
.mnAlignment
|= TABITEM_LAST_IN_GROUP
;
832 bNativeOK
= DrawNativeControl( CTRL_TAB_ITEM
, PART_ENTIRE_CONTROL
, aCtrlRegion
, nState
,
833 tiValue
, OUString() );
836 if( ! bLayout
&& !bNativeOK
)
838 if ( !(rStyleSettings
.GetOptions() & STYLE_OPTION_MONO
) )
840 SetLineColor( rStyleSettings
.GetLightColor() );
841 DrawPixel( Point( aRect
.Left()+1-nOff2
, aRect
.Top()+1-nOff2
) ); // diagonally indented top-left pixel
844 DrawLine( Point( aRect
.Left()-nOff2
, aRect
.Top()+2-nOff2
),
845 Point( aRect
.Left()-nOff2
, nLeftBottom
-1 ) );
847 DrawLine( Point( aRect
.Left()+2-nOff2
, aRect
.Top()-nOff2
), // top line starting 2px from left border
848 Point( aRect
.Right()+nOff2
-3, aRect
.Top()-nOff2
) ); // ending 3px from right border
852 SetLineColor( rStyleSettings
.GetShadowColor() );
853 DrawLine( Point( aRect
.Right()+nOff2
-2, aRect
.Top()+1-nOff2
),
854 Point( aRect
.Right()+nOff2
-2, nRightBottom
-1 ) );
856 SetLineColor( rStyleSettings
.GetDarkShadowColor() );
857 DrawLine( Point( aRect
.Right()+nOff2
-1, aRect
.Top()+3-nOff2
),
858 Point( aRect
.Right()+nOff2
-1, nRightBottom
-1 ) );
863 SetLineColor( Color( COL_BLACK
) );
864 DrawPixel( Point( aRect
.Left()+1-nOff2
, aRect
.Top()+1-nOff2
) );
865 DrawPixel( Point( aRect
.Right()+nOff2
-2, aRect
.Top()+1-nOff2
) );
868 DrawLine( Point( aRect
.Left()-nOff2
, aRect
.Top()+2-nOff2
),
869 Point( aRect
.Left()-nOff2
, nLeftBottom
-1 ) );
871 DrawLine( Point( aRect
.Left()+2-nOff2
, aRect
.Top()-nOff2
),
872 Point( aRect
.Right()-3, aRect
.Top()-nOff2
) );
875 DrawLine( Point( aRect
.Right()+nOff2
-1, aRect
.Top()+2-nOff2
),
876 Point( aRect
.Right()+nOff2
-1, nRightBottom
-1 ) );
883 int nLine
= mpControlData
->mpLayoutData
->m_aLineIndices
.size();
884 mpControlData
->mpLayoutData
->m_aLineIndices
.push_back( mpControlData
->mpLayoutData
->m_aDisplayText
.getLength() );
885 mpTabCtrlData
->maLayoutPageIdToLine
[ (int)pItem
->mnId
] = nLine
;
886 mpTabCtrlData
->maLayoutLineToPageId
[ nLine
] = (int)pItem
->mnId
;
887 mpTabCtrlData
->maTabRectangles
.push_back( aRect
);
890 // set font accordingly, current item is painted bold
891 // we set the font attributes always before drawing to be re-entrant (DrawNativeControl may trigger additional paints)
892 Font
aFont( GetFont() );
893 aFont
.SetTransparent( sal_True
);
896 Size aTabSize
= aRect
.GetSize();
897 Size
aImageSize( 0, 0 );
898 long nTextHeight
= GetTextHeight();
899 long nTextWidth
= GetCtrlTextWidth( pItem
->maFormatText
);
900 if( !! pItem
->maTabImage
)
902 aImageSize
= pItem
->maTabImage
.GetSizePixel();
903 if( pItem
->maFormatText
.Len() )
904 aImageSize
.Width() += GetTextHeight()/4;
906 long nXPos
= aRect
.Left()+((aTabSize
.Width()-nTextWidth
-aImageSize
.Width())/2)-nOff
-nOff3
;
907 long nYPos
= aRect
.Top()+((aTabSize
.Height()-nTextHeight
)/2)-nOff3
;
908 if( pItem
->maFormatText
.Len() )
910 sal_uInt16 nStyle
= TEXT_DRAW_MNEMONIC
;
911 if( ! pItem
->mbEnabled
)
912 nStyle
|= TEXT_DRAW_DISABLE
;
913 DrawCtrlText( Point( nXPos
+ aImageSize
.Width(), nYPos
),
915 0, STRING_LEN
, nStyle
,
916 bLayout
? &mpControlData
->mpLayoutData
->m_aUnicodeBoundRects
: NULL
,
917 bLayout
? &mpControlData
->mpLayoutData
->m_aDisplayText
: NULL
921 if( !! pItem
->maTabImage
)
923 Point
aImgTL( nXPos
, aRect
.Top() );
924 if( aImageSize
.Height() < aRect
.GetHeight() )
925 aImgTL
.Y() += (aRect
.GetHeight() - aImageSize
.Height())/2;
926 DrawImage( aImgTL
, pItem
->maTabImage
, pItem
->mbEnabled
? 0 : IMAGE_DRAW_DISABLE
);
930 // -----------------------------------------------------------------------
932 long TabControl::ImplHandleKeyEvent( const KeyEvent
& rKeyEvent
)
936 if ( GetPageCount() > 1 )
938 KeyCode aKeyCode
= rKeyEvent
.GetKeyCode();
939 sal_uInt16 nKeyCode
= aKeyCode
.GetCode();
941 if ( aKeyCode
.IsMod1() )
943 if ( aKeyCode
.IsShift() || (nKeyCode
== KEY_PAGEUP
) )
945 if ( (nKeyCode
== KEY_TAB
) || (nKeyCode
== KEY_PAGEUP
) )
947 ImplActivateTabPage( sal_False
);
953 if ( (nKeyCode
== KEY_TAB
) || (nKeyCode
== KEY_PAGEDOWN
) )
955 ImplActivateTabPage( sal_True
);
966 // -----------------------------------------------------------------------
968 IMPL_LINK_NOARG(TabControl
, ImplListBoxSelectHdl
)
970 SelectTabPage( GetPageId( mpTabCtrlData
->mpListBox
->GetSelectEntryPos() ) );
974 // -----------------------------------------------------------------------
976 IMPL_LINK( TabControl
, ImplWindowEventListener
, VclSimpleEvent
*, pEvent
)
978 if ( pEvent
&& pEvent
->ISA( VclWindowEvent
) && (pEvent
->GetId() == VCLEVENT_WINDOW_KEYINPUT
) )
980 VclWindowEvent
* pWindowEvent
= static_cast< VclWindowEvent
* >(pEvent
);
981 // Do not handle events from TabControl or it's children, which is done in Notify(), where the events can be consumed.
982 if ( !IsWindowOrChild( pWindowEvent
->GetWindow() ) )
984 KeyEvent
* pKeyEvent
= static_cast< KeyEvent
* >(pWindowEvent
->GetData());
985 ImplHandleKeyEvent( *pKeyEvent
);
992 // -----------------------------------------------------------------------
994 void TabControl::MouseButtonDown( const MouseEvent
& rMEvt
)
996 if( mpTabCtrlData
->mpListBox
== NULL
)
1000 sal_uInt16 nPageId
= GetPageId( rMEvt
.GetPosPixel() );
1001 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
1002 if( pItem
&& pItem
->mbEnabled
)
1003 SelectTabPage( nPageId
);
1008 // -----------------------------------------------------------------------
1010 void TabControl::KeyInput( const KeyEvent
& rKEvt
)
1012 if( mpTabCtrlData
->mpListBox
)
1013 mpTabCtrlData
->mpListBox
->KeyInput( rKEvt
);
1014 else if ( GetPageCount() > 1 )
1016 KeyCode aKeyCode
= rKEvt
.GetKeyCode();
1017 sal_uInt16 nKeyCode
= aKeyCode
.GetCode();
1019 if ( (nKeyCode
== KEY_LEFT
) || (nKeyCode
== KEY_RIGHT
) )
1021 sal_Bool bNext
= (nKeyCode
== KEY_RIGHT
);
1022 ImplActivateTabPage( bNext
);
1026 Control::KeyInput( rKEvt
);
1029 // -----------------------------------------------------------------------
1031 void TabControl::Paint( const Rectangle
& rRect
)
1033 if ( !( GetStyle() & WB_NOBORDER
) )
1034 ImplPaint( rRect
, false );
1037 // -----------------------------------------------------------------------
1039 void TabControl::ImplPaint( const Rectangle
& rRect
, bool bLayout
)
1044 // reformat if needed
1045 Rectangle aRect
= ImplGetTabRect( TAB_PAGERECT
);
1047 // find current item
1048 ImplTabItem
* pCurItem
= NULL
;
1049 for( std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
1050 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
1052 if ( it
->mnId
== mnCurPageId
)
1059 // Draw the TabPage border
1060 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
1062 aRect
.Left() -= TAB_OFFSET
;
1063 aRect
.Top() -= TAB_OFFSET
;
1064 aRect
.Right() += TAB_OFFSET
;
1065 aRect
.Bottom() += TAB_OFFSET
;
1067 // if we have an invisible tabpage or no tabpage at all the tabpage rect should be
1068 // increased to avoid round corners that might be drawn by a theme
1069 // in this case we're only interested in the top border of the tabpage because the tabitems are used
1070 // standalone (eg impress)
1071 bool bNoTabPage
= false;
1072 TabPage
* pCurPage
= pCurItem
? pCurItem
->mpTabPage
: NULL
;
1073 if( !pCurPage
|| !pCurPage
->IsVisible() )
1080 sal_Bool bNativeOK
= sal_False
;
1081 if( ! bLayout
&& (bNativeOK
= IsNativeControlSupported( CTRL_TAB_PANE
, PART_ENTIRE_CONTROL
) ) == sal_True
)
1083 const ImplControlValue aControlValue
;
1085 ControlState nState
= CTRL_STATE_ENABLED
;
1086 int part
= PART_ENTIRE_CONTROL
;
1088 nState
&= ~CTRL_STATE_ENABLED
;
1090 nState
|= CTRL_STATE_FOCUSED
;
1092 Region
aClipRgn( GetActiveClipRegion() );
1093 aClipRgn
.Intersect( aRect
);
1094 if( !rRect
.IsEmpty() )
1095 aClipRgn
.Intersect( rRect
);
1097 if( !aClipRgn
.IsEmpty() )
1098 bNativeOK
= DrawNativeControl( CTRL_TAB_PANE
, part
, aRect
, nState
,
1099 aControlValue
, OUString() );
1104 if ( !(rStyleSettings
.GetOptions() & STYLE_OPTION_MONO
) )
1105 SetLineColor( rStyleSettings
.GetLightColor() );
1107 SetLineColor( Color( COL_BLACK
) );
1108 if ( pCurItem
&& !pCurItem
->maRect
.IsEmpty() )
1110 aCurRect
= pCurItem
->maRect
;
1112 DrawLine( aRect
.TopLeft(), Point( aCurRect
.Left()-2, aRect
.Top() ) );
1113 if ( aCurRect
.Right()+1 < aRect
.Right() )
1116 DrawLine( Point( aCurRect
.Right(), aRect
.Top() ), aRect
.TopRight() );
1123 DrawLine( aRect
.TopLeft(), aRect
.TopRight() );
1127 DrawLine( aRect
.TopLeft(), aRect
.BottomLeft() );
1129 if ( !(rStyleSettings
.GetOptions() & STYLE_OPTION_MONO
) )
1131 // if we have not tab page the bottom line of the tab page
1132 // directly touches the tab items, so choose a color that fits seamlessly
1134 SetLineColor( rStyleSettings
.GetDialogColor() );
1136 SetLineColor( rStyleSettings
.GetShadowColor() );
1137 DrawLine( Point( 1, aRect
.Bottom()-1 ),
1138 Point( aRect
.Right()-1, aRect
.Bottom()-1 ) );
1139 DrawLine( Point( aRect
.Right()-1, aRect
.Top()+nTopOff
),
1140 Point( aRect
.Right()-1, aRect
.Bottom()-1 ) );
1142 SetLineColor( rStyleSettings
.GetDialogColor() );
1144 SetLineColor( rStyleSettings
.GetDarkShadowColor() );
1145 DrawLine( Point( 0, aRect
.Bottom() ),
1146 Point( aRect
.Right(), aRect
.Bottom() ) );
1147 DrawLine( Point( aRect
.Right(), aRect
.Top()+nTopOff
),
1148 Point( aRect
.Right(), aRect
.Bottom() ) );
1152 DrawLine( aRect
.TopRight(), aRect
.BottomRight() );
1153 DrawLine( aRect
.BottomLeft(), aRect
.BottomRight() );
1158 if ( !mpTabCtrlData
->maItemList
.empty() && mpTabCtrlData
->mpListBox
== NULL
)
1160 // Some native toolkits (GTK+) draw tabs right-to-left, with an
1161 // overlap between adjacent tabs
1162 bool bDrawTabsRTL
= IsNativeControlSupported( CTRL_TAB_ITEM
, PART_TABS_DRAW_RTL
);
1163 ImplTabItem
* pFirstTab
= NULL
;
1164 ImplTabItem
* pLastTab
= NULL
;
1167 // Event though there is a tab overlap with GTK+, the first tab is not
1168 // overlapped on the left side. Other tookits ignore this option.
1171 pFirstTab
= &mpTabCtrlData
->maItemList
.front();
1172 pLastTab
= &mpTabCtrlData
->maItemList
.back();
1173 idx
= mpTabCtrlData
->maItemList
.size()-1;
1177 pLastTab
= &mpTabCtrlData
->maItemList
.back();
1178 pFirstTab
= &mpTabCtrlData
->maItemList
.front();
1182 while ( idx
< mpTabCtrlData
->maItemList
.size() )
1184 ImplTabItem
* pItem
= &mpTabCtrlData
->maItemList
[idx
];
1185 if ( pItem
!= pCurItem
)
1187 Region
aClipRgn( GetActiveClipRegion() );
1188 aClipRgn
.Intersect( pItem
->maRect
);
1189 if( !rRect
.IsEmpty() )
1190 aClipRgn
.Intersect( rRect
);
1191 if( bLayout
|| !aClipRgn
.IsEmpty() )
1192 ImplDrawItem( pItem
, aCurRect
, bLayout
, (pItem
==pFirstTab
), (pItem
==pLastTab
), sal_False
);
1203 Region
aClipRgn( GetActiveClipRegion() );
1204 aClipRgn
.Intersect( pCurItem
->maRect
);
1205 if( !rRect
.IsEmpty() )
1206 aClipRgn
.Intersect( rRect
);
1207 if( bLayout
|| !aClipRgn
.IsEmpty() )
1208 ImplDrawItem( pCurItem
, aCurRect
, bLayout
, (pCurItem
==pFirstTab
), (pCurItem
==pLastTab
), sal_True
);
1212 if ( !bLayout
&& HasFocus() )
1216 mbSmallInvalidate
= sal_True
;
1219 // -----------------------------------------------------------------------
1221 void TabControl::setAllocation(const Size
&rAllocation
)
1223 ImplFreeLayoutData();
1225 if ( !IsReallyShown() )
1228 if( mpTabCtrlData
->mpListBox
)
1230 // get the listbox' preferred size
1231 Size
aTabCtrlSize( GetSizePixel() );
1232 long nPrefWidth
= mpTabCtrlData
->mpListBox
->get_preferred_size().Width();
1233 if( nPrefWidth
> aTabCtrlSize
.Width() )
1234 nPrefWidth
= aTabCtrlSize
.Width();
1235 Size
aNewSize( nPrefWidth
, LogicToPixel( Size( 12, 12 ), MapMode( MAP_APPFONT
) ).Height() );
1236 Point
aNewPos( (aTabCtrlSize
.Width() - nPrefWidth
) / 2, 0 );
1237 mpTabCtrlData
->mpListBox
->SetPosSizePixel( aNewPos
, aNewSize
);
1240 mbFormat
= sal_True
;
1242 // resize/position active TabPage
1243 sal_Bool bTabPage
= ImplPosCurTabPage();
1245 // check what needs to be invalidated
1246 Size aNewSize
= rAllocation
;
1247 long nNewWidth
= aNewSize
.Width();
1248 for( std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
1249 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
1251 if ( !it
->mbFullVisible
||
1252 (it
->maRect
.Right()-2 >= nNewWidth
) )
1254 mbSmallInvalidate
= sal_False
;
1259 if ( mbSmallInvalidate
)
1261 Rectangle aRect
= ImplGetTabRect( TAB_PAGERECT
);
1262 aRect
.Left() -= TAB_OFFSET
+TAB_BORDER_LEFT
;
1263 aRect
.Top() -= TAB_OFFSET
+TAB_BORDER_TOP
;
1264 aRect
.Right() += TAB_OFFSET
+TAB_BORDER_RIGHT
;
1265 aRect
.Bottom() += TAB_OFFSET
+TAB_BORDER_BOTTOM
;
1267 Invalidate( aRect
, INVALIDATE_NOCHILDREN
);
1269 Invalidate( aRect
);
1275 Invalidate( INVALIDATE_NOCHILDREN
);
1280 mbLayoutDirty
= false;
1283 void TabControl::SetPosSizePixel(const Point
& rNewPos
, const Size
& rNewSize
)
1285 Window::SetPosSizePixel(rNewPos
, rNewSize
);
1286 //if size changed, TabControl::Resize got called already
1288 setAllocation(rNewSize
);
1291 void TabControl::SetSizePixel(const Size
& rNewSize
)
1293 Window::SetSizePixel(rNewSize
);
1294 //if size changed, TabControl::Resize got called already
1296 setAllocation(rNewSize
);
1299 void TabControl::SetPosPixel(const Point
& rPos
)
1301 Window::SetPosPixel(rPos
);
1303 setAllocation(GetOutputSizePixel());
1306 void TabControl::Resize()
1308 setAllocation(Control::GetOutputSizePixel());
1311 // -----------------------------------------------------------------------
1313 void TabControl::GetFocus()
1315 if( ! mpTabCtrlData
->mpListBox
)
1318 SetInputContext( InputContext( GetFont() ) );
1322 if( mpTabCtrlData
->mpListBox
->IsReallyVisible() )
1323 mpTabCtrlData
->mpListBox
->GrabFocus();
1325 Control::GetFocus();
1328 // -----------------------------------------------------------------------
1330 void TabControl::LoseFocus()
1332 if( ! mpTabCtrlData
->mpListBox
)
1334 Control::LoseFocus();
1337 // -----------------------------------------------------------------------
1339 void TabControl::RequestHelp( const HelpEvent
& rHEvt
)
1341 sal_uInt16 nItemId
= rHEvt
.KeyboardActivated() ? mnCurPageId
: GetPageId( ScreenToOutputPixel( rHEvt
.GetMousePosPixel() ) );
1345 if ( rHEvt
.GetMode() & HELPMODE_BALLOON
)
1347 XubString aStr
= GetHelpText( nItemId
);
1350 Rectangle aItemRect
= ImplGetTabRect( GetPagePos( nItemId
) );
1351 Point aPt
= OutputToScreenPixel( aItemRect
.TopLeft() );
1352 aItemRect
.Left() = aPt
.X();
1353 aItemRect
.Top() = aPt
.Y();
1354 aPt
= OutputToScreenPixel( aItemRect
.BottomRight() );
1355 aItemRect
.Right() = aPt
.X();
1356 aItemRect
.Bottom() = aPt
.Y();
1357 Help::ShowBalloon( this, aItemRect
.Center(), aItemRect
, aStr
);
1361 else if ( rHEvt
.GetMode() & HELPMODE_EXTENDED
)
1363 OUString
aHelpId( OStringToOUString( GetHelpId( nItemId
), RTL_TEXTENCODING_UTF8
) );
1364 if ( !aHelpId
.isEmpty() )
1366 // call Help if existing
1367 Help
* pHelp
= Application::GetHelp();
1369 pHelp
->Start( aHelpId
, this );
1374 // for Quick or Ballon Help, we show the text, if it is cut
1375 if ( rHEvt
.GetMode() & (HELPMODE_QUICK
| HELPMODE_BALLOON
) )
1377 ImplTabItem
* pItem
= ImplGetItem( nItemId
);
1378 const XubString
& rStr
= pItem
->maText
;
1379 if ( rStr
!= pItem
->maFormatText
)
1381 Rectangle aItemRect
= ImplGetTabRect( GetPagePos( nItemId
) );
1382 Point aPt
= OutputToScreenPixel( aItemRect
.TopLeft() );
1383 aItemRect
.Left() = aPt
.X();
1384 aItemRect
.Top() = aPt
.Y();
1385 aPt
= OutputToScreenPixel( aItemRect
.BottomRight() );
1386 aItemRect
.Right() = aPt
.X();
1387 aItemRect
.Bottom() = aPt
.Y();
1390 if ( rHEvt
.GetMode() & HELPMODE_BALLOON
)
1391 Help::ShowBalloon( this, aItemRect
.Center(), aItemRect
, rStr
);
1393 Help::ShowQuickHelp( this, aItemRect
, rStr
);
1399 if ( rHEvt
.GetMode() & HELPMODE_QUICK
)
1401 ImplTabItem
* pItem
= ImplGetItem( nItemId
);
1402 const XubString
& rHelpText
= pItem
->maHelpText
;
1403 // show tooltip if not text but image is set and helptext is available
1404 if ( rHelpText
.Len() > 0 && pItem
->maText
.Len() == 0 && !!pItem
->maTabImage
)
1406 Rectangle aItemRect
= ImplGetTabRect( GetPagePos( nItemId
) );
1407 Point aPt
= OutputToScreenPixel( aItemRect
.TopLeft() );
1408 aItemRect
.Left() = aPt
.X();
1409 aItemRect
.Top() = aPt
.Y();
1410 aPt
= OutputToScreenPixel( aItemRect
.BottomRight() );
1411 aItemRect
.Right() = aPt
.X();
1412 aItemRect
.Bottom() = aPt
.Y();
1413 Help::ShowQuickHelp( this, aItemRect
, rHelpText
);
1419 Control::RequestHelp( rHEvt
);
1422 // -----------------------------------------------------------------------
1424 void TabControl::Command( const CommandEvent
& rCEvt
)
1426 if( (mpTabCtrlData
->mpListBox
== NULL
) && (rCEvt
.GetCommand() == COMMAND_CONTEXTMENU
) && (GetPageCount() > 1) )
1430 if ( rCEvt
.IsMouseEvent() )
1432 aMenuPos
= rCEvt
.GetMousePosPixel();
1433 bMenu
= GetPageId( aMenuPos
) != 0;
1437 aMenuPos
= ImplGetTabRect( GetPagePos( mnCurPageId
) ).Center();
1444 for( std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
1445 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
1447 aMenu
.InsertItem( it
->mnId
, it
->maText
, MIB_CHECKABLE
| MIB_RADIOCHECK
);
1448 if ( it
->mnId
== mnCurPageId
)
1449 aMenu
.CheckItem( it
->mnId
);
1450 aMenu
.SetHelpId( it
->mnId
, it
->maHelpId
);
1453 sal_uInt16 nId
= aMenu
.Execute( this, aMenuPos
);
1454 if ( nId
&& (nId
!= mnCurPageId
) )
1455 SelectTabPage( nId
);
1460 Control::Command( rCEvt
);
1463 // -----------------------------------------------------------------------
1465 void TabControl::StateChanged( StateChangedType nType
)
1467 Control::StateChanged( nType
);
1469 if ( nType
== STATE_CHANGE_INITSHOW
)
1471 ImplPosCurTabPage();
1472 if( mpTabCtrlData
->mpListBox
)
1475 else if ( nType
== STATE_CHANGE_UPDATEMODE
)
1477 if ( IsUpdateMode() )
1480 else if ( (nType
== STATE_CHANGE_ZOOM
) ||
1481 (nType
== STATE_CHANGE_CONTROLFONT
) )
1483 ImplInitSettings( sal_True
, sal_False
, sal_False
);
1486 else if ( nType
== STATE_CHANGE_CONTROLFOREGROUND
)
1488 ImplInitSettings( sal_False
, sal_True
, sal_False
);
1491 else if ( nType
== STATE_CHANGE_CONTROLBACKGROUND
)
1493 ImplInitSettings( sal_False
, sal_False
, sal_True
);
1498 // -----------------------------------------------------------------------
1500 void TabControl::DataChanged( const DataChangedEvent
& rDCEvt
)
1502 Control::DataChanged( rDCEvt
);
1504 if ( (rDCEvt
.GetType() == DATACHANGED_FONTS
) ||
1505 (rDCEvt
.GetType() == DATACHANGED_FONTSUBSTITUTION
) ||
1506 ((rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
1507 (rDCEvt
.GetFlags() & SETTINGS_STYLE
)) )
1509 ImplInitSettings( sal_True
, sal_True
, sal_True
);
1514 // -----------------------------------------------------------------------
1516 Rectangle
* TabControl::ImplFindPartRect( const Point
& rPt
)
1518 ImplTabItem
* pFoundItem
= NULL
;
1520 for( std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin();
1521 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
1523 if ( it
->maRect
.IsInside( rPt
) )
1525 // assure that only one tab is highlighted at a time
1527 pFoundItem
= &(*it
);
1530 // assure that only one tab is highlighted at a time
1531 return nFound
== 1 ? &pFoundItem
->maRect
: NULL
;
1534 long TabControl::PreNotify( NotifyEvent
& rNEvt
)
1537 const MouseEvent
* pMouseEvt
= NULL
;
1539 if( (rNEvt
.GetType() == EVENT_MOUSEMOVE
) && (pMouseEvt
= rNEvt
.GetMouseEvent()) != NULL
)
1541 if( !pMouseEvt
->GetButtons() && !pMouseEvt
->IsSynthetic() && !pMouseEvt
->IsModifierChanged() )
1543 // trigger redraw if mouse over state has changed
1544 if( IsNativeControlSupported(CTRL_TAB_ITEM
, PART_ENTIRE_CONTROL
) )
1546 Rectangle
* pRect
= ImplFindPartRect( GetPointerPosPixel() );
1547 Rectangle
* pLastRect
= ImplFindPartRect( GetLastPointerPosPixel() );
1548 if( pRect
!= pLastRect
|| (pMouseEvt
->IsLeaveWindow() || pMouseEvt
->IsEnterWindow()) )
1553 // allow for slightly bigger tabitems
1555 // TODO: query for the correct sizes
1556 Rectangle
aRect(*pLastRect
);
1560 aClipRgn
.Union( aRect
);
1564 // allow for slightly bigger tabitems
1566 // TODO: query for the correct sizes
1567 Rectangle
aRect(*pRect
);
1571 aClipRgn
.Union( aRect
);
1573 if( !aClipRgn
.IsEmpty() )
1574 Invalidate( aClipRgn
);
1580 return nDone
? nDone
: Control::PreNotify(rNEvt
);
1583 // -----------------------------------------------------------------------
1585 long TabControl::Notify( NotifyEvent
& rNEvt
)
1589 if ( rNEvt
.GetType() == EVENT_KEYINPUT
)
1590 nRet
= ImplHandleKeyEvent( *rNEvt
.GetKeyEvent() );
1592 return nRet
? nRet
: Control::Notify( rNEvt
);
1595 // -----------------------------------------------------------------------
1597 void TabControl::ActivatePage()
1599 maActivateHdl
.Call( this );
1602 // -----------------------------------------------------------------------
1604 long TabControl::DeactivatePage()
1606 if ( maDeactivateHdl
.IsSet() )
1607 return maDeactivateHdl
.Call( this );
1612 // -----------------------------------------------------------------------
1614 void TabControl::SetTabPageSizePixel( const Size
& rSize
)
1616 ImplFreeLayoutData();
1618 Size
aNewSize( rSize
);
1619 aNewSize
.Width() += TAB_OFFSET
*2;
1620 Rectangle aRect
= ImplGetTabRect( TAB_PAGERECT
,
1621 aNewSize
.Width(), aNewSize
.Height() );
1622 aNewSize
.Height() += aRect
.Top()+TAB_OFFSET
;
1623 Window::SetOutputSizePixel( aNewSize
);
1626 // -----------------------------------------------------------------------
1628 Size
TabControl::GetTabPageSizePixel() const
1630 Rectangle aRect
= ((TabControl
*)this)->ImplGetTabRect( TAB_PAGERECT
);
1631 return aRect
.GetSize();
1634 // -----------------------------------------------------------------------
1636 void TabControl::InsertPage( const ResId
& rResId
, sal_uInt16 nPos
)
1638 GetRes( rResId
.SetRT( RSC_TABCONTROLITEM
) );
1640 sal_uLong nObjMask
= ReadLongRes();
1641 sal_uInt16 nItemId
= 1;
1644 if ( nObjMask
& RSC_TABCONTROLITEM_ID
)
1645 nItemId
= sal::static_int_cast
<sal_uInt16
>(ReadLongRes());
1649 if( nObjMask
& RSC_TABCONTROLITEM_TEXT
)
1650 aTmpStr
= ReadStringRes();
1651 InsertPage( nItemId
, aTmpStr
, nPos
);
1654 if ( nObjMask
& RSC_TABCONTROLITEM_PAGERESID
)
1656 //skip unused TabPageResId value
1661 // -----------------------------------------------------------------------
1663 void TabControl::InsertPage( sal_uInt16 nPageId
, const XubString
& rText
,
1666 DBG_ASSERT( nPageId
, "TabControl::InsertPage(): PageId == 0" );
1667 DBG_ASSERT( GetPagePos( nPageId
) == TAB_PAGE_NOTFOUND
,
1668 "TabControl::InsertPage(): PageId already exists" );
1670 // insert new page item
1671 ImplTabItem
* pItem
= NULL
;
1672 if( nPos
== TAB_APPEND
|| size_t(nPos
) >= mpTabCtrlData
->maItemList
.size() )
1674 mpTabCtrlData
->maItemList
.push_back( ImplTabItem() );
1675 pItem
= &mpTabCtrlData
->maItemList
.back();
1676 if( mpTabCtrlData
->mpListBox
)
1677 mpTabCtrlData
->mpListBox
->InsertEntry( rText
);
1681 std::vector
< ImplTabItem
>::iterator new_it
=
1682 mpTabCtrlData
->maItemList
.insert( mpTabCtrlData
->maItemList
.begin() + nPos
, ImplTabItem() );
1684 if( mpTabCtrlData
->mpListBox
)
1685 mpTabCtrlData
->mpListBox
->InsertEntry( rText
, nPos
);
1687 if( mpTabCtrlData
->mpListBox
)
1690 mpTabCtrlData
->mpListBox
->SelectEntryPos( 0 );
1691 mpTabCtrlData
->mpListBox
->SetDropDownLineCount( mpTabCtrlData
->mpListBox
->GetEntryCount() );
1694 // set current page id
1696 mnCurPageId
= nPageId
;
1698 // init new page item
1699 pItem
->mnId
= nPageId
;
1700 pItem
->mpTabPage
= NULL
;
1701 pItem
->maText
= rText
;
1702 pItem
->mbFullVisible
= sal_False
;
1704 mbFormat
= sal_True
;
1705 if ( IsUpdateMode() )
1708 ImplFreeLayoutData();
1709 if( mpTabCtrlData
->mpListBox
) // reposition/resize listbox
1712 ImplCallEventListeners( VCLEVENT_TABPAGE_INSERTED
, (void*) (sal_uLong
)nPageId
);
1715 // -----------------------------------------------------------------------
1717 void TabControl::RemovePage( sal_uInt16 nPageId
)
1719 sal_uInt16 nPos
= GetPagePos( nPageId
);
1721 // does the item exist ?
1722 if ( nPos
!= TAB_PAGE_NOTFOUND
)
1725 std::vector
< ImplTabItem
>::iterator it
= mpTabCtrlData
->maItemList
.begin() + nPos
;
1726 bool bIsCurrentPage
= (it
->mnId
== mnCurPageId
);
1727 mpTabCtrlData
->maItemList
.erase( it
);
1728 if( mpTabCtrlData
->mpListBox
)
1730 mpTabCtrlData
->mpListBox
->RemoveEntry( nPos
);
1731 mpTabCtrlData
->mpListBox
->SetDropDownLineCount( mpTabCtrlData
->mpListBox
->GetEntryCount() );
1734 // If current page is removed, than first page gets the current page
1735 if ( bIsCurrentPage
)
1739 if( ! mpTabCtrlData
->maItemList
.empty() )
1741 // don't do this by simply setting mnCurPageId to pFirstItem->mnId
1742 // this leaves a lot of stuff (such trivias as _showing_ the new current page) undone
1743 // instead, call SetCurPageId
1744 // without this, the next (outside) call to SetCurPageId with the id of the first page
1745 // will result in doing nothing (as we assume that nothing changed, then), and the page
1746 // will never be shown.
1747 // 86875 - 05/11/2001 - frank.schoenheit@germany.sun.com
1749 SetCurPageId( mpTabCtrlData
->maItemList
[0].mnId
);
1753 mbFormat
= sal_True
;
1754 if ( IsUpdateMode() )
1757 ImplFreeLayoutData();
1759 ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVED
, (void*) (sal_uLong
) nPageId
);
1763 // -----------------------------------------------------------------------
1765 void TabControl::Clear()
1768 mpTabCtrlData
->maItemList
.clear();
1770 if( mpTabCtrlData
->mpListBox
)
1771 mpTabCtrlData
->mpListBox
->Clear();
1773 ImplFreeLayoutData();
1775 mbFormat
= sal_True
;
1776 if ( IsUpdateMode() )
1779 ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVEDALL
);
1782 // -----------------------------------------------------------------------
1784 void TabControl::EnablePage( sal_uInt16 i_nPageId
, bool i_bEnable
)
1786 ImplTabItem
* pItem
= ImplGetItem( i_nPageId
);
1788 if ( pItem
&& pItem
->mbEnabled
!= i_bEnable
)
1790 pItem
->mbEnabled
= i_bEnable
;
1791 mbFormat
= sal_True
;
1792 if( mpTabCtrlData
->mpListBox
)
1793 mpTabCtrlData
->mpListBox
->SetEntryFlags( GetPagePos( i_nPageId
),
1794 i_bEnable
? 0 : (LISTBOX_ENTRY_FLAG_DISABLE_SELECTION
| LISTBOX_ENTRY_FLAG_DRAW_DISABLED
) );
1795 if( pItem
->mnId
== mnCurPageId
)
1797 // SetCurPageId will change to an enabled page
1798 SetCurPageId( mnCurPageId
);
1800 else if ( IsUpdateMode() )
1805 // -----------------------------------------------------------------------
1807 sal_uInt16
TabControl::GetPageCount() const
1809 return (sal_uInt16
)mpTabCtrlData
->maItemList
.size();
1812 // -----------------------------------------------------------------------
1814 sal_uInt16
TabControl::GetPageId( sal_uInt16 nPos
) const
1816 if( size_t(nPos
) < mpTabCtrlData
->maItemList
.size() )
1817 return mpTabCtrlData
->maItemList
[ nPos
].mnId
;
1821 // -----------------------------------------------------------------------
1823 sal_uInt16
TabControl::GetPagePos( sal_uInt16 nPageId
) const
1825 for( std::vector
< ImplTabItem
>::const_iterator it
= mpTabCtrlData
->maItemList
.begin();
1826 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
1828 if ( it
->mnId
== nPageId
)
1829 return (sal_uInt16
)(it
- mpTabCtrlData
->maItemList
.begin());
1832 return TAB_PAGE_NOTFOUND
;
1835 // -----------------------------------------------------------------------
1837 sal_uInt16
TabControl::GetPageId( const Point
& rPos
) const
1839 for( size_t i
= 0; i
< mpTabCtrlData
->maItemList
.size(); ++i
)
1841 if ( ((TabControl
*)this)->ImplGetTabRect( static_cast<sal_uInt16
>(i
) ).IsInside( rPos
) )
1842 return mpTabCtrlData
->maItemList
[ i
].mnId
;
1848 sal_uInt16
TabControl::GetPageId( const TabPage
& rPage
) const
1850 for( std::vector
< ImplTabItem
>::const_iterator it
= mpTabCtrlData
->maItemList
.begin();
1851 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
1853 if ( it
->mpTabPage
== &rPage
)
1860 sal_uInt16
TabControl::GetPageId( const OString
& rName
) const
1862 for( std::vector
< ImplTabItem
>::const_iterator it
= mpTabCtrlData
->maItemList
.begin();
1863 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
1865 if ( it
->maTabName
== rName
)
1872 // -----------------------------------------------------------------------
1874 void TabControl::SetCurPageId( sal_uInt16 nPageId
)
1876 sal_uInt16 nPos
= GetPagePos( nPageId
);
1877 while( nPos
!= TAB_PAGE_NOTFOUND
&&
1878 ! mpTabCtrlData
->maItemList
[nPos
].mbEnabled
)
1881 if( size_t(nPos
) >= mpTabCtrlData
->maItemList
.size() )
1883 if( mpTabCtrlData
->maItemList
[nPos
].mnId
== nPageId
)
1887 if( nPos
!= TAB_PAGE_NOTFOUND
)
1889 nPageId
= mpTabCtrlData
->maItemList
[nPos
].mnId
;
1890 if ( nPageId
== mnCurPageId
)
1893 mnActPageId
= nPageId
;
1898 mnActPageId
= nPageId
;
1901 mbFormat
= sal_True
;
1902 sal_uInt16 nOldId
= mnCurPageId
;
1903 mnCurPageId
= nPageId
;
1904 ImplChangeTabPage( nPageId
, nOldId
);
1909 // -----------------------------------------------------------------------
1911 sal_uInt16
TabControl::GetCurPageId() const
1919 // -----------------------------------------------------------------------
1921 void TabControl::SelectTabPage( sal_uInt16 nPageId
)
1923 if ( nPageId
&& (nPageId
!= mnCurPageId
) )
1925 ImplFreeLayoutData();
1927 ImplCallEventListeners( VCLEVENT_TABPAGE_DEACTIVATE
, (void*) (sal_uLong
) mnCurPageId
);
1928 if ( DeactivatePage() )
1930 mnActPageId
= nPageId
;
1932 // Page could have been switched by the Activate handler
1933 nPageId
= mnActPageId
;
1935 SetCurPageId( nPageId
);
1936 if( mpTabCtrlData
->mpListBox
)
1937 mpTabCtrlData
->mpListBox
->SelectEntryPos( GetPagePos( nPageId
) );
1938 ImplCallEventListeners( VCLEVENT_TABPAGE_ACTIVATE
, (void*) (sal_uLong
) nPageId
);
1943 // -----------------------------------------------------------------------
1945 void TabControl::SetTabPage( sal_uInt16 nPageId
, TabPage
* pTabPage
)
1947 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
1949 if ( pItem
&& (pItem
->mpTabPage
!= pTabPage
) )
1953 DBG_ASSERT( !pTabPage
->IsVisible() || isLayoutEnabled(pTabPage
),
1954 "TabControl::SetTabPage() - Non-Layout Enabled Page is visible" );
1956 if ( IsDefaultSize() )
1957 SetTabPageSizePixel( pTabPage
->GetSizePixel() );
1959 // only set here, so that Resize does not reposition TabPage
1960 pItem
->mpTabPage
= pTabPage
;
1962 if ( pItem
->mnId
== mnCurPageId
)
1963 ImplChangeTabPage( pItem
->mnId
, 0 );
1967 pItem
->mpTabPage
= NULL
;
1973 // -----------------------------------------------------------------------
1975 TabPage
* TabControl::GetTabPage( sal_uInt16 nPageId
) const
1977 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
1980 return pItem
->mpTabPage
;
1985 // -----------------------------------------------------------------------
1987 void TabControl::SetPageText( sal_uInt16 nPageId
, const XubString
& rText
)
1989 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
1991 if ( pItem
&& pItem
->maText
!= rText
)
1993 pItem
->maText
= rText
;
1994 mbFormat
= sal_True
;
1995 if( mpTabCtrlData
->mpListBox
)
1997 sal_uInt16 nPos
= GetPagePos( nPageId
);
1998 mpTabCtrlData
->mpListBox
->RemoveEntry( nPos
);
1999 mpTabCtrlData
->mpListBox
->InsertEntry( rText
, nPos
);
2001 if ( IsUpdateMode() )
2003 ImplFreeLayoutData();
2004 ImplCallEventListeners( VCLEVENT_TABPAGE_PAGETEXTCHANGED
, (void*) (sal_uLong
) nPageId
);
2008 // -----------------------------------------------------------------------
2010 XubString
TabControl::GetPageText( sal_uInt16 nPageId
) const
2012 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
2015 return pItem
->maText
;
2017 return ImplGetSVEmptyStr();
2020 // -----------------------------------------------------------------------
2022 void TabControl::SetHelpText( sal_uInt16 nPageId
, const XubString
& rText
)
2024 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
2027 pItem
->maHelpText
= rText
;
2030 // -----------------------------------------------------------------------
2032 const XubString
& TabControl::GetHelpText( sal_uInt16 nPageId
) const
2034 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
2038 if ( !pItem
->maHelpText
.Len() && !pItem
->maHelpId
.isEmpty() )
2040 Help
* pHelp
= Application::GetHelp();
2042 pItem
->maHelpText
= pHelp
->GetHelpText( OStringToOUString( pItem
->maHelpId
, RTL_TEXTENCODING_UTF8
), this );
2045 return pItem
->maHelpText
;
2048 return ImplGetSVEmptyStr();
2051 // -----------------------------------------------------------------------
2053 void TabControl::SetHelpId( sal_uInt16 nPageId
, const OString
& rId
) const
2055 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
2058 pItem
->maHelpId
= rId
;
2061 OString
TabControl::GetHelpId( sal_uInt16 nPageId
) const
2063 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
2066 return pItem
->maHelpId
;
2071 void TabControl::SetPageName( sal_uInt16 nPageId
, const OString
& rName
) const
2073 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
2076 pItem
->maTabName
= rName
;
2079 OString
TabControl::GetPageName( sal_uInt16 nPageId
) const
2081 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
2084 return pItem
->maTabName
;
2089 // -----------------------------------------------------------------------
2091 void TabControl::SetPageImage( sal_uInt16 i_nPageId
, const Image
& i_rImage
)
2093 ImplTabItem
* pItem
= ImplGetItem( i_nPageId
);
2097 pItem
->maTabImage
= i_rImage
;
2098 mbFormat
= sal_True
;
2099 if ( IsUpdateMode() )
2104 // -----------------------------------------------------------------------
2106 Rectangle
TabControl::GetCharacterBounds( sal_uInt16 nPageId
, long nIndex
) const
2110 if( !HasLayoutData() || ! mpTabCtrlData
->maLayoutPageIdToLine
.size() )
2113 if( HasLayoutData() )
2115 boost::unordered_map
< int, int >::const_iterator it
= mpTabCtrlData
->maLayoutPageIdToLine
.find( (int)nPageId
);
2116 if( it
!= mpTabCtrlData
->maLayoutPageIdToLine
.end() )
2118 Pair aPair
= mpControlData
->mpLayoutData
->GetLineStartEnd( it
->second
);
2119 if( (aPair
.B() - aPair
.A()) >= nIndex
)
2120 aRet
= mpControlData
->mpLayoutData
->GetCharacterBounds( aPair
.A() + nIndex
);
2127 // -----------------------------------------------------------------------
2129 long TabControl::GetIndexForPoint( const Point
& rPoint
, sal_uInt16
& rPageId
) const
2133 if( !HasLayoutData() || ! mpTabCtrlData
->maLayoutPageIdToLine
.size() )
2136 if( HasLayoutData() )
2138 int nIndex
= mpControlData
->mpLayoutData
->GetIndexForPoint( rPoint
);
2141 // what line (->pageid) is this index in ?
2142 int nLines
= mpControlData
->mpLayoutData
->GetLineCount();
2144 while( ++nLine
< nLines
)
2146 Pair aPair
= mpControlData
->mpLayoutData
->GetLineStartEnd( nLine
);
2147 if( aPair
.A() <= nIndex
&& aPair
.B() >= nIndex
)
2149 nRet
= nIndex
- aPair
.A();
2150 rPageId
= (sal_uInt16
)mpTabCtrlData
->maLayoutLineToPageId
[ nLine
];
2160 // -----------------------------------------------------------------------
2162 void TabControl::FillLayoutData() const
2164 mpTabCtrlData
->maLayoutLineToPageId
.clear();
2165 mpTabCtrlData
->maLayoutPageIdToLine
.clear();
2166 const_cast<TabControl
*>(this)->ImplPaint( Rectangle(), true );
2169 // -----------------------------------------------------------------------
2171 Rectangle
TabControl::GetTabBounds( sal_uInt16 nPageId
) const
2175 ImplTabItem
* pItem
= ImplGetItem( nPageId
);
2177 aRet
= pItem
->maRect
;
2182 // -----------------------------------------------------------------------
2184 void TabControl::SetItemsOffset( const Point
& rOffs
)
2187 mpTabCtrlData
->maItemsOffset
= rOffs
;
2190 Point
TabControl::GetItemsOffset() const
2193 return mpTabCtrlData
->maItemsOffset
;
2198 // -----------------------------------------------------------------------
2200 Size
TabControl::calculateRequisition() const
2202 Size
aOptimalPageSize(0, 0);
2204 sal_uInt16 nOrigPageId
= GetCurPageId();
2205 for( std::vector
< ImplTabItem
>::const_iterator it
= mpTabCtrlData
->maItemList
.begin();
2206 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
2208 const TabPage
*pPage
= it
->mpTabPage
;
2209 //it's a real nuisance if the page is not inserted yet :-(
2210 //We need to force all tabs to exist to get overall optimal size for dialog
2213 TabControl
*pThis
= const_cast<TabControl
*>(this);
2214 pThis
->SetCurPageId(it
->mnId
);
2215 pThis
->ActivatePage();
2216 pPage
= it
->mpTabPage
;
2222 Size
aPageSize(VclContainer::getLayoutRequisition(*pPage
));
2224 if (aPageSize
.Width() > aOptimalPageSize
.Width())
2225 aOptimalPageSize
.Width() = aPageSize
.Width();
2226 if (aPageSize
.Height() > aOptimalPageSize
.Height())
2227 aOptimalPageSize
.Height() = aPageSize
.Height();
2230 //fdo#61940 If we were forced to activate pages in order to on-demand
2231 //create them to get their optimal size, then switch back to the original
2232 //page and re-activate it
2233 if (nOrigPageId
!= GetCurPageId())
2235 TabControl
*pThis
= const_cast<TabControl
*>(this);
2236 pThis
->SetCurPageId(nOrigPageId
);
2237 pThis
->ActivatePage();
2240 long nTabLabelsBottom
= 0, nTabLabelsRight
= 0;
2241 for( std::vector
< ImplTabItem
>::const_iterator it
= mpTabCtrlData
->maItemList
.begin();
2242 it
!= mpTabCtrlData
->maItemList
.end(); ++it
)
2244 TabControl
* pThis
= const_cast<TabControl
*>(this);
2246 sal_uInt16 nPos
= it
- mpTabCtrlData
->maItemList
.begin();
2247 Rectangle aTabRect
= pThis
->ImplGetTabRect(nPos
, aOptimalPageSize
.Width(), LONG_MAX
);
2248 if (aTabRect
.Bottom() > nTabLabelsBottom
)
2249 nTabLabelsBottom
= aTabRect
.Bottom();
2250 if (aTabRect
.Right() > nTabLabelsRight
)
2251 nTabLabelsRight
= aTabRect
.Right();
2254 Size
aOptimalSize(aOptimalPageSize
);
2255 aOptimalSize
.Height() += nTabLabelsBottom
;
2256 aOptimalSize
.Width() = std::max(nTabLabelsRight
, aOptimalSize
.Width());
2258 aOptimalSize
.Width() += TAB_OFFSET
* 2;
2259 aOptimalSize
.Height() += TAB_OFFSET
* 2;
2261 return aOptimalSize
;
2264 Size
TabControl::GetOptimalSize() const
2266 return calculateRequisition();
2269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */