1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 // MARKER(update_precomp.py): autogen include statement, do not remove 30 #include "precompiled_svtools.hxx" 31 32 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 33 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 34 #include <comphelper/processfactory.hxx> 35 36 #include <vcl/dockwin.hxx> 37 #include <vcl/decoview.hxx> 38 #include <vcl/image.hxx> 39 #include <vcl/taskpanelist.hxx> 40 #include <vcl/toolbox.hxx> 41 42 #include "svtools/valueset.hxx" 43 #include "svtools/toolbarmenu.hxx" 44 #include "toolbarmenuimp.hxx" 45 46 using ::rtl::OUString; 47 using namespace ::com::sun::star::uno; 48 using namespace ::com::sun::star::lang; 49 using namespace ::com::sun::star::frame; 50 using namespace ::com::sun::star::accessibility; 51 52 namespace svtools { 53 54 // -------------------------------------------------------------------- 55 56 static Window* GetTopMostParentSystemWindow( Window* pWindow ) 57 { 58 OSL_ASSERT( pWindow ); 59 if ( pWindow ) 60 { 61 // ->manually search topmost system window 62 // required because their might be another system window between this and the top window 63 pWindow = pWindow->GetParent(); 64 SystemWindow* pTopMostSysWin = NULL; 65 while ( pWindow ) 66 { 67 if ( pWindow->IsSystemWindow() ) 68 pTopMostSysWin = (SystemWindow*)pWindow; 69 pWindow = pWindow->GetParent(); 70 } 71 pWindow = pTopMostSysWin; 72 OSL_ASSERT( pWindow ); 73 return pWindow; 74 } 75 76 return NULL; 77 } 78 79 // -------------------------------------------------------------------- 80 81 void ToolbarMenuEntry::init( int nEntryId, MenuItemBits nBits ) 82 { 83 mnEntryId = nEntryId; 84 mnBits = nBits; 85 86 mbHasText = false; 87 mbHasImage = false; 88 mbChecked = false; 89 mbEnabled = true; 90 91 mpControl = NULL; 92 } 93 94 // -------------------------------------------------------------------- 95 96 ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const String& rText, MenuItemBits nBits ) 97 : mrMenu( rMenu ) 98 { 99 init( nEntryId, nBits ); 100 101 maText = rText; 102 mbHasText = true; 103 } 104 105 // -------------------------------------------------------------------- 106 107 ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, MenuItemBits nBits ) 108 : mrMenu( rMenu ) 109 { 110 init( nEntryId, nBits ); 111 112 maImage = rImage; 113 mbHasImage = true; 114 } 115 116 // -------------------------------------------------------------------- 117 118 ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, const String& rText, MenuItemBits nBits ) 119 : mrMenu( rMenu ) 120 { 121 init( nEntryId, nBits ); 122 123 maText = rText; 124 mbHasText = true; 125 126 maImage = rImage; 127 mbHasImage = true; 128 } 129 130 // -------------------------------------------------------------------- 131 132 ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, Control* pControl, MenuItemBits nBits ) 133 : mrMenu( rMenu ) 134 { 135 init( nEntryId, nBits ); 136 137 if( pControl ) 138 { 139 mpControl = pControl; 140 mpControl->Show(); 141 } 142 } 143 144 // -------------------------------------------------------------------- 145 146 ToolbarMenuEntry::~ToolbarMenuEntry() 147 { 148 if( mxAccContext.is() ) 149 { 150 Reference< XComponent > xComponent( mxAccContext, UNO_QUERY ); 151 if( xComponent.is() ) 152 xComponent->dispose(); 153 mxAccContext.clear(); 154 } 155 delete mpControl; 156 } 157 158 // -------------------------------------------------------------------- 159 160 const Reference< XAccessibleContext >& ToolbarMenuEntry::GetAccessible( bool bCreate /* = false */ ) 161 { 162 if( !mxAccContext.is() && bCreate ) 163 { 164 if( mpControl ) 165 { 166 mxAccContext = Reference< XAccessibleContext >( mpControl->GetAccessible( sal_True ), UNO_QUERY ); 167 } 168 else 169 { 170 mxAccContext = Reference< XAccessibleContext >( new ToolbarMenuEntryAcc( this ) ); 171 } 172 } 173 174 return mxAccContext; 175 } 176 177 // -------------------------------------------------------------------- 178 179 sal_Int32 ToolbarMenuEntry::getAccessibleChildCount() throw (RuntimeException) 180 { 181 if( mpControl ) 182 { 183 const Reference< XAccessibleContext >& xContext = GetAccessible( true ); 184 if( xContext.is() ) 185 { 186 return xContext->getAccessibleChildCount(); 187 } 188 } 189 return 1; 190 } 191 192 // -------------------------------------------------------------------- 193 194 Reference< XAccessible > ToolbarMenuEntry::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException) 195 { 196 const Reference< XAccessibleContext >& xContext = GetAccessible( true ); 197 if( mpControl ) 198 { 199 if( xContext.is() ) 200 { 201 return xContext->getAccessibleChild(index); 202 } 203 } 204 else if( index == 0 ) 205 { 206 Reference< XAccessible > xRet( xContext, UNO_QUERY ); 207 if( xRet.is() ) 208 return xRet; 209 } 210 211 throw IndexOutOfBoundsException(); 212 } 213 214 // -------------------------------------------------------------------- 215 216 ToolbarMenu_Impl::ToolbarMenu_Impl( ToolbarMenu& rMenu, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame ) 217 : mrMenu( rMenu ) 218 , mxFrame( xFrame ) 219 , mxServiceManager( ::comphelper::getProcessServiceFactory() ) 220 , mnCheckPos(0) 221 , mnImagePos(0) 222 , mnTextPos(0) 223 , mnHighlightedEntry(-1) 224 , mnSelectedEntry(-1) 225 , mnLastColumn(0) 226 { 227 } 228 229 // -------------------------------------------------------------------- 230 231 ToolbarMenu_Impl::~ToolbarMenu_Impl() 232 { 233 setAccessible( 0 ); 234 } 235 236 // -------------------------------------------------------------------- 237 238 void ToolbarMenu_Impl::setAccessible( ToolbarMenuAcc* pAccessible ) 239 { 240 if( mxAccessible.get() != pAccessible ) 241 { 242 if( mxAccessible.is() ) 243 mxAccessible->dispose(); 244 245 mxAccessible.set( pAccessible ); 246 } 247 } 248 249 // ----------------------------------------------------------------------- 250 251 void ToolbarMenu_Impl::fireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ) 252 { 253 if( mxAccessible.is() ) 254 mxAccessible->FireAccessibleEvent( nEventId, rOldValue, rNewValue ); 255 } 256 257 // ----------------------------------------------------------------------- 258 259 bool ToolbarMenu_Impl::hasAccessibleListeners() 260 { 261 return( mxAccessible.is() && mxAccessible->HasAccessibleListeners() ); 262 } 263 264 // -------------------------------------------------------------------- 265 266 sal_Int32 ToolbarMenu_Impl::getAccessibleChildCount() throw (RuntimeException) 267 { 268 sal_Int32 nCount = 0; 269 const int nEntryCount = maEntryVector.size(); 270 for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) 271 { 272 ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; 273 if( pEntry ) 274 { 275 if( pEntry->mpControl ) 276 { 277 nCount += pEntry->getAccessibleChildCount(); 278 } 279 else 280 { 281 nCount += 1; 282 } 283 } 284 } 285 286 return nCount; 287 } 288 289 // -------------------------------------------------------------------- 290 291 Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException) 292 { 293 const int nEntryCount = maEntryVector.size(); 294 for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) 295 { 296 ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; 297 if( pEntry ) 298 { 299 const sal_Int32 nCount = pEntry->getAccessibleChildCount(); 300 if( index < nCount ) 301 { 302 return pEntry->getAccessibleChild( index ); 303 } 304 index -= nCount; 305 } 306 } 307 308 throw IndexOutOfBoundsException(); 309 } 310 311 // -------------------------------------------------------------------- 312 313 Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( Control* pControl, sal_Int32 childIndex ) throw (IndexOutOfBoundsException, RuntimeException) 314 { 315 const int nEntryCount = maEntryVector.size(); 316 for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) 317 { 318 ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; 319 if( pEntry && (pEntry->mpControl == pControl) ) 320 { 321 return pEntry->getAccessibleChild( childIndex ); 322 } 323 } 324 325 throw IndexOutOfBoundsException(); 326 } 327 328 // -------------------------------------------------------------------- 329 330 void ToolbarMenu_Impl::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 331 { 332 const int nEntryCount = maEntryVector.size(); 333 for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) 334 { 335 ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; 336 if( pEntry ) 337 { 338 const sal_Int32 nCount = pEntry->getAccessibleChildCount(); 339 if( nChildIndex < nCount ) 340 { 341 if( pEntry->mpControl ) 342 { 343 Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW ); 344 xSel->selectAccessibleChild(nChildIndex); 345 } 346 else if( pEntry->mnEntryId != TITLE_ID ) 347 { 348 mrMenu.implSelectEntry( nEntry ); 349 } 350 return; 351 } 352 nChildIndex -= nCount; 353 } 354 } 355 356 throw IndexOutOfBoundsException(); 357 } 358 359 // -------------------------------------------------------------------- 360 361 sal_Bool ToolbarMenu_Impl::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 362 { 363 const int nEntryCount = maEntryVector.size(); 364 for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) 365 { 366 ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; 367 if( pEntry ) 368 { 369 const sal_Int32 nCount = pEntry->getAccessibleChildCount(); 370 if( nChildIndex < nCount ) 371 { 372 if( mnHighlightedEntry == nEntry ) 373 { 374 if( pEntry->mpControl ) 375 { 376 Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW ); 377 xSel->isAccessibleChildSelected(nChildIndex); 378 } 379 return true; 380 } 381 else 382 { 383 return false; 384 } 385 } 386 nChildIndex -= nCount; 387 } 388 } 389 390 throw IndexOutOfBoundsException(); 391 } 392 393 // -------------------------------------------------------------------- 394 395 void ToolbarMenu_Impl::clearAccessibleSelection() 396 { 397 if( mnHighlightedEntry != -1 ) 398 { 399 mrMenu.implHighlightEntry( mnHighlightedEntry, false ); 400 mnHighlightedEntry = -1; 401 } 402 } 403 404 405 // -------------------------------------------------------------------- 406 407 void ToolbarMenu_Impl::notifyHighlightedEntry() 408 { 409 if( hasAccessibleListeners() ) 410 { 411 ToolbarMenuEntry* pEntry = implGetEntry( mnHighlightedEntry ); 412 if( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) ) 413 { 414 Any aNew; 415 Any aOld( mxOldSelection ); 416 if( pEntry->mpControl ) 417 { 418 sal_Int32 nChildIndex = 0; 419 // todo: if other controls than ValueSet are allowed, addapt this code 420 ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl ); 421 if( pValueSet ) 422 nChildIndex = static_cast< sal_Int32 >( pValueSet->GetItemPos( pValueSet->GetSelectItemId() ) ); 423 424 if( nChildIndex >= pEntry->getAccessibleChildCount() ) 425 return; 426 427 aNew <<= getAccessibleChild( pEntry->mpControl, nChildIndex ); 428 } 429 else 430 { 431 aNew <<= pEntry->GetAccessible(true); 432 } 433 434 fireAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOld, aNew ); 435 fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOld, aNew ); 436 fireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), Any( AccessibleStateType::FOCUSED ) ); 437 aNew >>= mxOldSelection; 438 } 439 } 440 } 441 442 // -------------------------------------------------------------------- 443 444 ToolbarMenuEntry* ToolbarMenu_Impl::implGetEntry( int nEntry ) const 445 { 446 if( (nEntry < 0) || (nEntry >= (int)maEntryVector.size() ) ) 447 return NULL; 448 449 return maEntryVector[nEntry]; 450 } 451 452 453 // -------------------------------------------------------------------- 454 455 IMPL_LINK( ToolbarMenu, HighlightHdl, Control *, pControl ) 456 { 457 (void)pControl; 458 mpImpl->notifyHighlightedEntry(); 459 return 0; 460 } 461 462 // ==================================================================== 463 464 ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, WinBits nBits ) 465 : DockingWindow(pParentWindow, nBits) 466 { 467 implInit(rFrame); 468 } 469 470 // -------------------------------------------------------------------- 471 472 ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, const ResId& rResId ) 473 : DockingWindow(pParentWindow, rResId) 474 { 475 implInit(rFrame); 476 } 477 478 // -------------------------------------------------------------------- 479 480 void ToolbarMenu::implInit(const Reference< XFrame >& rFrame) 481 { 482 mpImpl = new ToolbarMenu_Impl( *this, rFrame ); 483 484 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 485 SetControlBackground( rStyleSettings.GetMenuColor() ); 486 487 initWindow(); 488 489 Window* pWindow = GetTopMostParentSystemWindow( this ); 490 if ( pWindow ) 491 ((SystemWindow *)pWindow)->GetTaskPaneList()->AddWindow( this ); 492 } 493 494 // -------------------------------------------------------------------- 495 496 ToolbarMenu::~ToolbarMenu() 497 { 498 Window* pWindow = GetTopMostParentSystemWindow( this ); 499 if ( pWindow ) 500 ((SystemWindow *)pWindow)->GetTaskPaneList()->RemoveWindow( this ); 501 502 if ( mpImpl->mxStatusListener.is() ) 503 { 504 mpImpl->mxStatusListener->dispose(); 505 mpImpl->mxStatusListener.clear(); 506 } 507 508 // delete all menu entries 509 const int nEntryCount = mpImpl->maEntryVector.size(); 510 int nEntry; 511 for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) 512 { 513 delete mpImpl->maEntryVector[nEntry]; 514 } 515 516 delete mpImpl; 517 } 518 519 // -------------------------------------------------------------------- 520 521 int ToolbarMenu::getSelectedEntryId() const 522 { 523 ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnSelectedEntry ); 524 return pEntry ? pEntry->mnEntryId : -1; 525 } 526 527 // -------------------------------------------------------------------- 528 529 int ToolbarMenu::getHighlightedEntryId() const 530 { 531 ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry ); 532 return pEntry ? pEntry->mnEntryId : -1; 533 } 534 535 // -------------------------------------------------------------------- 536 537 void ToolbarMenu::checkEntry( int nEntryId, bool bChecked ) 538 { 539 ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); 540 if( pEntry && pEntry->mbChecked != bChecked ) 541 { 542 pEntry->mbChecked = bChecked; 543 Invalidate(); 544 } 545 } 546 547 // -------------------------------------------------------------------- 548 549 bool ToolbarMenu::isEntryChecked( int nEntryId ) const 550 { 551 ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); 552 return pEntry && pEntry->mbChecked; 553 } 554 555 // -------------------------------------------------------------------- 556 557 void ToolbarMenu::enableEntry( int nEntryId, bool bEnable ) 558 { 559 ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); 560 if( pEntry && pEntry->mbEnabled != bEnable ) 561 { 562 pEntry->mbEnabled = bEnable; 563 if( pEntry->mpControl ) 564 { 565 pEntry->mpControl->Enable( bEnable ); 566 567 // hack for the valueset to make it paint itself anew 568 pEntry->mpControl->Resize(); 569 } 570 Invalidate(); 571 } 572 } 573 574 // -------------------------------------------------------------------- 575 576 bool ToolbarMenu::isEntryEnabled( int nEntryId ) const 577 { 578 ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); 579 return pEntry && pEntry->mbEnabled; 580 } 581 582 // -------------------------------------------------------------------- 583 584 void ToolbarMenu::setEntryText( int nEntryId, const String& rStr ) 585 { 586 ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); 587 if( pEntry && pEntry->maText != rStr ) 588 { 589 pEntry->maText = rStr; 590 mpImpl->maSize = implCalcSize(); 591 if( IsVisible() ) 592 Invalidate(); 593 } 594 } 595 596 // -------------------------------------------------------------------- 597 598 const String& ToolbarMenu::getEntryText( int nEntryId ) const 599 { 600 ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); 601 if( pEntry ) 602 return pEntry->maText; 603 else 604 { 605 static String aEmptyStr; 606 return aEmptyStr; 607 } 608 } 609 610 // -------------------------------------------------------------------- 611 612 void ToolbarMenu::setEntryImage( int nEntryId, const Image& rImage ) 613 { 614 ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); 615 if( pEntry && pEntry->maImage != rImage ) 616 { 617 pEntry->maImage = rImage; 618 mpImpl->maSize = implCalcSize(); 619 if( IsVisible() ) 620 Invalidate(); 621 } 622 } 623 624 // -------------------------------------------------------------------- 625 626 const Image& ToolbarMenu::getEntryImage( int nEntryId ) const 627 { 628 ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); 629 if( pEntry ) 630 return pEntry->maImage; 631 else 632 { 633 static Image aEmptyImage; 634 return aEmptyImage; 635 } 636 } 637 638 // -------------------------------------------------------------------- 639 640 void ToolbarMenu::initWindow() 641 { 642 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 643 644 SetPointFont( rStyleSettings.GetMenuFont() ); 645 SetBackground( Wallpaper( GetControlBackground() ) ); 646 SetTextColor( rStyleSettings.GetMenuTextColor() ); 647 SetTextFillColor(); 648 SetLineColor(); 649 650 mpImpl->maSize = implCalcSize(); 651 } 652 653 // -------------------------------------------------------------------- 654 655 Size ToolbarMenu::implCalcSize() 656 { 657 const long nFontHeight = GetTextHeight(); 658 long nExtra = nFontHeight/4; 659 660 Size aSz; 661 Size aMaxImgSz; 662 long nMaxTextWidth = 0; 663 long nMinMenuItemHeight = nFontHeight+2; 664 sal_Bool bCheckable = sal_False; 665 666 const int nEntryCount = mpImpl->maEntryVector.size(); 667 int nEntry; 668 669 const StyleSettings& rSettings = GetSettings().GetStyleSettings(); 670 const bool bUseImages = rSettings.GetUseImagesInMenus(); 671 672 // get maximum image size 673 if( bUseImages ) 674 { 675 for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) 676 { 677 ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; 678 if( pEntry && pEntry->mbHasImage ) 679 { 680 Size aImgSz( pEntry->maImage.GetSizePixel() ); 681 nMinMenuItemHeight = std::max( nMinMenuItemHeight, aImgSz.Height() + 6 ); 682 aMaxImgSz.Width() = std::max( aMaxImgSz.Width(), aImgSz.Width() ); 683 } 684 } 685 } 686 687 mpImpl->mnCheckPos = nExtra; 688 mpImpl->mnImagePos = nExtra; 689 mpImpl->mnTextPos = mpImpl->mnImagePos + aMaxImgSz.Width(); 690 691 if ( aMaxImgSz.Width() ) 692 mpImpl->mnTextPos += std::max( nExtra, 7L ); 693 if ( bCheckable ) 694 mpImpl->mnTextPos += 16; 695 696 // set heights, calc maximum width 697 for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) 698 { 699 ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; 700 701 if( pEntry ) 702 { 703 if ( ( pEntry->mnBits ) & ( MIB_RADIOCHECK | MIB_CHECKABLE ) ) 704 bCheckable = sal_True; 705 706 // Text: 707 if( pEntry->mbHasText || pEntry->mbHasImage ) 708 { 709 pEntry->maSize.Height() = nMinMenuItemHeight; 710 711 if( pEntry->mbHasText ) 712 { 713 long nTextWidth = GetCtrlTextWidth( pEntry->maText ) + mpImpl->mnTextPos + nExtra; 714 nMaxTextWidth = std::max( nTextWidth, nMaxTextWidth ); 715 } 716 } 717 // Control: 718 else if( pEntry->mpControl ) 719 { 720 Size aControlSize( pEntry->mpControl->GetOutputSizePixel() ); 721 722 nMaxTextWidth = std::max( aControlSize.Width(), nMaxTextWidth ); 723 pEntry->maSize.Height() = aControlSize.Height() + 1; 724 } 725 726 } 727 } 728 729 aSz.Width() = nMaxTextWidth + (BORDER_X<<1); 730 731 // positionate controls 732 int nY = BORDER_Y; 733 for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) 734 { 735 ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; 736 737 if( pEntry ) 738 { 739 pEntry->maSize.Width() = nMaxTextWidth; 740 741 if( pEntry->mpControl ) 742 { 743 Size aControlSize( pEntry->mpControl->GetOutputSizePixel() ); 744 Point aControlPos( (aSz.Width() - aControlSize.Width())>>1, nY); 745 746 pEntry->mpControl->SetPosPixel( aControlPos ); 747 748 pEntry->maRect = Rectangle( aControlPos, aControlSize ); 749 } 750 else 751 { 752 pEntry->maRect = Rectangle( Point( 0, nY ), pEntry->maSize ); 753 } 754 755 nY += pEntry->maSize.Height(); 756 } 757 else 758 { 759 nY += SEPARATOR_HEIGHT; 760 } 761 } 762 763 aSz.Height() += nY + BORDER_Y; 764 765 return aSz; 766 } 767 768 // -------------------------------------------------------------------- 769 770 void ToolbarMenu::highlightFirstEntry() 771 { 772 implChangeHighlightEntry( 0 ); 773 } 774 775 // -------------------------------------------------------------------- 776 777 void ToolbarMenu::GetFocus() 778 { 779 if( mpImpl->mnHighlightedEntry == -1 ) 780 implChangeHighlightEntry( 0 ); 781 782 DockingWindow::GetFocus(); 783 } 784 785 // -------------------------------------------------------------------- 786 787 void ToolbarMenu::LoseFocus() 788 { 789 if( mpImpl->mnHighlightedEntry != -1 ) 790 implChangeHighlightEntry( -1 ); 791 792 DockingWindow::LoseFocus(); 793 } 794 795 // -------------------------------------------------------------------- 796 797 void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, MenuItemBits nItemBits ) 798 { 799 appendEntry( new ToolbarMenuEntry( *this, nEntryId, rStr, nItemBits ) ); 800 } 801 802 // -------------------------------------------------------------------- 803 804 void ToolbarMenu::appendEntry( int nEntryId, const Image& rImage, MenuItemBits nItemBits ) 805 { 806 appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, nItemBits ) ); 807 } 808 809 // -------------------------------------------------------------------- 810 811 void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, const Image& rImage, MenuItemBits nItemBits ) 812 { 813 appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, rStr, nItemBits ) ); 814 } 815 816 // -------------------------------------------------------------------- 817 818 void ToolbarMenu::appendEntry( int nEntryId, Control* pControl, MenuItemBits nItemBits ) 819 { 820 appendEntry( new ToolbarMenuEntry( *this, nEntryId, pControl, nItemBits ) ); 821 } 822 823 // -------------------------------------------------------------------- 824 825 void ToolbarMenu::appendEntry( ToolbarMenuEntry* pEntry ) 826 { 827 mpImpl->maEntryVector.push_back( pEntry ); 828 mpImpl->maSize = implCalcSize(); 829 if( IsVisible() ) 830 Invalidate(); 831 } 832 833 // -------------------------------------------------------------------- 834 835 void ToolbarMenu::appendSeparator() 836 { 837 appendEntry( 0 ); 838 } 839 840 // -------------------------------------------------------------------- 841 842 /** creates an empty ValueSet that is initialized and can be inserted with appendEntry. */ 843 ValueSet* ToolbarMenu::createEmptyValueSetControl() 844 { 845 ValueSet* pSet = new ValueSet( this, WB_TABSTOP | WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NOBORDER | WB_NO_DIRECTSELECT ); 846 pSet->EnableFullItemMode( sal_False ); 847 pSet->SetColor( GetControlBackground() ); 848 pSet->SetHighlightHdl( LINK( this, ToolbarMenu, HighlightHdl ) ); 849 return pSet; 850 } 851 852 // -------------------------------------------------------------------- 853 854 ToolbarMenuEntry* ToolbarMenu::implGetEntry( int nEntry ) const 855 { 856 return mpImpl->implGetEntry( nEntry ); 857 } 858 859 // -------------------------------------------------------------------- 860 861 ToolbarMenuEntry* ToolbarMenu::implSearchEntry( int nEntryId ) const 862 { 863 const int nEntryCount = mpImpl->maEntryVector.size(); 864 int nEntry; 865 for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) 866 { 867 ToolbarMenuEntry* p = mpImpl->maEntryVector[nEntry]; 868 if( p && p->mnEntryId == nEntryId ) 869 { 870 return p; 871 } 872 } 873 874 return NULL; 875 } 876 877 // -------------------------------------------------------------------- 878 879 void ToolbarMenu::implHighlightEntry( int nHighlightEntry, bool bHighlight ) 880 { 881 Size aSz( GetOutputSizePixel() ); 882 long nX = 0, nY = 0; 883 884 const int nEntryCount = mpImpl->maEntryVector.size(); 885 int nEntry; 886 for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) 887 { 888 ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; 889 if( pEntry && (nEntry == nHighlightEntry) ) 890 { 891 // no highlights for controls only items 892 if( pEntry->mpControl ) 893 { 894 if( !bHighlight ) 895 { 896 ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl ); 897 if( pValueSet ) 898 { 899 pValueSet->SetNoSelection(); 900 } 901 } 902 break; 903 } 904 905 bool bRestoreLineColor = false; 906 Color oldLineColor; 907 bool bDrawItemRect = true; 908 909 Rectangle aItemRect( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) ); 910 if ( pEntry->mnBits & MIB_POPUPSELECT ) 911 { 912 long nFontHeight = GetTextHeight(); 913 aItemRect.Right() -= nFontHeight + nFontHeight/4; 914 } 915 916 if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) ) 917 { 918 Size aPxSize( GetOutputSizePixel() ); 919 Push( PUSH_CLIPREGION ); 920 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) ) ); 921 Rectangle aCtrlRect( Point( nX, 0 ), Size( aPxSize.Width()-nX, aPxSize.Height() ) ); 922 DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, 923 aCtrlRect, 924 CTRL_STATE_ENABLED, 925 ImplControlValue(), 926 OUString() ); 927 if( bHighlight && IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) ) 928 { 929 bDrawItemRect = false; 930 if( sal_False == DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM, 931 aItemRect, 932 CTRL_STATE_SELECTED | ( pEntry->mbEnabled? CTRL_STATE_ENABLED: 0 ), 933 ImplControlValue(), 934 OUString() ) ) 935 { 936 bDrawItemRect = bHighlight; 937 } 938 } 939 else 940 bDrawItemRect = bHighlight; 941 Pop(); 942 } 943 if( bDrawItemRect ) 944 { 945 if ( bHighlight ) 946 { 947 if( pEntry->mbEnabled ) 948 SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() ); 949 else 950 { 951 SetFillColor(); 952 oldLineColor = GetLineColor(); 953 SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() ); 954 bRestoreLineColor = true; 955 } 956 } 957 else 958 SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() ); 959 960 DrawRect( aItemRect ); 961 } 962 implPaint( pEntry, bHighlight ); 963 if( bRestoreLineColor ) 964 SetLineColor( oldLineColor ); 965 break; 966 } 967 968 nY += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT; 969 } 970 } 971 972 // -------------------------------------------------------------------- 973 974 void ToolbarMenu::implSelectEntry( int nSelectedEntry ) 975 { 976 mpImpl->mnSelectedEntry = nSelectedEntry; 977 978 ToolbarMenuEntry* pEntry = NULL; 979 if( nSelectedEntry != -1 ) 980 pEntry = mpImpl->maEntryVector[ nSelectedEntry ]; 981 982 if( pEntry ) 983 mpImpl->maSelectHdl.Call( this ); 984 } 985 986 // -------------------------------------------------------------------- 987 988 void ToolbarMenu::MouseButtonDown( const MouseEvent& rMEvt ) 989 { 990 implHighlightEntry( rMEvt, true ); 991 992 implSelectEntry( mpImpl->mnHighlightedEntry ); 993 } 994 995 // -------------------------------------------------------------------- 996 997 void ToolbarMenu::MouseButtonUp( const MouseEvent& ) 998 { 999 } 1000 1001 // -------------------------------------------------------------------- 1002 1003 void ToolbarMenu::MouseMove( const MouseEvent& rMEvt ) 1004 { 1005 if ( !IsVisible() ) 1006 return; 1007 1008 implHighlightEntry( rMEvt, false ); 1009 } 1010 1011 // -------------------------------------------------------------------- 1012 1013 void ToolbarMenu::implHighlightEntry( const MouseEvent& rMEvt, bool bMBDown ) 1014 { 1015 long nY = 0; 1016 long nMouseY = rMEvt.GetPosPixel().Y(); 1017 Size aOutSz = GetOutputSizePixel(); 1018 if ( ( nMouseY >= 0 ) && ( nMouseY < aOutSz.Height() ) ) 1019 { 1020 bool bHighlighted = sal_False; 1021 1022 const int nEntryCount = mpImpl->maEntryVector.size(); 1023 int nEntry; 1024 for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) 1025 { 1026 ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; 1027 if( pEntry ) 1028 { 1029 long nOldY = nY; 1030 nY += pEntry->maSize.Height(); 1031 1032 if( pEntry->mnEntryId != TITLE_ID ) 1033 { 1034 if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) ) 1035 { 1036 if( bMBDown ) 1037 { 1038 if( nEntry != mpImpl->mnHighlightedEntry ) 1039 { 1040 implChangeHighlightEntry( nEntry ); 1041 } 1042 } 1043 else 1044 { 1045 if ( nEntry != mpImpl->mnHighlightedEntry ) 1046 { 1047 implChangeHighlightEntry( nEntry ); 1048 } 1049 } 1050 bHighlighted = true; 1051 } 1052 } 1053 } 1054 else 1055 { 1056 nY += SEPARATOR_HEIGHT; 1057 } 1058 } 1059 if ( !bHighlighted ) 1060 implChangeHighlightEntry( -1 ); 1061 } 1062 else 1063 { 1064 implChangeHighlightEntry( -1 ); 1065 } 1066 } 1067 1068 // -------------------------------------------------------------------- 1069 1070 void ToolbarMenu::implChangeHighlightEntry( int nEntry ) 1071 { 1072 if( mpImpl->mnHighlightedEntry != -1 ) 1073 { 1074 implHighlightEntry( mpImpl->mnHighlightedEntry, false ); 1075 } 1076 1077 mpImpl->mnHighlightedEntry = nEntry; 1078 Invalidate(); 1079 1080 if( mpImpl->mnHighlightedEntry != -1 ) 1081 { 1082 implHighlightEntry( mpImpl->mnHighlightedEntry, true ); 1083 } 1084 1085 mpImpl->notifyHighlightedEntry(); 1086 } 1087 1088 // -------------------------------------------------------------------- 1089 1090 static bool implCheckSubControlCursorMove( Control* pControl, bool bUp, int& nLastColumn ) 1091 { 1092 ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); 1093 if( pValueSet ) 1094 { 1095 sal_uInt16 nItemPos = pValueSet->GetItemPos( pValueSet->GetSelectItemId() ); 1096 if( nItemPos != VALUESET_ITEM_NOTFOUND ) 1097 { 1098 const sal_uInt16 nColCount = pValueSet->GetColCount(); 1099 const sal_uInt16 nLine = nItemPos / nColCount; 1100 1101 nLastColumn = nItemPos - (nLine * nColCount); 1102 1103 if( bUp ) 1104 { 1105 return nLine > 0; 1106 } 1107 else 1108 { 1109 const sal_uInt16 nLineCount = (pValueSet->GetItemCount() + nColCount - 1) / nColCount; 1110 return (nLine+1) < nLineCount; 1111 } 1112 } 1113 } 1114 1115 return false; 1116 } 1117 1118 // -------------------------------------------------------------------- 1119 1120 ToolbarMenuEntry* ToolbarMenu::implCursorUpDown( bool bUp, bool bHomeEnd ) 1121 { 1122 int n = 0, nLoop = 0; 1123 if( !bHomeEnd ) 1124 { 1125 n = mpImpl->mnHighlightedEntry; 1126 if( n == -1 ) 1127 { 1128 if( bUp ) 1129 n = 0; 1130 else 1131 n = mpImpl->maEntryVector.size()-1; 1132 } 1133 else 1134 { 1135 // if we have a currently selected entry and 1136 // cursor keys are used than check if this entry 1137 // has a control that can use those cursor keys 1138 ToolbarMenuEntry* pData = mpImpl->maEntryVector[n]; 1139 if( pData && pData->mpControl && !pData->mbHasText ) 1140 { 1141 if( implCheckSubControlCursorMove( pData->mpControl, bUp, mpImpl->mnLastColumn ) ) 1142 return pData; 1143 } 1144 } 1145 nLoop = n; 1146 } 1147 else 1148 { 1149 // absolute positioning 1150 if( bUp ) 1151 { 1152 n = mpImpl->maEntryVector.size(); 1153 nLoop = n-1; 1154 } 1155 else 1156 { 1157 n = -1; 1158 nLoop = mpImpl->maEntryVector.size()-1; 1159 } 1160 } 1161 1162 do 1163 { 1164 if( bUp ) 1165 { 1166 if ( n ) 1167 n--; 1168 else 1169 if( mpImpl->mnHighlightedEntry == -1 ) 1170 n = mpImpl->maEntryVector.size()-1; 1171 else 1172 break; 1173 } 1174 else 1175 { 1176 if( n < ((int)mpImpl->maEntryVector.size()-1) ) 1177 n++; 1178 else 1179 if( mpImpl->mnHighlightedEntry == -1 ) 1180 n = 0; 1181 else 1182 break; 1183 } 1184 1185 ToolbarMenuEntry* pData = mpImpl->maEntryVector[n]; 1186 if( pData && (pData->mnEntryId != TITLE_ID) ) 1187 { 1188 implChangeHighlightEntry( n ); 1189 return pData; 1190 } 1191 } while ( n != nLoop ); 1192 1193 return 0; 1194 } 1195 1196 // -------------------------------------------------------------------- 1197 1198 void ToolbarMenu_Impl::implHighlightControl( sal_uInt16 nCode, Control* pControl ) 1199 { 1200 ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); 1201 if( pValueSet ) 1202 { 1203 const sal_uInt16 nItemCount = pValueSet->GetItemCount(); 1204 sal_uInt16 nItemPos = VALUESET_ITEM_NOTFOUND; 1205 switch( nCode ) 1206 { 1207 case KEY_UP: 1208 { 1209 const sal_uInt16 nColCount = pValueSet->GetColCount(); 1210 const sal_uInt16 nLastLine = nItemCount / nColCount; 1211 nItemPos = std::min( ((nLastLine-1) * nColCount) + mnLastColumn, nItemCount-1 ); 1212 break; 1213 } 1214 case KEY_DOWN: 1215 nItemPos = std::min( mnLastColumn, nItemCount-1 ); 1216 break; 1217 case KEY_END: 1218 nItemPos = nItemCount -1; 1219 break; 1220 case KEY_HOME: 1221 nItemPos = 0; 1222 break; 1223 } 1224 pValueSet->SelectItem( pValueSet->GetItemId( nItemPos ) ); 1225 notifyHighlightedEntry(); 1226 } 1227 } 1228 1229 // -------------------------------------------------------------------- 1230 1231 void ToolbarMenu::KeyInput( const KeyEvent& rKEvent ) 1232 { 1233 Control* pForwardControl = 0; 1234 sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode(); 1235 switch ( nCode ) 1236 { 1237 case KEY_UP: 1238 case KEY_DOWN: 1239 { 1240 int nOldEntry = mpImpl->mnHighlightedEntry; 1241 ToolbarMenuEntry*p = implCursorUpDown( nCode == KEY_UP, false ); 1242 if( p && p->mpControl ) 1243 { 1244 if( nOldEntry != mpImpl->mnHighlightedEntry ) 1245 { 1246 mpImpl->implHighlightControl( nCode, p->mpControl ); 1247 } 1248 else 1249 { 1250 // in case we are in a system floating window, GrabFocus does not work :-/ 1251 pForwardControl = p->mpControl; 1252 } 1253 } 1254 } 1255 break; 1256 case KEY_END: 1257 case KEY_HOME: 1258 { 1259 ToolbarMenuEntry* p = implCursorUpDown( nCode == KEY_END, true ); 1260 if( p && p->mpControl ) 1261 { 1262 mpImpl->implHighlightControl( nCode, p->mpControl ); 1263 } 1264 } 1265 break; 1266 case KEY_F6: 1267 case KEY_ESCAPE: 1268 { 1269 // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document 1270 if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() ) 1271 break; 1272 1273 implSelectEntry( -1 ); 1274 } 1275 break; 1276 1277 case KEY_RETURN: 1278 { 1279 ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry ); 1280 if ( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) ) 1281 { 1282 if( pEntry->mpControl ) 1283 { 1284 pForwardControl = pEntry->mpControl; 1285 } 1286 else 1287 { 1288 implSelectEntry( mpImpl->mnHighlightedEntry ); 1289 } 1290 } 1291 } 1292 break; 1293 default: 1294 { 1295 ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry ); 1296 if ( pEntry && pEntry->mbEnabled && pEntry->mpControl && !pEntry->mbHasText ) 1297 { 1298 pForwardControl = pEntry->mpControl; 1299 } 1300 } 1301 1302 } 1303 if( pForwardControl ) 1304 pForwardControl->KeyInput( rKEvent ); 1305 1306 } 1307 1308 // -------------------------------------------------------------------- 1309 static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight ) 1310 { 1311 sal_Bool bNativeOk = sal_False; 1312 if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) ) 1313 { 1314 ImplControlValue aControlValue; 1315 ControlState nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED; 1316 1317 aControlValue.setTristateVal( BUTTONVALUE_ON ); 1318 1319 bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON, 1320 i_rRect, nState, aControlValue, 1321 rtl::OUString() ); 1322 } 1323 1324 if( ! bNativeOk ) 1325 { 1326 const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings(); 1327 Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() ); 1328 i_pWindow->DrawSelectionBackground( i_rRect, 0, i_bHighlight, sal_True, sal_False, 2, NULL, &aColor ); 1329 } 1330 } 1331 1332 static long ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, long& rRadioHeight, long &rMaxWidth ) 1333 { 1334 rMaxWidth = rCheckHeight = rRadioHeight = 0; 1335 1336 ImplControlValue aVal; 1337 Rectangle aNativeBounds; 1338 Rectangle aNativeContent; 1339 Point tmp( 0, 0 ); 1340 Rectangle aCtrlRegion( tmp, Size( 100, 15 ) ); 1341 if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK ) ) 1342 { 1343 if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP), 1344 ControlPart(PART_MENU_ITEM_CHECK_MARK), 1345 aCtrlRegion, 1346 ControlState(CTRL_STATE_ENABLED), 1347 aVal, 1348 OUString(), 1349 aNativeBounds, 1350 aNativeContent ) 1351 ) 1352 { 1353 rCheckHeight = aNativeBounds.GetHeight(); 1354 rMaxWidth = aNativeContent.GetWidth(); 1355 } 1356 } 1357 if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK ) ) 1358 { 1359 if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP), 1360 ControlPart(PART_MENU_ITEM_RADIO_MARK), 1361 aCtrlRegion, 1362 ControlState(CTRL_STATE_ENABLED), 1363 aVal, 1364 OUString(), 1365 aNativeBounds, 1366 aNativeContent ) 1367 ) 1368 { 1369 rRadioHeight = aNativeBounds.GetHeight(); 1370 rMaxWidth = Max (rMaxWidth, aNativeContent.GetWidth()); 1371 } 1372 } 1373 return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight; 1374 } 1375 1376 void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) 1377 { 1378 sal_uInt16 nBorder = 0; long nStartY = 0; // from Menu implementations, needed when we support native menu background & scrollable menu 1379 1380 long nFontHeight = GetTextHeight(); 1381 // long nExtra = nFontHeight/4; 1382 1383 long nCheckHeight = 0, nRadioHeight = 0, nMaxCheckWidth = 0; 1384 ImplGetNativeCheckAndRadioSize( this, nCheckHeight, nRadioHeight, nMaxCheckWidth ); 1385 1386 DecorationView aDecoView( this ); 1387 const StyleSettings& rSettings = GetSettings().GetStyleSettings(); 1388 const bool bUseImages = rSettings.GetUseImagesInMenus(); 1389 1390 int nOuterSpace = 0; // ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder; 1391 Point aTopLeft( nOuterSpace, nOuterSpace ), aTmpPos; 1392 1393 Size aOutSz( GetOutputSizePixel() ); 1394 const int nEntryCount = mpImpl->maEntryVector.size(); 1395 int nEntry; 1396 for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) 1397 { 1398 ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; 1399 1400 Point aPos( aTopLeft ); 1401 aPos.Y() += nBorder; 1402 aPos.Y() += nStartY; 1403 1404 1405 if( (pEntry == 0) && !pThisOnly ) 1406 { 1407 // Separator 1408 aTmpPos.Y() = aPos.Y() + ((SEPARATOR_HEIGHT-2)/2); 1409 aTmpPos.X() = aPos.X() + 2 + nOuterSpace; 1410 SetLineColor( rSettings.GetShadowColor() ); 1411 DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) ); 1412 aTmpPos.Y()++; 1413 SetLineColor( rSettings.GetLightColor() ); 1414 DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) ); 1415 SetLineColor(); 1416 } 1417 else if( !pThisOnly || ( pEntry == pThisOnly ) ) 1418 { 1419 const bool bTitle = pEntry->mnEntryId == TITLE_ID; 1420 1421 if ( pThisOnly && bHighlighted ) 1422 SetTextColor( rSettings.GetMenuHighlightTextColor() ); 1423 1424 if( aPos.Y() >= 0 ) 1425 { 1426 long nTextOffsetY = ((pEntry->maSize.Height()-nFontHeight)/2); 1427 1428 sal_uInt16 nTextStyle = 0; 1429 sal_uInt16 nSymbolStyle = 0; 1430 sal_uInt16 nImageStyle = 0; 1431 1432 if( !pEntry->mbEnabled ) 1433 { 1434 nTextStyle |= TEXT_DRAW_DISABLE; 1435 nSymbolStyle |= SYMBOL_DRAW_DISABLE; 1436 nImageStyle |= IMAGE_DRAW_DISABLE; 1437 } 1438 1439 Rectangle aOuterCheckRect( Point( aPos.X()+mpImpl->mnCheckPos, aPos.Y() ), Size( pEntry->maSize.Height(), pEntry->maSize.Height() ) ); 1440 aOuterCheckRect.Left() += 1; 1441 aOuterCheckRect.Right() -= 1; 1442 aOuterCheckRect.Top() += 1; 1443 aOuterCheckRect.Bottom() -= 1; 1444 1445 if( bTitle ) 1446 { 1447 // fill the background 1448 Rectangle aRect( aTopLeft, Size( aOutSz.Width(), pEntry->maSize.Height() ) ); 1449 SetFillColor(rSettings.GetDialogColor()); 1450 SetLineColor(); 1451 DrawRect(aRect); 1452 SetLineColor( rSettings.GetLightColor() ); 1453 DrawLine( aRect.TopLeft(), aRect.TopRight() ); 1454 SetLineColor( rSettings.GetShadowColor() ); 1455 DrawLine( aRect.BottomLeft(), aRect.BottomRight() ); 1456 } 1457 1458 // CheckMark 1459 if ( pEntry->HasCheck() ) 1460 { 1461 // draw selection transparent marker if checked 1462 // onto that either a checkmark or the item image 1463 // will be painted 1464 // however do not do this if native checks will be painted since 1465 // the selection color too often does not fit the theme's check and/or radio 1466 1467 if( !pEntry->mbHasImage ) 1468 { 1469 if( this->IsNativeControlSupported( CTRL_MENU_POPUP, 1470 (pEntry->mnBits & MIB_RADIOCHECK) 1471 ? PART_MENU_ITEM_CHECK_MARK 1472 : PART_MENU_ITEM_RADIO_MARK ) ) 1473 { 1474 ControlPart nPart = ((pEntry->mnBits & MIB_RADIOCHECK) 1475 ? PART_MENU_ITEM_RADIO_MARK 1476 : PART_MENU_ITEM_CHECK_MARK); 1477 1478 ControlState nState = 0; 1479 1480 if ( pEntry->mbChecked ) 1481 nState |= CTRL_STATE_PRESSED; 1482 1483 if ( pEntry->mbEnabled ) 1484 nState |= CTRL_STATE_ENABLED; 1485 1486 if ( bHighlighted ) 1487 nState |= CTRL_STATE_SELECTED; 1488 1489 long nCtrlHeight = (pEntry->mnBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight; 1490 aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2; 1491 aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2; 1492 1493 Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) ); 1494 DrawNativeControl( CTRL_MENU_POPUP, nPart, aCheckRect, nState, ImplControlValue(), OUString() ); 1495 } 1496 else if ( pEntry->mbChecked ) // by default do nothing for unchecked items 1497 { 1498 ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted ); 1499 1500 SymbolType eSymbol; 1501 Size aSymbolSize; 1502 if ( pEntry->mnBits & MIB_RADIOCHECK ) 1503 { 1504 eSymbol = SYMBOL_RADIOCHECKMARK; 1505 aSymbolSize = Size( nFontHeight/2, nFontHeight/2 ); 1506 } 1507 else 1508 { 1509 eSymbol = SYMBOL_CHECKMARK; 1510 aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 ); 1511 } 1512 aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2; 1513 aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2; 1514 Rectangle aRect( aTmpPos, aSymbolSize ); 1515 aDecoView.DrawSymbol( aRect, eSymbol, GetTextColor(), nSymbolStyle ); 1516 } 1517 } 1518 } 1519 1520 // Image: 1521 if( pEntry->mbHasImage && bUseImages ) 1522 { 1523 // Don't render an image for a check thing 1524 /* if((nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) || !pEntry->HasCheck() )*/ 1525 { 1526 if( pEntry->mbChecked ) 1527 ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted ); 1528 aTmpPos = aOuterCheckRect.TopLeft(); 1529 aTmpPos.X() += (aOuterCheckRect.GetWidth()-pEntry->maImage.GetSizePixel().Width())/2; 1530 aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pEntry->maImage.GetSizePixel().Height())/2; 1531 DrawImage( aTmpPos, pEntry->maImage, nImageStyle ); 1532 } 1533 } 1534 1535 // Text: 1536 if( pEntry->mbHasText ) 1537 { 1538 aTmpPos.X() = aPos.X() + (bTitle ? 4 : mpImpl->mnTextPos); 1539 aTmpPos.Y() = aPos.Y(); 1540 aTmpPos.Y() += nTextOffsetY; 1541 sal_uInt16 nStyle = nTextStyle|TEXT_DRAW_MNEMONIC; 1542 1543 DrawCtrlText( aTmpPos, pEntry->maText, 0, pEntry->maText.Len(), nStyle, NULL, NULL ); // pVector, pDisplayText ); 1544 } 1545 1546 /* 1547 // Accel 1548 if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() ) 1549 { 1550 XubString aAccText = pData->aAccelKey.GetName(); 1551 aTmpPos.X() = aOutSz.Width() - this->GetTextWidth( aAccText ); 1552 aTmpPos.X() -= 4*nExtra; 1553 1554 aTmpPos.X() -= nOuterSpace; 1555 aTmpPos.Y() = aPos.Y(); 1556 aTmpPos.Y() += nTextOffsetY; 1557 this->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle ); 1558 } 1559 */ 1560 1561 /* 1562 // SubMenu? 1563 if ( !bLayout && !bIsMenuBar && pData->pSubMenu ) 1564 { 1565 aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace; 1566 aTmpPos.Y() = aPos.Y(); 1567 aTmpPos.Y() += nExtra/2; 1568 aTmpPos.Y() += ( pEntry->maSize.Height() / 2 ) - ( nFontHeight/4 ); 1569 if ( pEntry->mnBits & MIB_POPUPSELECT ) 1570 { 1571 this->SetTextColor( rSettings.GetMenuTextColor() ); 1572 Point aTmpPos2( aPos ); 1573 aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4; 1574 aDecoView.DrawFrame( 1575 Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pEntry->maSize.Height() ) ), FRAME_DRAW_GROUP ); 1576 } 1577 aDecoView.DrawSymbol( 1578 Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ), 1579 SYMBOL_SPIN_RIGHT, this->GetTextColor(), nSymbolStyle ); 1580 // if ( pEntry->mnBits & MIB_POPUPSELECT ) 1581 // { 1582 // aTmpPos.Y() += nFontHeight/2 ; 1583 // this->SetLineColor( rSettings.GetShadowColor() ); 1584 // this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) ); 1585 // this->SetLineColor( rSettings.GetLightColor() ); 1586 // aTmpPos.Y()++; 1587 // this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) ); 1588 // this->SetLineColor(); 1589 // } 1590 } 1591 */ 1592 1593 if ( pThisOnly && bHighlighted ) 1594 { 1595 // This restores the normal menu or menu bar text 1596 // color for when it is no longer highlighted. 1597 SetTextColor( rSettings.GetMenuTextColor() ); 1598 } 1599 } 1600 } 1601 1602 aTopLeft.Y() += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT; 1603 } 1604 } 1605 1606 // -------------------------------------------------------------------- 1607 1608 void ToolbarMenu::Paint( const Rectangle& ) 1609 { 1610 SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() ); 1611 1612 implPaint(); 1613 1614 if( mpImpl->mnHighlightedEntry != -1 ) 1615 implHighlightEntry( mpImpl->mnHighlightedEntry, true ); 1616 } 1617 1618 // -------------------------------------------------------------------- 1619 1620 void ToolbarMenu::RequestHelp( const HelpEvent& rHEvt ) 1621 { 1622 DockingWindow::RequestHelp( rHEvt ); 1623 } 1624 1625 // -------------------------------------------------------------------- 1626 1627 void ToolbarMenu::StateChanged( StateChangedType nType ) 1628 { 1629 DockingWindow::StateChanged( nType ); 1630 1631 if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) ) 1632 { 1633 initWindow(); 1634 Invalidate(); 1635 } 1636 } 1637 1638 // -------------------------------------------------------------------- 1639 1640 void ToolbarMenu::DataChanged( const DataChangedEvent& rDCEvt ) 1641 { 1642 DockingWindow::DataChanged( rDCEvt ); 1643 1644 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || 1645 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || 1646 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && 1647 (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) 1648 { 1649 initWindow(); 1650 Invalidate(); 1651 } 1652 } 1653 1654 // -------------------------------------------------------------------- 1655 1656 void ToolbarMenu::Command( const CommandEvent& rCEvt ) 1657 { 1658 if ( rCEvt.GetCommand() == COMMAND_WHEEL ) 1659 { 1660 const CommandWheelData* pData = rCEvt.GetWheelData(); 1661 if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) 1662 { 1663 implCursorUpDown( pData->GetDelta() > 0L, false ); 1664 } 1665 } 1666 } 1667 1668 // -------------------------------------------------------------------- 1669 1670 Reference< ::com::sun::star::accessibility::XAccessible > ToolbarMenu::CreateAccessible() 1671 { 1672 mpImpl->setAccessible( new ToolbarMenuAcc( *mpImpl ) ); 1673 return Reference< XAccessible >( mpImpl->mxAccessible.get() ); 1674 } 1675 1676 // -------------------------------------------------------------------- 1677 1678 // todo: move to new base class that will replace SfxPopupWindo 1679 void ToolbarMenu::AddStatusListener( const rtl::OUString& rCommandURL ) 1680 { 1681 initStatusListener(); 1682 mpImpl->mxStatusListener->addStatusListener( rCommandURL ); 1683 } 1684 1685 // -------------------------------------------------------------------- 1686 1687 void ToolbarMenu::RemoveStatusListener( const rtl::OUString& rCommandURL ) 1688 { 1689 mpImpl->mxStatusListener->removeStatusListener( rCommandURL ); 1690 } 1691 // -------------------------------------------------------------------- 1692 1693 1694 void ToolbarMenu::UpdateStatus( const rtl::OUString& rCommandURL ) 1695 { 1696 mpImpl->mxStatusListener->updateStatus( rCommandURL ); 1697 } 1698 1699 // -------------------------------------------------------------------- 1700 1701 // XStatusListener (subclasses must override this one to get the status updates 1702 void SAL_CALL ToolbarMenu::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& /*Event*/ ) throw ( ::com::sun::star::uno::RuntimeException ) 1703 { 1704 } 1705 1706 // -------------------------------------------------------------------- 1707 1708 class ToolbarMenuStatusListener : public svt::FrameStatusListener 1709 { 1710 public: 1711 ToolbarMenuStatusListener( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager, 1712 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame, 1713 ToolbarMenu& rToolbarMenu ); 1714 1715 virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException); 1716 virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ); 1717 1718 ToolbarMenu* mpMenu; 1719 }; 1720 1721 // -------------------------------------------------------------------- 1722 1723 ToolbarMenuStatusListener::ToolbarMenuStatusListener( 1724 const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager, 1725 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame, 1726 ToolbarMenu& rToolbarMenu ) 1727 : svt::FrameStatusListener( xServiceManager, xFrame ) 1728 , mpMenu( &rToolbarMenu ) 1729 { 1730 } 1731 1732 // -------------------------------------------------------------------- 1733 1734 void SAL_CALL ToolbarMenuStatusListener::dispose() throw (::com::sun::star::uno::RuntimeException) 1735 { 1736 mpMenu = 0; 1737 svt::FrameStatusListener::dispose(); 1738 } 1739 1740 // -------------------------------------------------------------------- 1741 1742 void SAL_CALL ToolbarMenuStatusListener::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ) 1743 { 1744 if( mpMenu ) 1745 mpMenu->statusChanged( Event ); 1746 } 1747 1748 // -------------------------------------------------------------------- 1749 1750 void ToolbarMenu::initStatusListener() 1751 { 1752 if( !mpImpl->mxStatusListener.is() ) 1753 mpImpl->mxStatusListener.set( new ToolbarMenuStatusListener( mpImpl->mxServiceManager, mpImpl->mxFrame, *this ) ); 1754 } 1755 1756 // -------------------------------------------------------------------- 1757 1758 bool ToolbarMenu::IsInPopupMode() 1759 { 1760 return GetDockingManager()->IsInPopupMode(this); 1761 } 1762 1763 // -------------------------------------------------------------------- 1764 1765 void ToolbarMenu::EndPopupMode() 1766 { 1767 GetDockingManager()->EndPopupMode(this); 1768 } 1769 1770 // -------------------------------------------------------------------- 1771 1772 const Size& ToolbarMenu::getMenuSize() const 1773 { 1774 return mpImpl->maSize; 1775 } 1776 1777 // -------------------------------------------------------------------- 1778 1779 void ToolbarMenu::SetSelectHdl( const Link& rLink ) 1780 { 1781 mpImpl->maSelectHdl = rLink; 1782 } 1783 1784 // -------------------------------------------------------------------- 1785 1786 const Link& ToolbarMenu::GetSelectHdl() const 1787 { 1788 return mpImpl->maSelectHdl; 1789 } 1790 1791 // -------------------------------------------------------------------- 1792 1793 Reference< XFrame > ToolbarMenu::GetFrame() const 1794 { 1795 return mpImpl->mxFrame; 1796 } 1797 1798 // -------------------------------------------------------------------- 1799 1800 1801 // -------------------------------------------------------------------- 1802 1803 } 1804 1805 1806