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

Generated by: LCOV version 1.10