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