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