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