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 //IAccessibility2 Implementation 2009----- 623 pPage->Show(); 624 //-----IAccessibility2 Implementation 2009 625 626 if ( pOldPage && pOldPage->HasChildPathFocus() ) 627 { 628 sal_uInt16 n = 0; 629 Window* pFirstChild = pPage->ImplGetDlgWindow( n, DLGWINDOW_FIRST ); 630 if ( pFirstChild ) 631 pFirstChild->ImplControlFocus( GETFOCUS_INIT ); 632 else 633 GrabFocus(); 634 } 635 636 //IAccessibility2 Implementation 2009----- 637 // pPage->Show(); 638 //-----IAccessibility2 Implementation 2009 639 } 640 641 if ( pOldPage ) 642 pOldPage->Hide(); 643 644 // Invalidate the same region that will be send to NWF 645 // to always allow for bitmap caching 646 // see Window::DrawNativeControl() 647 if( IsNativeControlSupported( CTRL_TAB_PANE, PART_ENTIRE_CONTROL ) ) 648 { 649 aRect.Left() -= TAB_OFFSET; 650 aRect.Top() -= TAB_OFFSET; 651 aRect.Right() += TAB_OFFSET; 652 aRect.Bottom() += TAB_OFFSET; 653 } 654 655 Invalidate( aRect ); 656 } 657 658 // ----------------------------------------------------------------------- 659 660 sal_Bool TabControl::ImplPosCurTabPage() 661 { 662 // Aktuelle TabPage resizen/positionieren 663 ImplTabItem* pItem = ImplGetItem( GetCurPageId() ); 664 if ( pItem && pItem->mpTabPage ) 665 { 666 Rectangle aRect = ImplGetTabRect( TAB_PAGERECT ); 667 pItem->mpTabPage->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() ); 668 return sal_True; 669 } 670 671 return sal_False; 672 } 673 674 // ----------------------------------------------------------------------- 675 676 void TabControl::ImplActivateTabPage( sal_Bool bNext ) 677 { 678 sal_uInt16 nCurPos = GetPagePos( GetCurPageId() ); 679 680 if ( bNext ) 681 nCurPos = (nCurPos + 1) % GetPageCount(); 682 else 683 { 684 if ( !nCurPos ) 685 nCurPos = GetPageCount()-1; 686 else 687 nCurPos--; 688 } 689 690 SelectTabPage( GetPageId( nCurPos ) ); 691 } 692 693 // ----------------------------------------------------------------------- 694 695 void TabControl::ImplShowFocus() 696 { 697 if ( !GetPageCount() || mpTabCtrlData->mpListBox ) 698 return; 699 700 // make sure the focussed item rect is computed using a bold font 701 // the font may have changed meanwhile due to mouse over 702 703 Font aOldFont( GetFont() ); 704 Font aFont( aOldFont ); 705 aFont.SetWeight( (!ImplGetSVData()->maNWFData.mbNoBoldTabFocus) ? WEIGHT_BOLD : WEIGHT_LIGHT ); 706 SetFont( aFont ); 707 708 sal_uInt16 nCurPos = GetPagePos( mnCurPageId ); 709 Rectangle aRect = ImplGetTabRect( nCurPos ); 710 const ImplTabItem& rItem = mpTabCtrlData->maItemList[ nCurPos ]; 711 Size aTabSize = aRect.GetSize(); 712 Size aImageSize( 0, 0 ); 713 long nTextHeight = GetTextHeight(); 714 long nTextWidth = GetCtrlTextWidth( rItem.maFormatText ); 715 sal_uInt16 nOff; 716 717 if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_MONO) ) 718 nOff = 1; 719 else 720 nOff = 0; 721 722 if( !! rItem.maTabImage ) 723 { 724 aImageSize = rItem.maTabImage.GetSizePixel(); 725 if( rItem.maFormatText.Len() ) 726 aImageSize.Width() += GetTextHeight()/4; 727 } 728 729 if( rItem.maFormatText.Len() ) 730 { 731 // show focus around text 732 aRect.Left() = aRect.Left()+aImageSize.Width()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-1-1; 733 aRect.Top() = aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-1-1; 734 aRect.Right() = aRect.Left()+nTextWidth+2; 735 aRect.Bottom() = aRect.Top()+nTextHeight+2; 736 } 737 else 738 { 739 // show focus around image 740 long nXPos = aRect.Left()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-1; 741 long nYPos = aRect.Top(); 742 if( aImageSize.Height() < aRect.GetHeight() ) 743 nYPos += (aRect.GetHeight() - aImageSize.Height())/2; 744 745 aRect.Left() = nXPos - 2; 746 aRect.Top() = nYPos - 2; 747 aRect.Right() = aRect.Left() + aImageSize.Width() + 4; 748 aRect.Bottom() = aRect.Top() + aImageSize.Height() + 4; 749 } 750 ShowFocus( aRect ); 751 752 SetFont( aOldFont ); 753 } 754 755 // ----------------------------------------------------------------------- 756 757 void TabControl::ImplDrawItem( ImplTabItem* pItem, const Rectangle& rCurRect, bool bLayout, bool bFirstInGroup, bool bLastInGroup, bool bIsCurrentItem ) 758 { 759 if ( pItem->maRect.IsEmpty() ) 760 return; 761 762 if( bLayout ) 763 { 764 if( !HasLayoutData() ) 765 { 766 mpControlData->mpLayoutData = new vcl::ControlLayoutData(); 767 mpTabCtrlData->maLayoutLineToPageId.clear(); 768 mpTabCtrlData->maLayoutPageIdToLine.clear(); 769 mpTabCtrlData->maTabRectangles.clear(); 770 } 771 } 772 773 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 774 Rectangle aRect = pItem->maRect; 775 long nLeftBottom = aRect.Bottom(); 776 long nRightBottom = aRect.Bottom(); 777 sal_Bool bLeftBorder = sal_True; 778 sal_Bool bRightBorder = sal_True; 779 sal_uInt16 nOff; 780 sal_Bool bNativeOK = sal_False; 781 782 sal_uInt16 nOff2 = 0; 783 sal_uInt16 nOff3 = 0; 784 785 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) 786 nOff = 1; 787 else 788 nOff = 0; 789 790 // Wenn wir die aktuelle Page sind, muessen wir etwas mehr zeichnen 791 if ( pItem->mnId == mnCurPageId ) 792 { 793 nOff2 = 2; 794 if( ! ImplGetSVData()->maNWFData.mbNoActiveTabTextRaise ) 795 nOff3 = 1; 796 } 797 else 798 { 799 Point aLeftTestPos = aRect.BottomLeft(); 800 Point aRightTestPos = aRect.BottomRight(); 801 if ( aLeftTestPos.Y() == rCurRect.Bottom() ) 802 { 803 aLeftTestPos.X() -= 2; 804 if ( rCurRect.IsInside( aLeftTestPos ) ) 805 bLeftBorder = sal_False; 806 aRightTestPos.X() += 2; 807 if ( rCurRect.IsInside( aRightTestPos ) ) 808 bRightBorder = sal_False; 809 } 810 else 811 { 812 if ( rCurRect.IsInside( aLeftTestPos ) ) 813 nLeftBottom -= 2; 814 if ( rCurRect.IsInside( aRightTestPos ) ) 815 nRightBottom -= 2; 816 } 817 } 818 819 if( !bLayout && (bNativeOK = IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL)) == sal_True ) 820 { 821 Rectangle aCtrlRegion( pItem->maRect ); 822 ControlState nState = 0; 823 824 if( pItem->mnId == mnCurPageId ) 825 { 826 nState |= CTRL_STATE_SELECTED; 827 // only the selected item can be focussed 828 if ( HasFocus() ) 829 nState |= CTRL_STATE_FOCUSED; 830 } 831 if ( IsEnabled() ) 832 nState |= CTRL_STATE_ENABLED; 833 if( IsMouseOver() && pItem->maRect.IsInside( GetPointerPosPixel() ) ) 834 { 835 nState |= CTRL_STATE_ROLLOVER; 836 for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); 837 it != mpTabCtrlData->maItemList.end(); ++it ) 838 { 839 if( (&(*it) != pItem) && (it->maRect.IsInside( GetPointerPosPixel() ) ) ) 840 { 841 nState &= ~CTRL_STATE_ROLLOVER; // avoid multiple highlighted tabs 842 break; 843 } 844 } 845 } 846 847 TabitemValue tiValue; 848 if(pItem->maRect.Left() < 5) 849 tiValue.mnAlignment |= TABITEM_LEFTALIGNED; 850 if(pItem->maRect.Right() > mnLastWidth - 5) 851 tiValue.mnAlignment |= TABITEM_RIGHTALIGNED; 852 if ( bFirstInGroup ) 853 tiValue.mnAlignment |= TABITEM_FIRST_IN_GROUP; 854 if ( bLastInGroup ) 855 tiValue.mnAlignment |= TABITEM_LAST_IN_GROUP; 856 857 bNativeOK = DrawNativeControl( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, aCtrlRegion, nState, 858 tiValue, rtl::OUString() ); 859 } 860 861 if( ! bLayout && !bNativeOK ) 862 { 863 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) 864 { 865 SetLineColor( rStyleSettings.GetLightColor() ); 866 DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) ); // diagonally indented top-left pixel 867 if ( bLeftBorder ) 868 { 869 DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ), 870 Point( aRect.Left()-nOff2, nLeftBottom-1 ) ); 871 } 872 DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ), // top line starting 2px from left border 873 Point( aRect.Right()+nOff2-3, aRect.Top()-nOff2 ) ); // ending 3px from right border 874 875 if ( bRightBorder ) 876 { 877 SetLineColor( rStyleSettings.GetShadowColor() ); 878 DrawLine( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ), 879 Point( aRect.Right()+nOff2-2, nRightBottom-1 ) ); 880 881 SetLineColor( rStyleSettings.GetDarkShadowColor() ); 882 DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+3-nOff2 ), 883 Point( aRect.Right()+nOff2-1, nRightBottom-1 ) ); 884 } 885 } 886 else 887 { 888 SetLineColor( Color( COL_BLACK ) ); 889 DrawPixel( Point( aRect.Left()+1-nOff2, aRect.Top()+1-nOff2 ) ); 890 DrawPixel( Point( aRect.Right()+nOff2-2, aRect.Top()+1-nOff2 ) ); 891 if ( bLeftBorder ) 892 { 893 DrawLine( Point( aRect.Left()-nOff2, aRect.Top()+2-nOff2 ), 894 Point( aRect.Left()-nOff2, nLeftBottom-1 ) ); 895 } 896 DrawLine( Point( aRect.Left()+2-nOff2, aRect.Top()-nOff2 ), 897 Point( aRect.Right()-3, aRect.Top()-nOff2 ) ); 898 if ( bRightBorder ) 899 { 900 DrawLine( Point( aRect.Right()+nOff2-1, aRect.Top()+2-nOff2 ), 901 Point( aRect.Right()+nOff2-1, nRightBottom-1 ) ); 902 } 903 } 904 } 905 906 if( bLayout ) 907 { 908 int nLine = mpControlData->mpLayoutData->m_aLineIndices.size(); 909 mpControlData->mpLayoutData->m_aLineIndices.push_back( mpControlData->mpLayoutData->m_aDisplayText.Len() ); 910 mpTabCtrlData->maLayoutPageIdToLine[ (int)pItem->mnId ] = nLine; 911 mpTabCtrlData->maLayoutLineToPageId[ nLine ] = (int)pItem->mnId; 912 mpTabCtrlData->maTabRectangles.push_back( aRect ); 913 } 914 915 // set font accordingly, current item is painted bold 916 // we set the font attributes always before drawing to be re-entrant (DrawNativeControl may trigger additional paints) 917 Font aFont( GetFont() ); 918 aFont.SetTransparent( sal_True ); 919 aFont.SetWeight( ((bIsCurrentItem) && (!ImplGetSVData()->maNWFData.mbNoBoldTabFocus)) ? WEIGHT_BOLD : WEIGHT_LIGHT ); 920 SetFont( aFont ); 921 922 Size aTabSize = aRect.GetSize(); 923 Size aImageSize( 0, 0 ); 924 long nTextHeight = GetTextHeight(); 925 long nTextWidth = GetCtrlTextWidth( pItem->maFormatText ); 926 if( !! pItem->maTabImage ) 927 { 928 aImageSize = pItem->maTabImage.GetSizePixel(); 929 if( pItem->maFormatText.Len() ) 930 aImageSize.Width() += GetTextHeight()/4; 931 } 932 long nXPos = aRect.Left()+((aTabSize.Width()-nTextWidth-aImageSize.Width())/2)-nOff-nOff3; 933 long nYPos = aRect.Top()+((aTabSize.Height()-nTextHeight)/2)-nOff3; 934 if( pItem->maFormatText.Len() ) 935 { 936 sal_uInt16 nStyle = TEXT_DRAW_MNEMONIC; 937 if( ! pItem->mbEnabled ) 938 nStyle |= TEXT_DRAW_DISABLE; 939 DrawCtrlText( Point( nXPos + aImageSize.Width(), nYPos ), 940 pItem->maFormatText, 941 0, STRING_LEN, nStyle, 942 bLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL, 943 bLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL 944 ); 945 } 946 947 if( !! pItem->maTabImage ) 948 { 949 Point aImgTL( nXPos, aRect.Top() ); 950 if( aImageSize.Height() < aRect.GetHeight() ) 951 aImgTL.Y() += (aRect.GetHeight() - aImageSize.Height())/2; 952 DrawImage( aImgTL, pItem->maTabImage, pItem->mbEnabled ? 0 : IMAGE_DRAW_DISABLE ); 953 } 954 } 955 956 // ----------------------------------------------------------------------- 957 958 long TabControl::ImplHandleKeyEvent( const KeyEvent& rKeyEvent ) 959 { 960 long nRet = 0; 961 962 if ( GetPageCount() > 1 ) 963 { 964 KeyCode aKeyCode = rKeyEvent.GetKeyCode(); 965 sal_uInt16 nKeyCode = aKeyCode.GetCode(); 966 967 if ( aKeyCode.IsMod1() ) 968 { 969 if ( aKeyCode.IsShift() || (nKeyCode == KEY_PAGEUP) ) 970 { 971 if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEUP) ) 972 { 973 ImplActivateTabPage( sal_False ); 974 nRet = 1; 975 } 976 } 977 else 978 { 979 if ( (nKeyCode == KEY_TAB) || (nKeyCode == KEY_PAGEDOWN) ) 980 { 981 ImplActivateTabPage( sal_True ); 982 nRet = 1; 983 } 984 } 985 } 986 } 987 988 return nRet; 989 } 990 991 992 // ----------------------------------------------------------------------- 993 994 IMPL_LINK( TabControl, ImplListBoxSelectHdl, ListBox*, EMPTYARG ) 995 { 996 SelectTabPage( GetPageId( mpTabCtrlData->mpListBox->GetSelectEntryPos() ) ); 997 return 0; 998 } 999 1000 // ----------------------------------------------------------------------- 1001 1002 IMPL_LINK( TabControl, ImplWindowEventListener, VclSimpleEvent*, pEvent ) 1003 { 1004 if ( pEvent && pEvent->ISA( VclWindowEvent ) && (pEvent->GetId() == VCLEVENT_WINDOW_KEYINPUT) ) 1005 { 1006 VclWindowEvent* pWindowEvent = static_cast< VclWindowEvent* >(pEvent); 1007 // Do not handle events from TabControl or it's children, which is done in Notify(), where the events can be consumed. 1008 if ( !IsWindowOrChild( pWindowEvent->GetWindow() ) ) 1009 { 1010 KeyEvent* pKeyEvent = static_cast< KeyEvent* >(pWindowEvent->GetData()); 1011 ImplHandleKeyEvent( *pKeyEvent ); 1012 } 1013 } 1014 return 0; 1015 } 1016 1017 1018 // ----------------------------------------------------------------------- 1019 1020 void TabControl::MouseButtonDown( const MouseEvent& rMEvt ) 1021 { 1022 if( mpTabCtrlData->mpListBox == NULL ) 1023 { 1024 if( rMEvt.IsLeft() ) 1025 { 1026 sal_uInt16 nPageId = GetPageId( rMEvt.GetPosPixel() ); 1027 ImplTabItem* pItem = ImplGetItem( nPageId ); 1028 if( pItem && pItem->mbEnabled ) 1029 SelectTabPage( nPageId ); 1030 } 1031 } 1032 } 1033 1034 // ----------------------------------------------------------------------- 1035 1036 void TabControl::KeyInput( const KeyEvent& rKEvt ) 1037 { 1038 if( mpTabCtrlData->mpListBox ) 1039 mpTabCtrlData->mpListBox->KeyInput( rKEvt ); 1040 else if ( GetPageCount() > 1 ) 1041 { 1042 KeyCode aKeyCode = rKEvt.GetKeyCode(); 1043 sal_uInt16 nKeyCode = aKeyCode.GetCode(); 1044 1045 if ( (nKeyCode == KEY_LEFT) || (nKeyCode == KEY_RIGHT) ) 1046 { 1047 sal_Bool bNext = (nKeyCode == KEY_RIGHT); 1048 ImplActivateTabPage( bNext ); 1049 } 1050 } 1051 1052 Control::KeyInput( rKEvt ); 1053 } 1054 1055 // ----------------------------------------------------------------------- 1056 1057 void TabControl::Paint( const Rectangle& rRect ) 1058 { 1059 ImplPaint( rRect, false ); 1060 } 1061 1062 // ----------------------------------------------------------------------- 1063 1064 void TabControl::ImplPaint( const Rectangle& rRect, bool bLayout ) 1065 { 1066 if( ! bLayout ) 1067 HideFocus(); 1068 1069 // Hier wird gegebenenfalls auch neu formatiert 1070 Rectangle aRect = ImplGetTabRect( TAB_PAGERECT ); 1071 1072 // find current item 1073 ImplTabItem* pCurItem = NULL; 1074 for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); 1075 it != mpTabCtrlData->maItemList.end(); ++it ) 1076 { 1077 if ( it->mnId == mnCurPageId ) 1078 { 1079 pCurItem = &(*it); 1080 break; 1081 } 1082 } 1083 1084 // Draw the TabPage border 1085 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 1086 Rectangle aCurRect; 1087 long nTopOff = 1; 1088 aRect.Left() -= TAB_OFFSET; 1089 aRect.Top() -= TAB_OFFSET; 1090 aRect.Right() += TAB_OFFSET; 1091 aRect.Bottom() += TAB_OFFSET; 1092 1093 // if we have an invisible tabpage or no tabpage at all the tabpage rect should be 1094 // increased to avoid round corners that might be drawn by a theme 1095 // in this case we're only interested in the top border of the tabpage because the tabitems are used 1096 // standalone (eg impress) 1097 sal_Bool bNoTabPage = sal_False; 1098 TabPage* pCurPage = (pCurItem) ? pCurItem->mpTabPage : NULL; 1099 if( !pCurPage || !pCurPage->IsVisible() ) 1100 { 1101 bNoTabPage = sal_True; 1102 aRect.Left()-=10; 1103 aRect.Right()+=10; 1104 } 1105 1106 sal_Bool bNativeOK = sal_False; 1107 if( ! bLayout && (bNativeOK = IsNativeControlSupported( CTRL_TAB_PANE, PART_ENTIRE_CONTROL) ) == sal_True ) 1108 { 1109 const ImplControlValue aControlValue; 1110 1111 ControlState nState = CTRL_STATE_ENABLED; 1112 int part = PART_ENTIRE_CONTROL; 1113 if ( !IsEnabled() ) 1114 nState &= ~CTRL_STATE_ENABLED; 1115 if ( HasFocus() ) 1116 nState |= CTRL_STATE_FOCUSED; 1117 1118 Region aClipRgn( GetActiveClipRegion() ); 1119 aClipRgn.Intersect( aRect ); 1120 if( !rRect.IsEmpty() ) 1121 aClipRgn.Intersect( rRect ); 1122 1123 if( !aClipRgn.IsEmpty() ) 1124 bNativeOK = DrawNativeControl( CTRL_TAB_PANE, part, aRect, nState, 1125 aControlValue, rtl::OUString() ); 1126 } 1127 else 1128 { 1129 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) 1130 SetLineColor( rStyleSettings.GetLightColor() ); 1131 else 1132 SetLineColor( Color( COL_BLACK ) ); 1133 if ( pCurItem && !pCurItem->maRect.IsEmpty() ) 1134 { 1135 aCurRect = pCurItem->maRect; 1136 if( ! bLayout ) 1137 DrawLine( aRect.TopLeft(), Point( aCurRect.Left()-2, aRect.Top() ) ); 1138 if ( aCurRect.Right()+1 < aRect.Right() ) 1139 { 1140 if( ! bLayout ) 1141 DrawLine( Point( aCurRect.Right(), aRect.Top() ), aRect.TopRight() ); 1142 } 1143 else 1144 nTopOff = 0; 1145 } 1146 else 1147 if( ! bLayout ) 1148 DrawLine( aRect.TopLeft(), aRect.TopRight() ); 1149 1150 if( ! bLayout ) 1151 { 1152 DrawLine( aRect.TopLeft(), aRect.BottomLeft() ); 1153 1154 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) 1155 { 1156 // if we have not tab page the bottom line of the tab page 1157 // directly touches the tab items, so choose a color that fits seamlessly 1158 if( bNoTabPage ) 1159 SetLineColor( rStyleSettings.GetDialogColor() ); 1160 else 1161 SetLineColor( rStyleSettings.GetShadowColor() ); 1162 DrawLine( Point( 1, aRect.Bottom()-1 ), 1163 Point( aRect.Right()-1, aRect.Bottom()-1 ) ); 1164 DrawLine( Point( aRect.Right()-1, aRect.Top()+nTopOff ), 1165 Point( aRect.Right()-1, aRect.Bottom()-1 ) ); 1166 if( bNoTabPage ) 1167 SetLineColor( rStyleSettings.GetDialogColor() ); 1168 else 1169 SetLineColor( rStyleSettings.GetDarkShadowColor() ); 1170 DrawLine( Point( 0, aRect.Bottom() ), 1171 Point( aRect.Right(), aRect.Bottom() ) ); 1172 DrawLine( Point( aRect.Right(), aRect.Top()+nTopOff ), 1173 Point( aRect.Right(), aRect.Bottom() ) ); 1174 } 1175 else 1176 { 1177 DrawLine( aRect.TopRight(), aRect.BottomRight() ); 1178 DrawLine( aRect.BottomLeft(), aRect.BottomRight() ); 1179 } 1180 } 1181 } 1182 1183 if ( !mpTabCtrlData->maItemList.empty() && mpTabCtrlData->mpListBox == NULL ) 1184 { 1185 // Some native toolkits (GTK+) draw tabs right-to-left, with an 1186 // overlap between adjacent tabs 1187 bool bDrawTabsRTL = IsNativeControlSupported( CTRL_TAB_ITEM, PART_TABS_DRAW_RTL ); 1188 ImplTabItem * pFirstTab = NULL; 1189 ImplTabItem * pLastTab = NULL; 1190 size_t idx; 1191 1192 // Event though there is a tab overlap with GTK+, the first tab is not 1193 // overlapped on the left side. Other tookits ignore this option. 1194 if ( bDrawTabsRTL ) 1195 { 1196 pFirstTab = &mpTabCtrlData->maItemList.front(); 1197 pLastTab = &mpTabCtrlData->maItemList.back(); 1198 idx = mpTabCtrlData->maItemList.size()-1; 1199 } 1200 else 1201 { 1202 pLastTab = &mpTabCtrlData->maItemList.back(); 1203 pFirstTab = &mpTabCtrlData->maItemList.front(); 1204 idx = 0; 1205 } 1206 1207 while ( idx < mpTabCtrlData->maItemList.size() ) 1208 { 1209 ImplTabItem* pItem = &mpTabCtrlData->maItemList[idx]; 1210 if ( pItem != pCurItem ) 1211 { 1212 Region aClipRgn( GetActiveClipRegion() ); 1213 aClipRgn.Intersect( pItem->maRect ); 1214 if( !rRect.IsEmpty() ) 1215 aClipRgn.Intersect( rRect ); 1216 if( bLayout || !aClipRgn.IsEmpty() ) 1217 ImplDrawItem( pItem, aCurRect, bLayout, (pItem==pFirstTab), (pItem==pLastTab), sal_False ); 1218 } 1219 1220 if ( bDrawTabsRTL ) 1221 idx--; 1222 else 1223 idx++; 1224 } 1225 1226 if ( pCurItem ) 1227 { 1228 Region aClipRgn( GetActiveClipRegion() ); 1229 aClipRgn.Intersect( pCurItem->maRect ); 1230 if( !rRect.IsEmpty() ) 1231 aClipRgn.Intersect( rRect ); 1232 if( bLayout || !aClipRgn.IsEmpty() ) 1233 ImplDrawItem( pCurItem, aCurRect, bLayout, (pCurItem==pFirstTab), (pCurItem==pLastTab), sal_True ); 1234 } 1235 } 1236 1237 if ( !bLayout && HasFocus() ) 1238 ImplShowFocus(); 1239 1240 if( ! bLayout ) 1241 mbSmallInvalidate = sal_True; 1242 } 1243 1244 // ----------------------------------------------------------------------- 1245 1246 void TabControl::Resize() 1247 { 1248 ImplFreeLayoutData(); 1249 1250 if ( !IsReallyShown() ) 1251 return; 1252 1253 if( mpTabCtrlData->mpListBox ) 1254 { 1255 // get the listbox' preferred size 1256 Size aTabCtrlSize( GetSizePixel() ); 1257 long nPrefWidth = mpTabCtrlData->mpListBox->GetOptimalSize( WINDOWSIZE_PREFERRED ).Width(); 1258 if( nPrefWidth > aTabCtrlSize.Width() ) 1259 nPrefWidth = aTabCtrlSize.Width(); 1260 Size aNewSize( nPrefWidth, LogicToPixel( Size( 12, 12 ), MapMode( MAP_APPFONT ) ).Height() ); 1261 Point aNewPos( (aTabCtrlSize.Width() - nPrefWidth) / 2, 0 ); 1262 mpTabCtrlData->mpListBox->SetPosSizePixel( aNewPos, aNewSize ); 1263 } 1264 1265 mbFormat = sal_True; 1266 1267 // Aktuelle TabPage resizen/positionieren 1268 sal_Bool bTabPage = ImplPosCurTabPage(); 1269 // Feststellen, was invalidiert werden muss 1270 Size aNewSize = Control::GetOutputSizePixel(); 1271 long nNewWidth = aNewSize.Width(); 1272 for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); 1273 it != mpTabCtrlData->maItemList.end(); ++it ) 1274 { 1275 if ( !it->mbFullVisible || 1276 (it->maRect.Right()-2 >= nNewWidth) ) 1277 { 1278 mbSmallInvalidate = sal_False; 1279 break; 1280 } 1281 } 1282 1283 if ( mbSmallInvalidate ) 1284 { 1285 Rectangle aRect = ImplGetTabRect( TAB_PAGERECT ); 1286 aRect.Left() -= TAB_OFFSET+TAB_BORDER_LEFT; 1287 aRect.Top() -= TAB_OFFSET+TAB_BORDER_TOP; 1288 aRect.Right() += TAB_OFFSET+TAB_BORDER_RIGHT; 1289 aRect.Bottom() += TAB_OFFSET+TAB_BORDER_BOTTOM; 1290 if ( bTabPage ) 1291 Invalidate( aRect, INVALIDATE_NOCHILDREN ); 1292 else 1293 Invalidate( aRect ); 1294 1295 } 1296 else 1297 { 1298 if ( bTabPage ) 1299 Invalidate( INVALIDATE_NOCHILDREN ); 1300 else 1301 Invalidate(); 1302 } 1303 } 1304 1305 // ----------------------------------------------------------------------- 1306 1307 void TabControl::GetFocus() 1308 { 1309 if( ! mpTabCtrlData->mpListBox ) 1310 { 1311 ImplShowFocus(); 1312 SetInputContext( InputContext( GetFont() ) ); 1313 } 1314 else 1315 { 1316 if( mpTabCtrlData->mpListBox->IsReallyVisible() ) 1317 mpTabCtrlData->mpListBox->GrabFocus(); 1318 } 1319 Control::GetFocus(); 1320 } 1321 1322 // ----------------------------------------------------------------------- 1323 1324 void TabControl::LoseFocus() 1325 { 1326 if( ! mpTabCtrlData->mpListBox ) 1327 HideFocus(); 1328 Control::LoseFocus(); 1329 } 1330 1331 // ----------------------------------------------------------------------- 1332 1333 void TabControl::RequestHelp( const HelpEvent& rHEvt ) 1334 { 1335 sal_uInt16 nItemId = rHEvt.KeyboardActivated() ? mnCurPageId : GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ); 1336 1337 if ( nItemId ) 1338 { 1339 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 1340 { 1341 XubString aStr = GetHelpText( nItemId ); 1342 if ( aStr.Len() ) 1343 { 1344 Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) ); 1345 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); 1346 aItemRect.Left() = aPt.X(); 1347 aItemRect.Top() = aPt.Y(); 1348 aPt = OutputToScreenPixel( aItemRect.BottomRight() ); 1349 aItemRect.Right() = aPt.X(); 1350 aItemRect.Bottom() = aPt.Y(); 1351 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr ); 1352 return; 1353 } 1354 } 1355 else if ( rHEvt.GetMode() & HELPMODE_EXTENDED ) 1356 { 1357 rtl::OUString aHelpId( rtl::OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) ); 1358 if ( aHelpId.getLength() ) 1359 { 1360 // Wenn eine Hilfe existiert, dann ausloesen 1361 Help* pHelp = Application::GetHelp(); 1362 if ( pHelp ) 1363 pHelp->Start( aHelpId, this ); 1364 return; 1365 } 1366 } 1367 1368 // Bei Quick- oder Balloon-Help zeigen wir den Text an, 1369 // wenn dieser abgeschnitten ist 1370 if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) ) 1371 { 1372 ImplTabItem* pItem = ImplGetItem( nItemId ); 1373 const XubString& rStr = pItem->maText; 1374 if ( rStr != pItem->maFormatText ) 1375 { 1376 Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) ); 1377 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); 1378 aItemRect.Left() = aPt.X(); 1379 aItemRect.Top() = aPt.Y(); 1380 aPt = OutputToScreenPixel( aItemRect.BottomRight() ); 1381 aItemRect.Right() = aPt.X(); 1382 aItemRect.Bottom() = aPt.Y(); 1383 if ( rStr.Len() ) 1384 { 1385 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 1386 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, rStr ); 1387 else 1388 Help::ShowQuickHelp( this, aItemRect, rStr ); 1389 return; 1390 } 1391 } 1392 } 1393 1394 if ( rHEvt.GetMode() & HELPMODE_QUICK ) 1395 { 1396 ImplTabItem* pItem = ImplGetItem( nItemId ); 1397 const XubString& rHelpText = pItem->maHelpText; 1398 // show tooltip if not text but image is set and helptext is available 1399 if ( rHelpText.Len() > 0 && pItem->maText.Len() == 0 && !!pItem->maTabImage ) 1400 { 1401 Rectangle aItemRect = ImplGetTabRect( GetPagePos( nItemId ) ); 1402 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); 1403 aItemRect.Left() = aPt.X(); 1404 aItemRect.Top() = aPt.Y(); 1405 aPt = OutputToScreenPixel( aItemRect.BottomRight() ); 1406 aItemRect.Right() = aPt.X(); 1407 aItemRect.Bottom() = aPt.Y(); 1408 Help::ShowQuickHelp( this, aItemRect, rHelpText ); 1409 return; 1410 } 1411 } 1412 } 1413 1414 Control::RequestHelp( rHEvt ); 1415 } 1416 1417 // ----------------------------------------------------------------------- 1418 1419 void TabControl::Command( const CommandEvent& rCEvt ) 1420 { 1421 if( (mpTabCtrlData->mpListBox == NULL) && (rCEvt.GetCommand() == COMMAND_CONTEXTMENU) && (GetPageCount() > 1) ) 1422 { 1423 Point aMenuPos; 1424 sal_Bool bMenu; 1425 if ( rCEvt.IsMouseEvent() ) 1426 { 1427 aMenuPos = rCEvt.GetMousePosPixel(); 1428 bMenu = GetPageId( aMenuPos ) != 0; 1429 } 1430 else 1431 { 1432 aMenuPos = ImplGetTabRect( GetPagePos( mnCurPageId ) ).Center(); 1433 bMenu = sal_True; 1434 } 1435 1436 if ( bMenu ) 1437 { 1438 PopupMenu aMenu; 1439 for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); 1440 it != mpTabCtrlData->maItemList.end(); ++it ) 1441 { 1442 aMenu.InsertItem( it->mnId, it->maText, MIB_CHECKABLE | MIB_RADIOCHECK ); 1443 if ( it->mnId == mnCurPageId ) 1444 aMenu.CheckItem( it->mnId ); 1445 aMenu.SetHelpId( it->mnId, it->maHelpId ); 1446 } 1447 1448 sal_uInt16 nId = aMenu.Execute( this, aMenuPos ); 1449 if ( nId && (nId != mnCurPageId) ) 1450 SelectTabPage( nId ); 1451 return; 1452 } 1453 } 1454 1455 Control::Command( rCEvt ); 1456 } 1457 1458 // ----------------------------------------------------------------------- 1459 1460 void TabControl::StateChanged( StateChangedType nType ) 1461 { 1462 Control::StateChanged( nType ); 1463 1464 if ( nType == STATE_CHANGE_INITSHOW ) 1465 { 1466 ImplPosCurTabPage(); 1467 if( mpTabCtrlData->mpListBox ) 1468 Resize(); 1469 } 1470 else if ( nType == STATE_CHANGE_UPDATEMODE ) 1471 { 1472 if ( IsUpdateMode() ) 1473 Invalidate(); 1474 } 1475 else if ( (nType == STATE_CHANGE_ZOOM) || 1476 (nType == STATE_CHANGE_CONTROLFONT) ) 1477 { 1478 ImplInitSettings( sal_True, sal_False, sal_False ); 1479 Invalidate(); 1480 } 1481 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 1482 { 1483 ImplInitSettings( sal_False, sal_True, sal_False ); 1484 Invalidate(); 1485 } 1486 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 1487 { 1488 ImplInitSettings( sal_False, sal_False, sal_True ); 1489 Invalidate(); 1490 } 1491 } 1492 1493 // ----------------------------------------------------------------------- 1494 1495 void TabControl::DataChanged( const DataChangedEvent& rDCEvt ) 1496 { 1497 Control::DataChanged( rDCEvt ); 1498 1499 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || 1500 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || 1501 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && 1502 (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) 1503 { 1504 ImplInitSettings( sal_True, sal_True, sal_True ); 1505 Invalidate(); 1506 } 1507 } 1508 1509 // ----------------------------------------------------------------------- 1510 1511 Rectangle* TabControl::ImplFindPartRect( const Point& rPt ) 1512 { 1513 ImplTabItem* pFoundItem = NULL; 1514 int nFound = 0; 1515 for( std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin(); 1516 it != mpTabCtrlData->maItemList.end(); ++it ) 1517 { 1518 if ( it->maRect.IsInside( rPt ) ) 1519 { 1520 // assure that only one tab is highlighted at a time 1521 nFound++; 1522 pFoundItem = &(*it); 1523 } 1524 } 1525 // assure that only one tab is highlighted at a time 1526 return nFound == 1 ? &pFoundItem->maRect : NULL; 1527 } 1528 1529 long TabControl::PreNotify( NotifyEvent& rNEvt ) 1530 { 1531 long nDone = 0; 1532 const MouseEvent* pMouseEvt = NULL; 1533 1534 if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL ) 1535 { 1536 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() ) 1537 { 1538 // trigger redraw if mouse over state has changed 1539 if( IsNativeControlSupported(CTRL_TAB_ITEM, PART_ENTIRE_CONTROL) ) 1540 { 1541 Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); 1542 Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() ); 1543 if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) ) 1544 { 1545 Region aClipRgn; 1546 if( pLastRect ) 1547 { 1548 // allow for slightly bigger tabitems 1549 // as used by gtk 1550 // TODO: query for the correct sizes 1551 Rectangle aRect(*pLastRect); 1552 aRect.nLeft-=2; 1553 aRect.nRight+=2; 1554 aRect.nTop-=3; 1555 aClipRgn.Union( aRect ); 1556 } 1557 if( pRect ) 1558 { 1559 // allow for slightly bigger tabitems 1560 // as used by gtk 1561 // TODO: query for the correct sizes 1562 Rectangle aRect(*pRect); 1563 aRect.nLeft-=2; 1564 aRect.nRight+=2; 1565 aRect.nTop-=3; 1566 aClipRgn.Union( aRect ); 1567 } 1568 if( !aClipRgn.IsEmpty() ) 1569 Invalidate( aClipRgn ); 1570 } 1571 } 1572 } 1573 } 1574 1575 return nDone ? nDone : Control::PreNotify(rNEvt); 1576 } 1577 1578 // ----------------------------------------------------------------------- 1579 1580 long TabControl::Notify( NotifyEvent& rNEvt ) 1581 { 1582 long nRet = 0; 1583 1584 if ( rNEvt.GetType() == EVENT_KEYINPUT ) 1585 nRet = ImplHandleKeyEvent( *rNEvt.GetKeyEvent() ); 1586 1587 return nRet ? nRet : Control::Notify( rNEvt ); 1588 } 1589 1590 // ----------------------------------------------------------------------- 1591 1592 void TabControl::ActivatePage() 1593 { 1594 maActivateHdl.Call( this ); 1595 } 1596 1597 // ----------------------------------------------------------------------- 1598 1599 long TabControl::DeactivatePage() 1600 { 1601 if ( maDeactivateHdl.IsSet() ) 1602 return maDeactivateHdl.Call( this ); 1603 else 1604 return sal_True; 1605 } 1606 1607 // ----------------------------------------------------------------------- 1608 1609 void TabControl::SetTabPageSizePixel( const Size& rSize ) 1610 { 1611 ImplFreeLayoutData(); 1612 1613 Size aNewSize( rSize ); 1614 aNewSize.Width() += TAB_OFFSET*2; 1615 Rectangle aRect = ImplGetTabRect( TAB_PAGERECT, 1616 aNewSize.Width(), aNewSize.Height() ); 1617 aNewSize.Height() += aRect.Top()+TAB_OFFSET; 1618 Window::SetOutputSizePixel( aNewSize ); 1619 } 1620 1621 // ----------------------------------------------------------------------- 1622 1623 Size TabControl::GetTabPageSizePixel() const 1624 { 1625 Rectangle aRect = ((TabControl*)this)->ImplGetTabRect( TAB_PAGERECT ); 1626 return aRect.GetSize(); 1627 } 1628 1629 // ----------------------------------------------------------------------- 1630 1631 void TabControl::InsertPage( const ResId& rResId, sal_uInt16 nPos ) 1632 { 1633 GetRes( rResId.SetRT( RSC_TABCONTROLITEM ) ); 1634 1635 sal_uLong nObjMask = ReadLongRes(); 1636 sal_uInt16 nItemId = 1; 1637 1638 // ID 1639 if ( nObjMask & RSC_TABCONTROLITEM_ID ) 1640 nItemId = sal::static_int_cast<sal_uInt16>(ReadLongRes()); 1641 1642 // Text 1643 XubString aTmpStr; 1644 if( nObjMask & RSC_TABCONTROLITEM_TEXT ) 1645 aTmpStr = ReadStringRes(); 1646 InsertPage( nItemId, aTmpStr, nPos ); 1647 1648 // PageResID 1649 if ( nObjMask & RSC_TABCONTROLITEM_PAGERESID ) 1650 { 1651 ImplTabItem& rItem = mpTabCtrlData->maItemList[ GetPagePos( nItemId ) ]; 1652 rItem.mnTabPageResId = sal::static_int_cast<sal_uInt16>(ReadLongRes()); 1653 } 1654 } 1655 1656 // ----------------------------------------------------------------------- 1657 1658 void TabControl::InsertPage( sal_uInt16 nPageId, const XubString& rText, 1659 sal_uInt16 nPos ) 1660 { 1661 DBG_ASSERT( nPageId, "TabControl::InsertPage(): PageId == 0" ); 1662 DBG_ASSERT( GetPagePos( nPageId ) == TAB_PAGE_NOTFOUND, 1663 "TabControl::InsertPage(): PageId already exists" ); 1664 1665 // insert new page item 1666 ImplTabItem* pItem = NULL; 1667 if( nPos == TAB_APPEND || size_t(nPos) >= mpTabCtrlData->maItemList.size() ) 1668 { 1669 mpTabCtrlData->maItemList.push_back( ImplTabItem() ); 1670 pItem = &mpTabCtrlData->maItemList.back(); 1671 if( mpTabCtrlData->mpListBox ) 1672 mpTabCtrlData->mpListBox->InsertEntry( rText ); 1673 } 1674 else 1675 { 1676 std::vector< ImplTabItem >::iterator new_it = 1677 mpTabCtrlData->maItemList.insert( mpTabCtrlData->maItemList.begin() + nPos, ImplTabItem() ); 1678 pItem = &(*new_it); 1679 if( mpTabCtrlData->mpListBox ) 1680 mpTabCtrlData->mpListBox->InsertEntry( rText, nPos); 1681 } 1682 if( mpTabCtrlData->mpListBox ) 1683 { 1684 if( ! mnCurPageId ) 1685 mpTabCtrlData->mpListBox->SelectEntryPos( 0 ); 1686 mpTabCtrlData->mpListBox->SetDropDownLineCount( mpTabCtrlData->mpListBox->GetEntryCount() ); 1687 } 1688 1689 // set current page id 1690 if ( !mnCurPageId ) 1691 mnCurPageId = nPageId; 1692 1693 // init new page item 1694 pItem->mnId = nPageId; 1695 pItem->mpTabPage = NULL; 1696 pItem->mnTabPageResId = 0; 1697 pItem->maText = rText; 1698 pItem->mbFullVisible = sal_False; 1699 1700 mbFormat = sal_True; 1701 if ( IsUpdateMode() ) 1702 Invalidate(); 1703 1704 ImplFreeLayoutData(); 1705 if( mpTabCtrlData->mpListBox ) // reposition/resize listbox 1706 Resize(); 1707 1708 ImplCallEventListeners( VCLEVENT_TABPAGE_INSERTED, (void*) (sal_uLong)nPageId ); 1709 } 1710 1711 // ----------------------------------------------------------------------- 1712 1713 void TabControl::RemovePage( sal_uInt16 nPageId ) 1714 { 1715 sal_uInt16 nPos = GetPagePos( nPageId ); 1716 1717 // does the item exist ? 1718 if ( nPos != TAB_PAGE_NOTFOUND ) 1719 { 1720 //remove page item 1721 std::vector< ImplTabItem >::iterator it = mpTabCtrlData->maItemList.begin() + nPos; 1722 bool bIsCurrentPage = (it->mnId == mnCurPageId); 1723 mpTabCtrlData->maItemList.erase( it ); 1724 if( mpTabCtrlData->mpListBox ) 1725 { 1726 mpTabCtrlData->mpListBox->RemoveEntry( nPos ); 1727 mpTabCtrlData->mpListBox->SetDropDownLineCount( mpTabCtrlData->mpListBox->GetEntryCount() ); 1728 } 1729 1730 // If current page is removed, than first page gets the current page 1731 if ( bIsCurrentPage ) 1732 { 1733 mnCurPageId = 0; 1734 1735 if( ! mpTabCtrlData->maItemList.empty() ) 1736 { 1737 // don't do this by simply setting mnCurPageId to pFirstItem->mnId 1738 // this leaves a lot of stuff (such trivias as _showing_ the new current page) undone 1739 // instead, call SetCurPageId 1740 // without this, the next (outside) call to SetCurPageId with the id of the first page 1741 // will result in doing nothing (as we assume that nothing changed, then), and the page 1742 // will never be shown. 1743 // 86875 - 05/11/2001 - frank.schoenheit@germany.sun.com 1744 1745 SetCurPageId( mpTabCtrlData->maItemList[0].mnId ); 1746 } 1747 } 1748 1749 mbFormat = sal_True; 1750 if ( IsUpdateMode() ) 1751 Invalidate(); 1752 1753 ImplFreeLayoutData(); 1754 1755 ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVED, (void*) (sal_uLong) nPageId ); 1756 } 1757 } 1758 1759 // ----------------------------------------------------------------------- 1760 1761 void TabControl::Clear() 1762 { 1763 // clear item list 1764 mpTabCtrlData->maItemList.clear(); 1765 mnCurPageId = 0; 1766 if( mpTabCtrlData->mpListBox ) 1767 mpTabCtrlData->mpListBox->Clear(); 1768 1769 ImplFreeLayoutData(); 1770 1771 mbFormat = sal_True; 1772 if ( IsUpdateMode() ) 1773 Invalidate(); 1774 1775 ImplCallEventListeners( VCLEVENT_TABPAGE_REMOVEDALL ); 1776 } 1777 1778 // ----------------------------------------------------------------------- 1779 1780 void TabControl::EnablePage( sal_uInt16 i_nPageId, bool i_bEnable ) 1781 { 1782 ImplTabItem* pItem = ImplGetItem( i_nPageId ); 1783 1784 if ( pItem && pItem->mbEnabled != i_bEnable ) 1785 { 1786 pItem->mbEnabled = i_bEnable; 1787 mbFormat = sal_True; 1788 if( mpTabCtrlData->mpListBox ) 1789 mpTabCtrlData->mpListBox->SetEntryFlags( GetPagePos( i_nPageId ), 1790 i_bEnable ? 0 : (LISTBOX_ENTRY_FLAG_DISABLE_SELECTION | LISTBOX_ENTRY_FLAG_DRAW_DISABLED) ); 1791 if( pItem->mnId == mnCurPageId ) 1792 { 1793 // SetCurPageId will change to an enabled page 1794 SetCurPageId( mnCurPageId ); 1795 } 1796 else if ( IsUpdateMode() ) 1797 Invalidate(); 1798 } 1799 } 1800 1801 // ----------------------------------------------------------------------- 1802 1803 sal_uInt16 TabControl::GetPageCount() const 1804 { 1805 return (sal_uInt16)mpTabCtrlData->maItemList.size(); 1806 } 1807 1808 // ----------------------------------------------------------------------- 1809 1810 sal_uInt16 TabControl::GetPageId( sal_uInt16 nPos ) const 1811 { 1812 if( size_t(nPos) < mpTabCtrlData->maItemList.size() ) 1813 return mpTabCtrlData->maItemList[ nPos ].mnId; 1814 return 0; 1815 } 1816 1817 // ----------------------------------------------------------------------- 1818 1819 sal_uInt16 TabControl::GetPagePos( sal_uInt16 nPageId ) const 1820 { 1821 for( std::vector< ImplTabItem >::const_iterator it = mpTabCtrlData->maItemList.begin(); 1822 it != mpTabCtrlData->maItemList.end(); ++it ) 1823 { 1824 if ( it->mnId == nPageId ) 1825 return (sal_uInt16)(it - mpTabCtrlData->maItemList.begin()); 1826 } 1827 1828 return TAB_PAGE_NOTFOUND; 1829 } 1830 1831 // ----------------------------------------------------------------------- 1832 1833 sal_uInt16 TabControl::GetPageId( const Point& rPos ) const 1834 { 1835 for( size_t i = 0; i < mpTabCtrlData->maItemList.size(); ++i ) 1836 { 1837 if ( ((TabControl*)this)->ImplGetTabRect( static_cast<sal_uInt16>(i) ).IsInside( rPos ) ) 1838 return mpTabCtrlData->maItemList[ i ].mnId; 1839 } 1840 1841 return 0; 1842 } 1843 1844 // ----------------------------------------------------------------------- 1845 1846 void TabControl::SetCurPageId( sal_uInt16 nPageId ) 1847 { 1848 sal_uInt16 nPos = GetPagePos( nPageId ); 1849 while( nPos != TAB_PAGE_NOTFOUND && 1850 ! mpTabCtrlData->maItemList[nPos].mbEnabled ) 1851 { 1852 nPos++; 1853 if( size_t(nPos) >= mpTabCtrlData->maItemList.size() ) 1854 nPos = 0; 1855 if( mpTabCtrlData->maItemList[nPos].mnId == nPageId ) 1856 break; 1857 } 1858 1859 if( nPos != TAB_PAGE_NOTFOUND ) 1860 { 1861 nPageId = mpTabCtrlData->maItemList[nPos].mnId; 1862 if ( nPageId == mnCurPageId ) 1863 { 1864 if ( mnActPageId ) 1865 mnActPageId = nPageId; 1866 return; 1867 } 1868 1869 if ( mnActPageId ) 1870 mnActPageId = nPageId; 1871 else 1872 { 1873 mbFormat = sal_True; 1874 sal_uInt16 nOldId = mnCurPageId; 1875 mnCurPageId = nPageId; 1876 ImplChangeTabPage( nPageId, nOldId ); 1877 } 1878 } 1879 } 1880 1881 // ----------------------------------------------------------------------- 1882 1883 sal_uInt16 TabControl::GetCurPageId() const 1884 { 1885 if ( mnActPageId ) 1886 return mnActPageId; 1887 else 1888 return mnCurPageId; 1889 } 1890 1891 // ----------------------------------------------------------------------- 1892 1893 void TabControl::SelectTabPage( sal_uInt16 nPageId ) 1894 { 1895 if ( nPageId && (nPageId != mnCurPageId) ) 1896 { 1897 ImplFreeLayoutData(); 1898 1899 ImplCallEventListeners( VCLEVENT_TABPAGE_DEACTIVATE, (void*) (sal_uLong) mnCurPageId ); 1900 if ( DeactivatePage() ) 1901 { 1902 mnActPageId = nPageId; 1903 ActivatePage(); 1904 // Page koennte im Activate-Handler umgeschaltet wurden sein 1905 nPageId = mnActPageId; 1906 mnActPageId = 0; 1907 SetCurPageId( nPageId ); 1908 if( mpTabCtrlData->mpListBox ) 1909 mpTabCtrlData->mpListBox->SelectEntryPos( GetPagePos( nPageId ) ); 1910 ImplCallEventListeners( VCLEVENT_TABPAGE_ACTIVATE, (void*) (sal_uLong) nPageId ); 1911 } 1912 } 1913 } 1914 1915 // ----------------------------------------------------------------------- 1916 1917 void TabControl::SetTabPage( sal_uInt16 nPageId, TabPage* pTabPage ) 1918 { 1919 ImplTabItem* pItem = ImplGetItem( nPageId ); 1920 1921 if ( pItem && (pItem->mpTabPage != pTabPage) ) 1922 { 1923 if ( pTabPage ) 1924 { 1925 DBG_ASSERT( !pTabPage->IsVisible(), "TabControl::SetTabPage() - Page is visible" ); 1926 1927 if ( IsDefaultSize() ) 1928 SetTabPageSizePixel( pTabPage->GetSizePixel() ); 1929 1930 // Erst hier setzen, damit Resize nicht TabPage umpositioniert 1931 pItem->mpTabPage = pTabPage; 1932 if ( pItem->mnId == mnCurPageId ) 1933 ImplChangeTabPage( pItem->mnId, 0 ); 1934 } 1935 else 1936 pItem->mpTabPage = NULL; 1937 } 1938 } 1939 1940 // ----------------------------------------------------------------------- 1941 1942 TabPage* TabControl::GetTabPage( sal_uInt16 nPageId ) const 1943 { 1944 ImplTabItem* pItem = ImplGetItem( nPageId ); 1945 1946 if ( pItem ) 1947 return pItem->mpTabPage; 1948 else 1949 return NULL; 1950 } 1951 1952 // ----------------------------------------------------------------------- 1953 1954 sal_uInt16 TabControl::GetTabPageResId( sal_uInt16 nPageId ) const 1955 { 1956 ImplTabItem* pItem = ImplGetItem( nPageId ); 1957 1958 if ( pItem ) 1959 return pItem->mnTabPageResId; 1960 else 1961 return 0; 1962 } 1963 1964 // ----------------------------------------------------------------------- 1965 1966 void TabControl::SetPageText( sal_uInt16 nPageId, const XubString& rText ) 1967 { 1968 ImplTabItem* pItem = ImplGetItem( nPageId ); 1969 1970 if ( pItem && pItem->maText != rText ) 1971 { 1972 pItem->maText = rText; 1973 mbFormat = sal_True; 1974 if( mpTabCtrlData->mpListBox ) 1975 { 1976 sal_uInt16 nPos = GetPagePos( nPageId ); 1977 mpTabCtrlData->mpListBox->RemoveEntry( nPos ); 1978 mpTabCtrlData->mpListBox->InsertEntry( rText, nPos ); 1979 } 1980 if ( IsUpdateMode() ) 1981 Invalidate(); 1982 ImplFreeLayoutData(); 1983 ImplCallEventListeners( VCLEVENT_TABPAGE_PAGETEXTCHANGED, (void*) (sal_uLong) nPageId ); 1984 } 1985 } 1986 1987 // ----------------------------------------------------------------------- 1988 1989 XubString TabControl::GetPageText( sal_uInt16 nPageId ) const 1990 { 1991 ImplTabItem* pItem = ImplGetItem( nPageId ); 1992 1993 if ( pItem ) 1994 return pItem->maText; 1995 else 1996 return ImplGetSVEmptyStr(); 1997 } 1998 1999 // ----------------------------------------------------------------------- 2000 2001 void TabControl::SetHelpText( sal_uInt16 nPageId, const XubString& rText ) 2002 { 2003 ImplTabItem* pItem = ImplGetItem( nPageId ); 2004 2005 if ( pItem ) 2006 pItem->maHelpText = rText; 2007 } 2008 2009 // ----------------------------------------------------------------------- 2010 2011 const XubString& TabControl::GetHelpText( sal_uInt16 nPageId ) const 2012 { 2013 ImplTabItem* pItem = ImplGetItem( nPageId ); 2014 2015 if ( pItem ) 2016 { 2017 if ( !pItem->maHelpText.Len() && pItem->maHelpId.getLength() ) 2018 { 2019 Help* pHelp = Application::GetHelp(); 2020 if ( pHelp ) 2021 pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this ); 2022 } 2023 2024 return pItem->maHelpText; 2025 } 2026 else 2027 return ImplGetSVEmptyStr(); 2028 } 2029 2030 // ----------------------------------------------------------------------- 2031 2032 void TabControl::SetHelpId( sal_uInt16 nPageId, const rtl::OString& rHelpId ) 2033 { 2034 ImplTabItem* pItem = ImplGetItem( nPageId ); 2035 2036 if ( pItem ) 2037 pItem->maHelpId = rHelpId; 2038 } 2039 2040 // ----------------------------------------------------------------------- 2041 2042 rtl::OString TabControl::GetHelpId( sal_uInt16 nPageId ) const 2043 { 2044 rtl::OString aRet; 2045 ImplTabItem* pItem = ImplGetItem( nPageId ); 2046 2047 if ( pItem ) 2048 aRet = pItem->maHelpId; 2049 2050 return aRet; 2051 } 2052 2053 // ----------------------------------------------------------------------- 2054 2055 void TabControl::SetPageImage( sal_uInt16 i_nPageId, const Image& i_rImage ) 2056 { 2057 ImplTabItem* pItem = ImplGetItem( i_nPageId ); 2058 2059 if ( pItem ) 2060 { 2061 pItem->maTabImage = i_rImage; 2062 mbFormat = sal_True; 2063 if ( IsUpdateMode() ) 2064 Invalidate(); 2065 } 2066 } 2067 2068 // ----------------------------------------------------------------------- 2069 2070 const Image* TabControl::GetPageImage( sal_uInt16 i_nPageId ) const 2071 { 2072 const ImplTabItem* pItem = ImplGetItem( i_nPageId ); 2073 return pItem ? &pItem->maTabImage : NULL; 2074 } 2075 2076 // ----------------------------------------------------------------------- 2077 2078 Rectangle TabControl::GetCharacterBounds( sal_uInt16 nPageId, long nIndex ) const 2079 { 2080 Rectangle aRet; 2081 2082 if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() ) 2083 FillLayoutData(); 2084 2085 if( HasLayoutData() ) 2086 { 2087 std::hash_map< int, int >::const_iterator it = mpTabCtrlData->maLayoutPageIdToLine.find( (int)nPageId ); 2088 if( it != mpTabCtrlData->maLayoutPageIdToLine.end() ) 2089 { 2090 Pair aPair = mpControlData->mpLayoutData->GetLineStartEnd( it->second ); 2091 if( (aPair.B() - aPair.A()) >= nIndex ) 2092 aRet = mpControlData->mpLayoutData->GetCharacterBounds( aPair.A() + nIndex ); 2093 } 2094 } 2095 2096 return aRet; 2097 } 2098 2099 // ----------------------------------------------------------------------- 2100 2101 long TabControl::GetIndexForPoint( const Point& rPoint, sal_uInt16& rPageId ) const 2102 { 2103 long nRet = -1; 2104 2105 if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() ) 2106 FillLayoutData(); 2107 2108 if( HasLayoutData() ) 2109 { 2110 int nIndex = mpControlData->mpLayoutData->GetIndexForPoint( rPoint ); 2111 if( nIndex != -1 ) 2112 { 2113 // what line (->pageid) is this index in ? 2114 int nLines = mpControlData->mpLayoutData->GetLineCount(); 2115 int nLine = -1; 2116 while( ++nLine < nLines ) 2117 { 2118 Pair aPair = mpControlData->mpLayoutData->GetLineStartEnd( nLine ); 2119 if( aPair.A() <= nIndex && aPair.B() >= nIndex ) 2120 { 2121 nRet = nIndex - aPair.A(); 2122 rPageId = (sal_uInt16)mpTabCtrlData->maLayoutLineToPageId[ nLine ]; 2123 break; 2124 } 2125 } 2126 } 2127 } 2128 2129 return nRet; 2130 } 2131 2132 // ----------------------------------------------------------------------- 2133 2134 void TabControl::FillLayoutData() const 2135 { 2136 mpTabCtrlData->maLayoutLineToPageId.clear(); 2137 mpTabCtrlData->maLayoutPageIdToLine.clear(); 2138 const_cast<TabControl*>(this)->ImplPaint( Rectangle(), true ); 2139 } 2140 2141 // ----------------------------------------------------------------------- 2142 2143 Rectangle TabControl::GetTabPageBounds( sal_uInt16 nPage ) const 2144 { 2145 Rectangle aRet; 2146 2147 if( !HasLayoutData() || ! mpTabCtrlData->maLayoutPageIdToLine.size() ) 2148 FillLayoutData(); 2149 2150 if( HasLayoutData() ) 2151 { 2152 std::hash_map< int, int >::const_iterator it = mpTabCtrlData->maLayoutPageIdToLine.find( (int)nPage ); 2153 if( it != mpTabCtrlData->maLayoutPageIdToLine.end() ) 2154 { 2155 if( it->second >= 0 && it->second < static_cast<int>(mpTabCtrlData->maTabRectangles.size()) ) 2156 { 2157 aRet = mpTabCtrlData->maTabRectangles[ it->second ]; 2158 aRet.Union( const_cast<TabControl*>(this)->ImplGetTabRect( TAB_PAGERECT ) ); 2159 } 2160 } 2161 } 2162 2163 return aRet; 2164 } 2165 2166 // ----------------------------------------------------------------------- 2167 2168 Rectangle TabControl::GetTabBounds( sal_uInt16 nPageId ) const 2169 { 2170 Rectangle aRet; 2171 2172 ImplTabItem* pItem = ImplGetItem( nPageId ); 2173 if(pItem) 2174 aRet = pItem->maRect; 2175 2176 return aRet; 2177 } 2178 2179 // ----------------------------------------------------------------------- 2180 2181 void TabControl::SetItemsOffset( const Point& rOffs ) 2182 { 2183 if( mpTabCtrlData ) 2184 mpTabCtrlData->maItemsOffset = rOffs; 2185 } 2186 2187 Point TabControl::GetItemsOffset() const 2188 { 2189 if( mpTabCtrlData ) 2190 return mpTabCtrlData->maItemsOffset; 2191 else 2192 return Point(); 2193 } 2194 2195 // ----------------------------------------------------------------------- 2196 2197 Size TabControl::GetOptimalSize(WindowSizeType eType) const 2198 { 2199 switch (eType) { 2200 case WINDOWSIZE_MINIMUM: 2201 return mpTabCtrlData ? mpTabCtrlData->maMinSize : Size(); 2202 default: 2203 return Control::GetOptimalSize( eType ); 2204 } 2205 } 2206 2207 // ----------------------------------------------------------------------- 2208 2209 void TabControl::SetMinimumSizePixel( const Size& i_rSize ) 2210 { 2211 if( mpTabCtrlData ) 2212 mpTabCtrlData->maMinSize = i_rSize; 2213 } 2214 2215 // ----------------------------------------------------------------------- 2216 2217 2218