LCOV - code coverage report
Current view: top level - vcl/source/control - tabctrl.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 527 1195 44.1 %
Date: 2014-11-03 Functions: 46 86 53.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "tools/debug.hxx"
      21             : #include "tools/rc.h"
      22             : 
      23             : #include "vcl/svapp.hxx"
      24             : #include "vcl/help.hxx"
      25             : #include "vcl/event.hxx"
      26             : #include "vcl/menu.hxx"
      27             : #include "vcl/button.hxx"
      28             : #include "vcl/tabpage.hxx"
      29             : #include "vcl/tabctrl.hxx"
      30             : #include "vcl/controllayout.hxx"
      31             : #include "vcl/layout.hxx"
      32             : #include "vcl/lstbox.hxx"
      33             : #include "vcl/settings.hxx"
      34             : 
      35             : #include "controldata.hxx"
      36             : #include "svdata.hxx"
      37             : #include "window.h"
      38             : 
      39             : #include <boost/unordered_map.hpp>
      40             : #include <vector>
      41             : 
      42        1508 : struct ImplTabItem
      43             : {
      44             :     sal_uInt16          mnId;
      45             :     TabPage*            mpTabPage;
      46             :     OUString            maText;
      47             :     OUString            maFormatText;
      48             :     OUString            maHelpText;
      49             :     OString             maHelpId;
      50             :     OString             maTabName;
      51             :     Rectangle           maRect;
      52             :     sal_uInt16          mnLine;
      53             :     bool                mbFullVisible;
      54             :     bool                mbEnabled;
      55             :     Image               maTabImage;
      56             : 
      57         260 :     ImplTabItem()
      58             :     : mnId( 0 ), mpTabPage( NULL ),
      59         260 :       mnLine( 0 ), mbFullVisible( false ), mbEnabled( true )
      60         260 :     {}
      61             : };
      62             : 
      63         112 : struct ImplTabCtrlData
      64             : {
      65             :     boost::unordered_map< int, int >        maLayoutPageIdToLine;
      66             :     boost::unordered_map< int, int >        maLayoutLineToPageId;
      67             :     std::vector< Rectangle >        maTabRectangles;
      68             :     Point                           maItemsOffset;       // offset of the tabitems
      69             :     std::vector< ImplTabItem >      maItemList;
      70             :     ListBox*                        mpListBox;
      71             : };
      72             : 
      73             : #define TAB_OFFSET          3
      74             : #define TAB_TABOFFSET_X     3
      75             : #define TAB_TABOFFSET_Y     3
      76             : #define TAB_EXTRASPACE_X    6
      77             : #define TAB_BORDER_LEFT     1
      78             : #define TAB_BORDER_TOP      1
      79             : #define TAB_BORDER_RIGHT    2
      80             : #define TAB_BORDER_BOTTOM   2
      81             : 
      82             : // for the Tab positions
      83             : #define TAB_PAGERECT        0xFFFF
      84             : 
      85          56 : void TabControl::ImplInit( vcl::Window* pParent, WinBits nStyle )
      86             : {
      87          56 :     mbLayoutDirty = true;
      88             : 
      89          56 :     if ( !(nStyle & WB_NOTABSTOP) )
      90          56 :         nStyle |= WB_TABSTOP;
      91          56 :     if ( !(nStyle & WB_NOGROUP) )
      92          56 :         nStyle |= WB_GROUP;
      93          56 :     if ( !(nStyle & WB_NODIALOGCONTROL) )
      94          56 :         nStyle |= WB_DIALOGCONTROL;
      95             : 
      96          56 :     Control::ImplInit( pParent, nStyle, NULL );
      97             : 
      98          56 :     mnLastWidth                 = 0;
      99          56 :     mnLastHeight                = 0;
     100          56 :     mnBtnSize                   = 0;
     101          56 :     mnMaxPageWidth              = 0;
     102          56 :     mnActPageId                 = 0;
     103          56 :     mnCurPageId                 = 0;
     104          56 :     mbFormat                    = true;
     105          56 :     mbRestoreHelpId             = false;
     106          56 :     mbRestoreUnqId              = false;
     107          56 :     mbSmallInvalidate           = false;
     108          56 :     mpTabCtrlData               = new ImplTabCtrlData;
     109          56 :     mpTabCtrlData->mpListBox    = NULL;
     110             : 
     111          56 :     ImplInitSettings( true, true, true );
     112             : 
     113          56 :     if( (nStyle & WB_DROPDOWN) )
     114             :     {
     115           0 :         mpTabCtrlData->mpListBox = new ListBox( this, WB_DROPDOWN );
     116           0 :         mpTabCtrlData->mpListBox->SetPosSizePixel( Point( 0, 0 ), Size( 200, 20 ) );
     117           0 :         mpTabCtrlData->mpListBox->SetSelectHdl( LINK( this, TabControl, ImplListBoxSelectHdl ) );
     118           0 :         mpTabCtrlData->mpListBox->Show();
     119             :     }
     120             : 
     121             :     // if the tabcontrol is drawn (ie filled) by a native widget, make sure all contols will have transparent background
     122             :     // otherwise they will paint with a wrong background
     123          56 :     if( IsNativeControlSupported(CTRL_TAB_PANE, PART_ENTIRE_CONTROL) )
     124           0 :         EnableChildTransparentMode( true );
     125             : 
     126          56 :     if (pParent && pParent->IsDialog())
     127           0 :         pParent->AddChildEventListener( LINK( this, TabControl, ImplWindowEventListener ) );
     128          56 : }
     129             : 
     130          58 : const vcl::Font& TabControl::GetCanonicalFont( const StyleSettings& _rStyle ) const
     131             : {
     132          58 :     return _rStyle.GetAppFont();
     133             : }
     134             : 
     135          58 : const Color& TabControl::GetCanonicalTextColor( const StyleSettings& _rStyle ) const
     136             : {
     137          58 :     return _rStyle.GetButtonTextColor();
     138             : }
     139             : 
     140          58 : void TabControl::ImplInitSettings( bool bFont,
     141             :                                    bool bForeground, bool bBackground )
     142             : {
     143          58 :     Control::ImplInitSettings( bFont, bForeground );
     144             : 
     145          58 :     if ( bBackground )
     146             :     {
     147          58 :         vcl::Window* pParent = GetParent();
     148         116 :         if ( !IsControlBackground() &&
     149          58 :             (pParent->IsChildTransparentModeEnabled()
     150          58 :             || IsNativeControlSupported(CTRL_TAB_PANE, PART_ENTIRE_CONTROL)
     151          58 :             || IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL) ) )
     152             : 
     153             :         {
     154             :             // set transparent mode for NWF tabcontrols to have
     155             :             // the background always cleared properly
     156           0 :             EnableChildTransparentMode( true );
     157           0 :             SetParentClipMode( PARENTCLIPMODE_NOCLIP );
     158           0 :             SetPaintTransparent( true );
     159           0 :             SetBackground();
     160           0 :             ImplGetWindowImpl()->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects;
     161             :         }
     162             :         else
     163             :         {
     164          58 :             EnableChildTransparentMode( false );
     165          58 :             SetParentClipMode( 0 );
     166          58 :             SetPaintTransparent( false );
     167             : 
     168          58 :             if ( IsControlBackground() )
     169           0 :                 SetBackground( GetControlBackground() );
     170             :             else
     171          58 :                 SetBackground( pParent->GetBackground() );
     172             :         }
     173             :     }
     174          58 : }
     175             : 
     176        1112 : void TabControl::ImplFreeLayoutData()
     177             : {
     178        1112 :     if( HasLayoutData() )
     179             :     {
     180           0 :         ImplClearLayoutData();
     181           0 :         mpTabCtrlData->maLayoutPageIdToLine.clear();
     182           0 :         mpTabCtrlData->maLayoutLineToPageId.clear();
     183             :     }
     184        1112 : }
     185             : 
     186          56 : TabControl::TabControl( vcl::Window* pParent, WinBits nStyle ) :
     187          56 :     Control( WINDOW_TABCONTROL )
     188             : {
     189          56 :     ImplInit( pParent, nStyle );
     190             :     OSL_TRACE("*** TABCONTROL no notabs? %s", ( GetStyle() & WB_NOBORDER ) ? "true" : "false" );
     191          56 : }
     192             : 
     193         112 : TabControl::~TabControl()
     194             : {
     195          56 :     Window *pParent = GetParent();
     196          56 :     if (pParent && pParent->IsDialog())
     197           0 :         GetParent()->RemoveChildEventListener( LINK( this, TabControl, ImplWindowEventListener ) );
     198             : 
     199          56 :     ImplFreeLayoutData();
     200             : 
     201             :     // delete TabCtrl data
     202          56 :     if ( mpTabCtrlData )
     203             :     {
     204          56 :         if( mpTabCtrlData->mpListBox )
     205           0 :             delete mpTabCtrlData->mpListBox;
     206          56 :         delete mpTabCtrlData;
     207             :     }
     208          56 : }
     209             : 
     210        3536 : ImplTabItem* TabControl::ImplGetItem( sal_uInt16 nId ) const
     211             : {
     212       21840 :     for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
     213       14560 :          it != mpTabCtrlData->maItemList.end(); ++it )
     214             :     {
     215        7176 :         if( it->mnId == nId )
     216        3432 :             return &(*it);
     217             :     }
     218             : 
     219         104 :     return NULL;
     220             : }
     221             : 
     222        3404 : Size TabControl::ImplGetItemSize( ImplTabItem* pItem, long nMaxWidth )
     223             : {
     224        3404 :     pItem->maFormatText = pItem->maText;
     225        3404 :     Size aSize( GetCtrlTextWidth( pItem->maFormatText ), GetTextHeight() );
     226        3404 :     Size aImageSize( 0, 0 );
     227        3404 :     if( !!pItem->maTabImage )
     228             :     {
     229           0 :         aImageSize = pItem->maTabImage.GetSizePixel();
     230           0 :         if( !pItem->maFormatText.isEmpty() )
     231           0 :             aImageSize.Width() += GetTextHeight()/4;
     232             :     }
     233        3404 :     aSize.Width() += aImageSize.Width();
     234        3404 :     if( aImageSize.Height() > aSize.Height() )
     235           0 :         aSize.Height() = aImageSize.Height();
     236             : 
     237        3404 :     aSize.Width()  += TAB_TABOFFSET_X*2;
     238        3404 :     aSize.Height() += TAB_TABOFFSET_Y*2;
     239             : 
     240        3404 :     Rectangle aCtrlRegion( Point( 0, 0 ), aSize );
     241        3404 :     Rectangle aBoundingRgn, aContentRgn;
     242        3404 :     const ImplControlValue aControlValue;
     243        6808 :     if(GetNativeControlRegion( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, aCtrlRegion,
     244             :                                            CTRL_STATE_ENABLED, aControlValue, OUString(),
     245        6808 :                                            aBoundingRgn, aContentRgn ) )
     246             :     {
     247           0 :         return aContentRgn.GetSize();
     248             :     }
     249             : 
     250             :     // For languages with short names (e.g. Chinese), because the space is
     251             :     // normally only one pixel per char
     252        3404 :     if ( pItem->maFormatText.getLength() < TAB_EXTRASPACE_X )
     253         660 :         aSize.Width() += TAB_EXTRASPACE_X-pItem->maFormatText.getLength();
     254             : 
     255             :     // shorten Text if needed
     256        3404 :     if ( aSize.Width()+4 >= nMaxWidth )
     257             :     {
     258         104 :         OUString aAppendStr("...");
     259         104 :         pItem->maFormatText += aAppendStr;
     260         624 :         do
     261             :         {
     262         624 :             pItem->maFormatText = pItem->maFormatText.replaceAt( pItem->maFormatText.getLength()-aAppendStr.getLength()-1, 1, "" );
     263         624 :             aSize.Width() = GetCtrlTextWidth( pItem->maFormatText );
     264         624 :             aSize.Width() += aImageSize.Width();
     265         624 :             aSize.Width() += TAB_TABOFFSET_X*2;
     266             :         }
     267         624 :         while ( (aSize.Width()+4 >= nMaxWidth) && (pItem->maFormatText.getLength() > aAppendStr.getLength()) );
     268         104 :         if ( aSize.Width()+4 >= nMaxWidth )
     269             :         {
     270         104 :             pItem->maFormatText = ".";
     271         104 :             aSize.Width() = 1;
     272         104 :         }
     273             :     }
     274             : 
     275        3404 :     if( pItem->maFormatText.isEmpty() )
     276             :     {
     277           0 :         if( aSize.Height() < aImageSize.Height()+4 ) //leave space for focus rect
     278           0 :             aSize.Height() = aImageSize.Height()+4;
     279             :     }
     280             : 
     281        3404 :     return aSize;
     282             : }
     283             : 
     284             : // Feel free to move this to some more general place for reuse
     285             : // http://en.wikipedia.org/wiki/Word_wrap#Minimum_raggedness
     286             : // Mostly based on Alexey Frunze's nifty example at
     287             : // http://stackoverflow.com/questions/9071205/balanced-word-wrap-minimum-raggedness-in-php
     288             : namespace MinimumRaggednessWrap
     289             : {
     290         382 :     std::deque<size_t> GetEndOfLineIndexes(const std::vector<sal_Int32>& rWidthsOf, sal_Int32 nLineWidth)
     291             :     {
     292         382 :         ++nLineWidth;
     293             : 
     294         382 :         size_t nWidthsCount = rWidthsOf.size();
     295         382 :         std::vector<sal_Int32> aCosts(nWidthsCount * nWidthsCount);
     296             : 
     297             :         // cost function c(i, j) that computes the cost of a line consisting of
     298             :         // the words Word[i] to Word[j]
     299        2084 :         for (size_t i = 0; i < nWidthsCount; ++i)
     300             :         {
     301       10004 :             for (size_t j = 0; j < nWidthsCount; ++j)
     302             :             {
     303        8302 :                 if (j >= i)
     304             :                 {
     305        5002 :                     sal_Int32 c = nLineWidth - (j - i);
     306       16604 :                     for (size_t k = i; k <= j; ++k)
     307       11602 :                         c -= rWidthsOf[k];
     308        5002 :                     c = (c >= 0) ? c * c : SAL_MAX_INT32;
     309        5002 :                     aCosts[j * nWidthsCount + i] = c;
     310             :                 }
     311             :                 else
     312             :                 {
     313        3300 :                     aCosts[j * nWidthsCount + i] = SAL_MAX_INT32;
     314             :                 }
     315             :             }
     316             :         }
     317             : 
     318         764 :         std::vector<sal_Int32> aFunction(nWidthsCount);
     319         764 :         std::vector<sal_Int32> aWrapPoints(nWidthsCount);
     320             : 
     321             :         // f(j) in aFunction[], collect wrap points in aWrapPoints[]
     322        2084 :         for (size_t j = 0; j < nWidthsCount; ++j)
     323             :         {
     324        1702 :             aFunction[j] = aCosts[j * nWidthsCount];
     325        1702 :             if (aFunction[j] == SAL_MAX_INT32)
     326             :             {
     327          52 :                 for (size_t k = 0; k < j; ++k)
     328             :                 {
     329             :                     sal_Int32 s;
     330           0 :                     if (aFunction[k] == SAL_MAX_INT32 || aCosts[j * nWidthsCount + k + 1] == SAL_MAX_INT32)
     331           0 :                         s = SAL_MAX_INT32;
     332             :                     else
     333           0 :                         s = aFunction[k] + aCosts[j * nWidthsCount + k + 1];
     334           0 :                     if (aFunction[j] > s)
     335             :                     {
     336           0 :                         aFunction[j] = s;
     337           0 :                         aWrapPoints[j] = k + 1;
     338             :                     }
     339             :                 }
     340             :             }
     341             :         }
     342             : 
     343         382 :         std::deque<size_t> aSolution;
     344             : 
     345             :         // no solution
     346         382 :         if (aFunction[nWidthsCount - 1] == SAL_MAX_INT32)
     347          52 :             return aSolution;
     348             : 
     349             :         // optimal solution
     350         330 :         size_t j = nWidthsCount - 1;
     351             :         while (true)
     352             :         {
     353         330 :             aSolution.push_front(j);
     354         330 :             if (!aWrapPoints[j])
     355         330 :                 break;
     356           0 :             j = aWrapPoints[j] - 1;
     357             :         }
     358             : 
     359         712 :         return aSolution;
     360             :     }
     361             : };
     362             : 
     363        1034 : Rectangle TabControl::ImplGetTabRect( sal_uInt16 nItemPos, long nWidth, long nHeight )
     364             : {
     365        1034 :     Size aWinSize = Control::GetOutputSizePixel();
     366        1034 :     if ( nWidth < 0 )
     367         465 :         nWidth = aWinSize.Width();
     368        1034 :     if ( nHeight < 0 )
     369         465 :         nHeight = aWinSize.Height();
     370             : 
     371        1034 :     if ( mpTabCtrlData->maItemList.empty() )
     372             :     {
     373           0 :         long nW = nWidth-TAB_OFFSET*2;
     374           0 :         long nH = nHeight-TAB_OFFSET*2;
     375           0 :         return (nW > 0 && nH > 0)
     376             :         ? Rectangle( Point( TAB_OFFSET, TAB_OFFSET ), Size( nW, nH ) )
     377           0 :         : Rectangle();
     378             :     }
     379             : 
     380        1034 :     if ( nItemPos == TAB_PAGERECT )
     381             :     {
     382             :         sal_uInt16 nLastPos;
     383         517 :         if ( mnCurPageId )
     384         517 :             nLastPos = GetPagePos( mnCurPageId );
     385             :         else
     386           0 :             nLastPos = 0;
     387             : 
     388         517 :         Rectangle aRect = ImplGetTabRect( nLastPos, nWidth, nHeight );
     389         517 :         long nW = nWidth-TAB_OFFSET*2;
     390         517 :         long nH = nHeight-aRect.Bottom()-TAB_OFFSET*2;
     391         379 :         aRect = (nW > 0 && nH > 0)
     392         168 :         ? Rectangle( Point( TAB_OFFSET, aRect.Bottom()+TAB_OFFSET ), Size( nW, nH ) )
     393         853 :         : Rectangle();
     394         517 :         return aRect;
     395             :     }
     396             : 
     397         517 :     nWidth -= 1;
     398             : 
     399         517 :     if ( (nWidth <= 0) || (nHeight <= 0) )
     400          86 :         return Rectangle();
     401             : 
     402         431 :     if ( mbFormat || (mnLastWidth != nWidth) || (mnLastHeight != nHeight) )
     403             :     {
     404         382 :         vcl::Font aFont( GetFont() );
     405         382 :         aFont.SetTransparent( true );
     406         382 :         SetFont( aFont );
     407             : 
     408         382 :         Size            aSize;
     409         382 :         const long      nOffsetX = 2 + GetItemsOffset().X();
     410         382 :         const long      nOffsetY = 2 + GetItemsOffset().Y();
     411         382 :         long            nX = nOffsetX;
     412         382 :         long            nY = nOffsetY;
     413         382 :         long            nMaxWidth = nWidth;
     414         382 :         sal_uInt16          nPos = 0;
     415             : 
     416             :         //fdo#66435 throw Knuth/Tex minimum raggedness algorithm at the problem
     417             :         //of ugly bare tabs on lines of their own
     418             : 
     419             :         //collect widths
     420         764 :         std::vector<sal_Int32> aWidths;
     421        6252 :         for( std::vector<ImplTabItem>::iterator it = mpTabCtrlData->maItemList.begin();
     422        4168 :              it != mpTabCtrlData->maItemList.end(); ++it )
     423             :         {
     424        1702 :             aWidths.push_back(ImplGetItemSize( &(*it), nMaxWidth ).Width());
     425             :         }
     426             : 
     427             :         //aBreakIndexes will contain the indexes of the last tab on each row
     428         764 :         std::deque<size_t> aBreakIndexes(MinimumRaggednessWrap::GetEndOfLineIndexes(aWidths, nMaxWidth - nOffsetX - 2));
     429             : 
     430         382 :         if ( (mnMaxPageWidth > 0) && (mnMaxPageWidth < nMaxWidth) )
     431           0 :             nMaxWidth = mnMaxPageWidth;
     432         382 :         nMaxWidth -= GetItemsOffset().X();
     433             : 
     434         382 :         sal_uInt16          nLines = 0;
     435         382 :         sal_uInt16          nCurLine = 0;
     436             :         long            nLineWidthAry[100];
     437             :         sal_uInt16          nLinePosAry[101];
     438             : 
     439         382 :         nLineWidthAry[0] = 0;
     440         382 :         nLinePosAry[0] = 0;
     441         382 :         size_t nIndex = 0;
     442        6252 :         for( std::vector<ImplTabItem>::iterator it = mpTabCtrlData->maItemList.begin();
     443        4168 :              it != mpTabCtrlData->maItemList.end(); ++it, ++nIndex )
     444             :         {
     445        1702 :             aSize = ImplGetItemSize( &(*it), nMaxWidth );
     446             : 
     447        1702 :             bool bNewLine = false;
     448        1702 :             if (!aBreakIndexes.empty() && nIndex > aBreakIndexes.front())
     449             :             {
     450           0 :                 aBreakIndexes.pop_front();
     451           0 :                 bNewLine = true;
     452             :             }
     453             : 
     454        1702 :             if ( bNewLine && (nWidth > 2+nOffsetX) )
     455             :             {
     456           0 :                 if ( nLines == 99 )
     457           0 :                     break;
     458             : 
     459           0 :                 nX = nOffsetX;
     460           0 :                 nY += aSize.Height();
     461           0 :                 nLines++;
     462           0 :                 nLineWidthAry[nLines] = 0;
     463           0 :                 nLinePosAry[nLines] = nPos;
     464             :             }
     465             : 
     466        1702 :             Rectangle aNewRect( Point( nX, nY ), aSize );
     467        1702 :             if ( mbSmallInvalidate && (it->maRect != aNewRect) )
     468           0 :                 mbSmallInvalidate = false;
     469        1702 :             it->maRect = aNewRect;
     470        1702 :             it->mnLine = nLines;
     471        1702 :             it->mbFullVisible = true;
     472             : 
     473        1702 :             nLineWidthAry[nLines] += aSize.Width();
     474        1702 :             nX += aSize.Width();
     475             : 
     476        1702 :             if ( it->mnId == mnCurPageId )
     477         382 :                 nCurLine = nLines;
     478             : 
     479        1702 :             nPos++;
     480             :         }
     481             : 
     482         382 :         if ( nLines && !mpTabCtrlData->maItemList.empty() )
     483             :         {
     484           0 :             long    nDX = 0;
     485           0 :             long    nModDX = 0;
     486           0 :             long    nIDX = 0;
     487             :             sal_uInt16  i;
     488             :             sal_uInt16  n;
     489             :             long    nLineHeightAry[100];
     490           0 :             long    nIH = mpTabCtrlData->maItemList[0].maRect.Bottom()-2;
     491             : 
     492           0 :             i = 0;
     493           0 :             while ( i < nLines+1 )
     494             :             {
     495           0 :                 if ( i <= nCurLine )
     496           0 :                     nLineHeightAry[i] = nIH*(nLines-(nCurLine-i)) + GetItemsOffset().Y();
     497             :                 else
     498           0 :                     nLineHeightAry[i] = nIH*(i-nCurLine-1) + GetItemsOffset().Y();
     499           0 :                 i++;
     500             :             }
     501             : 
     502           0 :             i = 0;
     503           0 :             n = 0;
     504           0 :             nLinePosAry[nLines+1] = (sal_uInt16)mpTabCtrlData->maItemList.size();
     505           0 :             for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
     506           0 :                  it != mpTabCtrlData->maItemList.end(); ++it )
     507             :             {
     508           0 :                 if ( i == nLinePosAry[n] )
     509             :                 {
     510           0 :                     if ( n == nLines+1 )
     511           0 :                         break;
     512             : 
     513           0 :                     nIDX = 0;
     514           0 :                     if( nLinePosAry[n+1]-i > 0 )
     515             :                     {
     516           0 :                         nDX = (nWidth-nOffsetX-nLineWidthAry[n]) / (nLinePosAry[n+1]-i);
     517           0 :                         nModDX = (nWidth-nOffsetX-nLineWidthAry[n]) % (nLinePosAry[n+1]-i);
     518             :                     }
     519             :                     else
     520             :                     {
     521             :                         // FIXME: this is a bad case of tabctrl way too small
     522           0 :                         nDX = 0;
     523           0 :                         nModDX = 0;
     524             :                     }
     525           0 :                     n++;
     526             :                 }
     527             : 
     528           0 :                 it->maRect.Left()   += nIDX;
     529           0 :                 it->maRect.Right()  += nIDX+nDX;
     530           0 :                 it->maRect.Top()     = nLineHeightAry[n-1];
     531           0 :                 it->maRect.Bottom()  = nLineHeightAry[n-1]+nIH;
     532           0 :                 nIDX += nDX;
     533             : 
     534           0 :                 if ( nModDX )
     535             :                 {
     536           0 :                     nIDX++;
     537           0 :                     it->maRect.Right()++;
     538           0 :                     nModDX--;
     539             :                 }
     540             : 
     541           0 :                 i++;
     542             :             }
     543             :         }
     544             :         else
     545             :         {//only one line
     546         382 :             if(ImplGetSVData()->maNWFData.mbCenteredTabs)
     547             :             {
     548           0 :                 int nRightSpace=nMaxWidth;//space left on the right by the tabs
     549           0 :                 for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
     550           0 :                      it != mpTabCtrlData->maItemList.end(); ++it )
     551             :                 {
     552           0 :                     nRightSpace-=it->maRect.Right()-it->maRect.Left();
     553             :                 }
     554           0 :                 for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
     555           0 :                      it != mpTabCtrlData->maItemList.end(); ++it )
     556             :                 {
     557           0 :                     it->maRect.Left()+=(int) (nRightSpace/2);
     558           0 :                     it->maRect.Right()+=(int) (nRightSpace/2);
     559             :                 }
     560             :             }
     561             :         }
     562             : 
     563         382 :         mnLastWidth     = nWidth;
     564         382 :         mnLastHeight    = nHeight;
     565         764 :         mbFormat        = false;
     566             :     }
     567             : 
     568         431 :     return size_t(nItemPos) < mpTabCtrlData->maItemList.size() ? mpTabCtrlData->maItemList[nItemPos].maRect : Rectangle();
     569             : }
     570             : 
     571          52 : void TabControl::ImplChangeTabPage( sal_uInt16 nId, sal_uInt16 nOldId )
     572             : {
     573          52 :     ImplFreeLayoutData();
     574             : 
     575          52 :     ImplTabItem*    pOldItem = ImplGetItem( nOldId );
     576          52 :     ImplTabItem*    pItem = ImplGetItem( nId );
     577          52 :     TabPage*        pOldPage = (pOldItem) ? pOldItem->mpTabPage : NULL;
     578          52 :     TabPage*        pPage = (pItem) ? pItem->mpTabPage : NULL;
     579          52 :     vcl::Window*         pCtrlParent = GetParent();
     580             : 
     581          52 :     if ( IsReallyVisible() && IsUpdateMode() )
     582             :     {
     583           0 :         sal_uInt16 nPos = GetPagePos( nId );
     584           0 :         Rectangle aRect = ImplGetTabRect( nPos );
     585             : 
     586           0 :         if ( !pOldItem || !pItem || (pOldItem->mnLine != pItem->mnLine) )
     587             :         {
     588           0 :             aRect.Left() = 0;
     589           0 :             aRect.Top() = 0;
     590           0 :             aRect.Right() = Control::GetOutputSizePixel().Width();
     591             :         }
     592             :         else
     593             :         {
     594           0 :             aRect.Left()    -= 3;
     595           0 :             aRect.Top()     -= 2;
     596           0 :             aRect.Right()   += 3;
     597           0 :             Invalidate( aRect );
     598           0 :             nPos = GetPagePos( nOldId );
     599           0 :             aRect = ImplGetTabRect( nPos );
     600           0 :             aRect.Left()    -= 3;
     601           0 :             aRect.Top()     -= 2;
     602           0 :             aRect.Right()   += 3;
     603             :         }
     604           0 :         Invalidate( aRect );
     605             :     }
     606             : 
     607          52 :     if ( pOldPage == pPage )
     608          52 :         return;
     609             : 
     610          52 :     Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
     611             : 
     612          52 :     if ( pOldPage )
     613             :     {
     614           0 :         if ( mbRestoreHelpId )
     615           0 :             pCtrlParent->SetHelpId( OString() );
     616           0 :         if ( mbRestoreUnqId )
     617           0 :             pCtrlParent->SetUniqueId( OString() );
     618           0 :         pOldPage->DeactivatePage();
     619             :     }
     620             : 
     621          52 :     if ( pPage )
     622             :     {
     623          52 :         if (  ( GetStyle() & WB_NOBORDER ) )
     624             :         {
     625           0 :             Rectangle aRectNoTab( (const Point&)Point( 0, 0 ), GetSizePixel() );
     626           0 :             pPage->SetPosSizePixel( aRectNoTab.TopLeft(), aRectNoTab.GetSize() );
     627             :         }
     628             :         else
     629          52 :             pPage->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() );
     630             : 
     631             :         // activate page here so the conbtrols can be switched
     632             :         // also set the help id of the parent window to that of the tab page
     633          52 :         if ( GetHelpId().isEmpty() )
     634             :         {
     635          52 :             mbRestoreHelpId = true;
     636          52 :             pCtrlParent->SetHelpId( pPage->GetHelpId() );
     637             :         }
     638          52 :         if ( pCtrlParent->GetUniqueId().isEmpty() )
     639             :         {
     640          52 :             mbRestoreUnqId = true;
     641          52 :             pCtrlParent->SetUniqueId( pPage->GetUniqueId() );
     642             :         }
     643             : 
     644          52 :         pPage->ActivatePage();
     645          52 :         pPage->Show();
     646             : 
     647          52 :         if ( pOldPage && pOldPage->HasChildPathFocus() )
     648             :         {
     649           0 :             sal_uInt16  n = 0;
     650           0 :             vcl::Window* pFirstChild = pPage->ImplGetDlgWindow( n, DLGWINDOW_FIRST );
     651           0 :             if ( pFirstChild )
     652           0 :                 pFirstChild->ImplControlFocus( GETFOCUS_INIT );
     653             :             else
     654           0 :                 GrabFocus();
     655             :         }
     656             :     }
     657             : 
     658          52 :     if ( pOldPage )
     659           0 :         pOldPage->Hide();
     660             : 
     661             :     // Invalidate the same region that will be send to NWF
     662             :     // to always allow for bitmap caching
     663             :     // see Window::DrawNativeControl()
     664          52 :     if( IsNativeControlSupported( CTRL_TAB_PANE, PART_ENTIRE_CONTROL ) )
     665             :     {
     666           0 :         aRect.Left()   -= TAB_OFFSET;
     667           0 :         aRect.Top()    -= TAB_OFFSET;
     668           0 :         aRect.Right()  += TAB_OFFSET;
     669           0 :         aRect.Bottom() += TAB_OFFSET;
     670             :     }
     671             : 
     672          52 :     Invalidate( aRect );
     673             : }
     674             : 
     675         364 : bool TabControl::ImplPosCurTabPage()
     676             : {
     677             :     // resize/position current TabPage
     678         364 :     ImplTabItem* pItem = ImplGetItem( GetCurPageId() );
     679         364 :     if ( pItem && pItem->mpTabPage )
     680             :     {
     681         364 :         if (  ( GetStyle() & WB_NOBORDER ) )
     682             :         {
     683           0 :             Rectangle aRectNoTab( (const Point&)Point( 0, 0 ), GetSizePixel() );
     684           0 :             pItem->mpTabPage->SetPosSizePixel( aRectNoTab.TopLeft(), aRectNoTab.GetSize() );
     685           0 :             return true;
     686             :         }
     687         364 :         Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
     688         364 :         pItem->mpTabPage->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() );
     689         364 :         return true;
     690             :     }
     691             : 
     692           0 :     return false;
     693             : }
     694             : 
     695           0 : void TabControl::ImplActivateTabPage( bool bNext )
     696             : {
     697           0 :     sal_uInt16 nCurPos = GetPagePos( GetCurPageId() );
     698             : 
     699           0 :     if ( bNext )
     700           0 :         nCurPos = (nCurPos + 1) % GetPageCount();
     701             :     else
     702             :     {
     703           0 :         if ( !nCurPos )
     704           0 :             nCurPos = GetPageCount()-1;
     705             :         else
     706           0 :             nCurPos--;
     707             :     }
     708             : 
     709           0 :     SelectTabPage( GetPageId( nCurPos ) );
     710           0 : }
     711             : 
     712           0 : void TabControl::ImplShowFocus()
     713             : {
     714           0 :     if ( !GetPageCount() || mpTabCtrlData->mpListBox )
     715           0 :         return;
     716             : 
     717           0 :     sal_uInt16                   nCurPos     = GetPagePos( mnCurPageId );
     718           0 :     Rectangle                aRect       = ImplGetTabRect( nCurPos );
     719           0 :     const ImplTabItem&       rItem       = mpTabCtrlData->maItemList[ nCurPos ];
     720           0 :     Size                     aTabSize    = aRect.GetSize();
     721           0 :     Size aImageSize( 0, 0 );
     722           0 :     long                     nTextHeight = GetTextHeight();
     723           0 :     long                     nTextWidth  = GetCtrlTextWidth( rItem.maFormatText );
     724             :     sal_uInt16                   nOff;
     725             : 
     726           0 :     if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_MONO) )
     727           0 :         nOff = 1;
     728             :     else
     729           0 :         nOff = 0;
     730             : 
     731           0 :     if( !! rItem.maTabImage )
     732             :     {
     733           0 :         aImageSize = rItem.maTabImage.GetSizePixel();
     734           0 :         if( !rItem.maFormatText.isEmpty() )
     735           0 :             aImageSize.Width() += GetTextHeight()/4;
     736             :     }
     737             : 
     738           0 :     if( !rItem.maFormatText.isEmpty() )
     739             :     {
     740             :         // show focus around text
     741           0 :         aRect.Left()   = aRect.Left()+aImageSize.Width()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-1-1;
     742           0 :         aRect.Top()    = aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-1-1;
     743           0 :         aRect.Right()  = aRect.Left()+nTextWidth+2;
     744           0 :         aRect.Bottom() = aRect.Top()+nTextHeight+2;
     745             :     }
     746             :     else
     747             :     {
     748             :         // show focus around image
     749           0 :         long nXPos = aRect.Left()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-1;
     750           0 :         long nYPos = aRect.Top();
     751           0 :         if( aImageSize.Height() < aRect.GetHeight() )
     752           0 :             nYPos += (aRect.GetHeight() - aImageSize.Height())/2;
     753             : 
     754           0 :         aRect.Left() = nXPos - 2;
     755           0 :         aRect.Top() = nYPos - 2;
     756           0 :         aRect.Right() = aRect.Left() + aImageSize.Width() + 4;
     757           0 :         aRect.Bottom() = aRect.Top() + aImageSize.Height() + 4;
     758             :     }
     759           0 :     ShowFocus( aRect );
     760             : }
     761             : 
     762         125 : void TabControl::ImplDrawItem( ImplTabItem* pItem, const Rectangle& rCurRect, bool bLayout, bool bFirstInGroup, bool bLastInGroup, bool /* bIsCurrentItem */ )
     763             : {
     764         125 :     if ( pItem->maRect.IsEmpty() )
     765         125 :         return;
     766             : 
     767         125 :     if( bLayout )
     768             :     {
     769           0 :         if( !HasLayoutData() )
     770             :         {
     771           0 :             mpControlData->mpLayoutData = new vcl::ControlLayoutData();
     772           0 :             mpTabCtrlData->maLayoutLineToPageId.clear();
     773           0 :             mpTabCtrlData->maLayoutPageIdToLine.clear();
     774           0 :             mpTabCtrlData->maTabRectangles.clear();
     775             :         }
     776             :     }
     777             : 
     778         125 :     const StyleSettings&    rStyleSettings  = GetSettings().GetStyleSettings();
     779         125 :     Rectangle               aRect = pItem->maRect;
     780         125 :     long                    nLeftBottom = aRect.Bottom();
     781         125 :     long                    nRightBottom = aRect.Bottom();
     782         125 :     bool                    bLeftBorder = true;
     783         125 :     bool                    bRightBorder = true;
     784             :     sal_uInt16                  nOff;
     785         125 :     bool                    bNativeOK = false;
     786             : 
     787         125 :     sal_uInt16 nOff2 = 0;
     788         125 :     sal_uInt16 nOff3 = 0;
     789             : 
     790         125 :     if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
     791         125 :         nOff = 1;
     792             :     else
     793           0 :         nOff = 0;
     794             : 
     795             :     // if this is the active Page, we have to draw a little more
     796         125 :     if ( pItem->mnId == mnCurPageId )
     797             :     {
     798          25 :         nOff2 = 2;
     799          25 :         if( ! ImplGetSVData()->maNWFData.mbNoActiveTabTextRaise )
     800          25 :             nOff3 = 1;
     801             :     }
     802             :     else
     803             :     {
     804         100 :         Point aLeftTestPos = aRect.BottomLeft();
     805         100 :         Point aRightTestPos = aRect.BottomRight();
     806         100 :         if ( aLeftTestPos.Y() == rCurRect.Bottom() )
     807             :         {
     808         100 :             aLeftTestPos.X() -= 2;
     809         100 :             if ( rCurRect.IsInside( aLeftTestPos ) )
     810          25 :                 bLeftBorder = false;
     811         100 :             aRightTestPos.X() += 2;
     812         100 :             if ( rCurRect.IsInside( aRightTestPos ) )
     813           0 :                 bRightBorder = false;
     814             :         }
     815             :         else
     816             :         {
     817           0 :             if ( rCurRect.IsInside( aLeftTestPos ) )
     818           0 :                 nLeftBottom -= 2;
     819           0 :             if ( rCurRect.IsInside( aRightTestPos ) )
     820           0 :                 nRightBottom -= 2;
     821             :         }
     822             :     }
     823             : 
     824         125 :     if( !bLayout && (bNativeOK = IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL)) )
     825             :     {
     826           0 :         Rectangle           aCtrlRegion( pItem->maRect );
     827           0 :         ControlState        nState = 0;
     828             : 
     829           0 :         if( pItem->mnId == mnCurPageId )
     830             :         {
     831           0 :             nState |= CTRL_STATE_SELECTED;
     832             :             // only the selected item can be focussed
     833           0 :             if ( HasFocus() )
     834           0 :                 nState |= CTRL_STATE_FOCUSED;
     835             :         }
     836           0 :         if ( IsEnabled() )
     837           0 :             nState |= CTRL_STATE_ENABLED;
     838           0 :         if( IsMouseOver() && pItem->maRect.IsInside( GetPointerPosPixel() ) )
     839             :         {
     840           0 :             nState |= CTRL_STATE_ROLLOVER;
     841           0 :             for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
     842           0 :                  it != mpTabCtrlData->maItemList.end(); ++it )
     843             :             {
     844           0 :                 if( (&(*it) != pItem) && (it->maRect.IsInside( GetPointerPosPixel() ) ) )
     845             :                 {
     846           0 :                     nState &= ~CTRL_STATE_ROLLOVER; // avoid multiple highlighted tabs
     847           0 :                     break;
     848             :                 }
     849             :             }
     850             :         }
     851             : 
     852           0 :         TabitemValue tiValue;
     853           0 :         if(pItem->maRect.Left() < 5)
     854           0 :             tiValue.mnAlignment |= TABITEM_LEFTALIGNED;
     855           0 :         if(pItem->maRect.Right() > mnLastWidth - 5)
     856           0 :             tiValue.mnAlignment |= TABITEM_RIGHTALIGNED;
     857           0 :         if ( bFirstInGroup )
     858           0 :             tiValue.mnAlignment |= TABITEM_FIRST_IN_GROUP;
     859           0 :         if ( bLastInGroup )
     860           0 :             tiValue.mnAlignment |= TABITEM_LAST_IN_GROUP;
     861             : 
     862             :         bNativeOK = DrawNativeControl( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, aCtrlRegion, nState,
     863           0 :                     tiValue, OUString() );
     864             :     }
     865             : 
     866         125 :     if( ! bLayout && !bNativeOK )
     867             :     {
     868         125 :         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
     869             :         {
     870         125 :             SetLineColor( rStyleSettings.GetLightColor() );
     871         125 :             DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) );    // diagonally indented top-left pixel
     872         125 :             if ( bLeftBorder )
     873             :             {
     874         200 :                 DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ),
     875         300 :                           Point( aRect.Left()-nOff2, nLeftBottom-1 ) );
     876             :             }
     877         250 :             DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ),         // top line starting 2px from left border
     878         375 :                       Point( aRect.Right()+nOff2-3, aRect.Top()-nOff2 ) );      // ending 3px from right border
     879             : 
     880         125 :             if ( bRightBorder )
     881             :             {
     882         125 :                 SetLineColor( rStyleSettings.GetShadowColor() );
     883         250 :                 DrawLine( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ),
     884         375 :                           Point( aRect.Right()+nOff2-2, nRightBottom-1 ) );
     885             : 
     886         125 :                 SetLineColor( rStyleSettings.GetDarkShadowColor() );
     887         250 :                 DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+3-nOff2 ),
     888         375 :                           Point( aRect.Right()+nOff2-1, nRightBottom-1 ) );
     889             :             }
     890             :         }
     891             :         else
     892             :         {
     893           0 :             SetLineColor( Color( COL_BLACK ) );
     894           0 :             DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) );
     895           0 :             DrawPixel( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ) );
     896           0 :             if ( bLeftBorder )
     897             :             {
     898           0 :                 DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ),
     899           0 :                           Point( aRect.Left()-nOff2, nLeftBottom-1 ) );
     900             :             }
     901           0 :             DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ),
     902           0 :                       Point( aRect.Right()-3, aRect.Top()-nOff2 ) );
     903           0 :             if ( bRightBorder )
     904             :             {
     905           0 :             DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+2-nOff2 ),
     906           0 :                       Point( aRect.Right()+nOff2-1, nRightBottom-1 ) );
     907             :             }
     908             :         }
     909             :     }
     910             : 
     911         125 :     if( bLayout )
     912             :     {
     913           0 :         int nLine = mpControlData->mpLayoutData->m_aLineIndices.size();
     914           0 :         mpControlData->mpLayoutData->m_aLineIndices.push_back( mpControlData->mpLayoutData->m_aDisplayText.getLength() );
     915           0 :         mpTabCtrlData->maLayoutPageIdToLine[ (int)pItem->mnId ] = nLine;
     916           0 :         mpTabCtrlData->maLayoutLineToPageId[ nLine ] = (int)pItem->mnId;
     917           0 :         mpTabCtrlData->maTabRectangles.push_back( aRect );
     918             :     }
     919             : 
     920             :     // set font accordingly, current item is painted bold
     921             :     // we set the font attributes always before drawing to be re-entrant (DrawNativeControl may trigger additional paints)
     922         125 :     vcl::Font aFont( GetFont() );
     923         125 :     aFont.SetTransparent( true );
     924         125 :     SetFont( aFont );
     925             : 
     926         125 :     Size aTabSize = aRect.GetSize();
     927         125 :     Size aImageSize( 0, 0 );
     928         125 :     long nTextHeight = GetTextHeight();
     929         125 :     long nTextWidth = GetCtrlTextWidth( pItem->maFormatText );
     930         125 :     if( !! pItem->maTabImage )
     931             :     {
     932           0 :         aImageSize = pItem->maTabImage.GetSizePixel();
     933           0 :         if( !pItem->maFormatText.isEmpty() )
     934           0 :             aImageSize.Width() += GetTextHeight()/4;
     935             :     }
     936         125 :     long nXPos = aRect.Left()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-nOff3;
     937         125 :     long nYPos = aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-nOff3;
     938         125 :     if( !pItem->maFormatText.isEmpty() )
     939             :     {
     940         125 :         sal_uInt16 nStyle = TEXT_DRAW_MNEMONIC;
     941         125 :         if( ! pItem->mbEnabled )
     942           0 :             nStyle |= TEXT_DRAW_DISABLE;
     943         125 :         DrawCtrlText( Point( nXPos + aImageSize.Width(), nYPos ),
     944             :                       pItem->maFormatText, 0,
     945             :                       pItem->maFormatText.getLength(), nStyle,
     946             :                       bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL,
     947             :                       bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL
     948         250 :                       );
     949             :     }
     950             : 
     951         125 :     if( !! pItem->maTabImage )
     952             :     {
     953           0 :         Point aImgTL( nXPos, aRect.Top() );
     954           0 :         if( aImageSize.Height() < aRect.GetHeight() )
     955           0 :             aImgTL.Y() += (aRect.GetHeight() - aImageSize.Height())/2;
     956           0 :         DrawImage( aImgTL, pItem->maTabImage, pItem->mbEnabled ? 0 : IMAGE_DRAW_DISABLE );
     957         125 :     }
     958             : }
     959             : 
     960           0 : bool TabControl::ImplHandleKeyEvent( const KeyEvent& rKeyEvent )
     961             : {
     962           0 :     bool nRet = false;
     963             : 
     964           0 :     if ( GetPageCount() > 1 )
     965             :     {
     966           0 :         vcl::KeyCode aKeyCode = rKeyEvent.GetKeyCode();
     967           0 :         sal_uInt16 nKeyCode = aKeyCode.GetCode();
     968             : 
     969           0 :         if ( aKeyCode.IsMod1() )
     970             :         {
     971           0 :             if ( aKeyCode.IsShift() || (nKeyCode == KEY_PAGEUP) )
     972             :             {
     973           0 :                 if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEUP) )
     974             :                 {
     975           0 :                     ImplActivateTabPage( false );
     976           0 :                     nRet = true;
     977             :                 }
     978             :             }
     979             :             else
     980             :             {
     981           0 :                 if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEDOWN) )
     982             :                 {
     983           0 :                     ImplActivateTabPage( true );
     984           0 :                     nRet = true;
     985             :                 }
     986             :             }
     987             :         }
     988             :     }
     989             : 
     990           0 :     return nRet;
     991             : }
     992             : 
     993           0 : IMPL_LINK_NOARG(TabControl, ImplListBoxSelectHdl)
     994             : {
     995           0 :     SelectTabPage( GetPageId( mpTabCtrlData->mpListBox->GetSelectEntryPos() ) );
     996           0 :     return 0;
     997             : }
     998             : 
     999           0 : IMPL_LINK( TabControl, ImplWindowEventListener, VclSimpleEvent*, pEvent )
    1000             : {
    1001           0 :     if ( pEvent && pEvent->ISA( VclWindowEvent ) && (pEvent->GetId() == VCLEVENT_WINDOW_KEYINPUT) )
    1002             :     {
    1003           0 :         VclWindowEvent* pWindowEvent = static_cast< VclWindowEvent* >(pEvent);
    1004             :         // Do not handle events from TabControl or its children, which is done in Notify(), where the events can be consumed.
    1005           0 :         if ( !IsWindowOrChild( pWindowEvent->GetWindow() ) )
    1006             :         {
    1007           0 :             KeyEvent* pKeyEvent = static_cast< KeyEvent* >(pWindowEvent->GetData());
    1008           0 :             ImplHandleKeyEvent( *pKeyEvent );
    1009             :         }
    1010             :     }
    1011           0 :     return 0;
    1012             : }
    1013             : 
    1014           0 : void TabControl::MouseButtonDown( const MouseEvent& rMEvt )
    1015             : {
    1016           0 :     if( mpTabCtrlData->mpListBox == NULL )
    1017             :     {
    1018           0 :         if( rMEvt.IsLeft() )
    1019             :         {
    1020           0 :             sal_uInt16 nPageId = GetPageId( rMEvt.GetPosPixel() );
    1021           0 :             ImplTabItem* pItem = ImplGetItem( nPageId );
    1022           0 :             if( pItem && pItem->mbEnabled )
    1023           0 :                 SelectTabPage( nPageId );
    1024             :         }
    1025             :     }
    1026           0 : }
    1027             : 
    1028           0 : void TabControl::KeyInput( const KeyEvent& rKEvt )
    1029             : {
    1030           0 :     if( mpTabCtrlData->mpListBox )
    1031           0 :         mpTabCtrlData->mpListBox->KeyInput( rKEvt );
    1032           0 :     else if ( GetPageCount() > 1 )
    1033             :     {
    1034           0 :         vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
    1035           0 :         sal_uInt16  nKeyCode = aKeyCode.GetCode();
    1036             : 
    1037           0 :         if ( (nKeyCode == KEY_LEFT) || (nKeyCode == KEY_RIGHT) )
    1038             :         {
    1039           0 :             bool bNext = (nKeyCode == KEY_RIGHT);
    1040           0 :             ImplActivateTabPage( bNext );
    1041             :         }
    1042             :     }
    1043             : 
    1044           0 :     Control::KeyInput( rKEvt );
    1045           0 : }
    1046             : 
    1047          25 : void TabControl::Paint( const Rectangle& rRect )
    1048             : {
    1049          25 :     if (  !( GetStyle() & WB_NOBORDER ) )
    1050          25 :         ImplPaint( rRect, false );
    1051          25 : }
    1052             : 
    1053          25 : void TabControl::ImplPaint( const Rectangle& rRect, bool bLayout )
    1054             : {
    1055          25 :     if( ! bLayout )
    1056          25 :         HideFocus();
    1057             : 
    1058             :     // reformat if needed
    1059          25 :     Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
    1060             : 
    1061             :     // find current item
    1062          25 :     ImplTabItem* pCurItem = NULL;
    1063          75 :     for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
    1064          50 :          it != mpTabCtrlData->maItemList.end(); ++it )
    1065             :     {
    1066          25 :         if ( it->mnId == mnCurPageId )
    1067             :         {
    1068          25 :             pCurItem = &(*it);
    1069          25 :             break;
    1070             :         }
    1071             :     }
    1072             : 
    1073             :     // Draw the TabPage border
    1074          25 :     const StyleSettings&    rStyleSettings  = GetSettings().GetStyleSettings();
    1075          25 :     Rectangle               aCurRect;
    1076          25 :     aRect.Left()   -= TAB_OFFSET;
    1077          25 :     aRect.Top()    -= TAB_OFFSET;
    1078          25 :     aRect.Right()  += TAB_OFFSET;
    1079          25 :     aRect.Bottom() += TAB_OFFSET;
    1080             : 
    1081             :     // if we have an invisible tabpage or no tabpage at all the tabpage rect should be
    1082             :     // increased to avoid round corners that might be drawn by a theme
    1083             :     // in this case we're only interested in the top border of the tabpage because the tabitems are used
    1084             :     // standalone (eg impress)
    1085          25 :     bool bNoTabPage = false;
    1086          25 :     TabPage* pCurPage = pCurItem ? pCurItem->mpTabPage : NULL;
    1087          25 :     if( !pCurPage || !pCurPage->IsVisible() )
    1088             :     {
    1089          25 :         bNoTabPage = true;
    1090          25 :         aRect.Left()-=10;
    1091          25 :         aRect.Right()+=10;
    1092             :     }
    1093             : 
    1094          25 :     bool bNativeOK = false;
    1095          25 :     if( ! bLayout && (bNativeOK = IsNativeControlSupported( CTRL_TAB_PANE, PART_ENTIRE_CONTROL) ) )
    1096             :     {
    1097           0 :         const ImplControlValue aControlValue;
    1098             : 
    1099           0 :         ControlState nState = CTRL_STATE_ENABLED;
    1100           0 :         int part = PART_ENTIRE_CONTROL;
    1101           0 :         if ( !IsEnabled() )
    1102           0 :             nState &= ~CTRL_STATE_ENABLED;
    1103           0 :         if ( HasFocus() )
    1104           0 :             nState |= CTRL_STATE_FOCUSED;
    1105             : 
    1106           0 :         vcl::Region aClipRgn( GetActiveClipRegion() );
    1107           0 :         aClipRgn.Intersect( aRect );
    1108           0 :         if( !rRect.IsEmpty() )
    1109           0 :             aClipRgn.Intersect( rRect );
    1110             : 
    1111           0 :         if( !aClipRgn.IsEmpty() )
    1112             :             bNativeOK = DrawNativeControl( CTRL_TAB_PANE, part, aRect, nState,
    1113           0 :                 aControlValue, OUString() );
    1114             :     }
    1115             :     else
    1116             :     {
    1117          25 :         long nTopOff = 1;
    1118          25 :         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
    1119          25 :             SetLineColor( rStyleSettings.GetLightColor() );
    1120             :         else
    1121           0 :             SetLineColor( Color( COL_BLACK ) );
    1122          25 :         if ( pCurItem && !pCurItem->maRect.IsEmpty() )
    1123             :         {
    1124          25 :             aCurRect = pCurItem->maRect;
    1125          25 :             if( ! bLayout )
    1126          25 :                 DrawLine( aRect.TopLeft(), Point( aCurRect.Left()-2, aRect.Top() ) );
    1127          25 :             if ( aCurRect.Right()+1 < aRect.Right() )
    1128             :             {
    1129           0 :                 if( ! bLayout )
    1130           0 :                     DrawLine( Point( aCurRect.Right(), aRect.Top() ), aRect.TopRight() );
    1131             :             }
    1132             :             else
    1133          25 :                 nTopOff = 0;
    1134             :         }
    1135             :         else
    1136           0 :             if( ! bLayout )
    1137           0 :                 DrawLine( aRect.TopLeft(), aRect.TopRight() );
    1138             : 
    1139          25 :         if( ! bLayout )
    1140             :         {
    1141          25 :             DrawLine( aRect.TopLeft(), aRect.BottomLeft() );
    1142             : 
    1143          25 :             if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
    1144             :             {
    1145             :                 // if we have not tab page the bottom line of the tab page
    1146             :                 // directly touches the tab items, so choose a color that fits seamlessly
    1147          25 :                 if( bNoTabPage )
    1148          25 :                     SetLineColor( rStyleSettings.GetDialogColor() );
    1149             :                 else
    1150           0 :                     SetLineColor( rStyleSettings.GetShadowColor() );
    1151          25 :                 DrawLine( Point( 1, aRect.Bottom()-1 ),
    1152          50 :                         Point( aRect.Right()-1, aRect.Bottom()-1 ) );
    1153          50 :                 DrawLine( Point( aRect.Right()-1, aRect.Top()+nTopOff ),
    1154          75 :                         Point( aRect.Right()-1, aRect.Bottom()-1 ) );
    1155          25 :                 if( bNoTabPage )
    1156          25 :                     SetLineColor( rStyleSettings.GetDialogColor() );
    1157             :                 else
    1158           0 :                     SetLineColor( rStyleSettings.GetDarkShadowColor() );
    1159          25 :                 DrawLine( Point( 0, aRect.Bottom() ),
    1160          50 :                         Point( aRect.Right(), aRect.Bottom() ) );
    1161          50 :                 DrawLine( Point( aRect.Right(), aRect.Top()+nTopOff ),
    1162          75 :                         Point( aRect.Right(), aRect.Bottom() ) );
    1163             :             }
    1164             :             else
    1165             :             {
    1166           0 :                 DrawLine( aRect.TopRight(), aRect.BottomRight() );
    1167           0 :                 DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
    1168             :             }
    1169             :         }
    1170             :     }
    1171             : 
    1172          25 :     if ( !mpTabCtrlData->maItemList.empty() && mpTabCtrlData->mpListBox == NULL )
    1173             :     {
    1174             :         // Some native toolkits (GTK+) draw tabs right-to-left, with an
    1175             :         // overlap between adjacent tabs
    1176          25 :         bool            bDrawTabsRTL = IsNativeControlSupported( CTRL_TAB_ITEM, PART_TABS_DRAW_RTL );
    1177          25 :         ImplTabItem *   pFirstTab = NULL;
    1178          25 :         ImplTabItem *   pLastTab = NULL;
    1179             :         size_t idx;
    1180             : 
    1181             :         // Event though there is a tab overlap with GTK+, the first tab is not
    1182             :         // overlapped on the left side.  Other tookits ignore this option.
    1183          25 :         if ( bDrawTabsRTL )
    1184             :         {
    1185           0 :             pFirstTab = &mpTabCtrlData->maItemList.front();
    1186           0 :             pLastTab = &mpTabCtrlData->maItemList.back();
    1187           0 :             idx = mpTabCtrlData->maItemList.size()-1;
    1188             :         }
    1189             :         else
    1190             :         {
    1191          25 :             pLastTab = &mpTabCtrlData->maItemList.back();
    1192          25 :             pFirstTab = &mpTabCtrlData->maItemList.front();
    1193          25 :             idx = 0;
    1194             :         }
    1195             : 
    1196         175 :         while ( idx < mpTabCtrlData->maItemList.size() )
    1197             :         {
    1198         125 :             ImplTabItem* pItem = &mpTabCtrlData->maItemList[idx];
    1199         125 :             if ( pItem != pCurItem )
    1200             :             {
    1201         100 :                 vcl::Region aClipRgn( GetActiveClipRegion() );
    1202         100 :                 aClipRgn.Intersect( pItem->maRect );
    1203         100 :                 if( !rRect.IsEmpty() )
    1204         100 :                     aClipRgn.Intersect( rRect );
    1205         100 :                 if( bLayout || !aClipRgn.IsEmpty() )
    1206         100 :                     ImplDrawItem( pItem, aCurRect, bLayout, (pItem==pFirstTab), (pItem==pLastTab), false );
    1207             :             }
    1208             : 
    1209         125 :             if ( bDrawTabsRTL )
    1210           0 :                 idx--;
    1211             :             else
    1212         125 :                 idx++;
    1213             :         }
    1214             : 
    1215          25 :         if ( pCurItem )
    1216             :         {
    1217          25 :             vcl::Region aClipRgn( GetActiveClipRegion() );
    1218          25 :             aClipRgn.Intersect( pCurItem->maRect );
    1219          25 :             if( !rRect.IsEmpty() )
    1220          25 :                 aClipRgn.Intersect( rRect );
    1221          25 :             if( bLayout || !aClipRgn.IsEmpty() )
    1222          25 :                 ImplDrawItem( pCurItem, aCurRect, bLayout, (pCurItem==pFirstTab), (pCurItem==pLastTab), true );
    1223             :         }
    1224             :     }
    1225             : 
    1226          25 :     if ( !bLayout && HasFocus() )
    1227           0 :         ImplShowFocus();
    1228             : 
    1229          25 :     if( ! bLayout )
    1230          25 :         mbSmallInvalidate = true;
    1231          25 : }
    1232             : 
    1233         684 : void TabControl::setAllocation(const Size &rAllocation)
    1234             : {
    1235         684 :     ImplFreeLayoutData();
    1236             : 
    1237         684 :     if ( !IsReallyShown() )
    1238        1056 :         return;
    1239             : 
    1240         312 :     if( mpTabCtrlData->mpListBox )
    1241             :     {
    1242             :         // get the listbox' preferred size
    1243           0 :         Size aTabCtrlSize( GetSizePixel() );
    1244           0 :         long nPrefWidth = mpTabCtrlData->mpListBox->get_preferred_size().Width();
    1245           0 :         if( nPrefWidth > aTabCtrlSize.Width() )
    1246           0 :             nPrefWidth = aTabCtrlSize.Width();
    1247           0 :         Size aNewSize( nPrefWidth, LogicToPixel( Size( 12, 12 ), MapMode( MAP_APPFONT ) ).Height() );
    1248           0 :         Point aNewPos( (aTabCtrlSize.Width() - nPrefWidth) / 2, 0 );
    1249           0 :         mpTabCtrlData->mpListBox->SetPosSizePixel( aNewPos, aNewSize );
    1250             :     }
    1251             : 
    1252         312 :     mbFormat = true;
    1253             : 
    1254             :     // resize/position active TabPage
    1255         312 :     bool bTabPage = ImplPosCurTabPage();
    1256             : 
    1257             :     // check what needs to be invalidated
    1258         312 :     Size aNewSize = rAllocation;
    1259         312 :     long nNewWidth = aNewSize.Width();
    1260        5616 :     for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
    1261        3744 :          it != mpTabCtrlData->maItemList.end(); ++it )
    1262             :     {
    1263        3120 :         if ( !it->mbFullVisible ||
    1264        1560 :              (it->maRect.Right()-2 >= nNewWidth) )
    1265             :         {
    1266           0 :             mbSmallInvalidate = false;
    1267           0 :             break;
    1268             :         }
    1269             :     }
    1270             : 
    1271         312 :     if ( mbSmallInvalidate )
    1272             :     {
    1273          24 :         Rectangle aRect = ImplGetTabRect( TAB_PAGERECT );
    1274          24 :         aRect.Left()   -= TAB_OFFSET+TAB_BORDER_LEFT;
    1275          24 :         aRect.Top()    -= TAB_OFFSET+TAB_BORDER_TOP;
    1276          24 :         aRect.Right()  += TAB_OFFSET+TAB_BORDER_RIGHT;
    1277          24 :         aRect.Bottom() += TAB_OFFSET+TAB_BORDER_BOTTOM;
    1278          24 :         if ( bTabPage )
    1279          24 :             Invalidate( aRect, INVALIDATE_NOCHILDREN );
    1280             :         else
    1281           0 :             Invalidate( aRect );
    1282             : 
    1283             :     }
    1284             :     else
    1285             :     {
    1286         288 :         if ( bTabPage )
    1287         288 :             Invalidate( INVALIDATE_NOCHILDREN );
    1288             :         else
    1289           0 :             Invalidate();
    1290             :     }
    1291             : 
    1292         312 :     mbLayoutDirty = false;
    1293             : }
    1294             : 
    1295         420 : void TabControl::SetPosSizePixel(const Point& rNewPos, const Size& rNewSize)
    1296             : {
    1297         420 :     Window::SetPosSizePixel(rNewPos, rNewSize);
    1298             :     //if size changed, TabControl::Resize got called already
    1299         420 :     if (mbLayoutDirty)
    1300         108 :         setAllocation(rNewSize);
    1301         420 : }
    1302             : 
    1303          52 : void TabControl::SetSizePixel(const Size& rNewSize)
    1304             : {
    1305          52 :     Window::SetSizePixel(rNewSize);
    1306             :     //if size changed, TabControl::Resize got called already
    1307          52 :     if (mbLayoutDirty)
    1308          52 :         setAllocation(rNewSize);
    1309          52 : }
    1310             : 
    1311           0 : void TabControl::SetPosPixel(const Point& rPos)
    1312             : {
    1313           0 :     Window::SetPosPixel(rPos);
    1314           0 :     if (mbLayoutDirty)
    1315           0 :         setAllocation(GetOutputSizePixel());
    1316           0 : }
    1317             : 
    1318         524 : void TabControl::Resize()
    1319             : {
    1320         524 :     setAllocation(Control::GetOutputSizePixel());
    1321         524 : }
    1322             : 
    1323           0 : void TabControl::GetFocus()
    1324             : {
    1325           0 :     if( ! mpTabCtrlData->mpListBox )
    1326             :     {
    1327           0 :         ImplShowFocus();
    1328           0 :         SetInputContext( InputContext( GetFont() ) );
    1329             :     }
    1330             :     else
    1331             :     {
    1332           0 :         if( mpTabCtrlData->mpListBox->IsReallyVisible() )
    1333           0 :             mpTabCtrlData->mpListBox->GrabFocus();
    1334             :     }
    1335           0 :     Control::GetFocus();
    1336           0 : }
    1337             : 
    1338           0 : void TabControl::LoseFocus()
    1339             : {
    1340           0 :     if( ! mpTabCtrlData->mpListBox )
    1341           0 :         HideFocus();
    1342           0 :     Control::LoseFocus();
    1343           0 : }
    1344             : 
    1345           0 : void TabControl::RequestHelp( const HelpEvent& rHEvt )
    1346             : {
    1347           0 :     sal_uInt16 nItemId = rHEvt.KeyboardActivated() ? mnCurPageId : GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
    1348             : 
    1349           0 :     if ( nItemId )
    1350             :     {
    1351           0 :         if ( rHEvt.GetMode() & HELPMODE_BALLOON )
    1352             :         {
    1353           0 :             OUString aStr = GetHelpText( nItemId );
    1354           0 :             if ( !aStr.isEmpty() )
    1355             :             {
    1356           0 :                 Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) );
    1357           0 :                 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
    1358           0 :                 aItemRect.Left()   = aPt.X();
    1359           0 :                 aItemRect.Top()    = aPt.Y();
    1360           0 :                 aPt = OutputToScreenPixel( aItemRect.BottomRight() );
    1361           0 :                 aItemRect.Right()  = aPt.X();
    1362           0 :                 aItemRect.Bottom() = aPt.Y();
    1363           0 :                 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
    1364           0 :                 return;
    1365           0 :             }
    1366             :         }
    1367           0 :         else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
    1368             :         {
    1369           0 :             OUString aHelpId( OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) );
    1370           0 :             if ( !aHelpId.isEmpty() )
    1371             :             {
    1372             :                 // call Help if existing
    1373           0 :                 Help* pHelp = Application::GetHelp();
    1374           0 :                 if ( pHelp )
    1375           0 :                     pHelp->Start( aHelpId, this );
    1376           0 :                 return;
    1377           0 :             }
    1378             :         }
    1379             : 
    1380             :         // for Quick or Ballon Help, we show the text, if it is cut
    1381           0 :         if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
    1382             :         {
    1383           0 :             ImplTabItem* pItem = ImplGetItem( nItemId );
    1384           0 :             const OUString& rStr = pItem->maText;
    1385           0 :             if ( rStr != pItem->maFormatText )
    1386             :             {
    1387           0 :                 Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) );
    1388           0 :                 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
    1389           0 :                 aItemRect.Left()   = aPt.X();
    1390           0 :                 aItemRect.Top()    = aPt.Y();
    1391           0 :                 aPt = OutputToScreenPixel( aItemRect.BottomRight() );
    1392           0 :                 aItemRect.Right()  = aPt.X();
    1393           0 :                 aItemRect.Bottom() = aPt.Y();
    1394           0 :                 if ( !rStr.isEmpty() )
    1395             :                 {
    1396           0 :                     if ( rHEvt.GetMode() & HELPMODE_BALLOON )
    1397           0 :                         Help::ShowBalloon( this, aItemRect.Center(), aItemRect, rStr );
    1398             :                     else
    1399           0 :                         Help::ShowQuickHelp( this, aItemRect, rStr );
    1400           0 :                     return;
    1401             :                 }
    1402             :             }
    1403             :         }
    1404             : 
    1405           0 :         if ( rHEvt.GetMode() & HELPMODE_QUICK )
    1406             :         {
    1407           0 :             ImplTabItem* pItem = ImplGetItem( nItemId );
    1408           0 :             const OUString& rHelpText = pItem->maHelpText;
    1409             :             // show tooltip if not text but image is set and helptext is available
    1410           0 :             if ( !rHelpText.isEmpty() && pItem->maText.isEmpty() && !!pItem->maTabImage )
    1411             :             {
    1412           0 :                 Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) );
    1413           0 :                 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
    1414           0 :                 aItemRect.Left()   = aPt.X();
    1415           0 :                 aItemRect.Top()    = aPt.Y();
    1416           0 :                 aPt = OutputToScreenPixel( aItemRect.BottomRight() );
    1417           0 :                 aItemRect.Right()  = aPt.X();
    1418           0 :                 aItemRect.Bottom() = aPt.Y();
    1419           0 :                 Help::ShowQuickHelp( this, aItemRect, rHelpText );
    1420           0 :                 return;
    1421             :             }
    1422             :         }
    1423             :     }
    1424             : 
    1425           0 :     Control::RequestHelp( rHEvt );
    1426             : }
    1427             : 
    1428           0 : void TabControl::Command( const CommandEvent& rCEvt )
    1429             : {
    1430           0 :     if( (mpTabCtrlData->mpListBox == NULL) && (rCEvt.GetCommand() == COMMAND_CONTEXTMENU) && (GetPageCount() > 1) )
    1431             :     {
    1432           0 :         Point   aMenuPos;
    1433             :         bool    bMenu;
    1434           0 :         if ( rCEvt.IsMouseEvent() )
    1435             :         {
    1436           0 :             aMenuPos = rCEvt.GetMousePosPixel();
    1437           0 :             bMenu = GetPageId( aMenuPos ) != 0;
    1438             :         }
    1439             :         else
    1440             :         {
    1441           0 :             aMenuPos = ImplGetTabRect( GetPagePos( mnCurPageId ) ).Center();
    1442           0 :             bMenu = true;
    1443             :         }
    1444             : 
    1445           0 :         if ( bMenu )
    1446             :         {
    1447           0 :             PopupMenu aMenu;
    1448           0 :             for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
    1449           0 :                  it != mpTabCtrlData->maItemList.end(); ++it )
    1450             :             {
    1451           0 :                 aMenu.InsertItem( it->mnId, it->maText, MenuItemBits::CHECKABLE );
    1452           0 :                 if ( it->mnId == mnCurPageId )
    1453           0 :                     aMenu.CheckItem( it->mnId );
    1454           0 :                 aMenu.SetHelpId( it->mnId, it->maHelpId );
    1455             :             }
    1456             : 
    1457           0 :             sal_uInt16 nId = aMenu.Execute( this, aMenuPos );
    1458           0 :             if ( nId && (nId != mnCurPageId) )
    1459           0 :                 SelectTabPage( nId );
    1460           0 :             return;
    1461             :         }
    1462             :     }
    1463             : 
    1464           0 :     Control::Command( rCEvt );
    1465             : }
    1466             : 
    1467         112 : void TabControl::StateChanged( StateChangedType nType )
    1468             : {
    1469         112 :     Control::StateChanged( nType );
    1470             : 
    1471         112 :     if ( nType == StateChangedType::INITSHOW )
    1472             :     {
    1473          52 :         ImplPosCurTabPage();
    1474          52 :         if( mpTabCtrlData->mpListBox )
    1475           0 :             Resize();
    1476             :     }
    1477          60 :     else if ( nType == StateChangedType::UPDATEMODE )
    1478             :     {
    1479           0 :         if ( IsUpdateMode() )
    1480           0 :             Invalidate();
    1481             :     }
    1482          60 :     else if ( (nType == StateChangedType::ZOOM)  ||
    1483             :               (nType == StateChangedType::CONTROLFONT) )
    1484             :     {
    1485           0 :         ImplInitSettings( true, false, false );
    1486           0 :         Invalidate();
    1487             :     }
    1488          60 :     else if ( nType == StateChangedType::CONTROLFOREGROUND )
    1489             :     {
    1490           0 :         ImplInitSettings( false, true, false );
    1491           0 :         Invalidate();
    1492             :     }
    1493          60 :     else if ( nType == StateChangedType::CONTROLBACKGROUND )
    1494             :     {
    1495           0 :         ImplInitSettings( false, false, true );
    1496           0 :         Invalidate();
    1497             :     }
    1498         112 : }
    1499             : 
    1500           2 : void TabControl::DataChanged( const DataChangedEvent& rDCEvt )
    1501             : {
    1502           2 :     Control::DataChanged( rDCEvt );
    1503             : 
    1504           6 :     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
    1505           6 :          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
    1506           4 :          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
    1507           2 :           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
    1508             :     {
    1509           2 :         ImplInitSettings( true, true, true );
    1510           2 :         Invalidate();
    1511             :     }
    1512           2 : }
    1513             : 
    1514           0 : Rectangle* TabControl::ImplFindPartRect( const Point& rPt )
    1515             : {
    1516           0 :     ImplTabItem* pFoundItem = NULL;
    1517           0 :     int nFound = 0;
    1518           0 :     for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin();
    1519           0 :          it != mpTabCtrlData->maItemList.end(); ++it )
    1520             :     {
    1521           0 :         if ( it->maRect.IsInside( rPt ) )
    1522             :         {
    1523             :             // assure that only one tab is highlighted at a time
    1524           0 :             nFound++;
    1525           0 :             pFoundItem = &(*it);
    1526             :         }
    1527             :     }
    1528             :     // assure that only one tab is highlighted at a time
    1529           0 :     return nFound == 1 ? &pFoundItem->maRect : NULL;
    1530             : }
    1531             : 
    1532           0 : bool TabControl::PreNotify( NotifyEvent& rNEvt )
    1533             : {
    1534           0 :     const MouseEvent* pMouseEvt = NULL;
    1535             : 
    1536           0 :     if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
    1537             :     {
    1538           0 :         if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
    1539             :         {
    1540             :             // trigger redraw if mouse over state has changed
    1541           0 :             if( IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL) )
    1542             :             {
    1543           0 :                 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
    1544           0 :                 Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() );
    1545           0 :                 if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) )
    1546             :                 {
    1547           0 :                     vcl::Region aClipRgn;
    1548           0 :                     if( pLastRect )
    1549             :                     {
    1550             :                         // allow for slightly bigger tabitems
    1551             :                         // as used by gtk
    1552             :                         // TODO: query for the correct sizes
    1553           0 :                         Rectangle aRect(*pLastRect);
    1554           0 :                         aRect.Left()-=2;
    1555           0 :                         aRect.Right()+=2;
    1556           0 :                         aRect.Top()-=3;
    1557           0 :                         aClipRgn.Union( aRect );
    1558             :                     }
    1559           0 :                     if( pRect )
    1560             :                     {
    1561             :                         // allow for slightly bigger tabitems
    1562             :                         // as used by gtk
    1563             :                         // TODO: query for the correct sizes
    1564           0 :                         Rectangle aRect(*pRect);
    1565           0 :                         aRect.Left()-=2;
    1566           0 :                         aRect.Right()+=2;
    1567           0 :                         aRect.Top()-=3;
    1568           0 :                         aClipRgn.Union( aRect );
    1569             :                     }
    1570           0 :                     if( !aClipRgn.IsEmpty() )
    1571           0 :                         Invalidate( aClipRgn );
    1572             :                 }
    1573             :             }
    1574             :         }
    1575             :     }
    1576             : 
    1577           0 :     return Control::PreNotify(rNEvt);
    1578             : }
    1579             : 
    1580          52 : bool TabControl::Notify( NotifyEvent& rNEvt )
    1581             : {
    1582          52 :     bool nRet = false;
    1583             : 
    1584          52 :     if ( rNEvt.GetType() == EVENT_KEYINPUT )
    1585           0 :         nRet = ImplHandleKeyEvent( *rNEvt.GetKeyEvent() );
    1586             : 
    1587          52 :     return nRet || Control::Notify( rNEvt );
    1588             : }
    1589             : 
    1590         260 : void TabControl::ActivatePage()
    1591             : {
    1592         260 :     maActivateHdl.Call( this );
    1593         260 : }
    1594             : 
    1595           0 : bool TabControl::DeactivatePage()
    1596             : {
    1597           0 :     return !maDeactivateHdl.IsSet() || maDeactivateHdl.Call( this );
    1598             : }
    1599             : 
    1600          52 : void TabControl::SetTabPageSizePixel( const Size& rSize )
    1601             : {
    1602          52 :     ImplFreeLayoutData();
    1603             : 
    1604          52 :     Size aNewSize( rSize );
    1605          52 :     aNewSize.Width() += TAB_OFFSET*2;
    1606             :     Rectangle aRect = ImplGetTabRect( TAB_PAGERECT,
    1607          52 :                                       aNewSize.Width(), aNewSize.Height() );
    1608          52 :     aNewSize.Height() += aRect.Top()+TAB_OFFSET;
    1609          52 :     Window::SetOutputSizePixel( aNewSize );
    1610          52 : }
    1611             : 
    1612           0 : Size TabControl::GetTabPageSizePixel() const
    1613             : {
    1614           0 :     Rectangle aRect = ((TabControl*)this)->ImplGetTabRect( TAB_PAGERECT );
    1615           0 :     return aRect.GetSize();
    1616             : }
    1617             : 
    1618         260 : void TabControl::InsertPage( sal_uInt16 nPageId, const OUString& rText,
    1619             :                              sal_uInt16 nPos )
    1620             : {
    1621             :     DBG_ASSERT( nPageId, "TabControl::InsertPage(): PageId == 0" );
    1622             :     DBG_ASSERT( GetPagePos( nPageId ) == TAB_PAGE_NOTFOUND,
    1623             :                 "TabControl::InsertPage(): PageId already exists" );
    1624             : 
    1625             :     // insert new page item
    1626         260 :     ImplTabItem* pItem = NULL;
    1627         260 :     if( nPos == TAB_APPEND || size_t(nPos) >= mpTabCtrlData->maItemList.size() )
    1628             :     {
    1629         260 :         mpTabCtrlData->maItemList.push_back( ImplTabItem() );
    1630         260 :         pItem = &mpTabCtrlData->maItemList.back();
    1631         260 :         if( mpTabCtrlData->mpListBox )
    1632           0 :             mpTabCtrlData->mpListBox->InsertEntry( rText );
    1633             :     }
    1634             :     else
    1635             :     {
    1636             :         std::vector< ImplTabItem >::iterator new_it =
    1637           0 :             mpTabCtrlData->maItemList.insert( mpTabCtrlData->maItemList.begin() + nPos, ImplTabItem() );
    1638           0 :         pItem = &(*new_it);
    1639           0 :         if( mpTabCtrlData->mpListBox )
    1640           0 :             mpTabCtrlData->mpListBox->InsertEntry( rText, nPos);
    1641             :     }
    1642         260 :     if( mpTabCtrlData->mpListBox )
    1643             :     {
    1644           0 :         if( ! mnCurPageId )
    1645           0 :             mpTabCtrlData->mpListBox->SelectEntryPos( 0 );
    1646           0 :         mpTabCtrlData->mpListBox->SetDropDownLineCount( mpTabCtrlData->mpListBox->GetEntryCount() );
    1647             :     }
    1648             : 
    1649             :     // set current page id
    1650         260 :     if ( !mnCurPageId )
    1651          52 :         mnCurPageId = nPageId;
    1652             : 
    1653             :     // init new page item
    1654         260 :     pItem->mnId             = nPageId;
    1655         260 :     pItem->mpTabPage        = NULL;
    1656         260 :     pItem->maText           = rText;
    1657         260 :     pItem->mbFullVisible    = false;
    1658             : 
    1659         260 :     mbFormat = true;
    1660         260 :     if ( IsUpdateMode() )
    1661         260 :         Invalidate();
    1662             : 
    1663         260 :     ImplFreeLayoutData();
    1664         260 :     if( mpTabCtrlData->mpListBox ) // reposition/resize listbox
    1665           0 :         Resize();
    1666             : 
    1667         260 :     ImplCallEventListeners( VCLEVENT_TABPAGE_INSERTED, reinterpret_cast<void*>(nPageId) );
    1668         260 : }
    1669             : 
    1670           0 : void TabControl::RemovePage( sal_uInt16 nPageId )
    1671             : {
    1672           0 :     sal_uInt16 nPos = GetPagePos( nPageId );
    1673             : 
    1674             :     // does the item exist ?
    1675           0 :     if ( nPos != TAB_PAGE_NOTFOUND )
    1676             :     {
    1677             :         //remove page item
    1678           0 :         std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin() + nPos;
    1679           0 :         bool bIsCurrentPage = (it->mnId == mnCurPageId);
    1680           0 :         mpTabCtrlData->maItemList.erase( it );
    1681           0 :         if( mpTabCtrlData->mpListBox )
    1682             :         {
    1683           0 :             mpTabCtrlData->mpListBox->RemoveEntry( nPos );
    1684           0 :             mpTabCtrlData->mpListBox->SetDropDownLineCount( mpTabCtrlData->mpListBox->GetEntryCount() );
    1685             :         }
    1686             : 
    1687             :         // If current page is removed, than first page gets the current page
    1688           0 :         if ( bIsCurrentPage  )
    1689             :         {
    1690           0 :             mnCurPageId = 0;
    1691             : 
    1692           0 :             if( ! mpTabCtrlData->maItemList.empty() )
    1693             :             {
    1694             :                 // don't do this by simply setting mnCurPageId to pFirstItem->mnId
    1695             :                 // this leaves a lot of stuff (such trivias as _showing_ the new current page) undone
    1696             :                 // instead, call SetCurPageId
    1697             :                 // without this, the next (outside) call to SetCurPageId with the id of the first page
    1698             :                 // will result in doing nothing (as we assume that nothing changed, then), and the page
    1699             :                 // will never be shown.
    1700             :                 // 86875 - 05/11/2001 - frank.schoenheit@germany.sun.com
    1701             : 
    1702           0 :                 SetCurPageId( mpTabCtrlData->maItemList[0].mnId );
    1703             :             }
    1704             :         }
    1705             : 
    1706           0 :         mbFormat = true;
    1707           0 :         if ( IsUpdateMode() )
    1708           0 :             Invalidate();
    1709             : 
    1710           0 :         ImplFreeLayoutData();
    1711             : 
    1712           0 :         ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVED, reinterpret_cast<void*>(nPageId) );
    1713             :     }
    1714           0 : }
    1715             : 
    1716           8 : void TabControl::Clear()
    1717             : {
    1718             :     // clear item list
    1719           8 :     mpTabCtrlData->maItemList.clear();
    1720           8 :     mnCurPageId = 0;
    1721           8 :     if( mpTabCtrlData->mpListBox )
    1722           0 :         mpTabCtrlData->mpListBox->Clear();
    1723             : 
    1724           8 :     ImplFreeLayoutData();
    1725             : 
    1726           8 :     mbFormat = true;
    1727           8 :     if ( IsUpdateMode() )
    1728           8 :         Invalidate();
    1729             : 
    1730           8 :     ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVEDALL );
    1731           8 : }
    1732             : 
    1733           0 : void TabControl::EnablePage( sal_uInt16 i_nPageId, bool i_bEnable )
    1734             : {
    1735           0 :     ImplTabItem* pItem = ImplGetItem( i_nPageId );
    1736             : 
    1737           0 :     if ( pItem && pItem->mbEnabled != i_bEnable )
    1738             :     {
    1739           0 :         pItem->mbEnabled = i_bEnable;
    1740           0 :         mbFormat = true;
    1741           0 :         if( mpTabCtrlData->mpListBox )
    1742           0 :             mpTabCtrlData->mpListBox->SetEntryFlags( GetPagePos( i_nPageId ),
    1743           0 :                                                      i_bEnable ? 0 : (LISTBOX_ENTRY_FLAG_DISABLE_SELECTION | LISTBOX_ENTRY_FLAG_DRAW_DISABLED) );
    1744           0 :         if( pItem->mnId == mnCurPageId )
    1745             :         {
    1746             :              // SetCurPageId will change to an enabled page
    1747           0 :             SetCurPageId( mnCurPageId );
    1748             :         }
    1749           0 :         else if ( IsUpdateMode() )
    1750           0 :             Invalidate();
    1751             :     }
    1752           0 : }
    1753             : 
    1754         872 : sal_uInt16 TabControl::GetPageCount() const
    1755             : {
    1756         872 :     return (sal_uInt16)mpTabCtrlData->maItemList.size();
    1757             : }
    1758             : 
    1759           0 : sal_uInt16 TabControl::GetPageId( sal_uInt16 nPos ) const
    1760             : {
    1761           0 :     if( size_t(nPos) < mpTabCtrlData->maItemList.size() )
    1762           0 :         return mpTabCtrlData->maItemList[ nPos ].mnId;
    1763           0 :     return 0;
    1764             : }
    1765             : 
    1766         777 : sal_uInt16 TabControl::GetPagePos( sal_uInt16 nPageId ) const
    1767             : {
    1768        2331 :     for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
    1769        1554 :          it != mpTabCtrlData->maItemList.end(); ++it )
    1770             :     {
    1771         777 :         if ( it->mnId == nPageId )
    1772         777 :             return (sal_uInt16)(it - mpTabCtrlData->maItemList.begin());
    1773             :     }
    1774             : 
    1775           0 :     return TAB_PAGE_NOTFOUND;
    1776             : }
    1777             : 
    1778           0 : sal_uInt16 TabControl::GetPageId( const Point& rPos ) const
    1779             : {
    1780           0 :     for( size_t i = 0; i < mpTabCtrlData->maItemList.size(); ++i )
    1781             :     {
    1782           0 :         if ( ((TabControl*)this)->ImplGetTabRect( static_cast<sal_uInt16>(i) ).IsInside( rPos ) )
    1783           0 :             return mpTabCtrlData->maItemList[ i ].mnId;
    1784             :     }
    1785             : 
    1786           0 :     return 0;
    1787             : }
    1788             : 
    1789           0 : sal_uInt16 TabControl::GetPageId( const TabPage& rPage ) const
    1790             : {
    1791           0 :     for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
    1792           0 :          it != mpTabCtrlData->maItemList.end(); ++it )
    1793             :     {
    1794           0 :         if ( it->mpTabPage == &rPage )
    1795           0 :             return it->mnId;
    1796             :     }
    1797             : 
    1798           0 :     return 0;
    1799             : }
    1800             : 
    1801           0 : sal_uInt16 TabControl::GetPageId( const OString& rName ) const
    1802             : {
    1803           0 :     for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
    1804           0 :          it != mpTabCtrlData->maItemList.end(); ++it )
    1805             :     {
    1806           0 :         if ( it->maTabName == rName )
    1807           0 :             return it->mnId;
    1808             :     }
    1809             : 
    1810           0 :     return 0;
    1811             : }
    1812             : 
    1813         260 : void TabControl::SetCurPageId( sal_uInt16 nPageId )
    1814             : {
    1815         260 :     sal_uInt16 nPos = GetPagePos( nPageId );
    1816         780 :     while( nPos != TAB_PAGE_NOTFOUND &&
    1817         260 :            ! mpTabCtrlData->maItemList[nPos].mbEnabled )
    1818             :     {
    1819           0 :         nPos++;
    1820           0 :         if( size_t(nPos) >= mpTabCtrlData->maItemList.size() )
    1821           0 :             nPos = 0;
    1822           0 :         if( mpTabCtrlData->maItemList[nPos].mnId == nPageId )
    1823           0 :             break;
    1824             :     }
    1825             : 
    1826         260 :     if( nPos != TAB_PAGE_NOTFOUND )
    1827             :     {
    1828         260 :         nPageId = mpTabCtrlData->maItemList[nPos].mnId;
    1829         260 :         if ( nPageId == mnCurPageId )
    1830             :         {
    1831         260 :             if ( mnActPageId )
    1832           0 :                 mnActPageId = nPageId;
    1833         520 :             return;
    1834             :         }
    1835             : 
    1836           0 :         if ( mnActPageId )
    1837           0 :             mnActPageId = nPageId;
    1838             :         else
    1839             :         {
    1840           0 :             mbFormat = true;
    1841           0 :             sal_uInt16 nOldId = mnCurPageId;
    1842           0 :             mnCurPageId = nPageId;
    1843           0 :             ImplChangeTabPage( nPageId, nOldId );
    1844             :         }
    1845             :     }
    1846             : }
    1847             : 
    1848         832 : sal_uInt16 TabControl::GetCurPageId() const
    1849             : {
    1850         832 :     if ( mnActPageId )
    1851           0 :         return mnActPageId;
    1852             :     else
    1853         832 :         return mnCurPageId;
    1854             : }
    1855             : 
    1856           0 : void TabControl::SelectTabPage( sal_uInt16 nPageId )
    1857             : {
    1858           0 :     if ( nPageId && (nPageId != mnCurPageId) )
    1859             :     {
    1860           0 :         ImplFreeLayoutData();
    1861             : 
    1862           0 :         ImplCallEventListeners( VCLEVENT_TABPAGE_DEACTIVATE, reinterpret_cast<void*>(mnCurPageId) );
    1863           0 :         if ( DeactivatePage() )
    1864             :         {
    1865           0 :             mnActPageId = nPageId;
    1866           0 :             ActivatePage();
    1867             :             // Page could have been switched by the Activate handler
    1868           0 :             nPageId = mnActPageId;
    1869           0 :             mnActPageId = 0;
    1870           0 :             SetCurPageId( nPageId );
    1871           0 :             if( mpTabCtrlData->mpListBox )
    1872           0 :                 mpTabCtrlData->mpListBox->SelectEntryPos( GetPagePos( nPageId ) );
    1873           0 :             ImplCallEventListeners( VCLEVENT_TABPAGE_ACTIVATE, reinterpret_cast<void*>(nPageId) );
    1874             :         }
    1875             :     }
    1876           0 : }
    1877             : 
    1878        1040 : void TabControl::SetTabPage( sal_uInt16 nPageId, TabPage* pTabPage )
    1879             : {
    1880        1040 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1881             : 
    1882        1040 :     if ( pItem && (pItem->mpTabPage != pTabPage) )
    1883             :     {
    1884         468 :         if ( pTabPage )
    1885             :         {
    1886             :             DBG_ASSERT( !pTabPage->IsVisible() || isLayoutEnabled(pTabPage),
    1887             :                 "TabControl::SetTabPage() - Non-Layout Enabled Page is visible" );
    1888             : 
    1889         260 :             if ( IsDefaultSize() )
    1890          52 :                 SetTabPageSizePixel( pTabPage->GetSizePixel() );
    1891             : 
    1892             :             // only set here, so that Resize does not reposition TabPage
    1893         260 :             pItem->mpTabPage = pTabPage;
    1894         260 :             queue_resize();
    1895         260 :             if ( pItem->mnId == mnCurPageId )
    1896          52 :                 ImplChangeTabPage( pItem->mnId, 0 );
    1897             :         }
    1898             :         else
    1899             :         {
    1900         208 :             pItem->mpTabPage = NULL;
    1901         208 :             queue_resize();
    1902             :         }
    1903             :     }
    1904        1040 : }
    1905             : 
    1906         468 : TabPage* TabControl::GetTabPage( sal_uInt16 nPageId ) const
    1907             : {
    1908         468 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1909             : 
    1910         468 :     if ( pItem )
    1911         468 :         return pItem->mpTabPage;
    1912             :     else
    1913           0 :         return NULL;
    1914             : }
    1915             : 
    1916         780 : void TabControl::SetPageText( sal_uInt16 nPageId, const OUString& rText )
    1917             : {
    1918         780 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1919             : 
    1920         780 :     if ( pItem && pItem->maText != rText )
    1921             :     {
    1922           0 :         pItem->maText = rText;
    1923           0 :         mbFormat = true;
    1924           0 :         if( mpTabCtrlData->mpListBox )
    1925             :         {
    1926           0 :             sal_uInt16 nPos = GetPagePos( nPageId );
    1927           0 :             mpTabCtrlData->mpListBox->RemoveEntry( nPos );
    1928           0 :             mpTabCtrlData->mpListBox->InsertEntry( rText, nPos );
    1929             :         }
    1930           0 :         if ( IsUpdateMode() )
    1931           0 :             Invalidate();
    1932           0 :         ImplFreeLayoutData();
    1933           0 :         ImplCallEventListeners( VCLEVENT_TABPAGE_PAGETEXTCHANGED, reinterpret_cast<void*>(nPageId) );
    1934             :     }
    1935         780 : }
    1936             : 
    1937           0 : OUString TabControl::GetPageText( sal_uInt16 nPageId ) const
    1938             : {
    1939           0 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1940             : 
    1941             :     assert( pItem );
    1942             : 
    1943           0 :     return pItem->maText;
    1944             : }
    1945             : 
    1946         780 : void TabControl::SetHelpText( sal_uInt16 nPageId, const OUString& rText )
    1947             : {
    1948         780 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1949             : 
    1950             :     assert( pItem );
    1951             : 
    1952         780 :     pItem->maHelpText = rText;
    1953         780 : }
    1954             : 
    1955           0 : const OUString& TabControl::GetHelpText( sal_uInt16 nPageId ) const
    1956             : {
    1957           0 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1958             : 
    1959             :     assert( pItem );
    1960             : 
    1961           0 :     if ( pItem->maHelpText.isEmpty() && !pItem->maHelpId.isEmpty() )
    1962             :     {
    1963           0 :         Help* pHelp = Application::GetHelp();
    1964           0 :         if ( pHelp )
    1965           0 :             pItem->maHelpText = pHelp->GetHelpText( OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
    1966             :     }
    1967           0 :     return pItem->maHelpText;
    1968             : }
    1969             : 
    1970           0 : void TabControl::SetHelpId( sal_uInt16 nPageId, const OString& rId ) const
    1971             : {
    1972           0 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1973             : 
    1974           0 :     if ( pItem )
    1975           0 :         pItem->maHelpId = rId;
    1976           0 : }
    1977             : 
    1978           0 : OString TabControl::GetHelpId( sal_uInt16 nPageId ) const
    1979             : {
    1980           0 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1981             : 
    1982           0 :     if (pItem)
    1983           0 :         return pItem->maHelpId;
    1984             : 
    1985           0 :     return OString();
    1986             : }
    1987             : 
    1988           0 : void TabControl::SetPageName( sal_uInt16 nPageId, const OString& rName ) const
    1989             : {
    1990           0 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1991             : 
    1992           0 :     if ( pItem )
    1993           0 :         pItem->maTabName = rName;
    1994           0 : }
    1995             : 
    1996           0 : OString TabControl::GetPageName( sal_uInt16 nPageId ) const
    1997             : {
    1998           0 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    1999             : 
    2000           0 :     if (pItem)
    2001           0 :         return pItem->maTabName;
    2002             : 
    2003           0 :     return OString();
    2004             : }
    2005             : 
    2006           0 : void TabControl::SetPageImage( sal_uInt16 i_nPageId, const Image& i_rImage )
    2007             : {
    2008           0 :     ImplTabItem* pItem = ImplGetItem( i_nPageId );
    2009             : 
    2010           0 :     if ( pItem )
    2011             :     {
    2012           0 :         pItem->maTabImage = i_rImage;
    2013           0 :         mbFormat = true;
    2014           0 :         if ( IsUpdateMode() )
    2015           0 :             Invalidate();
    2016             :     }
    2017           0 : }
    2018             : 
    2019           0 : Rectangle TabControl::GetCharacterBounds( sal_uInt16 nPageId, long nIndex ) const
    2020             : {
    2021           0 :     Rectangle aRet;
    2022             : 
    2023           0 :     if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() )
    2024           0 :         FillLayoutData();
    2025             : 
    2026           0 :     if( HasLayoutData() )
    2027             :     {
    2028           0 :         boost::unordered_map< int, int >::const_iterator it = mpTabCtrlData->maLayoutPageIdToLine.find( (int)nPageId );
    2029           0 :         if( it != mpTabCtrlData->maLayoutPageIdToLine.end() )
    2030             :         {
    2031           0 :             Pair aPair = mpControlData->mpLayoutData->GetLineStartEnd( it->second );
    2032           0 :             if( (aPair.B() - aPair.A()) >= nIndex )
    2033           0 :                 aRet = mpControlData->mpLayoutData->GetCharacterBounds( aPair.A() + nIndex );
    2034             :         }
    2035             :     }
    2036             : 
    2037           0 :     return aRet;
    2038             : }
    2039             : 
    2040           0 : long TabControl::GetIndexForPoint( const Point& rPoint, sal_uInt16& rPageId ) const
    2041             : {
    2042           0 :     long nRet = -1;
    2043             : 
    2044           0 :     if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() )
    2045           0 :         FillLayoutData();
    2046             : 
    2047           0 :     if( HasLayoutData() )
    2048             :     {
    2049           0 :         int nIndex = mpControlData->mpLayoutData->GetIndexForPoint( rPoint );
    2050           0 :         if( nIndex != -1 )
    2051             :         {
    2052             :             // what line (->pageid) is this index in ?
    2053           0 :             int nLines = mpControlData->mpLayoutData->GetLineCount();
    2054           0 :             int nLine = -1;
    2055           0 :             while( ++nLine < nLines )
    2056             :             {
    2057           0 :                 Pair aPair = mpControlData->mpLayoutData->GetLineStartEnd( nLine );
    2058           0 :                 if( aPair.A() <= nIndex && aPair.B() >= nIndex )
    2059             :                 {
    2060           0 :                     nRet = nIndex - aPair.A();
    2061           0 :                     rPageId = (sal_uInt16)mpTabCtrlData->maLayoutLineToPageId[ nLine ];
    2062           0 :                     break;
    2063             :                 }
    2064             :             }
    2065             :         }
    2066             :     }
    2067             : 
    2068           0 :     return nRet;
    2069             : }
    2070             : 
    2071           0 : void TabControl::FillLayoutData() const
    2072             : {
    2073           0 :     mpTabCtrlData->maLayoutLineToPageId.clear();
    2074           0 :     mpTabCtrlData->maLayoutPageIdToLine.clear();
    2075           0 :     const_cast<TabControl*>(this)->ImplPaint( Rectangle(), true );
    2076           0 : }
    2077             : 
    2078           0 : Rectangle TabControl::GetTabBounds( sal_uInt16 nPageId ) const
    2079             : {
    2080           0 :     Rectangle aRet;
    2081             : 
    2082           0 :     ImplTabItem* pItem = ImplGetItem( nPageId );
    2083           0 :     if(pItem)
    2084           0 :         aRet = pItem->maRect;
    2085             : 
    2086           0 :     return aRet;
    2087             : }
    2088             : 
    2089          52 : void TabControl::SetItemsOffset( const Point& rOffs )
    2090             : {
    2091          52 :     if( mpTabCtrlData )
    2092          52 :         mpTabCtrlData->maItemsOffset = rOffs;
    2093          52 : }
    2094             : 
    2095        1146 : Point TabControl::GetItemsOffset() const
    2096             : {
    2097        1146 :     if( mpTabCtrlData )
    2098        1146 :         return mpTabCtrlData->maItemsOffset;
    2099             :     else
    2100           0 :         return Point();
    2101             : }
    2102             : 
    2103           0 : Size TabControl::calculateRequisition() const
    2104             : {
    2105           0 :     Size aOptimalPageSize(0, 0);
    2106             : 
    2107           0 :     sal_uInt16 nOrigPageId = GetCurPageId();
    2108           0 :     for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
    2109           0 :          it != mpTabCtrlData->maItemList.end(); ++it )
    2110             :     {
    2111           0 :         const TabPage *pPage = it->mpTabPage;
    2112             :         //it's a real nuisance if the page is not inserted yet :-(
    2113             :         //We need to force all tabs to exist to get overall optimal size for dialog
    2114           0 :         if (!pPage)
    2115             :         {
    2116           0 :             TabControl *pThis = const_cast<TabControl*>(this);
    2117           0 :             pThis->SetCurPageId(it->mnId);
    2118           0 :             pThis->ActivatePage();
    2119           0 :             pPage = it->mpTabPage;
    2120             :         }
    2121             : 
    2122           0 :         if (!pPage)
    2123           0 :             continue;
    2124             : 
    2125           0 :         Size aPageSize(VclContainer::getLayoutRequisition(*pPage));
    2126             : 
    2127           0 :         if (aPageSize.Width() > aOptimalPageSize.Width())
    2128           0 :             aOptimalPageSize.Width() = aPageSize.Width();
    2129           0 :         if (aPageSize.Height() > aOptimalPageSize.Height())
    2130           0 :             aOptimalPageSize.Height() = aPageSize.Height();
    2131             :     }
    2132             : 
    2133             :     //fdo#61940 If we were forced to activate pages in order to on-demand
    2134             :     //create them to get their optimal size, then switch back to the original
    2135             :     //page and re-activate it
    2136           0 :     if (nOrigPageId != GetCurPageId())
    2137             :     {
    2138           0 :         TabControl *pThis = const_cast<TabControl*>(this);
    2139           0 :         pThis->SetCurPageId(nOrigPageId);
    2140           0 :         pThis->ActivatePage();
    2141             :     }
    2142             : 
    2143           0 :     long nTabLabelsBottom = 0, nTabLabelsRight = 0;
    2144           0 :     for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin();
    2145           0 :          it != mpTabCtrlData->maItemList.end(); ++it )
    2146             :     {
    2147           0 :         TabControl* pThis = const_cast<TabControl*>(this);
    2148             : 
    2149           0 :         sal_uInt16 nPos = it - mpTabCtrlData->maItemList.begin();
    2150           0 :         Rectangle aTabRect = pThis->ImplGetTabRect(nPos, aOptimalPageSize.Width(), LONG_MAX);
    2151           0 :         if (aTabRect.Bottom() > nTabLabelsBottom)
    2152           0 :             nTabLabelsBottom = aTabRect.Bottom();
    2153           0 :         if (aTabRect.Right() > nTabLabelsRight)
    2154           0 :             nTabLabelsRight = aTabRect.Right();
    2155             :     }
    2156             : 
    2157           0 :     Size aOptimalSize(aOptimalPageSize);
    2158           0 :     aOptimalSize.Height() += nTabLabelsBottom;
    2159           0 :     aOptimalSize.Width() = std::max(nTabLabelsRight, aOptimalSize.Width());
    2160             : 
    2161           0 :     aOptimalSize.Width() += TAB_OFFSET * 2;
    2162           0 :     aOptimalSize.Height() += TAB_OFFSET * 2;
    2163             : 
    2164           0 :     return aOptimalSize;
    2165             : }
    2166             : 
    2167           0 : Size TabControl::GetOptimalSize() const
    2168             : {
    2169           0 :     return calculateRequisition();
    2170             : }
    2171             : 
    2172         628 : void TabControl::queue_resize(StateChangedType eReason)
    2173             : {
    2174         628 :     markLayoutDirty();
    2175         628 :     Window::queue_resize(eReason);
    2176        1861 : }
    2177             : 
    2178             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10