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

Generated by: LCOV version 1.11