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_svtools.hxx" 24 25 #include <svtools/tabbar.hxx> 26 #include <tools/time.hxx> 27 #include <tools/debug.hxx> 28 #include <tools/poly.hxx> 29 #include <vcl/svapp.hxx> 30 #include <vcl/help.hxx> 31 #include <vcl/decoview.hxx> 32 #include <vcl/button.hxx> 33 #include <vcl/edit.hxx> 34 #include "svtaccessiblefactory.hxx" 35 #include <filectrl.hrc> 36 #include <svtools/svtdata.hxx> 37 #include <limits> 38 39 // ======================================================================= 40 41 #define TABBAR_OFFSET_X 7 42 #define TABBAR_OFFSET_X2 2 43 #define TABBAR_DRAG_SCROLLOFF 5 44 #define TABBAR_MINSIZE 5 45 46 const sal_uInt16 ADDNEWPAGE_AREAWIDTH = 10; 47 48 // ======================================================================= 49 50 struct ImplTabBarItem 51 { 52 sal_uInt16 mnId; 53 TabBarPageBits mnBits; 54 XubString maText; 55 XubString maHelpText; 56 Rectangle maRect; 57 long mnWidth; 58 rtl::OString maHelpId; 59 sal_Bool mbShort; 60 sal_Bool mbSelect; 61 sal_Bool mbEnable; 62 Color maTabBgColor; 63 bool IsDefaultTabBgColor() const { return maTabBgColor == Color(COL_AUTO) ? sal_True : sal_False; }; 64 Color maTabTextColor; 65 bool IsDefaultTabTextColor() const { return maTabTextColor == Color(COL_AUTO) ? sal_True : sal_False; }; 66 67 ImplTabBarItem( sal_uInt16 nItemId, const XubString& rText, 68 TabBarPageBits nPageBits ) : 69 maText( rText ) 70 { 71 mnId = nItemId; 72 mnBits = nPageBits; 73 mnWidth = 0; 74 mbShort = sal_False; 75 mbSelect = sal_False; 76 mbEnable = sal_True; 77 maTabBgColor = Color( COL_AUTO ); 78 maTabTextColor = Color( COL_AUTO ); 79 } 80 }; 81 82 DECLARE_LIST( ImplTabBarList, ImplTabBarItem* ) 83 84 // ======================================================================= 85 86 // ----------------- 87 // - ImplTabButton - 88 // ----------------- 89 90 class ImplTabButton : public PushButton 91 { 92 public: 93 ImplTabButton( TabBar* pParent, WinBits nWinStyle = 0 ) : 94 PushButton( pParent, nWinStyle | WB_RECTSTYLE | WB_SMALLSTYLE | WB_NOLIGHTBORDER | WB_NOPOINTERFOCUS ) {} 95 96 TabBar* GetParent() const { return (TabBar*)Window::GetParent(); } 97 98 virtual long PreNotify( NotifyEvent& rNEvt ); 99 }; 100 101 // ======================================================================= 102 103 long ImplTabButton::PreNotify( NotifyEvent& rNEvt ) 104 { 105 if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN ) 106 { 107 if ( GetParent()->IsInEditMode() ) 108 { 109 GetParent()->EndEditMode(); 110 return sal_True; 111 } 112 } 113 114 return PushButton::PreNotify( rNEvt ); 115 } 116 117 // ======================================================================= 118 119 // ---------------- 120 // - ImplTabSizer - 121 // ---------------- 122 123 class ImplTabSizer : public Window 124 { 125 public: 126 ImplTabSizer( TabBar* pParent, WinBits nWinStyle = 0 ); 127 128 TabBar* GetParent() const { return (TabBar*)Window::GetParent(); } 129 130 private: 131 void ImplTrack( const Point& rScreenPos ); 132 133 virtual void MouseButtonDown( const MouseEvent& rMEvt ); 134 virtual void Tracking( const TrackingEvent& rTEvt ); 135 virtual void Paint( const Rectangle& rRect ); 136 137 Point maStartPos; 138 long mnStartWidth; 139 }; 140 141 // ----------------------------------------------------------------------- 142 143 ImplTabSizer::ImplTabSizer( TabBar* pParent, WinBits nWinStyle ) : 144 Window( pParent, nWinStyle & WB_3DLOOK ) 145 { 146 SetPointer( Pointer( POINTER_HSIZEBAR ) ); 147 SetSizePixel( Size( 7, 0 ) ); 148 } 149 150 // ----------------------------------------------------------------------- 151 152 void ImplTabSizer::ImplTrack( const Point& rScreenPos ) 153 { 154 TabBar* pParent = GetParent(); 155 long nDiff = rScreenPos.X() - maStartPos.X(); 156 pParent->mnSplitSize = mnStartWidth + (pParent->IsMirrored() ? -nDiff : nDiff); 157 if ( pParent->mnSplitSize < TABBAR_MINSIZE ) 158 pParent->mnSplitSize = TABBAR_MINSIZE; 159 pParent->Split(); 160 pParent->Update(); 161 } 162 163 // ----------------------------------------------------------------------- 164 165 void ImplTabSizer::MouseButtonDown( const MouseEvent& rMEvt ) 166 { 167 if ( GetParent()->IsInEditMode() ) 168 { 169 GetParent()->EndEditMode(); 170 return; 171 } 172 173 if ( rMEvt.IsLeft() ) 174 { 175 maStartPos = OutputToScreenPixel( rMEvt.GetPosPixel() ); 176 mnStartWidth = GetParent()->GetSizePixel().Width(); 177 StartTracking(); 178 } 179 } 180 181 // ----------------------------------------------------------------------- 182 183 void ImplTabSizer::Tracking( const TrackingEvent& rTEvt ) 184 { 185 if ( rTEvt.IsTrackingEnded() ) 186 { 187 if ( rTEvt.IsTrackingCanceled() ) 188 ImplTrack( maStartPos ); 189 GetParent()->mnSplitSize = 0; 190 } 191 else 192 ImplTrack( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) ); 193 } 194 195 // ----------------------------------------------------------------------- 196 197 void ImplTabSizer::Paint( const Rectangle& ) 198 { 199 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 200 DecorationView aDecoView( this ); 201 long nOffX = 0; 202 Size aOutputSize = GetOutputSizePixel(); 203 204 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) 205 { 206 SetLineColor( rStyleSettings.GetDarkShadowColor() ); 207 DrawLine( Point( 0, 0 ), Point( 0, aOutputSize.Height()-1 ) ); 208 nOffX++; 209 aOutputSize.Width()--; 210 } 211 aDecoView.DrawButton( Rectangle( Point( nOffX, 0 ), aOutputSize ), BUTTON_DRAW_NOLIGHTBORDER ); 212 } 213 214 // ======================================================================= 215 216 // Heißt nicht Impl, da evtl. mal von außen benutz- und überladbar 217 218 // -------------- 219 // - TabBarEdit - 220 // -------------- 221 222 class TabBarEdit : public Edit 223 { 224 private: 225 Timer maLoseFocusTimer; 226 sal_Bool mbPostEvt; 227 228 DECL_LINK( ImplEndEditHdl, void* ); 229 DECL_LINK( ImplEndTimerHdl, void* ); 230 231 public: 232 TabBarEdit( TabBar* pParent, WinBits nWinStyle = 0 ); 233 234 TabBar* GetParent() const { return (TabBar*)Window::GetParent(); } 235 236 void SetPostEvent() { mbPostEvt = sal_True; } 237 void ResetPostEvent() { mbPostEvt = sal_False; } 238 239 virtual long PreNotify( NotifyEvent& rNEvt ); 240 virtual void LoseFocus(); 241 }; 242 243 // ----------------------------------------------------------------------- 244 245 TabBarEdit::TabBarEdit( TabBar* pParent, WinBits nWinStyle ) : 246 Edit( pParent, nWinStyle ) 247 { 248 mbPostEvt = sal_False; 249 } 250 251 // ----------------------------------------------------------------------- 252 253 long TabBarEdit::PreNotify( NotifyEvent& rNEvt ) 254 { 255 if ( rNEvt.GetType() == EVENT_KEYINPUT ) 256 { 257 const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); 258 if ( !pKEvt->GetKeyCode().GetModifier() ) 259 { 260 if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN ) 261 { 262 if ( !mbPostEvt ) 263 { 264 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) ) 265 mbPostEvt = sal_True; 266 } 267 return sal_True; 268 } 269 else if ( pKEvt->GetKeyCode().GetCode() == KEY_ESCAPE ) 270 { 271 if ( !mbPostEvt ) 272 { 273 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_True ) ) 274 mbPostEvt = sal_True; 275 } 276 return sal_True; 277 } 278 } 279 } 280 281 return Edit::PreNotify( rNEvt ); 282 } 283 284 // ----------------------------------------------------------------------- 285 286 void TabBarEdit::LoseFocus() 287 { 288 if ( !mbPostEvt ) 289 { 290 if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) ) 291 mbPostEvt = sal_True; 292 } 293 294 Edit::LoseFocus(); 295 } 296 297 // ----------------------------------------------------------------------- 298 299 IMPL_LINK( TabBarEdit, ImplEndEditHdl, void*, pCancel ) 300 { 301 ResetPostEvent(); 302 maLoseFocusTimer.Stop(); 303 304 // We need this query, because the edit gets a LoseFocus event, 305 // when it shows the context menu or the insert symbol dialog 306 if ( !HasFocus() && HasChildPathFocus( sal_True ) ) 307 { 308 maLoseFocusTimer.SetTimeout( 30 ); 309 maLoseFocusTimer.SetTimeoutHdl( LINK( this, TabBarEdit, ImplEndTimerHdl ) ); 310 maLoseFocusTimer.Start(); 311 } 312 else 313 GetParent()->EndEditMode( pCancel != 0 ); 314 315 return 0; 316 } 317 318 // ----------------------------------------------------------------------- 319 320 IMPL_LINK( TabBarEdit, ImplEndTimerHdl, void*, EMPTYARG ) 321 { 322 if ( HasFocus() ) 323 return 0; 324 325 // We need this query, because the edit gets a LoseFocus event, 326 // when it shows the context menu or the insert symbol dialog 327 if ( HasChildPathFocus( sal_True ) ) 328 maLoseFocusTimer.Start(); 329 else 330 GetParent()->EndEditMode( sal_True ); 331 332 return 0; 333 } 334 335 // ======================================================================= 336 struct TabBar_Impl 337 { 338 ImplTabSizer* mpSizer; 339 ::svt::AccessibleFactoryAccess maAccessibleFactory; 340 341 TabBar_Impl() 342 :mpSizer( NULL ) 343 { 344 } 345 ~TabBar_Impl() 346 { 347 delete mpSizer; 348 } 349 }; 350 351 // ======================================================================= 352 353 const sal_uInt16 TabBar::APPEND = ::std::numeric_limits<sal_uInt16>::max(); 354 const sal_uInt16 TabBar::PAGE_NOT_FOUND = ::std::numeric_limits<sal_uInt16>::max(); 355 356 void TabBar::ImplInit( WinBits nWinStyle ) 357 { 358 mpItemList = new ImplTabBarList; 359 mpFirstBtn = NULL; 360 mpPrevBtn = NULL; 361 mpNextBtn = NULL; 362 mpLastBtn = NULL; 363 mpImpl = new TabBar_Impl; 364 mpEdit = NULL; 365 mnMaxPageWidth = 0; 366 mnCurMaxWidth = 0; 367 mnOffX = 0; 368 mnOffY = 0; 369 mnLastOffX = 0; 370 mnSplitSize = 0; 371 mnSwitchTime = 0; 372 mnWinStyle = nWinStyle; 373 mnCurPageId = 0; 374 mnFirstPos = 0; 375 mnDropPos = 0; 376 mnSwitchId = 0; 377 mnEditId = 0; 378 mbFormat = sal_True; 379 mbFirstFormat = sal_True; 380 mbSizeFormat = sal_True; 381 mbAutoMaxWidth = sal_True; 382 mbInSwitching = sal_False; 383 mbAutoEditMode = sal_False; 384 mbEditCanceled = sal_False; 385 mbDropPos = sal_False; 386 mbInSelect = sal_False; 387 mbSelColor = sal_False; 388 mbSelTextColor = sal_False; 389 mbMirrored = sal_False; 390 391 ImplInitControls(); 392 393 if(mpFirstBtn) 394 mpFirstBtn->SetAccessibleName(String(SvtResId(STR_TABBAR_PUSHBUTTON_MOVET0HOME))); 395 if(mpPrevBtn) 396 mpPrevBtn->SetAccessibleName( String(SvtResId(STR_TABBAR_PUSHBUTTON_MOVELEFT))); 397 if(mpNextBtn) 398 mpNextBtn->SetAccessibleName(String(SvtResId(STR_TABBAR_PUSHBUTTON_MOVERIGHT))); 399 if(mpLastBtn) 400 mpLastBtn->SetAccessibleName( String(SvtResId(STR_TABBAR_PUSHBUTTON_MOVETOEND))); 401 402 SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) ); 403 ImplInitSettings( sal_True, sal_True ); 404 } 405 406 // ----------------------------------------------------------------------- 407 408 TabBar::TabBar( Window* pParent, WinBits nWinStyle ) : 409 Window( pParent, (nWinStyle & WB_3DLOOK) | WB_CLIPCHILDREN ) 410 { 411 ImplInit( nWinStyle ); 412 } 413 414 // ----------------------------------------------------------------------- 415 416 TabBar::~TabBar() 417 { 418 EndEditMode( sal_True ); 419 420 // Delete Controls 421 if ( mpPrevBtn ) 422 delete mpPrevBtn; 423 if ( mpNextBtn ) 424 delete mpNextBtn; 425 if ( mpFirstBtn ) 426 delete mpFirstBtn; 427 if ( mpLastBtn ) 428 delete mpLastBtn; 429 delete mpImpl; 430 431 // Delete all Items 432 ImplTabBarItem* pItem = mpItemList->First(); 433 while ( pItem ) 434 { 435 delete pItem; 436 pItem = mpItemList->Next(); 437 } 438 439 // Delete Itemlist 440 delete mpItemList; 441 } 442 443 // ----------------------------------------------------------------------- 444 445 void TabBar::ImplInitSettings( sal_Bool bFont, sal_Bool bBackground ) 446 { 447 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 448 449 if ( bFont ) 450 { 451 Font aToolFont; 452 aToolFont = rStyleSettings.GetToolFont(); 453 if ( IsControlFont() ) 454 aToolFont.Merge( GetControlFont() ); 455 aToolFont.SetWeight( WEIGHT_BOLD ); 456 SetZoomedPointFont( aToolFont ); 457 458 // Font in der Größe Anpassen, wenn Fenster zu klein? 459 while ( GetTextHeight() > (GetOutputSizePixel().Height()-1) ) 460 { 461 Font aFont = GetFont(); 462 if ( aFont.GetHeight() <= 6 ) 463 break; 464 aFont.SetHeight( aFont.GetHeight()-1 ); 465 SetFont( aFont ); 466 } 467 } 468 469 if ( bBackground ) 470 { 471 Color aColor; 472 if ( IsControlBackground() ) 473 aColor = GetControlBackground(); 474 else 475 aColor = rStyleSettings.GetFaceColor(); 476 SetBackground( aColor ); 477 } 478 } 479 480 // ----------------------------------------------------------------------- 481 482 void TabBar::ImplGetColors( Color& rFaceColor, Color& rFaceTextColor, 483 Color& rSelectColor, Color& rSelectTextColor ) 484 { 485 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 486 487 if ( IsControlBackground() ) 488 rFaceColor = GetControlBackground(); 489 else 490 rFaceColor = rStyleSettings.GetInactiveTabColor(); 491 if ( IsControlForeground() ) 492 rFaceTextColor = GetControlForeground(); 493 else 494 rFaceTextColor = rStyleSettings.GetButtonTextColor(); 495 if ( mbSelColor ) 496 rSelectColor = maSelColor; 497 else 498 rSelectColor = rStyleSettings.GetActiveTabColor(); 499 if ( mbSelTextColor ) 500 rSelectTextColor = maSelTextColor; 501 else 502 rSelectTextColor = rStyleSettings.GetWindowTextColor(); 503 } 504 505 // ----------------------------------------------------------------------- 506 507 sal_Bool TabBar::ImplCalcWidth() 508 { 509 // Größen müssen nur ermittelt werden, wenn sich Text ändert oder 510 // wenn der Font geändert wurde 511 if ( !mbSizeFormat ) 512 return sal_False; 513 514 // Breiten der Tabs mit dem fetten Font ermitteln 515 Font aFont = GetFont(); 516 if ( aFont.GetWeight() != WEIGHT_BOLD ) 517 { 518 aFont.SetWeight( WEIGHT_BOLD ); 519 SetFont( aFont ); 520 } 521 522 if ( mnMaxPageWidth ) 523 mnCurMaxWidth = mnMaxPageWidth; 524 else if ( mbAutoMaxWidth ) 525 { 526 mnCurMaxWidth = mnLastOffX-mnOffX- 527 TABBAR_OFFSET_X-TABBAR_OFFSET_X- 528 TABBAR_OFFSET_X2-TABBAR_OFFSET_X2-TABBAR_OFFSET_X2; 529 if ( mnCurMaxWidth < 1 ) 530 mnCurMaxWidth = 1; 531 } 532 else 533 mnCurMaxWidth = 0; 534 535 sal_Bool bChanged = sal_False; 536 ImplTabBarItem* pItem = mpItemList->First(); 537 while ( pItem ) 538 { 539 long nNewWidth = GetTextWidth( pItem->maText ); 540 if ( mnCurMaxWidth && (nNewWidth > mnCurMaxWidth) ) 541 { 542 pItem->mbShort = sal_True; 543 nNewWidth = mnCurMaxWidth; 544 } 545 else 546 pItem->mbShort = sal_False; 547 nNewWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2; 548 if ( pItem->mnWidth != nNewWidth ) 549 { 550 pItem->mnWidth = nNewWidth; 551 if ( !pItem->maRect.IsEmpty() ) 552 bChanged = sal_True; 553 } 554 pItem = mpItemList->Next(); 555 } 556 mbSizeFormat = sal_False; 557 mbFormat = sal_True; 558 return bChanged; 559 } 560 561 // ----------------------------------------------------------------------- 562 563 void TabBar::ImplFormat() 564 { 565 ImplCalcWidth(); 566 567 if ( !mbFormat ) 568 return; 569 570 sal_uInt16 n = 0; 571 long x = mnOffX; 572 ImplTabBarItem* pItem = mpItemList->First(); 573 while ( pItem ) 574 { 575 // Bei allen nicht sichtbaren Tabs, wird ein leeres Rechteck 576 // gesetzt 577 if ( (n+1 < mnFirstPos) || (x > mnLastOffX) ) 578 pItem->maRect.SetEmpty(); 579 else 580 { 581 // Etwas von der Tab vor der ersten sichtbaren Page 582 // muss auch zu sehen sein 583 if ( n+1 == mnFirstPos ) 584 pItem->maRect.Left() = x-pItem->mnWidth; 585 else 586 { 587 pItem->maRect.Left() = x; 588 x += pItem->mnWidth; 589 } 590 pItem->maRect.Right() = x+TABBAR_OFFSET_X+TABBAR_OFFSET_X2; 591 pItem->maRect.Bottom() = maWinSize.Height()-1; 592 593 if( mbMirrored ) 594 { 595 long nTmp = mnOffX + mnLastOffX - pItem->maRect.Right(); 596 pItem->maRect.Right() = mnOffX + mnLastOffX - pItem->maRect.Left(); 597 pItem->maRect.Left() = nTmp; 598 } 599 } 600 601 n++; 602 pItem = mpItemList->Next(); 603 } 604 605 mbFormat = sal_False; 606 607 // Button enablen/disablen 608 ImplEnableControls(); 609 } 610 611 // ----------------------------------------------------------------------- 612 613 sal_uInt16 TabBar::ImplGetLastFirstPos() 614 { 615 sal_uInt16 nCount = (sal_uInt16)(mpItemList->Count()); 616 if ( !nCount || mbSizeFormat || mbFormat ) 617 return 0; 618 619 sal_uInt16 nLastFirstPos = nCount-1; 620 long nWinWidth = mnLastOffX-mnOffX-TABBAR_OFFSET_X-ADDNEWPAGE_AREAWIDTH; 621 long nWidth = mpItemList->GetObject( nLastFirstPos )->mnWidth; 622 while ( nLastFirstPos && (nWidth < nWinWidth) ) 623 { 624 nLastFirstPos--; 625 nWidth += mpItemList->GetObject( nLastFirstPos )->mnWidth; 626 } 627 if ( (nLastFirstPos != (sal_uInt16)(mpItemList->Count()-1)) && 628 (nWidth > nWinWidth) ) 629 nLastFirstPos++; 630 return nLastFirstPos; 631 } 632 633 // ----------------------------------------------------------------------- 634 635 void TabBar::ImplInitControls() 636 { 637 if ( mnWinStyle & WB_SIZEABLE ) 638 { 639 if ( !mpImpl->mpSizer ) 640 mpImpl->mpSizer = new ImplTabSizer( this, mnWinStyle & (WB_DRAG | WB_3DLOOK) ); 641 mpImpl->mpSizer->Show(); 642 } 643 else 644 { 645 DELETEZ( mpImpl->mpSizer ); 646 } 647 648 Link aLink = LINK( this, TabBar, ImplClickHdl ); 649 650 if ( mnWinStyle & (WB_MINSCROLL | WB_SCROLL) ) 651 { 652 if ( !mpPrevBtn ) 653 { 654 mpPrevBtn = new ImplTabButton( this, WB_REPEAT ); 655 mpPrevBtn->SetClickHdl( aLink ); 656 } 657 mpPrevBtn->SetSymbol( mbMirrored ? SYMBOL_NEXT : SYMBOL_PREV ); 658 mpPrevBtn->Show(); 659 660 if ( !mpNextBtn ) 661 { 662 mpNextBtn = new ImplTabButton( this, WB_REPEAT ); 663 mpNextBtn->SetClickHdl( aLink ); 664 } 665 mpNextBtn->SetSymbol( mbMirrored ? SYMBOL_PREV : SYMBOL_NEXT ); 666 mpNextBtn->Show(); 667 } 668 else 669 { 670 DELETEZ( mpPrevBtn ); 671 DELETEZ( mpNextBtn ); 672 } 673 674 if ( mnWinStyle & WB_SCROLL ) 675 { 676 if ( !mpFirstBtn ) 677 { 678 mpFirstBtn = new ImplTabButton( this ); 679 mpFirstBtn->SetClickHdl( aLink ); 680 } 681 mpFirstBtn->SetSymbol( mbMirrored ? SYMBOL_LAST : SYMBOL_FIRST ); 682 mpFirstBtn->Show(); 683 684 if ( !mpLastBtn ) 685 { 686 mpLastBtn = new ImplTabButton( this ); 687 mpLastBtn->SetClickHdl( aLink ); 688 } 689 mpLastBtn->SetSymbol( mbMirrored ? SYMBOL_FIRST : SYMBOL_LAST ); 690 mpLastBtn->Show(); 691 } 692 else 693 { 694 DELETEZ( mpFirstBtn ); 695 DELETEZ( mpLastBtn ); 696 } 697 } 698 699 // ----------------------------------------------------------------------- 700 701 void TabBar::ImplEnableControls() 702 { 703 if ( mbSizeFormat || mbFormat ) 704 return; 705 706 // Buttons enablen/disablen 707 sal_Bool bEnableBtn = mnFirstPos > 0; 708 if ( mpFirstBtn ) 709 mpFirstBtn->Enable( bEnableBtn ); 710 if ( mpPrevBtn ) 711 mpPrevBtn->Enable( bEnableBtn ); 712 713 bEnableBtn = mnFirstPos < ImplGetLastFirstPos(); 714 if ( mpNextBtn ) 715 mpNextBtn->Enable( bEnableBtn ); 716 if ( mpLastBtn ) 717 mpLastBtn->Enable( bEnableBtn ); 718 } 719 720 // ----------------------------------------------------------------------- 721 722 void TabBar::ImplShowPage( sal_uInt16 nPos ) 723 { 724 // Breite berechnen 725 long nWidth = GetOutputSizePixel().Width(); 726 if ( nWidth >= TABBAR_OFFSET_X ) 727 nWidth -= TABBAR_OFFSET_X; 728 ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); 729 if ( nPos < mnFirstPos ) 730 SetFirstPageId( pItem->mnId ); 731 else if ( pItem->maRect.Right() > nWidth ) 732 { 733 while ( pItem->maRect.Right() > nWidth ) 734 { 735 sal_uInt16 nNewPos = mnFirstPos+1; 736 SetFirstPageId( GetPageId( nNewPos ) ); 737 ImplFormat(); 738 if ( nNewPos != mnFirstPos ) 739 break; 740 } 741 } 742 } 743 744 // ----------------------------------------------------------------------- 745 746 IMPL_LINK( TabBar, ImplClickHdl, ImplTabButton*, pBtn ) 747 { 748 EndEditMode(); 749 750 sal_uInt16 nNewPos = mnFirstPos; 751 752 if ( pBtn == mpFirstBtn ) 753 nNewPos = 0; 754 else if ( pBtn == mpPrevBtn ) 755 { 756 if ( mnFirstPos ) 757 nNewPos = mnFirstPos-1; 758 } 759 else if ( pBtn == mpNextBtn ) 760 { 761 sal_uInt16 nCount = GetPageCount(); 762 if ( mnFirstPos < nCount ) 763 nNewPos = mnFirstPos+1; 764 } 765 else 766 { 767 sal_uInt16 nCount = GetPageCount(); 768 if ( nCount ) 769 nNewPos = nCount-1; 770 } 771 772 if ( nNewPos != mnFirstPos ) 773 SetFirstPageId( GetPageId( nNewPos ) ); 774 return 0; 775 } 776 777 // ----------------------------------------------------------------------- 778 779 void TabBar::MouseMove( const MouseEvent& rMEvt ) 780 { 781 if ( rMEvt.IsLeaveWindow() ) 782 mbInSelect = sal_False; 783 784 Window::MouseMove( rMEvt ); 785 } 786 787 // ----------------------------------------------------------------------- 788 789 void TabBar::MouseButtonDown( const MouseEvent& rMEvt ) 790 { 791 // Bei Klick in unser Fenster EditModus nur beenden und Klick nicht 792 // ausführen 793 if ( IsInEditMode() ) 794 { 795 EndEditMode(); 796 return; 797 } 798 799 ImplTabBarItem* pItem; 800 sal_uInt16 nSelId = GetPageId( rMEvt.GetPosPixel() ); 801 802 if ( !rMEvt.IsLeft() ) 803 { 804 Window::MouseButtonDown( rMEvt ); 805 if ( (nSelId > 0) && (nSelId != mnCurPageId) ) 806 { 807 sal_uInt16 nPos = GetPagePos( nSelId ); 808 pItem = mpItemList->GetObject( nPos ); 809 810 if ( pItem->mbEnable ) 811 { 812 if ( ImplDeactivatePage() ) 813 { 814 SetCurPageId( nSelId ); 815 Update(); 816 ImplActivatePage(); 817 ImplSelect(); 818 } 819 mbInSelect = sal_True; 820 } 821 } 822 return; 823 } 824 825 if ( rMEvt.IsMod2() && mbAutoEditMode && nSelId ) 826 { 827 if ( StartEditMode( nSelId ) ) 828 return; 829 } 830 831 if ( (rMEvt.GetMode() & (MOUSE_MULTISELECT | MOUSE_RANGESELECT)) && (rMEvt.GetClicks() == 1) ) 832 { 833 if ( nSelId ) 834 { 835 sal_uInt16 nPos = GetPagePos( nSelId ); 836 sal_Bool bSelectTab = sal_False; 837 pItem = mpItemList->GetObject( nPos ); 838 839 if ( pItem->mbEnable ) 840 { 841 if ( (rMEvt.GetMode() & MOUSE_MULTISELECT) && (mnWinStyle & WB_MULTISELECT) ) 842 { 843 if ( nSelId != mnCurPageId ) 844 { 845 SelectPage( nSelId, !IsPageSelected( nSelId ) ); 846 bSelectTab = sal_True; 847 } 848 } 849 else if ( mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT) ) 850 { 851 bSelectTab = sal_True; 852 sal_uInt16 n; 853 sal_Bool bSelect; 854 sal_uInt16 nCurPos = GetPagePos( mnCurPageId ); 855 if ( nPos <= nCurPos ) 856 { 857 // Alle Tabs bis zur angeklickten Tab deselektieren 858 // und alle Tabs von der angeklickten Tab bis 859 // zur aktuellen Position selektieren 860 n = 0; 861 while ( n < nCurPos ) 862 { 863 pItem = mpItemList->GetObject( n ); 864 if ( n < nPos ) 865 bSelect = sal_False; 866 else 867 bSelect = sal_True; 868 869 if ( pItem->mbSelect != bSelect ) 870 { 871 pItem->mbSelect = bSelect; 872 if ( !pItem->maRect.IsEmpty() ) 873 Invalidate( pItem->maRect ); 874 } 875 876 n++; 877 } 878 } 879 880 if ( nPos >= nCurPos ) 881 { 882 // Alle Tabs von der aktuellen bis zur angeklickten 883 // Tab selektieren und alle Tabs von der angeklickten 884 // Tab bis zur letzten Tab deselektieren 885 sal_uInt16 nCount = (sal_uInt16)mpItemList->Count(); 886 n = nCurPos; 887 while ( n < nCount ) 888 { 889 pItem = mpItemList->GetObject( n ); 890 891 if ( n <= nPos ) 892 bSelect = sal_True; 893 else 894 bSelect = sal_False; 895 896 if ( pItem->mbSelect != bSelect ) 897 { 898 pItem->mbSelect = bSelect; 899 if ( !pItem->maRect.IsEmpty() ) 900 Invalidate( pItem->maRect ); 901 } 902 903 n++; 904 } 905 } 906 } 907 908 // Gegebenenfalls muss die selektierte Tab gescrollt werden 909 if ( bSelectTab ) 910 { 911 ImplShowPage( nPos ); 912 Update(); 913 ImplSelect(); 914 } 915 } 916 else 917 ImplShowPage( nPos ); 918 mbInSelect = sal_True; 919 920 return; 921 } 922 } 923 else if ( rMEvt.GetClicks() == 2 ) 924 { 925 // Gegebenenfalls den Double-Click-Handler rufen 926 if ( !rMEvt.GetModifier() && (!nSelId || (nSelId == mnCurPageId)) ) 927 { 928 sal_uInt16 nOldCurId = mnCurPageId; 929 mnCurPageId = nSelId; 930 DoubleClick(); 931 // Abfrage, da im DoubleClick-Handler die aktuelle Seite 932 // umgeschaltet werden konnte 933 if ( mnCurPageId == nSelId ) 934 mnCurPageId = nOldCurId; 935 } 936 937 return; 938 } 939 else 940 { 941 if ( nSelId ) 942 { 943 // Nur Select ausführen, wenn noch nicht aktuelle Page 944 if ( nSelId != mnCurPageId ) 945 { 946 sal_uInt16 nPos = GetPagePos( nSelId ); 947 pItem = mpItemList->GetObject( nPos ); 948 949 if ( pItem->mbEnable ) 950 { 951 if ( !pItem->mbSelect ) 952 { 953 // Muss invalidiert werden 954 sal_Bool bUpdate = sal_False; 955 if ( IsReallyVisible() && IsUpdateMode() ) 956 bUpdate = sal_True; 957 958 // Alle selektierten Items deselektieren 959 pItem = mpItemList->First(); 960 while ( pItem ) 961 { 962 if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) ) 963 { 964 pItem->mbSelect = sal_False; 965 if ( bUpdate ) 966 Invalidate( pItem->maRect ); 967 } 968 969 pItem = mpItemList->Next(); 970 } 971 } 972 973 if ( ImplDeactivatePage() ) 974 { 975 SetCurPageId( nSelId ); 976 Update(); 977 ImplActivatePage(); 978 ImplSelect(); 979 } 980 } 981 else 982 ImplShowPage( nPos ); 983 mbInSelect = sal_True; 984 } 985 986 return; 987 } 988 } 989 990 Window::MouseButtonDown( rMEvt ); 991 } 992 993 // ----------------------------------------------------------------------- 994 995 void TabBar::MouseButtonUp( const MouseEvent& rMEvt ) 996 { 997 mbInSelect = sal_False; 998 Window::MouseButtonUp( rMEvt ); 999 } 1000 1001 // ----------------------------------------------------------------------- 1002 1003 void TabBar::Paint( const Rectangle& ) 1004 { 1005 // Items berechnen und ausgeben 1006 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count(); 1007 ImplTabBarItem* pItem; 1008 1009 // kein Item, dann auch nichts zu tun 1010 if ( nItemCount ) 1011 { 1012 // TabBar muss formatiert sein 1013 ImplFormat(); 1014 1015 // Beim ersten Format auch dafür sorgen, dass aktuelle TabPage 1016 // sichtbar wird 1017 if ( mbFirstFormat ) 1018 { 1019 mbFirstFormat = sal_False; 1020 1021 if ( mnCurPageId && (mnFirstPos == 0) && !mbDropPos ) 1022 { 1023 pItem = mpItemList->GetObject( GetPagePos( mnCurPageId ) ); 1024 if ( pItem->maRect.IsEmpty() ) 1025 { 1026 // mbDropPos setzen (bzw. missbrauchen) um Invalidate() 1027 // zu unterbinden 1028 mbDropPos = sal_True; 1029 SetFirstPageId( mnCurPageId ); 1030 mbDropPos = sal_False; 1031 if ( mnFirstPos != 0 ) 1032 ImplFormat(); 1033 } 1034 } 1035 } 1036 } 1037 1038 // Farben ermitteln 1039 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 1040 Color aFaceColor; 1041 Color aSelectColor; 1042 Color aFaceTextColor; 1043 Color aSelectTextColor; 1044 ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor ); 1045 1046 // Font selektieren 1047 Font aFont = GetFont(); 1048 Font aLightFont = aFont; 1049 //aLightFont.SetWeight( WEIGHT_LIGHT ); //TODO Make font weight light on custom color only? 1050 aLightFont.SetWeight( WEIGHT_NORMAL ); 1051 1052 // #i36013# exclude push buttons from painting area 1053 Rectangle aClipRect( Point( mnOffX, 0 ), Point( mnLastOffX, GetOutputHeightPixel() - 1 ) ); 1054 SetClipRegion( Region( aClipRect ) ); 1055 1056 // Bei Border oben und unten einen Strich extra malen 1057 if ( (mnWinStyle & WB_BORDER) ) 1058 { 1059 Size aOutputSize = GetOutputSizePixel(); 1060 1061 // Border malen (Strich oben und Strich unten) 1062 SetLineColor( rStyleSettings.GetDarkShadowColor() ); 1063 DrawLine( Point( mnOffX, mnOffY ), Point( aOutputSize.Width()-1, mnOffY ) ); 1064 } 1065 else 1066 SetLineColor( rStyleSettings.GetDarkShadowColor() ); 1067 1068 // Items ausgeben 1069 if ( nItemCount ) 1070 { 1071 // letzten sichtbaren Eintrag suchen 1072 sal_uInt16 n = mnFirstPos+1; 1073 if ( n >= nItemCount ) 1074 n = nItemCount-1; 1075 pItem = mpItemList->Seek( n ); 1076 while ( pItem ) 1077 { 1078 if ( !pItem->maRect.IsEmpty() ) 1079 { 1080 n++; 1081 pItem = mpItemList->Next(); 1082 } 1083 else 1084 break; 1085 } 1086 1087 // Alle Tabs ausgeben (von hinten nach vorn und aktuellen zuletzt) 1088 if ( pItem ) 1089 n--; 1090 else if ( n >= nItemCount ) 1091 n = nItemCount-1; 1092 pItem = mpItemList->Seek( n ); 1093 ImplTabBarItem* pCurItem = NULL; 1094 while ( pItem ) 1095 { 1096 // CurrentItem als letztes ausgeben, da es alle anderen überdeckt 1097 if ( !pCurItem && (pItem->mnId == mnCurPageId) ) 1098 { 1099 pCurItem = pItem; 1100 pItem = mpItemList->Prev(); 1101 if ( !pItem ) 1102 pItem = pCurItem; 1103 continue; 1104 } 1105 1106 if ( !pItem->maRect.IsEmpty() ) 1107 { 1108 Rectangle aRect = pItem->maRect; 1109 1110 // Aktuelle Page wird mit einem fetten Font ausgegeben 1111 if ( pItem->mnId == mnCurPageId ) 1112 SetFont( aFont ); 1113 else 1114 SetFont( aLightFont ); 1115 1116 // Set the correct FillInBrush depending upon status 1117 if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) ) 1118 { 1119 // Currently selected Tab 1120 SetFillColor( aSelectColor ); 1121 SetTextColor( aSelectTextColor ); 1122 } 1123 else 1124 { 1125 if ( !pItem->IsDefaultTabBgColor() && !rStyleSettings.GetHighContrastMode() ) 1126 { 1127 SetFillColor( pItem->maTabBgColor ); 1128 SetTextColor( pItem->maTabTextColor ); 1129 } else { 1130 SetFillColor( aFaceColor ); 1131 SetTextColor( aFaceTextColor ); 1132 } 1133 } 1134 1135 // Muss Font Kursiv geschaltet werden 1136 if ( pItem->mnBits & TPB_SPECIAL ) 1137 { 1138 SetTextColor( Color( COL_LIGHTBLUE ) ); 1139 } 1140 1141 // Position der Page berechnen 1142 Point aPos0 = Point( aRect.Left(), mnOffY ); 1143 Point aPos1 = Point( aRect.Left()+TABBAR_OFFSET_X, aRect.Bottom() ); 1144 Point aPos2 = Point( aRect.Right()-TABBAR_OFFSET_X, aRect.Bottom() ); 1145 Point aPos3 = Point( aRect.Right(), mnOffY ); 1146 1147 // Zuerst geben wir das Polygon gefüllt aus 1148 Polygon aPoly( 4 ); 1149 aPoly[0] = aPos0; 1150 aPoly[1] = aPos1; 1151 aPoly[2] = aPos2; 1152 aPoly[3] = aPos3; 1153 DrawPolygon( aPoly ); 1154 1155 // Danach den Text zentriert ausgeben 1156 XubString aText = pItem->maText; 1157 if ( pItem->mbShort ) 1158 aText = GetEllipsisString( aText, mnCurMaxWidth, TEXT_DRAW_ENDELLIPSIS ); 1159 Size aRectSize = aRect.GetSize(); 1160 long nTextWidth = GetTextWidth( aText ); 1161 long nTextHeight = GetTextHeight(); 1162 Point aTxtPos( aRect.Left()+(aRectSize.Width()-nTextWidth)/2, 1163 (aRectSize.Height()-nTextHeight)/2 ); 1164 if ( pItem->IsDefaultTabBgColor() || (!pItem->mbSelect) ) 1165 { 1166 if ( !pItem->mbEnable ) 1167 DrawCtrlText( aTxtPos, aText, 0, STRING_LEN, (TEXT_DRAW_DISABLE | TEXT_DRAW_MNEMONIC) ); 1168 else 1169 DrawText( aTxtPos, aText ); 1170 } 1171 1172 // draw a small 2px sliver of the original background color at the bottom of the selected tab 1173 if ( !pItem->IsDefaultTabBgColor() ) 1174 { 1175 if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) || rStyleSettings.GetHighContrastMode() ) { 1176 SetLineColor( pItem->maTabBgColor ); 1177 DrawLine( Point(aPos1.X(), aPos1.Y()-1), Point(aPos2.X(), aPos2.Y()-1) ); 1178 DrawLine( Point(aPos1.X(), aPos1.Y()-2), Point(aPos2.X(), aPos2.Y()-2) ); 1179 if ( !pItem->mbEnable ) 1180 DrawCtrlText( aTxtPos, aText, 0, STRING_LEN, (TEXT_DRAW_DISABLE | TEXT_DRAW_MNEMONIC) ); 1181 else 1182 DrawText( aTxtPos, aText ); 1183 } 1184 } 1185 1186 // Da etwas übermalt werden könnte, müssen wir die Polygonumrandung noch einmal ausgeben 1187 SetLineColor( rStyleSettings.GetDarkShadowColor() ); 1188 SetFillColor(); 1189 DrawPolygon( aPoly ); 1190 1191 // Beim aktuellen Tab die restlichen Ausgaben vornehmen und 1192 // die Schleife abbrechen, da der aktuelle Tab als letztes 1193 // ausgegeben wird 1194 if ( pItem == pCurItem ) 1195 { 1196 // Beim aktuellen Item muss der oberste Strich gelöscht werden 1197 SetLineColor(); 1198 SetFillColor( aSelectColor ); 1199 Rectangle aDelRect( Point(aPos0.X()+1, aPos0.Y()), Point(aPos3.X()-1, aPos3.Y()) ); 1200 DrawRect( aDelRect ); 1201 break; 1202 } 1203 1204 pItem = mpItemList->Prev(); 1205 } 1206 else 1207 { 1208 if ( pItem == pCurItem ) 1209 break; 1210 1211 pItem = NULL; 1212 } 1213 1214 if ( !pItem ) 1215 pItem = pCurItem; 1216 } 1217 } 1218 1219 // Font wieder herstellen 1220 SetFont( aFont ); 1221 // remove clip region 1222 SetClipRegion(); 1223 } 1224 1225 // ----------------------------------------------------------------------- 1226 1227 void TabBar::Resize() 1228 { 1229 Size aNewSize = GetOutputSizePixel(); 1230 1231 long nSizerWidth = 0; 1232 long nButtonWidth = 0; 1233 1234 // Arrange Sizer 1235 if ( mpImpl->mpSizer ) 1236 { 1237 Size aSizerSize = mpImpl->mpSizer->GetSizePixel(); 1238 Point aNewSizerPos( mbMirrored ? 0 : (aNewSize.Width()-aSizerSize.Width()), 0 ); 1239 Size aNewSizerSize( aSizerSize.Width(), aNewSize.Height() ); 1240 mpImpl->mpSizer->SetPosSizePixel( aNewSizerPos, aNewSizerSize ); 1241 nSizerWidth = aSizerSize.Width(); 1242 } 1243 1244 // Scroll-Buttons anordnen 1245 long nHeight = aNewSize.Height(); 1246 // Font in der Größe anpassen? 1247 ImplInitSettings( sal_True, sal_False ); 1248 1249 long nX = mbMirrored ? (aNewSize.Width()-nHeight) : 0; 1250 long nXDiff = mbMirrored ? -nHeight : nHeight; 1251 1252 Size aBtnSize( nHeight, nHeight ); 1253 if ( mpFirstBtn ) 1254 { 1255 mpFirstBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize ); 1256 nX += nXDiff; 1257 nButtonWidth += nHeight; 1258 } 1259 if ( mpPrevBtn ) 1260 { 1261 mpPrevBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize ); 1262 nX += nXDiff; 1263 nButtonWidth += nHeight; 1264 } 1265 if ( mpNextBtn ) 1266 { 1267 mpNextBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize ); 1268 nX += nXDiff; 1269 nButtonWidth += nHeight; 1270 } 1271 if ( mpLastBtn ) 1272 { 1273 mpLastBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize ); 1274 nX += nXDiff; 1275 nButtonWidth += nHeight; 1276 } 1277 1278 // Größe merken 1279 maWinSize = aNewSize; 1280 1281 if( mbMirrored ) 1282 { 1283 mnOffX = nSizerWidth; 1284 mnLastOffX = maWinSize.Width() - nButtonWidth - 1; 1285 } 1286 else 1287 { 1288 mnOffX = nButtonWidth; 1289 mnLastOffX = maWinSize.Width() - nSizerWidth - 1; 1290 } 1291 1292 // Neu formatieren 1293 mbSizeFormat = sal_True; 1294 if ( IsReallyVisible() ) 1295 { 1296 if ( ImplCalcWidth() ) 1297 Invalidate(); 1298 ImplFormat(); 1299 } 1300 1301 // Button enablen/disablen 1302 ImplEnableControls(); 1303 } 1304 1305 // ----------------------------------------------------------------------- 1306 1307 void TabBar::RequestHelp( const HelpEvent& rHEvt ) 1308 { 1309 sal_uInt16 nItemId = GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ); 1310 if ( nItemId ) 1311 { 1312 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 1313 { 1314 XubString aStr = GetHelpText( nItemId ); 1315 if ( aStr.Len() ) 1316 { 1317 Rectangle aItemRect = GetPageRect( nItemId ); 1318 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); 1319 aItemRect.Left() = aPt.X(); 1320 aItemRect.Top() = aPt.Y(); 1321 aPt = OutputToScreenPixel( aItemRect.BottomRight() ); 1322 aItemRect.Right() = aPt.X(); 1323 aItemRect.Bottom() = aPt.Y(); 1324 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr ); 1325 return; 1326 } 1327 } 1328 else if ( rHEvt.GetMode() & HELPMODE_EXTENDED ) 1329 { 1330 rtl::OUString aHelpId( rtl::OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) ); 1331 if ( aHelpId.getLength() ) 1332 { 1333 // Wenn eine Hilfe existiert, dann auslösen 1334 Help* pHelp = Application::GetHelp(); 1335 if ( pHelp ) 1336 pHelp->Start( aHelpId, this ); 1337 return; 1338 } 1339 } 1340 1341 // Bei Quick- oder Balloon-Help zeigen wir den Text an, 1342 // wenn dieser abgeschnitten oder nicht voll sichtbar ist 1343 if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) ) 1344 { 1345 sal_uInt16 nPos = GetPagePos( nItemId ); 1346 ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); 1347 if ( pItem->mbShort || 1348 (pItem->maRect.Right()-TABBAR_OFFSET_X-5 > mnLastOffX) ) 1349 { 1350 Rectangle aItemRect = GetPageRect( nItemId ); 1351 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); 1352 aItemRect.Left() = aPt.X(); 1353 aItemRect.Top() = aPt.Y(); 1354 aPt = OutputToScreenPixel( aItemRect.BottomRight() ); 1355 aItemRect.Right() = aPt.X(); 1356 aItemRect.Bottom() = aPt.Y(); 1357 XubString aStr = mpItemList->GetObject( nPos )->maText; 1358 if ( aStr.Len() ) 1359 { 1360 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 1361 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr ); 1362 else 1363 Help::ShowQuickHelp( this, aItemRect, aStr ); 1364 return; 1365 } 1366 } 1367 } 1368 } 1369 1370 Window::RequestHelp( rHEvt ); 1371 } 1372 1373 // ----------------------------------------------------------------------- 1374 1375 void TabBar::StateChanged( StateChangedType nType ) 1376 { 1377 Window::StateChanged( nType ); 1378 1379 if ( nType == STATE_CHANGE_INITSHOW ) 1380 { 1381 if ( (mbSizeFormat || mbFormat) && mpItemList->Count() ) 1382 ImplFormat(); 1383 } 1384 else if ( (nType == STATE_CHANGE_ZOOM) || 1385 (nType == STATE_CHANGE_CONTROLFONT) ) 1386 { 1387 ImplInitSettings( sal_True, sal_False ); 1388 Invalidate(); 1389 } 1390 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) 1391 Invalidate(); 1392 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) 1393 { 1394 ImplInitSettings( sal_False, sal_True ); 1395 Invalidate(); 1396 } 1397 else if ( nType == STATE_CHANGE_MIRRORING ) 1398 { 1399 // reacts on calls of EnableRTL, have to mirror all child controls 1400 if( mpFirstBtn ) mpFirstBtn->EnableRTL( IsRTLEnabled() ); 1401 if( mpPrevBtn ) mpPrevBtn->EnableRTL( IsRTLEnabled() ); 1402 if( mpNextBtn ) mpNextBtn->EnableRTL( IsRTLEnabled() ); 1403 if( mpLastBtn ) mpLastBtn->EnableRTL( IsRTLEnabled() ); 1404 if( mpImpl->mpSizer ) mpImpl->mpSizer->EnableRTL( IsRTLEnabled() ); 1405 if( mpEdit ) mpEdit->EnableRTL( IsRTLEnabled() ); 1406 } 1407 } 1408 1409 // ----------------------------------------------------------------------- 1410 1411 void TabBar::DataChanged( const DataChangedEvent& rDCEvt ) 1412 { 1413 Window::DataChanged( rDCEvt ); 1414 1415 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || 1416 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || 1417 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && 1418 (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) 1419 { 1420 ImplInitSettings( sal_True, sal_True ); 1421 Invalidate(); 1422 } 1423 } 1424 1425 // ----------------------------------------------------------------------- 1426 1427 void TabBar::ImplSelect() 1428 { 1429 Select(); 1430 1431 CallEventListeners( VCLEVENT_TABBAR_PAGESELECTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) ); 1432 } 1433 1434 // ----------------------------------------------------------------------- 1435 1436 void TabBar::Select() 1437 { 1438 maSelectHdl.Call( this ); 1439 } 1440 1441 // ----------------------------------------------------------------------- 1442 1443 void TabBar::DoubleClick() 1444 { 1445 maDoubleClickHdl.Call( this ); 1446 } 1447 1448 // ----------------------------------------------------------------------- 1449 1450 void TabBar::Split() 1451 { 1452 maSplitHdl.Call( this ); 1453 } 1454 1455 // ----------------------------------------------------------------------- 1456 1457 void TabBar::ImplActivatePage() 1458 { 1459 ActivatePage(); 1460 1461 CallEventListeners( VCLEVENT_TABBAR_PAGEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) ); 1462 } 1463 1464 // ----------------------------------------------------------------------- 1465 1466 void TabBar::ActivatePage() 1467 { 1468 maActivatePageHdl.Call( this ); 1469 } 1470 1471 // ----------------------------------------------------------------------- 1472 1473 long TabBar::ImplDeactivatePage() 1474 { 1475 long nRet = DeactivatePage(); 1476 1477 CallEventListeners( VCLEVENT_TABBAR_PAGEDEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) ); 1478 1479 return nRet; 1480 } 1481 1482 // ----------------------------------------------------------------------- 1483 1484 long TabBar::DeactivatePage() 1485 { 1486 if ( maDeactivatePageHdl.IsSet() ) 1487 return maDeactivatePageHdl.Call( this ); 1488 else 1489 return sal_True; 1490 } 1491 1492 // ----------------------------------------------------------------------- 1493 1494 long TabBar::StartRenaming() 1495 { 1496 if ( maStartRenamingHdl.IsSet() ) 1497 return maStartRenamingHdl.Call( this ); 1498 else 1499 return sal_True; 1500 } 1501 1502 // ----------------------------------------------------------------------- 1503 1504 long TabBar::AllowRenaming() 1505 { 1506 if ( maAllowRenamingHdl.IsSet() ) 1507 return maAllowRenamingHdl.Call( this ); 1508 else 1509 return sal_True; 1510 } 1511 1512 // ----------------------------------------------------------------------- 1513 1514 void TabBar::EndRenaming() 1515 { 1516 maEndRenamingHdl.Call( this ); 1517 } 1518 1519 // ----------------------------------------------------------------------- 1520 1521 void TabBar::Mirror() 1522 { 1523 1524 } 1525 1526 // ----------------------------------------------------------------------- 1527 1528 void TabBar::InsertPage( sal_uInt16 nPageId, const XubString& rText, 1529 TabBarPageBits nBits, sal_uInt16 nPos ) 1530 { 1531 DBG_ASSERT( nPageId, "TabBar::InsertPage(): PageId == 0" ); 1532 DBG_ASSERT( GetPagePos( nPageId ) == PAGE_NOT_FOUND, 1533 "TabBar::InsertPage(): PageId already exists" ); 1534 DBG_ASSERT( nBits <= TPB_SPECIAL, "TabBar::InsertPage(): nBits is wrong" ); 1535 1536 // PageItem anlegen und in die Item-Liste eintragen 1537 ImplTabBarItem* pItem = new ImplTabBarItem( nPageId, rText, nBits ); 1538 mpItemList->Insert( pItem, nPos ); 1539 mbSizeFormat = sal_True; 1540 1541 // CurPageId gegebenenfalls setzen 1542 if ( !mnCurPageId ) 1543 mnCurPageId = nPageId; 1544 1545 // Leiste neu ausgeben 1546 if ( IsReallyVisible() && IsUpdateMode() ) 1547 Invalidate(); 1548 1549 CallEventListeners( VCLEVENT_TABBAR_PAGEINSERTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) ); 1550 } 1551 1552 // ----------------------------------------------------------------------- 1553 1554 Color TabBar::GetTabBgColor( sal_uInt16 nPageId ) const 1555 { 1556 sal_uInt16 nPos = GetPagePos( nPageId ); 1557 1558 if ( nPos != PAGE_NOT_FOUND ) 1559 return mpItemList->GetObject( nPos )->maTabBgColor; 1560 else 1561 return Color( COL_AUTO ); 1562 } 1563 1564 void TabBar::SetTabBgColor( sal_uInt16 nPageId, const Color& aTabBgColor ) 1565 { 1566 sal_uInt16 nPos = GetPagePos( nPageId ); 1567 ImplTabBarItem* pItem; 1568 if ( nPos != PAGE_NOT_FOUND ) 1569 { 1570 pItem = mpItemList->GetObject( nPos ); 1571 if ( aTabBgColor != Color( COL_AUTO ) ) 1572 { 1573 pItem->maTabBgColor = aTabBgColor; 1574 if ( aTabBgColor.GetLuminance() <= 128 ) // Do not use aTabBgColor.IsDark(), because that threshold is way too low... 1575 pItem->maTabTextColor = Color( COL_WHITE ); 1576 else 1577 pItem->maTabTextColor = Color( COL_BLACK ); 1578 } 1579 else 1580 { 1581 pItem->maTabBgColor = Color( COL_AUTO ); 1582 pItem->maTabTextColor = Color( COL_AUTO ); 1583 } 1584 } 1585 } 1586 1587 // ----------------------------------------------------------------------- 1588 1589 void TabBar::RemovePage( sal_uInt16 nPageId ) 1590 { 1591 sal_uInt16 nPos = GetPagePos( nPageId ); 1592 1593 // Existiert Item 1594 if ( nPos != PAGE_NOT_FOUND ) 1595 { 1596 if ( mnCurPageId == nPageId ) 1597 mnCurPageId = 0; 1598 1599 // Testen, ob erste sichtbare Seite verschoben werden muss 1600 if ( mnFirstPos > nPos ) 1601 mnFirstPos--; 1602 1603 // Item-Daten löschen 1604 delete mpItemList->Remove( nPos ); 1605 mbFormat = sal_True; 1606 1607 // Leiste neu ausgeben 1608 if ( IsReallyVisible() && IsUpdateMode() ) 1609 Invalidate(); 1610 1611 CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) ); 1612 } 1613 } 1614 1615 // ----------------------------------------------------------------------- 1616 1617 void TabBar::MovePage( sal_uInt16 nPageId, sal_uInt16 nNewPos ) 1618 { 1619 sal_uInt16 nPos = GetPagePos( nPageId ); 1620 Pair aPair( nPos, nNewPos ); 1621 1622 if ( nPos < nNewPos ) 1623 nNewPos--; 1624 1625 if ( nPos == nNewPos ) 1626 return; 1627 1628 // Existiert Item 1629 if ( nPos != PAGE_NOT_FOUND ) 1630 { 1631 // TabBar-Item in der Liste verschieben 1632 ImplTabBarItem* pItem = mpItemList->Remove( nPos ); 1633 mpItemList->Insert( pItem, nNewPos ); 1634 mbFormat = sal_True; 1635 1636 // Leiste neu ausgeben 1637 if ( IsReallyVisible() && IsUpdateMode() ) 1638 Invalidate(); 1639 1640 CallEventListeners( VCLEVENT_TABBAR_PAGEMOVED, (void*) &aPair ); 1641 } 1642 } 1643 1644 // ----------------------------------------------------------------------- 1645 1646 void TabBar::Clear() 1647 { 1648 // Alle Items löschen 1649 ImplTabBarItem* pItem = mpItemList->First(); 1650 while ( pItem ) 1651 { 1652 // Item-Daten löschen 1653 delete pItem; 1654 pItem = mpItemList->Next(); 1655 } 1656 1657 // Items aus der Liste löschen 1658 mpItemList->Clear(); 1659 mbSizeFormat = sal_True; 1660 mnCurPageId = 0; 1661 mnFirstPos = 0; 1662 1663 // Leiste neu ausgeben 1664 if ( IsReallyVisible() && IsUpdateMode() ) 1665 Invalidate(); 1666 1667 CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, (void*) PAGE_NOT_FOUND ); 1668 } 1669 1670 // ----------------------------------------------------------------------- 1671 1672 void TabBar::EnablePage( sal_uInt16 nPageId, sal_Bool bEnable ) 1673 { 1674 sal_uInt16 nPos = GetPagePos( nPageId ); 1675 1676 if ( nPos != PAGE_NOT_FOUND ) 1677 { 1678 ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); 1679 1680 if ( pItem->mbEnable != bEnable ) 1681 { 1682 pItem->mbEnable = bEnable; 1683 1684 // Leiste neu ausgeben 1685 if ( IsReallyVisible() && IsUpdateMode() ) 1686 Invalidate( pItem->maRect ); 1687 1688 CallEventListeners( bEnable ? VCLEVENT_TABBAR_PAGEENABLED : VCLEVENT_TABBAR_PAGEDISABLED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) ); 1689 } 1690 } 1691 } 1692 1693 // ----------------------------------------------------------------------- 1694 1695 sal_Bool TabBar::IsPageEnabled( sal_uInt16 nPageId ) const 1696 { 1697 sal_uInt16 nPos = GetPagePos( nPageId ); 1698 1699 if ( nPos != PAGE_NOT_FOUND ) 1700 return mpItemList->GetObject( nPos )->mbEnable; 1701 else 1702 return sal_False; 1703 } 1704 1705 // ----------------------------------------------------------------------- 1706 1707 void TabBar::SetPageBits( sal_uInt16 nPageId, TabBarPageBits nBits ) 1708 { 1709 sal_uInt16 nPos = GetPagePos( nPageId ); 1710 1711 if ( nPos != PAGE_NOT_FOUND ) 1712 { 1713 ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); 1714 1715 if ( pItem->mnBits != nBits ) 1716 { 1717 pItem->mnBits = nBits; 1718 1719 // Leiste neu ausgeben 1720 if ( IsReallyVisible() && IsUpdateMode() ) 1721 Invalidate( pItem->maRect ); 1722 } 1723 } 1724 } 1725 1726 // ----------------------------------------------------------------------- 1727 1728 TabBarPageBits TabBar::GetPageBits( sal_uInt16 nPageId ) const 1729 { 1730 sal_uInt16 nPos = GetPagePos( nPageId ); 1731 1732 if ( nPos != PAGE_NOT_FOUND ) 1733 return mpItemList->GetObject( nPos )->mnBits; 1734 else 1735 return sal_False; 1736 } 1737 1738 // ----------------------------------------------------------------------- 1739 1740 sal_uInt16 TabBar::GetPageCount() const 1741 { 1742 return (sal_uInt16)mpItemList->Count(); 1743 } 1744 1745 // ----------------------------------------------------------------------- 1746 1747 sal_uInt16 TabBar::GetPageId( sal_uInt16 nPos ) const 1748 { 1749 ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); 1750 if ( pItem ) 1751 return pItem->mnId; 1752 else 1753 return 0; 1754 } 1755 1756 // ----------------------------------------------------------------------- 1757 1758 sal_uInt16 TabBar::GetPagePos( sal_uInt16 nPageId ) const 1759 { 1760 ImplTabBarItem* pItem = mpItemList->First(); 1761 while ( pItem ) 1762 { 1763 if ( pItem->mnId == nPageId ) 1764 return (sal_uInt16)mpItemList->GetCurPos(); 1765 1766 pItem = mpItemList->Next(); 1767 } 1768 1769 return PAGE_NOT_FOUND; 1770 } 1771 1772 // ----------------------------------------------------------------------- 1773 1774 sal_uInt16 TabBar::GetPageId( const Point& rPos ) const 1775 { 1776 ImplTabBarItem* pItem = mpItemList->First(); 1777 while ( pItem ) 1778 { 1779 if ( pItem->maRect.IsInside( rPos ) ) 1780 return pItem->mnId; 1781 1782 pItem = mpItemList->Next(); 1783 } 1784 1785 return 0; 1786 } 1787 1788 // ----------------------------------------------------------------------- 1789 1790 Rectangle TabBar::GetPageRect( sal_uInt16 nPageId ) const 1791 { 1792 sal_uInt16 nPos = GetPagePos( nPageId ); 1793 1794 if ( nPos != PAGE_NOT_FOUND ) 1795 return mpItemList->GetObject( nPos )->maRect; 1796 else 1797 return Rectangle(); 1798 } 1799 1800 // ----------------------------------------------------------------------- 1801 1802 void TabBar::SetCurPageId( sal_uInt16 nPageId ) 1803 { 1804 sal_uInt16 nPos = GetPagePos( nPageId ); 1805 1806 // Wenn Item nicht existiert, dann nichts machen 1807 if ( nPos != PAGE_NOT_FOUND ) 1808 { 1809 // Wenn sich aktuelle Page nicht geändert hat, dann müssen wir 1810 // jetzt nichts mehr machen 1811 if ( nPageId == mnCurPageId ) 1812 return; 1813 1814 // Muss invalidiert werden 1815 sal_Bool bUpdate = sal_False; 1816 if ( IsReallyVisible() && IsUpdateMode() ) 1817 bUpdate = sal_True; 1818 1819 ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); 1820 ImplTabBarItem* pOldItem; 1821 1822 if ( mnCurPageId ) 1823 pOldItem = mpItemList->GetObject( GetPagePos( mnCurPageId ) ); 1824 else 1825 pOldItem = NULL; 1826 1827 // Wenn Page nicht selektiert, dann vorher selektierte Seite 1828 // deselektieren, wenn dies die einzige selektierte Seite ist 1829 if ( !pItem->mbSelect && pOldItem ) 1830 { 1831 sal_uInt16 nSelPageCount = GetSelectPageCount(); 1832 if ( nSelPageCount == 1 ) 1833 pOldItem->mbSelect = sal_False; 1834 pItem->mbSelect = sal_True; 1835 } 1836 1837 mnCurPageId = nPageId; 1838 mbFormat = sal_True; 1839 1840 // Dafür sorgen, dass aktuelle Page sichtbar wird 1841 if ( IsReallyVisible() ) 1842 { 1843 if ( nPos < mnFirstPos ) 1844 SetFirstPageId( nPageId ); 1845 else 1846 { 1847 // sichtbare Breite berechnen 1848 long nWidth = mnLastOffX; 1849 if ( nWidth > TABBAR_OFFSET_X ) 1850 nWidth -= TABBAR_OFFSET_X; 1851 if ( nWidth > ADDNEWPAGE_AREAWIDTH ) 1852 nWidth -= ADDNEWPAGE_AREAWIDTH; 1853 1854 if ( pItem->maRect.IsEmpty() ) 1855 ImplFormat(); 1856 1857 while ( (mbMirrored ? (pItem->maRect.Left() < mnOffX) : (pItem->maRect.Right() > nWidth)) || 1858 pItem->maRect.IsEmpty() ) 1859 { 1860 sal_uInt16 nNewPos = mnFirstPos+1; 1861 // Dafür sorgen, dass min. die aktuelle TabPage als 1862 // erste TabPage sichtbar ist 1863 if ( nNewPos >= nPos ) 1864 { 1865 SetFirstPageId( nPageId ); 1866 break; 1867 } 1868 else 1869 SetFirstPageId( GetPageId( nNewPos ) ); 1870 ImplFormat(); 1871 // Falls erste Seite nicht weitergeschaltet wird, dann 1872 // können wir abbrechen 1873 if ( nNewPos != mnFirstPos ) 1874 break; 1875 } 1876 } 1877 } 1878 1879 // Leiste neu ausgeben 1880 if ( bUpdate ) 1881 { 1882 Invalidate( pItem->maRect ); 1883 if ( pOldItem ) 1884 Invalidate( pOldItem->maRect ); 1885 } 1886 } 1887 } 1888 1889 // ----------------------------------------------------------------------- 1890 1891 void TabBar::MakeVisible( sal_uInt16 nPageId ) 1892 { 1893 if ( !IsReallyVisible() ) 1894 return; 1895 1896 sal_uInt16 nPos = GetPagePos( nPageId ); 1897 1898 // Wenn Item nicht existiert, dann nichts machen 1899 if ( nPos != PAGE_NOT_FOUND ) 1900 { 1901 if ( nPos < mnFirstPos ) 1902 SetFirstPageId( nPageId ); 1903 else 1904 { 1905 ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); 1906 1907 // sichtbare Breite berechnen 1908 long nWidth = mnLastOffX; 1909 if ( nWidth > TABBAR_OFFSET_X ) 1910 nWidth -= TABBAR_OFFSET_X; 1911 1912 if ( mbFormat || pItem->maRect.IsEmpty() ) 1913 { 1914 mbFormat = sal_True; 1915 ImplFormat(); 1916 } 1917 1918 while ( (pItem->maRect.Right() > nWidth) || 1919 pItem->maRect.IsEmpty() ) 1920 { 1921 sal_uInt16 nNewPos = mnFirstPos+1; 1922 // Dafür sorgen, dass min. die aktuelle TabPage als 1923 // erste TabPage sichtbar ist 1924 if ( nNewPos >= nPos ) 1925 { 1926 SetFirstPageId( nPageId ); 1927 break; 1928 } 1929 else 1930 SetFirstPageId( GetPageId( nNewPos ) ); 1931 ImplFormat(); 1932 // Falls erste Seite nicht weitergeschaltet wird, dann 1933 // können wir abbrechen 1934 if ( nNewPos != mnFirstPos ) 1935 break; 1936 } 1937 } 1938 } 1939 } 1940 1941 // ----------------------------------------------------------------------- 1942 1943 void TabBar::SetFirstPageId( sal_uInt16 nPageId ) 1944 { 1945 sal_uInt16 nPos = GetPagePos( nPageId ); 1946 1947 // Wenn Item nicht existiert, dann sal_False zurückgeben 1948 if ( nPos != PAGE_NOT_FOUND ) 1949 { 1950 if ( nPos != mnFirstPos ) 1951 { 1952 // Dafür sorgen, dass nach Möglichkeit so viele Pages wie 1953 // möglich sichtbar sind 1954 ImplFormat(); 1955 sal_uInt16 nLastFirstPos = ImplGetLastFirstPos(); 1956 sal_uInt16 nNewPos; 1957 if ( nPos > nLastFirstPos ) 1958 nNewPos = nLastFirstPos; 1959 else 1960 nNewPos = nPos; 1961 1962 if ( nNewPos != mnFirstPos ) 1963 { 1964 mnFirstPos = nNewPos; 1965 mbFormat = sal_True; 1966 1967 // Leiste neu ausgeben (Achtung: mbDropPos beachten, da wenn 1968 // dieses Flag gesetzt ist, wird direkt gepaintet) 1969 if ( IsReallyVisible() && IsUpdateMode() && !mbDropPos ) 1970 Invalidate(); 1971 } 1972 } 1973 } 1974 } 1975 1976 // ----------------------------------------------------------------------- 1977 1978 void TabBar::SelectPage( sal_uInt16 nPageId, sal_Bool bSelect ) 1979 { 1980 sal_uInt16 nPos = GetPagePos( nPageId ); 1981 1982 if ( nPos != PAGE_NOT_FOUND ) 1983 { 1984 ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); 1985 1986 if ( pItem->mbSelect != bSelect ) 1987 { 1988 pItem->mbSelect = bSelect; 1989 1990 // Leiste neu ausgeben 1991 if ( IsReallyVisible() && IsUpdateMode() ) 1992 Invalidate( pItem->maRect ); 1993 } 1994 } 1995 } 1996 1997 // ----------------------------------------------------------------------- 1998 1999 void TabBar::SelectPageRange( sal_Bool bSelect, sal_uInt16 nStartPos, sal_uInt16 nEndPos ) 2000 { 2001 Rectangle aPaintRect; 2002 sal_uInt16 nPos = nStartPos; 2003 ImplTabBarItem* pItem = mpItemList->Seek( nPos ); 2004 while ( pItem && (nPos <= nEndPos) ) 2005 { 2006 if ( (pItem->mbSelect != bSelect) && (pItem->mnId != mnCurPageId) ) 2007 { 2008 pItem->mbSelect = bSelect; 2009 aPaintRect.Union( pItem->maRect ); 2010 } 2011 2012 nPos++; 2013 pItem = mpItemList->Next(); 2014 } 2015 2016 // Leiste neu ausgeben 2017 if ( IsReallyVisible() && IsUpdateMode() && !aPaintRect.IsEmpty() ) 2018 Invalidate( aPaintRect ); 2019 } 2020 2021 // ----------------------------------------------------------------------- 2022 2023 sal_uInt16 TabBar::GetSelectPage( sal_uInt16 nSelIndex ) const 2024 { 2025 sal_uInt16 nSelected = 0; 2026 ImplTabBarItem* pItem = mpItemList->First(); 2027 while ( pItem ) 2028 { 2029 if ( pItem->mbSelect ) 2030 nSelected++; 2031 2032 if ( nSelected == nSelIndex ) 2033 return pItem->mnId; 2034 2035 pItem = mpItemList->Next(); 2036 } 2037 2038 return 0; 2039 } 2040 2041 // ----------------------------------------------------------------------- 2042 2043 sal_uInt16 TabBar::GetSelectPageCount() const 2044 { 2045 sal_uInt16 nSelected = 0; 2046 ImplTabBarItem* pItem = mpItemList->First(); 2047 while ( pItem ) 2048 { 2049 if ( pItem->mbSelect ) 2050 nSelected++; 2051 2052 pItem = mpItemList->Next(); 2053 } 2054 2055 return nSelected; 2056 } 2057 2058 // ----------------------------------------------------------------------- 2059 2060 sal_Bool TabBar::IsPageSelected( sal_uInt16 nPageId ) const 2061 { 2062 sal_uInt16 nPos = GetPagePos( nPageId ); 2063 if ( nPos != PAGE_NOT_FOUND ) 2064 return mpItemList->GetObject( nPos )->mbSelect; 2065 else 2066 return sal_False; 2067 } 2068 2069 // ----------------------------------------------------------------------- 2070 2071 sal_Bool TabBar::StartEditMode( sal_uInt16 nPageId ) 2072 { 2073 sal_uInt16 nPos = GetPagePos( nPageId ); 2074 if ( mpEdit || (nPos == PAGE_NOT_FOUND) || (mnLastOffX < 8) ) 2075 return sal_False; 2076 2077 mnEditId = nPageId; 2078 if ( StartRenaming() ) 2079 { 2080 ImplShowPage( nPos ); 2081 ImplFormat(); 2082 Update(); 2083 2084 mpEdit = new TabBarEdit( this, WB_CENTER ); 2085 Rectangle aRect = GetPageRect( mnEditId ); 2086 long nX = aRect.Left()+TABBAR_OFFSET_X+(TABBAR_OFFSET_X2/2); 2087 long nWidth = aRect.GetWidth()-(TABBAR_OFFSET_X*2)-TABBAR_OFFSET_X2; 2088 if ( mnEditId != GetCurPageId() ) 2089 nX += 1; 2090 if ( nX+nWidth > mnLastOffX ) 2091 nWidth = mnLastOffX-nX; 2092 if ( nWidth < 3 ) 2093 { 2094 nX = aRect.Left(); 2095 nWidth = aRect.GetWidth(); 2096 } 2097 mpEdit->SetText( GetPageText( mnEditId ) ); 2098 mpEdit->SetPosSizePixel( nX, aRect.Top()+mnOffY+1, nWidth, aRect.GetHeight()-3 ); 2099 Font aFont = GetPointFont(); 2100 Color aForegroundColor; 2101 Color aBackgroundColor; 2102 Color aFaceColor; 2103 Color aSelectColor; 2104 Color aFaceTextColor; 2105 Color aSelectTextColor; 2106 ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor ); 2107 if ( mnEditId != GetCurPageId() ) 2108 aFont.SetWeight( WEIGHT_LIGHT ); 2109 if ( IsPageSelected( mnEditId ) || (mnEditId == GetCurPageId()) ) 2110 { 2111 aForegroundColor = aSelectTextColor; 2112 aBackgroundColor = aSelectColor; 2113 } 2114 else 2115 { 2116 aForegroundColor = aFaceTextColor; 2117 aBackgroundColor = aFaceColor; 2118 } 2119 if ( GetPageBits( mnEditId ) & TPB_SPECIAL ) 2120 aForegroundColor = Color( COL_LIGHTBLUE ); 2121 mpEdit->SetControlFont( aFont ); 2122 mpEdit->SetControlForeground( aForegroundColor ); 2123 mpEdit->SetControlBackground( aBackgroundColor ); 2124 mpEdit->GrabFocus(); 2125 mpEdit->SetSelection( Selection( 0, mpEdit->GetText().Len() ) ); 2126 mpEdit->Show(); 2127 return sal_True; 2128 } 2129 else 2130 { 2131 mnEditId = 0; 2132 return sal_False; 2133 } 2134 } 2135 2136 // ----------------------------------------------------------------------- 2137 2138 void TabBar::EndEditMode( sal_Bool bCancel ) 2139 { 2140 if ( mpEdit ) 2141 { 2142 // call hdl 2143 sal_Bool bEnd = sal_True; 2144 mbEditCanceled = bCancel; 2145 maEditText = mpEdit->GetText(); 2146 mpEdit->SetPostEvent(); 2147 if ( !bCancel ) 2148 { 2149 long nAllowRenaming = AllowRenaming(); 2150 if ( nAllowRenaming == TABBAR_RENAMING_YES ) 2151 SetPageText( mnEditId, maEditText ); 2152 else if ( nAllowRenaming == TABBAR_RENAMING_NO ) 2153 bEnd = sal_False; 2154 else // nAllowRenaming == TABBAR_RENAMING_CANCEL 2155 mbEditCanceled = sal_True; 2156 } 2157 2158 // renaming not allowed, then reset edit data 2159 if ( !bEnd ) 2160 { 2161 mpEdit->ResetPostEvent(); 2162 mpEdit->GrabFocus(); 2163 } 2164 else 2165 { 2166 // close edit and call end hdl 2167 delete mpEdit; 2168 mpEdit = NULL; 2169 EndRenaming(); 2170 mnEditId = 0; 2171 } 2172 2173 // reset 2174 maEditText.Erase(); 2175 mbEditCanceled = sal_False; 2176 } 2177 } 2178 2179 // ----------------------------------------------------------------------- 2180 2181 void TabBar::SetMirrored( sal_Bool bMirrored ) 2182 { 2183 if( mbMirrored != bMirrored ) 2184 { 2185 mbMirrored = bMirrored; 2186 mbSizeFormat = sal_True; 2187 ImplInitControls(); // for button images 2188 Resize(); // recalculates control positions 2189 Mirror(); 2190 } 2191 } 2192 2193 void TabBar::SetEffectiveRTL( sal_Bool bRTL ) 2194 { 2195 SetMirrored( bRTL != Application::GetSettings().GetLayoutRTL() ); 2196 } 2197 2198 sal_Bool TabBar::IsEffectiveRTL() const 2199 { 2200 return IsMirrored() != Application::GetSettings().GetLayoutRTL(); 2201 } 2202 2203 // ----------------------------------------------------------------------- 2204 2205 void TabBar::SetMaxPageWidth( long nMaxWidth ) 2206 { 2207 if ( mnMaxPageWidth != nMaxWidth ) 2208 { 2209 mnMaxPageWidth = nMaxWidth; 2210 mbSizeFormat = sal_True; 2211 2212 // Leiste neu ausgeben 2213 if ( IsReallyVisible() && IsUpdateMode() ) 2214 Invalidate(); 2215 } 2216 } 2217 2218 // ----------------------------------------------------------------------- 2219 2220 void TabBar::SetSelectColor() 2221 { 2222 if ( mbSelColor ) 2223 { 2224 maSelColor = Color( COL_TRANSPARENT ); 2225 mbSelColor = sal_False; 2226 Invalidate(); 2227 } 2228 } 2229 2230 // ----------------------------------------------------------------------- 2231 2232 void TabBar::SetSelectColor( const Color& rColor ) 2233 { 2234 if ( rColor.GetTransparency() ) 2235 { 2236 if ( mbSelColor ) 2237 { 2238 maSelColor = Color( COL_TRANSPARENT ); 2239 mbSelColor = sal_False; 2240 Invalidate(); 2241 } 2242 } 2243 else 2244 { 2245 if ( maSelColor != rColor ) 2246 { 2247 maSelColor = rColor; 2248 mbSelColor = sal_True; 2249 Invalidate(); 2250 } 2251 } 2252 } 2253 2254 // ----------------------------------------------------------------------- 2255 2256 void TabBar::SetSelectTextColor() 2257 { 2258 if ( mbSelTextColor ) 2259 { 2260 maSelTextColor = Color( COL_TRANSPARENT ); 2261 mbSelTextColor = sal_False; 2262 Invalidate(); 2263 } 2264 } 2265 2266 // ----------------------------------------------------------------------- 2267 2268 void TabBar::SetSelectTextColor( const Color& rColor ) 2269 { 2270 if ( rColor.GetTransparency() ) 2271 { 2272 if ( mbSelTextColor ) 2273 { 2274 maSelTextColor = Color( COL_TRANSPARENT ); 2275 mbSelTextColor = sal_False; 2276 Invalidate(); 2277 } 2278 } 2279 else 2280 { 2281 if ( maSelTextColor != rColor ) 2282 { 2283 maSelTextColor = rColor; 2284 mbSelTextColor = sal_True; 2285 Invalidate(); 2286 } 2287 } 2288 } 2289 2290 // ----------------------------------------------------------------------- 2291 2292 void TabBar::SetPageText( sal_uInt16 nPageId, const XubString& rText ) 2293 { 2294 sal_uInt16 nPos = GetPagePos( nPageId ); 2295 if ( nPos != PAGE_NOT_FOUND ) 2296 { 2297 mpItemList->GetObject( nPos )->maText = rText; 2298 mbSizeFormat = sal_True; 2299 2300 // Leiste neu ausgeben 2301 if ( IsReallyVisible() && IsUpdateMode() ) 2302 Invalidate(); 2303 2304 CallEventListeners( VCLEVENT_TABBAR_PAGETEXTCHANGED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) ); 2305 } 2306 } 2307 2308 // ----------------------------------------------------------------------- 2309 2310 XubString TabBar::GetPageText( sal_uInt16 nPageId ) const 2311 { 2312 sal_uInt16 nPos = GetPagePos( nPageId ); 2313 if ( nPos != PAGE_NOT_FOUND ) 2314 return mpItemList->GetObject( nPos )->maText; 2315 else 2316 return XubString(); 2317 } 2318 2319 // ----------------------------------------------------------------------- 2320 2321 void TabBar::SetHelpText( sal_uInt16 nPageId, const XubString& rText ) 2322 { 2323 sal_uInt16 nPos = GetPagePos( nPageId ); 2324 if ( nPos != PAGE_NOT_FOUND ) 2325 mpItemList->GetObject( nPos )->maHelpText = rText; 2326 } 2327 2328 // ----------------------------------------------------------------------- 2329 2330 XubString TabBar::GetHelpText( sal_uInt16 nPageId ) const 2331 { 2332 sal_uInt16 nPos = GetPagePos( nPageId ); 2333 if ( nPos != PAGE_NOT_FOUND ) 2334 { 2335 ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); 2336 if ( !pItem->maHelpText.Len() && pItem->maHelpId.getLength() ) 2337 { 2338 Help* pHelp = Application::GetHelp(); 2339 if ( pHelp ) 2340 pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this ); 2341 } 2342 2343 return pItem->maHelpText; 2344 } 2345 else 2346 return XubString(); 2347 } 2348 2349 // ----------------------------------------------------------------------- 2350 2351 void TabBar::SetHelpId( sal_uInt16 nPageId, const rtl::OString& rHelpId ) 2352 { 2353 sal_uInt16 nPos = GetPagePos( nPageId ); 2354 if ( nPos != PAGE_NOT_FOUND ) 2355 mpItemList->GetObject( nPos )->maHelpId = rHelpId; 2356 } 2357 2358 // ----------------------------------------------------------------------- 2359 2360 rtl::OString TabBar::GetHelpId( sal_uInt16 nPageId ) const 2361 { 2362 sal_uInt16 nPos = GetPagePos( nPageId ); 2363 rtl::OString aRet; 2364 if ( nPos != PAGE_NOT_FOUND ) 2365 aRet = mpItemList->GetObject( nPos )->maHelpId; 2366 return aRet; 2367 } 2368 2369 // ----------------------------------------------------------------------- 2370 2371 long TabBar::GetMinSize() const 2372 { 2373 long nMinSize = TABBAR_MINSIZE + TABBAR_OFFSET_X; 2374 if ( mnWinStyle & WB_MINSCROLL ) 2375 nMinSize += mpPrevBtn->GetSizePixel().Width()*2; 2376 else if ( mnWinStyle & WB_SCROLL ) 2377 nMinSize += mpFirstBtn->GetSizePixel().Width()*4; 2378 return nMinSize; 2379 } 2380 2381 // ----------------------------------------------------------------------- 2382 2383 sal_Bool TabBar::StartDrag( const CommandEvent& rCEvt, Region& rRegion ) 2384 { 2385 if ( !(mnWinStyle & WB_DRAG) || (rCEvt.GetCommand() != COMMAND_STARTDRAG) ) 2386 return sal_False; 2387 2388 // Testen, ob angeklickte Seite selektiert ist. Falls dies nicht 2389 // der Fall ist, setzen wir ihn als aktuellen Eintrag. Falls Drag and 2390 // Drop auch mal über Tastatur ausgelöst werden kann, testen wir 2391 // dies nur bei einer Mausaktion. 2392 // Außerdem machen wir das nur, wenn kein Select() ausgelöst wurde, 2393 // da der Select schon den Bereich gescrollt haben kann 2394 if ( rCEvt.IsMouseEvent() && !mbInSelect ) 2395 { 2396 sal_uInt16 nSelId = GetPageId( rCEvt.GetMousePosPixel() ); 2397 2398 // Falls kein Eintrag angeklickt wurde, starten wir kein Dragging 2399 if ( !nSelId ) 2400 return sal_False; 2401 2402 // Testen, ob Seite selektiert ist. Falls nicht, als aktuelle 2403 // Seite setzen und Select rufen. 2404 if ( !IsPageSelected( nSelId ) ) 2405 { 2406 if ( ImplDeactivatePage() ) 2407 { 2408 SetCurPageId( nSelId ); 2409 Update(); 2410 ImplActivatePage(); 2411 ImplSelect(); 2412 } 2413 else 2414 return sal_False; 2415 } 2416 } 2417 mbInSelect = sal_False; 2418 2419 Region aRegion; 2420 2421 // Region zuweisen 2422 rRegion = aRegion; 2423 2424 return sal_True; 2425 } 2426 2427 // ----------------------------------------------------------------------- 2428 2429 sal_uInt16 TabBar::ShowDropPos( const Point& rPos ) 2430 { 2431 ImplTabBarItem* pItem; 2432 sal_uInt16 nDropId; 2433 sal_uInt16 nNewDropPos; 2434 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count(); 2435 short nScroll = 0; 2436 2437 if ( rPos.X() > mnLastOffX-TABBAR_DRAG_SCROLLOFF ) 2438 { 2439 pItem = mpItemList->GetObject( mpItemList->Count()-1 ); 2440 if ( !pItem->maRect.IsEmpty() && (rPos.X() > pItem->maRect.Right()) ) 2441 nNewDropPos = (sal_uInt16)mpItemList->Count(); 2442 else 2443 { 2444 nNewDropPos = mnFirstPos+1; 2445 nScroll = 1; 2446 } 2447 } 2448 else if ( (rPos.X() <= mnOffX) || 2449 (!mnOffX && (rPos.X() <= TABBAR_DRAG_SCROLLOFF)) ) 2450 { 2451 if ( mnFirstPos ) 2452 { 2453 nNewDropPos = mnFirstPos; 2454 nScroll = -1; 2455 } 2456 else 2457 nNewDropPos = 0; 2458 } 2459 else 2460 { 2461 nDropId = GetPageId( rPos ); 2462 if ( nDropId ) 2463 { 2464 nNewDropPos = GetPagePos( nDropId ); 2465 if ( mnFirstPos && (nNewDropPos == mnFirstPos-1) ) 2466 nScroll = -1; 2467 } 2468 else 2469 nNewDropPos = nItemCount; 2470 } 2471 2472 if ( mbDropPos && (nNewDropPos == mnDropPos) && !nScroll ) 2473 return mnDropPos; 2474 2475 if ( mbDropPos ) 2476 HideDropPos(); 2477 mbDropPos = sal_True; 2478 mnDropPos = nNewDropPos; 2479 2480 if ( nScroll ) 2481 { 2482 sal_uInt16 nOldFirstPos = mnFirstPos; 2483 SetFirstPageId( GetPageId( mnFirstPos+nScroll ) ); 2484 2485 // Direkt ausgeben, da kein Paint bei Drag and Drop möglich 2486 if ( nOldFirstPos != mnFirstPos ) 2487 { 2488 Rectangle aRect( mnOffX, 0, mnLastOffX, maWinSize.Height() ); 2489 SetFillColor( GetBackground().GetColor() ); 2490 DrawRect( aRect ); 2491 Paint( aRect ); 2492 } 2493 } 2494 2495 // Drop-Position-Pfeile ausgeben 2496 Color aBlackColor( COL_BLACK ); 2497 long nX; 2498 long nY = (maWinSize.Height()/2)-1; 2499 sal_uInt16 nCurPos = GetPagePos( mnCurPageId ); 2500 2501 SetLineColor( aBlackColor ); 2502 if ( mnDropPos < nItemCount ) 2503 { 2504 pItem = mpItemList->GetObject( mnDropPos ); 2505 nX = pItem->maRect.Left()+TABBAR_OFFSET_X; 2506 if ( mnDropPos == nCurPos ) 2507 nX--; 2508 else 2509 nX++; 2510 if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect) 2511 SetLineColor( pItem->maTabTextColor ); 2512 DrawLine( Point( nX, nY ), Point( nX, nY ) ); 2513 DrawLine( Point( nX+1, nY-1 ), Point( nX+1, nY+1 ) ); 2514 DrawLine( Point( nX+2, nY-2 ), Point( nX+2, nY+2 ) ); 2515 SetLineColor( aBlackColor ); 2516 } 2517 if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) ) 2518 { 2519 pItem = mpItemList->GetObject( mnDropPos-1 ); 2520 nX = pItem->maRect.Right()-TABBAR_OFFSET_X; 2521 if ( mnDropPos == nCurPos ) 2522 nX++; 2523 if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect) 2524 SetLineColor( pItem->maTabTextColor ); 2525 DrawLine( Point( nX, nY ), Point( nX, nY ) ); 2526 DrawLine( Point( nX-1, nY-1 ), Point( nX-1, nY+1 ) ); 2527 DrawLine( Point( nX-2, nY-2 ), Point( nX-2, nY+2 ) ); 2528 } 2529 2530 return mnDropPos; 2531 } 2532 2533 // ----------------------------------------------------------------------- 2534 2535 void TabBar::HideDropPos() 2536 { 2537 if ( mbDropPos ) 2538 { 2539 ImplTabBarItem* pItem; 2540 long nX; 2541 long nY1 = (maWinSize.Height()/2)-3; 2542 long nY2 = nY1 + 5; 2543 sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count(); 2544 2545 if ( mnDropPos < nItemCount ) 2546 { 2547 pItem = mpItemList->GetObject( mnDropPos ); 2548 nX = pItem->maRect.Left()+TABBAR_OFFSET_X; 2549 // Paint direkt aufrufen, da bei Drag and Drop kein Paint 2550 // möglich 2551 Rectangle aRect( nX-1, nY1, nX+3, nY2 ); 2552 Region aRegion( aRect ); 2553 SetClipRegion( aRegion ); 2554 Paint( aRect ); 2555 SetClipRegion(); 2556 } 2557 if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) ) 2558 { 2559 pItem = mpItemList->GetObject( mnDropPos-1 ); 2560 nX = pItem->maRect.Right()-TABBAR_OFFSET_X; 2561 // Paint direkt aufrufen, da bei Drag and Drop kein Paint 2562 // möglich 2563 Rectangle aRect( nX-2, nY1, nX+1, nY2 ); 2564 Region aRegion( aRect ); 2565 SetClipRegion( aRegion ); 2566 Paint( aRect ); 2567 SetClipRegion(); 2568 } 2569 2570 mbDropPos = sal_False; 2571 mnDropPos = 0; 2572 } 2573 } 2574 2575 // ----------------------------------------------------------------------- 2576 2577 sal_Bool TabBar::SwitchPage( const Point& rPos ) 2578 { 2579 sal_Bool bSwitch = sal_False; 2580 sal_uInt16 nSwitchId = GetPageId( rPos ); 2581 if ( !nSwitchId ) 2582 EndSwitchPage(); 2583 else 2584 { 2585 if ( nSwitchId != mnSwitchId ) 2586 { 2587 mnSwitchId = nSwitchId; 2588 mnSwitchTime = Time::GetSystemTicks(); 2589 } 2590 else 2591 { 2592 // Erst nach 500 ms umschalten 2593 if ( mnSwitchId != GetCurPageId() ) 2594 { 2595 if ( Time::GetSystemTicks() > mnSwitchTime+500 ) 2596 { 2597 mbInSwitching = sal_True; 2598 if ( ImplDeactivatePage() ) 2599 { 2600 SetCurPageId( mnSwitchId ); 2601 Update(); 2602 ImplActivatePage(); 2603 ImplSelect(); 2604 bSwitch = sal_True; 2605 } 2606 mbInSwitching = sal_False; 2607 } 2608 } 2609 } 2610 } 2611 2612 return bSwitch; 2613 } 2614 2615 // ----------------------------------------------------------------------- 2616 2617 void TabBar::EndSwitchPage() 2618 { 2619 mnSwitchTime = 0; 2620 mnSwitchId = 0; 2621 } 2622 2623 // ----------------------------------------------------------------------- 2624 2625 void TabBar::SetStyle( WinBits nStyle ) 2626 { 2627 mnWinStyle = nStyle; 2628 ImplInitControls(); 2629 // Evtl. Controls neu anordnen 2630 if ( IsReallyVisible() && IsUpdateMode() ) 2631 Resize(); 2632 } 2633 2634 // ----------------------------------------------------------------------- 2635 2636 Size TabBar::CalcWindowSizePixel() const 2637 { 2638 long nWidth = 0; 2639 2640 if ( mpItemList->Count() ) 2641 { 2642 ((TabBar*)this)->ImplCalcWidth(); 2643 ImplTabBarItem* pItem = mpItemList->First(); 2644 while ( pItem ) 2645 { 2646 nWidth += pItem->mnWidth; 2647 pItem = mpItemList->Next(); 2648 } 2649 nWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2; 2650 } 2651 2652 return Size( nWidth, GetSettings().GetStyleSettings().GetScrollBarSize() ); 2653 } 2654 // ----------------------------------------------------------------------- 2655 2656 Rectangle TabBar::GetPageArea() const 2657 { 2658 return Rectangle( Point( mnOffX, mnOffY ), Size( mnLastOffX-mnOffX+1, GetSizePixel().Height()-mnOffY ) ); 2659 } 2660 2661 // ----------------------------------------------------------------------- 2662 2663 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > TabBar::CreateAccessible() 2664 { 2665 return mpImpl->maAccessibleFactory.getFactory().createAccessibleTabBar( *this ); 2666 } 2667 2668 /* vim: set noet sw=4 ts=4: */ 2669