| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include "tools/debug.hxx" |
| #include "tools/rc.h" |
| |
| #include "vcl/svapp.hxx" |
| #include "vcl/help.hxx" |
| #include "vcl/event.hxx" |
| #include "vcl/menu.hxx" |
| #include "vcl/button.hxx" |
| #include "vcl/tabpage.hxx" |
| #include "vcl/tabctrl.hxx" |
| #include "vcl/controllayout.hxx" |
| #include "vcl/sound.hxx" |
| #include "vcl/lstbox.hxx" |
| |
| #include "controldata.hxx" |
| #include "svdata.hxx" |
| #include "window.h" |
| |
| #include <hash_map> |
| #include <vector> |
| |
| // ======================================================================= |
| |
| struct ImplTabItem |
| { |
| sal_uInt16 mnId; |
| sal_uInt16 mnTabPageResId; |
| TabPage* mpTabPage; |
| String maText; |
| String maFormatText; |
| String maHelpText; |
| rtl::OString maHelpId; |
| Rectangle maRect; |
| sal_uInt16 mnLine; |
| bool mbFullVisible; |
| bool mbEnabled; |
| Image maTabImage; |
| |
| ImplTabItem() |
| : mnId( 0 ), mnTabPageResId( 0 ), mpTabPage( NULL ), |
| mnLine( 0 ), mbFullVisible( sal_False ), mbEnabled( true ) |
| {} |
| }; |
| |
| // ----------------------------------------------------------------------- |
| |
| struct ImplTabCtrlData |
| { |
| std::hash_map< int, int > maLayoutPageIdToLine; |
| std::hash_map< int, int > maLayoutLineToPageId; |
| std::vector< Rectangle > maTabRectangles; |
| Point maItemsOffset; // offset of the tabitems |
| std::vector< ImplTabItem > maItemList; |
| ListBox* mpListBox; |
| Size maMinSize; |
| }; |
| |
| // ----------------------------------------------------------------------- |
| |
| #define TAB_OFFSET 3 |
| #define TAB_TABOFFSET_X 3 |
| #define TAB_TABOFFSET_Y 3 |
| #define TAB_EXTRASPACE_X 6 |
| #define TAB_BORDER_LEFT 1 |
| #define TAB_BORDER_TOP 1 |
| #define TAB_BORDER_RIGHT 2 |
| #define TAB_BORDER_BOTTOM 2 |
| |
| // Fuer die Ermittlung von den Tab-Positionen |
| #define TAB_PAGERECT 0xFFFF |
| |
| // ======================================================================= |
| |
| void TabControl::ImplInit( Window* pParent, WinBits nStyle ) |
| { |
| if ( !(nStyle & WB_NOTABSTOP) ) |
| nStyle |= WB_TABSTOP; |
| if ( !(nStyle & WB_NOGROUP) ) |
| nStyle |= WB_GROUP; |
| if ( !(nStyle & WB_NODIALOGCONTROL) ) |
| nStyle |= WB_DIALOGCONTROL; |
| |
| Control::ImplInit( pParent, nStyle, NULL ); |
| |
| mnLastWidth = 0; |
| mnLastHeight = 0; |
| mnBtnSize = 0; |
| mnMaxPageWidth = 0; |
| mnActPageId = 0; |
| mnCurPageId = 0; |
| mbFormat = sal_True; |
| mbRestoreHelpId = sal_False; |
| mbRestoreUnqId = sal_False; |
| mbSmallInvalidate = sal_False; |
| mbExtraSpace = sal_False; |
| mpTabCtrlData = new ImplTabCtrlData; |
| mpTabCtrlData->mpListBox = NULL; |
| |
| |
| ImplInitSettings( sal_True, sal_True, sal_True ); |
| |
| if( (nStyle & WB_DROPDOWN) ) |
| { |
| mpTabCtrlData->mpListBox = new ListBox( this, WB_DROPDOWN ); |
| mpTabCtrlData->mpListBox->SetPosSizePixel( Point( 0, 0 ), Size( 200, 20 ) ); |
| mpTabCtrlData->mpListBox->SetSelectHdl( LINK( this, TabControl, ImplListBoxSelectHdl ) ); |
| mpTabCtrlData->mpListBox->Show(); |
| } |
| |
| // if the tabcontrol is drawn (ie filled) by a native widget, make sure all contols will have transparent background |
| // otherwise they will paint with a wrong background |
| if( IsNativeControlSupported(CTRL_TAB_PANE, PART_ENTIRE_CONTROL) ) |
| EnableChildTransparentMode( sal_True ); |
| |
| if ( pParent->IsDialog() ) |
| pParent->AddChildEventListener( LINK( this, TabControl, ImplWindowEventListener ) ); |
| } |
| |
| // ----------------------------------------------------------------- |
| |
| const Font& TabControl::GetCanonicalFont( const StyleSettings& _rStyle ) const |
| { |
| return _rStyle.GetAppFont(); |
| } |
| |
| // ----------------------------------------------------------------- |
| const Color& TabControl::GetCanonicalTextColor( const StyleSettings& _rStyle ) const |
| { |
| return _rStyle.GetButtonTextColor(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::ImplInitSettings( sal_Bool bFont, |
| sal_Bool bForeground, sal_Bool bBackground ) |
| { |
| Control::ImplInitSettings( bFont, bForeground ); |
| |
| if ( bBackground ) |
| { |
| Window* pParent = GetParent(); |
| if ( !IsControlBackground() && |
| (pParent->IsChildTransparentModeEnabled() |
| || IsNativeControlSupported(CTRL_TAB_PANE, PART_ENTIRE_CONTROL) |
| || IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL) ) ) |
| |
| { |
| // set transparent mode for NWF tabcontrols to have |
| // the background always cleared properly |
| EnableChildTransparentMode( sal_True ); |
| SetParentClipMode( PARENTCLIPMODE_NOCLIP ); |
| SetPaintTransparent( sal_True ); |
| SetBackground(); |
| ImplGetWindowImpl()->mbUseNativeFocus = ImplGetSVData()->maNWFData.mbNoFocusRects; |
| } |
| else |
| { |
| EnableChildTransparentMode( sal_False ); |
| SetParentClipMode( 0 ); |
| SetPaintTransparent( sal_False ); |
| |
| if ( IsControlBackground() ) |
| SetBackground( GetControlBackground() ); |
| else |
| SetBackground( pParent->GetBackground() ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::ImplFreeLayoutData() |
| { |
| if( HasLayoutData() ) |
| { |
| ImplClearLayoutData(); |
| mpTabCtrlData->maLayoutPageIdToLine.clear(); |
| mpTabCtrlData->maLayoutLineToPageId.clear(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| TabControl::TabControl( Window* pParent, WinBits nStyle ) : |
| Control( WINDOW_TABCONTROL ) |
| { |
| ImplInit( pParent, nStyle ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| TabControl::TabControl( Window* pParent, const ResId& rResId ) : |
| Control( WINDOW_TABCONTROL ) |
| { |
| rResId.SetRT( RSC_TABCONTROL ); |
| WinBits nStyle = ImplInitRes( rResId ); |
| ImplInit( pParent, nStyle ); |
| ImplLoadRes( rResId ); |
| |
| if ( !(nStyle & WB_HIDE) ) |
| Show(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::ImplLoadRes( const ResId& rResId ) |
| { |
| Control::ImplLoadRes( rResId ); |
| |
| sal_uLong nObjMask = ReadLongRes(); |
| |
| if ( nObjMask & RSC_TABCONTROL_ITEMLIST ) |
| { |
| sal_uLong nEle = ReadLongRes(); |
| |
| // Item hinzufuegen |
| for( sal_uLong i = 0; i < nEle; i++ ) |
| { |
| InsertPage( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); |
| IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| TabControl::~TabControl() |
| { |
| if ( GetParent()->IsDialog() ) |
| GetParent()->RemoveChildEventListener( LINK( this, TabControl, ImplWindowEventListener ) ); |
| |
| ImplFreeLayoutData(); |
| |
| // TabCtrl-Daten loeschen |
| if ( mpTabCtrlData ) |
| { |
| if( mpTabCtrlData->mpListBox ) |
| delete mpTabCtrlData->mpListBox; |
| delete mpTabCtrlData; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| ImplTabItem* TabControl::ImplGetItem( sal_uInt16 nId ) const |
| { |
| for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| if( it->mnId == nId ) |
| return &(*it); |
| } |
| |
| return NULL; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size TabControl::ImplGetItemSize( ImplTabItem* pItem, long nMaxWidth ) |
| { |
| pItem->maFormatText = pItem->maText; |
| Size aSize( GetCtrlTextWidth( pItem->maFormatText ), GetTextHeight() ); |
| Size aImageSize( 0, 0 ); |
| if( !!pItem->maTabImage ) |
| { |
| aImageSize = pItem->maTabImage.GetSizePixel(); |
| if( pItem->maFormatText.Len() ) |
| aImageSize.Width() += GetTextHeight()/4; |
| } |
| aSize.Width() += aImageSize.Width(); |
| if( aImageSize.Height() > aSize.Height() ) |
| aSize.Height() = aImageSize.Height(); |
| |
| aSize.Width() += TAB_TABOFFSET_X*2; |
| aSize.Height() += TAB_TABOFFSET_Y*2; |
| |
| Rectangle aCtrlRegion( Point( 0, 0 ), aSize ); |
| Rectangle aBoundingRgn, aContentRgn; |
| const ImplControlValue aControlValue; |
| if(GetNativeControlRegion( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, aCtrlRegion, |
| CTRL_STATE_ENABLED, aControlValue, rtl::OUString(), |
| aBoundingRgn, aContentRgn ) ) |
| { |
| return aContentRgn.GetSize(); |
| } |
| |
| // For systems without synthetic bold support |
| if ( mbExtraSpace ) |
| aSize.Width() += TAB_EXTRASPACE_X; |
| // For languages with short names (e.g. Chinese), because the space is |
| // normally only one pixel per char |
| else if ( pItem->maFormatText.Len() < TAB_EXTRASPACE_X ) |
| aSize.Width() += TAB_EXTRASPACE_X-pItem->maFormatText.Len(); |
| |
| // Evt. den Text kuerzen |
| if ( aSize.Width()+4 >= nMaxWidth ) |
| { |
| XubString aAppendStr( RTL_CONSTASCII_USTRINGPARAM( "..." ) ); |
| pItem->maFormatText += aAppendStr; |
| do |
| { |
| pItem->maFormatText.Erase( pItem->maFormatText.Len()-aAppendStr.Len()-1, 1 ); |
| aSize.Width() = GetCtrlTextWidth( pItem->maFormatText ); |
| aSize.Width() += aImageSize.Width(); |
| aSize.Width() += TAB_TABOFFSET_X*2; |
| } |
| while ( (aSize.Width()+4 >= nMaxWidth) && (pItem->maFormatText.Len() > aAppendStr.Len()) ); |
| if ( aSize.Width()+4 >= nMaxWidth ) |
| { |
| pItem->maFormatText.Assign( '.' ); |
| aSize.Width() = 1; |
| } |
| } |
| |
| if( pItem->maFormatText.Len() == 0 ) |
| { |
| if( aSize.Height() < aImageSize.Height()+4 ) //leave space for focus rect |
| aSize.Height() = aImageSize.Height()+4; |
| } |
| |
| return aSize; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle TabControl::ImplGetTabRect( sal_uInt16 nItemPos, long nWidth, long nHeight ) |
| { |
| Size aWinSize = Control::GetOutputSizePixel(); |
| if ( nWidth < 0 ) |
| nWidth = aWinSize.Width(); |
| if ( nHeight < 0 ) |
| nHeight = aWinSize.Height(); |
| |
| if ( mpTabCtrlData->maItemList.empty() ) |
| { |
| long nW = nWidth-TAB_OFFSET*2; |
| long nH = nHeight-TAB_OFFSET*2; |
| return (nW > 0 && nH > 0) |
| ? Rectangle( Point( TAB_OFFSET, TAB_OFFSET ), Size( nW, nH ) ) |
| : Rectangle(); |
| } |
| |
| if ( nItemPos == TAB_PAGERECT ) |
| { |
| sal_uInt16 nLastPos; |
| if ( mnCurPageId ) |
| nLastPos = GetPagePos( mnCurPageId ); |
| else |
| nLastPos = 0; |
| |
| Rectangle aRect = ImplGetTabRect( nLastPos, nWidth, nHeight ); |
| long nW = nWidth-TAB_OFFSET*2; |
| long nH = nHeight-aRect.Bottom()-TAB_OFFSET*2; |
| aRect = (nW > 0 && nH > 0) |
| ? Rectangle( Point( TAB_OFFSET, aRect.Bottom()+TAB_OFFSET ), Size( nW, nH ) ) |
| : Rectangle(); |
| return aRect; |
| } |
| |
| nWidth -= 1; |
| |
| if ( (nWidth <= 0) || (nHeight <= 0) ) |
| return Rectangle(); |
| |
| if ( mbFormat || (mnLastWidth != nWidth) || (mnLastHeight != nHeight) ) |
| { |
| Font aFont( GetFont() ); |
| Font aLightFont = aFont; |
| aFont.SetTransparent( sal_True ); |
| aFont.SetWeight( (!ImplGetSVData()->maNWFData.mbNoBoldTabFocus) ? WEIGHT_BOLD : WEIGHT_LIGHT ); |
| aLightFont.SetTransparent( sal_True ); |
| aLightFont.SetWeight( WEIGHT_LIGHT ); |
| |
| // If Bold and none Bold strings have the same width, we |
| // add in the calcultion extra space, so that the tabs |
| // looks better. The could be the case on systems without |
| // an bold UI font and without synthetic bold support |
| XubString aTestStr( RTL_CONSTASCII_USTRINGPARAM( "Abc." ) ); |
| SetFont( aLightFont ); |
| long nTextWidth1 = GetTextWidth( aTestStr ); |
| SetFont( aFont ); |
| long nTextWidth2 = GetTextWidth( aTestStr ); |
| mbExtraSpace = (nTextWidth1 == nTextWidth2); |
| |
| Size aSize; |
| const long nOffsetX = 2 + GetItemsOffset().X(); |
| const long nOffsetY = 2 + GetItemsOffset().Y(); |
| long nX = nOffsetX; |
| long nY = nOffsetY; |
| long nMaxWidth = nWidth; |
| sal_uInt16 nPos = 0; |
| |
| if ( (mnMaxPageWidth > 0) && (mnMaxPageWidth < nMaxWidth) ) |
| nMaxWidth = mnMaxPageWidth; |
| nMaxWidth -= GetItemsOffset().X(); |
| |
| sal_uInt16 nLines = 0; |
| sal_uInt16 nCurLine = 0; |
| long nLineWidthAry[100]; |
| sal_uInt16 nLinePosAry[101]; |
| |
| nLineWidthAry[0] = 0; |
| nLinePosAry[0] = 0; |
| for( std::vector<ImplTabItem>::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| aSize = ImplGetItemSize( &(*it), nMaxWidth ); |
| |
| if ( ((nX+aSize.Width()) > nWidth - 2) && (nWidth > 2+nOffsetX) ) |
| { |
| if ( nLines == 99 ) |
| break; |
| |
| nX = nOffsetX; |
| nY += aSize.Height(); |
| nLines++; |
| nLineWidthAry[nLines] = 0; |
| nLinePosAry[nLines] = nPos; |
| } |
| |
| Rectangle aNewRect( Point( nX, nY ), aSize ); |
| if ( mbSmallInvalidate && (it->maRect != aNewRect) ) |
| mbSmallInvalidate = sal_False; |
| it->maRect = aNewRect; |
| it->mnLine = nLines; |
| it->mbFullVisible = sal_True; |
| |
| nLineWidthAry[nLines] += aSize.Width(); |
| nX += aSize.Width(); |
| |
| if ( it->mnId == mnCurPageId ) |
| nCurLine = nLines; |
| |
| nPos++; |
| } |
| |
| if ( nLines && !mpTabCtrlData->maItemList.empty() ) |
| { |
| long nDX = 0; |
| long nModDX = 0; |
| long nIDX = 0; |
| sal_uInt16 i; |
| sal_uInt16 n; |
| long nLineHeightAry[100]; |
| long nIH = mpTabCtrlData->maItemList[0].maRect.Bottom()-2; |
| |
| i = 0; |
| while ( i < nLines+1 ) |
| { |
| if ( i <= nCurLine ) |
| nLineHeightAry[i] = nIH*(nLines-(nCurLine-i)) + GetItemsOffset().Y(); |
| else |
| nLineHeightAry[i] = nIH*(i-nCurLine-1) + GetItemsOffset().Y(); |
| i++; |
| } |
| |
| i = 0; |
| n = 0; |
| nLinePosAry[nLines+1] = (sal_uInt16)mpTabCtrlData->maItemList.size(); |
| for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| if ( i == nLinePosAry[n] ) |
| { |
| if ( n == nLines+1 ) |
| break; |
| |
| nIDX = 0; |
| if( nLinePosAry[n+1]-i > 0 ) |
| { |
| nDX = (nWidth-nOffsetX-nLineWidthAry[n]) / (nLinePosAry[n+1]-i); |
| nModDX = (nWidth-nOffsetX-nLineWidthAry[n]) % (nLinePosAry[n+1]-i); |
| } |
| else |
| { |
| // FIXME: this is a bad case of tabctrl way too small |
| nDX = 0; |
| nModDX = 0; |
| } |
| n++; |
| } |
| |
| it->maRect.Left() += nIDX; |
| it->maRect.Right() += nIDX+nDX; |
| it->maRect.Top() = nLineHeightAry[n-1]; |
| it->maRect.Bottom() = nLineHeightAry[n-1]+nIH; |
| nIDX += nDX; |
| |
| if ( nModDX ) |
| { |
| nIDX++; |
| it->maRect.Right()++; |
| nModDX--; |
| } |
| |
| i++; |
| } |
| } |
| else |
| {//only one line |
| if(ImplGetSVData()->maNWFData.mbCenteredTabs) |
| { |
| int nRightSpace=nMaxWidth;//space left on the right by the tabs |
| for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| nRightSpace-=it->maRect.Right()-it->maRect.Left(); |
| } |
| for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| it->maRect.Left()+=(int) (nRightSpace/2); |
| it->maRect.Right()+=(int) (nRightSpace/2); |
| } |
| } |
| } |
| |
| mnLastWidth = nWidth; |
| mnLastHeight = nHeight; |
| mbFormat = sal_False; |
| } |
| |
| return size_t(nItemPos) < mpTabCtrlData->maItemList.size() ? mpTabCtrlData->maItemList[nItemPos].maRect : Rectangle(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::ImplChangeTabPage( sal_uInt16 nId, sal_uInt16 nOldId ) |
| { |
| ImplFreeLayoutData(); |
| |
| ImplTabItem* pOldItem = ImplGetItem( nOldId ); |
| ImplTabItem* pItem = ImplGetItem( nId ); |
| TabPage* pOldPage = (pOldItem) ? pOldItem->mpTabPage : NULL; |
| TabPage* pPage = (pItem) ? pItem->mpTabPage : NULL; |
| Window* pCtrlParent = GetParent(); |
| |
| if ( IsReallyVisible() && IsUpdateMode() ) |
| { |
| sal_uInt16 nPos = GetPagePos( nId ); |
| Rectangle aRect = ImplGetTabRect( nPos ); |
| |
| if ( !pOldItem || (pOldItem->mnLine != pItem->mnLine) ) |
| { |
| aRect.Left() = 0; |
| aRect.Top() = 0; |
| aRect.Right() = Control::GetOutputSizePixel().Width(); |
| } |
| else |
| { |
| aRect.Left() -= 3; |
| aRect.Top() -= 2; |
| aRect.Right() += 3; |
| Invalidate( aRect ); |
| nPos = GetPagePos( nOldId ); |
| aRect = ImplGetTabRect( nPos ); |
| aRect.Left() -= 3; |
| aRect.Top() -= 2; |
| aRect.Right() += 3; |
| } |
| Invalidate( aRect ); |
| } |
| |
| if ( pOldPage == pPage ) |
| return; |
| |
| Rectangle aRect = ImplGetTabRect( TAB_PAGERECT ); |
| |
| if ( pOldPage ) |
| { |
| if ( mbRestoreHelpId ) |
| pCtrlParent->SetHelpId( rtl::OString() ); |
| if ( mbRestoreUnqId ) |
| pCtrlParent->SetUniqueId( rtl::OString() ); |
| pOldPage->DeactivatePage(); |
| } |
| |
| if ( pPage ) |
| { |
| pPage->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() ); |
| |
| // activate page here so the conbtrols can be switched |
| // also set the help id of the parent window to that of the tab page |
| if ( !GetHelpId().getLength() ) |
| { |
| mbRestoreHelpId = sal_True; |
| pCtrlParent->SetHelpId( pPage->GetHelpId() ); |
| } |
| if ( !pCtrlParent->GetUniqueId().getLength() ) |
| { |
| mbRestoreUnqId = sal_True; |
| pCtrlParent->SetUniqueId( pPage->GetUniqueId() ); |
| } |
| |
| pPage->ActivatePage(); |
| pPage->Show(); |
| |
| if ( pOldPage && pOldPage->HasChildPathFocus() ) |
| { |
| sal_uInt16 n = 0; |
| Window* pFirstChild = pPage->ImplGetDlgWindow( n, DLGWINDOW_FIRST ); |
| if ( pFirstChild ) |
| pFirstChild->ImplControlFocus( GETFOCUS_INIT ); |
| else |
| GrabFocus(); |
| } |
| |
| // pPage->Show(); |
| } |
| |
| if ( pOldPage ) |
| pOldPage->Hide(); |
| |
| // Invalidate the same region that will be send to NWF |
| // to always allow for bitmap caching |
| // see Window::DrawNativeControl() |
| if( IsNativeControlSupported( CTRL_TAB_PANE, PART_ENTIRE_CONTROL ) ) |
| { |
| aRect.Left() -= TAB_OFFSET; |
| aRect.Top() -= TAB_OFFSET; |
| aRect.Right() += TAB_OFFSET; |
| aRect.Bottom() += TAB_OFFSET; |
| } |
| |
| Invalidate( aRect ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool TabControl::ImplPosCurTabPage() |
| { |
| // Aktuelle TabPage resizen/positionieren |
| ImplTabItem* pItem = ImplGetItem( GetCurPageId() ); |
| if ( pItem && pItem->mpTabPage ) |
| { |
| Rectangle aRect = ImplGetTabRect( TAB_PAGERECT ); |
| pItem->mpTabPage->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() ); |
| return sal_True; |
| } |
| |
| return sal_False; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::ImplActivateTabPage( sal_Bool bNext ) |
| { |
| sal_uInt16 nCurPos = GetPagePos( GetCurPageId() ); |
| |
| if ( bNext ) |
| nCurPos = (nCurPos + 1) % GetPageCount(); |
| else |
| { |
| if ( !nCurPos ) |
| nCurPos = GetPageCount()-1; |
| else |
| nCurPos--; |
| } |
| |
| SelectTabPage( GetPageId( nCurPos ) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::ImplShowFocus() |
| { |
| if ( !GetPageCount() || mpTabCtrlData->mpListBox ) |
| return; |
| |
| // make sure the focussed item rect is computed using a bold font |
| // the font may have changed meanwhile due to mouse over |
| |
| Font aOldFont( GetFont() ); |
| Font aFont( aOldFont ); |
| aFont.SetWeight( (!ImplGetSVData()->maNWFData.mbNoBoldTabFocus) ? WEIGHT_BOLD : WEIGHT_LIGHT ); |
| SetFont( aFont ); |
| |
| sal_uInt16 nCurPos = GetPagePos( mnCurPageId ); |
| Rectangle aRect = ImplGetTabRect( nCurPos ); |
| const ImplTabItem& rItem = mpTabCtrlData->maItemList[ nCurPos ]; |
| Size aTabSize = aRect.GetSize(); |
| Size aImageSize( 0, 0 ); |
| long nTextHeight = GetTextHeight(); |
| long nTextWidth = GetCtrlTextWidth( rItem.maFormatText ); |
| sal_uInt16 nOff; |
| |
| if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_MONO) ) |
| nOff = 1; |
| else |
| nOff = 0; |
| |
| if( !! rItem.maTabImage ) |
| { |
| aImageSize = rItem.maTabImage.GetSizePixel(); |
| if( rItem.maFormatText.Len() ) |
| aImageSize.Width() += GetTextHeight()/4; |
| } |
| |
| if( rItem.maFormatText.Len() ) |
| { |
| // show focus around text |
| aRect.Left() = aRect.Left()+aImageSize.Width()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-1-1; |
| aRect.Top() = aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-1-1; |
| aRect.Right() = aRect.Left()+nTextWidth+2; |
| aRect.Bottom() = aRect.Top()+nTextHeight+2; |
| } |
| else |
| { |
| // show focus around image |
| long nXPos = aRect.Left()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-1; |
| long nYPos = aRect.Top(); |
| if( aImageSize.Height() < aRect.GetHeight() ) |
| nYPos += (aRect.GetHeight() - aImageSize.Height())/2; |
| |
| aRect.Left() = nXPos - 2; |
| aRect.Top() = nYPos - 2; |
| aRect.Right() = aRect.Left() + aImageSize.Width() + 4; |
| aRect.Bottom() = aRect.Top() + aImageSize.Height() + 4; |
| } |
| ShowFocus( aRect ); |
| |
| SetFont( aOldFont ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::ImplDrawItem( ImplTabItem* pItem, const Rectangle& rCurRect, bool bLayout, bool bFirstInGroup, bool bLastInGroup, bool bIsCurrentItem ) |
| { |
| if ( pItem->maRect.IsEmpty() ) |
| return; |
| |
| if( bLayout ) |
| { |
| if( !HasLayoutData() ) |
| { |
| mpControlData->mpLayoutData = new vcl::ControlLayoutData(); |
| mpTabCtrlData->maLayoutLineToPageId.clear(); |
| mpTabCtrlData->maLayoutPageIdToLine.clear(); |
| mpTabCtrlData->maTabRectangles.clear(); |
| } |
| } |
| |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| Rectangle aRect = pItem->maRect; |
| long nLeftBottom = aRect.Bottom(); |
| long nRightBottom = aRect.Bottom(); |
| sal_Bool bLeftBorder = sal_True; |
| sal_Bool bRightBorder = sal_True; |
| sal_uInt16 nOff; |
| sal_Bool bNativeOK = sal_False; |
| |
| sal_uInt16 nOff2 = 0; |
| sal_uInt16 nOff3 = 0; |
| |
| if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) |
| nOff = 1; |
| else |
| nOff = 0; |
| |
| // Wenn wir die aktuelle Page sind, muessen wir etwas mehr zeichnen |
| if ( pItem->mnId == mnCurPageId ) |
| { |
| nOff2 = 2; |
| if( ! ImplGetSVData()->maNWFData.mbNoActiveTabTextRaise ) |
| nOff3 = 1; |
| } |
| else |
| { |
| Point aLeftTestPos = aRect.BottomLeft(); |
| Point aRightTestPos = aRect.BottomRight(); |
| if ( aLeftTestPos.Y() == rCurRect.Bottom() ) |
| { |
| aLeftTestPos.X() -= 2; |
| if ( rCurRect.IsInside( aLeftTestPos ) ) |
| bLeftBorder = sal_False; |
| aRightTestPos.X() += 2; |
| if ( rCurRect.IsInside( aRightTestPos ) ) |
| bRightBorder = sal_False; |
| } |
| else |
| { |
| if ( rCurRect.IsInside( aLeftTestPos ) ) |
| nLeftBottom -= 2; |
| if ( rCurRect.IsInside( aRightTestPos ) ) |
| nRightBottom -= 2; |
| } |
| } |
| |
| if( !bLayout && (bNativeOK = IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL)) == sal_True ) |
| { |
| Rectangle aCtrlRegion( pItem->maRect ); |
| ControlState nState = 0; |
| |
| if( pItem->mnId == mnCurPageId ) |
| { |
| nState |= CTRL_STATE_SELECTED; |
| // only the selected item can be focussed |
| if ( HasFocus() ) |
| nState |= CTRL_STATE_FOCUSED; |
| } |
| if ( IsEnabled() ) |
| nState |= CTRL_STATE_ENABLED; |
| if( IsMouseOver() && pItem->maRect.IsInside( GetPointerPosPixel() ) ) |
| { |
| nState |= CTRL_STATE_ROLLOVER; |
| for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| if( (&(*it) != pItem) && (it->maRect.IsInside( GetPointerPosPixel() ) ) ) |
| { |
| nState &= ~CTRL_STATE_ROLLOVER; // avoid multiple highlighted tabs |
| break; |
| } |
| } |
| } |
| |
| TabitemValue tiValue; |
| if(pItem->maRect.Left() < 5) |
| tiValue.mnAlignment |= TABITEM_LEFTALIGNED; |
| if(pItem->maRect.Right() > mnLastWidth - 5) |
| tiValue.mnAlignment |= TABITEM_RIGHTALIGNED; |
| if ( bFirstInGroup ) |
| tiValue.mnAlignment |= TABITEM_FIRST_IN_GROUP; |
| if ( bLastInGroup ) |
| tiValue.mnAlignment |= TABITEM_LAST_IN_GROUP; |
| |
| bNativeOK = DrawNativeControl( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, aCtrlRegion, nState, |
| tiValue, rtl::OUString() ); |
| } |
| |
| if( ! bLayout && !bNativeOK ) |
| { |
| if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) |
| { |
| SetLineColor( rStyleSettings.GetLightColor() ); |
| DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) ); // diagonally indented top-left pixel |
| if ( bLeftBorder ) |
| { |
| DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ), |
| Point( aRect.Left()-nOff2, nLeftBottom-1 ) ); |
| } |
| DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ), // top line starting 2px from left border |
| Point( aRect.Right()+nOff2-3, aRect.Top()-nOff2 ) ); // ending 3px from right border |
| |
| if ( bRightBorder ) |
| { |
| SetLineColor( rStyleSettings.GetShadowColor() ); |
| DrawLine( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ), |
| Point( aRect.Right()+nOff2-2, nRightBottom-1 ) ); |
| |
| SetLineColor( rStyleSettings.GetDarkShadowColor() ); |
| DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+3-nOff2 ), |
| Point( aRect.Right()+nOff2-1, nRightBottom-1 ) ); |
| } |
| } |
| else |
| { |
| SetLineColor( Color( COL_BLACK ) ); |
| DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) ); |
| DrawPixel( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ) ); |
| if ( bLeftBorder ) |
| { |
| DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ), |
| Point( aRect.Left()-nOff2, nLeftBottom-1 ) ); |
| } |
| DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ), |
| Point( aRect.Right()-3, aRect.Top()-nOff2 ) ); |
| if ( bRightBorder ) |
| { |
| DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+2-nOff2 ), |
| Point( aRect.Right()+nOff2-1, nRightBottom-1 ) ); |
| } |
| } |
| } |
| |
| if( bLayout ) |
| { |
| int nLine = mpControlData->mpLayoutData->m_aLineIndices.size(); |
| mpControlData->mpLayoutData->m_aLineIndices.push_back( mpControlData->mpLayoutData->m_aDisplayText.Len() ); |
| mpTabCtrlData->maLayoutPageIdToLine[ (int)pItem->mnId ] = nLine; |
| mpTabCtrlData->maLayoutLineToPageId[ nLine ] = (int)pItem->mnId; |
| mpTabCtrlData->maTabRectangles.push_back( aRect ); |
| } |
| |
| // set font accordingly, current item is painted bold |
| // we set the font attributes always before drawing to be re-entrant (DrawNativeControl may trigger additional paints) |
| Font aFont( GetFont() ); |
| aFont.SetTransparent( sal_True ); |
| aFont.SetWeight( ((bIsCurrentItem) && (!ImplGetSVData()->maNWFData.mbNoBoldTabFocus)) ? WEIGHT_BOLD : WEIGHT_LIGHT ); |
| SetFont( aFont ); |
| |
| Size aTabSize = aRect.GetSize(); |
| Size aImageSize( 0, 0 ); |
| long nTextHeight = GetTextHeight(); |
| long nTextWidth = GetCtrlTextWidth( pItem->maFormatText ); |
| if( !! pItem->maTabImage ) |
| { |
| aImageSize = pItem->maTabImage.GetSizePixel(); |
| if( pItem->maFormatText.Len() ) |
| aImageSize.Width() += GetTextHeight()/4; |
| } |
| long nXPos = aRect.Left()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-nOff3; |
| long nYPos = aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-nOff3; |
| if( pItem->maFormatText.Len() ) |
| { |
| sal_uInt16 nStyle = TEXT_DRAW_MNEMONIC; |
| if( ! pItem->mbEnabled ) |
| nStyle |= TEXT_DRAW_DISABLE; |
| DrawCtrlText( Point( nXPos + aImageSize.Width(), nYPos ), |
| pItem->maFormatText, |
| 0, STRING_LEN, nStyle, |
| bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL, |
| bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL |
| ); |
| } |
| |
| if( !! pItem->maTabImage ) |
| { |
| Point aImgTL( nXPos, aRect.Top() ); |
| if( aImageSize.Height() < aRect.GetHeight() ) |
| aImgTL.Y() += (aRect.GetHeight() - aImageSize.Height())/2; |
| DrawImage( aImgTL, pItem->maTabImage, pItem->mbEnabled ? 0 : IMAGE_DRAW_DISABLE ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long TabControl::ImplHandleKeyEvent( const KeyEvent& rKeyEvent ) |
| { |
| long nRet = 0; |
| |
| if ( GetPageCount() > 1 ) |
| { |
| KeyCode aKeyCode = rKeyEvent.GetKeyCode(); |
| sal_uInt16 nKeyCode = aKeyCode.GetCode(); |
| |
| if ( aKeyCode.IsMod1() ) |
| { |
| if ( aKeyCode.IsShift() || (nKeyCode == KEY_PAGEUP) ) |
| { |
| if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEUP) ) |
| { |
| ImplActivateTabPage( sal_False ); |
| nRet = 1; |
| } |
| } |
| else |
| { |
| if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEDOWN) ) |
| { |
| ImplActivateTabPage( sal_True ); |
| nRet = 1; |
| } |
| } |
| } |
| } |
| |
| return nRet; |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( TabControl, ImplListBoxSelectHdl, ListBox*, EMPTYARG ) |
| { |
| SelectTabPage( GetPageId( mpTabCtrlData->mpListBox->GetSelectEntryPos() ) ); |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| IMPL_LINK( TabControl, ImplWindowEventListener, VclSimpleEvent*, pEvent ) |
| { |
| if ( pEvent && pEvent->ISA( VclWindowEvent ) && (pEvent->GetId() == VCLEVENT_WINDOW_KEYINPUT) ) |
| { |
| VclWindowEvent* pWindowEvent = static_cast< VclWindowEvent* >(pEvent); |
| // Do not handle events from TabControl or it's children, which is done in Notify(), where the events can be consumed. |
| if ( !IsWindowOrChild( pWindowEvent->GetWindow() ) ) |
| { |
| KeyEvent* pKeyEvent = static_cast< KeyEvent* >(pWindowEvent->GetData()); |
| ImplHandleKeyEvent( *pKeyEvent ); |
| } |
| } |
| return 0; |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::MouseButtonDown( const MouseEvent& rMEvt ) |
| { |
| if( mpTabCtrlData->mpListBox == NULL ) |
| { |
| if( rMEvt.IsLeft() ) |
| { |
| sal_uInt16 nPageId = GetPageId( rMEvt.GetPosPixel() ); |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| if( pItem && pItem->mbEnabled ) |
| SelectTabPage( nPageId ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::KeyInput( const KeyEvent& rKEvt ) |
| { |
| if( mpTabCtrlData->mpListBox ) |
| mpTabCtrlData->mpListBox->KeyInput( rKEvt ); |
| else if ( GetPageCount() > 1 ) |
| { |
| KeyCode aKeyCode = rKEvt.GetKeyCode(); |
| sal_uInt16 nKeyCode = aKeyCode.GetCode(); |
| |
| if ( (nKeyCode == KEY_LEFT) || (nKeyCode == KEY_RIGHT) ) |
| { |
| sal_Bool bNext = (nKeyCode == KEY_RIGHT); |
| ImplActivateTabPage( bNext ); |
| } |
| } |
| |
| Control::KeyInput( rKEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::Paint( const Rectangle& rRect ) |
| { |
| ImplPaint( rRect, false ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::ImplPaint( const Rectangle& rRect, bool bLayout ) |
| { |
| if( ! bLayout ) |
| HideFocus(); |
| |
| // Hier wird gegebenenfalls auch neu formatiert |
| Rectangle aRect = ImplGetTabRect( TAB_PAGERECT ); |
| |
| // find current item |
| ImplTabItem* pCurItem = NULL; |
| for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| if ( it->mnId == mnCurPageId ) |
| { |
| pCurItem = &(*it); |
| break; |
| } |
| } |
| |
| // Draw the TabPage border |
| const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
| Rectangle aCurRect; |
| long nTopOff = 1; |
| aRect.Left() -= TAB_OFFSET; |
| aRect.Top() -= TAB_OFFSET; |
| aRect.Right() += TAB_OFFSET; |
| aRect.Bottom() += TAB_OFFSET; |
| |
| // if we have an invisible tabpage or no tabpage at all the tabpage rect should be |
| // increased to avoid round corners that might be drawn by a theme |
| // in this case we're only interested in the top border of the tabpage because the tabitems are used |
| // standalone (eg impress) |
| sal_Bool bNoTabPage = sal_False; |
| TabPage* pCurPage = (pCurItem) ? pCurItem->mpTabPage : NULL; |
| if( !pCurPage || !pCurPage->IsVisible() ) |
| { |
| bNoTabPage = sal_True; |
| aRect.Left()-=10; |
| aRect.Right()+=10; |
| } |
| |
| sal_Bool bNativeOK = sal_False; |
| if( ! bLayout && (bNativeOK = IsNativeControlSupported( CTRL_TAB_PANE, PART_ENTIRE_CONTROL) ) == sal_True ) |
| { |
| const ImplControlValue aControlValue; |
| |
| ControlState nState = CTRL_STATE_ENABLED; |
| int part = PART_ENTIRE_CONTROL; |
| if ( !IsEnabled() ) |
| nState &= ~CTRL_STATE_ENABLED; |
| if ( HasFocus() ) |
| nState |= CTRL_STATE_FOCUSED; |
| |
| Region aClipRgn( GetActiveClipRegion() ); |
| aClipRgn.Intersect( aRect ); |
| if( !rRect.IsEmpty() ) |
| aClipRgn.Intersect( rRect ); |
| |
| if( !aClipRgn.IsEmpty() ) |
| bNativeOK = DrawNativeControl( CTRL_TAB_PANE, part, aRect, nState, |
| aControlValue, rtl::OUString() ); |
| } |
| else |
| { |
| if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) |
| SetLineColor( rStyleSettings.GetLightColor() ); |
| else |
| SetLineColor( Color( COL_BLACK ) ); |
| if ( pCurItem && !pCurItem->maRect.IsEmpty() ) |
| { |
| aCurRect = pCurItem->maRect; |
| if( ! bLayout ) |
| DrawLine( aRect.TopLeft(), Point( aCurRect.Left()-2, aRect.Top() ) ); |
| if ( aCurRect.Right()+1 < aRect.Right() ) |
| { |
| if( ! bLayout ) |
| DrawLine( Point( aCurRect.Right(), aRect.Top() ), aRect.TopRight() ); |
| } |
| else |
| nTopOff = 0; |
| } |
| else |
| if( ! bLayout ) |
| DrawLine( aRect.TopLeft(), aRect.TopRight() ); |
| |
| if( ! bLayout ) |
| { |
| DrawLine( aRect.TopLeft(), aRect.BottomLeft() ); |
| |
| if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) |
| { |
| // if we have not tab page the bottom line of the tab page |
| // directly touches the tab items, so choose a color that fits seamlessly |
| if( bNoTabPage ) |
| SetLineColor( rStyleSettings.GetDialogColor() ); |
| else |
| SetLineColor( rStyleSettings.GetShadowColor() ); |
| DrawLine( Point( 1, aRect.Bottom()-1 ), |
| Point( aRect.Right()-1, aRect.Bottom()-1 ) ); |
| DrawLine( Point( aRect.Right()-1, aRect.Top()+nTopOff ), |
| Point( aRect.Right()-1, aRect.Bottom()-1 ) ); |
| if( bNoTabPage ) |
| SetLineColor( rStyleSettings.GetDialogColor() ); |
| else |
| SetLineColor( rStyleSettings.GetDarkShadowColor() ); |
| DrawLine( Point( 0, aRect.Bottom() ), |
| Point( aRect.Right(), aRect.Bottom() ) ); |
| DrawLine( Point( aRect.Right(), aRect.Top()+nTopOff ), |
| Point( aRect.Right(), aRect.Bottom() ) ); |
| } |
| else |
| { |
| DrawLine( aRect.TopRight(), aRect.BottomRight() ); |
| DrawLine( aRect.BottomLeft(), aRect.BottomRight() ); |
| } |
| } |
| } |
| |
| if ( !mpTabCtrlData->maItemList.empty() && mpTabCtrlData->mpListBox == NULL ) |
| { |
| // Some native toolkits (GTK+) draw tabs right-to-left, with an |
| // overlap between adjacent tabs |
| bool bDrawTabsRTL = IsNativeControlSupported( CTRL_TAB_ITEM, PART_TABS_DRAW_RTL ); |
| ImplTabItem * pFirstTab = NULL; |
| ImplTabItem * pLastTab = NULL; |
| size_t idx; |
| |
| // Event though there is a tab overlap with GTK+, the first tab is not |
| // overlapped on the left side. Other tookits ignore this option. |
| if ( bDrawTabsRTL ) |
| { |
| pFirstTab = &mpTabCtrlData->maItemList.front(); |
| pLastTab = &mpTabCtrlData->maItemList.back(); |
| idx = mpTabCtrlData->maItemList.size()-1; |
| } |
| else |
| { |
| pLastTab = &mpTabCtrlData->maItemList.back(); |
| pFirstTab = &mpTabCtrlData->maItemList.front(); |
| idx = 0; |
| } |
| |
| while ( idx < mpTabCtrlData->maItemList.size() ) |
| { |
| ImplTabItem* pItem = &mpTabCtrlData->maItemList[idx]; |
| if ( pItem != pCurItem ) |
| { |
| Region aClipRgn( GetActiveClipRegion() ); |
| aClipRgn.Intersect( pItem->maRect ); |
| if( !rRect.IsEmpty() ) |
| aClipRgn.Intersect( rRect ); |
| if( bLayout || !aClipRgn.IsEmpty() ) |
| ImplDrawItem( pItem, aCurRect, bLayout, (pItem==pFirstTab), (pItem==pLastTab), sal_False ); |
| } |
| |
| if ( bDrawTabsRTL ) |
| idx--; |
| else |
| idx++; |
| } |
| |
| if ( pCurItem ) |
| { |
| Region aClipRgn( GetActiveClipRegion() ); |
| aClipRgn.Intersect( pCurItem->maRect ); |
| if( !rRect.IsEmpty() ) |
| aClipRgn.Intersect( rRect ); |
| if( bLayout || !aClipRgn.IsEmpty() ) |
| ImplDrawItem( pCurItem, aCurRect, bLayout, (pCurItem==pFirstTab), (pCurItem==pLastTab), sal_True ); |
| } |
| } |
| |
| if ( !bLayout && HasFocus() ) |
| ImplShowFocus(); |
| |
| if( ! bLayout ) |
| mbSmallInvalidate = sal_True; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::Resize() |
| { |
| ImplFreeLayoutData(); |
| |
| if ( !IsReallyShown() ) |
| return; |
| |
| if( mpTabCtrlData->mpListBox ) |
| { |
| // get the listbox' preferred size |
| Size aTabCtrlSize( GetSizePixel() ); |
| long nPrefWidth = mpTabCtrlData->mpListBox->GetOptimalSize( WINDOWSIZE_PREFERRED ).Width(); |
| if( nPrefWidth > aTabCtrlSize.Width() ) |
| nPrefWidth = aTabCtrlSize.Width(); |
| Size aNewSize( nPrefWidth, LogicToPixel( Size( 12, 12 ), MapMode( MAP_APPFONT ) ).Height() ); |
| Point aNewPos( (aTabCtrlSize.Width() - nPrefWidth) / 2, 0 ); |
| mpTabCtrlData->mpListBox->SetPosSizePixel( aNewPos, aNewSize ); |
| } |
| |
| mbFormat = sal_True; |
| |
| // Aktuelle TabPage resizen/positionieren |
| sal_Bool bTabPage = ImplPosCurTabPage(); |
| // Feststellen, was invalidiert werden muss |
| Size aNewSize = Control::GetOutputSizePixel(); |
| long nNewWidth = aNewSize.Width(); |
| for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| if ( !it->mbFullVisible || |
| (it->maRect.Right()-2 >= nNewWidth) ) |
| { |
| mbSmallInvalidate = sal_False; |
| break; |
| } |
| } |
| |
| if ( mbSmallInvalidate ) |
| { |
| Rectangle aRect = ImplGetTabRect( TAB_PAGERECT ); |
| aRect.Left() -= TAB_OFFSET+TAB_BORDER_LEFT; |
| aRect.Top() -= TAB_OFFSET+TAB_BORDER_TOP; |
| aRect.Right() += TAB_OFFSET+TAB_BORDER_RIGHT; |
| aRect.Bottom() += TAB_OFFSET+TAB_BORDER_BOTTOM; |
| if ( bTabPage ) |
| Invalidate( aRect, INVALIDATE_NOCHILDREN ); |
| else |
| Invalidate( aRect ); |
| |
| } |
| else |
| { |
| if ( bTabPage ) |
| Invalidate( INVALIDATE_NOCHILDREN ); |
| else |
| Invalidate(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::GetFocus() |
| { |
| if( ! mpTabCtrlData->mpListBox ) |
| { |
| ImplShowFocus(); |
| SetInputContext( InputContext( GetFont() ) ); |
| } |
| else |
| { |
| if( mpTabCtrlData->mpListBox->IsReallyVisible() ) |
| mpTabCtrlData->mpListBox->GrabFocus(); |
| } |
| Control::GetFocus(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::LoseFocus() |
| { |
| if( ! mpTabCtrlData->mpListBox ) |
| HideFocus(); |
| Control::LoseFocus(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::RequestHelp( const HelpEvent& rHEvt ) |
| { |
| sal_uInt16 nItemId = rHEvt.KeyboardActivated() ? mnCurPageId : GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ); |
| |
| if ( nItemId ) |
| { |
| if ( rHEvt.GetMode() & HELPMODE_BALLOON ) |
| { |
| XubString aStr = GetHelpText( nItemId ); |
| if ( aStr.Len() ) |
| { |
| Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) ); |
| Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); |
| aItemRect.Left() = aPt.X(); |
| aItemRect.Top() = aPt.Y(); |
| aPt = OutputToScreenPixel( aItemRect.BottomRight() ); |
| aItemRect.Right() = aPt.X(); |
| aItemRect.Bottom() = aPt.Y(); |
| Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr ); |
| return; |
| } |
| } |
| else if ( rHEvt.GetMode() & HELPMODE_EXTENDED ) |
| { |
| rtl::OUString aHelpId( rtl::OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) ); |
| if ( aHelpId.getLength() ) |
| { |
| // Wenn eine Hilfe existiert, dann ausloesen |
| Help* pHelp = Application::GetHelp(); |
| if ( pHelp ) |
| pHelp->Start( aHelpId, this ); |
| return; |
| } |
| } |
| |
| // Bei Quick- oder Balloon-Help zeigen wir den Text an, |
| // wenn dieser abgeschnitten ist |
| if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) ) |
| { |
| ImplTabItem* pItem = ImplGetItem( nItemId ); |
| const XubString& rStr = pItem->maText; |
| if ( rStr != pItem->maFormatText ) |
| { |
| Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) ); |
| Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); |
| aItemRect.Left() = aPt.X(); |
| aItemRect.Top() = aPt.Y(); |
| aPt = OutputToScreenPixel( aItemRect.BottomRight() ); |
| aItemRect.Right() = aPt.X(); |
| aItemRect.Bottom() = aPt.Y(); |
| if ( rStr.Len() ) |
| { |
| if ( rHEvt.GetMode() & HELPMODE_BALLOON ) |
| Help::ShowBalloon( this, aItemRect.Center(), aItemRect, rStr ); |
| else |
| Help::ShowQuickHelp( this, aItemRect, rStr ); |
| return; |
| } |
| } |
| } |
| |
| if ( rHEvt.GetMode() & HELPMODE_QUICK ) |
| { |
| ImplTabItem* pItem = ImplGetItem( nItemId ); |
| const XubString& rHelpText = pItem->maHelpText; |
| // show tooltip if not text but image is set and helptext is available |
| if ( rHelpText.Len() > 0 && pItem->maText.Len() == 0 && !!pItem->maTabImage ) |
| { |
| Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) ); |
| Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); |
| aItemRect.Left() = aPt.X(); |
| aItemRect.Top() = aPt.Y(); |
| aPt = OutputToScreenPixel( aItemRect.BottomRight() ); |
| aItemRect.Right() = aPt.X(); |
| aItemRect.Bottom() = aPt.Y(); |
| Help::ShowQuickHelp( this, aItemRect, rHelpText ); |
| return; |
| } |
| } |
| } |
| |
| Control::RequestHelp( rHEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::Command( const CommandEvent& rCEvt ) |
| { |
| if( (mpTabCtrlData->mpListBox == NULL) && (rCEvt.GetCommand() == COMMAND_CONTEXTMENU) && (GetPageCount() > 1) ) |
| { |
| Point aMenuPos; |
| sal_Bool bMenu; |
| if ( rCEvt.IsMouseEvent() ) |
| { |
| aMenuPos = rCEvt.GetMousePosPixel(); |
| bMenu = GetPageId( aMenuPos ) != 0; |
| } |
| else |
| { |
| aMenuPos = ImplGetTabRect( GetPagePos( mnCurPageId ) ).Center(); |
| bMenu = sal_True; |
| } |
| |
| if ( bMenu ) |
| { |
| PopupMenu aMenu; |
| for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| aMenu.InsertItem( it->mnId, it->maText, MIB_CHECKABLE | MIB_RADIOCHECK ); |
| if ( it->mnId == mnCurPageId ) |
| aMenu.CheckItem( it->mnId ); |
| aMenu.SetHelpId( it->mnId, it->maHelpId ); |
| } |
| |
| sal_uInt16 nId = aMenu.Execute( this, aMenuPos ); |
| if ( nId && (nId != mnCurPageId) ) |
| SelectTabPage( nId ); |
| return; |
| } |
| } |
| |
| Control::Command( rCEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::StateChanged( StateChangedType nType ) |
| { |
| Control::StateChanged( nType ); |
| |
| if ( nType == STATE_CHANGE_INITSHOW ) |
| { |
| ImplPosCurTabPage(); |
| if( mpTabCtrlData->mpListBox ) |
| Resize(); |
| } |
| else if ( nType == STATE_CHANGE_UPDATEMODE ) |
| { |
| if ( IsUpdateMode() ) |
| Invalidate(); |
| } |
| else if ( (nType == STATE_CHANGE_ZOOM) || |
| (nType == STATE_CHANGE_CONTROLFONT) ) |
| { |
| ImplInitSettings( sal_True, sal_False, sal_False ); |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) |
| { |
| ImplInitSettings( sal_False, sal_True, sal_False ); |
| Invalidate(); |
| } |
| else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) |
| { |
| ImplInitSettings( sal_False, sal_False, sal_True ); |
| Invalidate(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| Control::DataChanged( rDCEvt ); |
| |
| if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || |
| (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || |
| ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && |
| (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) |
| { |
| ImplInitSettings( sal_True, sal_True, sal_True ); |
| Invalidate(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle* TabControl::ImplFindPartRect( const Point& rPt ) |
| { |
| ImplTabItem* pFoundItem = NULL; |
| int nFound = 0; |
| for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| if ( it->maRect.IsInside( rPt ) ) |
| { |
| // assure that only one tab is highlighted at a time |
| nFound++; |
| pFoundItem = &(*it); |
| } |
| } |
| // assure that only one tab is highlighted at a time |
| return nFound == 1 ? &pFoundItem->maRect : NULL; |
| } |
| |
| long TabControl::PreNotify( NotifyEvent& rNEvt ) |
| { |
| long nDone = 0; |
| const MouseEvent* pMouseEvt = NULL; |
| |
| if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) |
| { |
| if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() ) |
| { |
| // trigger redraw if mouse over state has changed |
| if( IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL) ) |
| { |
| Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); |
| Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() ); |
| if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) ) |
| { |
| Region aClipRgn; |
| if( pLastRect ) |
| { |
| // allow for slightly bigger tabitems |
| // as used by gtk |
| // TODO: query for the correct sizes |
| Rectangle aRect(*pLastRect); |
| aRect.nLeft-=2; |
| aRect.nRight+=2; |
| aRect.nTop-=3; |
| aClipRgn.Union( aRect ); |
| } |
| if( pRect ) |
| { |
| // allow for slightly bigger tabitems |
| // as used by gtk |
| // TODO: query for the correct sizes |
| Rectangle aRect(*pRect); |
| aRect.nLeft-=2; |
| aRect.nRight+=2; |
| aRect.nTop-=3; |
| aClipRgn.Union( aRect ); |
| } |
| if( !aClipRgn.IsEmpty() ) |
| Invalidate( aClipRgn ); |
| } |
| } |
| } |
| } |
| |
| return nDone ? nDone : Control::PreNotify(rNEvt); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long TabControl::Notify( NotifyEvent& rNEvt ) |
| { |
| long nRet = 0; |
| |
| if ( rNEvt.GetType() == EVENT_KEYINPUT ) |
| nRet = ImplHandleKeyEvent( *rNEvt.GetKeyEvent() ); |
| |
| return nRet ? nRet : Control::Notify( rNEvt ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::ActivatePage() |
| { |
| maActivateHdl.Call( this ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long TabControl::DeactivatePage() |
| { |
| if ( maDeactivateHdl.IsSet() ) |
| return maDeactivateHdl.Call( this ); |
| else |
| return sal_True; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SetTabPageSizePixel( const Size& rSize ) |
| { |
| ImplFreeLayoutData(); |
| |
| Size aNewSize( rSize ); |
| aNewSize.Width() += TAB_OFFSET*2; |
| Rectangle aRect = ImplGetTabRect( TAB_PAGERECT, |
| aNewSize.Width(), aNewSize.Height() ); |
| aNewSize.Height() += aRect.Top()+TAB_OFFSET; |
| Window::SetOutputSizePixel( aNewSize ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size TabControl::GetTabPageSizePixel() const |
| { |
| Rectangle aRect = ((TabControl*)this)->ImplGetTabRect( TAB_PAGERECT ); |
| return aRect.GetSize(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::InsertPage( const ResId& rResId, sal_uInt16 nPos ) |
| { |
| GetRes( rResId.SetRT( RSC_TABCONTROLITEM ) ); |
| |
| sal_uLong nObjMask = ReadLongRes(); |
| sal_uInt16 nItemId = 1; |
| |
| // ID |
| if ( nObjMask & RSC_TABCONTROLITEM_ID ) |
| nItemId = sal::static_int_cast<sal_uInt16>(ReadLongRes()); |
| |
| // Text |
| XubString aTmpStr; |
| if( nObjMask & RSC_TABCONTROLITEM_TEXT ) |
| aTmpStr = ReadStringRes(); |
| InsertPage( nItemId, aTmpStr, nPos ); |
| |
| // PageResID |
| if ( nObjMask & RSC_TABCONTROLITEM_PAGERESID ) |
| { |
| ImplTabItem& rItem = mpTabCtrlData->maItemList[ GetPagePos( nItemId ) ]; |
| rItem.mnTabPageResId = sal::static_int_cast<sal_uInt16>(ReadLongRes()); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::InsertPage( sal_uInt16 nPageId, const XubString& rText, |
| sal_uInt16 nPos ) |
| { |
| DBG_ASSERT( nPageId, "TabControl::InsertPage(): PageId == 0" ); |
| DBG_ASSERT( GetPagePos( nPageId ) == TAB_PAGE_NOTFOUND, |
| "TabControl::InsertPage(): PageId already exists" ); |
| |
| // insert new page item |
| ImplTabItem* pItem = NULL; |
| if( nPos == TAB_APPEND || size_t(nPos) >= mpTabCtrlData->maItemList.size() ) |
| { |
| mpTabCtrlData->maItemList.push_back( ImplTabItem() ); |
| pItem = &mpTabCtrlData->maItemList.back(); |
| if( mpTabCtrlData->mpListBox ) |
| mpTabCtrlData->mpListBox->InsertEntry( rText ); |
| } |
| else |
| { |
| std::vector< ImplTabItem >::iterator new_it = |
| mpTabCtrlData->maItemList.insert( mpTabCtrlData->maItemList.begin() + nPos, ImplTabItem() ); |
| pItem = &(*new_it); |
| if( mpTabCtrlData->mpListBox ) |
| mpTabCtrlData->mpListBox->InsertEntry( rText, nPos); |
| } |
| if( mpTabCtrlData->mpListBox ) |
| { |
| if( ! mnCurPageId ) |
| mpTabCtrlData->mpListBox->SelectEntryPos( 0 ); |
| mpTabCtrlData->mpListBox->SetDropDownLineCount( mpTabCtrlData->mpListBox->GetEntryCount() ); |
| } |
| |
| // set current page id |
| if ( !mnCurPageId ) |
| mnCurPageId = nPageId; |
| |
| // init new page item |
| pItem->mnId = nPageId; |
| pItem->mpTabPage = NULL; |
| pItem->mnTabPageResId = 0; |
| pItem->maText = rText; |
| pItem->mbFullVisible = sal_False; |
| |
| mbFormat = sal_True; |
| if ( IsUpdateMode() ) |
| Invalidate(); |
| |
| ImplFreeLayoutData(); |
| if( mpTabCtrlData->mpListBox ) // reposition/resize listbox |
| Resize(); |
| |
| ImplCallEventListeners( VCLEVENT_TABPAGE_INSERTED, (void*) (sal_uLong)nPageId ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::RemovePage( sal_uInt16 nPageId ) |
| { |
| sal_uInt16 nPos = GetPagePos( nPageId ); |
| |
| // does the item exist ? |
| if ( nPos != TAB_PAGE_NOTFOUND ) |
| { |
| //remove page item |
| std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin() + nPos; |
| bool bIsCurrentPage = (it->mnId == mnCurPageId); |
| mpTabCtrlData->maItemList.erase( it ); |
| if( mpTabCtrlData->mpListBox ) |
| { |
| mpTabCtrlData->mpListBox->RemoveEntry( nPos ); |
| mpTabCtrlData->mpListBox->SetDropDownLineCount( mpTabCtrlData->mpListBox->GetEntryCount() ); |
| } |
| |
| // If current page is removed, than first page gets the current page |
| if ( bIsCurrentPage ) |
| { |
| mnCurPageId = 0; |
| |
| if( ! mpTabCtrlData->maItemList.empty() ) |
| { |
| // don't do this by simply setting mnCurPageId to pFirstItem->mnId |
| // this leaves a lot of stuff (such trivias as _showing_ the new current page) undone |
| // instead, call SetCurPageId |
| // without this, the next (outside) call to SetCurPageId with the id of the first page |
| // will result in doing nothing (as we assume that nothing changed, then), and the page |
| // will never be shown. |
| // 86875 - 05/11/2001 - frank.schoenheit@germany.sun.com |
| |
| SetCurPageId( mpTabCtrlData->maItemList[0].mnId ); |
| } |
| } |
| |
| mbFormat = sal_True; |
| if ( IsUpdateMode() ) |
| Invalidate(); |
| |
| ImplFreeLayoutData(); |
| |
| ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVED, (void*) (sal_uLong) nPageId ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::Clear() |
| { |
| // clear item list |
| mpTabCtrlData->maItemList.clear(); |
| mnCurPageId = 0; |
| if( mpTabCtrlData->mpListBox ) |
| mpTabCtrlData->mpListBox->Clear(); |
| |
| ImplFreeLayoutData(); |
| |
| mbFormat = sal_True; |
| if ( IsUpdateMode() ) |
| Invalidate(); |
| |
| ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVEDALL ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::EnablePage( sal_uInt16 i_nPageId, bool i_bEnable ) |
| { |
| ImplTabItem* pItem = ImplGetItem( i_nPageId ); |
| |
| if ( pItem && pItem->mbEnabled != i_bEnable ) |
| { |
| pItem->mbEnabled = i_bEnable; |
| mbFormat = sal_True; |
| if( mpTabCtrlData->mpListBox ) |
| mpTabCtrlData->mpListBox->SetEntryFlags( GetPagePos( i_nPageId ), |
| i_bEnable ? 0 : (LISTBOX_ENTRY_FLAG_DISABLE_SELECTION | LISTBOX_ENTRY_FLAG_DRAW_DISABLED) ); |
| if( pItem->mnId == mnCurPageId ) |
| { |
| // SetCurPageId will change to an enabled page |
| SetCurPageId( mnCurPageId ); |
| } |
| else if ( IsUpdateMode() ) |
| Invalidate(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 TabControl::GetPageCount() const |
| { |
| return (sal_uInt16)mpTabCtrlData->maItemList.size(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 TabControl::GetPageId( sal_uInt16 nPos ) const |
| { |
| if( size_t(nPos) < mpTabCtrlData->maItemList.size() ) |
| return mpTabCtrlData->maItemList[ nPos ].mnId; |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 TabControl::GetPagePos( sal_uInt16 nPageId ) const |
| { |
| for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin(); |
| it != mpTabCtrlData->maItemList.end(); ++it ) |
| { |
| if ( it->mnId == nPageId ) |
| return (sal_uInt16)(it - mpTabCtrlData->maItemList.begin()); |
| } |
| |
| return TAB_PAGE_NOTFOUND; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 TabControl::GetPageId( const Point& rPos ) const |
| { |
| for( size_t i = 0; i < mpTabCtrlData->maItemList.size(); ++i ) |
| { |
| if ( ((TabControl*)this)->ImplGetTabRect( static_cast<sal_uInt16>(i) ).IsInside( rPos ) ) |
| return mpTabCtrlData->maItemList[ i ].mnId; |
| } |
| |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SetCurPageId( sal_uInt16 nPageId ) |
| { |
| sal_uInt16 nPos = GetPagePos( nPageId ); |
| while( nPos != TAB_PAGE_NOTFOUND && |
| ! mpTabCtrlData->maItemList[nPos].mbEnabled ) |
| { |
| nPos++; |
| if( size_t(nPos) >= mpTabCtrlData->maItemList.size() ) |
| nPos = 0; |
| if( mpTabCtrlData->maItemList[nPos].mnId == nPageId ) |
| break; |
| } |
| |
| if( nPos != TAB_PAGE_NOTFOUND ) |
| { |
| nPageId = mpTabCtrlData->maItemList[nPos].mnId; |
| if ( nPageId == mnCurPageId ) |
| { |
| if ( mnActPageId ) |
| mnActPageId = nPageId; |
| return; |
| } |
| |
| if ( mnActPageId ) |
| mnActPageId = nPageId; |
| else |
| { |
| mbFormat = sal_True; |
| sal_uInt16 nOldId = mnCurPageId; |
| mnCurPageId = nPageId; |
| ImplChangeTabPage( nPageId, nOldId ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 TabControl::GetCurPageId() const |
| { |
| if ( mnActPageId ) |
| return mnActPageId; |
| else |
| return mnCurPageId; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SelectTabPage( sal_uInt16 nPageId ) |
| { |
| if ( nPageId && (nPageId != mnCurPageId) ) |
| { |
| ImplFreeLayoutData(); |
| |
| ImplCallEventListeners( VCLEVENT_TABPAGE_DEACTIVATE, (void*) (sal_uLong) mnCurPageId ); |
| if ( DeactivatePage() ) |
| { |
| mnActPageId = nPageId; |
| ActivatePage(); |
| // Page koennte im Activate-Handler umgeschaltet wurden sein |
| nPageId = mnActPageId; |
| mnActPageId = 0; |
| SetCurPageId( nPageId ); |
| if( mpTabCtrlData->mpListBox ) |
| mpTabCtrlData->mpListBox->SelectEntryPos( GetPagePos( nPageId ) ); |
| ImplCallEventListeners( VCLEVENT_TABPAGE_ACTIVATE, (void*) (sal_uLong) nPageId ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SetTabPage( sal_uInt16 nPageId, TabPage* pTabPage ) |
| { |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| |
| if ( pItem && (pItem->mpTabPage != pTabPage) ) |
| { |
| if ( pTabPage ) |
| { |
| DBG_ASSERT( !pTabPage->IsVisible(), "TabControl::SetTabPage() - Page is visible" ); |
| |
| if ( IsDefaultSize() ) |
| SetTabPageSizePixel( pTabPage->GetSizePixel() ); |
| |
| // Erst hier setzen, damit Resize nicht TabPage umpositioniert |
| pItem->mpTabPage = pTabPage; |
| if ( pItem->mnId == mnCurPageId ) |
| ImplChangeTabPage( pItem->mnId, 0 ); |
| } |
| else |
| pItem->mpTabPage = NULL; |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| TabPage* TabControl::GetTabPage( sal_uInt16 nPageId ) const |
| { |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| |
| if ( pItem ) |
| return pItem->mpTabPage; |
| else |
| return NULL; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 TabControl::GetTabPageResId( sal_uInt16 nPageId ) const |
| { |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| |
| if ( pItem ) |
| return pItem->mnTabPageResId; |
| else |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SetPageText( sal_uInt16 nPageId, const XubString& rText ) |
| { |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| |
| if ( pItem && pItem->maText != rText ) |
| { |
| pItem->maText = rText; |
| mbFormat = sal_True; |
| if( mpTabCtrlData->mpListBox ) |
| { |
| sal_uInt16 nPos = GetPagePos( nPageId ); |
| mpTabCtrlData->mpListBox->RemoveEntry( nPos ); |
| mpTabCtrlData->mpListBox->InsertEntry( rText, nPos ); |
| } |
| if ( IsUpdateMode() ) |
| Invalidate(); |
| ImplFreeLayoutData(); |
| ImplCallEventListeners( VCLEVENT_TABPAGE_PAGETEXTCHANGED, (void*) (sal_uLong) nPageId ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| XubString TabControl::GetPageText( sal_uInt16 nPageId ) const |
| { |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| |
| if ( pItem ) |
| return pItem->maText; |
| else |
| return ImplGetSVEmptyStr(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SetHelpText( sal_uInt16 nPageId, const XubString& rText ) |
| { |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| |
| if ( pItem ) |
| pItem->maHelpText = rText; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| const XubString& TabControl::GetHelpText( sal_uInt16 nPageId ) const |
| { |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| |
| if ( pItem ) |
| { |
| if ( !pItem->maHelpText.Len() && pItem->maHelpId.getLength() ) |
| { |
| Help* pHelp = Application::GetHelp(); |
| if ( pHelp ) |
| pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this ); |
| } |
| |
| return pItem->maHelpText; |
| } |
| else |
| return ImplGetSVEmptyStr(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SetHelpId( sal_uInt16 nPageId, const rtl::OString& rHelpId ) |
| { |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| |
| if ( pItem ) |
| pItem->maHelpId = rHelpId; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| rtl::OString TabControl::GetHelpId( sal_uInt16 nPageId ) const |
| { |
| rtl::OString aRet; |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| |
| if ( pItem ) |
| aRet = pItem->maHelpId; |
| |
| return aRet; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SetPageImage( sal_uInt16 i_nPageId, const Image& i_rImage ) |
| { |
| ImplTabItem* pItem = ImplGetItem( i_nPageId ); |
| |
| if ( pItem ) |
| { |
| pItem->maTabImage = i_rImage; |
| mbFormat = sal_True; |
| if ( IsUpdateMode() ) |
| Invalidate(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| const Image* TabControl::GetPageImage( sal_uInt16 i_nPageId ) const |
| { |
| const ImplTabItem* pItem = ImplGetItem( i_nPageId ); |
| return pItem ? &pItem->maTabImage : NULL; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle TabControl::GetCharacterBounds( sal_uInt16 nPageId, long nIndex ) const |
| { |
| Rectangle aRet; |
| |
| if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() ) |
| FillLayoutData(); |
| |
| if( HasLayoutData() ) |
| { |
| std::hash_map< int, int >::const_iterator it = mpTabCtrlData->maLayoutPageIdToLine.find( (int)nPageId ); |
| if( it != mpTabCtrlData->maLayoutPageIdToLine.end() ) |
| { |
| Pair aPair = mpControlData->mpLayoutData->GetLineStartEnd( it->second ); |
| if( (aPair.B() - aPair.A()) >= nIndex ) |
| aRet = mpControlData->mpLayoutData->GetCharacterBounds( aPair.A() + nIndex ); |
| } |
| } |
| |
| return aRet; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long TabControl::GetIndexForPoint( const Point& rPoint, sal_uInt16& rPageId ) const |
| { |
| long nRet = -1; |
| |
| if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() ) |
| FillLayoutData(); |
| |
| if( HasLayoutData() ) |
| { |
| int nIndex = mpControlData->mpLayoutData->GetIndexForPoint( rPoint ); |
| if( nIndex != -1 ) |
| { |
| // what line (->pageid) is this index in ? |
| int nLines = mpControlData->mpLayoutData->GetLineCount(); |
| int nLine = -1; |
| while( ++nLine < nLines ) |
| { |
| Pair aPair = mpControlData->mpLayoutData->GetLineStartEnd( nLine ); |
| if( aPair.A() <= nIndex && aPair.B() >= nIndex ) |
| { |
| nRet = nIndex - aPair.A(); |
| rPageId = (sal_uInt16)mpTabCtrlData->maLayoutLineToPageId[ nLine ]; |
| break; |
| } |
| } |
| } |
| } |
| |
| return nRet; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::FillLayoutData() const |
| { |
| mpTabCtrlData->maLayoutLineToPageId.clear(); |
| mpTabCtrlData->maLayoutPageIdToLine.clear(); |
| const_cast<TabControl*>(this)->ImplPaint( Rectangle(), true ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle TabControl::GetTabPageBounds( sal_uInt16 nPage ) const |
| { |
| Rectangle aRet; |
| |
| if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() ) |
| FillLayoutData(); |
| |
| if( HasLayoutData() ) |
| { |
| std::hash_map< int, int >::const_iterator it = mpTabCtrlData->maLayoutPageIdToLine.find( (int)nPage ); |
| if( it != mpTabCtrlData->maLayoutPageIdToLine.end() ) |
| { |
| if( it->second >= 0 && it->second < static_cast<int>(mpTabCtrlData->maTabRectangles.size()) ) |
| { |
| aRet = mpTabCtrlData->maTabRectangles[ it->second ]; |
| aRet.Union( const_cast<TabControl*>(this)->ImplGetTabRect( TAB_PAGERECT ) ); |
| } |
| } |
| } |
| |
| return aRet; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Rectangle TabControl::GetTabBounds( sal_uInt16 nPageId ) const |
| { |
| Rectangle aRet; |
| |
| ImplTabItem* pItem = ImplGetItem( nPageId ); |
| if(pItem) |
| aRet = pItem->maRect; |
| |
| return aRet; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SetItemsOffset( const Point& rOffs ) |
| { |
| if( mpTabCtrlData ) |
| mpTabCtrlData->maItemsOffset = rOffs; |
| } |
| |
| Point TabControl::GetItemsOffset() const |
| { |
| if( mpTabCtrlData ) |
| return mpTabCtrlData->maItemsOffset; |
| else |
| return Point(); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| Size TabControl::GetOptimalSize(WindowSizeType eType) const |
| { |
| switch (eType) { |
| case WINDOWSIZE_MINIMUM: |
| return mpTabCtrlData ? mpTabCtrlData->maMinSize : Size(); |
| default: |
| return Control::GetOptimalSize( eType ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void TabControl::SetMinimumSizePixel( const Size& i_rSize ) |
| { |
| if( mpTabCtrlData ) |
| mpTabCtrlData->maMinSize = i_rSize; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| |