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